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