88 changes: 72 additions & 16 deletions lld/ELF/Target.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ namespace {
class X86TargetInfo final : public TargetInfo {
public:
X86TargetInfo();
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
uint64_t PltEntryAddr, int32_t Index) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocPointsToGot(uint32_t Type) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
Expand All @@ -61,8 +64,11 @@ class X86_64TargetInfo final : public TargetInfo {
public:
X86_64TargetInfo();
unsigned getPLTRefReloc(unsigned Type) const override;
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
uint64_t PltEntryAddr, int32_t Index) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
Expand All @@ -74,8 +80,11 @@ class X86_64TargetInfo final : public TargetInfo {
class PPC64TargetInfo final : public TargetInfo {
public:
PPC64TargetInfo();
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
uint64_t PltEntryAddr, int32_t Index) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
Expand All @@ -87,8 +96,11 @@ class PPC64TargetInfo final : public TargetInfo {
class AArch64TargetInfo final : public TargetInfo {
public:
AArch64TargetInfo();
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
uint64_t PltEntryAddr, int32_t Index) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
Expand All @@ -99,8 +111,11 @@ class AArch64TargetInfo final : public TargetInfo {
template <class ELFT> class MipsTargetInfo final : public TargetInfo {
public:
MipsTargetInfo();
void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override;
void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const override;
uint64_t PltEntryAddr, int32_t Index) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Buf, uint8_t *BufEnd, const void *RelP,
Expand Down Expand Up @@ -144,10 +159,15 @@ X86TargetInfo::X86TargetInfo() {
PCRelReloc = R_386_PC32;
GotReloc = R_386_GLOB_DAT;
GotRefReloc = R_386_GOT32;
PltReloc = R_386_JUMP_SLOT;
}

void X86TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}

void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {
uint64_t PltEntryAddr, int32_t Index) const {
// jmpl *val; nop; nop
const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
memcpy(Buf, Inst, sizeof(Inst));
Expand Down Expand Up @@ -194,19 +214,43 @@ X86_64TargetInfo::X86_64TargetInfo() {
PCRelReloc = R_X86_64_PC32;
GotReloc = R_X86_64_GLOB_DAT;
GotRefReloc = R_X86_64_PC32;
PltReloc = R_X86_64_JUMP_SLOT;
RelativeReloc = R_X86_64_RELATIVE;
LazyRelocations = true;
PltEntrySize = 16;
PltZeroEntrySize = 16;
}

void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
// Skip 6 bytes of "jmpq *got(%rip)"
write32le(Buf, Plt + 6);
}

void X86_64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {
const uint8_t PltData[] = {
0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip)
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip)
0x0f, 0x1f, 0x40, 0x00 // nopl 0x0(rax)
};
memcpy(Buf, PltData, sizeof(PltData));
write32le(Buf + 2, GotEntryAddr - PltEntryAddr + 2); // GOT+8
write32le(Buf + 8, GotEntryAddr - PltEntryAddr + 4); // GOT+16
}

void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {
// jmpq *val(%rip); nop; nop
const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90};
uint64_t PltEntryAddr,
int32_t Index) const {
const uint8_t Inst[] = {
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip)
0x68, 0x00, 0x00, 0x00, 0x00, // pushq <relocation index>
0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
};
memcpy(Buf, Inst, sizeof(Inst));

uint64_t NextPC = PltEntryAddr + 6;
int64_t Delta = GotEntryAddr - NextPC;
assert(isInt<32>(Delta));
write32le(Buf + 2, Delta);
write32le(Buf + 2, GotEntryAddr - PltEntryAddr - 6);
write32le(Buf + 7, Index);
write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
}

bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
Expand Down Expand Up @@ -364,8 +408,11 @@ uint64_t getPPC64TocBase() {
return TocVA + 0x8000;
}

