Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -839,7 +839,7 @@ // This function is called after we sort input sections // and scan relocations to setup sections' offsets. template void OutputSection::assignOffsets() { - uintX_t Off = 0; + uintX_t Off = this->Header.sh_size; for (InputSection *S : Sections) { Off = alignTo(Off, S->Align); S->OutSecOff = Off; Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -96,7 +96,7 @@ void ensureBss(); void addCommonSymbols(std::vector &Syms); - void addCopyRelSymbols(std::vector *> &Syms); + void addCopyRelSymbol(SharedSymbol *Sym); std::unique_ptr Buffer; @@ -385,9 +385,7 @@ if (B->needsCopy()) continue; if (Target->needsCopyRel(Type, *B)) { - B->NeedsCopyOrPltAddr = true; - Out::RelaDyn->addReloc( - {Target->CopyRel, DynamicReloc::Off_Bss, B}); + addCopyRelSymbol(B); continue; } } @@ -743,21 +741,34 @@ return 1 << TrailingZeros; } -// Reserve space in .bss for copy relocations. +// Reserve space in .bss for copy relocation. template -void Writer::addCopyRelSymbols(std::vector *> &Syms) { - if (Syms.empty()) - return; +void Writer::addCopyRelSymbol(SharedSymbol *SS) { ensureBss(); uintX_t Off = Out::Bss->getSize(); + uintX_t Align = getAlignment(SS); + Off = alignTo(Off, Align); uintX_t MaxAlign = Out::Bss->getAlign(); - for (SharedSymbol *SS : Syms) { - uintX_t Align = getAlignment(SS); - Off = alignTo(Off, Align); - SS->OffsetInBss = Off; - Off += SS->Sym.st_size; - MaxAlign = std::max(MaxAlign, Align); + MaxAlign = std::max(MaxAlign, Align); + uintX_t Shndx = SS->Sym.st_shndx; + uintX_t Value = SS->Sym.st_value; + SharedSymbol *CopyRelSS = SS; + // 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 &SSInFile : SS->File->getSharedSymbols()) { + if (SSInFile.Sym.st_shndx == Shndx && SSInFile.Sym.st_value == Value) { + SSInFile.OffsetInBss = Off; + SSInFile.NeedsCopyOrPltAddr = true; + SSInFile.setUsedInRegularObj(); + SSInFile.MustBeInDynSym = true; + if (SSInFile.Sym.getBinding() == ELF::STB_GLOBAL) + CopyRelSS = &SSInFile; + } } + Out::RelaDyn->addReloc( + {Target->CopyRel, DynamicReloc::Off_Bss, CopyRelSS}); + Off += SS->Sym.st_size; Out::Bss->setSize(Off); Out::Bss->updateAlign(MaxAlign); } @@ -1061,7 +1072,6 @@ // Now that we have defined all possible symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. std::vector CommonSymbols; - std::vector *> CopyRelSymbols; for (auto &P : Symtab.getSymbols()) { SymbolBody *Body = P.second->Body; if (auto *U = dyn_cast(Body)) @@ -1070,9 +1080,6 @@ if (auto *C = dyn_cast(Body)) CommonSymbols.push_back(C); - if (auto *SC = dyn_cast>(Body)) - if (SC->needsCopy()) - CopyRelSymbols.push_back(SC); if (!includeInSymtab(*Body)) continue; @@ -1088,7 +1095,6 @@ return; addCommonSymbols(CommonSymbols); - addCopyRelSymbols(CopyRelSymbols); // So far we have added sections from input object files. // This function adds linker-created Out::* sections. Index: test/ELF/Inputs/relocation-copy-alias.s =================================================================== --- /dev/null +++ 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 Index: test/ELF/relocation-copy-alias.s =================================================================== --- /dev/null +++ test/ELF/relocation-copy-alias.s @@ -0,0 +1,72 @@ +// 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-NOT: Relocation { + +// CHECK: Relocation { +// CHECK-NEXT: Offset: +// CHECK-NEXT: Type: R_X86_64_COPY +// CHECK-NEXT: Symbol: a1 +// CHECK-NEXT: Addend: 0x0 +// CHECK-NEXT: } + +// CHECK-NOT: Relocation { + +// CHECK: Relocation { +// CHECK-NEXT: Offset: +// CHECK-NEXT: Type: R_X86_64_COPY +// CHECK-NEXT: Symbol: b3 +// CHECK-NEXT: Addend: 0x0 +// CHECK-NEXT: } + +// CHECK-NOT: Relocation { + +// 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