1 //===-- X86MachObjectWriter.cpp - X86 Mach-O Writer -----------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "MCTargetDesc/X86FixupKinds.h" 11 #include "MCTargetDesc/X86MCTargetDesc.h" 12 #include "llvm/ADT/Twine.h" 13 #include "llvm/BinaryFormat/MachO.h" 14 #include "llvm/MC/MCAsmInfo.h" 15 #include "llvm/MC/MCAsmLayout.h" 16 #include "llvm/MC/MCAssembler.h" 17 #include "llvm/MC/MCContext.h" 18 #include "llvm/MC/MCMachObjectWriter.h" 19 #include "llvm/MC/MCSectionMachO.h" 20 #include "llvm/MC/MCValue.h" 21 #include "llvm/Support/ErrorHandling.h" 22 #include "llvm/Support/Format.h" 23 24 using namespace llvm; 25 26 namespace { 27 class X86MachObjectWriter : public MCMachObjectTargetWriter { 28 bool recordScatteredRelocation(MachObjectWriter *Writer, 29 const MCAssembler &Asm, 30 const MCAsmLayout &Layout, 31 const MCFragment *Fragment, 32 const MCFixup &Fixup, 33 MCValue Target, 34 unsigned Log2Size, 35 uint64_t &FixedValue); 36 void recordTLVPRelocation(MachObjectWriter *Writer, 37 const MCAssembler &Asm, 38 const MCAsmLayout &Layout, 39 const MCFragment *Fragment, 40 const MCFixup &Fixup, 41 MCValue Target, 42 uint64_t &FixedValue); 43 44 void RecordX86Relocation(MachObjectWriter *Writer, 45 const MCAssembler &Asm, 46 const MCAsmLayout &Layout, 47 const MCFragment *Fragment, 48 const MCFixup &Fixup, 49 MCValue Target, 50 uint64_t &FixedValue); 51 void RecordX86_64Relocation(MachObjectWriter *Writer, MCAssembler &Asm, 52 const MCAsmLayout &Layout, 53 const MCFragment *Fragment, const MCFixup &Fixup, 54 MCValue Target, uint64_t &FixedValue); 55 56 public: 57 X86MachObjectWriter(bool Is64Bit, uint32_t CPUType, uint32_t CPUSubtype) 58 : MCMachObjectTargetWriter(Is64Bit, CPUType, CPUSubtype) {} 59 60 void recordRelocation(MachObjectWriter *Writer, MCAssembler &Asm, 61 const MCAsmLayout &Layout, const MCFragment *Fragment, 62 const MCFixup &Fixup, MCValue Target, 63 uint64_t &FixedValue) override { 64 if (Writer->is64Bit()) 65 RecordX86_64Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, 66 FixedValue); 67 else 68 RecordX86Relocation(Writer, Asm, Layout, Fragment, Fixup, Target, 69 FixedValue); 70 } 71 }; 72 } 73 74 static bool isFixupKindRIPRel(unsigned Kind) { 75 return Kind == X86::reloc_riprel_4byte || 76 Kind == X86::reloc_riprel_4byte_movq_load || 77 Kind == X86::reloc_riprel_4byte_relax || 78 Kind == X86::reloc_riprel_4byte_relax_rex; 79 } 80 81 static unsigned getFixupKindLog2Size(unsigned Kind) { 82 switch (Kind) { 83 default: 84 llvm_unreachable("invalid fixup kind!"); 85 case FK_PCRel_1: 86 case FK_Data_1: return 0; 87 case FK_PCRel_2: 88 case FK_Data_2: return 1; 89 case FK_PCRel_4: 90 // FIXME: Remove these!!! 91 case X86::reloc_riprel_4byte: 92 case X86::reloc_riprel_4byte_relax: 93 case X86::reloc_riprel_4byte_relax_rex: 94 case X86::reloc_riprel_4byte_movq_load: 95 case X86::reloc_signed_4byte: 96 case X86::reloc_signed_4byte_relax: 97 case FK_Data_4: return 2; 98 case FK_Data_8: return 3; 99 } 100 } 101 102 void X86MachObjectWriter::RecordX86_64Relocation( 103 MachObjectWriter *Writer, MCAssembler &Asm, const MCAsmLayout &Layout, 104 const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, 105 uint64_t &FixedValue) { 106 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 107 unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind()); 108 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); 109 110 // See <reloc.h>. 111 uint32_t FixupOffset = 112 Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); 113 uint32_t FixupAddress = 114 Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); 115 int64_t Value = 0; 116 unsigned Index = 0; 117 unsigned IsExtern = 0; 118 unsigned Type = 0; 119 const MCSymbol *RelSymbol = nullptr; 120 121 Value = Target.getConstant(); 122 123 if (IsPCRel) { 124 // Compensate for the relocation offset, Darwin x86_64 relocations only have 125 // the addend and appear to have attempted to define it to be the actual 126 // expression addend without the PCrel bias. However, instructions with data 127 // following the relocation are not accommodated for (see comment below 128 // regarding SIGNED{1,2,4}), so it isn't exactly that either. 129 Value += 1LL << Log2Size; 130 } 131 132 if (Target.isAbsolute()) { // constant 133 // SymbolNum of 0 indicates the absolute section. 134 Type = MachO::X86_64_RELOC_UNSIGNED; 135 136 // FIXME: I believe this is broken, I don't think the linker can understand 137 // it. I think it would require a local relocation, but I'm not sure if that 138 // would work either. The official way to get an absolute PCrel relocation 139 // is to use an absolute symbol (which we don't support yet). 140 if (IsPCRel) { 141 IsExtern = 1; 142 Type = MachO::X86_64_RELOC_BRANCH; 143 } 144 } else if (Target.getSymB()) { // A - B + constant 145 const MCSymbol *A = &Target.getSymA()->getSymbol(); 146 if (A->isTemporary()) 147 A = &Writer->findAliasedSymbol(*A); 148 const MCSymbol *A_Base = Asm.getAtom(*A); 149 150 const MCSymbol *B = &Target.getSymB()->getSymbol(); 151 if (B->isTemporary()) 152 B = &Writer->findAliasedSymbol(*B); 153 const MCSymbol *B_Base = Asm.getAtom(*B); 154 155 // Neither symbol can be modified. 156 if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None) { 157 Asm.getContext().reportError(Fixup.getLoc(), 158 "unsupported relocation of modified symbol"); 159 return; 160 } 161 162 // We don't support PCrel relocations of differences. Darwin 'as' doesn't 163 // implement most of these correctly. 164 if (IsPCRel) { 165 Asm.getContext().reportError( 166 Fixup.getLoc(), "unsupported pc-relative relocation of difference"); 167 return; 168 } 169 170 // The support for the situation where one or both of the symbols would 171 // require a local relocation is handled just like if the symbols were 172 // external. This is certainly used in the case of debug sections where the 173 // section has only temporary symbols and thus the symbols don't have base 174 // symbols. This is encoded using the section ordinal and non-extern 175 // relocation entries. 176 177 // Darwin 'as' doesn't emit correct relocations for this (it ends up with a 178 // single SIGNED relocation); reject it for now. Except the case where both 179 // symbols don't have a base, equal but both NULL. 180 if (A_Base == B_Base && A_Base) { 181 Asm.getContext().reportError( 182 Fixup.getLoc(), "unsupported relocation with identical base"); 183 return; 184 } 185 186 // A subtraction expression where either symbol is undefined is a 187 // non-relocatable expression. 188 if (A->isUndefined() || B->isUndefined()) { 189 StringRef Name = A->isUndefined() ? A->getName() : B->getName(); 190 Asm.getContext().reportError(Fixup.getLoc(), 191 "unsupported relocation with subtraction expression, symbol '" + 192 Name + "' can not be undefined in a subtraction expression"); 193 return; 194 } 195 196 Value += Writer->getSymbolAddress(*A, Layout) - 197 (!A_Base ? 0 : Writer->getSymbolAddress(*A_Base, Layout)); 198 Value -= Writer->getSymbolAddress(*B, Layout) - 199 (!B_Base ? 0 : Writer->getSymbolAddress(*B_Base, Layout)); 200 201 if (!A_Base) 202 Index = A->getFragment()->getParent()->getOrdinal() + 1; 203 Type = MachO::X86_64_RELOC_UNSIGNED; 204 205 MachO::any_relocation_info MRE; 206 MRE.r_word0 = FixupOffset; 207 MRE.r_word1 = 208 (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28); 209 Writer->addRelocation(A_Base, Fragment->getParent(), MRE); 210 211 if (B_Base) 212 RelSymbol = B_Base; 213 else 214 Index = B->getFragment()->getParent()->getOrdinal() + 1; 215 Type = MachO::X86_64_RELOC_SUBTRACTOR; 216 } else { 217 const MCSymbol *Symbol = &Target.getSymA()->getSymbol(); 218 if (Symbol->isTemporary() && Value) { 219 const MCSection &Sec = Symbol->getSection(); 220 if (!Asm.getContext().getAsmInfo()->isSectionAtomizableBySymbols(Sec)) 221 Symbol->setUsedInReloc(); 222 } 223 RelSymbol = Asm.getAtom(*Symbol); 224 225 // Relocations inside debug sections always use local relocations when 226 // possible. This seems to be done because the debugger doesn't fully 227 // understand x86_64 relocation entries, and expects to find values that 228 // have already been fixed up. 229 if (Symbol->isInSection()) { 230 const MCSectionMachO &Section = 231 static_cast<const MCSectionMachO &>(*Fragment->getParent()); 232 if (Section.hasAttribute(MachO::S_ATTR_DEBUG)) 233 RelSymbol = nullptr; 234 } 235 236 // x86_64 almost always uses external relocations, except when there is no 237 // symbol to use as a base address (a local symbol with no preceding 238 // non-local symbol). 239 if (RelSymbol) { 240 // Add the local offset, if needed. 241 if (RelSymbol != Symbol) 242 Value += Layout.getSymbolOffset(*Symbol) - 243 Layout.getSymbolOffset(*RelSymbol); 244 } else if (Symbol->isInSection() && !Symbol->isVariable()) { 245 // The index is the section ordinal (1-based). 246 Index = Symbol->getFragment()->getParent()->getOrdinal() + 1; 247 Value += Writer->getSymbolAddress(*Symbol, Layout); 248 249 if (IsPCRel) 250 Value -= FixupAddress + (1 << Log2Size); 251 } else if (Symbol->isVariable()) { 252 const MCExpr *Value = Symbol->getVariableValue(); 253 int64_t Res; 254 bool isAbs = Value->evaluateAsAbsolute(Res, Layout, 255 Writer->getSectionAddressMap()); 256 if (isAbs) { 257 FixedValue = Res; 258 return; 259 } else { 260 Asm.getContext().reportError(Fixup.getLoc(), 261 "unsupported relocation of variable '" + 262 Symbol->getName() + "'"); 263 return; 264 } 265 } else { 266 Asm.getContext().reportError( 267 Fixup.getLoc(), "unsupported relocation of undefined symbol '" + 268 Symbol->getName() + "'"); 269 return; 270 } 271 272 MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind(); 273 if (IsPCRel) { 274 if (IsRIPRel) { 275 if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { 276 // x86_64 distinguishes movq foo@GOTPCREL so that the linker can 277 // rewrite the movq to an leaq at link time if the symbol ends up in 278 // the same linkage unit. 279 if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load) 280 Type = MachO::X86_64_RELOC_GOT_LOAD; 281 else 282 Type = MachO::X86_64_RELOC_GOT; 283 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { 284 Type = MachO::X86_64_RELOC_TLV; 285 } else if (Modifier != MCSymbolRefExpr::VK_None) { 286 Asm.getContext().reportError( 287 Fixup.getLoc(), "unsupported symbol modifier in relocation"); 288 return; 289 } else { 290 Type = MachO::X86_64_RELOC_SIGNED; 291 292 // The Darwin x86_64 relocation format has a problem where it cannot 293 // encode an address (L<foo> + <constant>) which is outside the atom 294 // containing L<foo>. Generally, this shouldn't occur but it does 295 // happen when we have a RIPrel instruction with data following the 296 // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel 297 // adjustment Darwin x86_64 uses, the offset is still negative and the 298 // linker has no way to recognize this. 299 // 300 // To work around this, Darwin uses several special relocation types 301 // to indicate the offsets. However, the specification or 302 // implementation of these seems to also be incomplete; they should 303 // adjust the addend as well based on the actual encoded instruction 304 // (the additional bias), but instead appear to just look at the final 305 // offset. 306 switch (-(Target.getConstant() + (1LL << Log2Size))) { 307 case 1: Type = MachO::X86_64_RELOC_SIGNED_1; break; 308 case 2: Type = MachO::X86_64_RELOC_SIGNED_2; break; 309 case 4: Type = MachO::X86_64_RELOC_SIGNED_4; break; 310 } 311 } 312 } else { 313 if (Modifier != MCSymbolRefExpr::VK_None) { 314 Asm.getContext().reportError( 315 Fixup.getLoc(), 316 "unsupported symbol modifier in branch relocation"); 317 return; 318 } 319 320 Type = MachO::X86_64_RELOC_BRANCH; 321 } 322 } else { 323 if (Modifier == MCSymbolRefExpr::VK_GOT) { 324 Type = MachO::X86_64_RELOC_GOT; 325 } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) { 326 // GOTPCREL is allowed as a modifier on non-PCrel instructions, in which 327 // case all we do is set the PCrel bit in the relocation entry; this is 328 // used with exception handling, for example. The source is required to 329 // include any necessary offset directly. 330 Type = MachO::X86_64_RELOC_GOT; 331 IsPCRel = 1; 332 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) { 333 Asm.getContext().reportError( 334 Fixup.getLoc(), "TLVP symbol modifier should have been rip-rel"); 335 return; 336 } else if (Modifier != MCSymbolRefExpr::VK_None) { 337 Asm.getContext().reportError( 338 Fixup.getLoc(), "unsupported symbol modifier in relocation"); 339 return; 340 } else { 341 Type = MachO::X86_64_RELOC_UNSIGNED; 342 unsigned Kind = Fixup.getKind(); 343 if (Kind == X86::reloc_signed_4byte) { 344 Asm.getContext().reportError( 345 Fixup.getLoc(), 346 "32-bit absolute addressing is not supported in 64-bit mode"); 347 return; 348 } 349 } 350 } 351 } 352 353 // x86_64 always writes custom values into the fixups. 354 FixedValue = Value; 355 356 // struct relocation_info (8 bytes) 357 MachO::any_relocation_info MRE; 358 MRE.r_word0 = FixupOffset; 359 MRE.r_word1 = (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | 360 (IsExtern << 27) | (Type << 28); 361 Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); 362 } 363 364 bool X86MachObjectWriter::recordScatteredRelocation(MachObjectWriter *Writer, 365 const MCAssembler &Asm, 366 const MCAsmLayout &Layout, 367 const MCFragment *Fragment, 368 const MCFixup &Fixup, 369 MCValue Target, 370 unsigned Log2Size, 371 uint64_t &FixedValue) { 372 uint64_t OriginalFixedValue = FixedValue; 373 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 374 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 375 unsigned Type = MachO::GENERIC_RELOC_VANILLA; 376 377 // See <reloc.h>. 378 const MCSymbol *A = &Target.getSymA()->getSymbol(); 379 380 if (!A->getFragment()) { 381 Asm.getContext().reportError( 382 Fixup.getLoc(), 383 "symbol '" + A->getName() + 384 "' can not be undefined in a subtraction expression"); 385 return false; 386 } 387 388 uint32_t Value = Writer->getSymbolAddress(*A, Layout); 389 uint64_t SecAddr = Writer->getSectionAddress(A->getFragment()->getParent()); 390 FixedValue += SecAddr; 391 uint32_t Value2 = 0; 392 393 if (const MCSymbolRefExpr *B = Target.getSymB()) { 394 const MCSymbol *SB = &B->getSymbol(); 395 396 if (!SB->getFragment()) { 397 Asm.getContext().reportError( 398 Fixup.getLoc(), 399 "symbol '" + B->getSymbol().getName() + 400 "' can not be undefined in a subtraction expression"); 401 return false; 402 } 403 404 // Select the appropriate difference relocation type. 405 // 406 // Note that there is no longer any semantic difference between these two 407 // relocation types from the linkers point of view, this is done solely for 408 // pedantic compatibility with 'as'. 409 Type = A->isExternal() ? (unsigned)MachO::GENERIC_RELOC_SECTDIFF 410 : (unsigned)MachO::GENERIC_RELOC_LOCAL_SECTDIFF; 411 Value2 = Writer->getSymbolAddress(B->getSymbol(), Layout); 412 FixedValue -= Writer->getSectionAddress(SB->getFragment()->getParent()); 413 } 414 415 // Relocations are written out in reverse order, so the PAIR comes first. 416 if (Type == MachO::GENERIC_RELOC_SECTDIFF || 417 Type == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) { 418 // If the offset is too large to fit in a scattered relocation, 419 // we're hosed. It's an unfortunate limitation of the MachO format. 420 if (FixupOffset > 0xffffff) { 421 char Buffer[32]; 422 format("0x%x", FixupOffset).print(Buffer, sizeof(Buffer)); 423 Asm.getContext().reportError(Fixup.getLoc(), 424 Twine("Section too large, can't encode " 425 "r_address (") + Buffer + 426 ") into 24 bits of scattered " 427 "relocation entry."); 428 return false; 429 } 430 431 MachO::any_relocation_info MRE; 432 MRE.r_word0 = ((0 << 0) | // r_address 433 (MachO::GENERIC_RELOC_PAIR << 24) | // r_type 434 (Log2Size << 28) | 435 (IsPCRel << 30) | 436 MachO::R_SCATTERED); 437 MRE.r_word1 = Value2; 438 Writer->addRelocation(nullptr, Fragment->getParent(), MRE); 439 } else { 440 // If the offset is more than 24-bits, it won't fit in a scattered 441 // relocation offset field, so we fall back to using a non-scattered 442 // relocation. This is a bit risky, as if the offset reaches out of 443 // the block and the linker is doing scattered loading on this 444 // symbol, things can go badly. 445 // 446 // Required for 'as' compatibility. 447 if (FixupOffset > 0xffffff) { 448 FixedValue = OriginalFixedValue; 449 return false; 450 } 451 } 452 453 MachO::any_relocation_info MRE; 454 MRE.r_word0 = ((FixupOffset << 0) | 455 (Type << 24) | 456 (Log2Size << 28) | 457 (IsPCRel << 30) | 458 MachO::R_SCATTERED); 459 MRE.r_word1 = Value; 460 Writer->addRelocation(nullptr, Fragment->getParent(), MRE); 461 return true; 462 } 463 464 void X86MachObjectWriter::recordTLVPRelocation(MachObjectWriter *Writer, 465 const MCAssembler &Asm, 466 const MCAsmLayout &Layout, 467 const MCFragment *Fragment, 468 const MCFixup &Fixup, 469 MCValue Target, 470 uint64_t &FixedValue) { 471 assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP && 472 !is64Bit() && 473 "Should only be called with a 32-bit TLVP relocation!"); 474 475 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); 476 uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 477 unsigned IsPCRel = 0; 478 479 // We're only going to have a second symbol in pic mode and it'll be a 480 // subtraction from the picbase. For 32-bit pic the addend is the difference 481 // between the picbase and the next address. For 32-bit static the addend is 482 // zero. 483 if (Target.getSymB()) { 484 // If this is a subtraction then we're pcrel. 485 uint32_t FixupAddress = 486 Writer->getFragmentAddress(Fragment, Layout) + Fixup.getOffset(); 487 IsPCRel = 1; 488 FixedValue = 489 FixupAddress - 490 Writer->getSymbolAddress(Target.getSymB()->getSymbol(), Layout) + 491 Target.getConstant(); 492 FixedValue += 1ULL << Log2Size; 493 } else { 494 FixedValue = 0; 495 } 496 497 // struct relocation_info (8 bytes) 498 MachO::any_relocation_info MRE; 499 MRE.r_word0 = Value; 500 MRE.r_word1 = 501 (IsPCRel << 24) | (Log2Size << 25) | (MachO::GENERIC_RELOC_TLV << 28); 502 Writer->addRelocation(&Target.getSymA()->getSymbol(), Fragment->getParent(), 503 MRE); 504 } 505 506 void X86MachObjectWriter::RecordX86Relocation(MachObjectWriter *Writer, 507 const MCAssembler &Asm, 508 const MCAsmLayout &Layout, 509 const MCFragment *Fragment, 510 const MCFixup &Fixup, 511 MCValue Target, 512 uint64_t &FixedValue) { 513 unsigned IsPCRel = Writer->isFixupKindPCRel(Asm, Fixup.getKind()); 514 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind()); 515 516 // If this is a 32-bit TLVP reloc it's handled a bit differently. 517 if (Target.getSymA() && 518 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) { 519 recordTLVPRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, 520 FixedValue); 521 return; 522 } 523 524 // If this is a difference or a defined symbol plus an offset, then we need a 525 // scattered relocation entry. Differences always require scattered 526 // relocations. 527 if (Target.getSymB()) { 528 recordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, 529 Target, Log2Size, FixedValue); 530 return; 531 } 532 533 // Get the symbol data, if any. 534 const MCSymbol *A = nullptr; 535 if (Target.getSymA()) 536 A = &Target.getSymA()->getSymbol(); 537 538 // If this is an internal relocation with an offset, it also needs a scattered 539 // relocation entry. 540 uint32_t Offset = Target.getConstant(); 541 if (IsPCRel) 542 Offset += 1 << Log2Size; 543 // Try to record the scattered relocation if needed. Fall back to non 544 // scattered if necessary (see comments in recordScatteredRelocation() 545 // for details). 546 if (Offset && A && !Writer->doesSymbolRequireExternRelocation(*A) && 547 recordScatteredRelocation(Writer, Asm, Layout, Fragment, Fixup, Target, 548 Log2Size, FixedValue)) 549 return; 550 551 // See <reloc.h>. 552 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset(); 553 unsigned Index = 0; 554 unsigned Type = 0; 555 const MCSymbol *RelSymbol = nullptr; 556 557 if (Target.isAbsolute()) { // constant 558 // SymbolNum of 0 indicates the absolute section. 559 // 560 // FIXME: Currently, these are never generated (see code below). I cannot 561 // find a case where they are actually emitted. 562 Type = MachO::GENERIC_RELOC_VANILLA; 563 } else { 564 // Resolve constant variables. 565 if (A->isVariable()) { 566 int64_t Res; 567 if (A->getVariableValue()->evaluateAsAbsolute( 568 Res, Layout, Writer->getSectionAddressMap())) { 569 FixedValue = Res; 570 return; 571 } 572 } 573 574 // Check whether we need an external or internal relocation. 575 if (Writer->doesSymbolRequireExternRelocation(*A)) { 576 RelSymbol = A; 577 // For external relocations, make sure to offset the fixup value to 578 // compensate for the addend of the symbol address, if it was 579 // undefined. This occurs with weak definitions, for example. 580 if (!A->isUndefined()) 581 FixedValue -= Layout.getSymbolOffset(*A); 582 } else { 583 // The index is the section ordinal (1-based). 584 const MCSection &Sec = A->getSection(); 585 Index = Sec.getOrdinal() + 1; 586 FixedValue += Writer->getSectionAddress(&Sec); 587 } 588 if (IsPCRel) 589 FixedValue -= Writer->getSectionAddress(Fragment->getParent()); 590 591 Type = MachO::GENERIC_RELOC_VANILLA; 592 } 593 594 // struct relocation_info (8 bytes) 595 MachO::any_relocation_info MRE; 596 MRE.r_word0 = FixupOffset; 597 MRE.r_word1 = 598 (Index << 0) | (IsPCRel << 24) | (Log2Size << 25) | (Type << 28); 599 Writer->addRelocation(RelSymbol, Fragment->getParent(), MRE); 600 } 601 602 MCObjectWriter *llvm::createX86MachObjectWriter(raw_pwrite_stream &OS, 603 bool Is64Bit, uint32_t CPUType, 604 uint32_t CPUSubtype) { 605 return createMachObjectWriter(new X86MachObjectWriter(Is64Bit, 606 CPUType, 607 CPUSubtype), 608 OS, /*IsLittleEndian=*/true); 609 } 610