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