ARMMachObjectWriter.cpp revision 261991
1210944Sjkim//===-- ARMMachObjectWriter.cpp - ARM Mach Object Writer ------------------===// 2210944Sjkim// 3210944Sjkim// The LLVM Compiler Infrastructure 4210944Sjkim// 5210944Sjkim// This file is distributed under the University of Illinois Open Source 6210944Sjkim// License. See LICENSE.TXT for details. 7217365Sjkim// 8281075Sdim//===----------------------------------------------------------------------===// 9210944Sjkim 10210944Sjkim#include "MCTargetDesc/ARMMCTargetDesc.h" 11217365Sjkim#include "MCTargetDesc/ARMBaseInfo.h" 12217365Sjkim#include "MCTargetDesc/ARMFixupKinds.h" 13217365Sjkim#include "llvm/ADT/Twine.h" 14217365Sjkim#include "llvm/MC/MCAsmLayout.h" 15217365Sjkim#include "llvm/MC/MCAssembler.h" 16217365Sjkim#include "llvm/MC/MCContext.h" 17217365Sjkim#include "llvm/MC/MCExpr.h" 18217365Sjkim#include "llvm/MC/MCFixup.h" 19217365Sjkim#include "llvm/MC/MCFixupKindInfo.h" 20217365Sjkim#include "llvm/MC/MCMachOSymbolFlags.h" 21217365Sjkim#include "llvm/MC/MCMachObjectWriter.h" 22217365Sjkim#include "llvm/MC/MCValue.h" 23217365Sjkim#include "llvm/Support/ErrorHandling.h" 24217365Sjkim#include "llvm/Support/MachO.h" 25210944Sjkimusing namespace llvm; 26217365Sjkim 27217365Sjkimnamespace { 28217365Sjkimclass ARMMachObjectWriter : public MCMachObjectTargetWriter { 29210944Sjkim void RecordARMScatteredRelocation(MachObjectWriter *Writer, 30217365Sjkim const MCAssembler &Asm, 31217365Sjkim const MCAsmLayout &Layout, 32217365Sjkim const MCFragment *Fragment, 33217365Sjkim const MCFixup &Fixup, 34217365Sjkim MCValue Target, 35217365Sjkim unsigned Log2Size, 36217365Sjkim uint64_t &FixedValue); 37217365Sjkim void RecordARMScatteredHalfRelocation(MachObjectWriter *Writer, 38217365Sjkim const MCAssembler &Asm, 39217365Sjkim const MCAsmLayout &Layout, 40217365Sjkim const MCFragment *Fragment, 41217365Sjkim const MCFixup &Fixup, MCValue Target, 42217365Sjkim uint64_t &FixedValue); 43210944Sjkim 44210976Sjkim bool requiresExternRelocation(MachObjectWriter *Writer, 45210976Sjkim const MCAssembler &Asm, 46210944Sjkim const MCFragment &Fragment, 47210944Sjkim unsigned RelocType, const MCSymbolData *SD, 48210944Sjkim uint64_t FixedValue); 49210944Sjkim 50210944Sjkimpublic: 51281075Sdim ARMMachObjectWriter(bool Is64Bit, uint32_t CPUType, 52281075Sdim uint32_t CPUSubtype) 53281075Sdim : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype, 54281075Sdim /*UseAggressiveSymbolFolding=*/true) {} 55281075Sdim 56281075Sdim void RecordRelocation(MachObjectWriter *Writer, 57281075Sdim const MCAssembler &Asm, const MCAsmLayout &Layout, 58281075Sdim const MCFragment *Fragment, const MCFixup &Fixup, 59281075Sdim MCValue Target, uint64_t &FixedValue); 60281075Sdim}; 61281075Sdim} 62281075Sdim 63281075Sdimstatic bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType, 64281075Sdim unsigned &Log2Size) { 65281075Sdim RelocType = unsigned(MachO::ARM_RELOC_VANILLA); 66281075Sdim Log2Size = ~0U; 67281075Sdim 68281075Sdim switch (Kind) { 69281075Sdim default: 70281075Sdim return false; 71281075Sdim 72281075Sdim case FK_Data_1: 73281075Sdim Log2Size = llvm::Log2_32(1); 74281075Sdim return true; 75281075Sdim case FK_Data_2: 76281075Sdim Log2Size = llvm::Log2_32(2); 77281075Sdim return true; 78281075Sdim case FK_Data_4: 79210944Sjkim Log2Size = llvm::Log2_32(4); 80210944Sjkim return true; 81210944Sjkim case FK_Data_8: 82210944Sjkim Log2Size = llvm::Log2_32(8); 83210944Sjkim return true; 84210944Sjkim 85210944Sjkim // Handle 24-bit branch kinds. 86210944Sjkim case ARM::fixup_arm_ldst_pcrel_12: 87210944Sjkim case ARM::fixup_arm_pcrel_10: 88210944Sjkim case ARM::fixup_arm_adr_pcrel_12: 89210944Sjkim case ARM::fixup_arm_condbranch: 90210944Sjkim case ARM::fixup_arm_uncondbranch: 91210944Sjkim case ARM::fixup_arm_uncondbl: 92210944Sjkim case ARM::fixup_arm_condbl: 93210944Sjkim case ARM::fixup_arm_blx: 94210944Sjkim RelocType = unsigned(MachO::ARM_RELOC_BR24); 95210944Sjkim // Report as 'long', even though that is not quite accurate. 96210944Sjkim Log2Size = llvm::Log2_32(4); 97210944Sjkim return true; 98210944Sjkim 99210944Sjkim // Handle Thumb branches. 100210944Sjkim case ARM::fixup_arm_thumb_br: 101210944Sjkim RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22); 102210944Sjkim Log2Size = llvm::Log2_32(2); 103210944Sjkim return true; 104213806Sjkim 105210944Sjkim case ARM::fixup_t2_uncondbranch: 106239340Sjkim case ARM::fixup_arm_thumb_bl: 107281075Sdim case ARM::fixup_arm_thumb_blx: 108281687Sjkim RelocType = unsigned(MachO::ARM_THUMB_RELOC_BR22); 109210944Sjkim Log2Size = llvm::Log2_32(4); 110210944Sjkim return true; 111210944Sjkim 112253690Sjkim // For movw/movt r_type relocations they always have a pair following them and 113210944Sjkim // the r_length bits are used differently. The encoding of the r_length is as 114210944Sjkim // follows: 115210944Sjkim // low bit of r_length: 116253690Sjkim // 0 - :lower16: for movw instructions 117253690Sjkim // 1 - :upper16: for movt instructions 118253690Sjkim // high bit of r_length: 119210944Sjkim // 0 - arm instructions 120253690Sjkim // 1 - thumb instructions 121253690Sjkim case ARM::fixup_arm_movt_hi16: 122253690Sjkim case ARM::fixup_arm_movt_hi16_pcrel: 123253690Sjkim RelocType = unsigned(MachO::ARM_RELOC_HALF); 124253690Sjkim Log2Size = 1; 125253690Sjkim return true; 126210944Sjkim case ARM::fixup_t2_movt_hi16: 127210944Sjkim case ARM::fixup_t2_movt_hi16_pcrel: 128210944Sjkim RelocType = unsigned(MachO::ARM_RELOC_HALF); 129210944Sjkim Log2Size = 3; 130210944Sjkim return true; 131210944Sjkim 132210944Sjkim case ARM::fixup_arm_movw_lo16: 133210944Sjkim case ARM::fixup_arm_movw_lo16_pcrel: 134210944Sjkim RelocType = unsigned(MachO::ARM_RELOC_HALF); 135210944Sjkim Log2Size = 0; 136210944Sjkim return true; 137210944Sjkim case ARM::fixup_t2_movw_lo16: 138210944Sjkim case ARM::fixup_t2_movw_lo16_pcrel: 139210944Sjkim RelocType = unsigned(MachO::ARM_RELOC_HALF); 140210944Sjkim Log2Size = 2; 141210944Sjkim return true; 142210944Sjkim } 143210944Sjkim} 144210944Sjkim 145249112Sjkimvoid ARMMachObjectWriter:: 146210944SjkimRecordARMScatteredHalfRelocation(MachObjectWriter *Writer, 147210944Sjkim const MCAssembler &Asm, 148210944Sjkim const MCAsmLayout &Layout, 149249112Sjkim const MCFragment *Fragment, 150249112Sjkim const MCFixup &Fixup, 151249112Sjkim MCValue Target, 152249112Sjkim uint64_t &FixedValue) { 153249112Sjkim uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 154249112Sjkim unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 155210944Sjkim unsigned Type = MachO::ARM_RELOC_HALF; 156210944Sjkim 157210944Sjkim // See <reloc.h>. 158210944Sjkim const MCSymbol *A = &Target.getSymA()->getSymbol(); 159210944Sjkim MCSymbolData *A_SD = &Asm.getSymbolData(*A); 160210944Sjkim 161210944Sjkim if (!A_SD->getFragment()) 162210944Sjkim Asm.getContext().FatalError(Fixup.getLoc(), 163210944Sjkim "symbol '" + A->getName() + 164210944Sjkim "' can not be undefined in a subtraction expression"); 165210944Sjkim 166210944Sjkim uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); 167210944Sjkim uint32_t Value2 = 0; 168210944Sjkim uint64_t SecAddr = 169210944Sjkim Writer->getSectionAddress(A_SD->getFragment()->getParent()); 170210944Sjkim FixedValue += SecAddr; 171210944Sjkim 172210944Sjkim if (const MCSymbolRefExpr *B = Target.getSymB()) { 173210944Sjkim MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); 174210944Sjkim 175210944Sjkim if (!B_SD->getFragment()) 176249112Sjkim Asm.getContext().FatalError(Fixup.getLoc(), 177210944Sjkim "symbol '" + B->getSymbol().getName() + 178210944Sjkim "' can not be undefined in a subtraction expression"); 179210944Sjkim 180210944Sjkim // Select the appropriate difference relocation type. 181210944Sjkim Type = MachO::ARM_RELOC_HALF_SECTDIFF; 182210944Sjkim Value2 = Writer->getSymbolAddress(B_SD, Layout); 183249112Sjkim FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); 184210944Sjkim } 185210944Sjkim 186210944Sjkim // Relocations are written out in reverse order, so the PAIR comes first. 187249112Sjkim // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field: 188210944Sjkim // 189210944Sjkim // For these two r_type relocations they always have a pair following them and 190210944Sjkim // the r_length bits are used differently. The encoding of the r_length is as 191249112Sjkim // follows: 192249112Sjkim // low bit of r_length: 193249112Sjkim // 0 - :lower16: for movw instructions 194249112Sjkim // 1 - :upper16: for movt instructions 195249112Sjkim // high bit of r_length: 196249112Sjkim // 0 - arm instructions 197210944Sjkim // 1 - thumb instructions 198210944Sjkim // the other half of the relocated expression is in the following pair 199210944Sjkim // relocation entry in the low 16 bits of r_address field. 200210944Sjkim unsigned ThumbBit = 0; 201210944Sjkim unsigned MovtBit = 0; 202210944Sjkim switch ((unsigned)Fixup.getKind()) { 203210944Sjkim default: break; 204253690Sjkim case ARM::fixup_arm_movt_hi16: 205253690Sjkim case ARM::fixup_arm_movt_hi16_pcrel: 206210944Sjkim MovtBit = 1; 207210944Sjkim // The thumb bit shouldn't be set in the 'other-half' bit of the 208210944Sjkim // relocation, but it will be set in FixedValue if the base symbol 209253690Sjkim // is a thumb function. Clear it out here. 210253690Sjkim if (A_SD->getFlags() & SF_ThumbFunc) 211253690Sjkim FixedValue &= 0xfffffffe; 212210944Sjkim break; 213253690Sjkim case ARM::fixup_t2_movt_hi16: 214253690Sjkim case ARM::fixup_t2_movt_hi16_pcrel: 215253690Sjkim if (A_SD->getFlags() & SF_ThumbFunc) 216253690Sjkim FixedValue &= 0xfffffffe; 217253690Sjkim MovtBit = 1; 218253690Sjkim // Fallthrough 219253690Sjkim case ARM::fixup_t2_movw_lo16: 220253690Sjkim case ARM::fixup_t2_movw_lo16_pcrel: 221253690Sjkim ThumbBit = 1; 222253690Sjkim break; 223210944Sjkim } 224210944Sjkim 225210944Sjkim if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 226210944Sjkim uint32_t OtherHalf = MovtBit 227249112Sjkim ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16); 228210944Sjkim 229210944Sjkim MachO::any_relocation_info MRE; 230210944Sjkim MRE.r_word0 = ((OtherHalf << 0) | 231210944Sjkim (MachO::ARM_RELOC_PAIR << 24) | 232210944Sjkim (MovtBit << 28) | 233210944Sjkim (ThumbBit << 29) | 234210944Sjkim (IsPCRel << 30) | 235210944Sjkim MachO::R_SCATTERED); 236210944Sjkim MRE.r_word1 = Value2; 237210944Sjkim Writer->addRelocation(Fragment->getParent(), MRE); 238210944Sjkim } 239210944Sjkim 240210944Sjkim MachO::any_relocation_info MRE; 241210944Sjkim MRE.r_word0 = ((FixupOffset << 0) | 242210944Sjkim (Type << 24) | 243210944Sjkim (MovtBit << 28) | 244210944Sjkim (ThumbBit << 29) | 245210944Sjkim (IsPCRel << 30) | 246210944Sjkim MachO::R_SCATTERED); 247210944Sjkim MRE.r_word1 = Value; 248210944Sjkim Writer->addRelocation(Fragment->getParent(), MRE); 249210944Sjkim} 250210944Sjkim 251210944Sjkimvoid ARMMachObjectWriter::RecordARMScatteredRelocation(MachObjectWriter *Writer, 252210944Sjkim const MCAssembler &Asm, 253210944Sjkim const MCAsmLayout &Layout, 254210944Sjkim const MCFragment *Fragment, 255210944Sjkim const MCFixup &Fixup, 256210944Sjkim MCValue Target, 257210944Sjkim unsigned Log2Size, 258210944Sjkim uint64_t &FixedValue) { 259210944Sjkim uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 260210944Sjkim unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 261210944Sjkim unsigned Type = MachO::ARM_RELOC_VANILLA; 262210944Sjkim 263210944Sjkim // See <reloc.h>. 264210944Sjkim const MCSymbol *A = &Target.getSymA()->getSymbol(); 265210944Sjkim MCSymbolData *A_SD = &Asm.getSymbolData(*A); 266210944Sjkim 267210944Sjkim if (!A_SD->getFragment()) 268210944Sjkim Asm.getContext().FatalError(Fixup.getLoc(), 269210944Sjkim "symbol '" + A->getName() + 270210944Sjkim "' can not be undefined in a subtraction expression"); 271210944Sjkim 272210944Sjkim uint32_t Value = Writer->getSymbolAddress(A_SD, Layout); 273210944Sjkim uint64_t SecAddr = Writer->getSectionAddress(A_SD->getFragment()->getParent()); 274210944Sjkim FixedValue += SecAddr; 275210944Sjkim uint32_t Value2 = 0; 276210944Sjkim 277210944Sjkim if (const MCSymbolRefExpr *B = Target.getSymB()) { 278210944Sjkim MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol()); 279210944Sjkim 280210944Sjkim if (!B_SD->getFragment()) 281210944Sjkim Asm.getContext().FatalError(Fixup.getLoc(), 282210944Sjkim "symbol '" + B->getSymbol().getName() + 283210944Sjkim "' can not be undefined in a subtraction expression"); 284210944Sjkim 285210944Sjkim // Select the appropriate difference relocation type. 286210944Sjkim Type = MachO::ARM_RELOC_SECTDIFF; 287210944Sjkim Value2 = Writer->getSymbolAddress(B_SD, Layout); 288210944Sjkim FixedValue -= Writer->getSectionAddress(B_SD->getFragment()->getParent()); 289210944Sjkim } 290210944Sjkim 291210944Sjkim // Relocations are written out in reverse order, so the PAIR comes first. 292210944Sjkim if (Type == MachO::ARM_RELOC_SECTDIFF || 293210944Sjkim Type == MachO::ARM_RELOC_LOCAL_SECTDIFF) { 294210944Sjkim MachO::any_relocation_info MRE; 295210944Sjkim MRE.r_word0 = ((0 << 0) | 296210944Sjkim (MachO::ARM_RELOC_PAIR << 24) | 297210944Sjkim (Log2Size << 28) | 298210944Sjkim (IsPCRel << 30) | 299210944Sjkim MachO::R_SCATTERED); 300210944Sjkim MRE.r_word1 = Value2; 301210944Sjkim Writer->addRelocation(Fragment->getParent(), MRE); 302210944Sjkim } 303210944Sjkim 304210944Sjkim MachO::any_relocation_info MRE; 305210944Sjkim MRE.r_word0 = ((FixupOffset << 0) | 306210944Sjkim (Type << 24) | 307210944Sjkim (Log2Size << 28) | 308210944Sjkim (IsPCRel << 30) | 309210944Sjkim MachO::R_SCATTERED); 310210944Sjkim MRE.r_word1 = Value; 311210944Sjkim Writer->addRelocation(Fragment->getParent(), MRE); 312210944Sjkim} 313210944Sjkim 314210944Sjkimbool ARMMachObjectWriter::requiresExternRelocation(MachObjectWriter *Writer, 315210944Sjkim const MCAssembler &Asm, 316210944Sjkim const MCFragment &Fragment, 317210944Sjkim unsigned RelocType, 318210944Sjkim const MCSymbolData *SD, 319210944Sjkim uint64_t FixedValue) { 320210944Sjkim // Most cases can be identified purely from the symbol. 321210944Sjkim if (Writer->doesSymbolRequireExternRelocation(SD)) 322210944Sjkim return true; 323210944Sjkim int64_t Value = (int64_t)FixedValue; // The displacement is signed. 324210944Sjkim int64_t Range; 325210944Sjkim switch (RelocType) { 326210944Sjkim default: 327210944Sjkim return false; 328210944Sjkim case MachO::ARM_RELOC_BR24: 329210944Sjkim // PC pre-adjustment of 8 for these instructions. 330210944Sjkim Value -= 8; 331210944Sjkim // ARM BL/BLX has a 25-bit offset. 332210944Sjkim Range = 0x1ffffff; 333210944Sjkim break; 334210944Sjkim case MachO::ARM_THUMB_RELOC_BR22: 335210944Sjkim // PC pre-adjustment of 4 for these instructions. 336210944Sjkim Value -= 4; 337210944Sjkim // Thumb BL/BLX has a 24-bit offset. 338210944Sjkim Range = 0xffffff; 339210944Sjkim } 340210944Sjkim // BL/BLX also use external relocations when an internal relocation 341210944Sjkim // would result in the target being out of range. This gives the linker 342210944Sjkim // enough information to generate a branch island. 343210944Sjkim const MCSectionData &SymSD = Asm.getSectionData( 344210944Sjkim SD->getSymbol().getSection()); 345210944Sjkim Value += Writer->getSectionAddress(&SymSD); 346210944Sjkim Value -= Writer->getSectionAddress(Fragment.getParent()); 347210944Sjkim // If the resultant value would be out of range for an internal relocation, 348210944Sjkim // use an external instead. 349210944Sjkim if (Value > Range || Value < -(Range + 1)) 350253690Sjkim return true; 351253690Sjkim return false; 352253690Sjkim} 353253690Sjkim 354253690Sjkimvoid ARMMachObjectWriter::RecordRelocation(MachObjectWriter *Writer, 355253690Sjkim const MCAssembler &Asm, 356253690Sjkim const MCAsmLayout &Layout, 357253690Sjkim const MCFragment *Fragment, 358253690Sjkim const MCFixup &Fixup, 359253690Sjkim MCValue Target, 360253690Sjkim uint64_t &FixedValue) { 361253690Sjkim unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 362253690Sjkim unsigned Log2Size; 363253690Sjkim unsigned RelocType = MachO::ARM_RELOC_VANILLA; 364253690Sjkim if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) 365253690Sjkim // If we failed to get fixup kind info, it's because there's no legal 366253690Sjkim // relocation type for the fixup kind. This happens when it's a fixup that's 367253690Sjkim // expected to always be resolvable at assembly time and not have any 368253690Sjkim // relocations needed. 369253690Sjkim Asm.getContext().FatalError(Fixup.getLoc(), 370253690Sjkim "unsupported relocation on symbol"); 371253690Sjkim 372253690Sjkim // If this is a difference or a defined symbol plus an offset, then we need a 373253690Sjkim // scattered relocation entry. Differences always require scattered 374253690Sjkim // relocations. 375253690Sjkim if (Target.getSymB()) { 376253690Sjkim if (RelocType == MachO::ARM_RELOC_HALF) 377253690Sjkim return RecordARMScatteredHalfRelocation(Writer, Asm, Layout, Fragment, 378253690Sjkim Fixup, Target, FixedValue); 379253690Sjkim return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 380253690Sjkim Target, Log2Size, FixedValue); 381253690Sjkim } 382253690Sjkim 383253690Sjkim // Get the symbol data, if any. 384253690Sjkim MCSymbolData *SD = 0; 385253690Sjkim if (Target.getSymA()) 386253690Sjkim SD = &Asm.getSymbolData(Target.getSymA()->getSymbol()); 387253690Sjkim 388253690Sjkim // FIXME: For other platforms, we need to use scattered relocations for 389253690Sjkim // internal relocations with offsets. If this is an internal relocation with 390253690Sjkim // an offset, it also needs a scattered relocation entry. 391253690Sjkim // 392253690Sjkim // Is this right for ARM? 393253690Sjkim uint32_t Offset = Target.getConstant(); 394253690Sjkim if (IsPCRel && RelocType == MachO::ARM_RELOC_VANILLA) 395253690Sjkim Offset += 1 << Log2Size; 396253690Sjkim if (Offset && SD && !Writer->doesSymbolRequireExternRelocation(SD)) 397253690Sjkim return RecordARMScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 398253690Sjkim Target, Log2Size, FixedValue); 399253690Sjkim 400253690Sjkim // See <reloc.h>. 401210944Sjkim uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 402210944Sjkim unsigned Index = 0; 403210944Sjkim unsigned IsExtern = 0; 404210944Sjkim unsigned Type = 0; 405210944Sjkim 406210944Sjkim if (Target.isAbsolute()) { // constant 407210944Sjkim // FIXME! 408210944Sjkim report_fatal_error("FIXME: relocations to absolute targets " 409210944Sjkim "not yet implemented"); 410210944Sjkim } else { 411210944Sjkim // Resolve constant variables. 412210944Sjkim if (SD->getSymbol().isVariable()) { 413210944Sjkim int64_t Res; 414210944Sjkim if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute( 415210944Sjkim Res, Layout, Writer->getSectionAddressMap())) { 416210944Sjkim FixedValue = Res; 417210944Sjkim return; 418210944Sjkim } 419210944Sjkim } 420210944Sjkim 421210944Sjkim // Check whether we need an external or internal relocation. 422210944Sjkim if (requiresExternRelocation(Writer, Asm, *Fragment, RelocType, SD, 423210944Sjkim FixedValue)) { 424210944Sjkim IsExtern = 1; 425210944Sjkim Index = SD->getIndex(); 426210944Sjkim 427210944Sjkim // For external relocations, make sure to offset the fixup value to 428210944Sjkim // compensate for the addend of the symbol address, if it was 429210944Sjkim // undefined. This occurs with weak definitions, for example. 430210944Sjkim if (!SD->Symbol->isUndefined()) 431210944Sjkim FixedValue -= Layout.getSymbolOffset(SD); 432210944Sjkim } else { 433210944Sjkim // The index is the section ordinal (1-based). 434210944Sjkim const MCSectionData &SymSD = Asm.getSectionData( 435210944Sjkim SD->getSymbol().getSection()); 436210944Sjkim Index = SymSD.getOrdinal() + 1; 437210944Sjkim FixedValue += Writer->getSectionAddress(&SymSD); 438210944Sjkim } 439210944Sjkim if (IsPCRel) 440210944Sjkim FixedValue -= Writer->getSectionAddress(Fragment->getParent()); 441210944Sjkim 442210944Sjkim // The type is determined by the fixup kind. 443210944Sjkim Type = RelocType; 444210944Sjkim } 445210944Sjkim 446210944Sjkim // struct relocation_info (8 bytes) 447210944Sjkim MachO::any_relocation_info MRE; 448210944Sjkim MRE.r_word0 = FixupOffset; 449210944Sjkim MRE.r_word1 = ((Index << 0) | 450210944Sjkim (IsPCRel << 24) | 451210944Sjkim (Log2Size << 25) | 452210944Sjkim (IsExtern << 27) | 453210944Sjkim (Type << 28)); 454210944Sjkim 455210944Sjkim // Even when it's not a scattered relocation, movw/movt always uses 456249112Sjkim // a PAIR relocation. 457210944Sjkim if (Type == MachO::ARM_RELOC_HALF) { 458210944Sjkim // The other-half value only gets populated for the movt and movw 459210944Sjkim // relocation entries. 460210944Sjkim uint32_t Value = 0; 461210944Sjkim switch ((unsigned)Fixup.getKind()) { 462210944Sjkim default: break; 463210944Sjkim case ARM::fixup_arm_movw_lo16: 464210944Sjkim case ARM::fixup_arm_movw_lo16_pcrel: 465210944Sjkim case ARM::fixup_t2_movw_lo16: 466210944Sjkim case ARM::fixup_t2_movw_lo16_pcrel: 467210944Sjkim Value = (FixedValue >> 16) & 0xffff; 468210944Sjkim break; 469210944Sjkim case ARM::fixup_arm_movt_hi16: 470210944Sjkim case ARM::fixup_arm_movt_hi16_pcrel: 471210944Sjkim case ARM::fixup_t2_movt_hi16: 472210944Sjkim case ARM::fixup_t2_movt_hi16_pcrel: 473210944Sjkim Value = FixedValue & 0xffff; 474210944Sjkim break; 475210944Sjkim } 476210944Sjkim MachO::any_relocation_info MREPair; 477210944Sjkim MREPair.r_word0 = Value; 478210944Sjkim MREPair.r_word1 = ((0xffffff << 0) | 479210944Sjkim (Log2Size << 25) | 480210944Sjkim (MachO::ARM_RELOC_PAIR << 28)); 481210944Sjkim 482210944Sjkim Writer->addRelocation(Fragment->getParent(), MREPair); 483249112Sjkim } 484249112Sjkim 485249112Sjkim Writer->addRelocation(Fragment->getParent(), MRE); 486249663Sjkim} 487249112Sjkim 488249112SjkimMCObjectWriter *llvm::createARMMachObjectWriter(raw_ostream &OS, 489210944Sjkim bool Is64Bit, 490210944Sjkim uint32_t CPUType, 491210944Sjkim uint32_t CPUSubtype) { 492210944Sjkim return createMachObjectWriter(new ARMMachObjectWriter(Is64Bit, 493210944Sjkim CPUType, 494210944Sjkim CPUSubtype), 495210944Sjkim OS, /*IsLittleEndian=*/true); 496210944Sjkim} 497210944Sjkim