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