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