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