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