summaryrefslogtreecommitdiff
path: root/lib/MC/MachObjectWriter.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-12-22 13:50:05 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-12-22 13:50:05 +0000
commit4d74305a1f55f458d401a79db4deeed726567195 (patch)
treec72169d1242aa21a99aa9d1e5bf9920a3458b3b7 /lib/MC/MachObjectWriter.cpp
parent42b5286627172b24de73e7403b60b50fc2e0db59 (diff)
downloadllvm-4d74305a1f55f458d401a79db4deeed726567195.tar.gz
llvm-4d74305a1f55f458d401a79db4deeed726567195.tar.bz2
llvm-4d74305a1f55f458d401a79db4deeed726567195.tar.xz
MC/Mach-O/ARM: Stub out RecordARMRelocation, which is mostly a copy of
RecordRelocation with lots of FIXMEs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@122402 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MachObjectWriter.cpp')
-rw-r--r--lib/MC/MachObjectWriter.cpp79
1 files changed, 78 insertions, 1 deletions
diff --git a/lib/MC/MachObjectWriter.cpp b/lib/MC/MachObjectWriter.cpp
index a06176cad6..4ef1dfb3e0 100644
--- a/lib/MC/MachObjectWriter.cpp
+++ b/lib/MC/MachObjectWriter.cpp
@@ -846,7 +846,84 @@ public:
void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFragment *Fragment, const MCFixup &Fixup,
MCValue Target, uint64_t &FixedValue) {
- // FIXME!
+ unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
+ // FIXME: Eliminate this!
+ unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
+
+ // If this is a difference or a defined symbol plus an offset, then we need
+ // a scattered relocation entry. Differences always require scattered
+ // relocations.
+ if (Target.getSymB())
+ return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
+ Target, FixedValue);
+
+ // Get the symbol data, if any.
+ MCSymbolData *SD = 0;
+ if (Target.getSymA())
+ SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
+
+ // FIXME: For other platforms, we need to use scattered relocations for
+ // internal relocations with offsets. If this is an internal relocation
+ // with an offset, it also needs a scattered relocation entry.
+ //
+ // Is this right for ARM?
+ uint32_t Offset = Target.getConstant();
+ if (IsPCRel)
+ Offset += 1 << Log2Size;
+ if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
+ return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
+ Target, FixedValue);
+
+ // See <reloc.h>.
+ uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
+ unsigned Index = 0;
+ unsigned IsExtern = 0;
+ unsigned Type = 0;
+
+ if (Target.isAbsolute()) { // constant
+ // FIXME!
+ report_fatal_error("FIXME: relocations to absolute targets "
+ "not yet implemented");
+ } else if (SD->getSymbol().isVariable()) {
+ int64_t Res;
+ if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
+ Res, Layout, SectionAddress)) {
+ FixedValue = Res;
+ return;
+ }
+
+ report_fatal_error("unsupported relocation of variable '" +
+ SD->getSymbol().getName() + "'");
+ } else {
+ // Check whether we need an external or internal relocation.
+ if (doesSymbolRequireExternRelocation(SD)) {
+ IsExtern = 1;
+ Index = SD->getIndex();
+ // For external relocations, make sure to offset the fixup value to
+ // compensate for the addend of the symbol address, if it was
+ // undefined. This occurs with weak definitions, for example.
+ if (!SD->Symbol->isUndefined())
+ FixedValue -= Layout.getSymbolOffset(SD);
+ } else {
+ // The index is the section ordinal (1-based).
+ Index = SD->getFragment()->getParent()->getOrdinal() + 1;
+ FixedValue += getSectionAddress(SD->getFragment()->getParent());
+ }
+ if (IsPCRel)
+ FixedValue -= getSectionAddress(Fragment->getParent());
+
+ Type = macho::RIT_Vanilla;
+ }
+
+ // struct relocation_info (8 bytes)
+ macho::RelocationEntry MRE;
+ MRE.Word0 = FixupOffset;
+ MRE.Word1 = ((Index << 0) |
+ (IsPCRel << 24) |
+ (Log2Size << 25) |
+ (IsExtern << 27) |
+ (Type << 28));
+ Relocations[Fragment->getParent()].push_back(MRE);
}
void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,