1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- 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 // This file defines the MachOObjectFile class, which binds the MachOObject 11 // class to the generic ObjectFile wrapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Object/MachO.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/Triple.h" 18 #include "llvm/Support/DataExtractor.h" 19 #include "llvm/Support/Format.h" 20 #include "llvm/Support/Host.h" 21 #include "llvm/Support/MemoryBuffer.h" 22 #include "llvm/Support/raw_ostream.h" 23 #include <cctype> 24 #include <cstring> 25 #include <limits> 26 27 using namespace llvm; 28 using namespace object; 29 30 namespace llvm { 31 32 namespace object { 33 34 struct nlist_base { 35 uint32_t n_strx; 36 uint8_t n_type; 37 uint8_t n_sect; 38 uint16_t n_desc; 39 }; 40 41 struct section_base { 42 char sectname[16]; 43 char segname[16]; 44 }; 45 46 template<typename T> 47 static void SwapStruct(T &Value); 48 49 template<> 50 void SwapStruct(MachO::any_relocation_info &H) { 51 sys::swapByteOrder(H.r_word0); 52 sys::swapByteOrder(H.r_word1); 53 } 54 55 template<> 56 void SwapStruct(MachO::load_command &L) { 57 sys::swapByteOrder(L.cmd); 58 sys::swapByteOrder(L.cmdsize); 59 } 60 61 template<> 62 void SwapStruct(nlist_base &S) { 63 sys::swapByteOrder(S.n_strx); 64 sys::swapByteOrder(S.n_desc); 65 } 66 67 template<> 68 void SwapStruct(MachO::section &S) { 69 sys::swapByteOrder(S.addr); 70 sys::swapByteOrder(S.size); 71 sys::swapByteOrder(S.offset); 72 sys::swapByteOrder(S.align); 73 sys::swapByteOrder(S.reloff); 74 sys::swapByteOrder(S.nreloc); 75 sys::swapByteOrder(S.flags); 76 sys::swapByteOrder(S.reserved1); 77 sys::swapByteOrder(S.reserved2); 78 } 79 80 template<> 81 void SwapStruct(MachO::section_64 &S) { 82 sys::swapByteOrder(S.addr); 83 sys::swapByteOrder(S.size); 84 sys::swapByteOrder(S.offset); 85 sys::swapByteOrder(S.align); 86 sys::swapByteOrder(S.reloff); 87 sys::swapByteOrder(S.nreloc); 88 sys::swapByteOrder(S.flags); 89 sys::swapByteOrder(S.reserved1); 90 sys::swapByteOrder(S.reserved2); 91 sys::swapByteOrder(S.reserved3); 92 } 93 94 template<> 95 void SwapStruct(MachO::nlist &S) { 96 sys::swapByteOrder(S.n_strx); 97 sys::swapByteOrder(S.n_desc); 98 sys::swapByteOrder(S.n_value); 99 } 100 101 template<> 102 void SwapStruct(MachO::nlist_64 &S) { 103 sys::swapByteOrder(S.n_strx); 104 sys::swapByteOrder(S.n_desc); 105 sys::swapByteOrder(S.n_value); 106 } 107 108 template<> 109 void SwapStruct(MachO::mach_header &H) { 110 sys::swapByteOrder(H.magic); 111 sys::swapByteOrder(H.cputype); 112 sys::swapByteOrder(H.cpusubtype); 113 sys::swapByteOrder(H.filetype); 114 sys::swapByteOrder(H.ncmds); 115 sys::swapByteOrder(H.sizeofcmds); 116 sys::swapByteOrder(H.flags); 117 } 118 119 template<> 120 void SwapStruct(MachO::mach_header_64 &H) { 121 sys::swapByteOrder(H.magic); 122 sys::swapByteOrder(H.cputype); 123 sys::swapByteOrder(H.cpusubtype); 124 sys::swapByteOrder(H.filetype); 125 sys::swapByteOrder(H.ncmds); 126 sys::swapByteOrder(H.sizeofcmds); 127 sys::swapByteOrder(H.flags); 128 sys::swapByteOrder(H.reserved); 129 } 130 131 template<> 132 void SwapStruct(MachO::symtab_command &C) { 133 sys::swapByteOrder(C.cmd); 134 sys::swapByteOrder(C.cmdsize); 135 sys::swapByteOrder(C.symoff); 136 sys::swapByteOrder(C.nsyms); 137 sys::swapByteOrder(C.stroff); 138 sys::swapByteOrder(C.strsize); 139 } 140 141 template<> 142 void SwapStruct(MachO::dysymtab_command &C) { 143 sys::swapByteOrder(C.cmd); 144 sys::swapByteOrder(C.cmdsize); 145 sys::swapByteOrder(C.ilocalsym); 146 sys::swapByteOrder(C.nlocalsym); 147 sys::swapByteOrder(C.iextdefsym); 148 sys::swapByteOrder(C.nextdefsym); 149 sys::swapByteOrder(C.iundefsym); 150 sys::swapByteOrder(C.nundefsym); 151 sys::swapByteOrder(C.tocoff); 152 sys::swapByteOrder(C.ntoc); 153 sys::swapByteOrder(C.modtaboff); 154 sys::swapByteOrder(C.nmodtab); 155 sys::swapByteOrder(C.extrefsymoff); 156 sys::swapByteOrder(C.nextrefsyms); 157 sys::swapByteOrder(C.indirectsymoff); 158 sys::swapByteOrder(C.nindirectsyms); 159 sys::swapByteOrder(C.extreloff); 160 sys::swapByteOrder(C.nextrel); 161 sys::swapByteOrder(C.locreloff); 162 sys::swapByteOrder(C.nlocrel); 163 } 164 165 template<> 166 void SwapStruct(MachO::linkedit_data_command &C) { 167 sys::swapByteOrder(C.cmd); 168 sys::swapByteOrder(C.cmdsize); 169 sys::swapByteOrder(C.dataoff); 170 sys::swapByteOrder(C.datasize); 171 } 172 173 template<> 174 void SwapStruct(MachO::segment_command &C) { 175 sys::swapByteOrder(C.cmd); 176 sys::swapByteOrder(C.cmdsize); 177 sys::swapByteOrder(C.vmaddr); 178 sys::swapByteOrder(C.vmsize); 179 sys::swapByteOrder(C.fileoff); 180 sys::swapByteOrder(C.filesize); 181 sys::swapByteOrder(C.maxprot); 182 sys::swapByteOrder(C.initprot); 183 sys::swapByteOrder(C.nsects); 184 sys::swapByteOrder(C.flags); 185 } 186 187 template<> 188 void SwapStruct(MachO::segment_command_64 &C) { 189 sys::swapByteOrder(C.cmd); 190 sys::swapByteOrder(C.cmdsize); 191 sys::swapByteOrder(C.vmaddr); 192 sys::swapByteOrder(C.vmsize); 193 sys::swapByteOrder(C.fileoff); 194 sys::swapByteOrder(C.filesize); 195 sys::swapByteOrder(C.maxprot); 196 sys::swapByteOrder(C.initprot); 197 sys::swapByteOrder(C.nsects); 198 sys::swapByteOrder(C.flags); 199 } 200 201 template<> 202 void SwapStruct(uint32_t &C) { 203 sys::swapByteOrder(C); 204 } 205 206 template<> 207 void SwapStruct(MachO::linker_options_command &C) { 208 sys::swapByteOrder(C.cmd); 209 sys::swapByteOrder(C.cmdsize); 210 sys::swapByteOrder(C.count); 211 } 212 213 template<> 214 void SwapStruct(MachO::version_min_command&C) { 215 sys::swapByteOrder(C.cmd); 216 sys::swapByteOrder(C.cmdsize); 217 sys::swapByteOrder(C.version); 218 sys::swapByteOrder(C.reserved); 219 } 220 221 template<> 222 void SwapStruct(MachO::dylib_command&C) { 223 sys::swapByteOrder(C.cmd); 224 sys::swapByteOrder(C.cmdsize); 225 sys::swapByteOrder(C.dylib.name); 226 sys::swapByteOrder(C.dylib.timestamp); 227 sys::swapByteOrder(C.dylib.current_version); 228 sys::swapByteOrder(C.dylib.compatibility_version); 229 } 230 231 template<> 232 void SwapStruct(MachO::data_in_code_entry &C) { 233 sys::swapByteOrder(C.offset); 234 sys::swapByteOrder(C.length); 235 sys::swapByteOrder(C.kind); 236 } 237 238 template<typename T> 239 T getStruct(const MachOObjectFile *O, const char *P) { 240 T Cmd; 241 memcpy(&Cmd, P, sizeof(T)); 242 if (O->isLittleEndian() != sys::IsLittleEndianHost) 243 SwapStruct(Cmd); 244 return Cmd; 245 } 246 247 static uint32_t 248 getSegmentLoadCommandNumSections(const MachOObjectFile *O, 249 const MachOObjectFile::LoadCommandInfo &L) { 250 if (O->is64Bit()) { 251 MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 252 return S.nsects; 253 } 254 MachO::segment_command S = O->getSegmentLoadCommand(L); 255 return S.nsects; 256 } 257 258 static const char * 259 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 260 unsigned Sec) { 261 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 262 263 bool Is64 = O->is64Bit(); 264 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 265 sizeof(MachO::segment_command); 266 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 267 sizeof(MachO::section); 268 269 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 270 return reinterpret_cast<const char*>(SectionAddr); 271 } 272 273 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 274 return O->getData().substr(Offset, 1).data(); 275 } 276 277 static nlist_base 278 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 279 const char *P = reinterpret_cast<const char *>(DRI.p); 280 return getStruct<nlist_base>(O, P); 281 } 282 283 static StringRef parseSegmentOrSectionName(const char *P) { 284 if (P[15] == 0) 285 // Null terminated. 286 return P; 287 // Not null terminated, so this is a 16 char string. 288 return StringRef(P, 16); 289 } 290 291 // Helper to advance a section or symbol iterator multiple increments at a time. 292 template<class T> 293 static void advance(T &it, size_t Val) { 294 while (Val--) 295 ++it; 296 } 297 298 static unsigned getCPUType(const MachOObjectFile *O) { 299 return O->getHeader().cputype; 300 } 301 302 static void printRelocationTargetName(const MachOObjectFile *O, 303 const MachO::any_relocation_info &RE, 304 raw_string_ostream &fmt) { 305 bool IsScattered = O->isRelocationScattered(RE); 306 307 // Target of a scattered relocation is an address. In the interest of 308 // generating pretty output, scan through the symbol table looking for a 309 // symbol that aligns with that address. If we find one, print it. 310 // Otherwise, we just print the hex address of the target. 311 if (IsScattered) { 312 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 313 314 for (const SymbolRef &Symbol : O->symbols()) { 315 std::error_code ec; 316 uint64_t Addr; 317 StringRef Name; 318 319 if ((ec = Symbol.getAddress(Addr))) 320 report_fatal_error(ec.message()); 321 if (Addr != Val) 322 continue; 323 if ((ec = Symbol.getName(Name))) 324 report_fatal_error(ec.message()); 325 fmt << Name; 326 return; 327 } 328 329 // If we couldn't find a symbol that this relocation refers to, try 330 // to find a section beginning instead. 331 for (const SectionRef &Section : O->sections()) { 332 std::error_code ec; 333 uint64_t Addr; 334 StringRef Name; 335 336 if ((ec = Section.getAddress(Addr))) 337 report_fatal_error(ec.message()); 338 if (Addr != Val) 339 continue; 340 if ((ec = Section.getName(Name))) 341 report_fatal_error(ec.message()); 342 fmt << Name; 343 return; 344 } 345 346 fmt << format("0x%x", Val); 347 return; 348 } 349 350 StringRef S; 351 bool isExtern = O->getPlainRelocationExternal(RE); 352 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 353 354 if (isExtern) { 355 symbol_iterator SI = O->symbol_begin(); 356 advance(SI, Val); 357 SI->getName(S); 358 } else { 359 section_iterator SI = O->section_begin(); 360 // Adjust for the fact that sections are 1-indexed. 361 advance(SI, Val - 1); 362 SI->getName(S); 363 } 364 365 fmt << S; 366 } 367 368 static uint32_t 369 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 370 return RE.r_word0; 371 } 372 373 static unsigned 374 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 375 return RE.r_word0 & 0xffffff; 376 } 377 378 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 379 const MachO::any_relocation_info &RE) { 380 if (O->isLittleEndian()) 381 return (RE.r_word1 >> 24) & 1; 382 return (RE.r_word1 >> 7) & 1; 383 } 384 385 static bool 386 getScatteredRelocationPCRel(const MachOObjectFile *O, 387 const MachO::any_relocation_info &RE) { 388 return (RE.r_word0 >> 30) & 1; 389 } 390 391 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 392 const MachO::any_relocation_info &RE) { 393 if (O->isLittleEndian()) 394 return (RE.r_word1 >> 25) & 3; 395 return (RE.r_word1 >> 5) & 3; 396 } 397 398 static unsigned 399 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 400 return (RE.r_word0 >> 28) & 3; 401 } 402 403 static unsigned getPlainRelocationType(const MachOObjectFile *O, 404 const MachO::any_relocation_info &RE) { 405 if (O->isLittleEndian()) 406 return RE.r_word1 >> 28; 407 return RE.r_word1 & 0xf; 408 } 409 410 static unsigned 411 getScatteredRelocationType(const MachO::any_relocation_info &RE) { 412 return (RE.r_word0 >> 24) & 0xf; 413 } 414 415 static uint32_t getSectionFlags(const MachOObjectFile *O, 416 DataRefImpl Sec) { 417 if (O->is64Bit()) { 418 MachO::section_64 Sect = O->getSection64(Sec); 419 return Sect.flags; 420 } 421 MachO::section Sect = O->getSection(Sec); 422 return Sect.flags; 423 } 424 425 MachOObjectFile::MachOObjectFile(std::unique_ptr<MemoryBuffer> Object, 426 bool IsLittleEndian, bool Is64bits, 427 std::error_code &EC) 428 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), std::move(Object)), 429 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 430 DataInCodeLoadCmd(nullptr) { 431 uint32_t LoadCommandCount = this->getHeader().ncmds; 432 MachO::LoadCommandType SegmentLoadType = is64Bit() ? 433 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 434 435 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 436 for (unsigned I = 0; ; ++I) { 437 if (Load.C.cmd == MachO::LC_SYMTAB) { 438 assert(!SymtabLoadCmd && "Multiple symbol tables"); 439 SymtabLoadCmd = Load.Ptr; 440 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 441 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 442 DysymtabLoadCmd = Load.Ptr; 443 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 444 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 445 DataInCodeLoadCmd = Load.Ptr; 446 } else if (Load.C.cmd == SegmentLoadType) { 447 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 448 for (unsigned J = 0; J < NumSections; ++J) { 449 const char *Sec = getSectionPtr(this, Load, J); 450 Sections.push_back(Sec); 451 } 452 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || 453 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 454 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 455 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 456 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 457 Libraries.push_back(Load.Ptr); 458 } 459 460 if (I == LoadCommandCount - 1) 461 break; 462 else 463 Load = getNextLoadCommandInfo(Load); 464 } 465 } 466 467 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 468 unsigned SymbolTableEntrySize = is64Bit() ? 469 sizeof(MachO::nlist_64) : 470 sizeof(MachO::nlist); 471 Symb.p += SymbolTableEntrySize; 472 } 473 474 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 475 StringRef &Res) const { 476 StringRef StringTable = getStringTableData(); 477 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 478 const char *Start = &StringTable.data()[Entry.n_strx]; 479 Res = StringRef(Start); 480 return object_error::success; 481 } 482 483 // getIndirectName() returns the name of the alias'ed symbol who's string table 484 // index is in the n_value field. 485 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 486 StringRef &Res) const { 487 StringRef StringTable = getStringTableData(); 488 uint64_t NValue; 489 if (is64Bit()) { 490 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 491 NValue = Entry.n_value; 492 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 493 return object_error::parse_failed; 494 } else { 495 MachO::nlist Entry = getSymbolTableEntry(Symb); 496 NValue = Entry.n_value; 497 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 498 return object_error::parse_failed; 499 } 500 if (NValue >= StringTable.size()) 501 return object_error::parse_failed; 502 const char *Start = &StringTable.data()[NValue]; 503 Res = StringRef(Start); 504 return object_error::success; 505 } 506 507 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 508 uint64_t &Res) const { 509 if (is64Bit()) { 510 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 511 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 512 Entry.n_value == 0) 513 Res = UnknownAddressOrSize; 514 else 515 Res = Entry.n_value; 516 } else { 517 MachO::nlist Entry = getSymbolTableEntry(Symb); 518 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 519 Entry.n_value == 0) 520 Res = UnknownAddressOrSize; 521 else 522 Res = Entry.n_value; 523 } 524 return object_error::success; 525 } 526 527 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 528 uint32_t &Result) const { 529 uint32_t flags = getSymbolFlags(DRI); 530 if (flags & SymbolRef::SF_Common) { 531 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 532 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 533 } else { 534 Result = 0; 535 } 536 return object_error::success; 537 } 538 539 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 540 uint64_t &Result) const { 541 uint64_t BeginOffset; 542 uint64_t EndOffset = 0; 543 uint8_t SectionIndex; 544 545 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 546 uint64_t Value; 547 getSymbolAddress(DRI, Value); 548 if (Value == UnknownAddressOrSize) { 549 Result = UnknownAddressOrSize; 550 return object_error::success; 551 } 552 553 BeginOffset = Value; 554 555 SectionIndex = Entry.n_sect; 556 if (!SectionIndex) { 557 uint32_t flags = getSymbolFlags(DRI); 558 if (flags & SymbolRef::SF_Common) 559 Result = Value; 560 else 561 Result = UnknownAddressOrSize; 562 return object_error::success; 563 } 564 // Unfortunately symbols are unsorted so we need to touch all 565 // symbols from load command 566 for (const SymbolRef &Symbol : symbols()) { 567 DataRefImpl DRI = Symbol.getRawDataRefImpl(); 568 Entry = getSymbolTableEntryBase(this, DRI); 569 getSymbolAddress(DRI, Value); 570 if (Value == UnknownAddressOrSize) 571 continue; 572 if (Entry.n_sect == SectionIndex && Value > BeginOffset) 573 if (!EndOffset || Value < EndOffset) 574 EndOffset = Value; 575 } 576 if (!EndOffset) { 577 uint64_t Size; 578 DataRefImpl Sec; 579 Sec.d.a = SectionIndex-1; 580 getSectionSize(Sec, Size); 581 getSectionAddress(Sec, EndOffset); 582 EndOffset += Size; 583 } 584 Result = EndOffset - BeginOffset; 585 return object_error::success; 586 } 587 588 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 589 SymbolRef::Type &Res) const { 590 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 591 uint8_t n_type = Entry.n_type; 592 593 Res = SymbolRef::ST_Other; 594 595 // If this is a STAB debugging symbol, we can do nothing more. 596 if (n_type & MachO::N_STAB) { 597 Res = SymbolRef::ST_Debug; 598 return object_error::success; 599 } 600 601 switch (n_type & MachO::N_TYPE) { 602 case MachO::N_UNDF : 603 Res = SymbolRef::ST_Unknown; 604 break; 605 case MachO::N_SECT : 606 Res = SymbolRef::ST_Function; 607 break; 608 } 609 return object_error::success; 610 } 611 612 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 613 nlist_base Entry = getSymbolTableEntryBase(this, DRI); 614 615 uint8_t MachOType = Entry.n_type; 616 uint16_t MachOFlags = Entry.n_desc; 617 618 uint32_t Result = SymbolRef::SF_None; 619 620 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 621 Result |= SymbolRef::SF_Undefined; 622 623 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 624 Result |= SymbolRef::SF_Indirect; 625 626 if (MachOType & MachO::N_STAB) 627 Result |= SymbolRef::SF_FormatSpecific; 628 629 if (MachOType & MachO::N_EXT) { 630 Result |= SymbolRef::SF_Global; 631 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 632 uint64_t Value; 633 getSymbolAddress(DRI, Value); 634 if (Value && Value != UnknownAddressOrSize) 635 Result |= SymbolRef::SF_Common; 636 } 637 } 638 639 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 640 Result |= SymbolRef::SF_Weak; 641 642 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 643 Result |= SymbolRef::SF_Absolute; 644 645 return Result; 646 } 647 648 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 649 section_iterator &Res) const { 650 nlist_base Entry = getSymbolTableEntryBase(this, Symb); 651 uint8_t index = Entry.n_sect; 652 653 if (index == 0) { 654 Res = section_end(); 655 } else { 656 DataRefImpl DRI; 657 DRI.d.a = index - 1; 658 Res = section_iterator(SectionRef(DRI, this)); 659 } 660 661 return object_error::success; 662 } 663 664 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 665 Sec.d.a++; 666 } 667 668 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 669 StringRef &Result) const { 670 ArrayRef<char> Raw = getSectionRawName(Sec); 671 Result = parseSegmentOrSectionName(Raw.data()); 672 return object_error::success; 673 } 674 675 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, 676 uint64_t &Res) const { 677 if (is64Bit()) { 678 MachO::section_64 Sect = getSection64(Sec); 679 Res = Sect.addr; 680 } else { 681 MachO::section Sect = getSection(Sec); 682 Res = Sect.addr; 683 } 684 return object_error::success; 685 } 686 687 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, 688 uint64_t &Res) const { 689 if (is64Bit()) { 690 MachO::section_64 Sect = getSection64(Sec); 691 Res = Sect.size; 692 } else { 693 MachO::section Sect = getSection(Sec); 694 Res = Sect.size; 695 } 696 697 return object_error::success; 698 } 699 700 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 701 StringRef &Res) const { 702 uint32_t Offset; 703 uint64_t Size; 704 705 if (is64Bit()) { 706 MachO::section_64 Sect = getSection64(Sec); 707 Offset = Sect.offset; 708 Size = Sect.size; 709 } else { 710 MachO::section Sect = getSection(Sec); 711 Offset = Sect.offset; 712 Size = Sect.size; 713 } 714 715 Res = this->getData().substr(Offset, Size); 716 return object_error::success; 717 } 718 719 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 720 uint64_t &Res) const { 721 uint32_t Align; 722 if (is64Bit()) { 723 MachO::section_64 Sect = getSection64(Sec); 724 Align = Sect.align; 725 } else { 726 MachO::section Sect = getSection(Sec); 727 Align = Sect.align; 728 } 729 730 Res = uint64_t(1) << Align; 731 return object_error::success; 732 } 733 734 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, 735 bool &Res) const { 736 uint32_t Flags = getSectionFlags(this, Sec); 737 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 738 return object_error::success; 739 } 740 741 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, 742 bool &Result) const { 743 uint32_t Flags = getSectionFlags(this, Sec); 744 unsigned SectionType = Flags & MachO::SECTION_TYPE; 745 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 746 !(SectionType == MachO::S_ZEROFILL || 747 SectionType == MachO::S_GB_ZEROFILL); 748 return object_error::success; 749 } 750 751 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, 752 bool &Result) const { 753 uint32_t Flags = getSectionFlags(this, Sec); 754 unsigned SectionType = Flags & MachO::SECTION_TYPE; 755 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 756 (SectionType == MachO::S_ZEROFILL || 757 SectionType == MachO::S_GB_ZEROFILL); 758 return object_error::success; 759 } 760 761 std::error_code 762 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 763 bool &Result) const { 764 // FIXME: Unimplemented. 765 Result = true; 766 return object_error::success; 767 } 768 769 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 770 bool &Result) const { 771 // FIXME: Unimplemented. 772 Result = false; 773 return object_error::success; 774 } 775 776 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, 777 bool &Res) const { 778 uint32_t Flags = getSectionFlags(this, Sec); 779 unsigned SectionType = Flags & MachO::SECTION_TYPE; 780 Res = SectionType == MachO::S_ZEROFILL || 781 SectionType == MachO::S_GB_ZEROFILL; 782 return object_error::success; 783 } 784 785 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 786 bool &Result) const { 787 // Consider using the code from isSectionText to look for __const sections. 788 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 789 // to use section attributes to distinguish code from data. 790 791 // FIXME: Unimplemented. 792 Result = false; 793 return object_error::success; 794 } 795 796 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 797 DataRefImpl Symb, 798 bool &Result) const { 799 SymbolRef::Type ST; 800 this->getSymbolType(Symb, ST); 801 if (ST == SymbolRef::ST_Unknown) { 802 Result = false; 803 return object_error::success; 804 } 805 806 uint64_t SectBegin, SectEnd; 807 getSectionAddress(Sec, SectBegin); 808 getSectionSize(Sec, SectEnd); 809 SectEnd += SectBegin; 810 811 uint64_t SymAddr; 812 getSymbolAddress(Symb, SymAddr); 813 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 814 815 return object_error::success; 816 } 817 818 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 819 DataRefImpl Ret; 820 Ret.d.a = Sec.d.a; 821 Ret.d.b = 0; 822 return relocation_iterator(RelocationRef(Ret, this)); 823 } 824 825 relocation_iterator 826 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 827 uint32_t Num; 828 if (is64Bit()) { 829 MachO::section_64 Sect = getSection64(Sec); 830 Num = Sect.nreloc; 831 } else { 832 MachO::section Sect = getSection(Sec); 833 Num = Sect.nreloc; 834 } 835 836 DataRefImpl Ret; 837 Ret.d.a = Sec.d.a; 838 Ret.d.b = Num; 839 return relocation_iterator(RelocationRef(Ret, this)); 840 } 841 842 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 843 ++Rel.d.b; 844 } 845 846 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 847 uint64_t &Res) const { 848 uint64_t Offset; 849 getRelocationOffset(Rel, Offset); 850 851 DataRefImpl Sec; 852 Sec.d.a = Rel.d.a; 853 uint64_t SecAddress; 854 getSectionAddress(Sec, SecAddress); 855 Res = SecAddress + Offset; 856 return object_error::success; 857 } 858 859 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 860 uint64_t &Res) const { 861 assert(getHeader().filetype == MachO::MH_OBJECT && 862 "Only implemented for MH_OBJECT"); 863 MachO::any_relocation_info RE = getRelocation(Rel); 864 Res = getAnyRelocationAddress(RE); 865 return object_error::success; 866 } 867 868 symbol_iterator 869 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 870 MachO::any_relocation_info RE = getRelocation(Rel); 871 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 872 bool isExtern = getPlainRelocationExternal(RE); 873 if (!isExtern) 874 return symbol_end(); 875 876 MachO::symtab_command S = getSymtabLoadCommand(); 877 unsigned SymbolTableEntrySize = is64Bit() ? 878 sizeof(MachO::nlist_64) : 879 sizeof(MachO::nlist); 880 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 881 DataRefImpl Sym; 882 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 883 return symbol_iterator(SymbolRef(Sym, this)); 884 } 885 886 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 887 uint64_t &Res) const { 888 MachO::any_relocation_info RE = getRelocation(Rel); 889 Res = getAnyRelocationType(RE); 890 return object_error::success; 891 } 892 893 std::error_code 894 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 895 SmallVectorImpl<char> &Result) const { 896 StringRef res; 897 uint64_t RType; 898 getRelocationType(Rel, RType); 899 900 unsigned Arch = this->getArch(); 901 902 switch (Arch) { 903 case Triple::x86: { 904 static const char *const Table[] = { 905 "GENERIC_RELOC_VANILLA", 906 "GENERIC_RELOC_PAIR", 907 "GENERIC_RELOC_SECTDIFF", 908 "GENERIC_RELOC_PB_LA_PTR", 909 "GENERIC_RELOC_LOCAL_SECTDIFF", 910 "GENERIC_RELOC_TLV" }; 911 912 if (RType > 5) 913 res = "Unknown"; 914 else 915 res = Table[RType]; 916 break; 917 } 918 case Triple::x86_64: { 919 static const char *const Table[] = { 920 "X86_64_RELOC_UNSIGNED", 921 "X86_64_RELOC_SIGNED", 922 "X86_64_RELOC_BRANCH", 923 "X86_64_RELOC_GOT_LOAD", 924 "X86_64_RELOC_GOT", 925 "X86_64_RELOC_SUBTRACTOR", 926 "X86_64_RELOC_SIGNED_1", 927 "X86_64_RELOC_SIGNED_2", 928 "X86_64_RELOC_SIGNED_4", 929 "X86_64_RELOC_TLV" }; 930 931 if (RType > 9) 932 res = "Unknown"; 933 else 934 res = Table[RType]; 935 break; 936 } 937 case Triple::arm: { 938 static const char *const Table[] = { 939 "ARM_RELOC_VANILLA", 940 "ARM_RELOC_PAIR", 941 "ARM_RELOC_SECTDIFF", 942 "ARM_RELOC_LOCAL_SECTDIFF", 943 "ARM_RELOC_PB_LA_PTR", 944 "ARM_RELOC_BR24", 945 "ARM_THUMB_RELOC_BR22", 946 "ARM_THUMB_32BIT_BRANCH", 947 "ARM_RELOC_HALF", 948 "ARM_RELOC_HALF_SECTDIFF" }; 949 950 if (RType > 9) 951 res = "Unknown"; 952 else 953 res = Table[RType]; 954 break; 955 } 956 case Triple::arm64: 957 case Triple::aarch64: { 958 static const char *const Table[] = { 959 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 960 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 961 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 962 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 963 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 964 "ARM64_RELOC_ADDEND" 965 }; 966 967 if (RType >= array_lengthof(Table)) 968 res = "Unknown"; 969 else 970 res = Table[RType]; 971 break; 972 } 973 case Triple::ppc: { 974 static const char *const Table[] = { 975 "PPC_RELOC_VANILLA", 976 "PPC_RELOC_PAIR", 977 "PPC_RELOC_BR14", 978 "PPC_RELOC_BR24", 979 "PPC_RELOC_HI16", 980 "PPC_RELOC_LO16", 981 "PPC_RELOC_HA16", 982 "PPC_RELOC_LO14", 983 "PPC_RELOC_SECTDIFF", 984 "PPC_RELOC_PB_LA_PTR", 985 "PPC_RELOC_HI16_SECTDIFF", 986 "PPC_RELOC_LO16_SECTDIFF", 987 "PPC_RELOC_HA16_SECTDIFF", 988 "PPC_RELOC_JBSR", 989 "PPC_RELOC_LO14_SECTDIFF", 990 "PPC_RELOC_LOCAL_SECTDIFF" }; 991 992 if (RType > 15) 993 res = "Unknown"; 994 else 995 res = Table[RType]; 996 break; 997 } 998 case Triple::UnknownArch: 999 res = "Unknown"; 1000 break; 1001 } 1002 Result.append(res.begin(), res.end()); 1003 return object_error::success; 1004 } 1005 1006 std::error_code 1007 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 1008 SmallVectorImpl<char> &Result) const { 1009 MachO::any_relocation_info RE = getRelocation(Rel); 1010 1011 unsigned Arch = this->getArch(); 1012 1013 std::string fmtbuf; 1014 raw_string_ostream fmt(fmtbuf); 1015 unsigned Type = this->getAnyRelocationType(RE); 1016 bool IsPCRel = this->getAnyRelocationPCRel(RE); 1017 1018 // Determine any addends that should be displayed with the relocation. 1019 // These require decoding the relocation type, which is triple-specific. 1020 1021 // X86_64 has entirely custom relocation types. 1022 if (Arch == Triple::x86_64) { 1023 bool isPCRel = getAnyRelocationPCRel(RE); 1024 1025 switch (Type) { 1026 case MachO::X86_64_RELOC_GOT_LOAD: 1027 case MachO::X86_64_RELOC_GOT: { 1028 printRelocationTargetName(this, RE, fmt); 1029 fmt << "@GOT"; 1030 if (isPCRel) fmt << "PCREL"; 1031 break; 1032 } 1033 case MachO::X86_64_RELOC_SUBTRACTOR: { 1034 DataRefImpl RelNext = Rel; 1035 moveRelocationNext(RelNext); 1036 MachO::any_relocation_info RENext = getRelocation(RelNext); 1037 1038 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 1039 // X86_64_RELOC_UNSIGNED. 1040 // NOTE: Scattered relocations don't exist on x86_64. 1041 unsigned RType = getAnyRelocationType(RENext); 1042 if (RType != MachO::X86_64_RELOC_UNSIGNED) 1043 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 1044 "X86_64_RELOC_SUBTRACTOR."); 1045 1046 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 1047 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 1048 printRelocationTargetName(this, RENext, fmt); 1049 fmt << "-"; 1050 printRelocationTargetName(this, RE, fmt); 1051 break; 1052 } 1053 case MachO::X86_64_RELOC_TLV: 1054 printRelocationTargetName(this, RE, fmt); 1055 fmt << "@TLV"; 1056 if (isPCRel) fmt << "P"; 1057 break; 1058 case MachO::X86_64_RELOC_SIGNED_1: 1059 printRelocationTargetName(this, RE, fmt); 1060 fmt << "-1"; 1061 break; 1062 case MachO::X86_64_RELOC_SIGNED_2: 1063 printRelocationTargetName(this, RE, fmt); 1064 fmt << "-2"; 1065 break; 1066 case MachO::X86_64_RELOC_SIGNED_4: 1067 printRelocationTargetName(this, RE, fmt); 1068 fmt << "-4"; 1069 break; 1070 default: 1071 printRelocationTargetName(this, RE, fmt); 1072 break; 1073 } 1074 // X86 and ARM share some relocation types in common. 1075 } else if (Arch == Triple::x86 || Arch == Triple::arm || 1076 Arch == Triple::ppc) { 1077 // Generic relocation types... 1078 switch (Type) { 1079 case MachO::GENERIC_RELOC_PAIR: // prints no info 1080 return object_error::success; 1081 case MachO::GENERIC_RELOC_SECTDIFF: { 1082 DataRefImpl RelNext = Rel; 1083 moveRelocationNext(RelNext); 1084 MachO::any_relocation_info RENext = getRelocation(RelNext); 1085 1086 // X86 sect diff's must be followed by a relocation of type 1087 // GENERIC_RELOC_PAIR. 1088 unsigned RType = getAnyRelocationType(RENext); 1089 1090 if (RType != MachO::GENERIC_RELOC_PAIR) 1091 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1092 "GENERIC_RELOC_SECTDIFF."); 1093 1094 printRelocationTargetName(this, RE, fmt); 1095 fmt << "-"; 1096 printRelocationTargetName(this, RENext, fmt); 1097 break; 1098 } 1099 } 1100 1101 if (Arch == Triple::x86 || Arch == Triple::ppc) { 1102 switch (Type) { 1103 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 1104 DataRefImpl RelNext = Rel; 1105 moveRelocationNext(RelNext); 1106 MachO::any_relocation_info RENext = getRelocation(RelNext); 1107 1108 // X86 sect diff's must be followed by a relocation of type 1109 // GENERIC_RELOC_PAIR. 1110 unsigned RType = getAnyRelocationType(RENext); 1111 if (RType != MachO::GENERIC_RELOC_PAIR) 1112 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 1113 "GENERIC_RELOC_LOCAL_SECTDIFF."); 1114 1115 printRelocationTargetName(this, RE, fmt); 1116 fmt << "-"; 1117 printRelocationTargetName(this, RENext, fmt); 1118 break; 1119 } 1120 case MachO::GENERIC_RELOC_TLV: { 1121 printRelocationTargetName(this, RE, fmt); 1122 fmt << "@TLV"; 1123 if (IsPCRel) fmt << "P"; 1124 break; 1125 } 1126 default: 1127 printRelocationTargetName(this, RE, fmt); 1128 } 1129 } else { // ARM-specific relocations 1130 switch (Type) { 1131 case MachO::ARM_RELOC_HALF: 1132 case MachO::ARM_RELOC_HALF_SECTDIFF: { 1133 // Half relocations steal a bit from the length field to encode 1134 // whether this is an upper16 or a lower16 relocation. 1135 bool isUpper = getAnyRelocationLength(RE) >> 1; 1136 1137 if (isUpper) 1138 fmt << ":upper16:("; 1139 else 1140 fmt << ":lower16:("; 1141 printRelocationTargetName(this, RE, fmt); 1142 1143 DataRefImpl RelNext = Rel; 1144 moveRelocationNext(RelNext); 1145 MachO::any_relocation_info RENext = getRelocation(RelNext); 1146 1147 // ARM half relocs must be followed by a relocation of type 1148 // ARM_RELOC_PAIR. 1149 unsigned RType = getAnyRelocationType(RENext); 1150 if (RType != MachO::ARM_RELOC_PAIR) 1151 report_fatal_error("Expected ARM_RELOC_PAIR after " 1152 "ARM_RELOC_HALF"); 1153 1154 // NOTE: The half of the target virtual address is stashed in the 1155 // address field of the secondary relocation, but we can't reverse 1156 // engineer the constant offset from it without decoding the movw/movt 1157 // instruction to find the other half in its immediate field. 1158 1159 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 1160 // symbol/section pointer of the follow-on relocation. 1161 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 1162 fmt << "-"; 1163 printRelocationTargetName(this, RENext, fmt); 1164 } 1165 1166 fmt << ")"; 1167 break; 1168 } 1169 default: { 1170 printRelocationTargetName(this, RE, fmt); 1171 } 1172 } 1173 } 1174 } else 1175 printRelocationTargetName(this, RE, fmt); 1176 1177 fmt.flush(); 1178 Result.append(fmtbuf.begin(), fmtbuf.end()); 1179 return object_error::success; 1180 } 1181 1182 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 1183 bool &Result) const { 1184 unsigned Arch = getArch(); 1185 uint64_t Type; 1186 getRelocationType(Rel, Type); 1187 1188 Result = false; 1189 1190 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 1191 // is always hidden. 1192 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 1193 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 1194 } else if (Arch == Triple::x86_64) { 1195 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 1196 // an X86_64_RELOC_SUBTRACTOR. 1197 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 1198 DataRefImpl RelPrev = Rel; 1199 RelPrev.d.a--; 1200 uint64_t PrevType; 1201 getRelocationType(RelPrev, PrevType); 1202 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 1203 Result = true; 1204 } 1205 } 1206 1207 return object_error::success; 1208 } 1209 1210 std::error_code MachOObjectFile::getLibraryNext(DataRefImpl LibData, 1211 LibraryRef &Res) const { 1212 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1213 } 1214 1215 std::error_code MachOObjectFile::getLibraryPath(DataRefImpl LibData, 1216 StringRef &Res) const { 1217 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1218 } 1219 1220 // 1221 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1222 // guess on what the short name is. Then name is returned as a substring of the 1223 // StringRef Name passed in. The name of the dynamic library is recognized as 1224 // a framework if it has one of the two following forms: 1225 // Foo.framework/Versions/A/Foo 1226 // Foo.framework/Foo 1227 // Where A and Foo can be any string. And may contain a trailing suffix 1228 // starting with an underbar. If the Name is recognized as a framework then 1229 // isFramework is set to true else it is set to false. If the Name has a 1230 // suffix then Suffix is set to the substring in Name that contains the suffix 1231 // else it is set to a NULL StringRef. 1232 // 1233 // The Name of the dynamic library is recognized as a library name if it has 1234 // one of the two following forms: 1235 // libFoo.A.dylib 1236 // libFoo.dylib 1237 // The library may have a suffix trailing the name Foo of the form: 1238 // libFoo_profile.A.dylib 1239 // libFoo_profile.dylib 1240 // 1241 // The Name of the dynamic library is also recognized as a library name if it 1242 // has the following form: 1243 // Foo.qtx 1244 // 1245 // If the Name of the dynamic library is none of the forms above then a NULL 1246 // StringRef is returned. 1247 // 1248 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1249 bool &isFramework, 1250 StringRef &Suffix) { 1251 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1252 size_t a, b, c, d, Idx; 1253 1254 isFramework = false; 1255 Suffix = StringRef(); 1256 1257 // Pull off the last component and make Foo point to it 1258 a = Name.rfind('/'); 1259 if (a == Name.npos || a == 0) 1260 goto guess_library; 1261 Foo = Name.slice(a+1, Name.npos); 1262 1263 // Look for a suffix starting with a '_' 1264 Idx = Foo.rfind('_'); 1265 if (Idx != Foo.npos && Foo.size() >= 2) { 1266 Suffix = Foo.slice(Idx, Foo.npos); 1267 Foo = Foo.slice(0, Idx); 1268 } 1269 1270 // First look for the form Foo.framework/Foo 1271 b = Name.rfind('/', a); 1272 if (b == Name.npos) 1273 Idx = 0; 1274 else 1275 Idx = b+1; 1276 F = Name.slice(Idx, Idx + Foo.size()); 1277 DotFramework = Name.slice(Idx + Foo.size(), 1278 Idx + Foo.size() + sizeof(".framework/")-1); 1279 if (F == Foo && DotFramework == ".framework/") { 1280 isFramework = true; 1281 return Foo; 1282 } 1283 1284 // Next look for the form Foo.framework/Versions/A/Foo 1285 if (b == Name.npos) 1286 goto guess_library; 1287 c = Name.rfind('/', b); 1288 if (c == Name.npos || c == 0) 1289 goto guess_library; 1290 V = Name.slice(c+1, Name.npos); 1291 if (!V.startswith("Versions/")) 1292 goto guess_library; 1293 d = Name.rfind('/', c); 1294 if (d == Name.npos) 1295 Idx = 0; 1296 else 1297 Idx = d+1; 1298 F = Name.slice(Idx, Idx + Foo.size()); 1299 DotFramework = Name.slice(Idx + Foo.size(), 1300 Idx + Foo.size() + sizeof(".framework/")-1); 1301 if (F == Foo && DotFramework == ".framework/") { 1302 isFramework = true; 1303 return Foo; 1304 } 1305 1306 guess_library: 1307 // pull off the suffix after the "." and make a point to it 1308 a = Name.rfind('.'); 1309 if (a == Name.npos || a == 0) 1310 return StringRef(); 1311 Dylib = Name.slice(a, Name.npos); 1312 if (Dylib != ".dylib") 1313 goto guess_qtx; 1314 1315 // First pull off the version letter for the form Foo.A.dylib if any. 1316 if (a >= 3) { 1317 Dot = Name.slice(a-2, a-1); 1318 if (Dot == ".") 1319 a = a - 2; 1320 } 1321 1322 b = Name.rfind('/', a); 1323 if (b == Name.npos) 1324 b = 0; 1325 else 1326 b = b+1; 1327 // ignore any suffix after an underbar like Foo_profile.A.dylib 1328 Idx = Name.find('_', b); 1329 if (Idx != Name.npos && Idx != b) { 1330 Lib = Name.slice(b, Idx); 1331 Suffix = Name.slice(Idx, a); 1332 } 1333 else 1334 Lib = Name.slice(b, a); 1335 // There are incorrect library names of the form: 1336 // libATS.A_profile.dylib so check for these. 1337 if (Lib.size() >= 3) { 1338 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1339 if (Dot == ".") 1340 Lib = Lib.slice(0, Lib.size()-2); 1341 } 1342 return Lib; 1343 1344 guess_qtx: 1345 Qtx = Name.slice(a, Name.npos); 1346 if (Qtx != ".qtx") 1347 return StringRef(); 1348 b = Name.rfind('/', a); 1349 if (b == Name.npos) 1350 Lib = Name.slice(0, a); 1351 else 1352 Lib = Name.slice(b+1, a); 1353 // There are library names of the form: QT.A.qtx so check for these. 1354 if (Lib.size() >= 3) { 1355 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1356 if (Dot == ".") 1357 Lib = Lib.slice(0, Lib.size()-2); 1358 } 1359 return Lib; 1360 } 1361 1362 // getLibraryShortNameByIndex() is used to get the short name of the library 1363 // for an undefined symbol in a linked Mach-O binary that was linked with the 1364 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1365 // It is passed the index (0 - based) of the library as translated from 1366 // GET_LIBRARY_ORDINAL (1 - based). 1367 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1368 StringRef &Res) { 1369 if (Index >= Libraries.size()) 1370 return object_error::parse_failed; 1371 1372 MachO::dylib_command D = 1373 getStruct<MachO::dylib_command>(this, Libraries[Index]); 1374 if (D.dylib.name >= D.cmdsize) 1375 return object_error::parse_failed; 1376 1377 // If the cache of LibrariesShortNames is not built up do that first for 1378 // all the Libraries. 1379 if (LibrariesShortNames.size() == 0) { 1380 for (unsigned i = 0; i < Libraries.size(); i++) { 1381 MachO::dylib_command D = 1382 getStruct<MachO::dylib_command>(this, Libraries[i]); 1383 if (D.dylib.name >= D.cmdsize) { 1384 LibrariesShortNames.push_back(StringRef()); 1385 continue; 1386 } 1387 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1388 StringRef Name = StringRef(P); 1389 StringRef Suffix; 1390 bool isFramework; 1391 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1392 if (shortName == StringRef()) 1393 LibrariesShortNames.push_back(Name); 1394 else 1395 LibrariesShortNames.push_back(shortName); 1396 } 1397 } 1398 1399 Res = LibrariesShortNames[Index]; 1400 return object_error::success; 1401 } 1402 1403 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1404 return getSymbolByIndex(0); 1405 } 1406 1407 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1408 DataRefImpl DRI; 1409 if (!SymtabLoadCmd) 1410 return basic_symbol_iterator(SymbolRef(DRI, this)); 1411 1412 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1413 unsigned SymbolTableEntrySize = is64Bit() ? 1414 sizeof(MachO::nlist_64) : 1415 sizeof(MachO::nlist); 1416 unsigned Offset = Symtab.symoff + 1417 Symtab.nsyms * SymbolTableEntrySize; 1418 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1419 return basic_symbol_iterator(SymbolRef(DRI, this)); 1420 } 1421 1422 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1423 DataRefImpl DRI; 1424 if (!SymtabLoadCmd) 1425 return basic_symbol_iterator(SymbolRef(DRI, this)); 1426 1427 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1428 assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 1429 unsigned SymbolTableEntrySize = 1430 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1431 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1432 DRI.p += Index * SymbolTableEntrySize; 1433 return basic_symbol_iterator(SymbolRef(DRI, this)); 1434 } 1435 1436 section_iterator MachOObjectFile::section_begin() const { 1437 DataRefImpl DRI; 1438 return section_iterator(SectionRef(DRI, this)); 1439 } 1440 1441 section_iterator MachOObjectFile::section_end() const { 1442 DataRefImpl DRI; 1443 DRI.d.a = Sections.size(); 1444 return section_iterator(SectionRef(DRI, this)); 1445 } 1446 1447 library_iterator MachOObjectFile::needed_library_begin() const { 1448 // TODO: implement 1449 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1450 } 1451 1452 library_iterator MachOObjectFile::needed_library_end() const { 1453 // TODO: implement 1454 report_fatal_error("Needed libraries unimplemented in MachOObjectFile"); 1455 } 1456 1457 uint8_t MachOObjectFile::getBytesInAddress() const { 1458 return is64Bit() ? 8 : 4; 1459 } 1460 1461 StringRef MachOObjectFile::getFileFormatName() const { 1462 unsigned CPUType = getCPUType(this); 1463 if (!is64Bit()) { 1464 switch (CPUType) { 1465 case llvm::MachO::CPU_TYPE_I386: 1466 return "Mach-O 32-bit i386"; 1467 case llvm::MachO::CPU_TYPE_ARM: 1468 return "Mach-O arm"; 1469 case llvm::MachO::CPU_TYPE_POWERPC: 1470 return "Mach-O 32-bit ppc"; 1471 default: 1472 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 1473 "64-bit object file when we're not 64-bit?"); 1474 return "Mach-O 32-bit unknown"; 1475 } 1476 } 1477 1478 // Make sure the cpu type has the correct mask. 1479 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 1480 == llvm::MachO::CPU_ARCH_ABI64 && 1481 "32-bit object file when we're 64-bit?"); 1482 1483 switch (CPUType) { 1484 case llvm::MachO::CPU_TYPE_X86_64: 1485 return "Mach-O 64-bit x86-64"; 1486 case llvm::MachO::CPU_TYPE_ARM64: 1487 return "Mach-O arm64"; 1488 case llvm::MachO::CPU_TYPE_POWERPC64: 1489 return "Mach-O 64-bit ppc64"; 1490 default: 1491 return "Mach-O 64-bit unknown"; 1492 } 1493 } 1494 1495 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1496 switch (CPUType) { 1497 case llvm::MachO::CPU_TYPE_I386: 1498 return Triple::x86; 1499 case llvm::MachO::CPU_TYPE_X86_64: 1500 return Triple::x86_64; 1501 case llvm::MachO::CPU_TYPE_ARM: 1502 return Triple::arm; 1503 case llvm::MachO::CPU_TYPE_ARM64: 1504 return Triple::arm64; 1505 case llvm::MachO::CPU_TYPE_POWERPC: 1506 return Triple::ppc; 1507 case llvm::MachO::CPU_TYPE_POWERPC64: 1508 return Triple::ppc64; 1509 default: 1510 return Triple::UnknownArch; 1511 } 1512 } 1513 1514 unsigned MachOObjectFile::getArch() const { 1515 return getArch(getCPUType(this)); 1516 } 1517 1518 StringRef MachOObjectFile::getLoadName() const { 1519 // TODO: Implement 1520 report_fatal_error("get_load_name() unimplemented in MachOObjectFile"); 1521 } 1522 1523 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1524 DataRefImpl DRI; 1525 DRI.d.a = Index; 1526 return section_rel_begin(DRI); 1527 } 1528 1529 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1530 DataRefImpl DRI; 1531 DRI.d.a = Index; 1532 return section_rel_end(DRI); 1533 } 1534 1535 dice_iterator MachOObjectFile::begin_dices() const { 1536 DataRefImpl DRI; 1537 if (!DataInCodeLoadCmd) 1538 return dice_iterator(DiceRef(DRI, this)); 1539 1540 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1541 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1542 return dice_iterator(DiceRef(DRI, this)); 1543 } 1544 1545 dice_iterator MachOObjectFile::end_dices() const { 1546 DataRefImpl DRI; 1547 if (!DataInCodeLoadCmd) 1548 return dice_iterator(DiceRef(DRI, this)); 1549 1550 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1551 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1552 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1553 return dice_iterator(DiceRef(DRI, this)); 1554 } 1555 1556 StringRef 1557 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1558 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1559 return parseSegmentOrSectionName(Raw.data()); 1560 } 1561 1562 ArrayRef<char> 1563 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1564 const section_base *Base = 1565 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1566 return ArrayRef<char>(Base->sectname); 1567 } 1568 1569 ArrayRef<char> 1570 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1571 const section_base *Base = 1572 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1573 return ArrayRef<char>(Base->segname); 1574 } 1575 1576 bool 1577 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1578 const { 1579 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1580 return false; 1581 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1582 } 1583 1584 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1585 const MachO::any_relocation_info &RE) const { 1586 if (isLittleEndian()) 1587 return RE.r_word1 & 0xffffff; 1588 return RE.r_word1 >> 8; 1589 } 1590 1591 bool MachOObjectFile::getPlainRelocationExternal( 1592 const MachO::any_relocation_info &RE) const { 1593 if (isLittleEndian()) 1594 return (RE.r_word1 >> 27) & 1; 1595 return (RE.r_word1 >> 4) & 1; 1596 } 1597 1598 bool MachOObjectFile::getScatteredRelocationScattered( 1599 const MachO::any_relocation_info &RE) const { 1600 return RE.r_word0 >> 31; 1601 } 1602 1603 uint32_t MachOObjectFile::getScatteredRelocationValue( 1604 const MachO::any_relocation_info &RE) const { 1605 return RE.r_word1; 1606 } 1607 1608 unsigned MachOObjectFile::getAnyRelocationAddress( 1609 const MachO::any_relocation_info &RE) const { 1610 if (isRelocationScattered(RE)) 1611 return getScatteredRelocationAddress(RE); 1612 return getPlainRelocationAddress(RE); 1613 } 1614 1615 unsigned MachOObjectFile::getAnyRelocationPCRel( 1616 const MachO::any_relocation_info &RE) const { 1617 if (isRelocationScattered(RE)) 1618 return getScatteredRelocationPCRel(this, RE); 1619 return getPlainRelocationPCRel(this, RE); 1620 } 1621 1622 unsigned MachOObjectFile::getAnyRelocationLength( 1623 const MachO::any_relocation_info &RE) const { 1624 if (isRelocationScattered(RE)) 1625 return getScatteredRelocationLength(RE); 1626 return getPlainRelocationLength(this, RE); 1627 } 1628 1629 unsigned 1630 MachOObjectFile::getAnyRelocationType( 1631 const MachO::any_relocation_info &RE) const { 1632 if (isRelocationScattered(RE)) 1633 return getScatteredRelocationType(RE); 1634 return getPlainRelocationType(this, RE); 1635 } 1636 1637 SectionRef 1638 MachOObjectFile::getRelocationSection( 1639 const MachO::any_relocation_info &RE) const { 1640 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1641 return *section_end(); 1642 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 1643 DataRefImpl DRI; 1644 DRI.d.a = SecNum; 1645 return SectionRef(DRI, this); 1646 } 1647 1648 MachOObjectFile::LoadCommandInfo 1649 MachOObjectFile::getFirstLoadCommandInfo() const { 1650 MachOObjectFile::LoadCommandInfo Load; 1651 1652 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 1653 sizeof(MachO::mach_header); 1654 Load.Ptr = getPtr(this, HeaderSize); 1655 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 1656 return Load; 1657 } 1658 1659 MachOObjectFile::LoadCommandInfo 1660 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 1661 MachOObjectFile::LoadCommandInfo Next; 1662 Next.Ptr = L.Ptr + L.C.cmdsize; 1663 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 1664 return Next; 1665 } 1666 1667 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1668 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1669 } 1670 1671 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1672 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1673 } 1674 1675 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1676 unsigned Index) const { 1677 const char *Sec = getSectionPtr(this, L, Index); 1678 return getStruct<MachO::section>(this, Sec); 1679 } 1680 1681 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1682 unsigned Index) const { 1683 const char *Sec = getSectionPtr(this, L, Index); 1684 return getStruct<MachO::section_64>(this, Sec); 1685 } 1686 1687 MachO::nlist 1688 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1689 const char *P = reinterpret_cast<const char *>(DRI.p); 1690 return getStruct<MachO::nlist>(this, P); 1691 } 1692 1693 MachO::nlist_64 1694 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1695 const char *P = reinterpret_cast<const char *>(DRI.p); 1696 return getStruct<MachO::nlist_64>(this, P); 1697 } 1698 1699 MachO::linkedit_data_command 1700 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1701 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1702 } 1703 1704 MachO::segment_command 1705 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1706 return getStruct<MachO::segment_command>(this, L.Ptr); 1707 } 1708 1709 MachO::segment_command_64 1710 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1711 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1712 } 1713 1714 MachO::linker_options_command 1715 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 1716 return getStruct<MachO::linker_options_command>(this, L.Ptr); 1717 } 1718 1719 MachO::version_min_command 1720 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1721 return getStruct<MachO::version_min_command>(this, L.Ptr); 1722 } 1723 1724 MachO::dylib_command 1725 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 1726 return getStruct<MachO::dylib_command>(this, L.Ptr); 1727 } 1728 1729 1730 MachO::any_relocation_info 1731 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 1732 DataRefImpl Sec; 1733 Sec.d.a = Rel.d.a; 1734 uint32_t Offset; 1735 if (is64Bit()) { 1736 MachO::section_64 Sect = getSection64(Sec); 1737 Offset = Sect.reloff; 1738 } else { 1739 MachO::section Sect = getSection(Sec); 1740 Offset = Sect.reloff; 1741 } 1742 1743 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 1744 getPtr(this, Offset)) + Rel.d.b; 1745 return getStruct<MachO::any_relocation_info>( 1746 this, reinterpret_cast<const char *>(P)); 1747 } 1748 1749 MachO::data_in_code_entry 1750 MachOObjectFile::getDice(DataRefImpl Rel) const { 1751 const char *P = reinterpret_cast<const char *>(Rel.p); 1752 return getStruct<MachO::data_in_code_entry>(this, P); 1753 } 1754 1755 MachO::mach_header MachOObjectFile::getHeader() const { 1756 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 1757 } 1758 1759 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 1760 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 1761 } 1762 1763 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 1764 const MachO::dysymtab_command &DLC, 1765 unsigned Index) const { 1766 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 1767 return getStruct<uint32_t>(this, getPtr(this, Offset)); 1768 } 1769 1770 MachO::data_in_code_entry 1771 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 1772 unsigned Index) const { 1773 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 1774 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 1775 } 1776 1777 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 1778 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1779 } 1780 1781 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 1782 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1783 } 1784 1785 MachO::linkedit_data_command 1786 MachOObjectFile::getDataInCodeLoadCommand() const { 1787 if (DataInCodeLoadCmd) 1788 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 1789 1790 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 1791 MachO::linkedit_data_command Cmd; 1792 Cmd.cmd = MachO::LC_DATA_IN_CODE; 1793 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 1794 Cmd.dataoff = 0; 1795 Cmd.datasize = 0; 1796 return Cmd; 1797 } 1798 1799 StringRef MachOObjectFile::getStringTableData() const { 1800 MachO::symtab_command S = getSymtabLoadCommand(); 1801 return getData().substr(S.stroff, S.strsize); 1802 } 1803 1804 bool MachOObjectFile::is64Bit() const { 1805 return getType() == getMachOType(false, true) || 1806 getType() == getMachOType(true, true); 1807 } 1808 1809 void MachOObjectFile::ReadULEB128s(uint64_t Index, 1810 SmallVectorImpl<uint64_t> &Out) const { 1811 DataExtractor extractor(ObjectFile::getData(), true, 0); 1812 1813 uint32_t offset = Index; 1814 uint64_t data = 0; 1815 while (uint64_t delta = extractor.getULEB128(&offset)) { 1816 data += delta; 1817 Out.push_back(data); 1818 } 1819 } 1820 1821 const char *MachOObjectFile::getSectionPointer(DataRefImpl Rel) const { 1822 return Sections[Rel.d.a]; 1823 } 1824 1825 ErrorOr<ObjectFile *> 1826 ObjectFile::createMachOObjectFile(std::unique_ptr<MemoryBuffer> &Buffer) { 1827 StringRef Magic = Buffer->getBuffer().slice(0, 4); 1828 std::error_code EC; 1829 std::unique_ptr<MachOObjectFile> Ret; 1830 if (Magic == "\xFE\xED\xFA\xCE") 1831 Ret.reset(new MachOObjectFile(std::move(Buffer), false, false, EC)); 1832 else if (Magic == "\xCE\xFA\xED\xFE") 1833 Ret.reset(new MachOObjectFile(std::move(Buffer), true, false, EC)); 1834 else if (Magic == "\xFE\xED\xFA\xCF") 1835 Ret.reset(new MachOObjectFile(std::move(Buffer), false, true, EC)); 1836 else if (Magic == "\xCF\xFA\xED\xFE") 1837 Ret.reset(new MachOObjectFile(std::move(Buffer), true, true, EC)); 1838 else 1839 return object_error::parse_failed; 1840 1841 if (EC) 1842 return EC; 1843 return Ret.release(); 1844 } 1845 1846 } // end namespace object 1847 } // end namespace llvm 1848