Skip to content

Commit

Permalink
[ELF] getRelocTargetVA: pass Ctx and Relocation. NFC
Browse files Browse the repository at this point in the history
  • Loading branch information
MaskRay committed Oct 6, 2024
1 parent acf92a4 commit 2b5cb1b
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 104 deletions.
4 changes: 1 addition & 3 deletions lld/ELF/Arch/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -915,9 +915,7 @@ void AArch64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
for (size_t i = 0, size = sec.relocs().size(); i != size; ++i) {
const Relocation &rel = sec.relocs()[i];
uint8_t *loc = buf + rel.offset;
const uint64_t val =
sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
secAddr + rel.offset, *rel.sym, rel.expr);
const uint64_t val = sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset);

if (needsGotForMemtag(rel)) {
relocate(loc, rel, val);
Expand Down
6 changes: 2 additions & 4 deletions lld/ELF/Arch/PPC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,8 @@ void PPC::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
secAddr += s->outSecOff;
for (const Relocation &rel : sec.relocs()) {
uint8_t *loc = buf + rel.offset;
const uint64_t val = SignExtend64(
sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
secAddr + rel.offset, *rel.sym, rel.expr),
32);
const uint64_t val =
SignExtend64(sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), 32);
switch (rel.expr) {
case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
relaxTlsGdToIe(loc, rel, val);
Expand Down
4 changes: 1 addition & 3 deletions lld/ELF/Arch/PPC64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1569,9 +1569,7 @@ void PPC64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
uint64_t lastPPCRelaxedRelocOff = -1;
for (const Relocation &rel : sec.relocs()) {
uint8_t *loc = buf + rel.offset;
const uint64_t val =
sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
secAddr + rel.offset, *rel.sym, rel.expr);
const uint64_t val = sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset);
switch (rel.expr) {
case R_PPC64_RELAX_GOT_PC: {
// The R_PPC64_PCREL_OPT relocation must appear immediately after
Expand Down
4 changes: 1 addition & 3 deletions lld/ELF/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -602,9 +602,7 @@ void RISCV::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
for (size_t i = 0, size = relocs.size(); i != size; ++i) {
const Relocation &rel = relocs[i];
uint8_t *loc = buf + rel.offset;
uint64_t val =
sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
secAddr + rel.offset, *rel.sym, rel.expr);
uint64_t val = sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset);

switch (rel.expr) {
case R_RELAX_HINT:
Expand Down
3 changes: 1 addition & 2 deletions lld/ELF/Arch/SystemZ.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -447,8 +447,7 @@ bool SystemZ::relaxOnce(int pass) const {
continue;

uint64_t v = sec->getRelocTargetVA(
sec->file, rel.type, rel.addend,
sec->getOutputSection()->addr + rel.offset, *rel.sym, rel.expr);
ctx, rel, sec->getOutputSection()->addr + rel.offset);
if (isInt<33>(v) && !(v & 1))
continue;
if (rel.sym->auxIdx == 0) {
Expand Down
6 changes: 2 additions & 4 deletions lld/ELF/Arch/X86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,10 +487,8 @@ void X86::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
secAddr += s->outSecOff;
for (const Relocation &rel : sec.relocs()) {
uint8_t *loc = buf + rel.offset;
const uint64_t val = SignExtend64(
sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
secAddr + rel.offset, *rel.sym, rel.expr),
32);
const uint64_t val =
SignExtend64(sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset), 32);
switch (rel.expr) {
case R_RELAX_TLS_GD_TO_IE_GOTPLT:
relaxTlsGdToIe(loc, rel, val);
Expand Down
16 changes: 7 additions & 9 deletions lld/ELF/Arch/X86_64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,7 @@ static bool isFallThruRelocation(InputSection &is, InputFile *file,
return false;

uint64_t addrLoc = is.getOutputSection()->addr + is.outSecOff + r.offset;
uint64_t targetOffset = InputSectionBase::getRelocTargetVA(
file, r.type, r.addend, addrLoc, *r.sym, r.expr);
uint64_t targetOffset = is.getRelocTargetVA(ctx, r, addrLoc);

// If this jmp is a fall thru, the target offset is the beginning of the
// next section.
Expand Down Expand Up @@ -331,10 +330,11 @@ bool X86_64::relaxOnce(int pass) const {
continue;
assert(rel.addend == -4);

uint64_t v = sec->getRelocTargetVA(
sec->file, rel.type, rel.expr == R_RELAX_GOT_PC_NOPIC ? 0 : -4,
sec->getOutputSection()->addr + sec->outSecOff + rel.offset,
*rel.sym, rel.expr);
Relocation rel1 = rel;
rel1.addend = rel.expr == R_RELAX_GOT_PC_NOPIC ? 0 : -4;
uint64_t v = sec->getRelocTargetVA(ctx, rel1,
sec->getOutputSection()->addr +
sec->outSecOff + rel.offset);
if (isInt<32>(v))
continue;
if (rel.sym->auxIdx == 0) {
Expand Down Expand Up @@ -1059,9 +1059,7 @@ void X86_64::relocateAlloc(InputSectionBase &sec, uint8_t *buf) const {
if (rel.expr == R_NONE) // See deleteFallThruJmpInsn
continue;
uint8_t *loc = buf + rel.offset;
const uint64_t val =
sec.getRelocTargetVA(sec.file, rel.type, rel.addend,
secAddr + rel.offset, *rel.sym, rel.expr);
const uint64_t val = sec.getRelocTargetVA(ctx, rel, secAddr + rel.offset);
relocate(loc, rel, val);
}
if (sec.jumpInstrMod) {
Expand Down
136 changes: 68 additions & 68 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -717,84 +717,84 @@ static int64_t getTlsTpOffset(const Symbol &s) {
}
}

uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
int64_t a, uint64_t p,
const Symbol &sym, RelExpr expr) {
switch (expr) {
uint64_t InputSectionBase::getRelocTargetVA(Ctx &ctx, const Relocation &r,
uint64_t p) const {
int64_t a = r.addend;
switch (r.expr) {
case R_ABS:
case R_DTPREL:
case R_RELAX_TLS_LD_TO_LE_ABS:
case R_RELAX_GOT_PC_NOPIC:
case R_AARCH64_AUTH:
case R_RISCV_ADD:
case R_RISCV_LEB128:
return sym.getVA(a);
return r.sym->getVA(a);
case R_ADDEND:
return a;
case R_RELAX_HINT:
return 0;
case R_ARM_SBREL:
return sym.getVA(a) - getARMStaticBase(sym);
return r.sym->getVA(a) - getARMStaticBase(*r.sym);
case R_GOT:
case R_RELAX_TLS_GD_TO_IE_ABS:
return sym.getGotVA() + a;
return r.sym->getGotVA() + a;
case R_LOONGARCH_GOT:
// The LoongArch TLS GD relocs reuse the R_LARCH_GOT_PC_LO12 reloc type
// The LoongArch TLS GD relocs reuse the R_LARCH_GOT_PC_LO12 reloc r.type
// for their page offsets. The arithmetics are different in the TLS case
// so we have to duplicate some logic here.
if (sym.hasFlag(NEEDS_TLSGD) && type != R_LARCH_TLS_IE_PC_LO12)
if (r.sym->hasFlag(NEEDS_TLSGD) && r.type != R_LARCH_TLS_IE_PC_LO12)
// Like R_LOONGARCH_TLSGD_PAGE_PC but taking the absolute value.
return ctx.in.got->getGlobalDynAddr(sym) + a;
return getRelocTargetVA(file, type, a, p, sym, R_GOT);
return ctx.in.got->getGlobalDynAddr(*r.sym) + a;
return r.sym->getGotVA() + a;
case R_GOTONLY_PC:
return ctx.in.got->getVA() + a - p;
case R_GOTPLTONLY_PC:
return ctx.in.gotPlt->getVA() + a - p;
case R_GOTREL:
case R_PPC64_RELAX_TOC:
return sym.getVA(a) - ctx.in.got->getVA();
return r.sym->getVA(a) - ctx.in.got->getVA();
case R_GOTPLTREL:
return sym.getVA(a) - ctx.in.gotPlt->getVA();
return r.sym->getVA(a) - ctx.in.gotPlt->getVA();
case R_GOTPLT:
case R_RELAX_TLS_GD_TO_IE_GOTPLT:
return sym.getGotVA() + a - ctx.in.gotPlt->getVA();
return r.sym->getGotVA() + a - ctx.in.gotPlt->getVA();
case R_TLSLD_GOT_OFF:
case R_GOT_OFF:
case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
return sym.getGotOffset() + a;
return r.sym->getGotOffset() + a;
case R_AARCH64_GOT_PAGE_PC:
case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
return getAArch64Page(sym.getGotVA() + a) - getAArch64Page(p);
return getAArch64Page(r.sym->getGotVA() + a) - getAArch64Page(p);
case R_AARCH64_GOT_PAGE:
return sym.getGotVA() + a - getAArch64Page(ctx.in.got->getVA());
return r.sym->getGotVA() + a - getAArch64Page(ctx.in.got->getVA());
case R_GOT_PC:
case R_RELAX_TLS_GD_TO_IE:
return sym.getGotVA() + a - p;
return r.sym->getGotVA() + a - p;
case R_GOTPLT_GOTREL:
return sym.getGotPltVA() + a - ctx.in.got->getVA();
return r.sym->getGotPltVA() + a - ctx.in.got->getVA();
case R_GOTPLT_PC:
return sym.getGotPltVA() + a - p;
return r.sym->getGotPltVA() + a - p;
case R_LOONGARCH_GOT_PAGE_PC:
if (sym.hasFlag(NEEDS_TLSGD))
return getLoongArchPageDelta(ctx.in.got->getGlobalDynAddr(sym) + a, p,
type);
return getLoongArchPageDelta(sym.getGotVA() + a, p, type);
if (r.sym->hasFlag(NEEDS_TLSGD))
return getLoongArchPageDelta(ctx.in.got->getGlobalDynAddr(*r.sym) + a, p,
r.type);
return getLoongArchPageDelta(r.sym->getGotVA() + a, p, r.type);
case R_MIPS_GOTREL:
return sym.getVA(a) - ctx.in.mipsGot->getGp(file);
return r.sym->getVA(a) - ctx.in.mipsGot->getGp(file);
case R_MIPS_GOT_GP:
return ctx.in.mipsGot->getGp(file) + a;
case R_MIPS_GOT_GP_PC: {
// R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target
// R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC r.type iif the target
// is _gp_disp symbol. In that case we should use the following
// formula for calculation "AHL + GP - P + 4". For details see p. 4-19 at
// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
// microMIPS variants of these relocations use slightly different
// expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi()
// to correctly handle less-significant bit of the microMIPS symbol.
uint64_t v = ctx.in.mipsGot->getGp(file) + a - p;
if (type == R_MIPS_LO16 || type == R_MICROMIPS_LO16)
if (r.type == R_MIPS_LO16 || r.type == R_MICROMIPS_LO16)
v += 4;
if (type == R_MICROMIPS_LO16 || type == R_MICROMIPS_HI16)
if (r.type == R_MICROMIPS_LO16 || r.type == R_MICROMIPS_HI16)
v -= 1;
return v;
}
Expand All @@ -803,81 +803,80 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
// should be initialized by 'page address'. This address is high 16-bits
// of sum the symbol's value and the addend.
return ctx.in.mipsGot->getVA() +
ctx.in.mipsGot->getPageEntryOffset(file, sym, a) -
ctx.in.mipsGot->getPageEntryOffset(file, *r.sym, a) -
ctx.in.mipsGot->getGp(file);
case R_MIPS_GOT_OFF:
case R_MIPS_GOT_OFF32:
// In case of MIPS if a GOT relocation has non-zero addend this addend
// should be applied to the GOT entry content not to the GOT entry offset.
// That is why we use separate expression type.
// That is why we use separate expression r.type.
return ctx.in.mipsGot->getVA() +
ctx.in.mipsGot->getSymEntryOffset(file, sym, a) -
ctx.in.mipsGot->getSymEntryOffset(file, *r.sym, a) -
ctx.in.mipsGot->getGp(file);
case R_MIPS_TLSGD:
return ctx.in.mipsGot->getVA() +
ctx.in.mipsGot->getGlobalDynOffset(file, sym) -
ctx.in.mipsGot->getGlobalDynOffset(file, *r.sym) -
ctx.in.mipsGot->getGp(file);
case R_MIPS_TLSLD:
return ctx.in.mipsGot->getVA() + ctx.in.mipsGot->getTlsIndexOffset(file) -
ctx.in.mipsGot->getGp(file);
case R_AARCH64_PAGE_PC: {
uint64_t val = sym.isUndefWeak() ? p + a : sym.getVA(a);
uint64_t val = r.sym->isUndefWeak() ? p + a : r.sym->getVA(a);
return getAArch64Page(val) - getAArch64Page(p);
}
case R_RISCV_PC_INDIRECT: {
if (const Relocation *hiRel = getRISCVPCRelHi20(&sym, a))
return getRelocTargetVA(file, hiRel->type, hiRel->addend, sym.getVA(),
*hiRel->sym, hiRel->expr);
if (const Relocation *hiRel = getRISCVPCRelHi20(r.sym, a))
return getRelocTargetVA(ctx, *hiRel, r.sym->getVA());
return 0;
}
case R_LOONGARCH_PAGE_PC:
return getLoongArchPageDelta(sym.getVA(a), p, type);
return getLoongArchPageDelta(r.sym->getVA(a), p, r.type);
case R_PC:
case R_ARM_PCA: {
uint64_t dest;
if (expr == R_ARM_PCA)
if (r.expr == R_ARM_PCA)
// Some PC relative ARM (Thumb) relocations align down the place.
p = p & 0xfffffffc;
if (sym.isUndefined()) {
if (r.sym->isUndefined()) {
// On ARM and AArch64 a branch to an undefined weak resolves to the next
// instruction, otherwise the place. On RISC-V, resolve an undefined weak
// to the same instruction to cause an infinite loop (making the user
// aware of the issue) while ensuring no overflow.
// Note: if the symbol is hidden, its binding has been converted to local,
// so we just check isUndefined() here.
if (ctx.arg.emachine == EM_ARM)
dest = getARMUndefinedRelativeWeakVA(type, a, p);
dest = getARMUndefinedRelativeWeakVA(r.type, a, p);
else if (ctx.arg.emachine == EM_AARCH64)
dest = getAArch64UndefinedRelativeWeakVA(type, p) + a;
dest = getAArch64UndefinedRelativeWeakVA(r.type, p) + a;
else if (ctx.arg.emachine == EM_PPC)
dest = p;
else if (ctx.arg.emachine == EM_RISCV)
dest = getRISCVUndefinedRelativeWeakVA(type, p) + a;
dest = getRISCVUndefinedRelativeWeakVA(r.type, p) + a;
else
dest = sym.getVA(a);
dest = r.sym->getVA(a);
} else {
dest = sym.getVA(a);
dest = r.sym->getVA(a);
}
return dest - p;
}
case R_PLT:
return sym.getPltVA() + a;
return r.sym->getPltVA() + a;
case R_PLT_PC:
case R_PPC64_CALL_PLT:
return sym.getPltVA() + a - p;
return r.sym->getPltVA() + a - p;
case R_LOONGARCH_PLT_PAGE_PC:
return getLoongArchPageDelta(sym.getPltVA() + a, p, type);
return getLoongArchPageDelta(r.sym->getPltVA() + a, p, r.type);
case R_PLT_GOTPLT:
return sym.getPltVA() + a - ctx.in.gotPlt->getVA();
return r.sym->getPltVA() + a - ctx.in.gotPlt->getVA();
case R_PLT_GOTREL:
return sym.getPltVA() + a - ctx.in.got->getVA();
return r.sym->getPltVA() + a - ctx.in.got->getVA();
case R_PPC32_PLTREL:
// R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30
// stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for
// target VA computation.
return sym.getPltVA() - p;
return r.sym->getPltVA() - p;
case R_PPC64_CALL: {
uint64_t symVA = sym.getVA(a);
uint64_t symVA = r.sym->getVA(a);
// If we have an undefined weak symbol, we might get here with a symbol
// address of zero. That could overflow, but the code must be unreachable,
// so don't bother doing anything at all.
Expand All @@ -890,13 +889,13 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
// the callee. For local calls the caller and callee share the same
// TOC base and so the TOC pointer initialization code should be skipped by
// branching to the local entry point.
return symVA - p + getPPC64GlobalEntryToLocalEntryOffset(sym.stOther);
return symVA - p + getPPC64GlobalEntryToLocalEntryOffset(r.sym->stOther);
}
case R_PPC64_TOCBASE:
return getPPC64TocBase(ctx) + a;
case R_RELAX_GOT_PC:
case R_PPC64_RELAX_GOT_PC:
return sym.getVA(a) - p;
return r.sym->getVA(a) - p;
case R_RELAX_TLS_GD_TO_LE:
case R_RELAX_TLS_IE_TO_LE:
case R_RELAX_TLS_LD_TO_LE:
Expand All @@ -905,36 +904,37 @@ uint64_t InputSectionBase::getRelocTargetVA(const InputFile *file, RelType type,
// --noinhibit-exec, even a non-weak undefined reference may reach here.
// Just return A, which matches R_ABS, and the behavior of some dynamic
// loaders.
if (sym.isUndefined())
if (r.sym->isUndefined())
return a;
return getTlsTpOffset(sym) + a;
return getTlsTpOffset(*r.sym) + a;
case R_RELAX_TLS_GD_TO_LE_NEG:
case R_TPREL_NEG:
if (sym.isUndefined())
if (r.sym->isUndefined())
return a;
return -getTlsTpOffset(sym) + a;
return -getTlsTpOffset(*r.sym) + a;
case R_SIZE:
return sym.getSize() + a;
return r.sym->getSize() + a;
case R_TLSDESC:
return ctx.in.got->getTlsDescAddr(sym) + a;
return ctx.in.got->getTlsDescAddr(*r.sym) + a;
case R_TLSDESC_PC:
return ctx.in.got->getTlsDescAddr(sym) + a - p;
return ctx.in.got->getTlsDescAddr(*r.sym) + a - p;
case R_TLSDESC_GOTPLT:
return ctx.in.got->getTlsDescAddr(sym) + a - ctx.in.gotPlt->getVA();
return ctx.in.got->getTlsDescAddr(*r.sym) + a - ctx.in.gotPlt->getVA();
case R_AARCH64_TLSDESC_PAGE:
return getAArch64Page(ctx.in.got->getTlsDescAddr(sym) + a) -
return getAArch64Page(ctx.in.got->getTlsDescAddr(*r.sym) + a) -
getAArch64Page(p);
case R_LOONGARCH_TLSDESC_PAGE_PC:
return getLoongArchPageDelta(ctx.in.got->getTlsDescAddr(sym) + a, p, type);
return getLoongArchPageDelta(ctx.in.got->getTlsDescAddr(*r.sym) + a, p,
r.type);
case R_TLSGD_GOT:
return ctx.in.got->getGlobalDynOffset(sym) + a;
return ctx.in.got->getGlobalDynOffset(*r.sym) + a;
case R_TLSGD_GOTPLT:
return ctx.in.got->getGlobalDynAddr(sym) + a - ctx.in.gotPlt->getVA();
return ctx.in.got->getGlobalDynAddr(*r.sym) + a - ctx.in.gotPlt->getVA();
case R_TLSGD_PC:
return ctx.in.got->getGlobalDynAddr(sym) + a - p;
return ctx.in.got->getGlobalDynAddr(*r.sym) + a - p;
case R_LOONGARCH_TLSGD_PAGE_PC:
return getLoongArchPageDelta(ctx.in.got->getGlobalDynAddr(sym) + a, p,
type);
return getLoongArchPageDelta(ctx.in.got->getGlobalDynAddr(*r.sym) + a, p,
r.type);
case R_TLSLD_GOTPLT:
return ctx.in.got->getVA() + ctx.in.got->getTlsIndexOff() + a -
ctx.in.gotPlt->getVA();
Expand Down
Loading

0 comments on commit 2b5cb1b

Please sign in to comment.