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