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