Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -223,6 +223,9 @@ bool AsNeeded = false; bool IsUsed = false; bool isNeeded() const { return !AsNeeded || IsUsed; } + + bool HasSortedObjectAliases = false; + std::vector *> SortedObjectAliases; }; std::unique_ptr createObjectFile(MemoryBufferRef MB, 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,71 @@ 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(); + if (!SS->File->HasSortedObjectAliases) { + SS->File->HasSortedObjectAliases = true; + auto &SOA = SS->File->SortedObjectAliases; + for (SharedSymbol &SSInFile : SS->File->getSharedSymbols()) { + if (SSInFile.Sym.getType() != STT_OBJECT) + continue; + SOA.push_back(&SSInFile); + } + std::stable_sort(SOA.begin(), SOA.end(), + [](SharedSymbol *S1, SharedSymbol *S2) { + return S1->Sym.st_value < S2->Sym.st_value; + }); + + uintX_t PrevVal; + size_t J = 0; + for (size_t I = 0; I != SOA.size();) { + uintX_t Val = SOA[I]->Sym.st_value; + if (I != 0 && PrevVal == Val) { + SOA[J++] = SOA[I-1]; + SOA[J++] = SOA[I]; + ++I; + while (I != SOA.size() && PrevVal == SOA[I]->Sym.st_value) + SOA[J++] = SOA[I++]; + } else { + ++I; + } + PrevVal = Val; + } + SOA.resize(J); + } + 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); + MaxAlign = std::max(MaxAlign, Align); + uintX_t Value = SS->Sym.st_value; + auto &SOA = SS->File->SortedObjectAliases; + auto I = std::lower_bound( + SOA.begin(), SOA.end(), Value, + [](SharedSymbol *S, uintX_t Val) { return S->Sym.st_value < Val; }); + if (I != SOA.end() && (*I)->Sym.st_value == Value) { + SharedSymbol *CopyRelSS = SS; + do { + (*I)->OffsetInBss = Off; + (*I)->NeedsCopyOrPltAddr = true; + (*I)->setUsedInRegularObj(); + (*I)->MustBeInDynSym = true; + if ((*I)->Sym.getBinding() == ELF::STB_GLOBAL) + CopyRelSS = *I; + ++I; + } while (I != SOA.end() && (*I)->Sym.st_value == Value); + Out::RelaDyn->addReloc( + {Target->CopyRel, DynamicReloc::Off_Bss, CopyRelSS}); + } else { SS->OffsetInBss = Off; - Off += SS->Sym.st_size; - MaxAlign = std::max(MaxAlign, Align); + SS->NeedsCopyOrPltAddr = true; + Out::RelaDyn->addReloc( + {Target->CopyRel, DynamicReloc::Off_Bss, SS}); } + Off += SS->Sym.st_size; Out::Bss->setSize(Off); Out::Bss->updateAlign(MaxAlign); } @@ -1061,7 +1109,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 +1117,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 +1132,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,47 @@ +// 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: Name: b1 +// CHECK-NEXT: Value: [[B:.*]] + +// CHECK: Name: b2 +// CHECK-NEXT: Value: [[B]] + +// CHECK: Name: a2 +// CHECK-NEXT: Value: [[A]] + +// CHECK: Name: b3 +// CHECK-NEXT: Value: [[B]]