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