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