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, 1136 Triple *ThumbTriple) { 1137 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); 1138 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, 1139 McpuDefault); 1140 return T; 1141 } 1142 1143 Triple MachOObjectFile::getHostArch() { 1144 return Triple(sys::getDefaultTargetTriple()); 1145 } 1146 1147 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 1148 return StringSwitch<bool>(ArchFlag) 1149 .Case("i386", true) 1150 .Case("x86_64", true) 1151 .Case("x86_64h", true) 1152 .Case("armv4t", true) 1153 .Case("arm", true) 1154 .Case("armv5e", true) 1155 .Case("armv6", true) 1156 .Case("armv6m", true) 1157 .Case("armv7", true) 1158 .Case("armv7em", true) 1159 .Case("armv7k", true) 1160 .Case("armv7m", true) 1161 .Case("armv7s", true) 1162 .Case("arm64", true) 1163 .Case("ppc", true) 1164 .Case("ppc64", true) 1165 .Default(false); 1166 } 1167 1168 unsigned MachOObjectFile::getArch() const { 1169 return getArch(getCPUType(this)); 1170 } 1171 1172 Triple MachOObjectFile::getArch(const char **McpuDefault, 1173 Triple *ThumbTriple) const { 1174 *ThumbTriple = getThumbArch(Header.cputype, Header.cpusubtype, McpuDefault); 1175 return getArch(Header.cputype, Header.cpusubtype, McpuDefault); 1176 } 1177 1178 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1179 DataRefImpl DRI; 1180 DRI.d.a = Index; 1181 return section_rel_begin(DRI); 1182 } 1183 1184 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1185 DataRefImpl DRI; 1186 DRI.d.a = Index; 1187 return section_rel_end(DRI); 1188 } 1189 1190 dice_iterator MachOObjectFile::begin_dices() const { 1191 DataRefImpl DRI; 1192 if (!DataInCodeLoadCmd) 1193 return dice_iterator(DiceRef(DRI, this)); 1194 1195 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1196 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1197 return dice_iterator(DiceRef(DRI, this)); 1198 } 1199 1200 dice_iterator MachOObjectFile::end_dices() const { 1201 DataRefImpl DRI; 1202 if (!DataInCodeLoadCmd) 1203 return dice_iterator(DiceRef(DRI, this)); 1204 1205 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1206 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1207 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1208 return dice_iterator(DiceRef(DRI, this)); 1209 } 1210 1211 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 1212 : Trie(T), Malformed(false), Done(false) {} 1213 1214 void ExportEntry::moveToFirst() { 1215 pushNode(0); 1216 pushDownUntilBottom(); 1217 } 1218 1219 void ExportEntry::moveToEnd() { 1220 Stack.clear(); 1221 Done = true; 1222 } 1223 1224 bool ExportEntry::operator==(const ExportEntry &Other) const { 1225 // Common case, one at end, other iterating from begin. 1226 if (Done || Other.Done) 1227 return (Done == Other.Done); 1228 // Not equal if different stack sizes. 1229 if (Stack.size() != Other.Stack.size()) 1230 return false; 1231 // Not equal if different cumulative strings. 1232 if (!CumulativeString.equals(Other.CumulativeString)) 1233 return false; 1234 // Equal if all nodes in both stacks match. 1235 for (unsigned i=0; i < Stack.size(); ++i) { 1236 if (Stack[i].Start != Other.Stack[i].Start) 1237 return false; 1238 } 1239 return true; 1240 } 1241 1242 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 1243 unsigned Count; 1244 uint64_t Result = decodeULEB128(Ptr, &Count); 1245 Ptr += Count; 1246 if (Ptr > Trie.end()) { 1247 Ptr = Trie.end(); 1248 Malformed = true; 1249 } 1250 return Result; 1251 } 1252 1253 StringRef ExportEntry::name() const { 1254 return CumulativeString; 1255 } 1256 1257 uint64_t ExportEntry::flags() const { 1258 return Stack.back().Flags; 1259 } 1260 1261 uint64_t ExportEntry::address() const { 1262 return Stack.back().Address; 1263 } 1264 1265 uint64_t ExportEntry::other() const { 1266 return Stack.back().Other; 1267 } 1268 1269 StringRef ExportEntry::otherName() const { 1270 const char* ImportName = Stack.back().ImportName; 1271 if (ImportName) 1272 return StringRef(ImportName); 1273 return StringRef(); 1274 } 1275 1276 uint32_t ExportEntry::nodeOffset() const { 1277 return Stack.back().Start - Trie.begin(); 1278 } 1279 1280 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 1281 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 1282 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 1283 ParentStringLength(0), IsExportNode(false) {} 1284 1285 void ExportEntry::pushNode(uint64_t offset) { 1286 const uint8_t *Ptr = Trie.begin() + offset; 1287 NodeState State(Ptr); 1288 uint64_t ExportInfoSize = readULEB128(State.Current); 1289 State.IsExportNode = (ExportInfoSize != 0); 1290 const uint8_t* Children = State.Current + ExportInfoSize; 1291 if (State.IsExportNode) { 1292 State.Flags = readULEB128(State.Current); 1293 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 1294 State.Address = 0; 1295 State.Other = readULEB128(State.Current); // dylib ordinal 1296 State.ImportName = reinterpret_cast<const char*>(State.Current); 1297 } else { 1298 State.Address = readULEB128(State.Current); 1299 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 1300 State.Other = readULEB128(State.Current); 1301 } 1302 } 1303 State.ChildCount = *Children; 1304 State.Current = Children + 1; 1305 State.NextChildIndex = 0; 1306 State.ParentStringLength = CumulativeString.size(); 1307 Stack.push_back(State); 1308 } 1309 1310 void ExportEntry::pushDownUntilBottom() { 1311 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 1312 NodeState &Top = Stack.back(); 1313 CumulativeString.resize(Top.ParentStringLength); 1314 for (;*Top.Current != 0; Top.Current++) { 1315 char C = *Top.Current; 1316 CumulativeString.push_back(C); 1317 } 1318 Top.Current += 1; 1319 uint64_t childNodeIndex = readULEB128(Top.Current); 1320 Top.NextChildIndex += 1; 1321 pushNode(childNodeIndex); 1322 } 1323 if (!Stack.back().IsExportNode) { 1324 Malformed = true; 1325 moveToEnd(); 1326 } 1327 } 1328 1329 // We have a trie data structure and need a way to walk it that is compatible 1330 // with the C++ iterator model. The solution is a non-recursive depth first 1331 // traversal where the iterator contains a stack of parent nodes along with a 1332 // string that is the accumulation of all edge strings along the parent chain 1333 // to this point. 1334 // 1335 // There is one "export" node for each exported symbol. But because some 1336 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 1337 // node may have child nodes too. 1338 // 1339 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 1340 // child until hitting a node with no children (which is an export node or 1341 // else the trie is malformed). On the way down, each node is pushed on the 1342 // stack ivar. If there is no more ways down, it pops up one and tries to go 1343 // down a sibling path until a childless node is reached. 1344 void ExportEntry::moveNext() { 1345 if (Stack.empty() || !Stack.back().IsExportNode) { 1346 Malformed = true; 1347 moveToEnd(); 1348 return; 1349 } 1350 1351 Stack.pop_back(); 1352 while (!Stack.empty()) { 1353 NodeState &Top = Stack.back(); 1354 if (Top.NextChildIndex < Top.ChildCount) { 1355 pushDownUntilBottom(); 1356 // Now at the next export node. 1357 return; 1358 } else { 1359 if (Top.IsExportNode) { 1360 // This node has no children but is itself an export node. 1361 CumulativeString.resize(Top.ParentStringLength); 1362 return; 1363 } 1364 Stack.pop_back(); 1365 } 1366 } 1367 Done = true; 1368 } 1369 1370 iterator_range<export_iterator> 1371 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 1372 ExportEntry Start(Trie); 1373 if (Trie.size() == 0) 1374 Start.moveToEnd(); 1375 else 1376 Start.moveToFirst(); 1377 1378 ExportEntry Finish(Trie); 1379 Finish.moveToEnd(); 1380 1381 return iterator_range<export_iterator>(export_iterator(Start), 1382 export_iterator(Finish)); 1383 } 1384 1385 iterator_range<export_iterator> MachOObjectFile::exports() const { 1386 return exports(getDyldInfoExportsTrie()); 1387 } 1388 1389 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 1390 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 1391 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 1392 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 1393 1394 void MachORebaseEntry::moveToFirst() { 1395 Ptr = Opcodes.begin(); 1396 moveNext(); 1397 } 1398 1399 void MachORebaseEntry::moveToEnd() { 1400 Ptr = Opcodes.end(); 1401 RemainingLoopCount = 0; 1402 Done = true; 1403 } 1404 1405 void MachORebaseEntry::moveNext() { 1406 // If in the middle of some loop, move to next rebasing in loop. 1407 SegmentOffset += AdvanceAmount; 1408 if (RemainingLoopCount) { 1409 --RemainingLoopCount; 1410 return; 1411 } 1412 if (Ptr == Opcodes.end()) { 1413 Done = true; 1414 return; 1415 } 1416 bool More = true; 1417 while (More && !Malformed) { 1418 // Parse next opcode and set up next loop. 1419 uint8_t Byte = *Ptr++; 1420 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 1421 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 1422 switch (Opcode) { 1423 case MachO::REBASE_OPCODE_DONE: 1424 More = false; 1425 Done = true; 1426 moveToEnd(); 1427 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 1428 break; 1429 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 1430 RebaseType = ImmValue; 1431 DEBUG_WITH_TYPE( 1432 "mach-o-rebase", 1433 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 1434 << "RebaseType=" << (int) RebaseType << "\n"); 1435 break; 1436 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 1437 SegmentIndex = ImmValue; 1438 SegmentOffset = readULEB128(); 1439 DEBUG_WITH_TYPE( 1440 "mach-o-rebase", 1441 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 1442 << "SegmentIndex=" << SegmentIndex << ", " 1443 << format("SegmentOffset=0x%06X", SegmentOffset) 1444 << "\n"); 1445 break; 1446 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 1447 SegmentOffset += readULEB128(); 1448 DEBUG_WITH_TYPE("mach-o-rebase", 1449 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 1450 << format("SegmentOffset=0x%06X", 1451 SegmentOffset) << "\n"); 1452 break; 1453 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 1454 SegmentOffset += ImmValue * PointerSize; 1455 DEBUG_WITH_TYPE("mach-o-rebase", 1456 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 1457 << format("SegmentOffset=0x%06X", 1458 SegmentOffset) << "\n"); 1459 break; 1460 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 1461 AdvanceAmount = PointerSize; 1462 RemainingLoopCount = ImmValue - 1; 1463 DEBUG_WITH_TYPE( 1464 "mach-o-rebase", 1465 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 1466 << format("SegmentOffset=0x%06X", SegmentOffset) 1467 << ", AdvanceAmount=" << AdvanceAmount 1468 << ", RemainingLoopCount=" << RemainingLoopCount 1469 << "\n"); 1470 return; 1471 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 1472 AdvanceAmount = PointerSize; 1473 RemainingLoopCount = readULEB128() - 1; 1474 DEBUG_WITH_TYPE( 1475 "mach-o-rebase", 1476 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 1477 << format("SegmentOffset=0x%06X", SegmentOffset) 1478 << ", AdvanceAmount=" << AdvanceAmount 1479 << ", RemainingLoopCount=" << RemainingLoopCount 1480 << "\n"); 1481 return; 1482 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 1483 AdvanceAmount = readULEB128() + PointerSize; 1484 RemainingLoopCount = 0; 1485 DEBUG_WITH_TYPE( 1486 "mach-o-rebase", 1487 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 1488 << format("SegmentOffset=0x%06X", SegmentOffset) 1489 << ", AdvanceAmount=" << AdvanceAmount 1490 << ", RemainingLoopCount=" << RemainingLoopCount 1491 << "\n"); 1492 return; 1493 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 1494 RemainingLoopCount = readULEB128() - 1; 1495 AdvanceAmount = readULEB128() + PointerSize; 1496 DEBUG_WITH_TYPE( 1497 "mach-o-rebase", 1498 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 1499 << format("SegmentOffset=0x%06X", SegmentOffset) 1500 << ", AdvanceAmount=" << AdvanceAmount 1501 << ", RemainingLoopCount=" << RemainingLoopCount 1502 << "\n"); 1503 return; 1504 default: 1505 Malformed = true; 1506 } 1507 } 1508 } 1509 1510 uint64_t MachORebaseEntry::readULEB128() { 1511 unsigned Count; 1512 uint64_t Result = decodeULEB128(Ptr, &Count); 1513 Ptr += Count; 1514 if (Ptr > Opcodes.end()) { 1515 Ptr = Opcodes.end(); 1516 Malformed = true; 1517 } 1518 return Result; 1519 } 1520 1521 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 1522 1523 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 1524 1525 StringRef MachORebaseEntry::typeName() const { 1526 switch (RebaseType) { 1527 case MachO::REBASE_TYPE_POINTER: 1528 return "pointer"; 1529 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 1530 return "text abs32"; 1531 case MachO::REBASE_TYPE_TEXT_PCREL32: 1532 return "text rel32"; 1533 } 1534 return "unknown"; 1535 } 1536 1537 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 1538 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 1539 return (Ptr == Other.Ptr) && 1540 (RemainingLoopCount == Other.RemainingLoopCount) && 1541 (Done == Other.Done); 1542 } 1543 1544 iterator_range<rebase_iterator> 1545 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 1546 MachORebaseEntry Start(Opcodes, is64); 1547 Start.moveToFirst(); 1548 1549 MachORebaseEntry Finish(Opcodes, is64); 1550 Finish.moveToEnd(); 1551 1552 return iterator_range<rebase_iterator>(rebase_iterator(Start), 1553 rebase_iterator(Finish)); 1554 } 1555 1556 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 1557 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 1558 } 1559 1560 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 1561 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 1562 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 1563 BindType(0), PointerSize(is64Bit ? 8 : 4), 1564 TableKind(BK), Malformed(false), Done(false) {} 1565 1566 void MachOBindEntry::moveToFirst() { 1567 Ptr = Opcodes.begin(); 1568 moveNext(); 1569 } 1570 1571 void MachOBindEntry::moveToEnd() { 1572 Ptr = Opcodes.end(); 1573 RemainingLoopCount = 0; 1574 Done = true; 1575 } 1576 1577 void MachOBindEntry::moveNext() { 1578 // If in the middle of some loop, move to next binding in loop. 1579 SegmentOffset += AdvanceAmount; 1580 if (RemainingLoopCount) { 1581 --RemainingLoopCount; 1582 return; 1583 } 1584 if (Ptr == Opcodes.end()) { 1585 Done = true; 1586 return; 1587 } 1588 bool More = true; 1589 while (More && !Malformed) { 1590 // Parse next opcode and set up next loop. 1591 uint8_t Byte = *Ptr++; 1592 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 1593 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 1594 int8_t SignExtended; 1595 const uint8_t *SymStart; 1596 switch (Opcode) { 1597 case MachO::BIND_OPCODE_DONE: 1598 if (TableKind == Kind::Lazy) { 1599 // Lazying bindings have a DONE opcode between entries. Need to ignore 1600 // it to advance to next entry. But need not if this is last entry. 1601 bool NotLastEntry = false; 1602 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 1603 if (*P) { 1604 NotLastEntry = true; 1605 } 1606 } 1607 if (NotLastEntry) 1608 break; 1609 } 1610 More = false; 1611 Done = true; 1612 moveToEnd(); 1613 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 1614 break; 1615 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 1616 Ordinal = ImmValue; 1617 DEBUG_WITH_TYPE( 1618 "mach-o-bind", 1619 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 1620 << "Ordinal=" << Ordinal << "\n"); 1621 break; 1622 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 1623 Ordinal = readULEB128(); 1624 DEBUG_WITH_TYPE( 1625 "mach-o-bind", 1626 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 1627 << "Ordinal=" << Ordinal << "\n"); 1628 break; 1629 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 1630 if (ImmValue) { 1631 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 1632 Ordinal = SignExtended; 1633 } else 1634 Ordinal = 0; 1635 DEBUG_WITH_TYPE( 1636 "mach-o-bind", 1637 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 1638 << "Ordinal=" << Ordinal << "\n"); 1639 break; 1640 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 1641 Flags = ImmValue; 1642 SymStart = Ptr; 1643 while (*Ptr) { 1644 ++Ptr; 1645 } 1646 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 1647 Ptr-SymStart); 1648 ++Ptr; 1649 DEBUG_WITH_TYPE( 1650 "mach-o-bind", 1651 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 1652 << "SymbolName=" << SymbolName << "\n"); 1653 if (TableKind == Kind::Weak) { 1654 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 1655 return; 1656 } 1657 break; 1658 case MachO::BIND_OPCODE_SET_TYPE_IMM: 1659 BindType = ImmValue; 1660 DEBUG_WITH_TYPE( 1661 "mach-o-bind", 1662 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 1663 << "BindType=" << (int)BindType << "\n"); 1664 break; 1665 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 1666 Addend = readSLEB128(); 1667 if (TableKind == Kind::Lazy) 1668 Malformed = true; 1669 DEBUG_WITH_TYPE( 1670 "mach-o-bind", 1671 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 1672 << "Addend=" << Addend << "\n"); 1673 break; 1674 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 1675 SegmentIndex = ImmValue; 1676 SegmentOffset = readULEB128(); 1677 DEBUG_WITH_TYPE( 1678 "mach-o-bind", 1679 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 1680 << "SegmentIndex=" << SegmentIndex << ", " 1681 << format("SegmentOffset=0x%06X", SegmentOffset) 1682 << "\n"); 1683 break; 1684 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 1685 SegmentOffset += readULEB128(); 1686 DEBUG_WITH_TYPE("mach-o-bind", 1687 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 1688 << format("SegmentOffset=0x%06X", 1689 SegmentOffset) << "\n"); 1690 break; 1691 case MachO::BIND_OPCODE_DO_BIND: 1692 AdvanceAmount = PointerSize; 1693 RemainingLoopCount = 0; 1694 DEBUG_WITH_TYPE("mach-o-bind", 1695 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 1696 << format("SegmentOffset=0x%06X", 1697 SegmentOffset) << "\n"); 1698 return; 1699 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 1700 AdvanceAmount = readULEB128() + PointerSize; 1701 RemainingLoopCount = 0; 1702 if (TableKind == Kind::Lazy) 1703 Malformed = true; 1704 DEBUG_WITH_TYPE( 1705 "mach-o-bind", 1706 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 1707 << format("SegmentOffset=0x%06X", SegmentOffset) 1708 << ", AdvanceAmount=" << AdvanceAmount 1709 << ", RemainingLoopCount=" << RemainingLoopCount 1710 << "\n"); 1711 return; 1712 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 1713 AdvanceAmount = ImmValue * PointerSize + PointerSize; 1714 RemainingLoopCount = 0; 1715 if (TableKind == Kind::Lazy) 1716 Malformed = true; 1717 DEBUG_WITH_TYPE("mach-o-bind", 1718 llvm::dbgs() 1719 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 1720 << format("SegmentOffset=0x%06X", 1721 SegmentOffset) << "\n"); 1722 return; 1723 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 1724 RemainingLoopCount = readULEB128() - 1; 1725 AdvanceAmount = readULEB128() + PointerSize; 1726 if (TableKind == Kind::Lazy) 1727 Malformed = true; 1728 DEBUG_WITH_TYPE( 1729 "mach-o-bind", 1730 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 1731 << format("SegmentOffset=0x%06X", SegmentOffset) 1732 << ", AdvanceAmount=" << AdvanceAmount 1733 << ", RemainingLoopCount=" << RemainingLoopCount 1734 << "\n"); 1735 return; 1736 default: 1737 Malformed = true; 1738 } 1739 } 1740 } 1741 1742 uint64_t MachOBindEntry::readULEB128() { 1743 unsigned Count; 1744 uint64_t Result = decodeULEB128(Ptr, &Count); 1745 Ptr += Count; 1746 if (Ptr > Opcodes.end()) { 1747 Ptr = Opcodes.end(); 1748 Malformed = true; 1749 } 1750 return Result; 1751 } 1752 1753 int64_t MachOBindEntry::readSLEB128() { 1754 unsigned Count; 1755 int64_t Result = decodeSLEB128(Ptr, &Count); 1756 Ptr += Count; 1757 if (Ptr > Opcodes.end()) { 1758 Ptr = Opcodes.end(); 1759 Malformed = true; 1760 } 1761 return Result; 1762 } 1763 1764 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 1765 1766 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 1767 1768 StringRef MachOBindEntry::typeName() const { 1769 switch (BindType) { 1770 case MachO::BIND_TYPE_POINTER: 1771 return "pointer"; 1772 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 1773 return "text abs32"; 1774 case MachO::BIND_TYPE_TEXT_PCREL32: 1775 return "text rel32"; 1776 } 1777 return "unknown"; 1778 } 1779 1780 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 1781 1782 int64_t MachOBindEntry::addend() const { return Addend; } 1783 1784 uint32_t MachOBindEntry::flags() const { return Flags; } 1785 1786 int MachOBindEntry::ordinal() const { return Ordinal; } 1787 1788 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 1789 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 1790 return (Ptr == Other.Ptr) && 1791 (RemainingLoopCount == Other.RemainingLoopCount) && 1792 (Done == Other.Done); 1793 } 1794 1795 iterator_range<bind_iterator> 1796 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 1797 MachOBindEntry::Kind BKind) { 1798 MachOBindEntry Start(Opcodes, is64, BKind); 1799 Start.moveToFirst(); 1800 1801 MachOBindEntry Finish(Opcodes, is64, BKind); 1802 Finish.moveToEnd(); 1803 1804 return iterator_range<bind_iterator>(bind_iterator(Start), 1805 bind_iterator(Finish)); 1806 } 1807 1808 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 1809 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 1810 MachOBindEntry::Kind::Regular); 1811 } 1812 1813 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 1814 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 1815 MachOBindEntry::Kind::Lazy); 1816 } 1817 1818 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 1819 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 1820 MachOBindEntry::Kind::Weak); 1821 } 1822 1823 MachOObjectFile::load_command_iterator 1824 MachOObjectFile::begin_load_commands() const { 1825 return LoadCommands.begin(); 1826 } 1827 1828 MachOObjectFile::load_command_iterator 1829 MachOObjectFile::end_load_commands() const { 1830 return LoadCommands.end(); 1831 } 1832 1833 iterator_range<MachOObjectFile::load_command_iterator> 1834 MachOObjectFile::load_commands() const { 1835 return iterator_range<load_command_iterator>(begin_load_commands(), 1836 end_load_commands()); 1837 } 1838 1839 StringRef 1840 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 1841 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 1842 return parseSegmentOrSectionName(Raw.data()); 1843 } 1844 1845 ArrayRef<char> 1846 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 1847 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 1848 const section_base *Base = 1849 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1850 return makeArrayRef(Base->sectname); 1851 } 1852 1853 ArrayRef<char> 1854 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 1855 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 1856 const section_base *Base = 1857 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 1858 return makeArrayRef(Base->segname); 1859 } 1860 1861 bool 1862 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 1863 const { 1864 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 1865 return false; 1866 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 1867 } 1868 1869 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 1870 const MachO::any_relocation_info &RE) const { 1871 if (isLittleEndian()) 1872 return RE.r_word1 & 0xffffff; 1873 return RE.r_word1 >> 8; 1874 } 1875 1876 bool MachOObjectFile::getPlainRelocationExternal( 1877 const MachO::any_relocation_info &RE) const { 1878 if (isLittleEndian()) 1879 return (RE.r_word1 >> 27) & 1; 1880 return (RE.r_word1 >> 4) & 1; 1881 } 1882 1883 bool MachOObjectFile::getScatteredRelocationScattered( 1884 const MachO::any_relocation_info &RE) const { 1885 return RE.r_word0 >> 31; 1886 } 1887 1888 uint32_t MachOObjectFile::getScatteredRelocationValue( 1889 const MachO::any_relocation_info &RE) const { 1890 return RE.r_word1; 1891 } 1892 1893 uint32_t MachOObjectFile::getScatteredRelocationType( 1894 const MachO::any_relocation_info &RE) const { 1895 return (RE.r_word0 >> 24) & 0xf; 1896 } 1897 1898 unsigned MachOObjectFile::getAnyRelocationAddress( 1899 const MachO::any_relocation_info &RE) const { 1900 if (isRelocationScattered(RE)) 1901 return getScatteredRelocationAddress(RE); 1902 return getPlainRelocationAddress(RE); 1903 } 1904 1905 unsigned MachOObjectFile::getAnyRelocationPCRel( 1906 const MachO::any_relocation_info &RE) const { 1907 if (isRelocationScattered(RE)) 1908 return getScatteredRelocationPCRel(this, RE); 1909 return getPlainRelocationPCRel(this, RE); 1910 } 1911 1912 unsigned MachOObjectFile::getAnyRelocationLength( 1913 const MachO::any_relocation_info &RE) const { 1914 if (isRelocationScattered(RE)) 1915 return getScatteredRelocationLength(RE); 1916 return getPlainRelocationLength(this, RE); 1917 } 1918 1919 unsigned 1920 MachOObjectFile::getAnyRelocationType( 1921 const MachO::any_relocation_info &RE) const { 1922 if (isRelocationScattered(RE)) 1923 return getScatteredRelocationType(RE); 1924 return getPlainRelocationType(this, RE); 1925 } 1926 1927 SectionRef 1928 MachOObjectFile::getAnyRelocationSection( 1929 const MachO::any_relocation_info &RE) const { 1930 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 1931 return *section_end(); 1932 unsigned SecNum = getPlainRelocationSymbolNum(RE); 1933 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 1934 return *section_end(); 1935 DataRefImpl DRI; 1936 DRI.d.a = SecNum - 1; 1937 return SectionRef(DRI, this); 1938 } 1939 1940 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 1941 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 1942 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 1943 } 1944 1945 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 1946 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 1947 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 1948 } 1949 1950 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 1951 unsigned Index) const { 1952 const char *Sec = getSectionPtr(this, L, Index); 1953 return getStruct<MachO::section>(this, Sec); 1954 } 1955 1956 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 1957 unsigned Index) const { 1958 const char *Sec = getSectionPtr(this, L, Index); 1959 return getStruct<MachO::section_64>(this, Sec); 1960 } 1961 1962 MachO::nlist 1963 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 1964 const char *P = reinterpret_cast<const char *>(DRI.p); 1965 return getStruct<MachO::nlist>(this, P); 1966 } 1967 1968 MachO::nlist_64 1969 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 1970 const char *P = reinterpret_cast<const char *>(DRI.p); 1971 return getStruct<MachO::nlist_64>(this, P); 1972 } 1973 1974 MachO::linkedit_data_command 1975 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 1976 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 1977 } 1978 1979 MachO::segment_command 1980 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 1981 return getStruct<MachO::segment_command>(this, L.Ptr); 1982 } 1983 1984 MachO::segment_command_64 1985 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 1986 return getStruct<MachO::segment_command_64>(this, L.Ptr); 1987 } 1988 1989 MachO::linker_option_command 1990 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 1991 return getStruct<MachO::linker_option_command>(this, L.Ptr); 1992 } 1993 1994 MachO::version_min_command 1995 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 1996 return getStruct<MachO::version_min_command>(this, L.Ptr); 1997 } 1998 1999 MachO::dylib_command 2000 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 2001 return getStruct<MachO::dylib_command>(this, L.Ptr); 2002 } 2003 2004 MachO::dyld_info_command 2005 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 2006 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 2007 } 2008 2009 MachO::dylinker_command 2010 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 2011 return getStruct<MachO::dylinker_command>(this, L.Ptr); 2012 } 2013 2014 MachO::uuid_command 2015 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 2016 return getStruct<MachO::uuid_command>(this, L.Ptr); 2017 } 2018 2019 MachO::rpath_command 2020 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 2021 return getStruct<MachO::rpath_command>(this, L.Ptr); 2022 } 2023 2024 MachO::source_version_command 2025 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 2026 return getStruct<MachO::source_version_command>(this, L.Ptr); 2027 } 2028 2029 MachO::entry_point_command 2030 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 2031 return getStruct<MachO::entry_point_command>(this, L.Ptr); 2032 } 2033 2034 MachO::encryption_info_command 2035 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 2036 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 2037 } 2038 2039 MachO::encryption_info_command_64 2040 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 2041 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 2042 } 2043 2044 MachO::sub_framework_command 2045 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 2046 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 2047 } 2048 2049 MachO::sub_umbrella_command 2050 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 2051 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 2052 } 2053 2054 MachO::sub_library_command 2055 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 2056 return getStruct<MachO::sub_library_command>(this, L.Ptr); 2057 } 2058 2059 MachO::sub_client_command 2060 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 2061 return getStruct<MachO::sub_client_command>(this, L.Ptr); 2062 } 2063 2064 MachO::routines_command 2065 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 2066 return getStruct<MachO::routines_command>(this, L.Ptr); 2067 } 2068 2069 MachO::routines_command_64 2070 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 2071 return getStruct<MachO::routines_command_64>(this, L.Ptr); 2072 } 2073 2074 MachO::thread_command 2075 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 2076 return getStruct<MachO::thread_command>(this, L.Ptr); 2077 } 2078 2079 MachO::any_relocation_info 2080 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 2081 DataRefImpl Sec; 2082 Sec.d.a = Rel.d.a; 2083 uint32_t Offset; 2084 if (is64Bit()) { 2085 MachO::section_64 Sect = getSection64(Sec); 2086 Offset = Sect.reloff; 2087 } else { 2088 MachO::section Sect = getSection(Sec); 2089 Offset = Sect.reloff; 2090 } 2091 2092 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 2093 getPtr(this, Offset)) + Rel.d.b; 2094 return getStruct<MachO::any_relocation_info>( 2095 this, reinterpret_cast<const char *>(P)); 2096 } 2097 2098 MachO::data_in_code_entry 2099 MachOObjectFile::getDice(DataRefImpl Rel) const { 2100 const char *P = reinterpret_cast<const char *>(Rel.p); 2101 return getStruct<MachO::data_in_code_entry>(this, P); 2102 } 2103 2104 const MachO::mach_header &MachOObjectFile::getHeader() const { 2105 return Header; 2106 } 2107 2108 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 2109 assert(is64Bit()); 2110 return Header64; 2111 } 2112 2113 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 2114 const MachO::dysymtab_command &DLC, 2115 unsigned Index) const { 2116 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 2117 return getStruct<uint32_t>(this, getPtr(this, Offset)); 2118 } 2119 2120 MachO::data_in_code_entry 2121 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 2122 unsigned Index) const { 2123 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 2124 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 2125 } 2126 2127 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 2128 if (SymtabLoadCmd) 2129 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 2130 2131 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 2132 MachO::symtab_command Cmd; 2133 Cmd.cmd = MachO::LC_SYMTAB; 2134 Cmd.cmdsize = sizeof(MachO::symtab_command); 2135 Cmd.symoff = 0; 2136 Cmd.nsyms = 0; 2137 Cmd.stroff = 0; 2138 Cmd.strsize = 0; 2139 return Cmd; 2140 } 2141 2142 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 2143 if (DysymtabLoadCmd) 2144 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 2145 2146 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 2147 MachO::dysymtab_command Cmd; 2148 Cmd.cmd = MachO::LC_DYSYMTAB; 2149 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 2150 Cmd.ilocalsym = 0; 2151 Cmd.nlocalsym = 0; 2152 Cmd.iextdefsym = 0; 2153 Cmd.nextdefsym = 0; 2154 Cmd.iundefsym = 0; 2155 Cmd.nundefsym = 0; 2156 Cmd.tocoff = 0; 2157 Cmd.ntoc = 0; 2158 Cmd.modtaboff = 0; 2159 Cmd.nmodtab = 0; 2160 Cmd.extrefsymoff = 0; 2161 Cmd.nextrefsyms = 0; 2162 Cmd.indirectsymoff = 0; 2163 Cmd.nindirectsyms = 0; 2164 Cmd.extreloff = 0; 2165 Cmd.nextrel = 0; 2166 Cmd.locreloff = 0; 2167 Cmd.nlocrel = 0; 2168 return Cmd; 2169 } 2170 2171 MachO::linkedit_data_command 2172 MachOObjectFile::getDataInCodeLoadCommand() const { 2173 if (DataInCodeLoadCmd) 2174 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 2175 2176 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 2177 MachO::linkedit_data_command Cmd; 2178 Cmd.cmd = MachO::LC_DATA_IN_CODE; 2179 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 2180 Cmd.dataoff = 0; 2181 Cmd.datasize = 0; 2182 return Cmd; 2183 } 2184 2185 MachO::linkedit_data_command 2186 MachOObjectFile::getLinkOptHintsLoadCommand() const { 2187 if (LinkOptHintsLoadCmd) 2188 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 2189 2190 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 2191 // fields. 2192 MachO::linkedit_data_command Cmd; 2193 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 2194 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 2195 Cmd.dataoff = 0; 2196 Cmd.datasize = 0; 2197 return Cmd; 2198 } 2199 2200 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 2201 if (!DyldInfoLoadCmd) 2202 return None; 2203 2204 MachO::dyld_info_command DyldInfo = 2205 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2206 const uint8_t *Ptr = 2207 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 2208 return makeArrayRef(Ptr, DyldInfo.rebase_size); 2209 } 2210 2211 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 2212 if (!DyldInfoLoadCmd) 2213 return None; 2214 2215 MachO::dyld_info_command DyldInfo = 2216 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2217 const uint8_t *Ptr = 2218 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 2219 return makeArrayRef(Ptr, DyldInfo.bind_size); 2220 } 2221 2222 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 2223 if (!DyldInfoLoadCmd) 2224 return None; 2225 2226 MachO::dyld_info_command DyldInfo = 2227 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2228 const uint8_t *Ptr = 2229 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 2230 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 2231 } 2232 2233 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 2234 if (!DyldInfoLoadCmd) 2235 return None; 2236 2237 MachO::dyld_info_command DyldInfo = 2238 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2239 const uint8_t *Ptr = 2240 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 2241 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 2242 } 2243 2244 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 2245 if (!DyldInfoLoadCmd) 2246 return None; 2247 2248 MachO::dyld_info_command DyldInfo = 2249 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2250 const uint8_t *Ptr = 2251 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 2252 return makeArrayRef(Ptr, DyldInfo.export_size); 2253 } 2254 2255 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 2256 if (!UuidLoadCmd) 2257 return None; 2258 // Returning a pointer is fine as uuid doesn't need endian swapping. 2259 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 2260 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 2261 } 2262 2263 StringRef MachOObjectFile::getStringTableData() const { 2264 MachO::symtab_command S = getSymtabLoadCommand(); 2265 return getData().substr(S.stroff, S.strsize); 2266 } 2267 2268 bool MachOObjectFile::is64Bit() const { 2269 return getType() == getMachOType(false, true) || 2270 getType() == getMachOType(true, true); 2271 } 2272 2273 void MachOObjectFile::ReadULEB128s(uint64_t Index, 2274 SmallVectorImpl<uint64_t> &Out) const { 2275 DataExtractor extractor(ObjectFile::getData(), true, 0); 2276 2277 uint32_t offset = Index; 2278 uint64_t data = 0; 2279 while (uint64_t delta = extractor.getULEB128(&offset)) { 2280 data += delta; 2281 Out.push_back(data); 2282 } 2283 } 2284 2285 bool MachOObjectFile::isRelocatableObject() const { 2286 return getHeader().filetype == MachO::MH_OBJECT; 2287 } 2288 2289 ErrorOr<std::unique_ptr<MachOObjectFile>> 2290 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 2291 StringRef Magic = Buffer.getBuffer().slice(0, 4); 2292 std::error_code EC; 2293 std::unique_ptr<MachOObjectFile> Ret; 2294 if (Magic == "\xFE\xED\xFA\xCE") 2295 Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); 2296 else if (Magic == "\xCE\xFA\xED\xFE") 2297 Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); 2298 else if (Magic == "\xFE\xED\xFA\xCF") 2299 Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); 2300 else if (Magic == "\xCF\xFA\xED\xFE") 2301 Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); 2302 else 2303 return object_error::parse_failed; 2304 2305 if (EC) 2306 return EC; 2307 return std::move(Ret); 2308 } 2309