blob: f4722a7e96368e2026b9f5fe5a166d962b819b5e [file]
//===- bolt/Core/Relocation.cpp - Object file relocations -----------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements the Relocation class.
//
//===----------------------------------------------------------------------===//
#include "bolt/Core/Relocation.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
using namespace llvm;
using namespace bolt;
MCBinaryExpr::Opcode
RelocationHandler::getComposeOpcodeFor(uint32_t Type) const {
llvm_unreachable("composed relocations are unsupported for this target");
}
uint32_t Relocation::getType(const object::RelocationRef &Rel) {
uint64_t RelType = Rel.getType();
assert(isUInt<32>(RelType) && "BOLT relocation types are 32 bits");
return static_cast<uint32_t>(RelType);
}
size_t Relocation::emit(MCStreamer *Streamer,
const RelocationHandler &RH) const {
const size_t Size = RH.getSizeForType(Type);
const auto *Value = createExpr(Streamer, RH);
Streamer->emitValue(Value, Size);
return Size;
}
const MCExpr *Relocation::createExpr(MCStreamer *Streamer,
const RelocationHandler &RH) const {
MCContext &Ctx = Streamer->getContext();
const MCExpr *Value = nullptr;
if (Symbol && Addend) {
Value = MCBinaryExpr::createAdd(MCSymbolRefExpr::create(Symbol, Ctx),
MCConstantExpr::create(Addend, Ctx), Ctx);
} else if (Symbol) {
Value = MCSymbolRefExpr::create(Symbol, Ctx);
} else {
Value = MCConstantExpr::create(Addend, Ctx);
}
if (RH.isPCRelative(Type)) {
MCSymbol *TempLabel = Ctx.createNamedTempSymbol();
Streamer->emitLabel(TempLabel);
Value = MCBinaryExpr::createSub(
Value, MCSymbolRefExpr::create(TempLabel, Ctx), Ctx);
}
return Value;
}
const MCExpr *Relocation::createExpr(MCStreamer *Streamer,
const MCExpr *RetainedValue,
const RelocationHandler &RH) const {
const auto *Value = createExpr(Streamer, RH);
if (RetainedValue) {
Value = MCBinaryExpr::create(RH.getComposeOpcodeFor(Type), RetainedValue,
Value, Streamer->getContext());
}
return Value;
}
void Relocation::print(raw_ostream &OS, const RelocationHandler &RH) const {
RH.printType(OS, Type);
OS << ", 0x" << Twine::utohexstr(Offset);
if (Symbol) {
OS << ", " << Symbol->getName();
}
if (int64_t(Addend) < 0)
OS << ", -0x" << Twine::utohexstr(-int64_t(Addend));
else
OS << ", 0x" << Twine::utohexstr(Addend);
OS << ", 0x" << Twine::utohexstr(Value);
}