}
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(
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:
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;
}
}
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;
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);
void addDefaultAtoms() {
_hexagonRuntimeFile.addAbsoluteAtom("_SDA_BASE_");
+ if (_targetInfo.isDynamic())
+ _hexagonRuntimeFile.addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
}
virtual void addFiles(InputFiles &inputFiles) {
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