[lld] r251526 - [ELF2] R_X86_64_COPY relocation implemented
George Rimar via llvm-commits
llvm-commits at lists.llvm.org
Wed Oct 28 09:48:59 PDT 2015
Author: grimar
Date: Wed Oct 28 11:48:58 2015
New Revision: 251526
URL: http://llvm.org/viewvc/llvm-project?rev=251526&view=rev
Log:
[ELF2] R_X86_64_COPY relocation implemented
Differential revision: http://reviews.llvm.org/D14090.
Added:
lld/trunk/test/elf2/Inputs/relocation-copy.s
lld/trunk/test/elf2/relocation-copy.s
Modified:
lld/trunk/ELF/InputSection.cpp
lld/trunk/ELF/OutputSections.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Target.cpp
lld/trunk/ELF/Target.h
lld/trunk/ELF/Writer.cpp
Modified: lld/trunk/ELF/InputSection.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.cpp (original)
+++ lld/trunk/ELF/InputSection.cpp Wed Oct 28 11:48:58 2015
@@ -112,7 +112,8 @@ void InputSection<ELFT>::relocate(
} else if (Target->relocPointsToGot(Type)) {
SymVA = Out<ELFT>::Got->getVA();
Type = Target->getPCRelReloc();
- } else if (isa<SharedSymbol<ELFT>>(Body)) {
+ } else if (!Target->relocNeedsCopy(Type, Body) &&
+ isa<SharedSymbol<ELFT>>(Body)) {
continue;
}
Target->relocateOne(Buf + RI.r_offset, BufEnd, Type, BaseAddr + RI.r_offset,
Modified: lld/trunk/ELF/OutputSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/OutputSections.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/OutputSections.cpp (original)
+++ lld/trunk/ELF/OutputSections.cpp Wed Oct 28 11:48:58 2015
@@ -163,6 +163,7 @@ template <class ELFT> void RelocationSec
Body = Body->repl();
uint32_t Type = RI.getType(Config->Mips64EL);
+ bool NeedsCopy = Body && Target->relocNeedsCopy(Type, *Body);
bool NeedsGot = Body && Target->relocNeedsGot(Type, *Body);
bool CanBePreempted = canBePreempted(Body, NeedsGot);
bool LazyReloc = Body && Target->supportsLazyRelocations() &&
@@ -175,7 +176,8 @@ template <class ELFT> void RelocationSec
: Target->getGotReloc(),
Config->Mips64EL);
else
- P->setSymbolAndType(Body->getDynamicSymbolTableIndex(), Type,
+ P->setSymbolAndType(Body->getDynamicSymbolTableIndex(),
+ NeedsCopy ? Target->getCopyReloc() : Type,
Config->Mips64EL);
} else {
P->setSymbolAndType(0, Target->getRelativeReloc(), Config->Mips64EL);
@@ -186,6 +188,9 @@ template <class ELFT> void RelocationSec
P->r_offset = Out<ELFT>::GotPlt->getEntryAddr(*Body);
else
P->r_offset = Out<ELFT>::Got->getEntryAddr(*Body);
+ } else if (NeedsCopy) {
+ P->r_offset = Out<ELFT>::Bss->getVA() +
+ dyn_cast<SharedSymbol<ELFT>>(Body)->OffsetInBSS;
} else {
P->r_offset = RI.r_offset + C.OutSec->getVA() + C.OutSecOff;
}
@@ -195,7 +200,9 @@ template <class ELFT> void RelocationSec
OrigAddend = static_cast<const Elf_Rela &>(RI).r_addend;
uintX_t Addend;
- if (CanBePreempted)
+ if (NeedsCopy)
+ Addend = 0;
+ else if (CanBePreempted)
Addend = OrigAddend;
else if (Body)
Addend = getSymVA<ELFT>(cast<ELFSymbolBody<ELFT>>(*Body)) + OrigAddend;
@@ -637,7 +644,12 @@ typename ELFFile<ELFT>::uintX_t lld::elf
}
case SymbolBody::DefinedCommonKind:
return Out<ELFT>::Bss->getVA() + cast<DefinedCommon<ELFT>>(S).OffsetInBSS;
- case SymbolBody::SharedKind:
+ case SymbolBody::SharedKind: {
+ auto &SS = cast<SharedSymbol<ELFT>>(S);
+ if (SS.NeedsCopy)
+ return Out<ELFT>::Bss->getVA() + SS.OffsetInBSS;
+ return 0;
+ }
case SymbolBody::UndefinedKind:
return 0;
case SymbolBody::LazyKind:
@@ -990,9 +1002,13 @@ void SymbolTableSection<ELFT>::writeGlob
case SymbolBody::DefinedCommonKind:
OutSec = Out<ELFT>::Bss;
break;
+ case SymbolBody::SharedKind: {
+ if (cast<SharedSymbol<ELFT>>(Body)->NeedsCopy)
+ OutSec = Out<ELFT>::Bss;
+ break;
+ }
case SymbolBody::UndefinedKind:
case SymbolBody::DefinedAbsoluteKind:
- case SymbolBody::SharedKind:
case SymbolBody::LazyKind:
break;
}
Modified: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h Wed Oct 28 11:48:58 2015
@@ -271,6 +271,7 @@ typename Undefined<ELFT>::Elf_Sym Undefi
template <class ELFT> class SharedSymbol : public Defined<ELFT> {
typedef Defined<ELFT> Base;
typedef typename Base::Elf_Sym Elf_Sym;
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
public:
static bool classof(const SymbolBody *S) {
@@ -281,6 +282,10 @@ public:
: Defined<ELFT>(Base::SharedKind, Name, Sym), File(F) {}
SharedFile<ELFT> *File;
+
+ // Can have offset if requires copy relocation.
+ uintX_t OffsetInBSS = 0;
+ bool NeedsCopy = false;
};
// This class represents a symbol defined in an archive file. It is
Modified: lld/trunk/ELF/Target.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Target.cpp (original)
+++ lld/trunk/ELF/Target.cpp Wed Oct 28 11:48:58 2015
@@ -68,6 +68,7 @@ public:
uint64_t PltEntryAddr) const override;
void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr, int32_t Index) const override;
+ bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const override;
bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const override;
void relocateOne(uint8_t *Loc, uint8_t *BufEnd, uint32_t Type, uint64_t P,
@@ -144,6 +145,10 @@ TargetInfo *createTarget() {
TargetInfo::~TargetInfo() {}
+bool TargetInfo::relocNeedsCopy(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+
unsigned TargetInfo::getPLTRefReloc(unsigned Type) const { return PCRelReloc; }
bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; }
@@ -200,6 +205,7 @@ void X86TargetInfo::relocateOne(uint8_t
}
X86_64TargetInfo::X86_64TargetInfo() {
+ CopyReloc = R_X86_64_COPY;
PCRelReloc = R_X86_64_PC32;
GotReloc = R_X86_64_GLOB_DAT;
GotRefReloc = R_X86_64_PC32;
@@ -242,6 +248,15 @@ void X86_64TargetInfo::writePltEntry(uin
write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 16);
}
+bool X86_64TargetInfo::relocNeedsCopy(uint32_t Type,
+ const SymbolBody &S) const {
+ if (Type == R_X86_64_32S || Type == R_X86_64_32 || Type == R_X86_64_PC32 ||
+ Type == R_X86_64_64)
+ if (auto *SS = dyn_cast<SharedSymbol<ELF64LE>>(&S))
+ return SS->Sym.getType() == STT_OBJECT;
+ return false;
+}
+
bool X86_64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
return Type == R_X86_64_GOTPCREL || relocNeedsPlt(Type, S);
}
@@ -258,6 +273,9 @@ unsigned X86_64TargetInfo::getPLTRefRelo
}
bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
+ if (relocNeedsCopy(Type, S))
+ return false;
+
switch (Type) {
default:
return false;
Modified: lld/trunk/ELF/Target.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Target.h?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Target.h (original)
+++ lld/trunk/ELF/Target.h Wed Oct 28 11:48:58 2015
@@ -22,6 +22,7 @@ class TargetInfo {
public:
unsigned getPageSize() const { return PageSize; }
uint64_t getVAStart() const { return VAStart; }
+ unsigned getCopyReloc() const { return CopyReloc; }
unsigned getPCRelReloc() const { return PCRelReloc; }
unsigned getGotReloc() const { return GotReloc; }
unsigned getPltReloc() const { return PltReloc; }
@@ -37,6 +38,7 @@ public:
virtual void writePltEntry(uint8_t *Buf, uint64_t GotEntryAddr,
uint64_t PltEntryAddr, int32_t Index) const = 0;
virtual bool isRelRelative(uint32_t Type) const;
+ virtual bool relocNeedsCopy(uint32_t Type, const SymbolBody &S) const;
virtual bool relocNeedsGot(uint32_t Type, const SymbolBody &S) const = 0;
virtual bool relocPointsToGot(uint32_t Type) const;
virtual bool relocNeedsPlt(uint32_t Type, const SymbolBody &S) const = 0;
@@ -56,6 +58,7 @@ protected:
// 0x200000, but it looks like every OS uses 4k pages for executables.
uint64_t VAStart = 0x10000;
+ unsigned CopyReloc;
unsigned PCRelReloc;
unsigned GotRefReloc;
unsigned GotReloc;
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=251526&r1=251525&r2=251526&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Oct 28 11:48:58 2015
@@ -200,6 +200,11 @@ void Writer<ELFT>::scanRelocs(
bool NeedsGot = false;
bool NeedsPlt = false;
if (Body) {
+ if (auto *E = dyn_cast<SharedSymbol<ELFT>>(Body)) {
+ if (E->NeedsCopy)
+ continue;
+ E->NeedsCopy = Target->relocNeedsCopy(Type, *Body);
+ }
NeedsPlt = Target->relocNeedsPlt(Type, *Body);
if (NeedsPlt) {
if (Body->isInPlt())
@@ -395,6 +400,24 @@ static void addCommonSymbols(std::vector
Out<ELFT>::Bss->setSize(Off);
}
+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;
+
+ 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);
+ C->OffsetInBSS = Off;
+ Off += Sym.st_size;
+ }
+ Out<ELFT>::Bss->setSize(Off);
+}
+
static StringRef getOutputName(StringRef S) {
if (S.startswith(".text."))
return ".text";
@@ -498,6 +521,7 @@ template <class ELFT> void Writer<ELFT>:
scanRelocs(*S);
std::vector<DefinedCommon<ELFT> *> CommonSymbols;
+ std::vector<SharedSymbol<ELFT> *> SharedCopySymbols;
for (auto &P : Symtab.getSymbols()) {
SymbolBody *Body = P.second->Body;
if (auto *U = dyn_cast<Undefined<ELFT>>(Body))
@@ -506,6 +530,10 @@ template <class ELFT> void Writer<ELFT>:
if (auto *C = dyn_cast<DefinedCommon<ELFT>>(Body))
CommonSymbols.push_back(C);
+ if (auto *SC = dyn_cast<SharedSymbol<ELFT>>(Body))
+ if (SC->NeedsCopy)
+ SharedCopySymbols.push_back(SC);
+
if (!includeInSymtab<ELFT>(*Body))
continue;
if (Out<ELFT>::SymTab)
@@ -515,6 +543,7 @@ template <class ELFT> void Writer<ELFT>:
Out<ELFT>::DynSymTab->addSymbol(Body);
}
addCommonSymbols(CommonSymbols);
+ addSharedCopySymbols(SharedCopySymbols);
// This order is not the same as the final output order
// because we sort the sections using their attributes below.
Added: lld/trunk/test/elf2/Inputs/relocation-copy.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/Inputs/relocation-copy.s?rev=251526&view=auto
==============================================================================
--- lld/trunk/test/elf2/Inputs/relocation-copy.s (added)
+++ lld/trunk/test/elf2/Inputs/relocation-copy.s Wed Oct 28 11:48:58 2015
@@ -0,0 +1,14 @@
+.text
+.type x, at object
+.bss
+.globl x
+.align 4
+x:
+.long 0
+.size x, 4
+.type y, at object
+.globl y
+.align 4
+y:
+.long 0
+.size y, 4
Added: lld/trunk/test/elf2/relocation-copy.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elf2/relocation-copy.s?rev=251526&view=auto
==============================================================================
--- lld/trunk/test/elf2/relocation-copy.s (added)
+++ lld/trunk/test/elf2/relocation-copy.s Wed Oct 28 11:48:58 2015
@@ -0,0 +1,52 @@
+// 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.s -o %t2.o
+// RUN: ld.lld2 -shared %t2.o -o %t.so
+// RUN: ld.lld2 -e main %t.o %t.so -o %t3
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -r --expand-relocs %t3 | FileCheck %s
+// RUN: llvm-objdump -r -d %t3 | FileCheck -check-prefix=CODE %s
+
+.text
+.globl main
+.align 16, 0x90
+.type main, at function
+main:
+movl $5, x
+movl $7, y
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS (0x8)
+// CHECK-NEXT: Flags [ (0x3)
+// CHECK-NEXT: SHF_ALLOC (0x2)
+// CHECK-NEXT: SHF_WRITE (0x1)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x120A0
+// CHECK-NEXT: Offset: 0x20A0
+// CHECK-NEXT: Size: 20
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 0
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: x
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: y
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+
+// 73888 = 0x120A0
+// 16 is alignment here
+// 73892 = 0x120A0 + 16
+// 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
More information about the llvm-commits
mailing list