[ELF2] R_X86_64_COPY relocation implemented

Differential revision: http://reviews.llvm.org/D14090.

llvm-svn: 251526
This commit is contained in:
George Rimar 2015-10-28 16:48:58 +00:00
parent 36e84c0fc7
commit bc590feb2b
8 changed files with 143 additions and 5 deletions

View File

@ -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,

View File

@ -163,6 +163,7 @@ template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
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 RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
: 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 RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
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 RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
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::elf2::getSymVA(const SymbolBody &S) {
}
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>::writeGlobalSymbols(uint8_t *Buf) {
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;
}

View File

@ -271,6 +271,7 @@ typename Undefined<ELFT>::Elf_Sym Undefined<ELFT>::Optional;
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

View File

@ -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 *Loc, uint8_t *BufEnd, uint32_t Type,
}
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(uint8_t *Buf, uint64_t GotEntryAddr,
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::getPLTRefReloc(unsigned Type) const {
}
bool X86_64TargetInfo::relocNeedsPlt(uint32_t Type, const SymbolBody &S) const {
if (relocNeedsCopy(Type, S))
return false;
switch (Type) {
default:
return false;

View File

@ -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;

View File

@ -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<DefinedCommon<ELFT> *> &Syms) {
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>::createSections() {
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>::createSections() {
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>::createSections() {
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.

View File

@ -0,0 +1,14 @@
.text
.type x,@object
.bss
.globl x
.align 4
x:
.long 0
.size x, 4
.type y,@object
.globl y
.align 4
y:
.long 0
.size y, 4

View File

@ -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,@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