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.cpp43
1 files changed, 36 insertions, 7 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index d4d10e0..3e96bdf 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) {
@@ -710,13 +735,17 @@ void MCAssembler::layout() {
// In the variable part, fixup offsets are relative to the fixed part's
// start. Extend the variable contents to the left to account for the
// fixed part size.
- Contents = MutableArrayRef(F.getParent()->ContentStorage)
- .slice(F.VarContentStart - Contents.size(), F.getSize());
- for (MCFixup &Fixup : F.getVarFixups()) {
- uint64_t FixedValue;
- MCValue Target;
- evaluateFixup(F, Fixup, Target, FixedValue,
- /*RecordReloc=*/true, Contents);
+ auto VarFixups = F.getVarFixups();
+ if (VarFixups.size()) {
+ Contents =
+ MutableArrayRef(F.getParent()->ContentStorage)
+ .slice(F.VarContentStart - Contents.size(), F.getSize());
+ for (MCFixup &Fixup : VarFixups) {
+ uint64_t FixedValue;
+ MCValue Target;
+ evaluateFixup(F, Fixup, Target, FixedValue,
+ /*RecordReloc=*/true, Contents);
+ }
}
} else if (auto *AF = dyn_cast<MCAlignFragment>(&F)) {
// For RISC-V linker relaxation, an alignment relocation might be