diff options
-rw-r--r-- | lld/ELF/OutputSections.cpp | 2 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 44 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/relocation-copy-alias.s | 25 | ||||
-rw-r--r-- | lld/test/ELF/relocation-copy-alias.s | 67 |
4 files changed, 115 insertions, 23 deletions
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index c019fa0f444..7617585a803 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -839,7 +839,7 @@ static int getPriority(StringRef S) { // This function is called after we sort input sections // and scan relocations to setup sections' offsets. template <class ELFT> void OutputSection<ELFT>::assignOffsets() { - uintX_t Off = 0; + uintX_t Off = this->Header.sh_size; for (InputSection<ELFT> *S : Sections) { Off = alignTo(Off, S->Align); S->OutSecOff = Off; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 1d8fdcff04c..dfb4380a268 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -96,7 +96,7 @@ private: void ensureBss(); void addCommonSymbols(std::vector<DefinedCommon *> &Syms); - void addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms); + void addCopyRelSymbol(SharedSymbol<ELFT> *Sym); std::unique_ptr<llvm::FileOutputBuffer> Buffer; @@ -385,9 +385,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, if (B->needsCopy()) continue; if (Target->needsCopyRel<ELFT>(Type, *B)) { - B->NeedsCopyOrPltAddr = true; - Out<ELFT>::RelaDyn->addReloc( - {Target->CopyRel, DynamicReloc<ELFT>::Off_Bss, B}); + addCopyRelSymbol(B); continue; } } @@ -741,23 +739,30 @@ template <class ELFT> static uint32_t getAlignment(SharedSymbol<ELFT> *SS) { return 1 << TrailingZeros; } -// Reserve space in .bss for copy relocations. +// Reserve space in .bss for copy relocation. template <class ELFT> -void Writer<ELFT>::addCopyRelSymbols(std::vector<SharedSymbol<ELFT> *> &Syms) { - if (Syms.empty()) - return; +void Writer<ELFT>::addCopyRelSymbol(SharedSymbol<ELFT> *SS) { ensureBss(); uintX_t Off = Out<ELFT>::Bss->getSize(); - uintX_t MaxAlign = Out<ELFT>::Bss->getAlign(); - for (SharedSymbol<ELFT> *SS : Syms) { - uintX_t Align = getAlignment(SS); - Off = alignTo(Off, Align); - SS->OffsetInBss = Off; - Off += SS->template getSize<ELFT>(); - MaxAlign = std::max(MaxAlign, Align); + uintX_t Align = getAlignment(SS); + Off = alignTo(Off, Align); + Out<ELFT>::Bss->setSize(Off + SS->template getSize<ELFT>()); + Out<ELFT>::Bss->updateAlign(Align); + Out<ELFT>::RelaDyn->addReloc( + {Target->CopyRel, DynamicReloc<ELFT>::Off_Bss, SS}); + uintX_t Shndx = SS->Sym.st_shndx; + uintX_t Value = SS->Sym.st_value; + // Look through the DSO's dynamic symbol for aliases and create a dynamic + // symbol for each one. This causes the copy relocation to correctly interpose + // any aliases. + for (SharedSymbol<ELFT> &S : SS->File->getSharedSymbols()) { + if (S.Sym.st_shndx != Shndx || S.Sym.st_value != Value) + continue; + S.OffsetInBss = Off; + S.NeedsCopyOrPltAddr = true; + S.setUsedInRegularObj(); + S.MustBeInDynSym = true; } - Out<ELFT>::Bss->setSize(Off); - Out<ELFT>::Bss->updateAlign(MaxAlign); } template <class ELFT> @@ -1080,7 +1085,6 @@ template <class ELFT> void Writer<ELFT>::createSections() { // Now that we have defined all possible symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. std::vector<DefinedCommon *> CommonSymbols; - std::vector<SharedSymbol<ELFT> *> CopyRelSymbols; for (auto &P : Symtab.getSymbols()) { SymbolBody *Body = P.second->Body; if (auto *U = dyn_cast<Undefined>(Body)) @@ -1089,9 +1093,6 @@ template <class ELFT> void Writer<ELFT>::createSections() { if (auto *C = dyn_cast<DefinedCommon>(Body)) CommonSymbols.push_back(C); - if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body)) - if (SC->needsCopy()) - CopyRelSymbols.push_back(SC); if (!includeInSymtab<ELFT>(*Body)) continue; @@ -1107,7 +1108,6 @@ template <class ELFT> void Writer<ELFT>::createSections() { return; addCommonSymbols(CommonSymbols); - addCopyRelSymbols(CopyRelSymbols); // So far we have added sections from input object files. // This function adds linker-created Out<ELFT>::* sections. diff --git a/lld/test/ELF/Inputs/relocation-copy-alias.s b/lld/test/ELF/Inputs/relocation-copy-alias.s new file mode 100644 index 00000000000..a9bc3d76a12 --- /dev/null +++ b/lld/test/ELF/Inputs/relocation-copy-alias.s @@ -0,0 +1,25 @@ +.data + +.globl a1 +.type a1, @object +.size a1, 1 +a1: +.weak a2 +.type a2, @object +.size a2, 1 +a2: +.byte 1 + +.weak b1 +.type b1, @object +.size b1, 1 +b1: +.weak b2 +.type b2, @object +.size b2, 1 +b2: +.globl b3 +.type b3, @object +.size b3, 1 +b3: +.byte 1 diff --git a/lld/test/ELF/relocation-copy-alias.s b/lld/test/ELF/relocation-copy-alias.s new file mode 100644 index 00000000000..d3256d24b53 --- /dev/null +++ b/lld/test/ELF/relocation-copy-alias.s @@ -0,0 +1,67 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-alias.s -o %t2.o +// RUN: ld.lld -shared %t2.o -o %t.so +// RUN: ld.lld %t.o %t.so -o %t3 +// RUN: llvm-readobj --dyn-symbols -r --expand-relocs %t3 | FileCheck %s + +.global _start +_start: +movl $5, a1 +movl $5, b1 +movl $5, b2 + +// CHECK: .rela.dyn { +// CHECK-NEXT: Relocation { +// CHECK-NEXT: Offset: +// CHECK-NEXT: Type: R_X86_64_COPY +// CHECK-NEXT: Symbol: a1 +// CHECK-NEXT: Addend: 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: Relocation { +// CHECK-NEXT: Offset: +// CHECK-NEXT: Type: R_X86_64_COPY +// CHECK-NEXT: Symbol: b1 +// CHECK-NEXT: Addend: 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: } + +// CHECK: Name: a1 +// CHECK-NEXT: Value: [[A:.*]] +// CHECK-NEXT: Size: 1 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss (0x7) + +// CHECK: Name: b1 +// CHECK-NEXT: Value: [[B:.*]] +// CHECK-NEXT: Size: 1 +// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss + +// CHECK: Name: b2 +// CHECK-NEXT: Value: [[B]] +// CHECK-NEXT: Size: 1 +// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss + +// CHECK: Name: a2 +// CHECK-NEXT: Value: [[A]] +// CHECK-NEXT: Size: 1 +// CHECK-NEXT: Binding: Weak (0x2) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss + +// CHECK: Name: b3 +// CHECK-NEXT: Value: [[B]] +// CHECK-NEXT: Size: 1 +// CHECK-NEXT: Binding: Global (0x1) +// CHECK-NEXT: Type: Object (0x1) +// CHECK-NEXT: Other: 0 +// CHECK-NEXT: Section: .bss |