diff options
author | Shankar Easwaran <shankare@codeaurora.org> | 2013-03-20 05:10:02 +0000 |
---|---|---|
committer | Shankar Easwaran <shankare@codeaurora.org> | 2013-03-20 05:10:02 +0000 |
commit | 452ba132712d284186ef79142f4906390f2bf0ad (patch) | |
tree | 898e99c739c605f07679717b786768535183032a | |
parent | 06a4039572b6c0e2d1dec87a50fb2b8a42432967 (diff) | |
download | bcm5719-llvm-452ba132712d284186ef79142f4906390f2bf0ad.tar.gz bcm5719-llvm-452ba132712d284186ef79142f4906390f2bf0ad.zip |
[ELF][Hexagon] Add Hexagon dynamic relocations
llvm-svn: 177484
3 files changed, 152 insertions, 8 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp index d0cd2400f45..d63eb918493 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp @@ -131,6 +131,81 @@ int relocHexGPRELN(uint8_t *location, uint64_t P, uint64_t S, uint64_t A, } return 1; } + +/// \brief Word32_LO: 0x00c03fff : (G) : Truncate +int relocHexGOTLO16(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G); + result = lld::scatterBits<int32_t>(result, 0x00c03fff); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + +/// \brief Word32_LO: 0x00c03fff : (G) >> 16 : Truncate +int relocHexGOTHI16(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G >> 16); + result = lld::scatterBits<int32_t>(result, 0x00c03fff); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + +/// \brief Word32: 0xffffffff : (G) : Truncate +int relocHexGOT32(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + +/// \brief Word32_U16 : (G) : Truncate +int relocHexGOT16(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G); + uint32_t range = 1L << 16; + if (result <= range) { + result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; + } + return 1; +} + +int relocHexGOT32_6_X(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G >> 6); + result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + +int relocHexGOT16_X(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G); + uint32_t range = 1L << 6; + if (result <= range) { + result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; + } + return 1; +} + +int relocHexGOT11_X(uint8_t *location, uint64_t G) { + uint32_t result = (uint32_t)(G); + result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location)); + *reinterpret_cast<llvm::support::ulittle32_t *>(location) = + result | + (uint32_t) * reinterpret_cast<llvm::support::ulittle32_t *>(location); + return 0; +} + } // end anon namespace ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation( @@ -211,6 +286,28 @@ ErrorOr<void> HexagonTargetRelocationHandler::applyRelocation( relocHex6PCRELX(location, relocVAddress, targetVAddress, ref.addend()); break; case R_HEX_JMP_SLOT: + case R_HEX_GLOB_DAT: + break; + case R_HEX_GOT_LO16: + relocHexGOTLO16(location, targetVAddress); + break; + case R_HEX_GOT_HI16: + relocHexGOTHI16(location, targetVAddress); + break; + case R_HEX_GOT_32: + relocHexGOT32(location, targetVAddress); + break; + case R_HEX_GOT_16: + relocHexGOT16(location, targetVAddress); + break; + case R_HEX_GOT_32_6_X: + relocHexGOT32_6_X(location, targetVAddress); + break; + case R_HEX_GOT_16_X: + relocHexGOT16_X(location, targetVAddress); + break; + case R_HEX_GOT_11_X: + relocHexGOT11_X(location, targetVAddress); break; case lld::Reference::kindLayoutAfter: case lld::Reference::kindLayoutBefore: diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp index 7b6da1c4ee7..8e5aadc67df 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp @@ -40,6 +40,13 @@ template <class Derived> class GOTPLTPass : public Pass { case R_HEX_PLT_B22_PCREL: static_cast<Derived *>(this)->handlePLT32(ref); break; + case R_HEX_GOT_LO16: + case R_HEX_GOT_HI16: + case R_HEX_GOT_32_6_X: + case R_HEX_GOT_16_X: + case R_HEX_GOT_11_X: + static_cast<Derived *>(this)->handleGOTREL(ref); + break; } } @@ -124,20 +131,21 @@ protected: class DynamicGOTPLTPass LLVM_FINAL : public GOTPLTPass<DynamicGOTPLTPass> { public: - DynamicGOTPLTPass(const elf::HexagonTargetInfo &ti) : GOTPLTPass(ti) {} + DynamicGOTPLTPass(const elf::HexagonTargetInfo &ti) : GOTPLTPass(ti) { + // Fill in the null entry. + getNullGOT(); + _got0 = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt"); +#ifndef NDEBUG + _got0->_name = "__got0"; +#endif + } const PLT0Atom *getPLT0() { if (_PLT0) return _PLT0; - // Fill in the null entry. - getNullGOT(); _PLT0 = new (_file._alloc) HexagonPLT0Atom(_file); - _got0 = new (_file._alloc) HexagonGOTAtom(_file, ".got.plt"); _PLT0->addReference(R_HEX_B32_PCREL_X, 0, _got0, 0); _PLT0->addReference(R_HEX_6_PCREL_X, 4, _got0, 0); -#ifndef NDEBUG - _got0->_name = "__got0"; -#endif DEBUG_WITH_TYPE("PLT", llvm::dbgs() << "[ PLT0/GOT0 ] " << "Adding plt0/got0 \n"); return _PLT0; @@ -171,6 +179,30 @@ public: return pa; } + const GOTAtom *getGOTEntry(const Atom *a) { + auto got = _gotMap.find(a); + if (got != _gotMap.end()) + return got->second; + auto ga = new (_file._alloc) HexagonGOTAtom(_file, ".got"); + ga->addReference(R_HEX_GLOB_DAT, 0, a, 0); + +#ifndef NDEBUG + ga->_name = "__got_"; + ga->_name += a->name(); + DEBUG_WITH_TYPE("GOT", llvm::dbgs() << "[" << a->name() << "] " + << "Adding got: " << ga->_name << "\n"); +#endif + _gotMap[a] = ga; + _gotVector.push_back(ga); + return ga; + } + + ErrorOr<void> handleGOTREL(const Reference &ref) { + // Turn this so that the target is set to the GOT entry + const_cast<Reference &>(ref).setTarget(getGOTEntry(ref.target())); + return error_code::success(); + } + ErrorOr<void> handlePLT32(const Reference &ref) { // Turn this into a PC32 to the PLT entry. const_cast<Reference &>(ref).setKind(R_HEX_B22_PCREL); diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h index 682311f9ddf..fc2753e1cb5 100644 --- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h +++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h @@ -170,6 +170,8 @@ public: void addDefaultAtoms() { _hexagonRuntimeFile.addAbsoluteAtom("_SDA_BASE_"); + if (_targetInfo.isDynamic()) + _hexagonRuntimeFile.addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); } virtual void addFiles(InputFiles &inputFiles) { @@ -180,14 +182,27 @@ public: void finalizeSymbolValues() { auto sdabaseAtomIter = _targetLayout.findAbsoluteAtom("_SDA_BASE_"); (*sdabaseAtomIter)->_virtualAddr = - _targetLayout.getSDataSection()->virtualAddr(); + _targetLayout.getSDataSection()->virtualAddr(); + if (_targetInfo.isDynamic()) { + auto gotAtomIter = + _targetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"); + _gotSymAtom = (*gotAtomIter); + auto gotpltSection = _targetLayout.findOutputSection(".got.plt"); + if (gotpltSection) + _gotSymAtom->_virtualAddr = gotpltSection->virtualAddr(); + else + _gotSymAtom->_virtualAddr = 0; + } } + uint64_t getGOTSymAddr() { return _gotSymAtom->_virtualAddr; } + private: HexagonTargetLayout<HexagonELFType> _targetLayout; HexagonTargetRelocationHandler _relocationHandler; HexagonTargetAtomHandler<HexagonELFType> _targetAtomHandler; HexagonRuntimeFile<HexagonELFType> _hexagonRuntimeFile; + AtomLayout *_gotSymAtom; }; } // end namespace elf } // end namespace lld |