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