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