aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r--llvm/lib/MC/MCAssembler.cpp25
1 files changed, 25 insertions, 0 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index d4d10e0..f1a82f6 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -398,6 +398,10 @@ bool MCAssembler::registerSymbol(const MCSymbol &Symbol) {
return Changed;
}
+void MCAssembler::addRelocDirective(RelocDirective RD) {
+ relocDirectives.push_back(RD);
+}
+
/// Write the fragment \p F to the output file.
static void writeFragment(raw_ostream &OS, const MCAssembler &Asm,
const MCFragment &F) {
@@ -695,6 +699,27 @@ void MCAssembler::layout() {
// helps check whether a PC-relative fixup is fully resolved.
this->HasFinalLayout = true;
+ // Resolve .reloc offsets and add fixups.
+ for (auto &PF : relocDirectives) {
+ MCValue Res;
+ auto &O = PF.Offset;
+ if (!O.evaluateAsValue(Res, *this)) {
+ getContext().reportError(O.getLoc(), ".reloc offset is not relocatable");
+ continue;
+ }
+ auto *Sym = Res.getAddSym();
+ auto *F = Sym ? Sym->getFragment() : nullptr;
+ auto *Sec = F ? F->getParent() : nullptr;
+ if (Res.getSubSym() || !Sec) {
+ getContext().reportError(O.getLoc(),
+ ".reloc offset is not relative to a section");
+ continue;
+ }
+
+ uint64_t Offset = Sym ? Sym->getOffset() + Res.getConstant() : 0;
+ F->addFixup(MCFixup::create(Offset, PF.Expr, PF.Kind));
+ }
+
// Evaluate and apply the fixups, generating relocation entries as necessary.
for (MCSection &Sec : *this) {
for (MCFragment &F : Sec) {