void PPC64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
void PPC64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
void PPC64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {
uint64_t PltEntryAddr, int32_t Index) const {
uint64_t Off = GotEntryAddr - getPPC64TocBase();

// FIXME: What we should do, in theory, is get the offset of the function
Expand Down Expand Up @@ -548,8 +595,12 @@ AArch64TargetInfo::AArch64TargetInfo() {
// PCRelReloc = FIXME
// GotReloc = FIXME
}

void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
uint64_t PltEntryAddr, int32_t Index) const {}
bool AArch64TargetInfo::relocNeedsGot(uint32_t Type,
const SymbolBody &S) const {
return false;
Expand Down Expand Up @@ -629,9 +680,14 @@ template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
PageSize = 65536;
}

template <class ELFT>
void MipsTargetInfo<ELFT>::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {}
template <class ELFT>
void MipsTargetInfo<ELFT>::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
template <class ELFT>
void MipsTargetInfo<ELFT>::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const {}
uint64_t PltEntryAddr, int32_t Index) const {}

template <class ELFT>
bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
Expand Down
11 changes: 10 additions & 1 deletion lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,18 @@ class TargetInfo {
uint64_t getVAStart() const { return VAStart; }
unsigned getPCRelReloc() const { return PCRelReloc; }
unsigned getGotReloc() const { return GotReloc; }
unsigned getPltReloc() const { return PltReloc; }
unsigned getGotRefReloc() const { return GotRefReloc; }
unsigned getRelativeReloc() const { return RelativeReloc; }
unsigned getPltZeroEntrySize() const { return PltZeroEntrySize; }
unsigned getPltEntrySize() const { return PltEntrySize; }
bool supportsLazyRelocations() const { return LazyRelocations; }
virtual unsigned getPLTRefReloc(unsigned Type) const;
virtual void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const = 0;
virtual void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const = 0;
virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr) const = 0;
uint64_t PltEntryAddr, int32_t Index) const = 0;
virtual bool isRelRelative(uint32_t Type) const;
virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
virtual bool relocPointsToGot(uint32_t Type) const;
Expand All @@ -54,8 +60,11 @@ class TargetInfo {
unsigned PCRelReloc;
unsigned GotRefReloc;
unsigned GotReloc;
unsigned PltReloc;
unsigned RelativeReloc;
unsigned PltEntrySize = 8;
unsigned PltZeroEntrySize = 0;
bool LazyRelocations = false;
};

uint64_t getPPC64TocBase();
Expand Down
32 changes: 26 additions & 6 deletions lld/ELF/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
Out<ELFT>::Bss = &Bss;
GotSection<ELFT> Got;
Out<ELFT>::Got = &Got;
GotPltSection<ELFT> GotPlt;
if (Target->supportsLazyRelocations())
Out<ELFT>::GotPlt = &GotPlt;
PltSection<ELFT> Plt;
Out<ELFT>::Plt = &Plt;
SymbolTableSection<ELFT> SymTab(*Symtab, *Out<ELFT>::StrTab);
Expand All @@ -110,8 +113,12 @@ template <class ELFT> void lld::elf2::writeResult(SymbolTable<ELFT> *Symtab) {
Out<ELFT>::DynSymTab = &DynSymTab;
HashTableSection<ELFT> HashTab;
Out<ELFT>::HashTab = &HashTab;
RelocationSection<ELFT> RelaDyn(Symtab->shouldUseRela());
bool IsRela = Symtab->shouldUseRela();
RelocationSection<ELFT> RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela);
Out<ELFT>::RelaDyn = &RelaDyn;
RelocationSection<ELFT> RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela);
if (Target->supportsLazyRelocations())
Out<ELFT>::RelaPlt = &RelaPlt;
DynamicSection<ELFT> Dynamic(*Symtab);
Out<ELFT>::Dynamic = &Dynamic;

