Index: lib/ReaderWriter/ELF/X86_64/TODO.rst =================================================================== --- lib/ReaderWriter/ELF/X86_64/TODO.rst +++ lib/ReaderWriter/ELF/X86_64/TODO.rst @@ -19,11 +19,6 @@ These are very simple relocation calculations to implement. See lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp -* R_X86_64_16 -* R_X86_64_PC16 -* R_X86_64_8 -* R_X86_64_PC8 -* R_X86_64_PC64 * R_X86_64_SIZE32 * R_X86_64_SIZE64 * R_X86_64_GOTPC32 (this relocation requires there to be a __GLOBAL_OFFSET_TABLE__) Index: lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp =================================================================== --- lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp +++ lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp @@ -47,6 +47,47 @@ // TODO: Make sure that the result sign extends to the 64bit value. } +/// \brief R_X86_64_16 - word16: S + A +static void reloc16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { + int16_t result = (uint16_t)(S + A); + *reinterpret_cast(location) = + result | + (uint16_t) * reinterpret_cast(location); +} + +/// \brief R_X86_64_PC16 - word16: S + A - P +static void relocPC16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { + int16_t result = (int16_t)((S + A) - P); + *reinterpret_cast(location) = + result | + (uint16_t) * reinterpret_cast(location); +} + +/// \brief R_X86_64_8 - word8: S + A +static void reloc8(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int8_t result = (int8_t)(S + A); + // XXX: reinterpret_cast needed? + *reinterpret_cast(location) = + result | + (uint8_t) * reinterpret_cast(location); +} + +/// \brief R_X86_64_PC8 - word8: S + A - P +static void relocPC8(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int8_t result = (int8_t)((S + A) - P); + // XXX: reinterpret_cast needed? + *reinterpret_cast(location) = + result | (uint8_t) * reinterpret_cast(location); +} + +/// \brief R_X86_64_PC64 - word64: S + A - P +static void relocPC64(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { + int64_t result = (uint64_t)((S + A) - P); + *reinterpret_cast(location) = + result | + (uint64_t) * reinterpret_cast(location); +} + std::error_code X86_64TargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, const Reference &ref) const { @@ -74,6 +115,18 @@ case R_X86_64_32S: reloc32S(location, relocVAddress, targetVAddress, ref.addend()); break; + case R_X86_64_16: + reloc16(location, relocVAddress, targetVAddress, ref.addend()); + break; + case R_X86_64_PC16: + relocPC16(location, relocVAddress, targetVAddress, ref.addend()); + break; + case R_X86_64_8: + reloc8(location, relocVAddress, targetVAddress, ref.addend()); + break; + case R_X86_64_PC8: + relocPC8(location, relocVAddress, targetVAddress, ref.addend()); + break; case R_X86_64_TPOFF64: case R_X86_64_DTPOFF32: case R_X86_64_TPOFF32: { @@ -100,6 +153,9 @@ std::memcpy(location - 3, instr, sizeof(instr)); break; } + case R_X86_64_PC64: + relocPC64(location, relocVAddress, targetVAddress, ref.addend()); + break; case LLD_R_X86_64_GOTRELINDEX: { const DefinedAtom *target = cast(ref.target()); for (const Reference *r : *target) {