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