Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -108,6 +108,23 @@ std::vector Entries; }; +template +class GotPltSection final : public OutputSectionBase { + typedef OutputSectionBase Base; + typedef typename Base::uintX_t uintX_t; + +public: + GotPltSection(); + void finalize() override; + void writeTo(uint8_t *Buf) override; + void addEntry(SymbolBody *Sym); + bool empty() const; + uintX_t getEntryAddr(const SymbolBody &B) const; + +private: + std::vector Entries; +}; + template class PltSection final : public OutputSectionBase { typedef OutputSectionBase Base; typedef typename Base::uintX_t uintX_t; @@ -163,7 +180,7 @@ typedef typename llvm::object::ELFFile::uintX_t uintX_t; public: - RelocationSection(bool IsRela); + RelocationSection(StringRef Name, bool IsRela); void addReloc(const DynamicReloc &Reloc) { Relocs.push_back(Reloc); } void finalize() override; void writeTo(uint8_t *Buf) override; @@ -263,6 +280,7 @@ // until Writer is initialized. template struct Out { static DynamicSection *Dynamic; + static GotPltSection *GotPlt; static GotSection *Got; static HashTableSection *HashTab; static InterpSection *Interp; @@ -271,6 +289,7 @@ static uint8_t *OpdBuf; static PltSection *Plt; static RelocationSection *RelaDyn; + static RelocationSection *RelaPlt; static StringTableSection *DynStrTab; static StringTableSection *StrTab; static SymbolTableSection *DynSymTab; @@ -278,6 +297,7 @@ }; template DynamicSection *Out::Dynamic; +template GotPltSection *Out::GotPlt; template GotSection *Out::Got; template HashTableSection *Out::HashTab; template InterpSection *Out::Interp; @@ -286,6 +306,7 @@ template uint8_t *Out::OpdBuf; template PltSection *Out::Plt; template RelocationSection *Out::RelaDyn; +template RelocationSection *Out::RelaPlt; template StringTableSection *Out::DynStrTab; template StringTableSection *Out::StrTab; template SymbolTableSection *Out::DynSymTab; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -30,6 +30,43 @@ } template +GotPltSection::GotPltSection() + : OutputSectionBase(".got.plt", llvm::ELF::SHT_PROGBITS, + llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) { + this->Header.sh_addralign = sizeof(uintX_t); + // .got.plt has 3 reserved entry + Entries.resize(3); +} + +template void GotPltSection::addEntry(SymbolBody *Sym) { + Sym->GotPltIndex = Entries.size(); + Entries.push_back(Sym); +} + +template bool GotPltSection::empty() const { + return Entries.size() == 3; +} + +template +typename GotPltSection::uintX_t +GotPltSection::getEntryAddr(const SymbolBody &B) const { + return this->getVA() + B.GotPltIndex * sizeof(uintX_t); +} + +template void GotPltSection::finalize() { + this->Header.sh_size = Entries.size() * sizeof(uintX_t); +} + +template void GotPltSection::writeTo(uint8_t *Buf) { + write(Buf, Out::Dynamic->getVA()); + for (const SymbolBody *B : Entries) { + if (B) + Target->writeGotPltEntry(Buf, Out::Plt->getEntryAddr(*B)); + Buf += sizeof(uintX_t); + } +} + +template GotSection::GotSection() : OutputSectionBase(".got", llvm::ELF::SHT_PROGBITS, llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) { @@ -67,10 +104,17 @@ template void PltSection::writeTo(uint8_t *Buf) { size_t Off = 0; + bool LazyReloc = Target->supportsLazyRelocations(); + if (LazyReloc) { + // First write PLT[0] entry which is special. + Target->writePltZeroEntry(Buf, Out::GotPlt->getVA(), this->getVA()); + Off += Target->getPltZeroEntrySize(); + } for (const SymbolBody *E : Entries) { - uint64_t Got = Out::Got->getEntryAddr(*E); + uint64_t Got = LazyReloc ? Out::GotPlt->getEntryAddr(*E) + : Out::Got->getEntryAddr(*E); uint64_t Plt = this->getVA() + Off; - Target->writePltEntry(Buf + Off, Got, Plt); + Target->writePltEntry(Buf + Off, Got, Plt, E->PltIndex); Off += Target->getPltEntrySize(); } } @@ -83,17 +127,18 @@ template typename PltSection::uintX_t PltSection::getEntryAddr(const SymbolBody &B) const { - return this->getVA() + B.PltIndex * Target->getPltEntrySize(); + return this->getVA() + Target->getPltZeroEntrySize() + + B.PltIndex * Target->getPltEntrySize(); } -template -void PltSection::finalize() { - this->Header.sh_size = Entries.size() * Target->getPltEntrySize(); +template void PltSection::finalize() { + this->Header.sh_size = Target->getPltZeroEntrySize() + + Entries.size() * Target->getPltEntrySize(); } template -RelocationSection::RelocationSection(bool IsRela) - : OutputSectionBase(IsRela ? ".rela.dyn" : ".rel.dyn", +RelocationSection::RelocationSection(StringRef Name, bool IsRela) + : OutputSectionBase(Name, IsRela ? llvm::ELF::SHT_RELA : llvm::ELF::SHT_REL, llvm::ELF::SHF_ALLOC), IsRela(IsRela) { @@ -131,10 +176,23 @@ } if (NeedsGot) { - P->r_offset = Out::Got->getEntryAddr(*Body); + // Each symbol that needs plt relocation is placed to Plt and GotPlt, + // otherwise to Got. + // Also symbol can be placed both to Got and Plt + GotPlt, for example + // when we take address of function from DSO and also make a call to it. + // So here depending on what type of relocation is we switch from which + // table to take the offset from. + bool LazyReloc = Body && Target->supportsLazyRelocations() && + Target->relocNeedsPlt(Type, *Body); + if (LazyReloc) + P->r_offset = Out::GotPlt->getEntryAddr(*Body); + else + P->r_offset = Out::Got->getEntryAddr(*Body); if (CanBePreempted) P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), - Target->getGotReloc(), Config->Mips64EL); + LazyReloc ? Target->getPltReloc() + : Target->getGotReloc(), + Config->Mips64EL); } else { if (IsRela) Addend += static_cast(RI).r_addend; @@ -251,6 +309,13 @@ ++NumEntries; // DT_RELASZ / DT_RELSZ ++NumEntries; // DT_RELAENT / DT_RELENT } + // RelaPlt can be missing if target does not supports lazy relocations. + if (Out::RelaPlt && Out::RelaPlt->hasRelocs()) { + ++NumEntries; // DT_JMPREL + ++NumEntries; // DT_PLTRELSZ + ++NumEntries; // DT_PLTGOT + ++NumEntries; // DT_PLTREL + } ++NumEntries; // DT_SYMTAB ++NumEntries; // DT_SYMENT ++NumEntries; // DT_STRTAB @@ -318,6 +383,13 @@ WriteVal(IsRela ? DT_RELAENT : DT_RELENT, IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)); } + // RelaPlt can be missing if target does not supports lazy relocations. + if (Out::RelaPlt && Out::RelaPlt->hasRelocs()) { + WritePtr(DT_JMPREL, Out::RelaPlt->getVA()); + WriteVal(DT_PLTRELSZ, Out::RelaPlt->getSize()); + WritePtr(DT_PLTGOT, Out::GotPlt->getVA()); + WriteVal(DT_PLTREL, Out::RelaPlt->isRela() ? DT_RELA : DT_REL); + } WritePtr(DT_SYMTAB, Out::DynSymTab->getVA()); WritePtr(DT_SYMENT, sizeof(Elf_Sym)); @@ -696,6 +768,11 @@ template class OutputSectionBase; template class OutputSectionBase; +template class GotPltSection; +template class GotPltSection; +template class GotPltSection; +template class GotPltSection; + template class GotSection; template class GotSection; template class GotSection; Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -93,8 +93,10 @@ void setDynamicSymbolTableIndex(unsigned V) { DynamicSymbolTableIndex = V; } uint32_t GotIndex = -1; + uint32_t GotPltIndex = -1; uint32_t PltIndex = -1; bool isInGot() const { return GotIndex != -1U; } + bool isInGotPlt() const { return GotPltIndex != -1U; } bool isInPlt() const { return PltIndex != -1U; } // A SymbolBody has a backreference to a Symbol. Originally they are Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -24,12 +24,18 @@ 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; @@ -54,8 +60,11 @@ unsigned PCRelReloc; unsigned GotRefReloc; unsigned GotReloc; + unsigned PltReloc; unsigned RelativeReloc; unsigned PltEntrySize = 8; + unsigned PltZeroEntrySize = 0; + bool LazyRelocations = false; }; uint64_t getPPC64TocBase(); Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -47,8 +47,11 @@ 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; @@ -61,8 +64,11 @@ 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, @@ -74,8 +80,11 @@ 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, @@ -87,8 +96,11 @@ 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, @@ -99,8 +111,11 @@ template 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, @@ -144,10 +159,15 @@ 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)); @@ -194,19 +214,64 @@ 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; + if (LazyRelocations) { + PltEntrySize = 16; + PltZeroEntrySize = 16; + } else { + PltEntrySize = 8; + PltZeroEntrySize = 0; + } } -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}; - memcpy(Buf, Inst, sizeof(Inst)); +void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { + if (!LazyRelocations) + return; + // 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 { + if (!LazyRelocations) + return; + + 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 +} - uint64_t NextPC = PltEntryAddr + 6; - int64_t Delta = GotEntryAddr - NextPC; - assert(isInt<32>(Delta)); - write32le(Buf + 2, Delta); +void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr, + int32_t Index) const { + if (LazyRelocations) { + const uint8_t Inst[] = { + 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *got(%rip) + 0x68, 0x00, 0x00, 0x00, 0x00, // pushq + 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0] + }; + memcpy(Buf, Inst, sizeof(Inst)); + + write32le(Buf + 2, GotEntryAddr - PltEntryAddr - 6); + write32le(Buf + 7, Index); + write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16); + } else { + // jmpq *val(%rip); nop; nop + const uint8_t Inst[] = {0xff, 0x25, 0, 0, 0, 0, 0x90, 0x90}; + memcpy(Buf, Inst, sizeof(Inst)); + + uint64_t NextPC = PltEntryAddr + 6; + int64_t Delta = GotEntryAddr - NextPC; + assert(isInt<32>(Delta)); + write32le(Buf + 2, Delta); + } } bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { @@ -331,6 +396,7 @@ GotReloc = R_PPC64_GLOB_DAT; GotRefReloc = R_PPC64_REL64; RelativeReloc = R_PPC64_RELATIVE; + // PltReloc = FIXME PltEntrySize = 32; // We need 64K pages (at least under glibc/Linux, the loader won't @@ -365,8 +431,11 @@ 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 @@ -548,9 +617,14 @@ AArch64TargetInfo::AArch64TargetInfo() { // PCRelReloc = FIXME // GotReloc = FIXME + // PltReloc = 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; @@ -627,12 +701,18 @@ template MipsTargetInfo::MipsTargetInfo() { // PCRelReloc = FIXME // GotReloc = FIXME + // PltReloc = FIXME PageSize = 65536; } template +void MipsTargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {} +template +void MipsTargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, + uint64_t PltEntryAddr) const {} +template void MipsTargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr, - uint64_t PltEntryAddr) const {} + uint64_t PltEntryAddr, int32_t Index) const {} template bool MipsTargetInfo::relocNeedsGot(uint32_t Type, Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -101,6 +101,8 @@ Out::Bss = &Bss; GotSection Got; Out::Got = &Got; + GotPltSection GotPlt; + Out::GotPlt = Target->supportsLazyRelocations() ? &GotPlt : nullptr; PltSection Plt; Out::Plt = &Plt; SymbolTableSection SymTab(*Symtab, *Out::StrTab); @@ -109,8 +111,11 @@ Out::DynSymTab = &DynSymTab; HashTableSection HashTab; Out::HashTab = &HashTab; - RelocationSection RelaDyn(Symtab->shouldUseRela()); + bool IsRela = Symtab->shouldUseRela(); + RelocationSection RelaDyn(IsRela ? ".rela.dyn" : ".rel.dyn", IsRela); Out::RelaDyn = &RelaDyn; + RelocationSection RelaPlt(IsRela ? ".rela.plt" : ".rel.plt", IsRela); + Out::RelaPlt = Target->supportsLazyRelocations() ? &RelaPlt : nullptr; DynamicSection Dynamic(*Symtab); Out::Dynamic = &Dynamic; @@ -185,17 +190,21 @@ if (Body) Body = Body->repl(); bool NeedsGot = false; + bool NeedsPlt = false; if (Body) { - if (Target->relocNeedsPlt(Type, *Body)) { + if ((NeedsPlt = Target->relocNeedsPlt(Type, *Body))) { if (Body->isInPlt()) continue; Out::Plt->addEntry(Body); } - NeedsGot = Target->relocNeedsGot(Type, *Body); - if (NeedsGot) { - if (Body->isInGot()) - continue; - Out::Got->addEntry(Body); + if ((NeedsGot = Target->relocNeedsGot(Type, *Body))) { + if (NeedsPlt && Target->supportsLazyRelocations()) { + Out::GotPlt->addEntry(Body); + } else { + if (Body->isInGot()) + continue; + Out::Got->addEntry(Body); + } } } @@ -204,7 +213,10 @@ continue; if (CBP) Body->setUsedInDynamicReloc(); - Out::RelaDyn->addReloc({C, RI}); + if (NeedsPlt && Target->supportsLazyRelocations()) + Out::RelaPlt->addReloc({C, RI}); + else + Out::RelaDyn->addReloc({C, RI}); } } @@ -490,9 +502,13 @@ OutputSections.push_back(Out::DynStrTab); if (Out::RelaDyn->hasRelocs()) OutputSections.push_back(Out::RelaDyn); + if (Out::RelaPlt && Out::RelaPlt->hasRelocs()) + OutputSections.push_back(Out::RelaPlt); } if (!Out::Got->empty()) OutputSections.push_back(Out::Got); + if (Out::GotPlt && !Out::GotPlt->empty()) + OutputSections.push_back(Out::GotPlt); if (!Out::Plt->empty()) OutputSections.push_back(Out::Plt); Index: test/elf2/dynamic-reloc-weak.s =================================================================== --- test/elf2/dynamic-reloc-weak.s +++ test/elf2/dynamic-reloc-weak.s @@ -26,6 +26,8 @@ // 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: ] \ No newline at end of file Index: test/elf2/plt.s =================================================================== --- test/elf2/plt.s +++ test/elf2/plt.s @@ -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: ] @@ -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 - -// 0x20A0 - 0x1026 = 4218 -// 0x20A8 - 0x102e = 4218 -// 0x20B0 - 0x1036 = 4218 +// DISASM-NEXT: 1000: e9 {{.*}} jmp 43 +// DISASM-NEXT: 1005: e9 {{.*}} jmp 38 +// DISASM-NEXT: 100a: e9 {{.*}} jmp 49 +// DISASM-NEXT: 100f: e9 {{.*}} jmp 60 + +// 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 - -// 0x11020 - (0x11000 + 1) - 4 = 27 -// 0x11020 - (0x11005 + 1) - 4 = 22 -// 0x11028 - (0x1100a + 1) - 4 = 25 +// 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 +// 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 +// 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 + +// 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 +// 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 // DISASM2-NEXT-NOT: 110C0 .global _start Index: test/elf2/relocation.s =================================================================== --- test/elf2/relocation.s +++ test/elf2/relocation.s @@ -14,7 +14,7 @@ // 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 @@ -22,15 +22,30 @@ // 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: @@ -76,12 +91,12 @@ 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 @@ -99,4 +114,4 @@ // 0x120A8 - 0x10160 = 8008 // 8008 = 0x481f0000 in little endian // CHECK: Contents of section .R_X86_64_GOTPCREL -// CHECK-NEXT: 10160 481f0000 +// CHECK-NEXT: 10160 801f0000