Expand Down Expand Up @@ -189,17 +196,23 @@ void Writer<ELFT>::scanRelocs(
if (Body)
Body = Body->repl();
bool NeedsGot = false;
bool NeedsPlt = false;
if (Body) {
if (Target->relocNeedsPlt(Type, *Body)) {
NeedsPlt = Target->relocNeedsPlt(Type, *Body);
if (NeedsPlt) {
if (Body->isInPlt())
continue;
Out<ELFT>::Plt->addEntry(Body);
}
NeedsGot = Target->relocNeedsGot(Type, *Body);
if (NeedsGot) {
if (Body->isInGot())
continue;
Out<ELFT>::Got->addEntry(Body);
if (NeedsPlt && Target->supportsLazyRelocations()) {
Out<ELFT>::GotPlt->addEntry(Body);
} else {
if (Body->isInGot())
continue;
Out<ELFT>::Got->addEntry(Body);
}
}
}

Expand All @@ -208,7 +221,10 @@ void Writer<ELFT>::scanRelocs(
continue;
if (CBP)
Body->setUsedInDynamicReloc();
Out<ELFT>::RelaDyn->addReloc({C, RI});
if (NeedsPlt && Target->supportsLazyRelocations())
Out<ELFT>::RelaPlt->addReloc({C, RI});
else
Out<ELFT>::RelaDyn->addReloc({C, RI});
}
}

Expand Down Expand Up @@ -508,9 +524,13 @@ template <class ELFT> void Writer<ELFT>::createSections() {
OutputSections.push_back(Out<ELFT>::DynStrTab);
if (Out<ELFT>::RelaDyn->hasRelocs())
OutputSections.push_back(Out<ELFT>::RelaDyn);
if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs())
OutputSections.push_back(Out<ELFT>::RelaPlt);
}
if (!Out<ELFT>::Got->empty())
OutputSections.push_back(Out<ELFT>::Got);
if (Out<ELFT>::GotPlt && !Out<ELFT>::GotPlt->empty())
OutputSections.push_back(Out<ELFT>::GotPlt);
if (!Out<ELFT>::Plt->empty())
OutputSections.push_back(Out<ELFT>::Plt);

Expand Down
6 changes: 4 additions & 2 deletions lld/test/elf2/dynamic-reloc-weak.s
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ _start:
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x{{.*}} R_X86_64_GLOB_DAT sym1 0x0
// CHECK-NEXT: 0x{{.*}} R_X86_64_GLOB_DAT sym2 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
// CHECK-NEXT: 0x{{.*}} R_X86_64_JUMP_SLOT sym2 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
91 changes: 50 additions & 41 deletions lld/test/elf2/plt.s
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x1020
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 24
// CHECK-NEXT: Size: 64
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16

// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK-NEXT: 0x20A0 R_X86_64_GLOB_DAT bar 0x0
// CHECK-NEXT: 0x20A8 R_X86_64_GLOB_DAT zed 0x0
// CHECK-NEXT: 0x20B0 R_X86_64_GLOB_DAT _start 0x0
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
// CHECK-NEXT: 0x20C8 R_X86_64_JUMP_SLOT bar 0x0
// CHECK-NEXT: 0x20D0 R_X86_64_JUMP_SLOT zed 0x0
// CHECK-NEXT: 0x20D8 R_X86_64_JUMP_SLOT _start 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]

Expand All @@ -39,67 +39,76 @@
// CHECK2-NEXT: ]
// CHECK2-NEXT: Address: 0x11020
// CHECK2-NEXT: Offset:
// CHECK2-NEXT: Size: 16
// CHECK2-NEXT: Size: 48
// CHECK2-NEXT: Link: 0
// CHECK2-NEXT: Info: 0
// CHECK2-NEXT: AddressAlignment: 16

// CHECK2: Relocations [
// CHECK2-NEXT: Section ({{.*}}) .rela.dyn {
// CHECK2-NEXT: 0x120A0 R_X86_64_GLOB_DAT bar 0x0
// CHECK2-NEXT: 0x120A8 R_X86_64_GLOB_DAT zed 0x0
// CHECK2-NEXT: Section ({{.*}}) .rela.plt {
// CHECK2-NEXT: 0x120C8 R_X86_64_JUMP_SLOT bar 0x0
// CHECK2-NEXT: 0x120D0 R_X86_64_JUMP_SLOT zed 0x0
// CHECK2-NEXT: }
// CHECK2-NEXT: ]

// Unfortunately FileCheck can't do math, so we have to check for explicit
// values:

