diff options
author | Daniel Dunbar <daniel@zuster.org> | 2010-03-19 03:18:18 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2010-03-19 03:18:18 +0000 |
commit | 034843ac8bca36d14ef9d83b50596354b5f3420f (patch) | |
tree | 2f3ffe9cabd48fd001e3079190c28273583f211a /lib | |
parent | 8ad0dccbf2f0c5ecf9fdad93ac0207f6eaabaa1b (diff) | |
download | external_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.cpp | 60 |
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) |