diff options
-rw-r--r-- | lld/ELF/InputFiles.cpp | 54 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 10 | ||||
-rw-r--r-- | lld/ELF/OutputSections.h | 4 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 12 | ||||
-rw-r--r-- | lld/test/elf2/Inputs/relocation-copy.s | 11 | ||||
-rw-r--r-- | lld/test/elf2/relocation-copy.s | 13 |
6 files changed, 82 insertions, 22 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index b2142b75523..f5a142ac7c1 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -51,6 +51,20 @@ ELFFileBase<ELFT>::getSymbolsHelper(bool Local) { return make_range(Syms.begin() + 1, Syms.begin() + FirstNonLocal); } +template <class ELFT> +uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const { + uint32_t Index = Sym.st_shndx; + if (Index == ELF::SHN_XINDEX) + Index = this->ELFObj.getExtendedSymbolTableIndex(&Sym, this->Symtab, + SymtabSHNDX); + else if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) + return 0; + + if (!Index) + error("Invalid section index"); + return Index; +} + template <class ELFT> void ELFFileBase<ELFT>::initStringTable() { if (!Symtab) return; @@ -176,7 +190,7 @@ void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) { case SHT_SYMTAB_SHNDX: { ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = Obj.getSHNDXTable(Sec); error(ErrorOrTable); - SymtabSHNDX = *ErrorOrTable; + this->SymtabSHNDX = *ErrorOrTable; break; } case SHT_STRTAB: @@ -219,14 +233,10 @@ template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() { template <class ELFT> InputSectionBase<ELFT> * elf2::ObjectFile<ELFT>::getSection(const Elf_Sym &Sym) const { - uint32_t Index = Sym.st_shndx; - if (Index == ELF::SHN_XINDEX) - Index = this->ELFObj.getExtendedSymbolTableIndex(&Sym, this->Symtab, - SymtabSHNDX); - else if (Index == ELF::SHN_UNDEF || Index >= ELF::SHN_LORESERVE) + uint32_t Index = this->getSectionIndex(Sym); + if (Index == 0) return nullptr; - - if (Index >= Sections.size() || !Index || !Sections[Index]) + if (Index >= Sections.size() || !Sections[Index]) error("Invalid section index"); return Sections[Index]; } @@ -313,6 +323,17 @@ SharedFile<ELFT>::SharedFile(MemoryBufferRef M) AsNeeded = Config->AsNeeded; } +template <class ELFT> +const typename ELFFile<ELFT>::Elf_Shdr * +SharedFile<ELFT>::getSection(const Elf_Sym &Sym) const { + uint32_t Index = this->getSectionIndex(Sym); + if (Index == 0) + return nullptr; + ErrorOr<const Elf_Shdr *> Ret = this->ELFObj.getSection(Index); + error(Ret); + return *Ret; +} + template <class ELFT> void SharedFile<ELFT>::parseSoName() { typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn; typedef typename ELFFile<ELFT>::uintX_t uintX_t; @@ -320,11 +341,22 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { const ELFFile<ELFT> Obj = this->ELFObj; for (const Elf_Shdr &Sec : Obj.sections()) { - uint32_t Type = Sec.sh_type; - if (Type == SHT_DYNSYM) + switch (Sec.sh_type) { + default: + continue; + case SHT_DYNSYM: this->Symtab = &Sec; - else if (Type == SHT_DYNAMIC) + break; + case SHT_DYNAMIC: DynamicSec = &Sec; + break; + case SHT_SYMTAB_SHNDX: { + ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = Obj.getSHNDXTable(Sec); + error(ErrorOrTable); + this->SymtabSHNDX = *ErrorOrTable; + break; + } + } } this->initStringTable(); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index b8ef6b3e5c4..06f88f880b6 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -49,6 +49,8 @@ private: template <typename ELFT> class ELFFileBase : public InputFile { public: typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; + typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word; typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; ELFFileBase(Kind K, MemoryBufferRef M); @@ -78,9 +80,12 @@ public: StringRef getStringTable() const { return StringTable; } + uint32_t getSectionIndex(const Elf_Sym &Sym) const; + protected: llvm::object::ELFFile<ELFT> ELFObj; const Elf_Shdr *Symtab = nullptr; + ArrayRef<Elf_Word> SymtabSHNDX; StringRef StringTable; void initStringTable(); Elf_Sym_Range getNonLocalSymbols(); @@ -135,8 +140,6 @@ private: // List of all sections defined by this file. std::vector<InputSectionBase<ELFT> *> Sections; - ArrayRef<Elf_Word> SymtabSHNDX; - // List of all symbols referenced or defined by this file. std::vector<SymbolBody *> SymbolBodies; @@ -168,6 +171,7 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { typedef ELFFileBase<ELFT> Base; typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr; typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word; typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym_Range Elf_Sym_Range; std::vector<SharedSymbol<ELFT>> SymbolBodies; @@ -179,7 +183,7 @@ public: llvm::MutableArrayRef<SharedSymbol<ELFT>> getSharedSymbols() { return SymbolBodies; } - + const Elf_Shdr *getSection(const Elf_Sym &Sym) const; llvm::ArrayRef<StringRef> getUndefinedSymbols() { return Undefs; } static bool classof(const InputFile *F) { diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h index 5b3953e91af..5a23c86411c 100644 --- a/lld/ELF/OutputSections.h +++ b/lld/ELF/OutputSections.h @@ -93,6 +93,10 @@ public: return std::max<uintX_t>(Header.sh_addralign, 1); } uint32_t getType() { return Header.sh_type; } + void updateAlign(uintX_t Align) { + if (Align > Header.sh_addralign) + Header.sh_addralign = Align; + } virtual void finalize() {} virtual void writeTo(uint8_t *Buf) = 0; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index d440afb7e85..426fd8b7bd6 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -404,14 +404,18 @@ template <class ELFT> static void addSharedCopySymbols(std::vector<SharedSymbol<ELFT> *> &Syms) { typedef typename ELFFile<ELFT>::uintX_t uintX_t; typedef typename ELFFile<ELFT>::Elf_Sym Elf_Sym; + typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr; uintX_t Off = Out<ELFT>::Bss->getSize(); for (SharedSymbol<ELFT> *C : Syms) { const Elf_Sym &Sym = C->Sym; - // We don't know the exact alignment requirement for the data copied by a - // copy relocation, so align that to 16 byte boundaries that should be large - // enough unconditionally. - Off = RoundUpToAlignment(Off, 16); + const Elf_Shdr *Sec = C->File->getSection(Sym); + uintX_t SecAlign = Sec->sh_addralign; + uintX_t Align = Sym.st_value % SecAlign; + if (Align == 0) + Align = SecAlign; + Out<ELFT>::Bss->updateAlign(Align); + Off = RoundUpToAlignment(Off, Align); C->OffsetInBSS = Off; Off += Sym.st_size; } diff --git a/lld/test/elf2/Inputs/relocation-copy.s b/lld/test/elf2/Inputs/relocation-copy.s index dfa73673c4c..35341652da9 100644 --- a/lld/test/elf2/Inputs/relocation-copy.s +++ b/lld/test/elf2/Inputs/relocation-copy.s @@ -2,14 +2,21 @@ .type x,@object .globl x -.align 4 +.align 16 x: .long 0 .size x, 4 .type y,@object .globl y -.align 4 +.align 16 y: .long 0 .size y, 4 + +.type z,@object +.globl z +.align 4 +z: +.long 0 +.size z, 4 diff --git a/lld/test/elf2/relocation-copy.s b/lld/test/elf2/relocation-copy.s index f4eb11279e3..c4a4f0f27b0 100644 --- a/lld/test/elf2/relocation-copy.s +++ b/lld/test/elf2/relocation-copy.s @@ -13,6 +13,7 @@ main: movl $5, x movl $7, y +movl $9, z // CHECK: Name: .bss // CHECK-NEXT: Type: SHT_NOBITS (0x8) @@ -22,10 +23,10 @@ movl $7, y // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x120A0 // CHECK-NEXT: Offset: 0x20A0 -// CHECK-NEXT: Size: 20 +// CHECK-NEXT: Size: 24 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 -// CHECK-NEXT: AddressAlignment: 4 +// CHECK-NEXT: AddressAlignment: 16 // CHECK-NEXT: EntrySize: 0 // CHECK: Relocations [ @@ -42,13 +43,21 @@ movl $7, y // CHECK-NEXT: Symbol: y // CHECK-NEXT: Addend: 0x0 // CHECK-NEXT: } +// CHECK-NEXT: Relocation { +// CHECK-NEXT: Offset: +// CHECK-NEXT: Type: R_X86_64_COPY +// CHECK-NEXT: Symbol: z +// CHECK-NEXT: Addend: 0x0 +// CHECK-NEXT: } // CHECK-NEXT: } // CHECK-NEXT: ] // 73888 = 0x120A0 // 16 is alignment here // 73904 = 0x120A0 + 16 +// 73908 = 0x120A0 + 16 + 4 // CODE: Disassembly of section .text: // CODE-NEXT: main: // CODE-NEXT: 11000: c7 04 25 a0 20 01 00 05 00 00 00 movl $5, 73888 // CODE-NEXT: 1100b: c7 04 25 b0 20 01 00 07 00 00 00 movl $7, 73904 +// CODE-NEXT: 11016: c7 04 25 b4 20 01 00 09 00 00 00 movl $9, 73908 |