1 //===- lib/FileFormat/MachO/ArchHandler_x86.cpp ---------------------------===// 2 // 3 // The LLVM Linker 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 "ArchHandler.h" 11 #include "Atoms.h" 12 #include "MachONormalizedFileBinaryUtils.h" 13 #include "llvm/ADT/StringRef.h" 14 #include "llvm/ADT/StringSwitch.h" 15 #include "llvm/ADT/Triple.h" 16 #include "llvm/Support/Endian.h" 17 #include "llvm/Support/ErrorHandling.h" 18 19 using namespace llvm::MachO; 20 using namespace lld::mach_o::normalized; 21 22 namespace lld { 23 namespace mach_o { 24 25 using llvm::support::ulittle16_t; 26 using llvm::support::ulittle32_t; 27 28 using llvm::support::little16_t; 29 using llvm::support::little32_t; 30 31 class ArchHandler_x86 : public ArchHandler { 32 public: 33 ArchHandler_x86() = default; 34 ~ArchHandler_x86() override = default; 35 36 const Registry::KindStrings *kindStrings() override { return _sKindStrings; } 37 38 Reference::KindArch kindArch() override { return Reference::KindArch::x86; } 39 40 const StubInfo &stubInfo() override { return _sStubInfo; } 41 bool isCallSite(const Reference &) override; 42 bool isNonCallBranch(const Reference &) override { 43 return false; 44 } 45 46 bool isPointer(const Reference &) override; 47 bool isPairedReloc(const normalized::Relocation &) override; 48 49 bool needsCompactUnwind() override { 50 return false; 51 } 52 53 Reference::KindValue imageOffsetKind() override { 54 return invalid; 55 } 56 57 Reference::KindValue imageOffsetKindIndirect() override { 58 return invalid; 59 } 60 61 Reference::KindValue unwindRefToPersonalityFunctionKind() override { 62 return invalid; 63 } 64 65 Reference::KindValue unwindRefToCIEKind() override { 66 return negDelta32; 67 } 68 69 Reference::KindValue unwindRefToFunctionKind() override{ 70 return delta32; 71 } 72 73 Reference::KindValue unwindRefToEhFrameKind() override { 74 return invalid; 75 } 76 77 Reference::KindValue pointerKind() override { 78 return invalid; 79 } 80 81 uint32_t dwarfCompactUnwindType() override { 82 return 0x04000000U; 83 } 84 85 llvm::Error getReferenceInfo(const normalized::Relocation &reloc, 86 const DefinedAtom *inAtom, 87 uint32_t offsetInAtom, 88 uint64_t fixupAddress, bool swap, 89 FindAtomBySectionAndAddress atomFromAddress, 90 FindAtomBySymbolIndex atomFromSymbolIndex, 91 Reference::KindValue *kind, 92 const lld::Atom **target, 93 Reference::Addend *addend) override; 94 llvm::Error 95 getPairReferenceInfo(const normalized::Relocation &reloc1, 96 const normalized::Relocation &reloc2, 97 const DefinedAtom *inAtom, 98 uint32_t offsetInAtom, 99 uint64_t fixupAddress, bool swap, bool scatterable, 100 FindAtomBySectionAndAddress atomFromAddress, 101 FindAtomBySymbolIndex atomFromSymbolIndex, 102 Reference::KindValue *kind, 103 const lld::Atom **target, 104 Reference::Addend *addend) override; 105 106 void generateAtomContent(const DefinedAtom &atom, bool relocatable, 107 FindAddressForAtom findAddress, 108 FindAddressForAtom findSectionAddress, 109 uint64_t imageBaseAddress, 110 llvm::MutableArrayRef<uint8_t> atomContentBuffer) override; 111 112 void appendSectionRelocations(const DefinedAtom &atom, 113 uint64_t atomSectionOffset, 114 const Reference &ref, 115 FindSymbolIndexForAtom symbolIndexForAtom, 116 FindSectionIndexForAtom sectionIndexForAtom, 117 FindAddressForAtom addressForAtom, 118 normalized::Relocations &relocs) override; 119 120 bool isDataInCodeTransition(Reference::KindValue refKind) override { 121 switch (refKind) { 122 case modeCode: 123 case modeData: 124 return true; 125 default: 126 return false; 127 break; 128 } 129 } 130 131 Reference::KindValue dataInCodeTransitionStart( 132 const MachODefinedAtom &atom) override { 133 return modeData; 134 } 135 136 Reference::KindValue dataInCodeTransitionEnd( 137 const MachODefinedAtom &atom) override { 138 return modeCode; 139 } 140 141 private: 142 static const Registry::KindStrings _sKindStrings[]; 143 static const StubInfo _sStubInfo; 144 145 enum X86Kind : Reference::KindValue { 146 invalid, /// for error condition 147 148 modeCode, /// Content starting at this offset is code. 149 modeData, /// Content starting at this offset is data. 150 151 // Kinds found in mach-o .o files: 152 branch32, /// ex: call _foo 153 branch16, /// ex: callw _foo 154 abs32, /// ex: movl _foo, %eax 155 funcRel32, /// ex: movl _foo-L1(%eax), %eax 156 pointer32, /// ex: .long _foo 157 delta32, /// ex: .long _foo - . 158 negDelta32, /// ex: .long . - _foo 159 160 // Kinds introduced by Passes: 161 lazyPointer, /// Location contains a lazy pointer. 162 lazyImmediateLocation, /// Location contains immediate value used in stub. 163 }; 164 165 static bool useExternalRelocationTo(const Atom &target); 166 167 void applyFixupFinal(const Reference &ref, uint8_t *location, 168 uint64_t fixupAddress, uint64_t targetAddress, 169 uint64_t inAtomAddress); 170 171 void applyFixupRelocatable(const Reference &ref, uint8_t *location, 172 uint64_t fixupAddress, 173 uint64_t targetAddress, 174 uint64_t inAtomAddress); 175 }; 176 177 //===----------------------------------------------------------------------===// 178 // ArchHandler_x86 179 //===----------------------------------------------------------------------===// 180 181 const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = { 182 LLD_KIND_STRING_ENTRY(invalid), 183 LLD_KIND_STRING_ENTRY(modeCode), 184 LLD_KIND_STRING_ENTRY(modeData), 185 LLD_KIND_STRING_ENTRY(branch32), 186 LLD_KIND_STRING_ENTRY(branch16), 187 LLD_KIND_STRING_ENTRY(abs32), 188 LLD_KIND_STRING_ENTRY(funcRel32), 189 LLD_KIND_STRING_ENTRY(pointer32), 190 LLD_KIND_STRING_ENTRY(delta32), 191 LLD_KIND_STRING_ENTRY(negDelta32), 192 LLD_KIND_STRING_ENTRY(lazyPointer), 193 LLD_KIND_STRING_ENTRY(lazyImmediateLocation), 194 LLD_KIND_STRING_END 195 }; 196 197 const ArchHandler::StubInfo ArchHandler_x86::_sStubInfo = { 198 "dyld_stub_binder", 199 200 // Lazy pointer references 201 { Reference::KindArch::x86, pointer32, 0, 0 }, 202 { Reference::KindArch::x86, lazyPointer, 0, 0 }, 203 204 // GOT pointer to dyld_stub_binder 205 { Reference::KindArch::x86, pointer32, 0, 0 }, 206 207 // x86 code alignment 208 1, 209 210 // Stub size and code 211 6, 212 { 0xff, 0x25, 0x00, 0x00, 0x00, 0x00 }, // jmp *lazyPointer 213 { Reference::KindArch::x86, abs32, 2, 0 }, 214 { false, 0, 0, 0 }, 215 216 // Stub Helper size and code 217 10, 218 { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $lazy-info-offset 219 0xE9, 0x00, 0x00, 0x00, 0x00 }, // jmp helperhelper 220 { Reference::KindArch::x86, lazyImmediateLocation, 1, 0 }, 221 { Reference::KindArch::x86, branch32, 6, 0 }, 222 223 // Stub helper image cache content type 224 DefinedAtom::typeNonLazyPointer, 225 226 // Stub Helper-Common size and code 227 12, 228 // Stub helper alignment 229 2, 230 { 0x68, 0x00, 0x00, 0x00, 0x00, // pushl $dyld_ImageLoaderCache 231 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, // jmp *_fast_lazy_bind 232 0x90 }, // nop 233 { Reference::KindArch::x86, abs32, 1, 0 }, 234 { false, 0, 0, 0 }, 235 { Reference::KindArch::x86, abs32, 7, 0 }, 236 { false, 0, 0, 0 } 237 }; 238 239 bool ArchHandler_x86::isCallSite(const Reference &ref) { 240 return (ref.kindValue() == branch32); 241 } 242 243 bool ArchHandler_x86::isPointer(const Reference &ref) { 244 return (ref.kindValue() == pointer32); 245 } 246 247 bool ArchHandler_x86::isPairedReloc(const Relocation &reloc) { 248 if (!reloc.scattered) 249 return false; 250 return (reloc.type == GENERIC_RELOC_LOCAL_SECTDIFF) || 251 (reloc.type == GENERIC_RELOC_SECTDIFF); 252 } 253 254 llvm::Error 255 ArchHandler_x86::getReferenceInfo(const Relocation &reloc, 256 const DefinedAtom *inAtom, 257 uint32_t offsetInAtom, 258 uint64_t fixupAddress, bool swap, 259 FindAtomBySectionAndAddress atomFromAddress, 260 FindAtomBySymbolIndex atomFromSymbolIndex, 261 Reference::KindValue *kind, 262 const lld::Atom **target, 263 Reference::Addend *addend) { 264 DefinedAtom::ContentPermissions perms; 265 const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; 266 uint64_t targetAddress; 267 switch (relocPattern(reloc)) { 268 case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength4: 269 // ex: call _foo (and _foo undefined) 270 *kind = branch32; 271 if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) 272 return ec; 273 *addend = fixupAddress + 4 + (int32_t)*(const little32_t *)fixupContent; 274 break; 275 case GENERIC_RELOC_VANILLA | rPcRel | rLength4: 276 // ex: call _foo (and _foo defined) 277 *kind = branch32; 278 targetAddress = 279 fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent; 280 return atomFromAddress(reloc.symbol, targetAddress, target, addend); 281 break; 282 case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4: 283 // ex: call _foo+n (and _foo defined) 284 *kind = branch32; 285 targetAddress = 286 fixupAddress + 4 + (int32_t) * (const little32_t *)fixupContent; 287 if (auto ec = atomFromAddress(0, reloc.value, target, addend)) 288 return ec; 289 *addend = targetAddress - reloc.value; 290 break; 291 case GENERIC_RELOC_VANILLA | rPcRel | rExtern | rLength2: 292 // ex: callw _foo (and _foo undefined) 293 *kind = branch16; 294 if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) 295 return ec; 296 *addend = fixupAddress + 2 + (int16_t)*(const little16_t *)fixupContent; 297 break; 298 case GENERIC_RELOC_VANILLA | rPcRel | rLength2: 299 // ex: callw _foo (and _foo defined) 300 *kind = branch16; 301 targetAddress = 302 fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent; 303 return atomFromAddress(reloc.symbol, targetAddress, target, addend); 304 break; 305 case GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2: 306 // ex: callw _foo+n (and _foo defined) 307 *kind = branch16; 308 targetAddress = 309 fixupAddress + 2 + (int16_t) * (const little16_t *)fixupContent; 310 if (auto ec = atomFromAddress(0, reloc.value, target, addend)) 311 return ec; 312 *addend = targetAddress - reloc.value; 313 break; 314 case GENERIC_RELOC_VANILLA | rExtern | rLength4: 315 // ex: movl _foo, %eax (and _foo undefined) 316 // ex: .long _foo (and _foo undefined) 317 perms = inAtom->permissions(); 318 *kind = 319 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32 320 : pointer32; 321 if (auto ec = atomFromSymbolIndex(reloc.symbol, target)) 322 return ec; 323 *addend = *(const ulittle32_t *)fixupContent; 324 break; 325 case GENERIC_RELOC_VANILLA | rLength4: 326 // ex: movl _foo, %eax (and _foo defined) 327 // ex: .long _foo (and _foo defined) 328 perms = inAtom->permissions(); 329 *kind = 330 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32 331 : pointer32; 332 targetAddress = *(const ulittle32_t *)fixupContent; 333 return atomFromAddress(reloc.symbol, targetAddress, target, addend); 334 break; 335 case GENERIC_RELOC_VANILLA | rScattered | rLength4: 336 // ex: .long _foo+n (and _foo defined) 337 perms = inAtom->permissions(); 338 *kind = 339 ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) ? abs32 340 : pointer32; 341 if (auto ec = atomFromAddress(0, reloc.value, target, addend)) 342 return ec; 343 *addend = *(const ulittle32_t *)fixupContent - reloc.value; 344 break; 345 default: 346 return llvm::make_error<GenericError>("unsupported i386 relocation type"); 347 } 348 return llvm::Error(); 349 } 350 351 llvm::Error 352 ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1, 353 const normalized::Relocation &reloc2, 354 const DefinedAtom *inAtom, 355 uint32_t offsetInAtom, 356 uint64_t fixupAddress, bool swap, 357 bool scatterable, 358 FindAtomBySectionAndAddress atomFromAddr, 359 FindAtomBySymbolIndex atomFromSymbolIndex, 360 Reference::KindValue *kind, 361 const lld::Atom **target, 362 Reference::Addend *addend) { 363 const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom]; 364 DefinedAtom::ContentPermissions perms = inAtom->permissions(); 365 uint32_t fromAddress; 366 uint32_t toAddress; 367 uint32_t value; 368 const lld::Atom *fromTarget; 369 Reference::Addend offsetInTo; 370 Reference::Addend offsetInFrom; 371 switch (relocPattern(reloc1) << 16 | relocPattern(reloc2)) { 372 case ((GENERIC_RELOC_SECTDIFF | rScattered | rLength4) << 16 | 373 GENERIC_RELOC_PAIR | rScattered | rLength4): 374 case ((GENERIC_RELOC_LOCAL_SECTDIFF | rScattered | rLength4) << 16 | 375 GENERIC_RELOC_PAIR | rScattered | rLength4): 376 toAddress = reloc1.value; 377 fromAddress = reloc2.value; 378 value = *(const little32_t *)fixupContent; 379 if (auto ec = atomFromAddr(0, toAddress, target, &offsetInTo)) 380 return ec; 381 if (auto ec = atomFromAddr(0, fromAddress, &fromTarget, &offsetInFrom)) 382 return ec; 383 if (fromTarget != inAtom) { 384 if (*target != inAtom) 385 return llvm::make_error<GenericError>( 386 "SECTDIFF relocation where neither target is in atom"); 387 *kind = negDelta32; 388 *addend = toAddress - value - fromAddress; 389 *target = fromTarget; 390 } else { 391 if ((perms & DefinedAtom::permR_X) == DefinedAtom::permR_X) { 392 // SECTDIFF relocations are used in i386 codegen where the function 393 // prolog does a CALL to the next instruction which POPs the return 394 // address into EBX which becomes the pic-base register. The POP 395 // instruction is label the used for the subtrahend in expressions. 396 // The funcRel32 kind represents the 32-bit delta to some symbol from 397 // the start of the function (atom) containing the funcRel32. 398 *kind = funcRel32; 399 uint32_t ta = fromAddress + value - toAddress; 400 *addend = ta - offsetInFrom; 401 } else { 402 *kind = delta32; 403 *addend = fromAddress + value - toAddress; 404 } 405 } 406 return llvm::Error(); 407 break; 408 default: 409 return llvm::make_error<GenericError>("unsupported i386 relocation type"); 410 } 411 } 412 413 void ArchHandler_x86::generateAtomContent(const DefinedAtom &atom, 414 bool relocatable, 415 FindAddressForAtom findAddress, 416 FindAddressForAtom findSectionAddress, 417 uint64_t imageBaseAddress, 418 llvm::MutableArrayRef<uint8_t> atomContentBuffer) { 419 // Copy raw bytes. 420 std::copy(atom.rawContent().begin(), atom.rawContent().end(), 421 atomContentBuffer.begin()); 422 // Apply fix-ups. 423 for (const Reference *ref : atom) { 424 uint32_t offset = ref->offsetInAtom(); 425 const Atom *target = ref->target(); 426 uint64_t targetAddress = 0; 427 if (isa<DefinedAtom>(target)) 428 targetAddress = findAddress(*target); 429 uint64_t atomAddress = findAddress(atom); 430 uint64_t fixupAddress = atomAddress + offset; 431 if (relocatable) { 432 applyFixupRelocatable(*ref, &atomContentBuffer[offset], 433 fixupAddress, targetAddress, 434 atomAddress); 435 } else { 436 applyFixupFinal(*ref, &atomContentBuffer[offset], 437 fixupAddress, targetAddress, 438 atomAddress); 439 } 440 } 441 } 442 443 void ArchHandler_x86::applyFixupFinal(const Reference &ref, uint8_t *loc, 444 uint64_t fixupAddress, 445 uint64_t targetAddress, 446 uint64_t inAtomAddress) { 447 if (ref.kindNamespace() != Reference::KindNamespace::mach_o) 448 return; 449 assert(ref.kindArch() == Reference::KindArch::x86); 450 ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc); 451 switch (static_cast<X86Kind>(ref.kindValue())) { 452 case branch32: 453 *loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend(); 454 break; 455 case branch16: 456 *loc32 = (targetAddress - (fixupAddress + 2)) + ref.addend(); 457 break; 458 case pointer32: 459 case abs32: 460 *loc32 = targetAddress + ref.addend(); 461 break; 462 case funcRel32: 463 *loc32 = targetAddress - inAtomAddress + ref.addend(); 464 break; 465 case delta32: 466 *loc32 = targetAddress - fixupAddress + ref.addend(); 467 break; 468 case negDelta32: 469 *loc32 = fixupAddress - targetAddress + ref.addend(); 470 break; 471 case modeCode: 472 case modeData: 473 case lazyPointer: 474 // do nothing 475 break; 476 case lazyImmediateLocation: 477 *loc32 = ref.addend(); 478 break; 479 case invalid: 480 llvm_unreachable("invalid x86 Reference Kind"); 481 break; 482 } 483 } 484 485 void ArchHandler_x86::applyFixupRelocatable(const Reference &ref, 486 uint8_t *loc, 487 uint64_t fixupAddress, 488 uint64_t targetAddress, 489 uint64_t inAtomAddress) { 490 if (ref.kindNamespace() != Reference::KindNamespace::mach_o) 491 return; 492 assert(ref.kindArch() == Reference::KindArch::x86); 493 bool useExternalReloc = useExternalRelocationTo(*ref.target()); 494 ulittle16_t *loc16 = reinterpret_cast<ulittle16_t *>(loc); 495 ulittle32_t *loc32 = reinterpret_cast<ulittle32_t *>(loc); 496 switch (static_cast<X86Kind>(ref.kindValue())) { 497 case branch32: 498 if (useExternalReloc) 499 *loc32 = ref.addend() - (fixupAddress + 4); 500 else 501 *loc32 =(targetAddress - (fixupAddress+4)) + ref.addend(); 502 break; 503 case branch16: 504 if (useExternalReloc) 505 *loc16 = ref.addend() - (fixupAddress + 2); 506 else 507 *loc16 = (targetAddress - (fixupAddress+2)) + ref.addend(); 508 break; 509 case pointer32: 510 case abs32: 511 *loc32 = targetAddress + ref.addend(); 512 break; 513 case funcRel32: 514 *loc32 = targetAddress - inAtomAddress + ref.addend(); // FIXME 515 break; 516 case delta32: 517 *loc32 = targetAddress - fixupAddress + ref.addend(); 518 break; 519 case negDelta32: 520 *loc32 = fixupAddress - targetAddress + ref.addend(); 521 break; 522 case modeCode: 523 case modeData: 524 case lazyPointer: 525 case lazyImmediateLocation: 526 // do nothing 527 break; 528 case invalid: 529 llvm_unreachable("invalid x86 Reference Kind"); 530 break; 531 } 532 } 533 534 bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) { 535 // Undefined symbols are referenced via external relocations. 536 if (isa<UndefinedAtom>(&target)) 537 return true; 538 if (const DefinedAtom *defAtom = dyn_cast<DefinedAtom>(&target)) { 539 switch (defAtom->merge()) { 540 case DefinedAtom::mergeAsTentative: 541 // Tentative definitions are referenced via external relocations. 542 return true; 543 case DefinedAtom::mergeAsWeak: 544 case DefinedAtom::mergeAsWeakAndAddressUsed: 545 // Global weak-defs are referenced via external relocations. 546 return (defAtom->scope() == DefinedAtom::scopeGlobal); 547 default: 548 break; 549 } 550 } 551 // Everything else is reference via an internal relocation. 552 return false; 553 } 554 555 void ArchHandler_x86::appendSectionRelocations( 556 const DefinedAtom &atom, 557 uint64_t atomSectionOffset, 558 const Reference &ref, 559 FindSymbolIndexForAtom symbolIndexForAtom, 560 FindSectionIndexForAtom sectionIndexForAtom, 561 FindAddressForAtom addressForAtom, 562 normalized::Relocations &relocs) { 563 if (ref.kindNamespace() != Reference::KindNamespace::mach_o) 564 return; 565 assert(ref.kindArch() == Reference::KindArch::x86); 566 uint32_t sectionOffset = atomSectionOffset + ref.offsetInAtom(); 567 bool useExternalReloc = useExternalRelocationTo(*ref.target()); 568 switch (static_cast<X86Kind>(ref.kindValue())) { 569 case modeCode: 570 case modeData: 571 break; 572 case branch32: 573 if (useExternalReloc) { 574 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, 575 GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength4); 576 } else { 577 if (ref.addend() != 0) 578 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), 579 GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength4); 580 else 581 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, 582 GENERIC_RELOC_VANILLA | rPcRel | rLength4); 583 } 584 break; 585 case branch16: 586 if (useExternalReloc) { 587 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, 588 GENERIC_RELOC_VANILLA | rExtern | rPcRel | rLength2); 589 } else { 590 if (ref.addend() != 0) 591 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), 592 GENERIC_RELOC_VANILLA | rScattered | rPcRel | rLength2); 593 else 594 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()),0, 595 GENERIC_RELOC_VANILLA | rPcRel | rLength2); 596 } 597 break; 598 case pointer32: 599 case abs32: 600 if (useExternalReloc) 601 appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0, 602 GENERIC_RELOC_VANILLA | rExtern | rLength4); 603 else { 604 if (ref.addend() != 0) 605 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), 606 GENERIC_RELOC_VANILLA | rScattered | rLength4); 607 else 608 appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0, 609 GENERIC_RELOC_VANILLA | rLength4); 610 } 611 break; 612 case funcRel32: 613 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), 614 GENERIC_RELOC_SECTDIFF | rScattered | rLength4); 615 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) - ref.addend(), 616 GENERIC_RELOC_PAIR | rScattered | rLength4); 617 break; 618 case delta32: 619 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), 620 GENERIC_RELOC_SECTDIFF | rScattered | rLength4); 621 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) + 622 ref.offsetInAtom(), 623 GENERIC_RELOC_PAIR | rScattered | rLength4); 624 break; 625 case negDelta32: 626 appendReloc(relocs, sectionOffset, 0, addressForAtom(atom) + 627 ref.offsetInAtom(), 628 GENERIC_RELOC_SECTDIFF | rScattered | rLength4); 629 appendReloc(relocs, sectionOffset, 0, addressForAtom(*ref.target()), 630 GENERIC_RELOC_PAIR | rScattered | rLength4); 631 break; 632 case lazyPointer: 633 case lazyImmediateLocation: 634 llvm_unreachable("lazy reference kind implies Stubs pass was run"); 635 break; 636 case invalid: 637 llvm_unreachable("unknown x86 Reference Kind"); 638 break; 639 } 640 } 641 642 std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() { 643 return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86()); 644 } 645 646 } // namespace mach_o 647 } // namespace lld 648