1f785676fSDimitry Andric //===-- PPCMachObjectWriter.cpp - PPC Mach-O Writer -----------------------===//
2f785676fSDimitry Andric //
3f785676fSDimitry Andric // The LLVM Compiler Infrastructure
4f785676fSDimitry Andric //
5f785676fSDimitry Andric // This file is distributed under the University of Illinois Open Source
6f785676fSDimitry Andric // License. See LICENSE.TXT for details.
7f785676fSDimitry Andric //
8f785676fSDimitry Andric //===----------------------------------------------------------------------===//
9f785676fSDimitry Andric
10f785676fSDimitry Andric #include "MCTargetDesc/PPCFixupKinds.h"
11db17bf38SDimitry Andric #include "MCTargetDesc/PPCMCTargetDesc.h"
12f785676fSDimitry Andric #include "llvm/ADT/Twine.h"
13db17bf38SDimitry Andric #include "llvm/BinaryFormat/MachO.h"
14f785676fSDimitry Andric #include "llvm/MC/MCAsmLayout.h"
15f785676fSDimitry Andric #include "llvm/MC/MCAssembler.h"
16f785676fSDimitry Andric #include "llvm/MC/MCContext.h"
17f785676fSDimitry Andric #include "llvm/MC/MCMachObjectWriter.h"
18f785676fSDimitry Andric #include "llvm/MC/MCSectionMachO.h"
19f785676fSDimitry Andric #include "llvm/MC/MCValue.h"
20f785676fSDimitry Andric #include "llvm/Support/ErrorHandling.h"
21f785676fSDimitry Andric #include "llvm/Support/Format.h"
22f785676fSDimitry Andric
23f785676fSDimitry Andric using namespace llvm;
24f785676fSDimitry Andric
25f785676fSDimitry Andric namespace {
26f785676fSDimitry Andric class PPCMachObjectWriter : public MCMachObjectTargetWriter {
2797bc6c73SDimitry Andric bool recordScatteredRelocation(MachObjectWriter *Writer,
28f785676fSDimitry Andric const MCAssembler &Asm,
29f785676fSDimitry Andric const MCAsmLayout &Layout,
30f785676fSDimitry Andric const MCFragment *Fragment,
31f785676fSDimitry Andric const MCFixup &Fixup, MCValue Target,
32f785676fSDimitry Andric unsigned Log2Size, uint64_t &FixedValue);
33f785676fSDimitry Andric
34f785676fSDimitry Andric void RecordPPCRelocation(MachObjectWriter *Writer, const MCAssembler &Asm,
35f785676fSDimitry Andric const MCAsmLayout &Layout,
36f785676fSDimitry Andric const MCFragment *Fragment, const MCFixup &Fixup,
37f785676fSDimitry Andric MCValue Target, uint64_t &FixedValue);
38f785676fSDimitry Andric
39f785676fSDimitry Andric public:
PPCMachObjectWriter(bool Is64Bit,uint32_t CPUType,uint32_t CPUSubtype)40f785676fSDimitry Andric PPCMachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype)
4197bc6c73SDimitry Andric : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {}
42f785676fSDimitry Andric
recordRelocation(MachObjectWriter * Writer,MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)4397bc6c73SDimitry Andric void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm,
44f785676fSDimitry Andric const MCAsmLayout &Layout, const MCFragment *Fragment,
45f785676fSDimitry Andric const MCFixup &Fixup, MCValue Target,
4691bc56edSDimitry Andric uint64_t &FixedValue) override {
47f785676fSDimitry Andric if (Writer->is64Bit()) {
48f785676fSDimitry Andric report_fatal_error("Relocation emission for MachO/PPC64 unimplemented.");
49f785676fSDimitry Andric } else
50f785676fSDimitry Andric RecordPPCRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
51f785676fSDimitry Andric FixedValue);
52f785676fSDimitry Andric }
53f785676fSDimitry Andric };
543dac3a9bSDimitry Andric }
55f785676fSDimitry Andric
56f785676fSDimitry Andric /// computes the log2 of the size of the relocation,
57f785676fSDimitry Andric /// used for relocation_info::r_length.
getFixupKindLog2Size(unsigned Kind)58f785676fSDimitry Andric static unsigned getFixupKindLog2Size(unsigned Kind) {
59f785676fSDimitry Andric switch (Kind) {
60f785676fSDimitry Andric default:
61f785676fSDimitry Andric report_fatal_error("log2size(FixupKind): Unhandled fixup kind!");
62f785676fSDimitry Andric case FK_PCRel_1:
63f785676fSDimitry Andric case FK_Data_1:
64f785676fSDimitry Andric return 0;
65f785676fSDimitry Andric case FK_PCRel_2:
66f785676fSDimitry Andric case FK_Data_2:
67f785676fSDimitry Andric return 1;
68f785676fSDimitry Andric case FK_PCRel_4:
69f785676fSDimitry Andric case PPC::fixup_ppc_brcond14:
70f785676fSDimitry Andric case PPC::fixup_ppc_half16:
71f785676fSDimitry Andric case PPC::fixup_ppc_br24:
72f785676fSDimitry Andric case FK_Data_4:
73f785676fSDimitry Andric return 2;
74f785676fSDimitry Andric case FK_PCRel_8:
75f785676fSDimitry Andric case FK_Data_8:
76f785676fSDimitry Andric return 3;
77f785676fSDimitry Andric }
78f785676fSDimitry Andric return 0;
79f785676fSDimitry Andric }
80f785676fSDimitry Andric
81f785676fSDimitry Andric /// Translates generic PPC fixup kind to Mach-O/PPC relocation type enum.
823ca95b02SDimitry Andric /// Outline based on PPCELFObjectWriter::getRelocType().
getRelocType(const MCValue & Target,const MCFixupKind FixupKind,const bool IsPCRel)83f785676fSDimitry Andric static unsigned getRelocType(const MCValue &Target,
84f785676fSDimitry Andric const MCFixupKind FixupKind, // from
85f785676fSDimitry Andric // Fixup.getKind()
86f785676fSDimitry Andric const bool IsPCRel) {
87f785676fSDimitry Andric const MCSymbolRefExpr::VariantKind Modifier =
88f785676fSDimitry Andric Target.isAbsolute() ? MCSymbolRefExpr::VK_None
89f785676fSDimitry Andric : Target.getSymA()->getKind();
90f785676fSDimitry Andric // determine the type of the relocation
91f785676fSDimitry Andric unsigned Type = MachO::GENERIC_RELOC_VANILLA;
92f785676fSDimitry Andric if (IsPCRel) { // relative to PC
93f785676fSDimitry Andric switch ((unsigned)FixupKind) {
94f785676fSDimitry Andric default:
95f785676fSDimitry Andric report_fatal_error("Unimplemented fixup kind (relative)");
96f785676fSDimitry Andric case PPC::fixup_ppc_br24:
97f785676fSDimitry Andric Type = MachO::PPC_RELOC_BR24; // R_PPC_REL24
98f785676fSDimitry Andric break;
99f785676fSDimitry Andric case PPC::fixup_ppc_brcond14:
100f785676fSDimitry Andric Type = MachO::PPC_RELOC_BR14;
101f785676fSDimitry Andric break;
102f785676fSDimitry Andric case PPC::fixup_ppc_half16:
103f785676fSDimitry Andric switch (Modifier) {
104f785676fSDimitry Andric default:
105f785676fSDimitry Andric llvm_unreachable("Unsupported modifier for half16 fixup");
106f785676fSDimitry Andric case MCSymbolRefExpr::VK_PPC_HA:
107f785676fSDimitry Andric Type = MachO::PPC_RELOC_HA16;
108f785676fSDimitry Andric break;
109f785676fSDimitry Andric case MCSymbolRefExpr::VK_PPC_LO:
110f785676fSDimitry Andric Type = MachO::PPC_RELOC_LO16;
111f785676fSDimitry Andric break;
112f785676fSDimitry Andric case MCSymbolRefExpr::VK_PPC_HI:
113f785676fSDimitry Andric Type = MachO::PPC_RELOC_HI16;
114f785676fSDimitry Andric break;
115f785676fSDimitry Andric }
116f785676fSDimitry Andric break;
117f785676fSDimitry Andric }
118f785676fSDimitry Andric } else {
119f785676fSDimitry Andric switch ((unsigned)FixupKind) {
120f785676fSDimitry Andric default:
121f785676fSDimitry Andric report_fatal_error("Unimplemented fixup kind (absolute)!");
122f785676fSDimitry Andric case PPC::fixup_ppc_half16:
123f785676fSDimitry Andric switch (Modifier) {
124f785676fSDimitry Andric default:
125f785676fSDimitry Andric llvm_unreachable("Unsupported modifier for half16 fixup");
126f785676fSDimitry Andric case MCSymbolRefExpr::VK_PPC_HA:
127f785676fSDimitry Andric Type = MachO::PPC_RELOC_HA16_SECTDIFF;
128f785676fSDimitry Andric break;
129f785676fSDimitry Andric case MCSymbolRefExpr::VK_PPC_LO:
130f785676fSDimitry Andric Type = MachO::PPC_RELOC_LO16_SECTDIFF;
131f785676fSDimitry Andric break;
132f785676fSDimitry Andric case MCSymbolRefExpr::VK_PPC_HI:
133f785676fSDimitry Andric Type = MachO::PPC_RELOC_HI16_SECTDIFF;
134f785676fSDimitry Andric break;
135f785676fSDimitry Andric }
136f785676fSDimitry Andric break;
137f785676fSDimitry Andric case FK_Data_4:
138f785676fSDimitry Andric break;
139f785676fSDimitry Andric case FK_Data_2:
140f785676fSDimitry Andric break;
141f785676fSDimitry Andric }
142f785676fSDimitry Andric }
143f785676fSDimitry Andric return Type;
144f785676fSDimitry Andric }
145f785676fSDimitry Andric
makeRelocationInfo(MachO::any_relocation_info & MRE,const uint32_t FixupOffset,const uint32_t Index,const unsigned IsPCRel,const unsigned Log2Size,const unsigned IsExtern,const unsigned Type)146f785676fSDimitry Andric static void makeRelocationInfo(MachO::any_relocation_info &MRE,
147f785676fSDimitry Andric const uint32_t FixupOffset, const uint32_t Index,
148f785676fSDimitry Andric const unsigned IsPCRel, const unsigned Log2Size,
149f785676fSDimitry Andric const unsigned IsExtern, const unsigned Type) {
150f785676fSDimitry Andric MRE.r_word0 = FixupOffset;
151f785676fSDimitry Andric // The bitfield offsets that work (as determined by trial-and-error)
152f785676fSDimitry Andric // are different than what is documented in the mach-o manuals.
153f785676fSDimitry Andric // This appears to be an endianness issue; reversing the order of the
154db17bf38SDimitry Andric // documented bitfields in <llvm/BinaryFormat/MachO.h> fixes this (but
155f785676fSDimitry Andric // breaks x86/ARM assembly).
156f785676fSDimitry Andric MRE.r_word1 = ((Index << 8) | // was << 0
157f785676fSDimitry Andric (IsPCRel << 7) | // was << 24
158f785676fSDimitry Andric (Log2Size << 5) | // was << 25
159f785676fSDimitry Andric (IsExtern << 4) | // was << 27
160f785676fSDimitry Andric (Type << 0)); // was << 28
161f785676fSDimitry Andric }
162f785676fSDimitry Andric
163f785676fSDimitry Andric static void
makeScatteredRelocationInfo(MachO::any_relocation_info & MRE,const uint32_t Addr,const unsigned Type,const unsigned Log2Size,const unsigned IsPCRel,const uint32_t Value2)164f785676fSDimitry Andric makeScatteredRelocationInfo(MachO::any_relocation_info &MRE,
165f785676fSDimitry Andric const uint32_t Addr, const unsigned Type,
166f785676fSDimitry Andric const unsigned Log2Size, const unsigned IsPCRel,
167f785676fSDimitry Andric const uint32_t Value2) {
168f785676fSDimitry Andric // For notes on bitfield positions and endianness, see:
169f785676fSDimitry Andric // https://developer.apple.com/library/mac/documentation/developertools/conceptual/MachORuntime/Reference/reference.html#//apple_ref/doc/uid/20001298-scattered_relocation_entry
170f785676fSDimitry Andric MRE.r_word0 = ((Addr << 0) | (Type << 24) | (Log2Size << 28) |
171f785676fSDimitry Andric (IsPCRel << 30) | MachO::R_SCATTERED);
172f785676fSDimitry Andric MRE.r_word1 = Value2;
173f785676fSDimitry Andric }
174f785676fSDimitry Andric
175f785676fSDimitry Andric /// Compute fixup offset (address).
getFixupOffset(const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup)176f785676fSDimitry Andric static uint32_t getFixupOffset(const MCAsmLayout &Layout,
177f785676fSDimitry Andric const MCFragment *Fragment,
178f785676fSDimitry Andric const MCFixup &Fixup) {
179f785676fSDimitry Andric uint32_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
180f785676fSDimitry Andric // On Mach-O, ppc_fixup_half16 relocations must refer to the
181f785676fSDimitry Andric // start of the instruction, not the second halfword, as ELF does
182f785676fSDimitry Andric if (unsigned(Fixup.getKind()) == PPC::fixup_ppc_half16)
183f785676fSDimitry Andric FixupOffset &= ~uint32_t(3);
184f785676fSDimitry Andric return FixupOffset;
185f785676fSDimitry Andric }
186f785676fSDimitry Andric
187f785676fSDimitry Andric /// \return false if falling back to using non-scattered relocation,
188f785676fSDimitry Andric /// otherwise true for normal scattered relocation.
18997bc6c73SDimitry Andric /// based on X86MachObjectWriter::recordScatteredRelocation
19097bc6c73SDimitry Andric /// and ARMMachObjectWriter::recordScatteredRelocation
recordScatteredRelocation(MachObjectWriter * Writer,const MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,unsigned Log2Size,uint64_t & FixedValue)19197bc6c73SDimitry Andric bool PPCMachObjectWriter::recordScatteredRelocation(
192f785676fSDimitry Andric MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
193f785676fSDimitry Andric const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
194f785676fSDimitry Andric unsigned Log2Size, uint64_t &FixedValue) {
195f785676fSDimitry Andric // caller already computes these, can we just pass and reuse?
196f785676fSDimitry Andric const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
197f785676fSDimitry Andric const MCFixupKind FK = Fixup.getKind();
198f785676fSDimitry Andric const unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
199f785676fSDimitry Andric const unsigned Type = getRelocType(Target, FK, IsPCRel);
200f785676fSDimitry Andric
201f785676fSDimitry Andric // Is this a local or SECTDIFF relocation entry?
202f785676fSDimitry Andric // SECTDIFF relocation entries have symbol subtractions,
203f785676fSDimitry Andric // and require two entries, the first for the add-symbol value,
204f785676fSDimitry Andric // the second for the subtract-symbol value.
205f785676fSDimitry Andric
206f785676fSDimitry Andric // See <reloc.h>.
207f785676fSDimitry Andric const MCSymbol *A = &Target.getSymA()->getSymbol();
208f785676fSDimitry Andric
20997bc6c73SDimitry Andric if (!A->getFragment())
210f785676fSDimitry Andric report_fatal_error("symbol '" + A->getName() +
211f785676fSDimitry Andric "' can not be undefined in a subtraction expression");
212f785676fSDimitry Andric
213ff0cc061SDimitry Andric uint32_t Value = Writer->getSymbolAddress(*A, Layout);
21497bc6c73SDimitry Andric uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent());
215f785676fSDimitry Andric FixedValue += SecAddr;
216f785676fSDimitry Andric uint32_t Value2 = 0;
217f785676fSDimitry Andric
218f785676fSDimitry Andric if (const MCSymbolRefExpr *B = Target.getSymB()) {
21997bc6c73SDimitry Andric const MCSymbol *SB = &B->getSymbol();
220f785676fSDimitry Andric
22197bc6c73SDimitry Andric if (!SB->getFragment())
222a580b014SDimitry Andric report_fatal_error("symbol '" + SB->getName() +
223f785676fSDimitry Andric "' can not be undefined in a subtraction expression");
224f785676fSDimitry Andric
225db17bf38SDimitry Andric // FIXME: is Type correct? see include/llvm/BinaryFormat/MachO.h
226a580b014SDimitry Andric Value2 = Writer->getSymbolAddress(*SB, Layout);
22797bc6c73SDimitry Andric FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent());
228f785676fSDimitry Andric }
229f785676fSDimitry Andric // FIXME: does FixedValue get used??
230f785676fSDimitry Andric
231f785676fSDimitry Andric // Relocations are written out in reverse order, so the PAIR comes first.
232f785676fSDimitry Andric if (Type == MachO::PPC_RELOC_SECTDIFF ||
233f785676fSDimitry Andric Type == MachO::PPC_RELOC_HI16_SECTDIFF ||
234f785676fSDimitry Andric Type == MachO::PPC_RELOC_LO16_SECTDIFF ||
235f785676fSDimitry Andric Type == MachO::PPC_RELOC_HA16_SECTDIFF ||
236f785676fSDimitry Andric Type == MachO::PPC_RELOC_LO14_SECTDIFF ||
237f785676fSDimitry Andric Type == MachO::PPC_RELOC_LOCAL_SECTDIFF) {
238f785676fSDimitry Andric // X86 had this piece, but ARM does not
239f785676fSDimitry Andric // If the offset is too large to fit in a scattered relocation,
240f785676fSDimitry Andric // we're hosed. It's an unfortunate limitation of the MachO format.
241f785676fSDimitry Andric if (FixupOffset > 0xffffff) {
242f785676fSDimitry Andric char Buffer[32];
243f785676fSDimitry Andric format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer));
2447d523365SDimitry Andric Asm.getContext().reportError(Fixup.getLoc(),
245f785676fSDimitry Andric Twine("Section too large, can't encode "
246f785676fSDimitry Andric "r_address (") +
247f785676fSDimitry Andric Buffer + ") into 24 bits of scattered "
248f785676fSDimitry Andric "relocation entry.");
2497d523365SDimitry Andric return false;
250f785676fSDimitry Andric }
251f785676fSDimitry Andric
252f785676fSDimitry Andric // Is this supposed to follow MCTarget/PPCAsmBackend.cpp:adjustFixupValue()?
25397bc6c73SDimitry Andric // see PPCMCExpr::evaluateAsRelocatableImpl()
254f785676fSDimitry Andric uint32_t other_half = 0;
255f785676fSDimitry Andric switch (Type) {
256f785676fSDimitry Andric case MachO::PPC_RELOC_LO16_SECTDIFF:
257f785676fSDimitry Andric other_half = (FixedValue >> 16) & 0xffff;
258f785676fSDimitry Andric // applyFixupOffset longer extracts the high part because it now assumes
259f785676fSDimitry Andric // this was already done.
260f785676fSDimitry Andric // It looks like this is not true for the FixedValue needed with Mach-O
261f785676fSDimitry Andric // relocs.
262f785676fSDimitry Andric // So we need to adjust FixedValue again here.
263f785676fSDimitry Andric FixedValue &= 0xffff;
264f785676fSDimitry Andric break;
265f785676fSDimitry Andric case MachO::PPC_RELOC_HA16_SECTDIFF:
266f785676fSDimitry Andric other_half = FixedValue & 0xffff;
267f785676fSDimitry Andric FixedValue =
268f785676fSDimitry Andric ((FixedValue >> 16) + ((FixedValue & 0x8000) ? 1 : 0)) & 0xffff;
269f785676fSDimitry Andric break;
270f785676fSDimitry Andric case MachO::PPC_RELOC_HI16_SECTDIFF:
271f785676fSDimitry Andric other_half = FixedValue & 0xffff;
272f785676fSDimitry Andric FixedValue = (FixedValue >> 16) & 0xffff;
273f785676fSDimitry Andric break;
274f785676fSDimitry Andric default:
275f785676fSDimitry Andric llvm_unreachable("Invalid PPC scattered relocation type.");
276f785676fSDimitry Andric break;
277f785676fSDimitry Andric }
278f785676fSDimitry Andric
279f785676fSDimitry Andric MachO::any_relocation_info MRE;
280f785676fSDimitry Andric makeScatteredRelocationInfo(MRE, other_half, MachO::GENERIC_RELOC_PAIR,
281f785676fSDimitry Andric Log2Size, IsPCRel, Value2);
282ff0cc061SDimitry Andric Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
283f785676fSDimitry Andric } else {
284f785676fSDimitry Andric // If the offset is more than 24-bits, it won't fit in a scattered
285f785676fSDimitry Andric // relocation offset field, so we fall back to using a non-scattered
286f785676fSDimitry Andric // relocation. This is a bit risky, as if the offset reaches out of
287f785676fSDimitry Andric // the block and the linker is doing scattered loading on this
288f785676fSDimitry Andric // symbol, things can go badly.
289f785676fSDimitry Andric //
290f785676fSDimitry Andric // Required for 'as' compatibility.
291f785676fSDimitry Andric if (FixupOffset > 0xffffff)
292f785676fSDimitry Andric return false;
293f785676fSDimitry Andric }
294f785676fSDimitry Andric MachO::any_relocation_info MRE;
295f785676fSDimitry Andric makeScatteredRelocationInfo(MRE, FixupOffset, Type, Log2Size, IsPCRel, Value);
296ff0cc061SDimitry Andric Writer->addRelocation(nullptr, Fragment->getParent(), MRE);
297f785676fSDimitry Andric return true;
298f785676fSDimitry Andric }
299f785676fSDimitry Andric
300f785676fSDimitry Andric // see PPCELFObjectWriter for a general outline of cases
RecordPPCRelocation(MachObjectWriter * Writer,const MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)301f785676fSDimitry Andric void PPCMachObjectWriter::RecordPPCRelocation(
302f785676fSDimitry Andric MachObjectWriter *Writer, const MCAssembler &Asm, const MCAsmLayout &Layout,
303f785676fSDimitry Andric const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target,
304f785676fSDimitry Andric uint64_t &FixedValue) {
305f785676fSDimitry Andric const MCFixupKind FK = Fixup.getKind(); // unsigned
306f785676fSDimitry Andric const unsigned Log2Size = getFixupKindLog2Size(FK);
307f785676fSDimitry Andric const bool IsPCRel = Writer->isFixupKindPCRel(Asm, FK);
308f785676fSDimitry Andric const unsigned RelocType = getRelocType(Target, FK, IsPCRel);
309f785676fSDimitry Andric
310f785676fSDimitry Andric // If this is a difference or a defined symbol plus an offset, then we need a
311f785676fSDimitry Andric // scattered relocation entry. Differences always require scattered
312f785676fSDimitry Andric // relocations.
313f785676fSDimitry Andric if (Target.getSymB() &&
314f785676fSDimitry Andric // Q: are branch targets ever scattered?
315f785676fSDimitry Andric RelocType != MachO::PPC_RELOC_BR24 &&
316f785676fSDimitry Andric RelocType != MachO::PPC_RELOC_BR14) {
31797bc6c73SDimitry Andric recordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target,
318f785676fSDimitry Andric Log2Size, FixedValue);
319f785676fSDimitry Andric return;
320f785676fSDimitry Andric }
321f785676fSDimitry Andric
322f785676fSDimitry Andric // this doesn't seem right for RIT_PPC_BR24
323f785676fSDimitry Andric // Get the symbol data, if any.
324ff0cc061SDimitry Andric const MCSymbol *A = nullptr;
325f785676fSDimitry Andric if (Target.getSymA())
326ff0cc061SDimitry Andric A = &Target.getSymA()->getSymbol();
327f785676fSDimitry Andric
328f785676fSDimitry Andric // See <reloc.h>.
329f785676fSDimitry Andric const uint32_t FixupOffset = getFixupOffset(Layout, Fragment, Fixup);
330f785676fSDimitry Andric unsigned Index = 0;
331f785676fSDimitry Andric unsigned Type = RelocType;
332f785676fSDimitry Andric
333ff0cc061SDimitry Andric const MCSymbol *RelSymbol = nullptr;
334f785676fSDimitry Andric if (Target.isAbsolute()) { // constant
335f785676fSDimitry Andric // SymbolNum of 0 indicates the absolute section.
336f785676fSDimitry Andric //
337f785676fSDimitry Andric // FIXME: Currently, these are never generated (see code below). I cannot
338f785676fSDimitry Andric // find a case where they are actually emitted.
339f785676fSDimitry Andric report_fatal_error("FIXME: relocations to absolute targets "
340f785676fSDimitry Andric "not yet implemented");
341f785676fSDimitry Andric // the above line stolen from ARM, not sure
342f785676fSDimitry Andric } else {
343f785676fSDimitry Andric // Resolve constant variables.
344ff0cc061SDimitry Andric if (A->isVariable()) {
345f785676fSDimitry Andric int64_t Res;
34697bc6c73SDimitry Andric if (A->getVariableValue()->evaluateAsAbsolute(
347f785676fSDimitry Andric Res, Layout, Writer->getSectionAddressMap())) {
348f785676fSDimitry Andric FixedValue = Res;
349f785676fSDimitry Andric return;
350f785676fSDimitry Andric }
351f785676fSDimitry Andric }
352f785676fSDimitry Andric
353f785676fSDimitry Andric // Check whether we need an external or internal relocation.
354ff0cc061SDimitry Andric if (Writer->doesSymbolRequireExternRelocation(*A)) {
355ff0cc061SDimitry Andric RelSymbol = A;
356f785676fSDimitry Andric // For external relocations, make sure to offset the fixup value to
357f785676fSDimitry Andric // compensate for the addend of the symbol address, if it was
358f785676fSDimitry Andric // undefined. This occurs with weak definitions, for example.
359ff0cc061SDimitry Andric if (!A->isUndefined())
360ff0cc061SDimitry Andric FixedValue -= Layout.getSymbolOffset(*A);
361f785676fSDimitry Andric } else {
362f785676fSDimitry Andric // The index is the section ordinal (1-based).
363ff0cc061SDimitry Andric const MCSection &Sec = A->getSection();
364ff0cc061SDimitry Andric Index = Sec.getOrdinal() + 1;
365ff0cc061SDimitry Andric FixedValue += Writer->getSectionAddress(&Sec);
366f785676fSDimitry Andric }
367f785676fSDimitry Andric if (IsPCRel)
368f785676fSDimitry Andric FixedValue -= Writer->getSectionAddress(Fragment->getParent());
369f785676fSDimitry Andric }
370f785676fSDimitry Andric
371f785676fSDimitry Andric // struct relocation_info (8 bytes)
372f785676fSDimitry Andric MachO::any_relocation_info MRE;
373ff0cc061SDimitry Andric makeRelocationInfo(MRE, FixupOffset, Index, IsPCRel, Log2Size, false, Type);
374ff0cc061SDimitry Andric Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE);
375f785676fSDimitry Andric }
376f785676fSDimitry Andric
377*4ba319b5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createPPCMachObjectWriter(bool Is64Bit,uint32_t CPUType,uint32_t CPUSubtype)378*4ba319b5SDimitry Andric llvm::createPPCMachObjectWriter(bool Is64Bit, uint32_t CPUType,
379*4ba319b5SDimitry Andric uint32_t CPUSubtype) {
380*4ba319b5SDimitry Andric return llvm::make_unique<PPCMachObjectWriter>(Is64Bit, CPUType, CPUSubtype);
381f785676fSDimitry Andric }
382