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