mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-14 11:39:35 +00:00
[ELF2] R_X86_64_COPY relocation implemented
Differential revision: http://reviews.llvm.org/D14090. llvm-svn: 251526
This commit is contained in:
parent
36e84c0fc7
commit
bc590feb2b
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
14
lld/test/elf2/Inputs/relocation-copy.s
Normal file
14
lld/test/elf2/Inputs/relocation-copy.s
Normal 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
|
52
lld/test/elf2/relocation-copy.s
Normal file
52
lld/test/elf2/relocation-copy.s
Normal 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
|
Loading…
Reference in New Issue
Block a user