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