// 0x1020 - (0x1000 + 1) - 4 = 27
// 0x1020 - (0x1005 + 1) - 4 = 22
// 0x1028 - (0x100a + 1) - 4 = 25
// 0x1030 - (0x100f + 1) - 4 = 28
// 0x1030 - (0x1000 + 5) = 43
// 0x1030 - (0x1005 + 5) = 38
// 0x1040 - (0x100a + 5) = 49
// 0x1048 - (0x100a + 5) = 60

// DISASM: _start:
// DISASM-NEXT: 1000: e9 {{.*}} jmp 27
// DISASM-NEXT: 1005: e9 {{.*}} jmp 22
// DISASM-NEXT: 100a: e9 {{.*}} jmp 25
// DISASM-NEXT: 100f: e9 {{.*}} jmp 28
// DISASM-NEXT: 1000: e9 {{.*}} jmp 43
// DISASM-NEXT: 1005: e9 {{.*}} jmp 38
// DISASM-NEXT: 100a: e9 {{.*}} jmp 49
// DISASM-NEXT: 100f: e9 {{.*}} jmp 60

// 0x20A0 - 0x1026 = 4218
// 0x20A8 - 0x102e = 4218
// 0x20B0 - 0x1036 = 4218
// 0x20C8 - 0x1036 = 4242
// 0x20D0 - 0x1046 = 4234
// 0x20D8 - 0x1056 = 4226

// DISASM: Disassembly of section .plt:
// DISASM-NEXT: .plt:
// DISASM-NEXT: 1020: ff 25 {{.*}} jmpq *4218(%rip)
// DISASM-NEXT: 1026: 90 nop
// DISASM-NEXT: 1027: 90 nop
// DISASM-NEXT: 1028: ff 25 {{.*}} jmpq *4218(%rip)
// DISASM-NEXT: 102e: 90 nop
// DISASM-NEXT: 102f: 90 nop
// DISASM-NEXT: 1030: ff 25 {{.*}} jmpq *4218(%rip)
// DISASM-NEXT: 1036: 90 nop
// DISASM-NEXT: 1037: 90 nop
// DISASM-NEXT: 1020: ff 35 92 10 00 00 pushq 4242(%rip)
// DISASM-NEXT: 1026: ff 25 94 10 00 00 jmpq *4244(%rip)
// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)
// DISASM-NEXT: 1030: ff 25 92 10 00 00 jmpq *4242(%rip)
// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0
// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <bar+1020>
// DISASM-NEXT: 1040: ff 25 8a 10 00 00 jmpq *4234(%rip)
// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1
// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <bar+1020>
// DISASM-NEXT: 1050: ff 25 82 10 00 00 jmpq *4226(%rip)
// DISASM-NEXT: 1056: 68 02 00 00 00 pushq $2
// DISASM-NEXT: 105b: e9 c0 ff ff ff jmp -64 <bar+1020>

// 0x11020 - (0x11000 + 1) - 4 = 27
// 0x11020 - (0x11005 + 1) - 4 = 22
// 0x11028 - (0x1100a + 1) - 4 = 25
// 0x11030 - (0x11000 + 1) - 4 = 43
// 0x11030 - (0x11005 + 1) - 4 = 38
// 0x11040 - (0x1100a + 1) - 4 = 49
// 0x11000 - (0x1100f + 1) - 4 = -20

// DISASM2: _start:
// DISASM2-NEXT: 11000: e9 {{.*}} jmp 27
// DISASM2-NEXT: 11005: e9 {{.*}} jmp 22
// DISASM2-NEXT: 1100a: e9 {{.*}} jmp 25
// DISASM2-NEXT: 11000: e9 {{.*}} jmp 43
// DISASM2-NEXT: 11005: e9 {{.*}} jmp 38
// DISASM2-NEXT: 1100a: e9 {{.*}} jmp 49
// DISASM2-NEXT: 1100f: e9 {{.*}} jmp -20

// 0x120C8 - 0x11036 = 4242
// 0x120D0 - 0x11046 = 4234

