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