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