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