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