bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const { ++stats::EvaluateFixup; if (!Fixup.getValue()->EvaluateAsRelocatable(Target, &Layout)) report_fatal_error("expected relocatable expression"); // FIXME: How do non-scattered symbols work in ELF? I presume the linker // doesn't support small relocations, but then under what criteria does the // assembler allow symbol differences? Value = Target.getConstant(); bool IsPCRel = Emitter.getFixupKindInfo( Fixup.getKind()).Flags & MCFixupKindInfo::FKF_IsPCRel; bool IsResolved = true; if (const MCSymbolRefExpr *A = Target.getSymA()) { if (A->getSymbol().isDefined()) Value += Layout.getSymbolAddress(&getSymbolData(A->getSymbol())); else IsResolved = false; } if (const MCSymbolRefExpr *B = Target.getSymB()) { if (B->getSymbol().isDefined()) Value -= Layout.getSymbolAddress(&getSymbolData(B->getSymbol())); else IsResolved = false; } // If we are using scattered symbols, determine whether this value is actually // resolved; scattering may cause atoms to move. if (IsResolved && getBackend().hasScatteredSymbols()) { if (getBackend().hasReliableSymbolDifference()) { // If this is a PCrel relocation, find the base atom (identified by its // symbol) that the fixup value is relative to. const MCSymbolData *BaseSymbol = 0; if (IsPCRel) { BaseSymbol = DF->getAtom(); if (!BaseSymbol) IsResolved = false; } if (IsResolved) IsResolved = isScatteredFixupFullyResolved(*this, Layout, Fixup, Target, BaseSymbol); } else { const MCSection *BaseSection = 0; if (IsPCRel) BaseSection = &DF->getParent()->getSection(); IsResolved = isScatteredFixupFullyResolvedSimple(*this, Fixup, Target, BaseSection); } } if (IsPCRel) Value -= Layout.getFragmentAddress(DF) + Fixup.getOffset(); return IsResolved; }