// DISASM2: Disassembly of section .plt:
// DISASM2-NEXT: .plt:
// DISASM2-NEXT: 11020: ff 25 7a 10 00 00 jmpq *4218(%rip)
// DISASM2-NEXT: 11026: 90 nop
// DISASM2-NEXT: 11027: 90 nop
// DISASM2-NEXT: 11028: ff 25 7a 10 00 00 jmpq *4218(%rip)
// DISASM2-NEXT: 1102e: 90 nop
// DISASM2-NEXT: 1102f: 90 nop
// DISASM2-NEXT: 11020: ff 35 92 10 00 00 pushq 4242(%rip)
// DISASM2-NEXT: 11026: ff 25 94 10 00 00 jmpq *4244(%rip)
// DISASM2-NEXT: 1102c: 0f 1f 40 00 nopl (%rax)
// DISASM2-NEXT: 11030: ff 25 92 10 00 00 jmpq *4242(%rip)
// DISASM2-NEXT: 11036: 68 00 00 00 00 pushq $0
// DISASM2-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <bar+11020>
// DISASM2-NEXT: 11040: ff 25 8a 10 00 00 jmpq *4234(%rip)
// DISASM2-NEXT: 11046: 68 01 00 00 00 pushq $1
// DISASM2-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <bar+11020>
// DISASM2-NEXT-NOT: 110C0

.global _start
Expand Down
31 changes: 23 additions & 8 deletions lld/test/elf2/relocation.s
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,38 @@
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x11030
// SEC-NEXT: Offset: 0x1030
// SEC-NEXT: Size: 8
// SEC-NEXT: Size: 32

// SEC: Name: .got
// SEC-NEXT: Type: SHT_PROGBITS
// SEC-NEXT: Flags [
// SEC-NEXT: SHF_ALLOC
// SEC-NEXT: SHF_WRITE
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x120A0
// SEC-NEXT: Address: 0x120E0
// SEC-NEXT: Offset:
// SEC-NEXT: Size: 16
// SEC-NEXT: Size: 8
// SEC-NEXT: Link: 0
// SEC-NEXT: Info: 0
// SEC-NEXT: AddressAlignment: 8
// SEC-NEXT: EntrySize: 0
// SEC-NEXT: }

// SEC: Name: .got.plt
// SEC-NEXT: Type: SHT_PROGBITS
// SEC-NEXT: Flags [
// SEC-NEXT: SHF_ALLOC
// SEC-NEXT: SHF_WRITE
// SEC-NEXT: ]
// SEC-NEXT: Address: 0x120E8
// SEC-NEXT: Offset: 0x20E8
// SEC-NEXT: Size: 32
// SEC-NEXT: Link: 0
// SEC-NEXT: Info: 0
// SEC-NEXT: AddressAlignment: 8
// SEC-NEXT: EntrySize: 0
// SEC-NEXT: }

.section .text,"ax",@progbits,unique,1
.global _start
_start:
Expand Down Expand Up @@ -76,12 +91,12 @@ R_X86_64_32S:
R_X86_64_PC32:
call bar
movl $bar, %eax
// 0x11030 - (0x11017 + 5) = 20
// 0x11030 = 69680
//16 is a size of PLT[0]
// 0x11030 + 16 - (0x11017 + 5) = 20
// CHECK: Disassembly of section .R_X86_64_PC32:
// CHECK-NEXT: R_X86_64_PC32:
// CHECK-NEXT: 11017: {{.*}} callq 20
// CHECK-NEXT: 1101c: {{.*}} movl $69680, %eax
// CHECK-NEXT: 11017: {{.*}} callq 36
// CHECK-NEXT: 1101c: {{.*}} movl $69696, %eax

.section .R_X86_64_64,"a",@progbits
.global R_X86_64_64
Expand All @@ -99,4 +114,4 @@ R_X86_64_GOTPCREL:
// 0x120A8 - 0x10160 = 8008
// 8008 = 0x481f0000 in little endian
// CHECK: Contents of section .R_X86_64_GOTPCREL
// CHECK-NEXT: 10160 481f0000
// CHECK-NEXT: 10160 801f0000