forked from OSchip/llvm-project
[ELF][x86-64] Separate static and dynamic GOT/PLT generation.
llvm-svn: 176294
This commit is contained in:
parent
ca5a85fad4
commit
a26f71c9ed
|
@ -164,9 +164,11 @@ public:
|
|||
_references.push_back(SimpleReference(kind, offset, target, addend));
|
||||
}
|
||||
|
||||
void setOrdinal(uint64_t ord) { _ordinal = ord; }
|
||||
|
||||
private:
|
||||
const File &_file;
|
||||
uint32_t _ordinal;
|
||||
uint64_t _ordinal;
|
||||
std::vector<SimpleReference> _references;
|
||||
};
|
||||
|
||||
|
|
|
@ -184,10 +184,7 @@ public:
|
|||
, _referenceStartIndex(referenceStart)
|
||||
, _referenceEndIndex(referenceEnd)
|
||||
, _referenceList(referenceList)
|
||||
, _targetAtomHandler(nullptr) {
|
||||
static uint64_t orderNumber = 0;
|
||||
_ordinal = ++orderNumber;
|
||||
}
|
||||
, _targetAtomHandler(nullptr) {}
|
||||
|
||||
virtual const ELFFile<ELFT> &file() const {
|
||||
return _owningFile;
|
||||
|
@ -480,8 +477,9 @@ public:
|
|||
_referenceEndIndex = _referenceList.size();
|
||||
}
|
||||
|
||||
private:
|
||||
void setOrdinal(uint64_t ord) { _ordinal = ord; }
|
||||
|
||||
private:
|
||||
const ELFFile<ELFT> &_owningFile;
|
||||
StringRef _symbolName;
|
||||
StringRef _sectionName;
|
||||
|
|
|
@ -98,7 +98,8 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
|||
*reinterpret_cast<llvm::support::little64_t *>(location) = result;
|
||||
}
|
||||
break;
|
||||
case R_X86_64_TLSLD:
|
||||
}
|
||||
case R_X86_64_TLSLD: {
|
||||
// Rewrite to move %fs:0 into %rax. Technically we should verify that the
|
||||
// next relocation is a PC32 to __tls_get_addr...
|
||||
static uint8_t instr[] = { 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25,
|
||||
|
@ -106,9 +107,25 @@ ErrorOr<void> X86_64TargetRelocationHandler::applyRelocation(
|
|||
std::memcpy(location - 3, instr, sizeof(instr));
|
||||
break;
|
||||
}
|
||||
case LLD_R_X86_64_GOTRELINDEX: {
|
||||
const DefinedAtom *target = cast<const DefinedAtom>(ref.target());
|
||||
for (const Reference *r : *target) {
|
||||
if (r->kind() == R_X86_64_JUMP_SLOT) {
|
||||
uint32_t index;
|
||||
if (!_targetInfo.getTargetHandler<X86_64ELFType>().targetLayout()
|
||||
.getPLTRelocationTable()->getRelocationIndex(*r, index))
|
||||
llvm_unreachable("Relocation doesn't exist");
|
||||
reloc32(location, 0, index, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Runtime only relocations. Ignore here.
|
||||
case R_X86_64_RELATIVE:
|
||||
case R_X86_64_IRELATIVE:
|
||||
case R_X86_64_JUMP_SLOT:
|
||||
case R_X86_64_GLOB_DAT:
|
||||
break;
|
||||
|
||||
case lld::Reference::kindLayoutAfter:
|
||||
|
@ -142,7 +159,7 @@ public:
|
|||
|
||||
virtual SectionChoice sectionChoice() const { return sectionCustomRequired; }
|
||||
|
||||
virtual StringRef customSectionName() const { return ".got"; }
|
||||
virtual StringRef customSectionName() const { return ".got.plt"; }
|
||||
|
||||
virtual ContentType contentType() const { return typeGOT; }
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace lld;
|
||||
using namespace lld::elf;
|
||||
|
||||
namespace {
|
||||
using namespace llvm::ELF;
|
||||
|
@ -90,8 +91,7 @@ public:
|
|||
}
|
||||
|
||||
virtual Alignment alignment() const {
|
||||
// The alignment should be 4 byte aligned
|
||||
return Alignment(2);
|
||||
return Alignment(4); // 16
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
@ -105,10 +105,31 @@ public:
|
|||
|
||||
const uint8_t PLTAtom::_defaultContent[16] = {
|
||||
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmpq *gotatom(%rip)
|
||||
0x68, 0x00, 0x00, 0x00, 0x00, // pushq pltentry
|
||||
0x68, 0x00, 0x00, 0x00, 0x00, // pushq reloc-index
|
||||
0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[-1]
|
||||
};
|
||||
|
||||
class PLT0Atom : public PLTAtom {
|
||||
static const uint8_t _plt0Content[16];
|
||||
|
||||
public:
|
||||
PLT0Atom(const File &f) : PLTAtom(f, ".plt") {
|
||||
#ifndef NDEBUG
|
||||
_name = ".PLT0";
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual ArrayRef<uint8_t> rawContent() const {
|
||||
return ArrayRef<uint8_t>(_plt0Content, 16);
|
||||
}
|
||||
};
|
||||
|
||||
const uint8_t PLT0Atom::_plt0Content[16] = {
|
||||
0xff, 0x35, 0x00, 0x00, 0x00, 0x00, // pushq GOT+8(%rip)
|
||||
0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *GOT+16(%rip)
|
||||
0x90, 0x90, 0x90, 0x90 // nopnopnop
|
||||
};
|
||||
|
||||
class ELFPassFile : public SimpleFile {
|
||||
public:
|
||||
ELFPassFile(const ELFTargetInfo &eti) : SimpleFile(eti, "ELFPassFile") {}
|
||||
|
@ -121,16 +142,15 @@ public:
|
|||
template <class Derived> class GOTPLTPass : public Pass {
|
||||
/// \brief Handle a specific reference.
|
||||
void handleReference(const DefinedAtom &atom, const Reference &ref) {
|
||||
const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target());
|
||||
switch (ref.kind()) {
|
||||
case R_X86_64_PLT32:
|
||||
static_cast<Derived *>(this)->handlePLT32(ref);
|
||||
break;
|
||||
case R_X86_64_PC32:
|
||||
static_cast<Derived *>(this)->handleIFUNC(ref, da);
|
||||
static_cast<Derived *>(this)->handlePC32(ref);
|
||||
break;
|
||||
case R_X86_64_GOTTPOFF: // GOT Thread Pointer Offset
|
||||
static_cast<Derived *>(this)->handleGOTTPOFF(ref, da);
|
||||
static_cast<Derived *>(this)->handleGOTTPOFF(ref);
|
||||
break;
|
||||
case R_X86_64_GOTPCREL:
|
||||
static_cast<Derived *>(this)->handleGOTPCREL(ref);
|
||||
|
@ -165,7 +185,8 @@ protected:
|
|||
///
|
||||
/// This create a PLT and GOT entry for the IFUNC if one does not exist. The
|
||||
/// GOT entry and a IRELATIVE relocation to the original target resolver.
|
||||
ErrorOr<void> handleIFUNC(const Reference &ref, const DefinedAtom *target) {
|
||||
ErrorOr<void> handleIFUNC(const Reference &ref) {
|
||||
auto target = dyn_cast_or_null<const DefinedAtom>(ref.target());
|
||||
if (target && target->contentType() == DefinedAtom::typeResolver)
|
||||
const_cast<Reference &>(ref).setTarget(getIFUNCPLTEntry(target));
|
||||
return error_code::success();
|
||||
|
@ -189,7 +210,8 @@ protected:
|
|||
|
||||
/// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
|
||||
/// the GOT.
|
||||
void handleGOTTPOFF(const Reference &ref, const DefinedAtom *target) {
|
||||
void handleGOTTPOFF(const Reference &ref) {
|
||||
auto target = dyn_cast_or_null<const DefinedAtom>(ref.target());
|
||||
const_cast<Reference &>(ref).setTarget(getGOTTPOFF(target));
|
||||
const_cast<Reference &>(ref).setKind(R_X86_64_PC32);
|
||||
}
|
||||
|
@ -197,7 +219,7 @@ protected:
|
|||
/// \brief Create a GOT entry containing 0.
|
||||
const GOTAtom *getNullGOT() {
|
||||
if (!_null) {
|
||||
_null = new (_file._alloc) GOTAtom(_file, ".got");
|
||||
_null = new (_file._alloc) GOTAtom(_file, ".got.plt");
|
||||
#ifndef NDEBUG
|
||||
_null->_name = "__got_null";
|
||||
#endif
|
||||
|
@ -231,7 +253,9 @@ protected:
|
|||
}
|
||||
|
||||
public:
|
||||
GOTPLTPass(const ELFTargetInfo &ti) : _file(ti), _null(nullptr) {}
|
||||
GOTPLTPass(const ELFTargetInfo &ti)
|
||||
: _file(ti), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
|
||||
_got1(nullptr) {}
|
||||
|
||||
/// \brief Do the pass.
|
||||
///
|
||||
|
@ -248,23 +272,51 @@ public:
|
|||
handleReference(*atom, *ref);
|
||||
|
||||
// Add all created atoms to the link.
|
||||
if (_null)
|
||||
mf.addAtom(*_null);
|
||||
for (const auto &got : _gotMap)
|
||||
mf.addAtom(*got.second);
|
||||
for (const auto &plt : _pltMap)
|
||||
uint64_t ordinal = 0;
|
||||
if (_PLT0) {
|
||||
_PLT0->setOrdinal(ordinal++);
|
||||
mf.addAtom(*_PLT0);
|
||||
}
|
||||
for (const auto &plt : _pltMap) {
|
||||
plt.second->setOrdinal(ordinal++);
|
||||
mf.addAtom(*plt.second);
|
||||
}
|
||||
if (_null) {
|
||||
_null->setOrdinal(ordinal++);
|
||||
mf.addAtom(*_null);
|
||||
}
|
||||
if (_PLT0) {
|
||||
_got0->setOrdinal(ordinal++);
|
||||
_got1->setOrdinal(ordinal++);
|
||||
mf.addAtom(*_got0);
|
||||
mf.addAtom(*_got1);
|
||||
}
|
||||
for (const auto &got : _gotMap) {
|
||||
got.second->setOrdinal(ordinal++);
|
||||
mf.addAtom(*got.second);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \brief Owner of all the Atoms created by this pass.
|
||||
ELFPassFile _file;
|
||||
|
||||
/// \brief Map Atoms to their GOT entries.
|
||||
llvm::DenseMap<const Atom *, const GOTAtom *> _gotMap;
|
||||
llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
|
||||
|
||||
/// \brief Map Atoms to their PLT entries.
|
||||
llvm::DenseMap<const Atom *, const PLTAtom *> _pltMap;
|
||||
llvm::DenseMap<const Atom *, PLTAtom *> _pltMap;
|
||||
|
||||
/// \brief GOT entry that is always 0. Used for undefined weaks.
|
||||
GOTAtom *_null;
|
||||
|
||||
/// \brief The got and plt entries for .PLT0. This is used to call into the
|
||||
/// dynamic linker for symbol resolution.
|
||||
/// @{
|
||||
PLT0Atom *_PLT0;
|
||||
GOTAtom *_got0;
|
||||
GOTAtom *_got1;
|
||||
/// @}
|
||||
};
|
||||
|
||||
/// This implements the static relocation model. Meaning GOT and PLT entries are
|
||||
|
@ -288,23 +340,47 @@ public:
|
|||
// Handle IFUNC.
|
||||
if (const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target()))
|
||||
if (da->contentType() == DefinedAtom::typeResolver)
|
||||
return handleIFUNC(ref, da);
|
||||
return handleIFUNC(ref);
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
ErrorOr<void> handlePC32(const Reference &ref) { return handleIFUNC(ref); }
|
||||
};
|
||||
|
||||
class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass<DynamicGOTPLTPass> {
|
||||
public:
|
||||
DynamicGOTPLTPass(const elf::X86_64TargetInfo &ti) : GOTPLTPass(ti) {}
|
||||
|
||||
const PLT0Atom *getPLT0() {
|
||||
if (_PLT0)
|
||||
return _PLT0;
|
||||
// Fill in the null entry.
|
||||
getNullGOT();
|
||||
_PLT0 = new (_file._alloc) PLT0Atom(_file);
|
||||
_got0 = new (_file._alloc) GOTAtom(_file, ".got.plt");
|
||||
_got1 = new (_file._alloc) GOTAtom(_file, ".got.plt");
|
||||
_PLT0->addReference(R_X86_64_PC32, 2, _got0, -4);
|
||||
_PLT0->addReference(R_X86_64_PC32, 8, _got1, -4);
|
||||
#ifndef NDEBUG
|
||||
_got0->_name = "__got0";
|
||||
_got1->_name = "__got1";
|
||||
#endif
|
||||
return _PLT0;
|
||||
}
|
||||
|
||||
const PLTAtom *getPLTEntry(const Atom *a) {
|
||||
auto plt = _pltMap.find(a);
|
||||
if (plt != _pltMap.end())
|
||||
return plt->second;
|
||||
auto ga = new (_file._alloc) GOTAtom(_file, ".got.plt");
|
||||
ga->addReference(R_X86_64_RELATIVE, 0, a, 0);
|
||||
ga->addReference(R_X86_64_JUMP_SLOT, 0, a, 0);
|
||||
auto pa = new (_file._alloc) PLTAtom(_file, ".plt");
|
||||
pa->addReference(R_X86_64_PC32, 2, ga, -4);
|
||||
pa->addReference(LLD_R_X86_64_GOTRELINDEX, 7, ga, 0);
|
||||
pa->addReference(R_X86_64_PC32, 12, getPLT0(), -4);
|
||||
// Set the starting address of the got entry to the second instruction in
|
||||
// the plt entry.
|
||||
ga->addReference(R_X86_64_64, 0, pa, 6);
|
||||
#ifndef NDEBUG
|
||||
ga->_name = "__got_";
|
||||
ga->_name += a->name();
|
||||
|
@ -322,10 +398,16 @@ public:
|
|||
// Handle IFUNC.
|
||||
if (const DefinedAtom *da = dyn_cast_or_null<const DefinedAtom>(ref.target()))
|
||||
if (da->contentType() == DefinedAtom::typeResolver)
|
||||
return handleIFUNC(ref, da);
|
||||
return handleIFUNC(ref);
|
||||
const_cast<Reference &>(ref).setTarget(getPLTEntry(ref.target()));
|
||||
return error_code::success();
|
||||
}
|
||||
|
||||
ErrorOr<void> handlePC32(const Reference &ref) {
|
||||
if (ref.target() && isa<SharedLibraryAtom>(ref.target()))
|
||||
return handlePLT32(ref);
|
||||
return handleIFUNC(ref);
|
||||
}
|
||||
};
|
||||
} // end anon namespace
|
||||
|
||||
|
@ -335,6 +417,7 @@ void elf::X86_64TargetInfo::addPasses(PassManager &pm) const {
|
|||
else if (_options._outputKind == OutputKind::DynamicExecutable ||
|
||||
_options._outputKind == OutputKind::Shared)
|
||||
pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
|
||||
ELFTargetInfo::addPasses(pm);
|
||||
}
|
||||
|
||||
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
|
||||
|
@ -380,6 +463,7 @@ ErrorOr<int32_t> elf::X86_64TargetInfo::relocKindFromString(
|
|||
LLD_CASE(R_X86_64_TLSDESC_CALL)
|
||||
LLD_CASE(R_X86_64_TLSDESC)
|
||||
LLD_CASE(R_X86_64_IRELATIVE)
|
||||
.Case("LLD_R_X86_64_GOTRELINDEX", LLD_R_X86_64_GOTRELINDEX)
|
||||
.Default(-1);
|
||||
|
||||
if (ret == -1)
|
||||
|
@ -432,6 +516,8 @@ ErrorOr<std::string> elf::X86_64TargetInfo::stringFromRelocKind(
|
|||
LLD_CASE(R_X86_64_TLSDESC_CALL)
|
||||
LLD_CASE(R_X86_64_TLSDESC)
|
||||
LLD_CASE(R_X86_64_IRELATIVE)
|
||||
case LLD_R_X86_64_GOTRELINDEX:
|
||||
return std::string("LLD_R_X86_64_GOTRELINDEX");
|
||||
}
|
||||
|
||||
return make_error_code(yaml_reader_error::illegal_value);
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
|
||||
namespace lld {
|
||||
namespace elf {
|
||||
/// \brief x86-64 internal references.
|
||||
enum {
|
||||
/// \brief The 32 bit index of the relocation in the got this reference refers
|
||||
/// to.
|
||||
LLD_R_X86_64_GOTRELINDEX = 1024,
|
||||
};
|
||||
|
||||
class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo {
|
||||
public:
|
||||
|
@ -38,9 +44,26 @@ public:
|
|||
return _options._baseAddress;
|
||||
}
|
||||
|
||||
virtual bool isRuntimeRelocation(const DefinedAtom &,
|
||||
virtual bool isDynamicRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
return r.kind() == llvm::ELF::R_X86_64_IRELATIVE;
|
||||
switch (r.kind()){
|
||||
case llvm::ELF::R_X86_64_RELATIVE:
|
||||
case llvm::ELF::R_X86_64_GLOB_DAT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool isPLTRelocation(const DefinedAtom &,
|
||||
const Reference &r) const {
|
||||
switch (r.kind()){
|
||||
case llvm::ELF::R_X86_64_JUMP_SLOT:
|
||||
case llvm::ELF::R_X86_64_IRELATIVE:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const;
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: llvm-readobj %t | FileCheck %s
|
||||
|
||||
CHECK: Sections:
|
||||
CHECK: .hash {{[0-9a-f]+}} 8 4 required,rodata
|
|
@ -1,8 +0,0 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: llvm-objdump -p %t | FileCheck %s
|
||||
|
||||
CHECK: INTERP
|
||||
CHECK: flags r--
|
||||
CHECK: off
|
|
@ -1,18 +0,0 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=- -noinhibit-exec \
|
||||
RUN: -output-type=dynamic \
|
||||
RUN: | FileCheck %s
|
||||
|
||||
CHECK: name: main
|
||||
CHECK: kind: R_X86_64_PC32
|
||||
CHECK: target: [[PLTNAME:[-a-zA-Z0-9_]+]]
|
||||
|
||||
CHECK: type: got
|
||||
CHECK: R_X86_64_RELATIVE
|
||||
|
||||
CHECK: name: [[PLTNAME]]
|
||||
CHECK: type: stub
|
||||
|
||||
CHECK: shared-library-atoms:
|
||||
CHECK: name: foo
|
||||
CHECK: load-name: shared.so-x86-64
|
|
@ -1,7 +0,0 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: llvm-objdump -p %t | FileCheck %s
|
||||
|
||||
CHECK: PHDR off 0x{{0+}}40
|
||||
CHECK: flags r--
|
|
@ -1,8 +0,0 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: llvm-readobj %t | FileCheck %s
|
||||
|
||||
CHECK: Dynamic Symbols:
|
||||
CHECK: foo FUNC {{[0-9a-f]+}} 0 {{[0-9a-f]+}} undef,global
|
||||
CHECK: Total: 1
|
|
@ -1,15 +0,0 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: llvm-readobj %t | FileCheck %s
|
||||
|
||||
CHECK: Dynamic section contains 7 entries
|
||||
CHECK: Tag Type Name/Value
|
||||
CHECK: 0x0000000000000004 (HASH)
|
||||
CHECK: 0x0000000000000005 (STRTAB)
|
||||
CHECK: 0x0000000000000006 (SYMTAB)
|
||||
CHECK: 0x000000000000000a (STRSZ)
|
||||
CHECK: 0x000000000000000b (SYMENT) 24
|
||||
CHECK: 0x0000000000000001 (NEEDED) Shared library: [shared.so-x86-64]
|
||||
CHECK: 0x0000000000000000 (NULL) 0x0
|
||||
CHECK: Total: 7
|
|
@ -0,0 +1,49 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -output=%t -entry=main \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=%t2 -noinhibit-exec \
|
||||
RUN: -output-type=dynamic
|
||||
RUN: llvm-objdump -p %t >> %t2
|
||||
RUN: llvm-readobj %t >> %t2
|
||||
RUN: FileCheck %s < %t2
|
||||
|
||||
CHECK: type: got
|
||||
CHECK: R_X86_64_JUMP_SLOT
|
||||
|
||||
CHECK: name: main
|
||||
CHECK: kind: R_X86_64_PC32
|
||||
CHECK: target: [[PLTNAME:[-a-zA-Z0-9_]+]]
|
||||
|
||||
CHECK: name: [[PLTNAME]]
|
||||
CHECK: type: stub
|
||||
|
||||
CHECK: shared-library-atoms:
|
||||
CHECK: name: foo
|
||||
CHECK: load-name: shared.so-x86-64
|
||||
|
||||
CHECK: PHDR off 0x{{0+}}40
|
||||
CHECK: INTERP
|
||||
CHECK: flags r--
|
||||
|
||||
CHECK: Dynamic Symbols:
|
||||
CHECK: foo FUNC {{[0-9a-f]+}} 0 {{[0-9a-f]+}} undef,global
|
||||
CHECK: Total: 1
|
||||
|
||||
CHECK: Sections:
|
||||
CHECK: .hash {{[0-9a-f]+}} 8 4 required,rodata
|
||||
|
||||
CHECK: Dynamic section contains 11 entries
|
||||
CHECK: Tag Type Name/Value
|
||||
CHECK: 0x0000000000000004 (HASH)
|
||||
CHECK: 0x0000000000000005 (STRTAB)
|
||||
CHECK: 0x0000000000000006 (SYMTAB)
|
||||
CHECK: 0x000000000000000a (STRSZ)
|
||||
CHECK: 0x000000000000000b (SYMENT) 24
|
||||
CHECK: 0x0000000000000002 (PLTRELSZ) 24
|
||||
CHECK: 0x0000000000000003 (PLTGOT)
|
||||
CHECK: 0x0000000000000014 (PLTREL) RELA
|
||||
CHECK: 0x0000000000000017 (JMPREL)
|
||||
CHECK: 0x0000000000000001 (NEEDED) Shared library: [shared.so-x86-64]
|
||||
CHECK: 0x0000000000000000 (NULL) 0x0
|
||||
CHECK: Total: 11
|
|
@ -2,16 +2,16 @@ RUN: lld -core -target x86_64-linux -output=- -entry=main -output-type=static \
|
|||
RUN: %p/Inputs/gotpcrel.x86-64 -emit-yaml -noinhibit-exec \
|
||||
RUN: | FileCheck %s -check-prefix=YAML
|
||||
|
||||
YAML: name: main
|
||||
YAML: kind: R_X86_64_PC32
|
||||
YAML: target: [[NULLGOT:[a-zA-Z0-9_]+]]
|
||||
YAML: kind: R_X86_64_PC32
|
||||
YAML: target: [[MAINGOT:[a-zA-Z0-9_]+]]
|
||||
|
||||
YAML: name: [[NULLGOT]]
|
||||
YAML: name: [[NULLGOT:[a-zA-Z0-9_]+]]
|
||||
YAML: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||
YAML-NOT: references:
|
||||
|
||||
YAML: name: [[MAINGOT]]
|
||||
YAML: name: [[MAINGOT:[a-zA-Z0-9_]+]]
|
||||
YAML: kind: R_X86_64_64
|
||||
YAML: target: main
|
||||
|
||||
YAML: name: main
|
||||
YAML: kind: R_X86_64_PC32
|
||||
YAML: target: [[NULLGOT]]
|
||||
YAML: kind: R_X86_64_PC32
|
||||
YAML: target: [[MAINGOT]]
|
||||
|
|
|
@ -9,9 +9,10 @@ RUN: lld -core -target x86_64-linux -output=%t %p/Inputs/ifunc.x86-64 \
|
|||
RUN: -entry=main -output-type=static %p/Inputs/ifunc.cpp.x86-64 \
|
||||
RUN: && llvm-objdump -d -s %t| FileCheck %s --check-prefix=BIN
|
||||
|
||||
CHECK: name: hey
|
||||
CHECK: scope: global
|
||||
CHECK: type: resolver
|
||||
// Make sure there's a got entry with a IRELATIVE relocation.
|
||||
PLT: type: got
|
||||
PLT: kind: R_X86_64_IRELATIVE
|
||||
PLT: target: hey
|
||||
|
||||
PLT: name: plt
|
||||
PLT: scope: global
|
||||
|
@ -24,9 +25,9 @@ PLT: references
|
|||
PLT: kind: R_X86_64_PC32
|
||||
PLT: target: [[PLTNAME]]
|
||||
|
||||
// Make sure there's a got entry with a IRELATIVE relocation.
|
||||
PLT: type: got
|
||||
PLT: kind: R_X86_64_IRELATIVE
|
||||
CHECK: name: hey
|
||||
CHECK: scope: global
|
||||
CHECK: type: resolver
|
||||
|
||||
// Make sure the target of main's relocation is a stub with a PC32 relocation.
|
||||
// This relocation is to the got atom, but you can't really write that check in
|
||||
|
@ -36,8 +37,6 @@ PLT: type: stub
|
|||
PLT: references
|
||||
PLT: kind: R_X86_64_PC32
|
||||
|
||||
// This is a horribly brittle test. We need a way to do arithmetic on captured
|
||||
// variables.
|
||||
BIN: 4000ec: ff 25 0e 0f 00 00 jmpq *3854(%rip)
|
||||
BIN: {{[0-9a-f]+}}: ff 25 {{[0-9a-f]+}} {{[0-9a-f]+}} 00 00 jmpq *{{[0-9]+}}(%rip)
|
||||
BIN: .got.plt:
|
||||
BIN-NEXT: 401000 00000000 00000000
|
||||
BIN-NEXT: {{[0-9a-f]+}} 00000000 00000000
|
||||
|
|
|
@ -8,6 +8,10 @@ RUN: | FileCheck %s
|
|||
|
||||
// Verify that the TLS accesses have the correct offsets.
|
||||
|
||||
YAML: type: got
|
||||
YAML: kind: R_X86_64_TPOFF64
|
||||
YAML: target: tls2
|
||||
|
||||
YAML: name: main
|
||||
YAML: kind: R_X86_64_TPOFF32
|
||||
YAML: offset: 9
|
||||
|
@ -23,11 +27,6 @@ YAML: name: GOTTPOFF
|
|||
YAML: kind: R_X86_64_PC32
|
||||
YAML: target: [[GOTNAME:[a-zA-Z0-9_]+]]
|
||||
|
||||
YAML: name: [[GOTNAME]]
|
||||
YAML: type: got
|
||||
YAML: kind: R_X86_64_TPOFF64
|
||||
YAML: target: tls2
|
||||
|
||||
// main
|
||||
CHECK: addl %fs:-4
|
||||
CHECK: addl %fs:-8
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
RUN: lld -core -target x86_64-linux %p/Inputs/use-shared.x86-64 \
|
||||
RUN: %p/Inputs/shared.so-x86-64 -emit-yaml -output=- -noinhibit-exec \
|
||||
RUN: -output-type=dynamic | FileCheck %s
|
||||
|
||||
// Don't check the GOT and PLT names as they are only present in assert builds.
|
||||
|
||||
- name: __got_null
|
||||
CHECK: type: got
|
||||
CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||
CHECK: alignment: 2^3
|
||||
CHECK: section-choice: custom-required
|
||||
CHECK: section-name: .got.plt
|
||||
CHECK: permissions: rw-
|
||||
- name: __got0
|
||||
CHECK: type: got
|
||||
CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||
CHECK: alignment: 2^3
|
||||
CHECK: section-choice: custom-required
|
||||
CHECK: section-name: .got.plt
|
||||
CHECK: permissions: rw-
|
||||
- name: __got1
|
||||
CHECK: type: got
|
||||
CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||
CHECK: alignment: 2^3
|
||||
CHECK: section-choice: custom-required
|
||||
CHECK: section-name: .got.plt
|
||||
CHECK: permissions: rw-
|
||||
- name: __got_foo
|
||||
CHECK: type: got
|
||||
CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
|
||||
CHECK: alignment: 2^3
|
||||
CHECK: section-choice: custom-required
|
||||
CHECK: section-name: .got.plt
|
||||
CHECK: permissions: rw-
|
||||
CHECK: references:
|
||||
CHECK: - kind: R_X86_64_JUMP_SLOT
|
||||
CHECK: offset: 0
|
||||
CHECK: target: foo
|
||||
CHECK: - kind: R_X86_64_64
|
||||
CHECK: offset: 0
|
||||
target: __plt_foo
|
||||
CHECK: addend: 6
|
||||
|
||||
CHECK: - name: main
|
||||
CHECK: scope: global
|
||||
CHECK: references:
|
||||
CHECK: - kind: R_X86_64_PC32
|
||||
CHECK: offset: 7
|
||||
target: __plt_foo
|
||||
CHECK: addend: -4
|
||||
|
||||
- name: .PLT0
|
||||
CHECK: type: stub
|
||||
CHECK: content: [ FF, 35, 00, 00, 00, 00, FF, 25, 00, 00, 00, 00,
|
||||
CHECK: 90, 90, 90, 90 ]
|
||||
CHECK: alignment: 2^4
|
||||
CHECK: section-choice: custom-required
|
||||
CHECK: section-name: .plt
|
||||
CHECK: references:
|
||||
CHECK: - kind: R_X86_64_PC32
|
||||
CHECK: offset: 2
|
||||
target: __got0
|
||||
CHECK: addend: -4
|
||||
CHECK: - kind: R_X86_64_PC32
|
||||
CHECK: offset: 8
|
||||
target: __got1
|
||||
CHECK: addend: -4
|
||||
- name: __plt_foo
|
||||
CHECK: type: stub
|
||||
CHECK: content: [ FF, 25, 00, 00, 00, 00, 68, 00, 00, 00, 00, E9,
|
||||
CHECK: 00, 00, 00, 00 ]
|
||||
CHECK: alignment: 2^4
|
||||
CHECK: section-choice: custom-required
|
||||
CHECK: section-name: .plt
|
||||
CHECK: references:
|
||||
CHECK: - kind: R_X86_64_PC32
|
||||
CHECK: offset: 2
|
||||
target: __got_foo
|
||||
CHECK: addend: -4
|
||||
CHECK: - kind: LLD_R_X86_64_GOTRELINDEX
|
||||
CHECK: offset: 7
|
||||
target: __got_foo
|
||||
CHECK: - kind: R_X86_64_PC32
|
||||
CHECK: offset: 12
|
||||
target: .PLT0
|
||||
CHECK: addend: -4
|
||||
|
||||
CHECK:shared-library-atoms:
|
||||
CHECK: - name: foo
|
||||
CHECK: load-name: shared.so-x86-64
|
Loading…
Reference in New Issue