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