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