forked from OSchip/llvm-project
[ELF][Hexagon] Add Hexagon dynamic relocations
llvm-svn: 177484
This commit is contained in:
parent
06a4039572
commit
452ba13271
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue