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