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