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