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