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