aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-03-19 03:18:18 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-03-19 03:18:18 +0000
commit034843ac8bca36d14ef9d83b50596354b5f3420f (patch)
tree2f3ffe9cabd48fd001e3079190c28273583f211a /lib
parent8ad0dccbf2f0c5ecf9fdad93ac0207f6eaabaa1b (diff)
downloadexternal_llvm-034843ac8bca36d14ef9d83b50596354b5f3420f.zip
external_llvm-034843ac8bca36d14ef9d83b50596354b5f3420f.tar.gz
external_llvm-034843ac8bca36d14ef9d83b50596354b5f3420f.tar.bz2
MC/Mach-O: Add isScatteredFixupFullyResolved, which implements the correct algorithm (used on x86_64) for determining whether an evaluated fixup is fully resolved (doesn't need relocation).
- Test cases will follow, once we have x86_64 relocation support. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98926 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/MC/MCAssembler.cpp60
1 files changed, 59 insertions, 1 deletions
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 0d4f98c..e88e574 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -1048,6 +1048,52 @@ static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm,
return true;
}
+static bool isScatteredFixupFullyResolved(const MCAssembler &Asm,
+ const MCAsmFixup &Fixup,
+ const MCDataFragment *DF,
+ const MCValue Target,
+ const MCSymbolData *BaseSymbol) {
+ // The effective fixup address is
+ // addr(atom(A)) + offset(A)
+ // - addr(atom(B)) - offset(B)
+ // - addr(BaseSymbol) + <fixup offset from base symbol>
+ // and the offsets are not relocatable, so the fixup is fully resolved when
+ // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0.
+ //
+ // Note that "false" is almost always conservatively correct (it means we emit
+ // a relocation which is unnecessary), except when it would force us to emit a
+ // relocation which the target cannot encode.
+
+ const MCSymbolData *A_Base = 0, *B_Base = 0;
+ if (const MCSymbolRefExpr *A = Target.getSymA()) {
+ // Modified symbol references cannot be resolved.
+ if (A->getKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
+ if (!A_Base)
+ return false;
+ }
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ // Modified symbol references cannot be resolved.
+ if (B->getKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
+ if (!B_Base)
+ return false;
+ }
+
+ // If there is no base, A and B have to be the same atom for this fixup to be
+ // fully resolved.
+ if (!BaseSymbol)
+ return A_Base == B_Base;
+
+ // Otherwise, B must be missing and A must be the base.
+ return !B_Base && BaseSymbol == A_Base;
+}
+
bool MCAssembler::isSymbolLinkerVisible(const MCSymbolData *SD) const {
// Non-temporary labels should always be visible to the linker.
if (!SD->getSymbol().isTemporary())
@@ -1128,7 +1174,19 @@ bool MCAssembler::EvaluateFixup(const MCAsmLayout &Layout, MCAsmFixup &Fixup,
// resolved; scattering may cause atoms to move.
if (IsResolved && getBackend().hasScatteredSymbols()) {
if (getBackend().hasReliableSymbolDifference()) {
- llvm_report_error("FIXME: Not yet implemented");
+ // 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 = getAtomForAddress(
+ DF->getParent(), DF->getAddress() + Fixup.Offset);
+ if (!BaseSymbol)
+ IsResolved = false;
+ }
+
+ if (IsResolved)
+ IsResolved = isScatteredFixupFullyResolved(*this, Fixup, DF, Target,
+ BaseSymbol);
} else {
const MCSection *BaseSection = 0;
if (IsPCRel)