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 #include <list> 31 32 using namespace llvm; 33 using namespace object; 34 35 namespace { 36 struct section_base { 37 char sectname[16]; 38 char segname[16]; 39 }; 40 } 41 42 static Error 43 malformedError(Twine Msg) { 44 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")"; 45 return make_error<GenericBinaryError>(std::move(StringMsg), 46 object_error::parse_failed); 47 } 48 49 // FIXME: Replace all uses of this function with getStructOrErr. 50 template <typename T> 51 static T getStruct(const MachOObjectFile *O, const char *P) { 52 // Don't read before the beginning or past the end of the file 53 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) 54 report_fatal_error("Malformed MachO file."); 55 56 T Cmd; 57 memcpy(&Cmd, P, sizeof(T)); 58 if (O->isLittleEndian() != sys::IsLittleEndianHost) 59 MachO::swapStruct(Cmd); 60 return Cmd; 61 } 62 63 template <typename T> 64 static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) { 65 // Don't read before the beginning or past the end of the file 66 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) 67 return malformedError("Structure read out-of-range"); 68 69 T Cmd; 70 memcpy(&Cmd, P, sizeof(T)); 71 if (O->isLittleEndian() != sys::IsLittleEndianHost) 72 MachO::swapStruct(Cmd); 73 return Cmd; 74 } 75 76 static const char * 77 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 78 unsigned Sec) { 79 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 80 81 bool Is64 = O->is64Bit(); 82 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 83 sizeof(MachO::segment_command); 84 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 85 sizeof(MachO::section); 86 87 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 88 return reinterpret_cast<const char*>(SectionAddr); 89 } 90 91 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 92 return O->getData().substr(Offset, 1).data(); 93 } 94 95 static MachO::nlist_base 96 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 97 const char *P = reinterpret_cast<const char *>(DRI.p); 98 return getStruct<MachO::nlist_base>(O, P); 99 } 100 101 static StringRef parseSegmentOrSectionName(const char *P) { 102 if (P[15] == 0) 103 // Null terminated. 104 return P; 105 // Not null terminated, so this is a 16 char string. 106 return StringRef(P, 16); 107 } 108 109 // Helper to advance a section or symbol iterator multiple increments at a time. 110 template<class T> 111 static void advance(T &it, size_t Val) { 112 while (Val--) 113 ++it; 114 } 115 116 static unsigned getCPUType(const MachOObjectFile *O) { 117 return O->getHeader().cputype; 118 } 119 120 static uint32_t 121 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 122 return RE.r_word0; 123 } 124 125 static unsigned 126 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 127 return RE.r_word0 & 0xffffff; 128 } 129 130 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 131 const MachO::any_relocation_info &RE) { 132 if (O->isLittleEndian()) 133 return (RE.r_word1 >> 24) & 1; 134 return (RE.r_word1 >> 7) & 1; 135 } 136 137 static bool 138 getScatteredRelocationPCRel(const MachOObjectFile *O, 139 const MachO::any_relocation_info &RE) { 140 return (RE.r_word0 >> 30) & 1; 141 } 142 143 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 144 const MachO::any_relocation_info &RE) { 145 if (O->isLittleEndian()) 146 return (RE.r_word1 >> 25) & 3; 147 return (RE.r_word1 >> 5) & 3; 148 } 149 150 static unsigned 151 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 152 return (RE.r_word0 >> 28) & 3; 153 } 154 155 static unsigned getPlainRelocationType(const MachOObjectFile *O, 156 const MachO::any_relocation_info &RE) { 157 if (O->isLittleEndian()) 158 return RE.r_word1 >> 28; 159 return RE.r_word1 & 0xf; 160 } 161 162 static uint32_t getSectionFlags(const MachOObjectFile *O, 163 DataRefImpl Sec) { 164 if (O->is64Bit()) { 165 MachO::section_64 Sect = O->getSection64(Sec); 166 return Sect.flags; 167 } 168 MachO::section Sect = O->getSection(Sec); 169 return Sect.flags; 170 } 171 172 static Expected<MachOObjectFile::LoadCommandInfo> 173 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr, 174 uint32_t LoadCommandIndex) { 175 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) { 176 if (CmdOrErr->cmdsize < 8) 177 return malformedError("load command " + Twine(LoadCommandIndex) + 178 " with size less than 8 bytes"); 179 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr}); 180 } else 181 return CmdOrErr.takeError(); 182 } 183 184 static Expected<MachOObjectFile::LoadCommandInfo> 185 getFirstLoadCommandInfo(const MachOObjectFile *Obj) { 186 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 187 : sizeof(MachO::mach_header); 188 if (sizeof(MachO::load_command) > Obj->getHeader().sizeofcmds) 189 return malformedError("load command 0 extends past the end all load " 190 "commands in the file"); 191 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0); 192 } 193 194 static Expected<MachOObjectFile::LoadCommandInfo> 195 getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex, 196 const MachOObjectFile::LoadCommandInfo &L) { 197 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 198 : sizeof(MachO::mach_header); 199 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) > 200 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds) 201 return malformedError("load command " + Twine(LoadCommandIndex + 1) + 202 " extends past the end all load commands in the file"); 203 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1); 204 } 205 206 template <typename T> 207 static void parseHeader(const MachOObjectFile *Obj, T &Header, 208 Error &Err) { 209 if (sizeof(T) > Obj->getData().size()) { 210 Err = malformedError("the mach header extends past the end of the " 211 "file"); 212 return; 213 } 214 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0))) 215 Header = *HeaderOrErr; 216 else 217 Err = HeaderOrErr.takeError(); 218 } 219 220 // This is used to check for overlapping of Mach-O elements. 221 struct MachOElement { 222 uint64_t Offset; 223 uint64_t Size; 224 const char *Name; 225 }; 226 227 static Error checkOverlappingElement(std::list<MachOElement> &Elements, 228 uint64_t Offset, uint64_t Size, 229 const char *Name) { 230 if (Size == 0) 231 return Error::success(); 232 233 for (auto it=Elements.begin() ; it != Elements.end(); ++it) { 234 auto E = *it; 235 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) || 236 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) || 237 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size)) 238 return malformedError(Twine(Name) + " at offset " + Twine(Offset) + 239 " with a size of " + Twine(Size) + ", overlaps " + 240 E.Name + " at offset " + Twine(E.Offset) + " with " 241 "a size of " + Twine(E.Size)); 242 auto nt = it; 243 nt++; 244 if (nt != Elements.end()) { 245 auto N = *nt; 246 if (Offset + Size <= N.Offset) { 247 Elements.insert(nt, {Offset, Size, Name}); 248 return Error::success(); 249 } 250 } 251 } 252 Elements.push_back({Offset, Size, Name}); 253 return Error::success(); 254 } 255 256 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all 257 // sections to \param Sections, and optionally sets 258 // \param IsPageZeroSegment to true. 259 template <typename Segment, typename Section> 260 static Error parseSegmentLoadCommand( 261 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, 262 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment, 263 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders, 264 std::list<MachOElement> &Elements) { 265 const unsigned SegmentLoadSize = sizeof(Segment); 266 if (Load.C.cmdsize < SegmentLoadSize) 267 return malformedError("load command " + Twine(LoadCommandIndex) + 268 " " + CmdName + " cmdsize too small"); 269 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) { 270 Segment S = SegOrErr.get(); 271 const unsigned SectionSize = sizeof(Section); 272 uint64_t FileSize = Obj->getData().size(); 273 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize || 274 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) 275 return malformedError("load command " + Twine(LoadCommandIndex) + 276 " inconsistent cmdsize in " + CmdName + 277 " for the number of sections"); 278 for (unsigned J = 0; J < S.nsects; ++J) { 279 const char *Sec = getSectionPtr(Obj, Load, J); 280 Sections.push_back(Sec); 281 Section s = getStruct<Section>(Obj, Sec); 282 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 283 Obj->getHeader().filetype != MachO::MH_DSYM && 284 s.flags != MachO::S_ZEROFILL && 285 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 286 s.offset > FileSize) 287 return malformedError("offset field of section " + Twine(J) + " in " + 288 CmdName + " command " + Twine(LoadCommandIndex) + 289 " extends past the end of the file"); 290 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 291 Obj->getHeader().filetype != MachO::MH_DSYM && 292 s.flags != MachO::S_ZEROFILL && 293 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 && 294 s.offset < SizeOfHeaders && s.size != 0) 295 return malformedError("offset field of section " + Twine(J) + " in " + 296 CmdName + " command " + Twine(LoadCommandIndex) + 297 " not past the headers of the file"); 298 uint64_t BigSize = s.offset; 299 BigSize += s.size; 300 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 301 Obj->getHeader().filetype != MachO::MH_DSYM && 302 s.flags != MachO::S_ZEROFILL && 303 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 304 BigSize > FileSize) 305 return malformedError("offset field plus size field of section " + 306 Twine(J) + " in " + CmdName + " command " + 307 Twine(LoadCommandIndex) + 308 " extends past the end of the file"); 309 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 310 Obj->getHeader().filetype != MachO::MH_DSYM && 311 s.flags != MachO::S_ZEROFILL && 312 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 313 s.size > S.filesize) 314 return malformedError("size field of section " + 315 Twine(J) + " in " + CmdName + " command " + 316 Twine(LoadCommandIndex) + 317 " greater than the segment"); 318 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 319 Obj->getHeader().filetype != MachO::MH_DSYM && s.size != 0 && 320 s.addr < S.vmaddr) 321 return malformedError("addr field of section " + Twine(J) + " in " + 322 CmdName + " command " + Twine(LoadCommandIndex) + 323 " less than the segment's vmaddr"); 324 BigSize = s.addr; 325 BigSize += s.size; 326 uint64_t BigEnd = S.vmaddr; 327 BigEnd += S.vmsize; 328 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd) 329 return malformedError("addr field plus size of section " + Twine(J) + 330 " in " + CmdName + " command " + 331 Twine(LoadCommandIndex) + 332 " greater than than " 333 "the segment's vmaddr plus vmsize"); 334 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 335 Obj->getHeader().filetype != MachO::MH_DSYM && 336 s.flags != MachO::S_ZEROFILL && 337 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL) 338 if (Error Err = checkOverlappingElement(Elements, s.offset, s.size, 339 "section contents")) 340 return Err; 341 if (s.reloff > FileSize) 342 return malformedError("reloff field of section " + Twine(J) + " in " + 343 CmdName + " command " + Twine(LoadCommandIndex) + 344 " extends past the end of the file"); 345 BigSize = s.nreloc; 346 BigSize *= sizeof(struct MachO::relocation_info); 347 BigSize += s.reloff; 348 if (BigSize > FileSize) 349 return malformedError("reloff field plus nreloc field times sizeof(" 350 "struct relocation_info) of section " + 351 Twine(J) + " in " + CmdName + " command " + 352 Twine(LoadCommandIndex) + 353 " extends past the end of the file"); 354 if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc * 355 sizeof(struct 356 MachO::relocation_info), 357 "section relocation entries")) 358 return Err; 359 } 360 if (S.fileoff > FileSize) 361 return malformedError("load command " + Twine(LoadCommandIndex) + 362 " fileoff field in " + CmdName + 363 " extends past the end of the file"); 364 uint64_t BigSize = S.fileoff; 365 BigSize += S.filesize; 366 if (BigSize > FileSize) 367 return malformedError("load command " + Twine(LoadCommandIndex) + 368 " fileoff field plus filesize field in " + 369 CmdName + " extends past the end of the file"); 370 if (S.vmsize != 0 && S.filesize > S.vmsize) 371 return malformedError("load command " + Twine(LoadCommandIndex) + 372 " fileoff field in " + CmdName + 373 " greater than vmsize field"); 374 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); 375 } else 376 return SegOrErr.takeError(); 377 378 return Error::success(); 379 } 380 381 static Error checkSymtabCommand(const MachOObjectFile *Obj, 382 const MachOObjectFile::LoadCommandInfo &Load, 383 uint32_t LoadCommandIndex, 384 const char **SymtabLoadCmd, 385 std::list<MachOElement> &Elements) { 386 if (Load.C.cmdsize < sizeof(MachO::symtab_command)) 387 return malformedError("load command " + Twine(LoadCommandIndex) + 388 " LC_SYMTAB cmdsize too small"); 389 if (*SymtabLoadCmd != nullptr) 390 return malformedError("more than one LC_SYMTAB command"); 391 MachO::symtab_command Symtab = 392 getStruct<MachO::symtab_command>(Obj, Load.Ptr); 393 if (Symtab.cmdsize != sizeof(MachO::symtab_command)) 394 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) + 395 " has incorrect cmdsize"); 396 uint64_t FileSize = Obj->getData().size(); 397 if (Symtab.symoff > FileSize) 398 return malformedError("symoff field of LC_SYMTAB command " + 399 Twine(LoadCommandIndex) + " extends past the end " 400 "of the file"); 401 uint64_t SymtabSize = Symtab.nsyms; 402 const char *struct_nlist_name; 403 if (Obj->is64Bit()) { 404 SymtabSize *= sizeof(MachO::nlist_64); 405 struct_nlist_name = "struct nlist_64"; 406 } else { 407 SymtabSize *= sizeof(MachO::nlist); 408 struct_nlist_name = "struct nlist"; 409 } 410 uint64_t BigSize = SymtabSize; 411 BigSize += Symtab.symoff; 412 if (BigSize > FileSize) 413 return malformedError("symoff field plus nsyms field times sizeof(" + 414 Twine(struct_nlist_name) + ") of LC_SYMTAB command " + 415 Twine(LoadCommandIndex) + " extends past the end " 416 "of the file"); 417 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize, 418 "symbol table")) 419 return Err; 420 if (Symtab.stroff > FileSize) 421 return malformedError("stroff field of LC_SYMTAB command " + 422 Twine(LoadCommandIndex) + " extends past the end " 423 "of the file"); 424 BigSize = Symtab.stroff; 425 BigSize += Symtab.strsize; 426 if (BigSize > FileSize) 427 return malformedError("stroff field plus strsize field of LC_SYMTAB " 428 "command " + Twine(LoadCommandIndex) + " extends " 429 "past the end of the file"); 430 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff, 431 Symtab.strsize, "string table")) 432 return Err; 433 *SymtabLoadCmd = Load.Ptr; 434 return Error::success(); 435 } 436 437 static Error checkDysymtabCommand(const MachOObjectFile *Obj, 438 const MachOObjectFile::LoadCommandInfo &Load, 439 uint32_t LoadCommandIndex, 440 const char **DysymtabLoadCmd, 441 std::list<MachOElement> &Elements) { 442 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command)) 443 return malformedError("load command " + Twine(LoadCommandIndex) + 444 " LC_DYSYMTAB cmdsize too small"); 445 if (*DysymtabLoadCmd != nullptr) 446 return malformedError("more than one LC_DYSYMTAB command"); 447 MachO::dysymtab_command Dysymtab = 448 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr); 449 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command)) 450 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) + 451 " has incorrect cmdsize"); 452 uint64_t FileSize = Obj->getData().size(); 453 if (Dysymtab.tocoff > FileSize) 454 return malformedError("tocoff field of LC_DYSYMTAB command " + 455 Twine(LoadCommandIndex) + " extends past the end of " 456 "the file"); 457 uint64_t BigSize = Dysymtab.ntoc; 458 BigSize *= sizeof(MachO::dylib_table_of_contents); 459 BigSize += Dysymtab.tocoff; 460 if (BigSize > FileSize) 461 return malformedError("tocoff field plus ntoc field times sizeof(struct " 462 "dylib_table_of_contents) of LC_DYSYMTAB command " + 463 Twine(LoadCommandIndex) + " extends past the end of " 464 "the file"); 465 if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff, 466 Dysymtab.ntoc * sizeof(struct 467 MachO::dylib_table_of_contents), 468 "table of contents")) 469 return Err; 470 if (Dysymtab.modtaboff > FileSize) 471 return malformedError("modtaboff field of LC_DYSYMTAB command " + 472 Twine(LoadCommandIndex) + " extends past the end of " 473 "the file"); 474 BigSize = Dysymtab.nmodtab; 475 const char *struct_dylib_module_name; 476 uint64_t sizeof_modtab; 477 if (Obj->is64Bit()) { 478 sizeof_modtab = sizeof(MachO::dylib_module_64); 479 struct_dylib_module_name = "struct dylib_module_64"; 480 } else { 481 sizeof_modtab = sizeof(MachO::dylib_module); 482 struct_dylib_module_name = "struct dylib_module"; 483 } 484 BigSize *= sizeof_modtab; 485 BigSize += Dysymtab.modtaboff; 486 if (BigSize > FileSize) 487 return malformedError("modtaboff field plus nmodtab field times sizeof(" + 488 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB " 489 "command " + Twine(LoadCommandIndex) + " extends " 490 "past the end of the file"); 491 if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff, 492 Dysymtab.nmodtab * sizeof_modtab, 493 "module table")) 494 return Err; 495 if (Dysymtab.extrefsymoff > FileSize) 496 return malformedError("extrefsymoff field of LC_DYSYMTAB command " + 497 Twine(LoadCommandIndex) + " extends past the end of " 498 "the file"); 499 BigSize = Dysymtab.nextrefsyms; 500 BigSize *= sizeof(MachO::dylib_reference); 501 BigSize += Dysymtab.extrefsymoff; 502 if (BigSize > FileSize) 503 return malformedError("extrefsymoff field plus nextrefsyms field times " 504 "sizeof(struct dylib_reference) of LC_DYSYMTAB " 505 "command " + Twine(LoadCommandIndex) + " extends " 506 "past the end of the file"); 507 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff, 508 Dysymtab.nextrefsyms * 509 sizeof(MachO::dylib_reference), 510 "reference table")) 511 return Err; 512 if (Dysymtab.indirectsymoff > FileSize) 513 return malformedError("indirectsymoff field of LC_DYSYMTAB command " + 514 Twine(LoadCommandIndex) + " extends past the end of " 515 "the file"); 516 BigSize = Dysymtab.nindirectsyms; 517 BigSize *= sizeof(uint32_t); 518 BigSize += Dysymtab.indirectsymoff; 519 if (BigSize > FileSize) 520 return malformedError("indirectsymoff field plus nindirectsyms field times " 521 "sizeof(uint32_t) of LC_DYSYMTAB command " + 522 Twine(LoadCommandIndex) + " extends past the end of " 523 "the file"); 524 if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff, 525 Dysymtab.nindirectsyms * 526 sizeof(uint32_t), 527 "indirect table")) 528 return Err; 529 if (Dysymtab.extreloff > FileSize) 530 return malformedError("extreloff field of LC_DYSYMTAB command " + 531 Twine(LoadCommandIndex) + " extends past the end of " 532 "the file"); 533 BigSize = Dysymtab.nextrel; 534 BigSize *= sizeof(MachO::relocation_info); 535 BigSize += Dysymtab.extreloff; 536 if (BigSize > FileSize) 537 return malformedError("extreloff field plus nextrel field times sizeof" 538 "(struct relocation_info) of LC_DYSYMTAB command " + 539 Twine(LoadCommandIndex) + " extends past the end of " 540 "the file"); 541 if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff, 542 Dysymtab.nextrel * 543 sizeof(MachO::relocation_info), 544 "external relocation table")) 545 return Err; 546 if (Dysymtab.locreloff > FileSize) 547 return malformedError("locreloff field of LC_DYSYMTAB command " + 548 Twine(LoadCommandIndex) + " extends past the end of " 549 "the file"); 550 BigSize = Dysymtab.nlocrel; 551 BigSize *= sizeof(MachO::relocation_info); 552 BigSize += Dysymtab.locreloff; 553 if (BigSize > FileSize) 554 return malformedError("locreloff field plus nlocrel field times sizeof" 555 "(struct relocation_info) of LC_DYSYMTAB command " + 556 Twine(LoadCommandIndex) + " extends past the end of " 557 "the file"); 558 if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff, 559 Dysymtab.nlocrel * 560 sizeof(MachO::relocation_info), 561 "local relocation table")) 562 return Err; 563 *DysymtabLoadCmd = Load.Ptr; 564 return Error::success(); 565 } 566 567 static Error checkLinkeditDataCommand(const MachOObjectFile *Obj, 568 const MachOObjectFile::LoadCommandInfo &Load, 569 uint32_t LoadCommandIndex, 570 const char **LoadCmd, const char *CmdName, 571 std::list<MachOElement> &Elements, 572 const char *ElementName) { 573 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command)) 574 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 575 CmdName + " cmdsize too small"); 576 if (*LoadCmd != nullptr) 577 return malformedError("more than one " + Twine(CmdName) + " command"); 578 MachO::linkedit_data_command LinkData = 579 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr); 580 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command)) 581 return malformedError(Twine(CmdName) + " command " + 582 Twine(LoadCommandIndex) + " has incorrect cmdsize"); 583 uint64_t FileSize = Obj->getData().size(); 584 if (LinkData.dataoff > FileSize) 585 return malformedError("dataoff field of " + Twine(CmdName) + " command " + 586 Twine(LoadCommandIndex) + " extends past the end of " 587 "the file"); 588 uint64_t BigSize = LinkData.dataoff; 589 BigSize += LinkData.datasize; 590 if (BigSize > FileSize) 591 return malformedError("dataoff field plus datasize field of " + 592 Twine(CmdName) + " command " + 593 Twine(LoadCommandIndex) + " extends past the end of " 594 "the file"); 595 if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff, 596 LinkData.datasize, ElementName)) 597 return Err; 598 *LoadCmd = Load.Ptr; 599 return Error::success(); 600 } 601 602 static Error checkDyldInfoCommand(const MachOObjectFile *Obj, 603 const MachOObjectFile::LoadCommandInfo &Load, 604 uint32_t LoadCommandIndex, 605 const char **LoadCmd, const char *CmdName, 606 std::list<MachOElement> &Elements) { 607 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command)) 608 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 609 CmdName + " cmdsize too small"); 610 if (*LoadCmd != nullptr) 611 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY " 612 "command"); 613 MachO::dyld_info_command DyldInfo = 614 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr); 615 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command)) 616 return malformedError(Twine(CmdName) + " command " + 617 Twine(LoadCommandIndex) + " has incorrect cmdsize"); 618 uint64_t FileSize = Obj->getData().size(); 619 if (DyldInfo.rebase_off > FileSize) 620 return malformedError("rebase_off field of " + Twine(CmdName) + 621 " command " + Twine(LoadCommandIndex) + " extends " 622 "past the end of the file"); 623 uint64_t BigSize = DyldInfo.rebase_off; 624 BigSize += DyldInfo.rebase_size; 625 if (BigSize > FileSize) 626 return malformedError("rebase_off field plus rebase_size field of " + 627 Twine(CmdName) + " command " + 628 Twine(LoadCommandIndex) + " extends past the end of " 629 "the file"); 630 if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off, 631 DyldInfo.rebase_size, 632 "dyld rebase info")) 633 return Err; 634 if (DyldInfo.bind_off > FileSize) 635 return malformedError("bind_off field of " + Twine(CmdName) + 636 " command " + Twine(LoadCommandIndex) + " extends " 637 "past the end of the file"); 638 BigSize = DyldInfo.bind_off; 639 BigSize += DyldInfo.bind_size; 640 if (BigSize > FileSize) 641 return malformedError("bind_off field plus bind_size field of " + 642 Twine(CmdName) + " command " + 643 Twine(LoadCommandIndex) + " extends past the end of " 644 "the file"); 645 if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off, 646 DyldInfo.bind_size, 647 "dyld bind info")) 648 return Err; 649 if (DyldInfo.weak_bind_off > FileSize) 650 return malformedError("weak_bind_off field of " + Twine(CmdName) + 651 " command " + Twine(LoadCommandIndex) + " extends " 652 "past the end of the file"); 653 BigSize = DyldInfo.weak_bind_off; 654 BigSize += DyldInfo.weak_bind_size; 655 if (BigSize > FileSize) 656 return malformedError("weak_bind_off field plus weak_bind_size field of " + 657 Twine(CmdName) + " command " + 658 Twine(LoadCommandIndex) + " extends past the end of " 659 "the file"); 660 if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off, 661 DyldInfo.weak_bind_size, 662 "dyld weak bind info")) 663 return Err; 664 if (DyldInfo.lazy_bind_off > FileSize) 665 return malformedError("lazy_bind_off field of " + Twine(CmdName) + 666 " command " + Twine(LoadCommandIndex) + " extends " 667 "past the end of the file"); 668 BigSize = DyldInfo.lazy_bind_off; 669 BigSize += DyldInfo.lazy_bind_size; 670 if (BigSize > FileSize) 671 return malformedError("lazy_bind_off field plus lazy_bind_size field of " + 672 Twine(CmdName) + " command " + 673 Twine(LoadCommandIndex) + " extends past the end of " 674 "the file"); 675 if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off, 676 DyldInfo.lazy_bind_size, 677 "dyld lazy bind info")) 678 return Err; 679 if (DyldInfo.export_off > FileSize) 680 return malformedError("export_off field of " + Twine(CmdName) + 681 " command " + Twine(LoadCommandIndex) + " extends " 682 "past the end of the file"); 683 BigSize = DyldInfo.export_off; 684 BigSize += DyldInfo.export_size; 685 if (BigSize > FileSize) 686 return malformedError("export_off field plus export_size field of " + 687 Twine(CmdName) + " command " + 688 Twine(LoadCommandIndex) + " extends past the end of " 689 "the file"); 690 if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off, 691 DyldInfo.export_size, 692 "dyld export info")) 693 return Err; 694 *LoadCmd = Load.Ptr; 695 return Error::success(); 696 } 697 698 static Error checkDylibCommand(const MachOObjectFile *Obj, 699 const MachOObjectFile::LoadCommandInfo &Load, 700 uint32_t LoadCommandIndex, const char *CmdName) { 701 if (Load.C.cmdsize < sizeof(MachO::dylib_command)) 702 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 703 CmdName + " cmdsize too small"); 704 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr); 705 if (D.dylib.name < sizeof(MachO::dylib_command)) 706 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 707 CmdName + " name.offset field too small, not past " 708 "the end of the dylib_command struct"); 709 if (D.dylib.name >= D.cmdsize) 710 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 711 CmdName + " name.offset field extends past the end " 712 "of the load command"); 713 // Make sure there is a null between the starting offset of the name and 714 // the end of the load command. 715 uint32_t i; 716 const char *P = (const char *)Load.Ptr; 717 for (i = D.dylib.name; i < D.cmdsize; i++) 718 if (P[i] == '\0') 719 break; 720 if (i >= D.cmdsize) 721 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 722 CmdName + " library name extends past the end of the " 723 "load command"); 724 return Error::success(); 725 } 726 727 static Error checkDylibIdCommand(const MachOObjectFile *Obj, 728 const MachOObjectFile::LoadCommandInfo &Load, 729 uint32_t LoadCommandIndex, 730 const char **LoadCmd) { 731 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex, 732 "LC_ID_DYLIB")) 733 return Err; 734 if (*LoadCmd != nullptr) 735 return malformedError("more than one LC_ID_DYLIB command"); 736 if (Obj->getHeader().filetype != MachO::MH_DYLIB && 737 Obj->getHeader().filetype != MachO::MH_DYLIB_STUB) 738 return malformedError("LC_ID_DYLIB load command in non-dynamic library " 739 "file type"); 740 *LoadCmd = Load.Ptr; 741 return Error::success(); 742 } 743 744 static Error checkDyldCommand(const MachOObjectFile *Obj, 745 const MachOObjectFile::LoadCommandInfo &Load, 746 uint32_t LoadCommandIndex, const char *CmdName) { 747 if (Load.C.cmdsize < sizeof(MachO::dylinker_command)) 748 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 749 CmdName + " cmdsize too small"); 750 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr); 751 if (D.name < sizeof(MachO::dylinker_command)) 752 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 753 CmdName + " name.offset field too small, not past " 754 "the end of the dylinker_command struct"); 755 if (D.name >= D.cmdsize) 756 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 757 CmdName + " name.offset field extends past the end " 758 "of the load command"); 759 // Make sure there is a null between the starting offset of the name and 760 // the end of the load command. 761 uint32_t i; 762 const char *P = (const char *)Load.Ptr; 763 for (i = D.name; i < D.cmdsize; i++) 764 if (P[i] == '\0') 765 break; 766 if (i >= D.cmdsize) 767 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 768 CmdName + " dyld name extends past the end of the " 769 "load command"); 770 return Error::success(); 771 } 772 773 static Error checkVersCommand(const MachOObjectFile *Obj, 774 const MachOObjectFile::LoadCommandInfo &Load, 775 uint32_t LoadCommandIndex, 776 const char **LoadCmd, const char *CmdName) { 777 if (Load.C.cmdsize != sizeof(MachO::version_min_command)) 778 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 779 CmdName + " has incorrect cmdsize"); 780 if (*LoadCmd != nullptr) 781 return malformedError("more than one LC_VERSION_MIN_MACOSX, " 782 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or " 783 "LC_VERSION_MIN_WATCHOS command"); 784 *LoadCmd = Load.Ptr; 785 return Error::success(); 786 } 787 788 static Error checkRpathCommand(const MachOObjectFile *Obj, 789 const MachOObjectFile::LoadCommandInfo &Load, 790 uint32_t LoadCommandIndex) { 791 if (Load.C.cmdsize < sizeof(MachO::rpath_command)) 792 return malformedError("load command " + Twine(LoadCommandIndex) + 793 " LC_RPATH cmdsize too small"); 794 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr); 795 if (R.path < sizeof(MachO::rpath_command)) 796 return malformedError("load command " + Twine(LoadCommandIndex) + 797 " LC_RPATH path.offset field too small, not past " 798 "the end of the rpath_command struct"); 799 if (R.path >= R.cmdsize) 800 return malformedError("load command " + Twine(LoadCommandIndex) + 801 " LC_RPATH path.offset field extends past the end " 802 "of the load command"); 803 // Make sure there is a null between the starting offset of the path and 804 // the end of the load command. 805 uint32_t i; 806 const char *P = (const char *)Load.Ptr; 807 for (i = R.path; i < R.cmdsize; i++) 808 if (P[i] == '\0') 809 break; 810 if (i >= R.cmdsize) 811 return malformedError("load command " + Twine(LoadCommandIndex) + 812 " LC_RPATH library name extends past the end of the " 813 "load command"); 814 return Error::success(); 815 } 816 817 static Error checkEncryptCommand(const MachOObjectFile *Obj, 818 const MachOObjectFile::LoadCommandInfo &Load, 819 uint32_t LoadCommandIndex, 820 uint64_t cryptoff, uint64_t cryptsize, 821 const char **LoadCmd, const char *CmdName) { 822 if (*LoadCmd != nullptr) 823 return malformedError("more than one LC_ENCRYPTION_INFO and or " 824 "LC_ENCRYPTION_INFO_64 command"); 825 uint64_t FileSize = Obj->getData().size(); 826 if (cryptoff > FileSize) 827 return malformedError("cryptoff field of " + Twine(CmdName) + 828 " command " + Twine(LoadCommandIndex) + " extends " 829 "past the end of the file"); 830 uint64_t BigSize = cryptoff; 831 BigSize += cryptsize; 832 if (BigSize > FileSize) 833 return malformedError("cryptoff field plus cryptsize field of " + 834 Twine(CmdName) + " command " + 835 Twine(LoadCommandIndex) + " extends past the end of " 836 "the file"); 837 *LoadCmd = Load.Ptr; 838 return Error::success(); 839 } 840 841 static Error checkLinkerOptCommand(const MachOObjectFile *Obj, 842 const MachOObjectFile::LoadCommandInfo &Load, 843 uint32_t LoadCommandIndex) { 844 if (Load.C.cmdsize < sizeof(MachO::linker_option_command)) 845 return malformedError("load command " + Twine(LoadCommandIndex) + 846 " LC_LINKER_OPTION cmdsize too small"); 847 MachO::linker_option_command L = 848 getStruct<MachO::linker_option_command>(Obj, Load.Ptr); 849 // Make sure the count of strings is correct. 850 const char *string = (const char *)Load.Ptr + 851 sizeof(struct MachO::linker_option_command); 852 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command); 853 uint32_t i = 0; 854 while (left > 0) { 855 while (*string == '\0' && left > 0) { 856 string++; 857 left--; 858 } 859 if (left > 0) { 860 i++; 861 uint32_t NullPos = StringRef(string, left).find('\0'); 862 uint32_t len = std::min(NullPos, left) + 1; 863 string += len; 864 left -= len; 865 } 866 } 867 if (L.count != i) 868 return malformedError("load command " + Twine(LoadCommandIndex) + 869 " LC_LINKER_OPTION string count " + Twine(L.count) + 870 " does not match number of strings"); 871 return Error::success(); 872 } 873 874 static Error checkSubCommand(const MachOObjectFile *Obj, 875 const MachOObjectFile::LoadCommandInfo &Load, 876 uint32_t LoadCommandIndex, const char *CmdName, 877 size_t SizeOfCmd, const char *CmdStructName, 878 uint32_t PathOffset, const char *PathFieldName) { 879 if (PathOffset < SizeOfCmd) 880 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 881 CmdName + " " + PathFieldName + ".offset field too " 882 "small, not past the end of the " + CmdStructName); 883 if (PathOffset >= Load.C.cmdsize) 884 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 885 CmdName + " " + PathFieldName + ".offset field " 886 "extends past the end of the load command"); 887 // Make sure there is a null between the starting offset of the path and 888 // the end of the load command. 889 uint32_t i; 890 const char *P = (const char *)Load.Ptr; 891 for (i = PathOffset; i < Load.C.cmdsize; i++) 892 if (P[i] == '\0') 893 break; 894 if (i >= Load.C.cmdsize) 895 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 896 CmdName + " " + PathFieldName + " name extends past " 897 "the end of the load command"); 898 return Error::success(); 899 } 900 901 static Error checkThreadCommand(const MachOObjectFile *Obj, 902 const MachOObjectFile::LoadCommandInfo &Load, 903 uint32_t LoadCommandIndex, 904 const char *CmdName) { 905 if (Load.C.cmdsize < sizeof(MachO::thread_command)) 906 return malformedError("load command " + Twine(LoadCommandIndex) + 907 CmdName + " cmdsize too small"); 908 MachO::thread_command T = 909 getStruct<MachO::thread_command>(Obj, Load.Ptr); 910 const char *state = Load.Ptr + sizeof(MachO::thread_command); 911 const char *end = Load.Ptr + T.cmdsize; 912 uint32_t nflavor = 0; 913 uint32_t cputype = getCPUType(Obj); 914 while (state < end) { 915 if(state + sizeof(uint32_t) > end) 916 return malformedError("load command " + Twine(LoadCommandIndex) + 917 "flavor in " + CmdName + " extends past end of " 918 "command"); 919 uint32_t flavor; 920 memcpy(&flavor, state, sizeof(uint32_t)); 921 if (Obj->isLittleEndian() != sys::IsLittleEndianHost) 922 sys::swapByteOrder(flavor); 923 state += sizeof(uint32_t); 924 925 if(state + sizeof(uint32_t) > end) 926 return malformedError("load command " + Twine(LoadCommandIndex) + 927 " count in " + CmdName + " extends past end of " 928 "command"); 929 uint32_t count; 930 memcpy(&count, state, sizeof(uint32_t)); 931 if (Obj->isLittleEndian() != sys::IsLittleEndianHost) 932 sys::swapByteOrder(count); 933 state += sizeof(uint32_t); 934 935 if (cputype == MachO::CPU_TYPE_X86_64) { 936 if (flavor == MachO::x86_THREAD_STATE64) { 937 if (count != MachO::x86_THREAD_STATE64_COUNT) 938 return malformedError("load command " + Twine(LoadCommandIndex) + 939 " count not x86_THREAD_STATE64_COUNT for " 940 "flavor number " + Twine(nflavor) + " which is " 941 "a x86_THREAD_STATE64 flavor in " + CmdName + 942 " command"); 943 if (state + sizeof(MachO::x86_thread_state64_t) > end) 944 return malformedError("load command " + Twine(LoadCommandIndex) + 945 " x86_THREAD_STATE64 extends past end of " 946 "command in " + CmdName + " command"); 947 state += sizeof(MachO::x86_thread_state64_t); 948 } else { 949 return malformedError("load command " + Twine(LoadCommandIndex) + 950 " unknown flavor (" + Twine(flavor) + ") for " 951 "flavor number " + Twine(nflavor) + " in " + 952 CmdName + " command"); 953 } 954 } else if (cputype == MachO::CPU_TYPE_ARM) { 955 if (flavor == MachO::ARM_THREAD_STATE) { 956 if (count != MachO::ARM_THREAD_STATE_COUNT) 957 return malformedError("load command " + Twine(LoadCommandIndex) + 958 " count not ARM_THREAD_STATE_COUNT for " 959 "flavor number " + Twine(nflavor) + " which is " 960 "a ARM_THREAD_STATE flavor in " + CmdName + 961 " command"); 962 if (state + sizeof(MachO::arm_thread_state32_t) > end) 963 return malformedError("load command " + Twine(LoadCommandIndex) + 964 " ARM_THREAD_STATE extends past end of " 965 "command in " + CmdName + " command"); 966 state += sizeof(MachO::arm_thread_state32_t); 967 } else { 968 return malformedError("load command " + Twine(LoadCommandIndex) + 969 " unknown flavor (" + Twine(flavor) + ") for " 970 "flavor number " + Twine(nflavor) + " in " + 971 CmdName + " command"); 972 } 973 } else if (cputype == MachO::CPU_TYPE_ARM64) { 974 if (flavor == MachO::ARM_THREAD_STATE64) { 975 if (count != MachO::ARM_THREAD_STATE64_COUNT) 976 return malformedError("load command " + Twine(LoadCommandIndex) + 977 " count not ARM_THREAD_STATE64_COUNT for " 978 "flavor number " + Twine(nflavor) + " which is " 979 "a ARM_THREAD_STATE64 flavor in " + CmdName + 980 " command"); 981 if (state + sizeof(MachO::arm_thread_state64_t) > end) 982 return malformedError("load command " + Twine(LoadCommandIndex) + 983 " ARM_THREAD_STATE64 extends past end of " 984 "command in " + CmdName + " command"); 985 state += sizeof(MachO::arm_thread_state64_t); 986 } else { 987 return malformedError("load command " + Twine(LoadCommandIndex) + 988 " unknown flavor (" + Twine(flavor) + ") for " 989 "flavor number " + Twine(nflavor) + " in " + 990 CmdName + " command"); 991 } 992 } else if (cputype == MachO::CPU_TYPE_POWERPC) { 993 if (flavor == MachO::PPC_THREAD_STATE) { 994 if (count != MachO::PPC_THREAD_STATE_COUNT) 995 return malformedError("load command " + Twine(LoadCommandIndex) + 996 " count not PPC_THREAD_STATE_COUNT for " 997 "flavor number " + Twine(nflavor) + " which is " 998 "a PPC_THREAD_STATE flavor in " + CmdName + 999 " command"); 1000 if (state + sizeof(MachO::ppc_thread_state32_t) > end) 1001 return malformedError("load command " + Twine(LoadCommandIndex) + 1002 " PPC_THREAD_STATE extends past end of " 1003 "command in " + CmdName + " command"); 1004 state += sizeof(MachO::ppc_thread_state32_t); 1005 } else { 1006 return malformedError("load command " + Twine(LoadCommandIndex) + 1007 " unknown flavor (" + Twine(flavor) + ") for " 1008 "flavor number " + Twine(nflavor) + " in " + 1009 CmdName + " command"); 1010 } 1011 } else { 1012 return malformedError("unknown cputype (" + Twine(cputype) + ") load " 1013 "command " + Twine(LoadCommandIndex) + " for " + 1014 CmdName + " command can't be checked"); 1015 } 1016 nflavor++; 1017 } 1018 return Error::success(); 1019 } 1020 1021 static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, 1022 const MachOObjectFile::LoadCommandInfo 1023 &Load, 1024 uint32_t LoadCommandIndex, 1025 const char **LoadCmd, 1026 std::list<MachOElement> &Elements) { 1027 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command)) 1028 return malformedError("load command " + Twine(LoadCommandIndex) + 1029 " LC_TWOLEVEL_HINTS has incorrect cmdsize"); 1030 if (*LoadCmd != nullptr) 1031 return malformedError("more than one LC_TWOLEVEL_HINTS command"); 1032 MachO::twolevel_hints_command Hints = 1033 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr); 1034 uint64_t FileSize = Obj->getData().size(); 1035 if (Hints.offset > FileSize) 1036 return malformedError("offset field of LC_TWOLEVEL_HINTS command " + 1037 Twine(LoadCommandIndex) + " extends past the end of " 1038 "the file"); 1039 uint64_t BigSize = Hints.nhints; 1040 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint); 1041 BigSize += Hints.offset; 1042 if (BigSize > FileSize) 1043 return malformedError("offset field plus nhints times sizeof(struct " 1044 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " + 1045 Twine(LoadCommandIndex) + " extends past the end of " 1046 "the file"); 1047 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints * 1048 sizeof(MachO::twolevel_hint), 1049 "two level hints")) 1050 return Err; 1051 *LoadCmd = Load.Ptr; 1052 return Error::success(); 1053 } 1054 1055 // Returns true if the libObject code does not support the load command and its 1056 // contents. The cmd value it is treated as an unknown load command but with 1057 // an error message that says the cmd value is obsolete. 1058 static bool isLoadCommandObsolete(uint32_t cmd) { 1059 if (cmd == MachO::LC_SYMSEG || 1060 cmd == MachO::LC_LOADFVMLIB || 1061 cmd == MachO::LC_IDFVMLIB || 1062 cmd == MachO::LC_IDENT || 1063 cmd == MachO::LC_FVMFILE || 1064 cmd == MachO::LC_PREPAGE || 1065 cmd == MachO::LC_PREBOUND_DYLIB || 1066 cmd == MachO::LC_TWOLEVEL_HINTS || 1067 cmd == MachO::LC_PREBIND_CKSUM) 1068 return true; 1069 return false; 1070 } 1071 1072 Expected<std::unique_ptr<MachOObjectFile>> 1073 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, 1074 bool Is64Bits, uint32_t UniversalCputype, 1075 uint32_t UniversalIndex) { 1076 Error Err = Error::success(); 1077 std::unique_ptr<MachOObjectFile> Obj( 1078 new MachOObjectFile(std::move(Object), IsLittleEndian, 1079 Is64Bits, Err, UniversalCputype, 1080 UniversalIndex)); 1081 if (Err) 1082 return std::move(Err); 1083 return std::move(Obj); 1084 } 1085 1086 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 1087 bool Is64bits, Error &Err, 1088 uint32_t UniversalCputype, 1089 uint32_t UniversalIndex) 1090 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 1091 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 1092 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 1093 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 1094 HasPageZeroSegment(false) { 1095 ErrorAsOutParameter ErrAsOutParam(&Err); 1096 uint64_t SizeOfHeaders; 1097 uint32_t cputype; 1098 if (is64Bit()) { 1099 parseHeader(this, Header64, Err); 1100 SizeOfHeaders = sizeof(MachO::mach_header_64); 1101 cputype = Header64.cputype; 1102 } else { 1103 parseHeader(this, Header, Err); 1104 SizeOfHeaders = sizeof(MachO::mach_header); 1105 cputype = Header.cputype; 1106 } 1107 if (Err) 1108 return; 1109 SizeOfHeaders += getHeader().sizeofcmds; 1110 if (getData().data() + SizeOfHeaders > getData().end()) { 1111 Err = malformedError("load commands extend past the end of the file"); 1112 return; 1113 } 1114 if (UniversalCputype != 0 && cputype != UniversalCputype) { 1115 Err = malformedError("universal header architecture: " + 1116 Twine(UniversalIndex) + "'s cputype does not match " 1117 "object file's mach header"); 1118 return; 1119 } 1120 std::list<MachOElement> Elements; 1121 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"}); 1122 1123 uint32_t LoadCommandCount = getHeader().ncmds; 1124 LoadCommandInfo Load; 1125 if (LoadCommandCount != 0) { 1126 if (auto LoadOrErr = getFirstLoadCommandInfo(this)) 1127 Load = *LoadOrErr; 1128 else { 1129 Err = LoadOrErr.takeError(); 1130 return; 1131 } 1132 } 1133 1134 const char *DyldIdLoadCmd = nullptr; 1135 const char *FuncStartsLoadCmd = nullptr; 1136 const char *SplitInfoLoadCmd = nullptr; 1137 const char *CodeSignDrsLoadCmd = nullptr; 1138 const char *CodeSignLoadCmd = nullptr; 1139 const char *VersLoadCmd = nullptr; 1140 const char *SourceLoadCmd = nullptr; 1141 const char *EntryPointLoadCmd = nullptr; 1142 const char *EncryptLoadCmd = nullptr; 1143 const char *RoutinesLoadCmd = nullptr; 1144 const char *UnixThreadLoadCmd = nullptr; 1145 const char *TwoLevelHintsLoadCmd = nullptr; 1146 for (unsigned I = 0; I < LoadCommandCount; ++I) { 1147 if (is64Bit()) { 1148 if (Load.C.cmdsize % 8 != 0) { 1149 // We have a hack here to allow 64-bit Mach-O core files to have 1150 // LC_THREAD commands that are only a multiple of 4 and not 8 to be 1151 // allowed since the macOS kernel produces them. 1152 if (getHeader().filetype != MachO::MH_CORE || 1153 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { 1154 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 1155 "multiple of 8"); 1156 return; 1157 } 1158 } 1159 } else { 1160 if (Load.C.cmdsize % 4 != 0) { 1161 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 1162 "multiple of 4"); 1163 return; 1164 } 1165 } 1166 LoadCommands.push_back(Load); 1167 if (Load.C.cmd == MachO::LC_SYMTAB) { 1168 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd, Elements))) 1169 return; 1170 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 1171 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd, 1172 Elements))) 1173 return; 1174 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 1175 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd, 1176 "LC_DATA_IN_CODE", Elements, 1177 "data in code info"))) 1178 return; 1179 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 1180 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, 1181 "LC_LINKER_OPTIMIZATION_HINT", 1182 Elements, "linker optimization " 1183 "hints"))) 1184 return; 1185 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) { 1186 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd, 1187 "LC_FUNCTION_STARTS", Elements, 1188 "function starts data"))) 1189 return; 1190 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) { 1191 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd, 1192 "LC_SEGMENT_SPLIT_INFO", Elements, 1193 "split info data"))) 1194 return; 1195 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) { 1196 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd, 1197 "LC_DYLIB_CODE_SIGN_DRS", Elements, 1198 "code signing RDs data"))) 1199 return; 1200 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) { 1201 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd, 1202 "LC_CODE_SIGNATURE", Elements, 1203 "code signature data"))) 1204 return; 1205 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { 1206 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1207 "LC_DYLD_INFO", Elements))) 1208 return; 1209 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 1210 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1211 "LC_DYLD_INFO_ONLY", Elements))) 1212 return; 1213 } else if (Load.C.cmd == MachO::LC_UUID) { 1214 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { 1215 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " 1216 "cmdsize"); 1217 return; 1218 } 1219 if (UuidLoadCmd) { 1220 Err = malformedError("more than one LC_UUID command"); 1221 return; 1222 } 1223 UuidLoadCmd = Load.Ptr; 1224 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1225 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64, 1226 MachO::section_64>( 1227 this, Load, Sections, HasPageZeroSegment, I, 1228 "LC_SEGMENT_64", SizeOfHeaders, Elements))) 1229 return; 1230 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1231 if ((Err = parseSegmentLoadCommand<MachO::segment_command, 1232 MachO::section>( 1233 this, Load, Sections, HasPageZeroSegment, I, 1234 "LC_SEGMENT", SizeOfHeaders, Elements))) 1235 return; 1236 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) { 1237 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd))) 1238 return; 1239 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) { 1240 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB"))) 1241 return; 1242 Libraries.push_back(Load.Ptr); 1243 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) { 1244 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB"))) 1245 return; 1246 Libraries.push_back(Load.Ptr); 1247 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) { 1248 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB"))) 1249 return; 1250 Libraries.push_back(Load.Ptr); 1251 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) { 1252 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB"))) 1253 return; 1254 Libraries.push_back(Load.Ptr); 1255 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 1256 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB"))) 1257 return; 1258 Libraries.push_back(Load.Ptr); 1259 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) { 1260 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER"))) 1261 return; 1262 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) { 1263 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER"))) 1264 return; 1265 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 1266 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT"))) 1267 return; 1268 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) { 1269 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1270 "LC_VERSION_MIN_MACOSX"))) 1271 return; 1272 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { 1273 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1274 "LC_VERSION_MIN_IPHONEOS"))) 1275 return; 1276 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) { 1277 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1278 "LC_VERSION_MIN_TVOS"))) 1279 return; 1280 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 1281 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1282 "LC_VERSION_MIN_WATCHOS"))) 1283 return; 1284 } else if (Load.C.cmd == MachO::LC_RPATH) { 1285 if ((Err = checkRpathCommand(this, Load, I))) 1286 return; 1287 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) { 1288 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) { 1289 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) + 1290 " has incorrect cmdsize"); 1291 return; 1292 } 1293 if (SourceLoadCmd) { 1294 Err = malformedError("more than one LC_SOURCE_VERSION command"); 1295 return; 1296 } 1297 SourceLoadCmd = Load.Ptr; 1298 } else if (Load.C.cmd == MachO::LC_MAIN) { 1299 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) { 1300 Err = malformedError("LC_MAIN command " + Twine(I) + 1301 " has incorrect cmdsize"); 1302 return; 1303 } 1304 if (EntryPointLoadCmd) { 1305 Err = malformedError("more than one LC_MAIN command"); 1306 return; 1307 } 1308 EntryPointLoadCmd = Load.Ptr; 1309 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) { 1310 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) { 1311 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) + 1312 " has incorrect cmdsize"); 1313 return; 1314 } 1315 MachO::encryption_info_command E = 1316 getStruct<MachO::encryption_info_command>(this, Load.Ptr); 1317 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1318 &EncryptLoadCmd, "LC_ENCRYPTION_INFO"))) 1319 return; 1320 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 1321 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) { 1322 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) + 1323 " has incorrect cmdsize"); 1324 return; 1325 } 1326 MachO::encryption_info_command_64 E = 1327 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr); 1328 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1329 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64"))) 1330 return; 1331 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) { 1332 if ((Err = checkLinkerOptCommand(this, Load, I))) 1333 return; 1334 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) { 1335 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) { 1336 Err = malformedError("load command " + Twine(I) + 1337 " LC_SUB_FRAMEWORK cmdsize too small"); 1338 return; 1339 } 1340 MachO::sub_framework_command S = 1341 getStruct<MachO::sub_framework_command>(this, Load.Ptr); 1342 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK", 1343 sizeof(MachO::sub_framework_command), 1344 "sub_framework_command", S.umbrella, 1345 "umbrella"))) 1346 return; 1347 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) { 1348 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) { 1349 Err = malformedError("load command " + Twine(I) + 1350 " LC_SUB_UMBRELLA cmdsize too small"); 1351 return; 1352 } 1353 MachO::sub_umbrella_command S = 1354 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr); 1355 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA", 1356 sizeof(MachO::sub_umbrella_command), 1357 "sub_umbrella_command", S.sub_umbrella, 1358 "sub_umbrella"))) 1359 return; 1360 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) { 1361 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) { 1362 Err = malformedError("load command " + Twine(I) + 1363 " LC_SUB_LIBRARY cmdsize too small"); 1364 return; 1365 } 1366 MachO::sub_library_command S = 1367 getStruct<MachO::sub_library_command>(this, Load.Ptr); 1368 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY", 1369 sizeof(MachO::sub_library_command), 1370 "sub_library_command", S.sub_library, 1371 "sub_library"))) 1372 return; 1373 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) { 1374 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) { 1375 Err = malformedError("load command " + Twine(I) + 1376 " LC_SUB_CLIENT cmdsize too small"); 1377 return; 1378 } 1379 MachO::sub_client_command S = 1380 getStruct<MachO::sub_client_command>(this, Load.Ptr); 1381 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT", 1382 sizeof(MachO::sub_client_command), 1383 "sub_client_command", S.client, "client"))) 1384 return; 1385 } else if (Load.C.cmd == MachO::LC_ROUTINES) { 1386 if (Load.C.cmdsize != sizeof(MachO::routines_command)) { 1387 Err = malformedError("LC_ROUTINES command " + Twine(I) + 1388 " has incorrect cmdsize"); 1389 return; 1390 } 1391 if (RoutinesLoadCmd) { 1392 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 " 1393 "command"); 1394 return; 1395 } 1396 RoutinesLoadCmd = Load.Ptr; 1397 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) { 1398 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) { 1399 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) + 1400 " has incorrect cmdsize"); 1401 return; 1402 } 1403 if (RoutinesLoadCmd) { 1404 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES " 1405 "command"); 1406 return; 1407 } 1408 RoutinesLoadCmd = Load.Ptr; 1409 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) { 1410 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD"))) 1411 return; 1412 if (UnixThreadLoadCmd) { 1413 Err = malformedError("more than one LC_UNIXTHREAD command"); 1414 return; 1415 } 1416 UnixThreadLoadCmd = Load.Ptr; 1417 } else if (Load.C.cmd == MachO::LC_THREAD) { 1418 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD"))) 1419 return; 1420 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported. 1421 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) { 1422 if ((Err = checkTwoLevelHintsCommand(this, Load, I, 1423 &TwoLevelHintsLoadCmd, Elements))) 1424 return; 1425 } else if (isLoadCommandObsolete(Load.C.cmd)) { 1426 Err = malformedError("load command " + Twine(I) + " for cmd value of: " + 1427 Twine(Load.C.cmd) + " is obsolete and not " 1428 "supported"); 1429 return; 1430 } 1431 // TODO: generate a error for unknown load commands by default. But still 1432 // need work out an approach to allow or not allow unknown values like this 1433 // as an option for some uses like lldb. 1434 if (I < LoadCommandCount - 1) { 1435 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) 1436 Load = *LoadOrErr; 1437 else { 1438 Err = LoadOrErr.takeError(); 1439 return; 1440 } 1441 } 1442 } 1443 if (!SymtabLoadCmd) { 1444 if (DysymtabLoadCmd) { 1445 Err = malformedError("contains LC_DYSYMTAB load command without a " 1446 "LC_SYMTAB load command"); 1447 return; 1448 } 1449 } else if (DysymtabLoadCmd) { 1450 MachO::symtab_command Symtab = 1451 getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1452 MachO::dysymtab_command Dysymtab = 1453 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1454 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1455 Err = malformedError("ilocalsym in LC_DYSYMTAB load command " 1456 "extends past the end of the symbol table"); 1457 return; 1458 } 1459 uint64_t BigSize = Dysymtab.ilocalsym; 1460 BigSize += Dysymtab.nlocalsym; 1461 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { 1462 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " 1463 "command extends past the end of the symbol table"); 1464 return; 1465 } 1466 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1467 Err = malformedError("nextdefsym in LC_DYSYMTAB load command " 1468 "extends past the end of the symbol table"); 1469 return; 1470 } 1471 BigSize = Dysymtab.iextdefsym; 1472 BigSize += Dysymtab.nextdefsym; 1473 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { 1474 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " 1475 "load command extends past the end of the symbol " 1476 "table"); 1477 return; 1478 } 1479 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { 1480 Err = malformedError("nundefsym in LC_DYSYMTAB load command " 1481 "extends past the end of the symbol table"); 1482 return; 1483 } 1484 BigSize = Dysymtab.iundefsym; 1485 BigSize += Dysymtab.nundefsym; 1486 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { 1487 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " 1488 " command extends past the end of the symbol table"); 1489 return; 1490 } 1491 } 1492 if ((getHeader().filetype == MachO::MH_DYLIB || 1493 getHeader().filetype == MachO::MH_DYLIB_STUB) && 1494 DyldIdLoadCmd == nullptr) { 1495 Err = malformedError("no LC_ID_DYLIB load command in dynamic library " 1496 "filetype"); 1497 return; 1498 } 1499 assert(LoadCommands.size() == LoadCommandCount); 1500 1501 Err = Error::success(); 1502 } 1503 1504 Error MachOObjectFile::checkSymbolTable() const { 1505 uint32_t Flags = 0; 1506 if (is64Bit()) { 1507 MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64(); 1508 Flags = H_64.flags; 1509 } else { 1510 MachO::mach_header H = MachOObjectFile::getHeader(); 1511 Flags = H.flags; 1512 } 1513 uint8_t NType = 0; 1514 uint8_t NSect = 0; 1515 uint16_t NDesc = 0; 1516 uint32_t NStrx = 0; 1517 uint64_t NValue = 0; 1518 uint32_t SymbolIndex = 0; 1519 MachO::symtab_command S = getSymtabLoadCommand(); 1520 for (const SymbolRef &Symbol : symbols()) { 1521 DataRefImpl SymDRI = Symbol.getRawDataRefImpl(); 1522 if (is64Bit()) { 1523 MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI); 1524 NType = STE_64.n_type; 1525 NSect = STE_64.n_sect; 1526 NDesc = STE_64.n_desc; 1527 NStrx = STE_64.n_strx; 1528 NValue = STE_64.n_value; 1529 } else { 1530 MachO::nlist STE = getSymbolTableEntry(SymDRI); 1531 NType = STE.n_type; 1532 NType = STE.n_type; 1533 NSect = STE.n_sect; 1534 NDesc = STE.n_desc; 1535 NStrx = STE.n_strx; 1536 NValue = STE.n_value; 1537 } 1538 if ((NType & MachO::N_STAB) == 0 && 1539 (NType & MachO::N_TYPE) == MachO::N_SECT) { 1540 if (NSect == 0 || NSect > Sections.size()) 1541 return malformedError("bad section index: " + Twine((int)NSect) + 1542 " for symbol at index " + Twine(SymbolIndex)); 1543 } 1544 if ((NType & MachO::N_STAB) == 0 && 1545 (NType & MachO::N_TYPE) == MachO::N_INDR) { 1546 if (NValue >= S.strsize) 1547 return malformedError("bad n_value: " + Twine((int)NValue) + " past " 1548 "the end of string table, for N_INDR symbol at " 1549 "index " + Twine(SymbolIndex)); 1550 } 1551 if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && 1552 (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || 1553 (NType & MachO::N_TYPE) == MachO::N_PBUD)) { 1554 uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); 1555 if (LibraryOrdinal != 0 && 1556 LibraryOrdinal != MachO::EXECUTABLE_ORDINAL && 1557 LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL && 1558 LibraryOrdinal - 1 >= Libraries.size() ) { 1559 return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) + 1560 " for symbol at index " + Twine(SymbolIndex)); 1561 } 1562 } 1563 if (NStrx >= S.strsize) 1564 return malformedError("bad string table index: " + Twine((int)NStrx) + 1565 " past the end of string table, for symbol at " 1566 "index " + Twine(SymbolIndex)); 1567 SymbolIndex++; 1568 } 1569 return Error::success(); 1570 } 1571 1572 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1573 unsigned SymbolTableEntrySize = is64Bit() ? 1574 sizeof(MachO::nlist_64) : 1575 sizeof(MachO::nlist); 1576 Symb.p += SymbolTableEntrySize; 1577 } 1578 1579 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 1580 StringRef StringTable = getStringTableData(); 1581 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1582 const char *Start = &StringTable.data()[Entry.n_strx]; 1583 if (Start < getData().begin() || Start >= getData().end()) { 1584 return malformedError("bad string index: " + Twine(Entry.n_strx) + 1585 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1586 } 1587 return StringRef(Start); 1588 } 1589 1590 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 1591 DataRefImpl DRI = Sec.getRawDataRefImpl(); 1592 uint32_t Flags = getSectionFlags(this, DRI); 1593 return Flags & MachO::SECTION_TYPE; 1594 } 1595 1596 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 1597 if (is64Bit()) { 1598 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 1599 return Entry.n_value; 1600 } 1601 MachO::nlist Entry = getSymbolTableEntry(Sym); 1602 return Entry.n_value; 1603 } 1604 1605 // getIndirectName() returns the name of the alias'ed symbol who's string table 1606 // index is in the n_value field. 1607 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 1608 StringRef &Res) const { 1609 StringRef StringTable = getStringTableData(); 1610 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1611 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 1612 return object_error::parse_failed; 1613 uint64_t NValue = getNValue(Symb); 1614 if (NValue >= StringTable.size()) 1615 return object_error::parse_failed; 1616 const char *Start = &StringTable.data()[NValue]; 1617 Res = StringRef(Start); 1618 return std::error_code(); 1619 } 1620 1621 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { 1622 return getNValue(Sym); 1623 } 1624 1625 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { 1626 return getSymbolValue(Sym); 1627 } 1628 1629 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 1630 uint32_t flags = getSymbolFlags(DRI); 1631 if (flags & SymbolRef::SF_Common) { 1632 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1633 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 1634 } 1635 return 0; 1636 } 1637 1638 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 1639 return getNValue(DRI); 1640 } 1641 1642 Expected<SymbolRef::Type> 1643 MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 1644 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1645 uint8_t n_type = Entry.n_type; 1646 1647 // If this is a STAB debugging symbol, we can do nothing more. 1648 if (n_type & MachO::N_STAB) 1649 return SymbolRef::ST_Debug; 1650 1651 switch (n_type & MachO::N_TYPE) { 1652 case MachO::N_UNDF : 1653 return SymbolRef::ST_Unknown; 1654 case MachO::N_SECT : 1655 Expected<section_iterator> SecOrError = getSymbolSection(Symb); 1656 if (!SecOrError) 1657 return SecOrError.takeError(); 1658 section_iterator Sec = *SecOrError; 1659 if (Sec->isData() || Sec->isBSS()) 1660 return SymbolRef::ST_Data; 1661 return SymbolRef::ST_Function; 1662 } 1663 return SymbolRef::ST_Other; 1664 } 1665 1666 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 1667 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1668 1669 uint8_t MachOType = Entry.n_type; 1670 uint16_t MachOFlags = Entry.n_desc; 1671 1672 uint32_t Result = SymbolRef::SF_None; 1673 1674 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 1675 Result |= SymbolRef::SF_Indirect; 1676 1677 if (MachOType & MachO::N_STAB) 1678 Result |= SymbolRef::SF_FormatSpecific; 1679 1680 if (MachOType & MachO::N_EXT) { 1681 Result |= SymbolRef::SF_Global; 1682 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 1683 if (getNValue(DRI)) 1684 Result |= SymbolRef::SF_Common; 1685 else 1686 Result |= SymbolRef::SF_Undefined; 1687 } 1688 1689 if (!(MachOType & MachO::N_PEXT)) 1690 Result |= SymbolRef::SF_Exported; 1691 } 1692 1693 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 1694 Result |= SymbolRef::SF_Weak; 1695 1696 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 1697 Result |= SymbolRef::SF_Thumb; 1698 1699 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 1700 Result |= SymbolRef::SF_Absolute; 1701 1702 return Result; 1703 } 1704 1705 Expected<section_iterator> 1706 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { 1707 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1708 uint8_t index = Entry.n_sect; 1709 1710 if (index == 0) 1711 return section_end(); 1712 DataRefImpl DRI; 1713 DRI.d.a = index - 1; 1714 if (DRI.d.a >= Sections.size()){ 1715 return malformedError("bad section index: " + Twine((int)index) + 1716 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1717 } 1718 return section_iterator(SectionRef(DRI, this)); 1719 } 1720 1721 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 1722 MachO::nlist_base Entry = 1723 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 1724 return Entry.n_sect - 1; 1725 } 1726 1727 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 1728 Sec.d.a++; 1729 } 1730 1731 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 1732 StringRef &Result) const { 1733 ArrayRef<char> Raw = getSectionRawName(Sec); 1734 Result = parseSegmentOrSectionName(Raw.data()); 1735 return std::error_code(); 1736 } 1737 1738 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 1739 if (is64Bit()) 1740 return getSection64(Sec).addr; 1741 return getSection(Sec).addr; 1742 } 1743 1744 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 1745 // In the case if a malformed Mach-O file where the section offset is past 1746 // the end of the file or some part of the section size is past the end of 1747 // the file return a size of zero or a size that covers the rest of the file 1748 // but does not extend past the end of the file. 1749 uint32_t SectOffset, SectType; 1750 uint64_t SectSize; 1751 1752 if (is64Bit()) { 1753 MachO::section_64 Sect = getSection64(Sec); 1754 SectOffset = Sect.offset; 1755 SectSize = Sect.size; 1756 SectType = Sect.flags & MachO::SECTION_TYPE; 1757 } else { 1758 MachO::section Sect = getSection(Sec); 1759 SectOffset = Sect.offset; 1760 SectSize = Sect.size; 1761 SectType = Sect.flags & MachO::SECTION_TYPE; 1762 } 1763 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL) 1764 return SectSize; 1765 uint64_t FileSize = getData().size(); 1766 if (SectOffset > FileSize) 1767 return 0; 1768 if (FileSize - SectOffset < SectSize) 1769 return FileSize - SectOffset; 1770 return SectSize; 1771 } 1772 1773 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 1774 StringRef &Res) const { 1775 uint32_t Offset; 1776 uint64_t Size; 1777 1778 if (is64Bit()) { 1779 MachO::section_64 Sect = getSection64(Sec); 1780 Offset = Sect.offset; 1781 Size = Sect.size; 1782 } else { 1783 MachO::section Sect = getSection(Sec); 1784 Offset = Sect.offset; 1785 Size = Sect.size; 1786 } 1787 1788 Res = this->getData().substr(Offset, Size); 1789 return std::error_code(); 1790 } 1791 1792 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1793 uint32_t Align; 1794 if (is64Bit()) { 1795 MachO::section_64 Sect = getSection64(Sec); 1796 Align = Sect.align; 1797 } else { 1798 MachO::section Sect = getSection(Sec); 1799 Align = Sect.align; 1800 } 1801 1802 return uint64_t(1) << Align; 1803 } 1804 1805 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1806 return false; 1807 } 1808 1809 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 1810 uint32_t Flags = getSectionFlags(this, Sec); 1811 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 1812 } 1813 1814 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 1815 uint32_t Flags = getSectionFlags(this, Sec); 1816 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1817 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1818 !(SectionType == MachO::S_ZEROFILL || 1819 SectionType == MachO::S_GB_ZEROFILL); 1820 } 1821 1822 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 1823 uint32_t Flags = getSectionFlags(this, Sec); 1824 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1825 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1826 (SectionType == MachO::S_ZEROFILL || 1827 SectionType == MachO::S_GB_ZEROFILL); 1828 } 1829 1830 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 1831 return Sec.getRawDataRefImpl().d.a; 1832 } 1833 1834 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 1835 // FIXME: Unimplemented. 1836 return false; 1837 } 1838 1839 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { 1840 StringRef SegmentName = getSectionFinalSegmentName(Sec); 1841 StringRef SectName; 1842 if (!getSectionName(Sec, SectName)) 1843 return (SegmentName == "__LLVM" && SectName == "__bitcode"); 1844 return false; 1845 } 1846 1847 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1848 DataRefImpl Ret; 1849 Ret.d.a = Sec.d.a; 1850 Ret.d.b = 0; 1851 return relocation_iterator(RelocationRef(Ret, this)); 1852 } 1853 1854 relocation_iterator 1855 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1856 uint32_t Num; 1857 if (is64Bit()) { 1858 MachO::section_64 Sect = getSection64(Sec); 1859 Num = Sect.nreloc; 1860 } else { 1861 MachO::section Sect = getSection(Sec); 1862 Num = Sect.nreloc; 1863 } 1864 1865 DataRefImpl Ret; 1866 Ret.d.a = Sec.d.a; 1867 Ret.d.b = Num; 1868 return relocation_iterator(RelocationRef(Ret, this)); 1869 } 1870 1871 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1872 ++Rel.d.b; 1873 } 1874 1875 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1876 assert(getHeader().filetype == MachO::MH_OBJECT && 1877 "Only implemented for MH_OBJECT"); 1878 MachO::any_relocation_info RE = getRelocation(Rel); 1879 return getAnyRelocationAddress(RE); 1880 } 1881 1882 symbol_iterator 1883 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1884 MachO::any_relocation_info RE = getRelocation(Rel); 1885 if (isRelocationScattered(RE)) 1886 return symbol_end(); 1887 1888 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1889 bool isExtern = getPlainRelocationExternal(RE); 1890 if (!isExtern) 1891 return symbol_end(); 1892 1893 MachO::symtab_command S = getSymtabLoadCommand(); 1894 unsigned SymbolTableEntrySize = is64Bit() ? 1895 sizeof(MachO::nlist_64) : 1896 sizeof(MachO::nlist); 1897 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1898 DataRefImpl Sym; 1899 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1900 return symbol_iterator(SymbolRef(Sym, this)); 1901 } 1902 1903 section_iterator 1904 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 1905 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 1906 } 1907 1908 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 1909 MachO::any_relocation_info RE = getRelocation(Rel); 1910 return getAnyRelocationType(RE); 1911 } 1912 1913 void MachOObjectFile::getRelocationTypeName( 1914 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1915 StringRef res; 1916 uint64_t RType = getRelocationType(Rel); 1917 1918 unsigned Arch = this->getArch(); 1919 1920 switch (Arch) { 1921 case Triple::x86: { 1922 static const char *const Table[] = { 1923 "GENERIC_RELOC_VANILLA", 1924 "GENERIC_RELOC_PAIR", 1925 "GENERIC_RELOC_SECTDIFF", 1926 "GENERIC_RELOC_PB_LA_PTR", 1927 "GENERIC_RELOC_LOCAL_SECTDIFF", 1928 "GENERIC_RELOC_TLV" }; 1929 1930 if (RType > 5) 1931 res = "Unknown"; 1932 else 1933 res = Table[RType]; 1934 break; 1935 } 1936 case Triple::x86_64: { 1937 static const char *const Table[] = { 1938 "X86_64_RELOC_UNSIGNED", 1939 "X86_64_RELOC_SIGNED", 1940 "X86_64_RELOC_BRANCH", 1941 "X86_64_RELOC_GOT_LOAD", 1942 "X86_64_RELOC_GOT", 1943 "X86_64_RELOC_SUBTRACTOR", 1944 "X86_64_RELOC_SIGNED_1", 1945 "X86_64_RELOC_SIGNED_2", 1946 "X86_64_RELOC_SIGNED_4", 1947 "X86_64_RELOC_TLV" }; 1948 1949 if (RType > 9) 1950 res = "Unknown"; 1951 else 1952 res = Table[RType]; 1953 break; 1954 } 1955 case Triple::arm: { 1956 static const char *const Table[] = { 1957 "ARM_RELOC_VANILLA", 1958 "ARM_RELOC_PAIR", 1959 "ARM_RELOC_SECTDIFF", 1960 "ARM_RELOC_LOCAL_SECTDIFF", 1961 "ARM_RELOC_PB_LA_PTR", 1962 "ARM_RELOC_BR24", 1963 "ARM_THUMB_RELOC_BR22", 1964 "ARM_THUMB_32BIT_BRANCH", 1965 "ARM_RELOC_HALF", 1966 "ARM_RELOC_HALF_SECTDIFF" }; 1967 1968 if (RType > 9) 1969 res = "Unknown"; 1970 else 1971 res = Table[RType]; 1972 break; 1973 } 1974 case Triple::aarch64: { 1975 static const char *const Table[] = { 1976 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 1977 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 1978 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 1979 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 1980 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 1981 "ARM64_RELOC_ADDEND" 1982 }; 1983 1984 if (RType >= array_lengthof(Table)) 1985 res = "Unknown"; 1986 else 1987 res = Table[RType]; 1988 break; 1989 } 1990 case Triple::ppc: { 1991 static const char *const Table[] = { 1992 "PPC_RELOC_VANILLA", 1993 "PPC_RELOC_PAIR", 1994 "PPC_RELOC_BR14", 1995 "PPC_RELOC_BR24", 1996 "PPC_RELOC_HI16", 1997 "PPC_RELOC_LO16", 1998 "PPC_RELOC_HA16", 1999 "PPC_RELOC_LO14", 2000 "PPC_RELOC_SECTDIFF", 2001 "PPC_RELOC_PB_LA_PTR", 2002 "PPC_RELOC_HI16_SECTDIFF", 2003 "PPC_RELOC_LO16_SECTDIFF", 2004 "PPC_RELOC_HA16_SECTDIFF", 2005 "PPC_RELOC_JBSR", 2006 "PPC_RELOC_LO14_SECTDIFF", 2007 "PPC_RELOC_LOCAL_SECTDIFF" }; 2008 2009 if (RType > 15) 2010 res = "Unknown"; 2011 else 2012 res = Table[RType]; 2013 break; 2014 } 2015 case Triple::UnknownArch: 2016 res = "Unknown"; 2017 break; 2018 } 2019 Result.append(res.begin(), res.end()); 2020 } 2021 2022 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 2023 MachO::any_relocation_info RE = getRelocation(Rel); 2024 return getAnyRelocationLength(RE); 2025 } 2026 2027 // 2028 // guessLibraryShortName() is passed a name of a dynamic library and returns a 2029 // guess on what the short name is. Then name is returned as a substring of the 2030 // StringRef Name passed in. The name of the dynamic library is recognized as 2031 // a framework if it has one of the two following forms: 2032 // Foo.framework/Versions/A/Foo 2033 // Foo.framework/Foo 2034 // Where A and Foo can be any string. And may contain a trailing suffix 2035 // starting with an underbar. If the Name is recognized as a framework then 2036 // isFramework is set to true else it is set to false. If the Name has a 2037 // suffix then Suffix is set to the substring in Name that contains the suffix 2038 // else it is set to a NULL StringRef. 2039 // 2040 // The Name of the dynamic library is recognized as a library name if it has 2041 // one of the two following forms: 2042 // libFoo.A.dylib 2043 // libFoo.dylib 2044 // The library may have a suffix trailing the name Foo of the form: 2045 // libFoo_profile.A.dylib 2046 // libFoo_profile.dylib 2047 // 2048 // The Name of the dynamic library is also recognized as a library name if it 2049 // has the following form: 2050 // Foo.qtx 2051 // 2052 // If the Name of the dynamic library is none of the forms above then a NULL 2053 // StringRef is returned. 2054 // 2055 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 2056 bool &isFramework, 2057 StringRef &Suffix) { 2058 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 2059 size_t a, b, c, d, Idx; 2060 2061 isFramework = false; 2062 Suffix = StringRef(); 2063 2064 // Pull off the last component and make Foo point to it 2065 a = Name.rfind('/'); 2066 if (a == Name.npos || a == 0) 2067 goto guess_library; 2068 Foo = Name.slice(a+1, Name.npos); 2069 2070 // Look for a suffix starting with a '_' 2071 Idx = Foo.rfind('_'); 2072 if (Idx != Foo.npos && Foo.size() >= 2) { 2073 Suffix = Foo.slice(Idx, Foo.npos); 2074 Foo = Foo.slice(0, Idx); 2075 } 2076 2077 // First look for the form Foo.framework/Foo 2078 b = Name.rfind('/', a); 2079 if (b == Name.npos) 2080 Idx = 0; 2081 else 2082 Idx = b+1; 2083 F = Name.slice(Idx, Idx + Foo.size()); 2084 DotFramework = Name.slice(Idx + Foo.size(), 2085 Idx + Foo.size() + sizeof(".framework/")-1); 2086 if (F == Foo && DotFramework == ".framework/") { 2087 isFramework = true; 2088 return Foo; 2089 } 2090 2091 // Next look for the form Foo.framework/Versions/A/Foo 2092 if (b == Name.npos) 2093 goto guess_library; 2094 c = Name.rfind('/', b); 2095 if (c == Name.npos || c == 0) 2096 goto guess_library; 2097 V = Name.slice(c+1, Name.npos); 2098 if (!V.startswith("Versions/")) 2099 goto guess_library; 2100 d = Name.rfind('/', c); 2101 if (d == Name.npos) 2102 Idx = 0; 2103 else 2104 Idx = d+1; 2105 F = Name.slice(Idx, Idx + Foo.size()); 2106 DotFramework = Name.slice(Idx + Foo.size(), 2107 Idx + Foo.size() + sizeof(".framework/")-1); 2108 if (F == Foo && DotFramework == ".framework/") { 2109 isFramework = true; 2110 return Foo; 2111 } 2112 2113 guess_library: 2114 // pull off the suffix after the "." and make a point to it 2115 a = Name.rfind('.'); 2116 if (a == Name.npos || a == 0) 2117 return StringRef(); 2118 Dylib = Name.slice(a, Name.npos); 2119 if (Dylib != ".dylib") 2120 goto guess_qtx; 2121 2122 // First pull off the version letter for the form Foo.A.dylib if any. 2123 if (a >= 3) { 2124 Dot = Name.slice(a-2, a-1); 2125 if (Dot == ".") 2126 a = a - 2; 2127 } 2128 2129 b = Name.rfind('/', a); 2130 if (b == Name.npos) 2131 b = 0; 2132 else 2133 b = b+1; 2134 // ignore any suffix after an underbar like Foo_profile.A.dylib 2135 Idx = Name.find('_', b); 2136 if (Idx != Name.npos && Idx != b) { 2137 Lib = Name.slice(b, Idx); 2138 Suffix = Name.slice(Idx, a); 2139 } 2140 else 2141 Lib = Name.slice(b, a); 2142 // There are incorrect library names of the form: 2143 // libATS.A_profile.dylib so check for these. 2144 if (Lib.size() >= 3) { 2145 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 2146 if (Dot == ".") 2147 Lib = Lib.slice(0, Lib.size()-2); 2148 } 2149 return Lib; 2150 2151 guess_qtx: 2152 Qtx = Name.slice(a, Name.npos); 2153 if (Qtx != ".qtx") 2154 return StringRef(); 2155 b = Name.rfind('/', a); 2156 if (b == Name.npos) 2157 Lib = Name.slice(0, a); 2158 else 2159 Lib = Name.slice(b+1, a); 2160 // There are library names of the form: QT.A.qtx so check for these. 2161 if (Lib.size() >= 3) { 2162 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 2163 if (Dot == ".") 2164 Lib = Lib.slice(0, Lib.size()-2); 2165 } 2166 return Lib; 2167 } 2168 2169 // getLibraryShortNameByIndex() is used to get the short name of the library 2170 // for an undefined symbol in a linked Mach-O binary that was linked with the 2171 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 2172 // It is passed the index (0 - based) of the library as translated from 2173 // GET_LIBRARY_ORDINAL (1 - based). 2174 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 2175 StringRef &Res) const { 2176 if (Index >= Libraries.size()) 2177 return object_error::parse_failed; 2178 2179 // If the cache of LibrariesShortNames is not built up do that first for 2180 // all the Libraries. 2181 if (LibrariesShortNames.size() == 0) { 2182 for (unsigned i = 0; i < Libraries.size(); i++) { 2183 MachO::dylib_command D = 2184 getStruct<MachO::dylib_command>(this, Libraries[i]); 2185 if (D.dylib.name >= D.cmdsize) 2186 return object_error::parse_failed; 2187 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 2188 StringRef Name = StringRef(P); 2189 if (D.dylib.name+Name.size() >= D.cmdsize) 2190 return object_error::parse_failed; 2191 StringRef Suffix; 2192 bool isFramework; 2193 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 2194 if (shortName.empty()) 2195 LibrariesShortNames.push_back(Name); 2196 else 2197 LibrariesShortNames.push_back(shortName); 2198 } 2199 } 2200 2201 Res = LibrariesShortNames[Index]; 2202 return std::error_code(); 2203 } 2204 2205 section_iterator 2206 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 2207 DataRefImpl Sec; 2208 Sec.d.a = Rel->getRawDataRefImpl().d.a; 2209 return section_iterator(SectionRef(Sec, this)); 2210 } 2211 2212 basic_symbol_iterator MachOObjectFile::symbol_begin() const { 2213 DataRefImpl DRI; 2214 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2215 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2216 return basic_symbol_iterator(SymbolRef(DRI, this)); 2217 2218 return getSymbolByIndex(0); 2219 } 2220 2221 basic_symbol_iterator MachOObjectFile::symbol_end() const { 2222 DataRefImpl DRI; 2223 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2224 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2225 return basic_symbol_iterator(SymbolRef(DRI, this)); 2226 2227 unsigned SymbolTableEntrySize = is64Bit() ? 2228 sizeof(MachO::nlist_64) : 2229 sizeof(MachO::nlist); 2230 unsigned Offset = Symtab.symoff + 2231 Symtab.nsyms * SymbolTableEntrySize; 2232 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2233 return basic_symbol_iterator(SymbolRef(DRI, this)); 2234 } 2235 2236 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 2237 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2238 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 2239 report_fatal_error("Requested symbol index is out of range."); 2240 unsigned SymbolTableEntrySize = 2241 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2242 DataRefImpl DRI; 2243 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 2244 DRI.p += Index * SymbolTableEntrySize; 2245 return basic_symbol_iterator(SymbolRef(DRI, this)); 2246 } 2247 2248 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 2249 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2250 if (!SymtabLoadCmd) 2251 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 2252 unsigned SymbolTableEntrySize = 2253 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2254 DataRefImpl DRIstart; 2255 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 2256 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 2257 return Index; 2258 } 2259 2260 section_iterator MachOObjectFile::section_begin() const { 2261 DataRefImpl DRI; 2262 return section_iterator(SectionRef(DRI, this)); 2263 } 2264 2265 section_iterator MachOObjectFile::section_end() const { 2266 DataRefImpl DRI; 2267 DRI.d.a = Sections.size(); 2268 return section_iterator(SectionRef(DRI, this)); 2269 } 2270 2271 uint8_t MachOObjectFile::getBytesInAddress() const { 2272 return is64Bit() ? 8 : 4; 2273 } 2274 2275 StringRef MachOObjectFile::getFileFormatName() const { 2276 unsigned CPUType = getCPUType(this); 2277 if (!is64Bit()) { 2278 switch (CPUType) { 2279 case llvm::MachO::CPU_TYPE_I386: 2280 return "Mach-O 32-bit i386"; 2281 case llvm::MachO::CPU_TYPE_ARM: 2282 return "Mach-O arm"; 2283 case llvm::MachO::CPU_TYPE_POWERPC: 2284 return "Mach-O 32-bit ppc"; 2285 default: 2286 return "Mach-O 32-bit unknown"; 2287 } 2288 } 2289 2290 switch (CPUType) { 2291 case llvm::MachO::CPU_TYPE_X86_64: 2292 return "Mach-O 64-bit x86-64"; 2293 case llvm::MachO::CPU_TYPE_ARM64: 2294 return "Mach-O arm64"; 2295 case llvm::MachO::CPU_TYPE_POWERPC64: 2296 return "Mach-O 64-bit ppc64"; 2297 default: 2298 return "Mach-O 64-bit unknown"; 2299 } 2300 } 2301 2302 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 2303 switch (CPUType) { 2304 case llvm::MachO::CPU_TYPE_I386: 2305 return Triple::x86; 2306 case llvm::MachO::CPU_TYPE_X86_64: 2307 return Triple::x86_64; 2308 case llvm::MachO::CPU_TYPE_ARM: 2309 return Triple::arm; 2310 case llvm::MachO::CPU_TYPE_ARM64: 2311 return Triple::aarch64; 2312 case llvm::MachO::CPU_TYPE_POWERPC: 2313 return Triple::ppc; 2314 case llvm::MachO::CPU_TYPE_POWERPC64: 2315 return Triple::ppc64; 2316 default: 2317 return Triple::UnknownArch; 2318 } 2319 } 2320 2321 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 2322 const char **McpuDefault) { 2323 if (McpuDefault) 2324 *McpuDefault = nullptr; 2325 2326 switch (CPUType) { 2327 case MachO::CPU_TYPE_I386: 2328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2329 case MachO::CPU_SUBTYPE_I386_ALL: 2330 return Triple("i386-apple-darwin"); 2331 default: 2332 return Triple(); 2333 } 2334 case MachO::CPU_TYPE_X86_64: 2335 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2336 case MachO::CPU_SUBTYPE_X86_64_ALL: 2337 return Triple("x86_64-apple-darwin"); 2338 case MachO::CPU_SUBTYPE_X86_64_H: 2339 return Triple("x86_64h-apple-darwin"); 2340 default: 2341 return Triple(); 2342 } 2343 case MachO::CPU_TYPE_ARM: 2344 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2345 case MachO::CPU_SUBTYPE_ARM_V4T: 2346 return Triple("armv4t-apple-darwin"); 2347 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2348 return Triple("armv5e-apple-darwin"); 2349 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2350 return Triple("xscale-apple-darwin"); 2351 case MachO::CPU_SUBTYPE_ARM_V6: 2352 return Triple("armv6-apple-darwin"); 2353 case MachO::CPU_SUBTYPE_ARM_V6M: 2354 if (McpuDefault) 2355 *McpuDefault = "cortex-m0"; 2356 return Triple("armv6m-apple-darwin"); 2357 case MachO::CPU_SUBTYPE_ARM_V7: 2358 return Triple("armv7-apple-darwin"); 2359 case MachO::CPU_SUBTYPE_ARM_V7EM: 2360 if (McpuDefault) 2361 *McpuDefault = "cortex-m4"; 2362 return Triple("thumbv7em-apple-darwin"); 2363 case MachO::CPU_SUBTYPE_ARM_V7K: 2364 return Triple("armv7k-apple-darwin"); 2365 case MachO::CPU_SUBTYPE_ARM_V7M: 2366 if (McpuDefault) 2367 *McpuDefault = "cortex-m3"; 2368 return Triple("thumbv7m-apple-darwin"); 2369 case MachO::CPU_SUBTYPE_ARM_V7S: 2370 return Triple("armv7s-apple-darwin"); 2371 default: 2372 return Triple(); 2373 } 2374 case MachO::CPU_TYPE_ARM64: 2375 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2376 case MachO::CPU_SUBTYPE_ARM64_ALL: 2377 return Triple("arm64-apple-darwin"); 2378 default: 2379 return Triple(); 2380 } 2381 case MachO::CPU_TYPE_POWERPC: 2382 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2383 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2384 return Triple("ppc-apple-darwin"); 2385 default: 2386 return Triple(); 2387 } 2388 case MachO::CPU_TYPE_POWERPC64: 2389 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2390 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2391 return Triple("ppc64-apple-darwin"); 2392 default: 2393 return Triple(); 2394 } 2395 default: 2396 return Triple(); 2397 } 2398 } 2399 2400 Triple MachOObjectFile::getHostArch() { 2401 return Triple(sys::getDefaultTargetTriple()); 2402 } 2403 2404 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2405 return StringSwitch<bool>(ArchFlag) 2406 .Case("i386", true) 2407 .Case("x86_64", true) 2408 .Case("x86_64h", true) 2409 .Case("armv4t", true) 2410 .Case("arm", true) 2411 .Case("armv5e", true) 2412 .Case("armv6", true) 2413 .Case("armv6m", true) 2414 .Case("armv7", true) 2415 .Case("armv7em", true) 2416 .Case("armv7k", true) 2417 .Case("armv7m", true) 2418 .Case("armv7s", true) 2419 .Case("arm64", true) 2420 .Case("ppc", true) 2421 .Case("ppc64", true) 2422 .Default(false); 2423 } 2424 2425 unsigned MachOObjectFile::getArch() const { 2426 return getArch(getCPUType(this)); 2427 } 2428 2429 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2430 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2431 } 2432 2433 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2434 DataRefImpl DRI; 2435 DRI.d.a = Index; 2436 return section_rel_begin(DRI); 2437 } 2438 2439 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2440 DataRefImpl DRI; 2441 DRI.d.a = Index; 2442 return section_rel_end(DRI); 2443 } 2444 2445 dice_iterator MachOObjectFile::begin_dices() const { 2446 DataRefImpl DRI; 2447 if (!DataInCodeLoadCmd) 2448 return dice_iterator(DiceRef(DRI, this)); 2449 2450 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2451 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 2452 return dice_iterator(DiceRef(DRI, this)); 2453 } 2454 2455 dice_iterator MachOObjectFile::end_dices() const { 2456 DataRefImpl DRI; 2457 if (!DataInCodeLoadCmd) 2458 return dice_iterator(DiceRef(DRI, this)); 2459 2460 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2461 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2462 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2463 return dice_iterator(DiceRef(DRI, this)); 2464 } 2465 2466 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 2467 : Trie(T), Malformed(false), Done(false) {} 2468 2469 void ExportEntry::moveToFirst() { 2470 pushNode(0); 2471 pushDownUntilBottom(); 2472 } 2473 2474 void ExportEntry::moveToEnd() { 2475 Stack.clear(); 2476 Done = true; 2477 } 2478 2479 bool ExportEntry::operator==(const ExportEntry &Other) const { 2480 // Common case, one at end, other iterating from begin. 2481 if (Done || Other.Done) 2482 return (Done == Other.Done); 2483 // Not equal if different stack sizes. 2484 if (Stack.size() != Other.Stack.size()) 2485 return false; 2486 // Not equal if different cumulative strings. 2487 if (!CumulativeString.equals(Other.CumulativeString)) 2488 return false; 2489 // Equal if all nodes in both stacks match. 2490 for (unsigned i=0; i < Stack.size(); ++i) { 2491 if (Stack[i].Start != Other.Stack[i].Start) 2492 return false; 2493 } 2494 return true; 2495 } 2496 2497 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 2498 unsigned Count; 2499 uint64_t Result = decodeULEB128(Ptr, &Count); 2500 Ptr += Count; 2501 if (Ptr > Trie.end()) { 2502 Ptr = Trie.end(); 2503 Malformed = true; 2504 } 2505 return Result; 2506 } 2507 2508 StringRef ExportEntry::name() const { 2509 return CumulativeString; 2510 } 2511 2512 uint64_t ExportEntry::flags() const { 2513 return Stack.back().Flags; 2514 } 2515 2516 uint64_t ExportEntry::address() const { 2517 return Stack.back().Address; 2518 } 2519 2520 uint64_t ExportEntry::other() const { 2521 return Stack.back().Other; 2522 } 2523 2524 StringRef ExportEntry::otherName() const { 2525 const char* ImportName = Stack.back().ImportName; 2526 if (ImportName) 2527 return StringRef(ImportName); 2528 return StringRef(); 2529 } 2530 2531 uint32_t ExportEntry::nodeOffset() const { 2532 return Stack.back().Start - Trie.begin(); 2533 } 2534 2535 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2536 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 2537 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 2538 ParentStringLength(0), IsExportNode(false) {} 2539 2540 void ExportEntry::pushNode(uint64_t offset) { 2541 const uint8_t *Ptr = Trie.begin() + offset; 2542 NodeState State(Ptr); 2543 uint64_t ExportInfoSize = readULEB128(State.Current); 2544 State.IsExportNode = (ExportInfoSize != 0); 2545 const uint8_t* Children = State.Current + ExportInfoSize; 2546 if (State.IsExportNode) { 2547 State.Flags = readULEB128(State.Current); 2548 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2549 State.Address = 0; 2550 State.Other = readULEB128(State.Current); // dylib ordinal 2551 State.ImportName = reinterpret_cast<const char*>(State.Current); 2552 } else { 2553 State.Address = readULEB128(State.Current); 2554 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 2555 State.Other = readULEB128(State.Current); 2556 } 2557 } 2558 State.ChildCount = *Children; 2559 State.Current = Children + 1; 2560 State.NextChildIndex = 0; 2561 State.ParentStringLength = CumulativeString.size(); 2562 Stack.push_back(State); 2563 } 2564 2565 void ExportEntry::pushDownUntilBottom() { 2566 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2567 NodeState &Top = Stack.back(); 2568 CumulativeString.resize(Top.ParentStringLength); 2569 for (;*Top.Current != 0; Top.Current++) { 2570 char C = *Top.Current; 2571 CumulativeString.push_back(C); 2572 } 2573 Top.Current += 1; 2574 uint64_t childNodeIndex = readULEB128(Top.Current); 2575 Top.NextChildIndex += 1; 2576 pushNode(childNodeIndex); 2577 } 2578 if (!Stack.back().IsExportNode) { 2579 Malformed = true; 2580 moveToEnd(); 2581 } 2582 } 2583 2584 // We have a trie data structure and need a way to walk it that is compatible 2585 // with the C++ iterator model. The solution is a non-recursive depth first 2586 // traversal where the iterator contains a stack of parent nodes along with a 2587 // string that is the accumulation of all edge strings along the parent chain 2588 // to this point. 2589 // 2590 // There is one "export" node for each exported symbol. But because some 2591 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2592 // node may have child nodes too. 2593 // 2594 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2595 // child until hitting a node with no children (which is an export node or 2596 // else the trie is malformed). On the way down, each node is pushed on the 2597 // stack ivar. If there is no more ways down, it pops up one and tries to go 2598 // down a sibling path until a childless node is reached. 2599 void ExportEntry::moveNext() { 2600 if (Stack.empty() || !Stack.back().IsExportNode) { 2601 Malformed = true; 2602 moveToEnd(); 2603 return; 2604 } 2605 2606 Stack.pop_back(); 2607 while (!Stack.empty()) { 2608 NodeState &Top = Stack.back(); 2609 if (Top.NextChildIndex < Top.ChildCount) { 2610 pushDownUntilBottom(); 2611 // Now at the next export node. 2612 return; 2613 } else { 2614 if (Top.IsExportNode) { 2615 // This node has no children but is itself an export node. 2616 CumulativeString.resize(Top.ParentStringLength); 2617 return; 2618 } 2619 Stack.pop_back(); 2620 } 2621 } 2622 Done = true; 2623 } 2624 2625 iterator_range<export_iterator> 2626 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 2627 ExportEntry Start(Trie); 2628 if (Trie.size() == 0) 2629 Start.moveToEnd(); 2630 else 2631 Start.moveToFirst(); 2632 2633 ExportEntry Finish(Trie); 2634 Finish.moveToEnd(); 2635 2636 return make_range(export_iterator(Start), export_iterator(Finish)); 2637 } 2638 2639 iterator_range<export_iterator> MachOObjectFile::exports() const { 2640 return exports(getDyldInfoExportsTrie()); 2641 } 2642 2643 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 2644 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2645 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 2646 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 2647 2648 void MachORebaseEntry::moveToFirst() { 2649 Ptr = Opcodes.begin(); 2650 moveNext(); 2651 } 2652 2653 void MachORebaseEntry::moveToEnd() { 2654 Ptr = Opcodes.end(); 2655 RemainingLoopCount = 0; 2656 Done = true; 2657 } 2658 2659 void MachORebaseEntry::moveNext() { 2660 // If in the middle of some loop, move to next rebasing in loop. 2661 SegmentOffset += AdvanceAmount; 2662 if (RemainingLoopCount) { 2663 --RemainingLoopCount; 2664 return; 2665 } 2666 if (Ptr == Opcodes.end()) { 2667 Done = true; 2668 return; 2669 } 2670 bool More = true; 2671 while (More && !Malformed) { 2672 // Parse next opcode and set up next loop. 2673 uint8_t Byte = *Ptr++; 2674 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2675 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2676 switch (Opcode) { 2677 case MachO::REBASE_OPCODE_DONE: 2678 More = false; 2679 Done = true; 2680 moveToEnd(); 2681 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 2682 break; 2683 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2684 RebaseType = ImmValue; 2685 DEBUG_WITH_TYPE( 2686 "mach-o-rebase", 2687 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2688 << "RebaseType=" << (int) RebaseType << "\n"); 2689 break; 2690 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2691 SegmentIndex = ImmValue; 2692 SegmentOffset = readULEB128(); 2693 DEBUG_WITH_TYPE( 2694 "mach-o-rebase", 2695 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2696 << "SegmentIndex=" << SegmentIndex << ", " 2697 << format("SegmentOffset=0x%06X", SegmentOffset) 2698 << "\n"); 2699 break; 2700 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 2701 SegmentOffset += readULEB128(); 2702 DEBUG_WITH_TYPE("mach-o-rebase", 2703 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 2704 << format("SegmentOffset=0x%06X", 2705 SegmentOffset) << "\n"); 2706 break; 2707 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 2708 SegmentOffset += ImmValue * PointerSize; 2709 DEBUG_WITH_TYPE("mach-o-rebase", 2710 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 2711 << format("SegmentOffset=0x%06X", 2712 SegmentOffset) << "\n"); 2713 break; 2714 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 2715 AdvanceAmount = PointerSize; 2716 RemainingLoopCount = ImmValue - 1; 2717 DEBUG_WITH_TYPE( 2718 "mach-o-rebase", 2719 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 2720 << format("SegmentOffset=0x%06X", SegmentOffset) 2721 << ", AdvanceAmount=" << AdvanceAmount 2722 << ", RemainingLoopCount=" << RemainingLoopCount 2723 << "\n"); 2724 return; 2725 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 2726 AdvanceAmount = PointerSize; 2727 RemainingLoopCount = readULEB128() - 1; 2728 DEBUG_WITH_TYPE( 2729 "mach-o-rebase", 2730 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 2731 << format("SegmentOffset=0x%06X", SegmentOffset) 2732 << ", AdvanceAmount=" << AdvanceAmount 2733 << ", RemainingLoopCount=" << RemainingLoopCount 2734 << "\n"); 2735 return; 2736 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2737 AdvanceAmount = readULEB128() + PointerSize; 2738 RemainingLoopCount = 0; 2739 DEBUG_WITH_TYPE( 2740 "mach-o-rebase", 2741 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2742 << format("SegmentOffset=0x%06X", SegmentOffset) 2743 << ", AdvanceAmount=" << AdvanceAmount 2744 << ", RemainingLoopCount=" << RemainingLoopCount 2745 << "\n"); 2746 return; 2747 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2748 RemainingLoopCount = readULEB128() - 1; 2749 AdvanceAmount = readULEB128() + PointerSize; 2750 DEBUG_WITH_TYPE( 2751 "mach-o-rebase", 2752 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2753 << format("SegmentOffset=0x%06X", SegmentOffset) 2754 << ", AdvanceAmount=" << AdvanceAmount 2755 << ", RemainingLoopCount=" << RemainingLoopCount 2756 << "\n"); 2757 return; 2758 default: 2759 Malformed = true; 2760 } 2761 } 2762 } 2763 2764 uint64_t MachORebaseEntry::readULEB128() { 2765 unsigned Count; 2766 uint64_t Result = decodeULEB128(Ptr, &Count); 2767 Ptr += Count; 2768 if (Ptr > Opcodes.end()) { 2769 Ptr = Opcodes.end(); 2770 Malformed = true; 2771 } 2772 return Result; 2773 } 2774 2775 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2776 2777 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2778 2779 StringRef MachORebaseEntry::typeName() const { 2780 switch (RebaseType) { 2781 case MachO::REBASE_TYPE_POINTER: 2782 return "pointer"; 2783 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2784 return "text abs32"; 2785 case MachO::REBASE_TYPE_TEXT_PCREL32: 2786 return "text rel32"; 2787 } 2788 return "unknown"; 2789 } 2790 2791 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2792 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2793 return (Ptr == Other.Ptr) && 2794 (RemainingLoopCount == Other.RemainingLoopCount) && 2795 (Done == Other.Done); 2796 } 2797 2798 iterator_range<rebase_iterator> 2799 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2800 MachORebaseEntry Start(Opcodes, is64); 2801 Start.moveToFirst(); 2802 2803 MachORebaseEntry Finish(Opcodes, is64); 2804 Finish.moveToEnd(); 2805 2806 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2807 } 2808 2809 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2810 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2811 } 2812 2813 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2814 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2815 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2816 BindType(0), PointerSize(is64Bit ? 8 : 4), 2817 TableKind(BK), Malformed(false), Done(false) {} 2818 2819 void MachOBindEntry::moveToFirst() { 2820 Ptr = Opcodes.begin(); 2821 moveNext(); 2822 } 2823 2824 void MachOBindEntry::moveToEnd() { 2825 Ptr = Opcodes.end(); 2826 RemainingLoopCount = 0; 2827 Done = true; 2828 } 2829 2830 void MachOBindEntry::moveNext() { 2831 // If in the middle of some loop, move to next binding in loop. 2832 SegmentOffset += AdvanceAmount; 2833 if (RemainingLoopCount) { 2834 --RemainingLoopCount; 2835 return; 2836 } 2837 if (Ptr == Opcodes.end()) { 2838 Done = true; 2839 return; 2840 } 2841 bool More = true; 2842 while (More && !Malformed) { 2843 // Parse next opcode and set up next loop. 2844 uint8_t Byte = *Ptr++; 2845 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2846 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2847 int8_t SignExtended; 2848 const uint8_t *SymStart; 2849 switch (Opcode) { 2850 case MachO::BIND_OPCODE_DONE: 2851 if (TableKind == Kind::Lazy) { 2852 // Lazying bindings have a DONE opcode between entries. Need to ignore 2853 // it to advance to next entry. But need not if this is last entry. 2854 bool NotLastEntry = false; 2855 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2856 if (*P) { 2857 NotLastEntry = true; 2858 } 2859 } 2860 if (NotLastEntry) 2861 break; 2862 } 2863 More = false; 2864 Done = true; 2865 moveToEnd(); 2866 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2867 break; 2868 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2869 Ordinal = ImmValue; 2870 DEBUG_WITH_TYPE( 2871 "mach-o-bind", 2872 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2873 << "Ordinal=" << Ordinal << "\n"); 2874 break; 2875 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2876 Ordinal = readULEB128(); 2877 DEBUG_WITH_TYPE( 2878 "mach-o-bind", 2879 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2880 << "Ordinal=" << Ordinal << "\n"); 2881 break; 2882 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2883 if (ImmValue) { 2884 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2885 Ordinal = SignExtended; 2886 } else 2887 Ordinal = 0; 2888 DEBUG_WITH_TYPE( 2889 "mach-o-bind", 2890 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2891 << "Ordinal=" << Ordinal << "\n"); 2892 break; 2893 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2894 Flags = ImmValue; 2895 SymStart = Ptr; 2896 while (*Ptr) { 2897 ++Ptr; 2898 } 2899 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2900 Ptr-SymStart); 2901 ++Ptr; 2902 DEBUG_WITH_TYPE( 2903 "mach-o-bind", 2904 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2905 << "SymbolName=" << SymbolName << "\n"); 2906 if (TableKind == Kind::Weak) { 2907 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2908 return; 2909 } 2910 break; 2911 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2912 BindType = ImmValue; 2913 DEBUG_WITH_TYPE( 2914 "mach-o-bind", 2915 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2916 << "BindType=" << (int)BindType << "\n"); 2917 break; 2918 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2919 Addend = readSLEB128(); 2920 if (TableKind == Kind::Lazy) 2921 Malformed = true; 2922 DEBUG_WITH_TYPE( 2923 "mach-o-bind", 2924 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2925 << "Addend=" << Addend << "\n"); 2926 break; 2927 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2928 SegmentIndex = ImmValue; 2929 SegmentOffset = readULEB128(); 2930 DEBUG_WITH_TYPE( 2931 "mach-o-bind", 2932 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2933 << "SegmentIndex=" << SegmentIndex << ", " 2934 << format("SegmentOffset=0x%06X", SegmentOffset) 2935 << "\n"); 2936 break; 2937 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2938 SegmentOffset += readULEB128(); 2939 DEBUG_WITH_TYPE("mach-o-bind", 2940 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2941 << format("SegmentOffset=0x%06X", 2942 SegmentOffset) << "\n"); 2943 break; 2944 case MachO::BIND_OPCODE_DO_BIND: 2945 AdvanceAmount = PointerSize; 2946 RemainingLoopCount = 0; 2947 DEBUG_WITH_TYPE("mach-o-bind", 2948 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2949 << format("SegmentOffset=0x%06X", 2950 SegmentOffset) << "\n"); 2951 return; 2952 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2953 AdvanceAmount = readULEB128() + PointerSize; 2954 RemainingLoopCount = 0; 2955 if (TableKind == Kind::Lazy) 2956 Malformed = true; 2957 DEBUG_WITH_TYPE( 2958 "mach-o-bind", 2959 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2960 << format("SegmentOffset=0x%06X", SegmentOffset) 2961 << ", AdvanceAmount=" << AdvanceAmount 2962 << ", RemainingLoopCount=" << RemainingLoopCount 2963 << "\n"); 2964 return; 2965 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2966 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2967 RemainingLoopCount = 0; 2968 if (TableKind == Kind::Lazy) 2969 Malformed = true; 2970 DEBUG_WITH_TYPE("mach-o-bind", 2971 llvm::dbgs() 2972 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2973 << format("SegmentOffset=0x%06X", 2974 SegmentOffset) << "\n"); 2975 return; 2976 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2977 RemainingLoopCount = readULEB128() - 1; 2978 AdvanceAmount = readULEB128() + PointerSize; 2979 if (TableKind == Kind::Lazy) 2980 Malformed = true; 2981 DEBUG_WITH_TYPE( 2982 "mach-o-bind", 2983 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2984 << format("SegmentOffset=0x%06X", SegmentOffset) 2985 << ", AdvanceAmount=" << AdvanceAmount 2986 << ", RemainingLoopCount=" << RemainingLoopCount 2987 << "\n"); 2988 return; 2989 default: 2990 Malformed = true; 2991 } 2992 } 2993 } 2994 2995 uint64_t MachOBindEntry::readULEB128() { 2996 unsigned Count; 2997 uint64_t Result = decodeULEB128(Ptr, &Count); 2998 Ptr += Count; 2999 if (Ptr > Opcodes.end()) { 3000 Ptr = Opcodes.end(); 3001 Malformed = true; 3002 } 3003 return Result; 3004 } 3005 3006 int64_t MachOBindEntry::readSLEB128() { 3007 unsigned Count; 3008 int64_t Result = decodeSLEB128(Ptr, &Count); 3009 Ptr += Count; 3010 if (Ptr > Opcodes.end()) { 3011 Ptr = Opcodes.end(); 3012 Malformed = true; 3013 } 3014 return Result; 3015 } 3016 3017 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 3018 3019 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 3020 3021 StringRef MachOBindEntry::typeName() const { 3022 switch (BindType) { 3023 case MachO::BIND_TYPE_POINTER: 3024 return "pointer"; 3025 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 3026 return "text abs32"; 3027 case MachO::BIND_TYPE_TEXT_PCREL32: 3028 return "text rel32"; 3029 } 3030 return "unknown"; 3031 } 3032 3033 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 3034 3035 int64_t MachOBindEntry::addend() const { return Addend; } 3036 3037 uint32_t MachOBindEntry::flags() const { return Flags; } 3038 3039 int MachOBindEntry::ordinal() const { return Ordinal; } 3040 3041 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 3042 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 3043 return (Ptr == Other.Ptr) && 3044 (RemainingLoopCount == Other.RemainingLoopCount) && 3045 (Done == Other.Done); 3046 } 3047 3048 iterator_range<bind_iterator> 3049 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 3050 MachOBindEntry::Kind BKind) { 3051 MachOBindEntry Start(Opcodes, is64, BKind); 3052 Start.moveToFirst(); 3053 3054 MachOBindEntry Finish(Opcodes, is64, BKind); 3055 Finish.moveToEnd(); 3056 3057 return make_range(bind_iterator(Start), bind_iterator(Finish)); 3058 } 3059 3060 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 3061 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 3062 MachOBindEntry::Kind::Regular); 3063 } 3064 3065 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 3066 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 3067 MachOBindEntry::Kind::Lazy); 3068 } 3069 3070 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 3071 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 3072 MachOBindEntry::Kind::Weak); 3073 } 3074 3075 MachOObjectFile::load_command_iterator 3076 MachOObjectFile::begin_load_commands() const { 3077 return LoadCommands.begin(); 3078 } 3079 3080 MachOObjectFile::load_command_iterator 3081 MachOObjectFile::end_load_commands() const { 3082 return LoadCommands.end(); 3083 } 3084 3085 iterator_range<MachOObjectFile::load_command_iterator> 3086 MachOObjectFile::load_commands() const { 3087 return make_range(begin_load_commands(), end_load_commands()); 3088 } 3089 3090 StringRef 3091 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 3092 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 3093 return parseSegmentOrSectionName(Raw.data()); 3094 } 3095 3096 ArrayRef<char> 3097 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 3098 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3099 const section_base *Base = 3100 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3101 return makeArrayRef(Base->sectname); 3102 } 3103 3104 ArrayRef<char> 3105 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 3106 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3107 const section_base *Base = 3108 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3109 return makeArrayRef(Base->segname); 3110 } 3111 3112 bool 3113 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 3114 const { 3115 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 3116 return false; 3117 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 3118 } 3119 3120 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 3121 const MachO::any_relocation_info &RE) const { 3122 if (isLittleEndian()) 3123 return RE.r_word1 & 0xffffff; 3124 return RE.r_word1 >> 8; 3125 } 3126 3127 bool MachOObjectFile::getPlainRelocationExternal( 3128 const MachO::any_relocation_info &RE) const { 3129 if (isLittleEndian()) 3130 return (RE.r_word1 >> 27) & 1; 3131 return (RE.r_word1 >> 4) & 1; 3132 } 3133 3134 bool MachOObjectFile::getScatteredRelocationScattered( 3135 const MachO::any_relocation_info &RE) const { 3136 return RE.r_word0 >> 31; 3137 } 3138 3139 uint32_t MachOObjectFile::getScatteredRelocationValue( 3140 const MachO::any_relocation_info &RE) const { 3141 return RE.r_word1; 3142 } 3143 3144 uint32_t MachOObjectFile::getScatteredRelocationType( 3145 const MachO::any_relocation_info &RE) const { 3146 return (RE.r_word0 >> 24) & 0xf; 3147 } 3148 3149 unsigned MachOObjectFile::getAnyRelocationAddress( 3150 const MachO::any_relocation_info &RE) const { 3151 if (isRelocationScattered(RE)) 3152 return getScatteredRelocationAddress(RE); 3153 return getPlainRelocationAddress(RE); 3154 } 3155 3156 unsigned MachOObjectFile::getAnyRelocationPCRel( 3157 const MachO::any_relocation_info &RE) const { 3158 if (isRelocationScattered(RE)) 3159 return getScatteredRelocationPCRel(this, RE); 3160 return getPlainRelocationPCRel(this, RE); 3161 } 3162 3163 unsigned MachOObjectFile::getAnyRelocationLength( 3164 const MachO::any_relocation_info &RE) const { 3165 if (isRelocationScattered(RE)) 3166 return getScatteredRelocationLength(RE); 3167 return getPlainRelocationLength(this, RE); 3168 } 3169 3170 unsigned 3171 MachOObjectFile::getAnyRelocationType( 3172 const MachO::any_relocation_info &RE) const { 3173 if (isRelocationScattered(RE)) 3174 return getScatteredRelocationType(RE); 3175 return getPlainRelocationType(this, RE); 3176 } 3177 3178 SectionRef 3179 MachOObjectFile::getAnyRelocationSection( 3180 const MachO::any_relocation_info &RE) const { 3181 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 3182 return *section_end(); 3183 unsigned SecNum = getPlainRelocationSymbolNum(RE); 3184 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 3185 return *section_end(); 3186 DataRefImpl DRI; 3187 DRI.d.a = SecNum - 1; 3188 return SectionRef(DRI, this); 3189 } 3190 3191 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 3192 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3193 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 3194 } 3195 3196 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 3197 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3198 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 3199 } 3200 3201 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 3202 unsigned Index) const { 3203 const char *Sec = getSectionPtr(this, L, Index); 3204 return getStruct<MachO::section>(this, Sec); 3205 } 3206 3207 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 3208 unsigned Index) const { 3209 const char *Sec = getSectionPtr(this, L, Index); 3210 return getStruct<MachO::section_64>(this, Sec); 3211 } 3212 3213 MachO::nlist 3214 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 3215 const char *P = reinterpret_cast<const char *>(DRI.p); 3216 return getStruct<MachO::nlist>(this, P); 3217 } 3218 3219 MachO::nlist_64 3220 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 3221 const char *P = reinterpret_cast<const char *>(DRI.p); 3222 return getStruct<MachO::nlist_64>(this, P); 3223 } 3224 3225 MachO::linkedit_data_command 3226 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 3227 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 3228 } 3229 3230 MachO::segment_command 3231 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 3232 return getStruct<MachO::segment_command>(this, L.Ptr); 3233 } 3234 3235 MachO::segment_command_64 3236 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 3237 return getStruct<MachO::segment_command_64>(this, L.Ptr); 3238 } 3239 3240 MachO::linker_option_command 3241 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 3242 return getStruct<MachO::linker_option_command>(this, L.Ptr); 3243 } 3244 3245 MachO::version_min_command 3246 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 3247 return getStruct<MachO::version_min_command>(this, L.Ptr); 3248 } 3249 3250 MachO::dylib_command 3251 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 3252 return getStruct<MachO::dylib_command>(this, L.Ptr); 3253 } 3254 3255 MachO::dyld_info_command 3256 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 3257 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 3258 } 3259 3260 MachO::dylinker_command 3261 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 3262 return getStruct<MachO::dylinker_command>(this, L.Ptr); 3263 } 3264 3265 MachO::uuid_command 3266 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 3267 return getStruct<MachO::uuid_command>(this, L.Ptr); 3268 } 3269 3270 MachO::rpath_command 3271 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 3272 return getStruct<MachO::rpath_command>(this, L.Ptr); 3273 } 3274 3275 MachO::source_version_command 3276 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 3277 return getStruct<MachO::source_version_command>(this, L.Ptr); 3278 } 3279 3280 MachO::entry_point_command 3281 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 3282 return getStruct<MachO::entry_point_command>(this, L.Ptr); 3283 } 3284 3285 MachO::encryption_info_command 3286 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 3287 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 3288 } 3289 3290 MachO::encryption_info_command_64 3291 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 3292 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 3293 } 3294 3295 MachO::sub_framework_command 3296 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 3297 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 3298 } 3299 3300 MachO::sub_umbrella_command 3301 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 3302 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 3303 } 3304 3305 MachO::sub_library_command 3306 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 3307 return getStruct<MachO::sub_library_command>(this, L.Ptr); 3308 } 3309 3310 MachO::sub_client_command 3311 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 3312 return getStruct<MachO::sub_client_command>(this, L.Ptr); 3313 } 3314 3315 MachO::routines_command 3316 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 3317 return getStruct<MachO::routines_command>(this, L.Ptr); 3318 } 3319 3320 MachO::routines_command_64 3321 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 3322 return getStruct<MachO::routines_command_64>(this, L.Ptr); 3323 } 3324 3325 MachO::thread_command 3326 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 3327 return getStruct<MachO::thread_command>(this, L.Ptr); 3328 } 3329 3330 MachO::any_relocation_info 3331 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 3332 DataRefImpl Sec; 3333 Sec.d.a = Rel.d.a; 3334 uint32_t Offset; 3335 if (is64Bit()) { 3336 MachO::section_64 Sect = getSection64(Sec); 3337 Offset = Sect.reloff; 3338 } else { 3339 MachO::section Sect = getSection(Sec); 3340 Offset = Sect.reloff; 3341 } 3342 3343 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 3344 getPtr(this, Offset)) + Rel.d.b; 3345 return getStruct<MachO::any_relocation_info>( 3346 this, reinterpret_cast<const char *>(P)); 3347 } 3348 3349 MachO::data_in_code_entry 3350 MachOObjectFile::getDice(DataRefImpl Rel) const { 3351 const char *P = reinterpret_cast<const char *>(Rel.p); 3352 return getStruct<MachO::data_in_code_entry>(this, P); 3353 } 3354 3355 const MachO::mach_header &MachOObjectFile::getHeader() const { 3356 return Header; 3357 } 3358 3359 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 3360 assert(is64Bit()); 3361 return Header64; 3362 } 3363 3364 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 3365 const MachO::dysymtab_command &DLC, 3366 unsigned Index) const { 3367 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 3368 return getStruct<uint32_t>(this, getPtr(this, Offset)); 3369 } 3370 3371 MachO::data_in_code_entry 3372 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 3373 unsigned Index) const { 3374 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 3375 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 3376 } 3377 3378 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 3379 if (SymtabLoadCmd) 3380 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 3381 3382 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 3383 MachO::symtab_command Cmd; 3384 Cmd.cmd = MachO::LC_SYMTAB; 3385 Cmd.cmdsize = sizeof(MachO::symtab_command); 3386 Cmd.symoff = 0; 3387 Cmd.nsyms = 0; 3388 Cmd.stroff = 0; 3389 Cmd.strsize = 0; 3390 return Cmd; 3391 } 3392 3393 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 3394 if (DysymtabLoadCmd) 3395 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 3396 3397 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 3398 MachO::dysymtab_command Cmd; 3399 Cmd.cmd = MachO::LC_DYSYMTAB; 3400 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 3401 Cmd.ilocalsym = 0; 3402 Cmd.nlocalsym = 0; 3403 Cmd.iextdefsym = 0; 3404 Cmd.nextdefsym = 0; 3405 Cmd.iundefsym = 0; 3406 Cmd.nundefsym = 0; 3407 Cmd.tocoff = 0; 3408 Cmd.ntoc = 0; 3409 Cmd.modtaboff = 0; 3410 Cmd.nmodtab = 0; 3411 Cmd.extrefsymoff = 0; 3412 Cmd.nextrefsyms = 0; 3413 Cmd.indirectsymoff = 0; 3414 Cmd.nindirectsyms = 0; 3415 Cmd.extreloff = 0; 3416 Cmd.nextrel = 0; 3417 Cmd.locreloff = 0; 3418 Cmd.nlocrel = 0; 3419 return Cmd; 3420 } 3421 3422 MachO::linkedit_data_command 3423 MachOObjectFile::getDataInCodeLoadCommand() const { 3424 if (DataInCodeLoadCmd) 3425 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 3426 3427 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 3428 MachO::linkedit_data_command Cmd; 3429 Cmd.cmd = MachO::LC_DATA_IN_CODE; 3430 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3431 Cmd.dataoff = 0; 3432 Cmd.datasize = 0; 3433 return Cmd; 3434 } 3435 3436 MachO::linkedit_data_command 3437 MachOObjectFile::getLinkOptHintsLoadCommand() const { 3438 if (LinkOptHintsLoadCmd) 3439 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 3440 3441 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 3442 // fields. 3443 MachO::linkedit_data_command Cmd; 3444 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 3445 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3446 Cmd.dataoff = 0; 3447 Cmd.datasize = 0; 3448 return Cmd; 3449 } 3450 3451 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 3452 if (!DyldInfoLoadCmd) 3453 return None; 3454 3455 MachO::dyld_info_command DyldInfo = 3456 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3457 const uint8_t *Ptr = 3458 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 3459 return makeArrayRef(Ptr, DyldInfo.rebase_size); 3460 } 3461 3462 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 3463 if (!DyldInfoLoadCmd) 3464 return None; 3465 3466 MachO::dyld_info_command DyldInfo = 3467 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3468 const uint8_t *Ptr = 3469 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 3470 return makeArrayRef(Ptr, DyldInfo.bind_size); 3471 } 3472 3473 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 3474 if (!DyldInfoLoadCmd) 3475 return None; 3476 3477 MachO::dyld_info_command DyldInfo = 3478 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3479 const uint8_t *Ptr = 3480 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 3481 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 3482 } 3483 3484 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 3485 if (!DyldInfoLoadCmd) 3486 return None; 3487 3488 MachO::dyld_info_command DyldInfo = 3489 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3490 const uint8_t *Ptr = 3491 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 3492 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 3493 } 3494 3495 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 3496 if (!DyldInfoLoadCmd) 3497 return None; 3498 3499 MachO::dyld_info_command DyldInfo = 3500 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3501 const uint8_t *Ptr = 3502 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 3503 return makeArrayRef(Ptr, DyldInfo.export_size); 3504 } 3505 3506 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 3507 if (!UuidLoadCmd) 3508 return None; 3509 // Returning a pointer is fine as uuid doesn't need endian swapping. 3510 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 3511 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 3512 } 3513 3514 StringRef MachOObjectFile::getStringTableData() const { 3515 MachO::symtab_command S = getSymtabLoadCommand(); 3516 return getData().substr(S.stroff, S.strsize); 3517 } 3518 3519 bool MachOObjectFile::is64Bit() const { 3520 return getType() == getMachOType(false, true) || 3521 getType() == getMachOType(true, true); 3522 } 3523 3524 void MachOObjectFile::ReadULEB128s(uint64_t Index, 3525 SmallVectorImpl<uint64_t> &Out) const { 3526 DataExtractor extractor(ObjectFile::getData(), true, 0); 3527 3528 uint32_t offset = Index; 3529 uint64_t data = 0; 3530 while (uint64_t delta = extractor.getULEB128(&offset)) { 3531 data += delta; 3532 Out.push_back(data); 3533 } 3534 } 3535 3536 bool MachOObjectFile::isRelocatableObject() const { 3537 return getHeader().filetype == MachO::MH_OBJECT; 3538 } 3539 3540 Expected<std::unique_ptr<MachOObjectFile>> 3541 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, 3542 uint32_t UniversalCputype, 3543 uint32_t UniversalIndex) { 3544 StringRef Magic = Buffer.getBuffer().slice(0, 4); 3545 if (Magic == "\xFE\xED\xFA\xCE") 3546 return MachOObjectFile::create(Buffer, false, false, 3547 UniversalCputype, UniversalIndex); 3548 if (Magic == "\xCE\xFA\xED\xFE") 3549 return MachOObjectFile::create(Buffer, true, false, 3550 UniversalCputype, UniversalIndex); 3551 if (Magic == "\xFE\xED\xFA\xCF") 3552 return MachOObjectFile::create(Buffer, false, true, 3553 UniversalCputype, UniversalIndex); 3554 if (Magic == "\xCF\xFA\xED\xFE") 3555 return MachOObjectFile::create(Buffer, true, true, 3556 UniversalCputype, UniversalIndex); 3557 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 3558 object_error::invalid_file_type); 3559 } 3560