mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-22 13:29:44 +00:00
It can fail trying to get the section on ELF and COFF. This makes sure the error is handled. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@241366 91177308-0d34-0410-b5e6-96231b3b80d8
142 lines
4.7 KiB
C++
142 lines
4.7 KiB
C++
//===-- X86ELFRelocationInfo.cpp ----------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MCTargetDesc/X86MCTargetDesc.h"
|
|
#include "llvm/MC/MCContext.h"
|
|
#include "llvm/MC/MCExpr.h"
|
|
#include "llvm/MC/MCInst.h"
|
|
#include "llvm/MC/MCRelocationInfo.h"
|
|
#include "llvm/MC/MCSymbol.h"
|
|
#include "llvm/Object/ELFObjectFile.h"
|
|
#include "llvm/Support/ELF.h"
|
|
|
|
using namespace llvm;
|
|
using namespace object;
|
|
using namespace ELF;
|
|
|
|
namespace {
|
|
class X86_64ELFRelocationInfo : public MCRelocationInfo {
|
|
public:
|
|
X86_64ELFRelocationInfo(MCContext &Ctx) : MCRelocationInfo(Ctx) {}
|
|
|
|
const MCExpr *createExprForRelocation(RelocationRef Rel) override {
|
|
uint64_t RelType = Rel.getType();
|
|
elf_symbol_iterator SymI = Rel.getSymbol();
|
|
|
|
ErrorOr<StringRef> SymNameOrErr = SymI->getName();
|
|
if (std::error_code EC = SymNameOrErr.getError())
|
|
report_fatal_error(EC.message());
|
|
StringRef SymName = *SymNameOrErr;
|
|
|
|
ErrorOr<uint64_t> SymAddr = SymI->getAddress();
|
|
if (std::error_code EC = SymAddr.getError())
|
|
report_fatal_error(EC.message());
|
|
uint64_t SymSize = SymI->getSize();
|
|
int64_t Addend = *ELFRelocationRef(Rel).getAddend();
|
|
|
|
MCSymbol *Sym = Ctx.getOrCreateSymbol(SymName);
|
|
// FIXME: check that the value is actually the same.
|
|
if (!Sym->isVariable())
|
|
Sym->setVariableValue(MCConstantExpr::create(*SymAddr, Ctx));
|
|
|
|
const MCExpr *Expr = nullptr;
|
|
// If hasAddend is true, then we need to add Addend (r_addend) to Expr.
|
|
bool hasAddend = false;
|
|
|
|
// The AMD64 SysV ABI says:
|
|
// A: the addend used to compute the value of the relocatable field.
|
|
// B: the base address at which a shared object has been loaded into memory
|
|
// during execution. Generally, a shared object is built with a 0 base
|
|
// virtual address, but the execution address will be different.
|
|
// G: the offset into the global offset table at which the relocation
|
|
// entry's symbol will reside during execution.
|
|
// GOT: the address of the global offset table.
|
|
// L: the place (section offset or address) of the Procedure Linkage Table
|
|
// entry for a symbol.
|
|
// P: the place (section offset or address) of the storage unit being
|
|
// relocated (computed using r_offset).
|
|
// S: the value of the symbol whose index resides in the relocation entry.
|
|
// Z: the size of the symbol whose index resides in the relocation entry.
|
|
|
|
switch(RelType) {
|
|
case R_X86_64_NONE:
|
|
case R_X86_64_COPY:
|
|
// none
|
|
break;
|
|
case R_X86_64_64:
|
|
case R_X86_64_16:
|
|
case R_X86_64_8:
|
|
// S + A
|
|
case R_X86_64_32:
|
|
case R_X86_64_32S:
|
|
// S + A (We don't care about the result not fitting in 32 bits.)
|
|
case R_X86_64_PC32:
|
|
case R_X86_64_PC16:
|
|
case R_X86_64_PC8:
|
|
case R_X86_64_PC64:
|
|
// S + A - P (P/pcrel is implicit)
|
|
hasAddend = true;
|
|
Expr = MCSymbolRefExpr::create(Sym, Ctx);
|
|
break;
|
|
case R_X86_64_GOT32:
|
|
case R_X86_64_GOT64:
|
|
case R_X86_64_GOTPC32:
|
|
case R_X86_64_GOTPC64:
|
|
case R_X86_64_GOTPLT64:
|
|
// G + A
|
|
hasAddend = true;
|
|
Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOT, Ctx);
|
|
break;
|
|
case R_X86_64_PLT32:
|
|
// L + A - P -> S@PLT + A
|
|
hasAddend = true;
|
|
Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_PLT, Ctx);
|
|
break;
|
|
case R_X86_64_GLOB_DAT:
|
|
case R_X86_64_JUMP_SLOT:
|
|
// S
|
|
Expr = MCSymbolRefExpr::create(Sym, Ctx);
|
|
break;
|
|
case R_X86_64_GOTPCREL:
|
|
case R_X86_64_GOTPCREL64:
|
|
// G + GOT + A - P -> S@GOTPCREL + A
|
|
hasAddend = true;
|
|
Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTPCREL, Ctx);
|
|
break;
|
|
case R_X86_64_GOTOFF64:
|
|
// S + A - GOT
|
|
Expr = MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_GOTOFF, Ctx);
|
|
break;
|
|
case R_X86_64_PLTOFF64:
|
|
// L + A - GOT
|
|
break;
|
|
case R_X86_64_SIZE32:
|
|
case R_X86_64_SIZE64:
|
|
// Z + A
|
|
Expr = MCConstantExpr::create(SymSize, Ctx);
|
|
break;
|
|
default:
|
|
Expr = MCSymbolRefExpr::create(Sym, Ctx);
|
|
break;
|
|
}
|
|
if (Expr && hasAddend && Addend != 0)
|
|
Expr = MCBinaryExpr::createAdd(Expr,
|
|
MCConstantExpr::create(Addend, Ctx),
|
|
Ctx);
|
|
return Expr;
|
|
}
|
|
};
|
|
} // End unnamed namespace
|
|
|
|
/// createX86ELFRelocationInfo - Construct an X86 Mach-O RelocationInfo.
|
|
MCRelocationInfo *llvm::createX86_64ELFRelocationInfo(MCContext &Ctx) {
|
|
// We only handle x86-64 for now.
|
|
return new X86_64ELFRelocationInfo(Ctx);
|
|
}
|