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