ErrorOr<void> X86TargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, const Reference &ref) const { uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; uint8_t *location = atomContent + ref.offsetInAtom(); uint64_t targetVAddress = writer.addressOfAtom(ref.target()); uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom(); switch (ref.kind()) { case R_386_32: reloc32(location, relocVAddress, targetVAddress, ref.addend()); break; case R_386_PC32: relocPC32(location, relocVAddress, targetVAddress, ref.addend()); break; case lld::Reference::kindLayoutAfter: case lld::Reference::kindLayoutBefore: case lld::Reference::kindInGroup: break; default : { std::string str; llvm::raw_string_ostream s(str); auto name = _targetInfo.stringFromRelocKind(ref.kind()); s << "Unhandled relocation: " << (name ? *name : "<unknown>" ) << " (" << ref.kind() << ")"; s.flush(); llvm_unreachable(str.c_str()); } } return error_code::success(); }
std::error_code X86TargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, const Reference &ref) const { uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; uint8_t *loc = atomContent + ref.offsetInAtom(); uint64_t target = writer.addressOfAtom(ref.target()); uint64_t reloc = atom._virtualAddr + ref.offsetInAtom(); if (ref.kindNamespace() != Reference::KindNamespace::ELF) return std::error_code(); assert(ref.kindArch() == Reference::KindArch::x86); switch (ref.kindValue()) { case R_386_32: reloc32(loc, reloc, target, ref.addend()); break; case R_386_PC32: relocPC32(loc, reloc, target, ref.addend()); break; default: return make_unhandled_reloc_error(); } return std::error_code(); }
std::error_code X86_64TargetRelocationHandler::applyRelocation( ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, const Reference &ref) const { uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; uint8_t *loc = atomContent + ref.offsetInAtom(); uint64_t target = writer.addressOfAtom(ref.target()); uint64_t reloc = atom._virtualAddr + ref.offsetInAtom(); if (ref.kindNamespace() != Reference::KindNamespace::ELF) return std::error_code(); assert(ref.kindArch() == Reference::KindArch::x86_64); switch (ref.kindValue()) { case R_X86_64_NONE: break; case R_X86_64_64: reloc64(loc, reloc, target, ref.addend()); break; case R_X86_64_PC32: case R_X86_64_GOTPCREL: relocPC32(loc, reloc, target, ref.addend()); break; case R_X86_64_32: reloc32(loc, reloc, target, ref.addend()); break; case R_X86_64_32S: reloc32S(loc, reloc, target, ref.addend()); break; case R_X86_64_16: reloc16(loc, reloc, target, ref.addend()); break; case R_X86_64_PC16: relocPC16(loc, reloc, target, ref.addend()); break; case R_X86_64_TPOFF64: case R_X86_64_DTPOFF32: case R_X86_64_TPOFF32: { _tlsSize = _layout.getTLSSize(); if (ref.kindValue() == R_X86_64_TPOFF32 || ref.kindValue() == R_X86_64_DTPOFF32) { write32le(loc, target - _tlsSize); } else { write64le(loc, target - _tlsSize); } break; } case R_X86_64_TLSGD: { relocPC32(loc, reloc, target, ref.addend()); break; } 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, 0x00, 0x00, 0x00, 0x00 }; std::memcpy(loc - 3, instr, sizeof(instr)); break; } case R_X86_64_PC64: relocPC64(loc, reloc, target, ref.addend()); break; case LLD_R_X86_64_GOTRELINDEX: { const DefinedAtom *target = cast<const DefinedAtom>(ref.target()); for (const Reference *r : *target) { if (r->kindValue() == R_X86_64_JUMP_SLOT) { uint32_t index; if (!_layout.getPLTRelocationTable()->getRelocationIndex(*r, index)) llvm_unreachable("Relocation doesn't exist"); reloc32(loc, 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: case R_X86_64_DTPMOD64: case R_X86_64_DTPOFF64: break; default: return make_unhandled_reloc_error(); } return std::error_code(); }