aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-12-22 16:45:29 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-12-22 16:45:29 +0000
commit25bcc9cdc8adcda093bfdf4cf2bda2aaadeb7ee8 (patch)
treee5699adda8064a726cb2ec382854289aef72b624
parent5cc639049574748b96c9806bb84680837917433e (diff)
downloadexternal_llvm-25bcc9cdc8adcda093bfdf4cf2bda2aaadeb7ee8.zip
external_llvm-25bcc9cdc8adcda093bfdf4cf2bda2aaadeb7ee8.tar.gz
external_llvm-25bcc9cdc8adcda093bfdf4cf2bda2aaadeb7ee8.tar.bz2
MC/Mach-O/ARM: Clone off an ARM version of RecordScatteredRelocation until I figure out how it is supposed to work.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122410 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/MC/MachObjectWriter.cpp72
1 files changed, 68 insertions, 4 deletions
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index 167cda7..b746683 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -796,6 +796,70 @@ public:
Relocations[Fragment->getParent()].push_back(MRE);
}
+ void RecordARMScatteredRelocation(const MCAssembler &Asm,
+ const MCAsmLayout &Layout,
+ const MCFragment *Fragment,
+ const MCFixup &Fixup, MCValue Target,
+ uint64_t &FixedValue) {
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
+ unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
+ unsigned Type = macho::RIT_Vanilla;
+
+ // See <reloc.h>.
+ const MCSymbol *A = &Target.getSymA()->getSymbol();
+ MCSymbolData *A_SD = &Asm.getSymbolData(*A);
+
+ if (!A_SD->getFragment())
+ report_fatal_error("symbol '" + A->getName() +
+ "' can not be undefined in a subtraction expression");
+
+ uint32_t Value = getSymbolAddress(A_SD, Layout);
+ uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
+ FixedValue += SecAddr;
+ uint32_t Value2 = 0;
+
+ if (const MCSymbolRefExpr *B = Target.getSymB()) {
+ MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
+
+ if (!B_SD->getFragment())
+ report_fatal_error("symbol '" + B->getSymbol().getName() +
+ "' can not be undefined in a subtraction expression");
+
+ // Select the appropriate difference relocation type.
+ //
+ // Note that there is no longer any semantic difference between these two
+ // relocation types from the linkers point of view, this is done solely
+ // for pedantic compatibility with 'as'.
+ Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
+ (unsigned)macho::RIT_Generic_LocalDifference;
+ Value2 = getSymbolAddress(B_SD, Layout);
+ FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
+ }
+
+ // Relocations are written out in reverse order, so the PAIR comes first.
+ if (Type == macho::RIT_Difference ||
+ Type == macho::RIT_Generic_LocalDifference) {
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((0 << 0) |
+ (macho::RIT_Pair << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value2;
+ Relocations[Fragment->getParent()].push_back(MRE);
+ }
+
+ macho::RelocationEntry MRE;
+ MRE.Word0 = ((FixupOffset << 0) |
+ (Type << 24) |
+ (Log2Size << 28) |
+ (IsPCRel << 30) |
+ macho::RF_Scattered);
+ MRE.Word1 = Value;
+ Relocations[Fragment->getParent()].push_back(MRE);
+ }
+
void RecordTLVPRelocation(const MCAssembler &Asm,
const MCAsmLayout &Layout,
const MCFragment *Fragment,
@@ -889,8 +953,8 @@ public:
// a scattered relocation entry. Differences always require scattered
// relocations.
if (Target.getSymB())
- return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
- Target, FixedValue);
+ return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup,
+ Target, FixedValue);
// Get the symbol data, if any.
MCSymbolData *SD = 0;
@@ -906,8 +970,8 @@ public:
if (IsPCRel)
Offset += 1 << Log2Size;
if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
- return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
- Target, FixedValue);
+ return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup,
+ Target, FixedValue);
// See <reloc.h>.
uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();