1 //===-- RuntimeDyldMachO.cpp - Run-time dynamic linker for MC-JIT -*- C++ -*-=// 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 // Implementation of the MC-JIT runtime dynamic linker. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "RuntimeDyldMachO.h" 15 #include "llvm/ADT/STLExtras.h" 16 #include "llvm/ADT/StringRef.h" 17 #include "ObjectImageCommon.h" 18 #include "JITRegistrar.h" 19 using namespace llvm; 20 using namespace llvm::object; 21 22 #define DEBUG_TYPE "dyld" 23 24 namespace llvm { 25 26 class MachOObjectImage : public ObjectImageCommon { 27 private: 28 typedef SmallVector<uint64_t, 1> SectionAddrList; 29 SectionAddrList OldSectionAddrList; 30 31 protected: 32 bool is64; 33 bool Registered; 34 35 private: 36 void initOldAddress() { 37 MachOObjectFile *objf = static_cast<MachOObjectFile *>(ObjFile.get()); 38 // Unfortunately we need to do this, since there's information encoded 39 // in the original addr of the section that we could not otherwise 40 // recover. The reason for this is that symbols do not actually store 41 // their file offset, but only their vmaddr. This means that in order 42 // to locate the symbol correctly in the object file, we need to know 43 // where the original start of the section was (including any padding, 44 // etc). 45 for (section_iterator i = objf->section_begin(), e = objf->section_end(); 46 i != e; ++i) { 47 uint64_t Addr; 48 i->getAddress(Addr); 49 OldSectionAddrList[i->getRawDataRefImpl().d.a] = Addr; 50 } 51 } 52 53 public: 54 MachOObjectImage(ObjectBuffer *Input, bool is64) 55 : ObjectImageCommon(Input), 56 OldSectionAddrList(ObjFile->section_end()->getRawDataRefImpl().d.a, 0), 57 is64(is64), Registered(false) { 58 initOldAddress(); 59 } 60 61 MachOObjectImage(std::unique_ptr<object::ObjectFile> Input, bool is64) 62 : ObjectImageCommon(std::move(Input)), 63 OldSectionAddrList(ObjFile->section_end()->getRawDataRefImpl().d.a, 0), 64 is64(is64), Registered(false) { 65 initOldAddress(); 66 } 67 68 virtual ~MachOObjectImage() { 69 if (Registered) 70 deregisterWithDebugger(); 71 } 72 73 // Subclasses can override these methods to update the image with loaded 74 // addresses for sections and common symbols 75 virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) { 76 MachOObjectFile *objf = static_cast<MachOObjectFile *>(ObjFile.get()); 77 char *data = 78 const_cast<char *>(objf->getSectionPointer(Sec.getRawDataRefImpl())); 79 80 uint64_t oldAddr = OldSectionAddrList[Sec.getRawDataRefImpl().d.a]; 81 82 if (is64) { 83 ((MachO::section_64 *)data)->addr = Addr; 84 } else { 85 ((MachO::section *)data)->addr = Addr; 86 } 87 88 for (symbol_iterator i = objf->symbol_begin(), e = objf->symbol_end(); 89 i != e; ++i) { 90 section_iterator symSec(objf->section_end()); 91 (*i).getSection(symSec); 92 if (*symSec == Sec) { 93 uint64_t symAddr; 94 (*i).getAddress(symAddr); 95 updateSymbolAddress(*i, symAddr + Addr - oldAddr); 96 } 97 } 98 } 99 100 uint64_t getOldSectionAddr(const SectionRef &Sec) const { 101 return OldSectionAddrList[Sec.getRawDataRefImpl().d.a]; 102 } 103 104 virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) { 105 char *data = const_cast<char *>( 106 reinterpret_cast<const char *>(Sym.getRawDataRefImpl().p)); 107 if (is64) 108 ((MachO::nlist_64 *)data)->n_value = Addr; 109 else 110 ((MachO::nlist *)data)->n_value = Addr; 111 } 112 113 virtual void registerWithDebugger() { 114 JITRegistrar::getGDBRegistrar().registerObject(*Buffer); 115 Registered = true; 116 } 117 118 virtual void deregisterWithDebugger() { 119 JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer); 120 } 121 }; 122 123 ObjectImage *RuntimeDyldMachO::createObjectImage(ObjectBuffer *Buffer) { 124 uint32_t magic = *((const uint32_t *)Buffer->getBufferStart()); 125 bool is64 = (magic == MachO::MH_MAGIC_64); 126 assert((magic == MachO::MH_MAGIC_64 || magic == MachO::MH_MAGIC) && 127 "Unrecognized Macho Magic"); 128 return new MachOObjectImage(Buffer, is64); 129 } 130 131 ObjectImage *RuntimeDyldMachO::createObjectImageFromFile( 132 std::unique_ptr<object::ObjectFile> ObjFile) { 133 if (!ObjFile) 134 return nullptr; 135 136 MemoryBuffer *Buffer = 137 MemoryBuffer::getMemBuffer(ObjFile->getData(), "", false); 138 139 uint32_t magic = *((const uint32_t *)Buffer->getBufferStart()); 140 bool is64 = (magic == MachO::MH_MAGIC_64); 141 assert((magic == MachO::MH_MAGIC_64 || magic == MachO::MH_MAGIC) && 142 "Unrecognized Macho Magic"); 143 return new MachOObjectImage(std::move(ObjFile), is64); 144 } 145 146 static unsigned char *processFDE(unsigned char *P, intptr_t DeltaForText, 147 intptr_t DeltaForEH) { 148 DEBUG(dbgs() << "Processing FDE: Delta for text: " << DeltaForText 149 << ", Delta for EH: " << DeltaForEH << "\n"); 150 uint32_t Length = *((uint32_t *)P); 151 P += 4; 152 unsigned char *Ret = P + Length; 153 uint32_t Offset = *((uint32_t *)P); 154 if (Offset == 0) // is a CIE 155 return Ret; 156 157 P += 4; 158 intptr_t FDELocation = *((intptr_t *)P); 159 intptr_t NewLocation = FDELocation - DeltaForText; 160 *((intptr_t *)P) = NewLocation; 161 P += sizeof(intptr_t); 162 163 // Skip the FDE address range 164 P += sizeof(intptr_t); 165 166 uint8_t Augmentationsize = *P; 167 P += 1; 168 if (Augmentationsize != 0) { 169 intptr_t LSDA = *((intptr_t *)P); 170 intptr_t NewLSDA = LSDA - DeltaForEH; 171 *((intptr_t *)P) = NewLSDA; 172 } 173 174 return Ret; 175 } 176 177 static intptr_t computeDelta(SectionEntry *A, SectionEntry *B) { 178 intptr_t ObjDistance = A->ObjAddress - B->ObjAddress; 179 intptr_t MemDistance = A->LoadAddress - B->LoadAddress; 180 return ObjDistance - MemDistance; 181 } 182 183 void RuntimeDyldMachO::registerEHFrames() { 184 185 if (!MemMgr) 186 return; 187 for (int i = 0, e = UnregisteredEHFrameSections.size(); i != e; ++i) { 188 EHFrameRelatedSections &SectionInfo = UnregisteredEHFrameSections[i]; 189 if (SectionInfo.EHFrameSID == RTDYLD_INVALID_SECTION_ID || 190 SectionInfo.TextSID == RTDYLD_INVALID_SECTION_ID) 191 continue; 192 SectionEntry *Text = &Sections[SectionInfo.TextSID]; 193 SectionEntry *EHFrame = &Sections[SectionInfo.EHFrameSID]; 194 SectionEntry *ExceptTab = nullptr; 195 if (SectionInfo.ExceptTabSID != RTDYLD_INVALID_SECTION_ID) 196 ExceptTab = &Sections[SectionInfo.ExceptTabSID]; 197 198 intptr_t DeltaForText = computeDelta(Text, EHFrame); 199 intptr_t DeltaForEH = 0; 200 if (ExceptTab) 201 DeltaForEH = computeDelta(ExceptTab, EHFrame); 202 203 unsigned char *P = EHFrame->Address; 204 unsigned char *End = P + EHFrame->Size; 205 do { 206 P = processFDE(P, DeltaForText, DeltaForEH); 207 } while (P != End); 208 209 MemMgr->registerEHFrames(EHFrame->Address, EHFrame->LoadAddress, 210 EHFrame->Size); 211 } 212 UnregisteredEHFrameSections.clear(); 213 } 214 215 void RuntimeDyldMachO::finalizeLoad(ObjectImage &ObjImg, 216 ObjSectionToIDMap &SectionMap) { 217 unsigned EHFrameSID = RTDYLD_INVALID_SECTION_ID; 218 unsigned TextSID = RTDYLD_INVALID_SECTION_ID; 219 unsigned ExceptTabSID = RTDYLD_INVALID_SECTION_ID; 220 ObjSectionToIDMap::iterator i, e; 221 for (i = SectionMap.begin(), e = SectionMap.end(); i != e; ++i) { 222 const SectionRef &Section = i->first; 223 StringRef Name; 224 Section.getName(Name); 225 if (Name == "__eh_frame") 226 EHFrameSID = i->second; 227 else if (Name == "__text") 228 TextSID = i->second; 229 else if (Name == "__gcc_except_tab") 230 ExceptTabSID = i->second; 231 else if (Name == "__jump_table") 232 populateJumpTable(cast<MachOObjectFile>(*ObjImg.getObjectFile()), 233 Section, i->second); 234 else if (Name == "__pointers") 235 populatePointersSection(cast<MachOObjectFile>(*ObjImg.getObjectFile()), 236 Section, i->second); 237 } 238 UnregisteredEHFrameSections.push_back( 239 EHFrameRelatedSections(EHFrameSID, TextSID, ExceptTabSID)); 240 } 241 242 // The target location for the relocation is described by RE.SectionID and 243 // RE.Offset. RE.SectionID can be used to find the SectionEntry. Each 244 // SectionEntry has three members describing its location. 245 // SectionEntry::Address is the address at which the section has been loaded 246 // into memory in the current (host) process. SectionEntry::LoadAddress is the 247 // address that the section will have in the target process. 248 // SectionEntry::ObjAddress is the address of the bits for this section in the 249 // original emitted object image (also in the current address space). 250 // 251 // Relocations will be applied as if the section were loaded at 252 // SectionEntry::LoadAddress, but they will be applied at an address based 253 // on SectionEntry::Address. SectionEntry::ObjAddress will be used to refer to 254 // Target memory contents if they are required for value calculations. 255 // 256 // The Value parameter here is the load address of the symbol for the 257 // relocation to be applied. For relocations which refer to symbols in the 258 // current object Value will be the LoadAddress of the section in which 259 // the symbol resides (RE.Addend provides additional information about the 260 // symbol location). For external symbols, Value will be the address of the 261 // symbol in the target address space. 262 void RuntimeDyldMachO::resolveRelocation(const RelocationEntry &RE, 263 uint64_t Value) { 264 DEBUG ( 265 const SectionEntry &Section = Sections[RE.SectionID]; 266 uint8_t* LocalAddress = Section.Address + RE.Offset; 267 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 268 269 dbgs() << "resolveRelocation Section: " << RE.SectionID 270 << " LocalAddress: " << format("%p", LocalAddress) 271 << " FinalAddress: " << format("%p", FinalAddress) 272 << " Value: " << format("%p", Value) 273 << " Addend: " << RE.Addend 274 << " isPCRel: " << RE.IsPCRel 275 << " MachoType: " << RE.RelType 276 << " Size: " << (1 << RE.Size) << "\n"; 277 ); 278 279 // This just dispatches to the proper target specific routine. 280 switch (Arch) { 281 default: 282 llvm_unreachable("Unsupported CPU type!"); 283 case Triple::x86_64: 284 resolveX86_64Relocation(RE, Value); 285 break; 286 case Triple::x86: 287 resolveI386Relocation(RE, Value); 288 break; 289 case Triple::arm: // Fall through. 290 case Triple::thumb: 291 resolveARMRelocation(RE, Value); 292 break; 293 case Triple::aarch64: 294 case Triple::arm64: 295 resolveAArch64Relocation(RE, Value); 296 break; 297 } 298 } 299 300 bool RuntimeDyldMachO::resolveI386Relocation(const RelocationEntry &RE, 301 uint64_t Value) { 302 const SectionEntry &Section = Sections[RE.SectionID]; 303 uint8_t* LocalAddress = Section.Address + RE.Offset; 304 305 if (RE.IsPCRel) { 306 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 307 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 308 } 309 310 switch (RE.RelType) { 311 default: 312 llvm_unreachable("Invalid relocation type!"); 313 case MachO::GENERIC_RELOC_VANILLA: 314 return applyRelocationValue(LocalAddress, Value + RE.Addend, 315 1 << RE.Size); 316 case MachO::GENERIC_RELOC_SECTDIFF: 317 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 318 uint64_t SectionABase = Sections[RE.Sections.SectionA].LoadAddress; 319 uint64_t SectionBBase = Sections[RE.Sections.SectionB].LoadAddress; 320 assert((Value == SectionABase || Value == SectionBBase) && 321 "Unexpected SECTDIFF relocation value."); 322 Value = SectionABase - SectionBBase + RE.Addend; 323 return applyRelocationValue(LocalAddress, Value, 1 << RE.Size); 324 } 325 case MachO::GENERIC_RELOC_PB_LA_PTR: 326 return Error("Relocation type not implemented yet!"); 327 } 328 } 329 330 bool RuntimeDyldMachO::resolveX86_64Relocation(const RelocationEntry &RE, 331 uint64_t Value) { 332 const SectionEntry &Section = Sections[RE.SectionID]; 333 uint8_t* LocalAddress = Section.Address + RE.Offset; 334 335 // If the relocation is PC-relative, the value to be encoded is the 336 // pointer difference. 337 if (RE.IsPCRel) { 338 // FIXME: It seems this value needs to be adjusted by 4 for an effective PC 339 // address. Is that expected? Only for branches, perhaps? 340 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 341 Value -= FinalAddress + 4; // see MachOX86_64::resolveRelocation. 342 } 343 344 switch (RE.RelType) { 345 default: 346 llvm_unreachable("Invalid relocation type!"); 347 case MachO::X86_64_RELOC_SIGNED_1: 348 case MachO::X86_64_RELOC_SIGNED_2: 349 case MachO::X86_64_RELOC_SIGNED_4: 350 case MachO::X86_64_RELOC_SIGNED: 351 case MachO::X86_64_RELOC_UNSIGNED: 352 case MachO::X86_64_RELOC_BRANCH: 353 return applyRelocationValue(LocalAddress, Value + RE.Addend, 1 << RE.Size); 354 case MachO::X86_64_RELOC_GOT_LOAD: 355 case MachO::X86_64_RELOC_GOT: 356 case MachO::X86_64_RELOC_SUBTRACTOR: 357 case MachO::X86_64_RELOC_TLV: 358 return Error("Relocation type not implemented yet!"); 359 } 360 } 361 362 bool RuntimeDyldMachO::resolveARMRelocation(const RelocationEntry &RE, 363 uint64_t Value) { 364 const SectionEntry &Section = Sections[RE.SectionID]; 365 uint8_t* LocalAddress = Section.Address + RE.Offset; 366 367 // If the relocation is PC-relative, the value to be encoded is the 368 // pointer difference. 369 if (RE.IsPCRel) { 370 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 371 Value -= FinalAddress; 372 // ARM PCRel relocations have an effective-PC offset of two instructions 373 // (four bytes in Thumb mode, 8 bytes in ARM mode). 374 // FIXME: For now, assume ARM mode. 375 Value -= 8; 376 } 377 378 switch (RE.RelType) { 379 default: 380 llvm_unreachable("Invalid relocation type!"); 381 case MachO::ARM_RELOC_VANILLA: 382 return applyRelocationValue(LocalAddress, Value, 1 << RE.Size); 383 case MachO::ARM_RELOC_BR24: { 384 // Mask the value into the target address. We know instructions are 385 // 32-bit aligned, so we can do it all at once. 386 uint32_t *p = (uint32_t *)LocalAddress; 387 // The low two bits of the value are not encoded. 388 Value >>= 2; 389 // Mask the value to 24 bits. 390 uint64_t FinalValue = Value & 0xffffff; 391 // Check for overflow. 392 if (Value != FinalValue) 393 return Error("ARM BR24 relocation out of range."); 394 // FIXME: If the destination is a Thumb function (and the instruction 395 // is a non-predicated BL instruction), we need to change it to a BLX 396 // instruction instead. 397 398 // Insert the value into the instruction. 399 *p = (*p & ~0xffffff) | FinalValue; 400 break; 401 } 402 case MachO::ARM_THUMB_RELOC_BR22: 403 case MachO::ARM_THUMB_32BIT_BRANCH: 404 case MachO::ARM_RELOC_HALF: 405 case MachO::ARM_RELOC_HALF_SECTDIFF: 406 case MachO::ARM_RELOC_PAIR: 407 case MachO::ARM_RELOC_SECTDIFF: 408 case MachO::ARM_RELOC_LOCAL_SECTDIFF: 409 case MachO::ARM_RELOC_PB_LA_PTR: 410 return Error("Relocation type not implemented yet!"); 411 } 412 return false; 413 } 414 415 bool RuntimeDyldMachO::resolveAArch64Relocation(const RelocationEntry &RE, 416 uint64_t Value) { 417 const SectionEntry &Section = Sections[RE.SectionID]; 418 uint8_t* LocalAddress = Section.Address + RE.Offset; 419 420 // If the relocation is PC-relative, the value to be encoded is the 421 // pointer difference. 422 if (RE.IsPCRel) { 423 uint64_t FinalAddress = Section.LoadAddress + RE.Offset; 424 Value -= FinalAddress; 425 } 426 427 switch (RE.RelType) { 428 default: 429 llvm_unreachable("Invalid relocation type!"); 430 case MachO::ARM64_RELOC_UNSIGNED: 431 return applyRelocationValue(LocalAddress, Value, 1 << RE.Size); 432 case MachO::ARM64_RELOC_BRANCH26: { 433 // Mask the value into the target address. We know instructions are 434 // 32-bit aligned, so we can do it all at once. 435 uint32_t *p = (uint32_t *)LocalAddress; 436 // The low two bits of the value are not encoded. 437 Value >>= 2; 438 // Mask the value to 26 bits. 439 uint64_t FinalValue = Value & 0x3ffffff; 440 // Check for overflow. 441 if (FinalValue != Value) 442 return Error("ARM64 BRANCH26 relocation out of range."); 443 // Insert the value into the instruction. 444 *p = (*p & ~0x3ffffff) | FinalValue; 445 break; 446 } 447 case MachO::ARM64_RELOC_SUBTRACTOR: 448 case MachO::ARM64_RELOC_PAGE21: 449 case MachO::ARM64_RELOC_PAGEOFF12: 450 case MachO::ARM64_RELOC_GOT_LOAD_PAGE21: 451 case MachO::ARM64_RELOC_GOT_LOAD_PAGEOFF12: 452 case MachO::ARM64_RELOC_POINTER_TO_GOT: 453 case MachO::ARM64_RELOC_TLVP_LOAD_PAGE21: 454 case MachO::ARM64_RELOC_TLVP_LOAD_PAGEOFF12: 455 case MachO::ARM64_RELOC_ADDEND: 456 return Error("Relocation type not implemented yet!"); 457 } 458 return false; 459 } 460 461 void RuntimeDyldMachO::populateJumpTable(MachOObjectFile &Obj, 462 const SectionRef &JTSection, 463 unsigned JTSectionID) { 464 assert(!Obj.is64Bit() && 465 "__jump_table section not supported in 64-bit MachO."); 466 467 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 468 MachO::section Sec32 = Obj.getSection(JTSection.getRawDataRefImpl()); 469 uint32_t JTSectionSize = Sec32.size; 470 unsigned FirstIndirectSymbol = Sec32.reserved1; 471 unsigned JTEntrySize = Sec32.reserved2; 472 unsigned NumJTEntries = JTSectionSize / JTEntrySize; 473 uint8_t* JTSectionAddr = getSectionAddress(JTSectionID); 474 unsigned JTEntryOffset = 0; 475 476 assert((JTSectionSize % JTEntrySize) == 0 && 477 "Jump-table section does not contain a whole number of stubs?"); 478 479 for (unsigned i = 0; i < NumJTEntries; ++i) { 480 unsigned SymbolIndex = 481 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 482 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 483 StringRef IndirectSymbolName; 484 SI->getName(IndirectSymbolName); 485 uint8_t* JTEntryAddr = JTSectionAddr + JTEntryOffset; 486 createStubFunction(JTEntryAddr); 487 RelocationEntry RE(JTSectionID, JTEntryOffset + 1, 488 MachO::GENERIC_RELOC_VANILLA, 0, true, 2); 489 addRelocationForSymbol(RE, IndirectSymbolName); 490 JTEntryOffset += JTEntrySize; 491 } 492 } 493 494 void RuntimeDyldMachO::populatePointersSection(MachOObjectFile &Obj, 495 const SectionRef &PTSection, 496 unsigned PTSectionID) { 497 assert(!Obj.is64Bit() && 498 "__pointers section not supported in 64-bit MachO."); 499 500 MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); 501 MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); 502 uint32_t PTSectionSize = Sec32.size; 503 unsigned FirstIndirectSymbol = Sec32.reserved1; 504 const unsigned PTEntrySize = 4; 505 unsigned NumPTEntries = PTSectionSize / PTEntrySize; 506 unsigned PTEntryOffset = 0; 507 508 assert((PTSectionSize % PTEntrySize) == 0 && 509 "Pointers section does not contain a whole number of stubs?"); 510 511 DEBUG(dbgs() << "Populating __pointers, Section ID " << PTSectionID 512 << ", " << NumPTEntries << " entries, " 513 << PTEntrySize << " bytes each:\n"); 514 515 for (unsigned i = 0; i < NumPTEntries; ++i) { 516 unsigned SymbolIndex = 517 Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); 518 symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); 519 StringRef IndirectSymbolName; 520 SI->getName(IndirectSymbolName); 521 DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex 522 << ", PT offset: " << PTEntryOffset << "\n"); 523 RelocationEntry RE(PTSectionID, PTEntryOffset, 524 MachO::GENERIC_RELOC_VANILLA, 0, false, 2); 525 addRelocationForSymbol(RE, IndirectSymbolName); 526 PTEntryOffset += PTEntrySize; 527 } 528 } 529 530 531 section_iterator getSectionByAddress(const MachOObjectFile &Obj, 532 uint64_t Addr) { 533 section_iterator SI = Obj.section_begin(); 534 section_iterator SE = Obj.section_end(); 535 536 for (; SI != SE; ++SI) { 537 uint64_t SAddr, SSize; 538 SI->getAddress(SAddr); 539 SI->getSize(SSize); 540 if ((Addr >= SAddr) && (Addr < SAddr + SSize)) 541 return SI; 542 } 543 544 return SE; 545 } 546 547 relocation_iterator RuntimeDyldMachO::processSECTDIFFRelocation( 548 unsigned SectionID, 549 relocation_iterator RelI, 550 ObjectImage &Obj, 551 ObjSectionToIDMap &ObjSectionToID) { 552 const MachOObjectFile *MachO = 553 static_cast<const MachOObjectFile*>(Obj.getObjectFile()); 554 MachO::any_relocation_info RE = 555 MachO->getRelocation(RelI->getRawDataRefImpl()); 556 557 SectionEntry &Section = Sections[SectionID]; 558 uint32_t RelocType = MachO->getAnyRelocationType(RE); 559 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 560 unsigned Size = MachO->getAnyRelocationLength(RE); 561 uint64_t Offset; 562 RelI->getOffset(Offset); 563 uint8_t *LocalAddress = Section.Address + Offset; 564 unsigned NumBytes = 1 << Size; 565 int64_t Addend = 0; 566 memcpy(&Addend, LocalAddress, NumBytes); 567 568 ++RelI; 569 MachO::any_relocation_info RE2 = 570 MachO->getRelocation(RelI->getRawDataRefImpl()); 571 572 uint32_t AddrA = MachO->getScatteredRelocationValue(RE); 573 section_iterator SAI = getSectionByAddress(*MachO, AddrA); 574 assert(SAI != MachO->section_end() && "Can't find section for address A"); 575 uint64_t SectionABase; 576 SAI->getAddress(SectionABase); 577 uint64_t SectionAOffset = AddrA - SectionABase; 578 SectionRef SectionA = *SAI; 579 bool IsCode; 580 SectionA.isText(IsCode); 581 uint32_t SectionAID = findOrEmitSection(Obj, SectionA, IsCode, 582 ObjSectionToID); 583 584 uint32_t AddrB = MachO->getScatteredRelocationValue(RE2); 585 section_iterator SBI = getSectionByAddress(*MachO, AddrB); 586 assert(SBI != MachO->section_end() && "Can't find section for address B"); 587 uint64_t SectionBBase; 588 SBI->getAddress(SectionBBase); 589 uint64_t SectionBOffset = AddrB - SectionBBase; 590 SectionRef SectionB = *SBI; 591 uint32_t SectionBID = findOrEmitSection(Obj, SectionB, IsCode, 592 ObjSectionToID); 593 594 if (Addend != AddrA - AddrB) 595 Error("Unexpected SECTDIFF relocation addend."); 596 597 DEBUG(dbgs() << "Found SECTDIFF: AddrA: " << AddrA << ", AddrB: " << AddrB 598 << ", Addend: " << Addend << ", SectionA ID: " 599 << SectionAID << ", SectionAOffset: " << SectionAOffset 600 << ", SectionB ID: " << SectionBID << ", SectionBOffset: " 601 << SectionBOffset << "\n"); 602 RelocationEntry R(SectionID, Offset, RelocType, 0, 603 SectionAID, SectionAOffset, SectionBID, SectionBOffset, 604 IsPCRel, Size); 605 606 addRelocationForSection(R, SectionAID); 607 addRelocationForSection(R, SectionBID); 608 609 return ++RelI; 610 } 611 612 relocation_iterator RuntimeDyldMachO::processI386ScatteredVANILLA( 613 unsigned SectionID, 614 relocation_iterator RelI, 615 ObjectImage &Obj, 616 ObjSectionToIDMap &ObjSectionToID) { 617 const MachOObjectFile *MachO = 618 static_cast<const MachOObjectFile*>(Obj.getObjectFile()); 619 MachO::any_relocation_info RE = 620 MachO->getRelocation(RelI->getRawDataRefImpl()); 621 622 SectionEntry &Section = Sections[SectionID]; 623 uint32_t RelocType = MachO->getAnyRelocationType(RE); 624 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 625 unsigned Size = MachO->getAnyRelocationLength(RE); 626 uint64_t Offset; 627 RelI->getOffset(Offset); 628 uint8_t *LocalAddress = Section.Address + Offset; 629 unsigned NumBytes = 1 << Size; 630 int64_t Addend = 0; 631 memcpy(&Addend, LocalAddress, NumBytes); 632 633 unsigned SymbolBaseAddr = MachO->getScatteredRelocationValue(RE); 634 section_iterator TargetSI = getSectionByAddress(*MachO, SymbolBaseAddr); 635 assert(TargetSI != MachO->section_end() && "Can't find section for symbol"); 636 uint64_t SectionBaseAddr; 637 TargetSI->getAddress(SectionBaseAddr); 638 SectionRef TargetSection = *TargetSI; 639 bool IsCode; 640 TargetSection.isText(IsCode); 641 uint32_t TargetSectionID = findOrEmitSection(Obj, TargetSection, IsCode, 642 ObjSectionToID); 643 644 Addend -= SectionBaseAddr; 645 RelocationEntry R(SectionID, Offset, RelocType, Addend, 646 IsPCRel, Size); 647 648 addRelocationForSection(R, TargetSectionID); 649 650 return ++RelI; 651 } 652 653 relocation_iterator RuntimeDyldMachO::processRelocationRef( 654 unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj, 655 ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols, 656 StubMap &Stubs) { 657 const ObjectFile *OF = Obj.getObjectFile(); 658 const MachOObjectImage &MachOObj = *static_cast<MachOObjectImage *>(&Obj); 659 const MachOObjectFile *MachO = static_cast<const MachOObjectFile *>(OF); 660 MachO::any_relocation_info RE = 661 MachO->getRelocation(RelI->getRawDataRefImpl()); 662 663 uint32_t RelType = MachO->getAnyRelocationType(RE); 664 665 // FIXME: Properly handle scattered relocations. 666 // Special case the couple of scattered relocations that we know how 667 // to handle: SECTDIFF relocations, and scattered VANILLA relocations 668 // on I386. 669 // For all other scattered relocations, just bail out and hope for the 670 // best, since the offsets computed by scattered relocations have often 671 // been optimisticaly filled in by the compiler. This will fail 672 // horribly where the relocations *do* need to be applied, but that was 673 // already the case. 674 if (MachO->isRelocationScattered(RE)) { 675 if (RelType == MachO::GENERIC_RELOC_SECTDIFF || 676 RelType == MachO::GENERIC_RELOC_LOCAL_SECTDIFF) 677 return processSECTDIFFRelocation(SectionID, RelI, Obj, ObjSectionToID); 678 else if (Arch == Triple::x86 && RelType == MachO::GENERIC_RELOC_VANILLA) 679 return processI386ScatteredVANILLA(SectionID, RelI, Obj, ObjSectionToID); 680 else 681 return ++RelI; 682 } 683 684 RelocationValueRef Value; 685 SectionEntry &Section = Sections[SectionID]; 686 687 bool IsExtern = MachO->getPlainRelocationExternal(RE); 688 bool IsPCRel = MachO->getAnyRelocationPCRel(RE); 689 unsigned Size = MachO->getAnyRelocationLength(RE); 690 uint64_t Offset; 691 RelI->getOffset(Offset); 692 uint8_t *LocalAddress = Section.Address + Offset; 693 unsigned NumBytes = 1 << Size; 694 uint64_t Addend = 0; 695 memcpy(&Addend, LocalAddress, NumBytes); 696 697 if (IsExtern) { 698 // Obtain the symbol name which is referenced in the relocation 699 symbol_iterator Symbol = RelI->getSymbol(); 700 StringRef TargetName; 701 Symbol->getName(TargetName); 702 // First search for the symbol in the local symbol table 703 SymbolTableMap::const_iterator lsi = Symbols.find(TargetName.data()); 704 if (lsi != Symbols.end()) { 705 Value.SectionID = lsi->second.first; 706 Value.Addend = lsi->second.second + Addend; 707 } else { 708 // Search for the symbol in the global symbol table 709 SymbolTableMap::const_iterator gsi = 710 GlobalSymbolTable.find(TargetName.data()); 711 if (gsi != GlobalSymbolTable.end()) { 712 Value.SectionID = gsi->second.first; 713 Value.Addend = gsi->second.second + Addend; 714 } else { 715 Value.SymbolName = TargetName.data(); 716 Value.Addend = Addend; 717 } 718 } 719 720 // Addends for external, PC-rel relocations on i386 point back to the zero 721 // offset. Calculate the final offset from the relocation target instead. 722 // This allows us to use the same logic for both external and internal 723 // relocations in resolveI386RelocationRef. 724 if (Arch == Triple::x86 && IsPCRel) { 725 uint64_t RelocAddr = 0; 726 RelI->getAddress(RelocAddr); 727 Value.Addend += RelocAddr + 4; 728 } 729 730 } else { 731 SectionRef Sec = MachO->getRelocationSection(RE); 732 bool IsCode = false; 733 Sec.isText(IsCode); 734 Value.SectionID = findOrEmitSection(Obj, Sec, IsCode, ObjSectionToID); 735 uint64_t Addr = MachOObj.getOldSectionAddr(Sec); 736 DEBUG(dbgs() << "\nAddr: " << Addr << "\nAddend: " << Addend); 737 Value.Addend = Addend - Addr; 738 if (IsPCRel) 739 Value.Addend += Offset + NumBytes; 740 } 741 742 if (Arch == Triple::x86_64 && (RelType == MachO::X86_64_RELOC_GOT || 743 RelType == MachO::X86_64_RELOC_GOT_LOAD)) { 744 assert(IsPCRel); 745 assert(Size == 2); 746 747 // FIXME: Teach the generic code above not to prematurely conflate 748 // relocation addends and symbol offsets. 749 Value.Addend -= Addend; 750 StubMap::const_iterator i = Stubs.find(Value); 751 uint8_t *Addr; 752 if (i != Stubs.end()) { 753 Addr = Section.Address + i->second; 754 } else { 755 Stubs[Value] = Section.StubOffset; 756 uint8_t *GOTEntry = Section.Address + Section.StubOffset; 757 RelocationEntry GOTRE(SectionID, Section.StubOffset, 758 MachO::X86_64_RELOC_UNSIGNED, Value.Addend, false, 759 3); 760 if (Value.SymbolName) 761 addRelocationForSymbol(GOTRE, Value.SymbolName); 762 else 763 addRelocationForSection(GOTRE, Value.SectionID); 764 Section.StubOffset += 8; 765 Addr = GOTEntry; 766 } 767 RelocationEntry TargetRE(SectionID, Offset, 768 MachO::X86_64_RELOC_UNSIGNED, Addend, true, 769 2); 770 resolveRelocation(TargetRE, (uint64_t)Addr); 771 } else if (Arch == Triple::arm && (RelType & 0xf) == MachO::ARM_RELOC_BR24) { 772 // This is an ARM branch relocation, need to use a stub function. 773 774 // Look up for existing stub. 775 StubMap::const_iterator i = Stubs.find(Value); 776 uint8_t *Addr; 777 if (i != Stubs.end()) { 778 Addr = Section.Address + i->second; 779 } else { 780 // Create a new stub function. 781 Stubs[Value] = Section.StubOffset; 782 uint8_t *StubTargetAddr = 783 createStubFunction(Section.Address + Section.StubOffset); 784 RelocationEntry StubRE(SectionID, StubTargetAddr - Section.Address, 785 MachO::GENERIC_RELOC_VANILLA, Value.Addend); 786 if (Value.SymbolName) 787 addRelocationForSymbol(StubRE, Value.SymbolName); 788 else 789 addRelocationForSection(StubRE, Value.SectionID); 790 Addr = Section.Address + Section.StubOffset; 791 Section.StubOffset += getMaxStubSize(); 792 } 793 RelocationEntry TargetRE(Value.SectionID, Offset, RelType, 0, IsPCRel, 794 Size); 795 resolveRelocation(TargetRE, (uint64_t)Addr); 796 } else { 797 RelocationEntry RE(SectionID, Offset, RelType, Value.Addend, IsPCRel, Size); 798 if (Value.SymbolName) 799 addRelocationForSymbol(RE, Value.SymbolName); 800 else 801 addRelocationForSection(RE, Value.SectionID); 802 } 803 return ++RelI; 804 } 805 806 bool 807 RuntimeDyldMachO::isCompatibleFormat(const ObjectBuffer *InputBuffer) const { 808 if (InputBuffer->getBufferSize() < 4) 809 return false; 810 StringRef Magic(InputBuffer->getBufferStart(), 4); 811 if (Magic == "\xFE\xED\xFA\xCE") 812 return true; 813 if (Magic == "\xCE\xFA\xED\xFE") 814 return true; 815 if (Magic == "\xFE\xED\xFA\xCF") 816 return true; 817 if (Magic == "\xCF\xFA\xED\xFE") 818 return true; 819 return false; 820 } 821 822 bool RuntimeDyldMachO::isCompatibleFile(const object::ObjectFile *Obj) const { 823 return Obj->isMachO(); 824 } 825 826 } // end namespace llvm 827