summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/OutputSections.cpp2
-rw-r--r--lld/ELF/Writer.cpp44
-rw-r--r--lld/test/ELF/Inputs/relocation-copy-alias.s25
-rw-r--r--lld/test/ELF/relocation-copy-alias.s67
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
OpenPOWER on IntegriCloud