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