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