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 if (McpuDefault) 2323 *McpuDefault = nullptr; 2324 2325 switch (CPUType) { 2326 case MachO::CPU_TYPE_I386: 2327 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2328 case MachO::CPU_SUBTYPE_I386_ALL: 2329 return Triple("i386-apple-darwin"); 2330 default: 2331 return Triple(); 2332 } 2333 case MachO::CPU_TYPE_X86_64: 2334 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2335 case MachO::CPU_SUBTYPE_X86_64_ALL: 2336 return Triple("x86_64-apple-darwin"); 2337 case MachO::CPU_SUBTYPE_X86_64_H: 2338 return Triple("x86_64h-apple-darwin"); 2339 default: 2340 return Triple(); 2341 } 2342 case MachO::CPU_TYPE_ARM: 2343 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2344 case MachO::CPU_SUBTYPE_ARM_V4T: 2345 return Triple("armv4t-apple-darwin"); 2346 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2347 return Triple("armv5e-apple-darwin"); 2348 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2349 return Triple("xscale-apple-darwin"); 2350 case MachO::CPU_SUBTYPE_ARM_V6: 2351 return Triple("armv6-apple-darwin"); 2352 case MachO::CPU_SUBTYPE_ARM_V6M: 2353 if (McpuDefault) 2354 *McpuDefault = "cortex-m0"; 2355 return Triple("armv6m-apple-darwin"); 2356 case MachO::CPU_SUBTYPE_ARM_V7: 2357 return Triple("armv7-apple-darwin"); 2358 case MachO::CPU_SUBTYPE_ARM_V7EM: 2359 if (McpuDefault) 2360 *McpuDefault = "cortex-m4"; 2361 return Triple("thumbv7em-apple-darwin"); 2362 case MachO::CPU_SUBTYPE_ARM_V7K: 2363 return Triple("armv7k-apple-darwin"); 2364 case MachO::CPU_SUBTYPE_ARM_V7M: 2365 if (McpuDefault) 2366 *McpuDefault = "cortex-m3"; 2367 return Triple("thumbv7m-apple-darwin"); 2368 case MachO::CPU_SUBTYPE_ARM_V7S: 2369 return Triple("armv7s-apple-darwin"); 2370 default: 2371 return Triple(); 2372 } 2373 case MachO::CPU_TYPE_ARM64: 2374 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2375 case MachO::CPU_SUBTYPE_ARM64_ALL: 2376 return Triple("arm64-apple-darwin"); 2377 default: 2378 return Triple(); 2379 } 2380 case MachO::CPU_TYPE_POWERPC: 2381 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2382 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2383 return Triple("ppc-apple-darwin"); 2384 default: 2385 return Triple(); 2386 } 2387 case MachO::CPU_TYPE_POWERPC64: 2388 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2389 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2390 return Triple("ppc64-apple-darwin"); 2391 default: 2392 return Triple(); 2393 } 2394 default: 2395 return Triple(); 2396 } 2397 } 2398 2399 Triple MachOObjectFile::getHostArch() { 2400 return Triple(sys::getDefaultTargetTriple()); 2401 } 2402 2403 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2404 return StringSwitch<bool>(ArchFlag) 2405 .Case("i386", true) 2406 .Case("x86_64", true) 2407 .Case("x86_64h", true) 2408 .Case("armv4t", true) 2409 .Case("arm", true) 2410 .Case("armv5e", true) 2411 .Case("armv6", true) 2412 .Case("armv6m", true) 2413 .Case("armv7", true) 2414 .Case("armv7em", true) 2415 .Case("armv7k", true) 2416 .Case("armv7m", true) 2417 .Case("armv7s", true) 2418 .Case("arm64", true) 2419 .Case("ppc", true) 2420 .Case("ppc64", true) 2421 .Default(false); 2422 } 2423 2424 unsigned MachOObjectFile::getArch() const { 2425 return getArch(getCPUType(*this)); 2426 } 2427 2428 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2429 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2430 } 2431 2432 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2433 DataRefImpl DRI; 2434 DRI.d.a = Index; 2435 return section_rel_begin(DRI); 2436 } 2437 2438 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2439 DataRefImpl DRI; 2440 DRI.d.a = Index; 2441 return section_rel_end(DRI); 2442 } 2443 2444 dice_iterator MachOObjectFile::begin_dices() const { 2445 DataRefImpl DRI; 2446 if (!DataInCodeLoadCmd) 2447 return dice_iterator(DiceRef(DRI, this)); 2448 2449 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2450 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff)); 2451 return dice_iterator(DiceRef(DRI, this)); 2452 } 2453 2454 dice_iterator MachOObjectFile::end_dices() const { 2455 DataRefImpl DRI; 2456 if (!DataInCodeLoadCmd) 2457 return dice_iterator(DiceRef(DRI, this)); 2458 2459 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2460 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2461 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset)); 2462 return dice_iterator(DiceRef(DRI, this)); 2463 } 2464 2465 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 2466 : Trie(T), Malformed(false), Done(false) {} 2467 2468 void ExportEntry::moveToFirst() { 2469 pushNode(0); 2470 pushDownUntilBottom(); 2471 } 2472 2473 void ExportEntry::moveToEnd() { 2474 Stack.clear(); 2475 Done = true; 2476 } 2477 2478 bool ExportEntry::operator==(const ExportEntry &Other) const { 2479 // Common case, one at end, other iterating from begin. 2480 if (Done || Other.Done) 2481 return (Done == Other.Done); 2482 // Not equal if different stack sizes. 2483 if (Stack.size() != Other.Stack.size()) 2484 return false; 2485 // Not equal if different cumulative strings. 2486 if (!CumulativeString.equals(Other.CumulativeString)) 2487 return false; 2488 // Equal if all nodes in both stacks match. 2489 for (unsigned i=0; i < Stack.size(); ++i) { 2490 if (Stack[i].Start != Other.Stack[i].Start) 2491 return false; 2492 } 2493 return true; 2494 } 2495 2496 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 2497 unsigned Count; 2498 uint64_t Result = decodeULEB128(Ptr, &Count); 2499 Ptr += Count; 2500 if (Ptr > Trie.end()) { 2501 Ptr = Trie.end(); 2502 Malformed = true; 2503 } 2504 return Result; 2505 } 2506 2507 StringRef ExportEntry::name() const { 2508 return CumulativeString; 2509 } 2510 2511 uint64_t ExportEntry::flags() const { 2512 return Stack.back().Flags; 2513 } 2514 2515 uint64_t ExportEntry::address() const { 2516 return Stack.back().Address; 2517 } 2518 2519 uint64_t ExportEntry::other() const { 2520 return Stack.back().Other; 2521 } 2522 2523 StringRef ExportEntry::otherName() const { 2524 const char* ImportName = Stack.back().ImportName; 2525 if (ImportName) 2526 return StringRef(ImportName); 2527 return StringRef(); 2528 } 2529 2530 uint32_t ExportEntry::nodeOffset() const { 2531 return Stack.back().Start - Trie.begin(); 2532 } 2533 2534 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2535 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 2536 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 2537 ParentStringLength(0), IsExportNode(false) {} 2538 2539 void ExportEntry::pushNode(uint64_t offset) { 2540 const uint8_t *Ptr = Trie.begin() + offset; 2541 NodeState State(Ptr); 2542 uint64_t ExportInfoSize = readULEB128(State.Current); 2543 State.IsExportNode = (ExportInfoSize != 0); 2544 const uint8_t* Children = State.Current + ExportInfoSize; 2545 if (State.IsExportNode) { 2546 State.Flags = readULEB128(State.Current); 2547 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2548 State.Address = 0; 2549 State.Other = readULEB128(State.Current); // dylib ordinal 2550 State.ImportName = reinterpret_cast<const char*>(State.Current); 2551 } else { 2552 State.Address = readULEB128(State.Current); 2553 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 2554 State.Other = readULEB128(State.Current); 2555 } 2556 } 2557 State.ChildCount = *Children; 2558 State.Current = Children + 1; 2559 State.NextChildIndex = 0; 2560 State.ParentStringLength = CumulativeString.size(); 2561 Stack.push_back(State); 2562 } 2563 2564 void ExportEntry::pushDownUntilBottom() { 2565 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2566 NodeState &Top = Stack.back(); 2567 CumulativeString.resize(Top.ParentStringLength); 2568 for (;*Top.Current != 0; Top.Current++) { 2569 char C = *Top.Current; 2570 CumulativeString.push_back(C); 2571 } 2572 Top.Current += 1; 2573 uint64_t childNodeIndex = readULEB128(Top.Current); 2574 Top.NextChildIndex += 1; 2575 pushNode(childNodeIndex); 2576 } 2577 if (!Stack.back().IsExportNode) { 2578 Malformed = true; 2579 moveToEnd(); 2580 } 2581 } 2582 2583 // We have a trie data structure and need a way to walk it that is compatible 2584 // with the C++ iterator model. The solution is a non-recursive depth first 2585 // traversal where the iterator contains a stack of parent nodes along with a 2586 // string that is the accumulation of all edge strings along the parent chain 2587 // to this point. 2588 // 2589 // There is one "export" node for each exported symbol. But because some 2590 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2591 // node may have child nodes too. 2592 // 2593 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2594 // child until hitting a node with no children (which is an export node or 2595 // else the trie is malformed). On the way down, each node is pushed on the 2596 // stack ivar. If there is no more ways down, it pops up one and tries to go 2597 // down a sibling path until a childless node is reached. 2598 void ExportEntry::moveNext() { 2599 if (Stack.empty() || !Stack.back().IsExportNode) { 2600 Malformed = true; 2601 moveToEnd(); 2602 return; 2603 } 2604 2605 Stack.pop_back(); 2606 while (!Stack.empty()) { 2607 NodeState &Top = Stack.back(); 2608 if (Top.NextChildIndex < Top.ChildCount) { 2609 pushDownUntilBottom(); 2610 // Now at the next export node. 2611 return; 2612 } else { 2613 if (Top.IsExportNode) { 2614 // This node has no children but is itself an export node. 2615 CumulativeString.resize(Top.ParentStringLength); 2616 return; 2617 } 2618 Stack.pop_back(); 2619 } 2620 } 2621 Done = true; 2622 } 2623 2624 iterator_range<export_iterator> 2625 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 2626 ExportEntry Start(Trie); 2627 if (Trie.size() == 0) 2628 Start.moveToEnd(); 2629 else 2630 Start.moveToFirst(); 2631 2632 ExportEntry Finish(Trie); 2633 Finish.moveToEnd(); 2634 2635 return make_range(export_iterator(Start), export_iterator(Finish)); 2636 } 2637 2638 iterator_range<export_iterator> MachOObjectFile::exports() const { 2639 return exports(getDyldInfoExportsTrie()); 2640 } 2641 2642 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 2643 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2644 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 2645 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 2646 2647 void MachORebaseEntry::moveToFirst() { 2648 Ptr = Opcodes.begin(); 2649 moveNext(); 2650 } 2651 2652 void MachORebaseEntry::moveToEnd() { 2653 Ptr = Opcodes.end(); 2654 RemainingLoopCount = 0; 2655 Done = true; 2656 } 2657 2658 void MachORebaseEntry::moveNext() { 2659 // If in the middle of some loop, move to next rebasing in loop. 2660 SegmentOffset += AdvanceAmount; 2661 if (RemainingLoopCount) { 2662 --RemainingLoopCount; 2663 return; 2664 } 2665 if (Ptr == Opcodes.end()) { 2666 Done = true; 2667 return; 2668 } 2669 bool More = true; 2670 while (More && !Malformed) { 2671 // Parse next opcode and set up next loop. 2672 uint8_t Byte = *Ptr++; 2673 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2674 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2675 switch (Opcode) { 2676 case MachO::REBASE_OPCODE_DONE: 2677 More = false; 2678 Done = true; 2679 moveToEnd(); 2680 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 2681 break; 2682 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2683 RebaseType = ImmValue; 2684 DEBUG_WITH_TYPE( 2685 "mach-o-rebase", 2686 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2687 << "RebaseType=" << (int) RebaseType << "\n"); 2688 break; 2689 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2690 SegmentIndex = ImmValue; 2691 SegmentOffset = readULEB128(); 2692 DEBUG_WITH_TYPE( 2693 "mach-o-rebase", 2694 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2695 << "SegmentIndex=" << SegmentIndex << ", " 2696 << format("SegmentOffset=0x%06X", SegmentOffset) 2697 << "\n"); 2698 break; 2699 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 2700 SegmentOffset += readULEB128(); 2701 DEBUG_WITH_TYPE("mach-o-rebase", 2702 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 2703 << format("SegmentOffset=0x%06X", 2704 SegmentOffset) << "\n"); 2705 break; 2706 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 2707 SegmentOffset += ImmValue * PointerSize; 2708 DEBUG_WITH_TYPE("mach-o-rebase", 2709 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 2710 << format("SegmentOffset=0x%06X", 2711 SegmentOffset) << "\n"); 2712 break; 2713 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 2714 AdvanceAmount = PointerSize; 2715 RemainingLoopCount = ImmValue - 1; 2716 DEBUG_WITH_TYPE( 2717 "mach-o-rebase", 2718 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 2719 << format("SegmentOffset=0x%06X", SegmentOffset) 2720 << ", AdvanceAmount=" << AdvanceAmount 2721 << ", RemainingLoopCount=" << RemainingLoopCount 2722 << "\n"); 2723 return; 2724 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 2725 AdvanceAmount = PointerSize; 2726 RemainingLoopCount = readULEB128() - 1; 2727 DEBUG_WITH_TYPE( 2728 "mach-o-rebase", 2729 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 2730 << format("SegmentOffset=0x%06X", SegmentOffset) 2731 << ", AdvanceAmount=" << AdvanceAmount 2732 << ", RemainingLoopCount=" << RemainingLoopCount 2733 << "\n"); 2734 return; 2735 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2736 AdvanceAmount = readULEB128() + PointerSize; 2737 RemainingLoopCount = 0; 2738 DEBUG_WITH_TYPE( 2739 "mach-o-rebase", 2740 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2741 << format("SegmentOffset=0x%06X", SegmentOffset) 2742 << ", AdvanceAmount=" << AdvanceAmount 2743 << ", RemainingLoopCount=" << RemainingLoopCount 2744 << "\n"); 2745 return; 2746 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2747 RemainingLoopCount = readULEB128() - 1; 2748 AdvanceAmount = readULEB128() + PointerSize; 2749 DEBUG_WITH_TYPE( 2750 "mach-o-rebase", 2751 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2752 << format("SegmentOffset=0x%06X", SegmentOffset) 2753 << ", AdvanceAmount=" << AdvanceAmount 2754 << ", RemainingLoopCount=" << RemainingLoopCount 2755 << "\n"); 2756 return; 2757 default: 2758 Malformed = true; 2759 } 2760 } 2761 } 2762 2763 uint64_t MachORebaseEntry::readULEB128() { 2764 unsigned Count; 2765 uint64_t Result = decodeULEB128(Ptr, &Count); 2766 Ptr += Count; 2767 if (Ptr > Opcodes.end()) { 2768 Ptr = Opcodes.end(); 2769 Malformed = true; 2770 } 2771 return Result; 2772 } 2773 2774 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2775 2776 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2777 2778 StringRef MachORebaseEntry::typeName() const { 2779 switch (RebaseType) { 2780 case MachO::REBASE_TYPE_POINTER: 2781 return "pointer"; 2782 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2783 return "text abs32"; 2784 case MachO::REBASE_TYPE_TEXT_PCREL32: 2785 return "text rel32"; 2786 } 2787 return "unknown"; 2788 } 2789 2790 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2791 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2792 return (Ptr == Other.Ptr) && 2793 (RemainingLoopCount == Other.RemainingLoopCount) && 2794 (Done == Other.Done); 2795 } 2796 2797 iterator_range<rebase_iterator> 2798 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2799 MachORebaseEntry Start(Opcodes, is64); 2800 Start.moveToFirst(); 2801 2802 MachORebaseEntry Finish(Opcodes, is64); 2803 Finish.moveToEnd(); 2804 2805 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2806 } 2807 2808 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2809 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2810 } 2811 2812 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2813 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2814 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2815 BindType(0), PointerSize(is64Bit ? 8 : 4), 2816 TableKind(BK), Malformed(false), Done(false) {} 2817 2818 void MachOBindEntry::moveToFirst() { 2819 Ptr = Opcodes.begin(); 2820 moveNext(); 2821 } 2822 2823 void MachOBindEntry::moveToEnd() { 2824 Ptr = Opcodes.end(); 2825 RemainingLoopCount = 0; 2826 Done = true; 2827 } 2828 2829 void MachOBindEntry::moveNext() { 2830 // If in the middle of some loop, move to next binding in loop. 2831 SegmentOffset += AdvanceAmount; 2832 if (RemainingLoopCount) { 2833 --RemainingLoopCount; 2834 return; 2835 } 2836 if (Ptr == Opcodes.end()) { 2837 Done = true; 2838 return; 2839 } 2840 bool More = true; 2841 while (More && !Malformed) { 2842 // Parse next opcode and set up next loop. 2843 uint8_t Byte = *Ptr++; 2844 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2845 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2846 int8_t SignExtended; 2847 const uint8_t *SymStart; 2848 switch (Opcode) { 2849 case MachO::BIND_OPCODE_DONE: 2850 if (TableKind == Kind::Lazy) { 2851 // Lazying bindings have a DONE opcode between entries. Need to ignore 2852 // it to advance to next entry. But need not if this is last entry. 2853 bool NotLastEntry = false; 2854 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2855 if (*P) { 2856 NotLastEntry = true; 2857 } 2858 } 2859 if (NotLastEntry) 2860 break; 2861 } 2862 More = false; 2863 Done = true; 2864 moveToEnd(); 2865 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2866 break; 2867 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2868 Ordinal = ImmValue; 2869 DEBUG_WITH_TYPE( 2870 "mach-o-bind", 2871 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2872 << "Ordinal=" << Ordinal << "\n"); 2873 break; 2874 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2875 Ordinal = readULEB128(); 2876 DEBUG_WITH_TYPE( 2877 "mach-o-bind", 2878 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2879 << "Ordinal=" << Ordinal << "\n"); 2880 break; 2881 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2882 if (ImmValue) { 2883 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2884 Ordinal = SignExtended; 2885 } else 2886 Ordinal = 0; 2887 DEBUG_WITH_TYPE( 2888 "mach-o-bind", 2889 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2890 << "Ordinal=" << Ordinal << "\n"); 2891 break; 2892 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2893 Flags = ImmValue; 2894 SymStart = Ptr; 2895 while (*Ptr) { 2896 ++Ptr; 2897 } 2898 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2899 Ptr-SymStart); 2900 ++Ptr; 2901 DEBUG_WITH_TYPE( 2902 "mach-o-bind", 2903 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2904 << "SymbolName=" << SymbolName << "\n"); 2905 if (TableKind == Kind::Weak) { 2906 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2907 return; 2908 } 2909 break; 2910 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2911 BindType = ImmValue; 2912 DEBUG_WITH_TYPE( 2913 "mach-o-bind", 2914 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2915 << "BindType=" << (int)BindType << "\n"); 2916 break; 2917 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2918 Addend = readSLEB128(); 2919 if (TableKind == Kind::Lazy) 2920 Malformed = true; 2921 DEBUG_WITH_TYPE( 2922 "mach-o-bind", 2923 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2924 << "Addend=" << Addend << "\n"); 2925 break; 2926 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2927 SegmentIndex = ImmValue; 2928 SegmentOffset = readULEB128(); 2929 DEBUG_WITH_TYPE( 2930 "mach-o-bind", 2931 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2932 << "SegmentIndex=" << SegmentIndex << ", " 2933 << format("SegmentOffset=0x%06X", SegmentOffset) 2934 << "\n"); 2935 break; 2936 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2937 SegmentOffset += readULEB128(); 2938 DEBUG_WITH_TYPE("mach-o-bind", 2939 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2940 << format("SegmentOffset=0x%06X", 2941 SegmentOffset) << "\n"); 2942 break; 2943 case MachO::BIND_OPCODE_DO_BIND: 2944 AdvanceAmount = PointerSize; 2945 RemainingLoopCount = 0; 2946 DEBUG_WITH_TYPE("mach-o-bind", 2947 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2948 << format("SegmentOffset=0x%06X", 2949 SegmentOffset) << "\n"); 2950 return; 2951 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2952 AdvanceAmount = readULEB128() + PointerSize; 2953 RemainingLoopCount = 0; 2954 if (TableKind == Kind::Lazy) 2955 Malformed = true; 2956 DEBUG_WITH_TYPE( 2957 "mach-o-bind", 2958 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2959 << format("SegmentOffset=0x%06X", SegmentOffset) 2960 << ", AdvanceAmount=" << AdvanceAmount 2961 << ", RemainingLoopCount=" << RemainingLoopCount 2962 << "\n"); 2963 return; 2964 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2965 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2966 RemainingLoopCount = 0; 2967 if (TableKind == Kind::Lazy) 2968 Malformed = true; 2969 DEBUG_WITH_TYPE("mach-o-bind", 2970 llvm::dbgs() 2971 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2972 << format("SegmentOffset=0x%06X", 2973 SegmentOffset) << "\n"); 2974 return; 2975 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2976 RemainingLoopCount = readULEB128() - 1; 2977 AdvanceAmount = readULEB128() + PointerSize; 2978 if (TableKind == Kind::Lazy) 2979 Malformed = true; 2980 DEBUG_WITH_TYPE( 2981 "mach-o-bind", 2982 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2983 << format("SegmentOffset=0x%06X", SegmentOffset) 2984 << ", AdvanceAmount=" << AdvanceAmount 2985 << ", RemainingLoopCount=" << RemainingLoopCount 2986 << "\n"); 2987 return; 2988 default: 2989 Malformed = true; 2990 } 2991 } 2992 } 2993 2994 uint64_t MachOBindEntry::readULEB128() { 2995 unsigned Count; 2996 uint64_t Result = decodeULEB128(Ptr, &Count); 2997 Ptr += Count; 2998 if (Ptr > Opcodes.end()) { 2999 Ptr = Opcodes.end(); 3000 Malformed = true; 3001 } 3002 return Result; 3003 } 3004 3005 int64_t MachOBindEntry::readSLEB128() { 3006 unsigned Count; 3007 int64_t Result = decodeSLEB128(Ptr, &Count); 3008 Ptr += Count; 3009 if (Ptr > Opcodes.end()) { 3010 Ptr = Opcodes.end(); 3011 Malformed = true; 3012 } 3013 return Result; 3014 } 3015 3016 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 3017 3018 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 3019 3020 StringRef MachOBindEntry::typeName() const { 3021 switch (BindType) { 3022 case MachO::BIND_TYPE_POINTER: 3023 return "pointer"; 3024 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 3025 return "text abs32"; 3026 case MachO::BIND_TYPE_TEXT_PCREL32: 3027 return "text rel32"; 3028 } 3029 return "unknown"; 3030 } 3031 3032 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 3033 3034 int64_t MachOBindEntry::addend() const { return Addend; } 3035 3036 uint32_t MachOBindEntry::flags() const { return Flags; } 3037 3038 int MachOBindEntry::ordinal() const { return Ordinal; } 3039 3040 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 3041 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 3042 return (Ptr == Other.Ptr) && 3043 (RemainingLoopCount == Other.RemainingLoopCount) && 3044 (Done == Other.Done); 3045 } 3046 3047 iterator_range<bind_iterator> 3048 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 3049 MachOBindEntry::Kind BKind) { 3050 MachOBindEntry Start(Opcodes, is64, BKind); 3051 Start.moveToFirst(); 3052 3053 MachOBindEntry Finish(Opcodes, is64, BKind); 3054 Finish.moveToEnd(); 3055 3056 return make_range(bind_iterator(Start), bind_iterator(Finish)); 3057 } 3058 3059 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 3060 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 3061 MachOBindEntry::Kind::Regular); 3062 } 3063 3064 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 3065 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 3066 MachOBindEntry::Kind::Lazy); 3067 } 3068 3069 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 3070 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 3071 MachOBindEntry::Kind::Weak); 3072 } 3073 3074 MachOObjectFile::load_command_iterator 3075 MachOObjectFile::begin_load_commands() const { 3076 return LoadCommands.begin(); 3077 } 3078 3079 MachOObjectFile::load_command_iterator 3080 MachOObjectFile::end_load_commands() const { 3081 return LoadCommands.end(); 3082 } 3083 3084 iterator_range<MachOObjectFile::load_command_iterator> 3085 MachOObjectFile::load_commands() const { 3086 return make_range(begin_load_commands(), end_load_commands()); 3087 } 3088 3089 StringRef 3090 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 3091 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 3092 return parseSegmentOrSectionName(Raw.data()); 3093 } 3094 3095 ArrayRef<char> 3096 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 3097 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3098 const section_base *Base = 3099 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3100 return makeArrayRef(Base->sectname); 3101 } 3102 3103 ArrayRef<char> 3104 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 3105 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3106 const section_base *Base = 3107 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3108 return makeArrayRef(Base->segname); 3109 } 3110 3111 bool 3112 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 3113 const { 3114 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64) 3115 return false; 3116 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 3117 } 3118 3119 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 3120 const MachO::any_relocation_info &RE) const { 3121 if (isLittleEndian()) 3122 return RE.r_word1 & 0xffffff; 3123 return RE.r_word1 >> 8; 3124 } 3125 3126 bool MachOObjectFile::getPlainRelocationExternal( 3127 const MachO::any_relocation_info &RE) const { 3128 if (isLittleEndian()) 3129 return (RE.r_word1 >> 27) & 1; 3130 return (RE.r_word1 >> 4) & 1; 3131 } 3132 3133 bool MachOObjectFile::getScatteredRelocationScattered( 3134 const MachO::any_relocation_info &RE) const { 3135 return RE.r_word0 >> 31; 3136 } 3137 3138 uint32_t MachOObjectFile::getScatteredRelocationValue( 3139 const MachO::any_relocation_info &RE) const { 3140 return RE.r_word1; 3141 } 3142 3143 uint32_t MachOObjectFile::getScatteredRelocationType( 3144 const MachO::any_relocation_info &RE) const { 3145 return (RE.r_word0 >> 24) & 0xf; 3146 } 3147 3148 unsigned MachOObjectFile::getAnyRelocationAddress( 3149 const MachO::any_relocation_info &RE) const { 3150 if (isRelocationScattered(RE)) 3151 return getScatteredRelocationAddress(RE); 3152 return getPlainRelocationAddress(RE); 3153 } 3154 3155 unsigned MachOObjectFile::getAnyRelocationPCRel( 3156 const MachO::any_relocation_info &RE) const { 3157 if (isRelocationScattered(RE)) 3158 return getScatteredRelocationPCRel(RE); 3159 return getPlainRelocationPCRel(*this, RE); 3160 } 3161 3162 unsigned MachOObjectFile::getAnyRelocationLength( 3163 const MachO::any_relocation_info &RE) const { 3164 if (isRelocationScattered(RE)) 3165 return getScatteredRelocationLength(RE); 3166 return getPlainRelocationLength(*this, RE); 3167 } 3168 3169 unsigned 3170 MachOObjectFile::getAnyRelocationType( 3171 const MachO::any_relocation_info &RE) const { 3172 if (isRelocationScattered(RE)) 3173 return getScatteredRelocationType(RE); 3174 return getPlainRelocationType(*this, RE); 3175 } 3176 3177 SectionRef 3178 MachOObjectFile::getAnyRelocationSection( 3179 const MachO::any_relocation_info &RE) const { 3180 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 3181 return *section_end(); 3182 unsigned SecNum = getPlainRelocationSymbolNum(RE); 3183 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 3184 return *section_end(); 3185 DataRefImpl DRI; 3186 DRI.d.a = SecNum - 1; 3187 return SectionRef(DRI, this); 3188 } 3189 3190 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 3191 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3192 return getStruct<MachO::section>(*this, Sections[DRI.d.a]); 3193 } 3194 3195 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 3196 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3197 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]); 3198 } 3199 3200 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 3201 unsigned Index) const { 3202 const char *Sec = getSectionPtr(*this, L, Index); 3203 return getStruct<MachO::section>(*this, Sec); 3204 } 3205 3206 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 3207 unsigned Index) const { 3208 const char *Sec = getSectionPtr(*this, L, Index); 3209 return getStruct<MachO::section_64>(*this, Sec); 3210 } 3211 3212 MachO::nlist 3213 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 3214 const char *P = reinterpret_cast<const char *>(DRI.p); 3215 return getStruct<MachO::nlist>(*this, P); 3216 } 3217 3218 MachO::nlist_64 3219 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 3220 const char *P = reinterpret_cast<const char *>(DRI.p); 3221 return getStruct<MachO::nlist_64>(*this, P); 3222 } 3223 3224 MachO::linkedit_data_command 3225 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 3226 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr); 3227 } 3228 3229 MachO::segment_command 3230 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 3231 return getStruct<MachO::segment_command>(*this, L.Ptr); 3232 } 3233 3234 MachO::segment_command_64 3235 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 3236 return getStruct<MachO::segment_command_64>(*this, L.Ptr); 3237 } 3238 3239 MachO::linker_option_command 3240 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 3241 return getStruct<MachO::linker_option_command>(*this, L.Ptr); 3242 } 3243 3244 MachO::version_min_command 3245 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 3246 return getStruct<MachO::version_min_command>(*this, L.Ptr); 3247 } 3248 3249 MachO::dylib_command 3250 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 3251 return getStruct<MachO::dylib_command>(*this, L.Ptr); 3252 } 3253 3254 MachO::dyld_info_command 3255 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 3256 return getStruct<MachO::dyld_info_command>(*this, L.Ptr); 3257 } 3258 3259 MachO::dylinker_command 3260 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 3261 return getStruct<MachO::dylinker_command>(*this, L.Ptr); 3262 } 3263 3264 MachO::uuid_command 3265 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 3266 return getStruct<MachO::uuid_command>(*this, L.Ptr); 3267 } 3268 3269 MachO::rpath_command 3270 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 3271 return getStruct<MachO::rpath_command>(*this, L.Ptr); 3272 } 3273 3274 MachO::source_version_command 3275 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 3276 return getStruct<MachO::source_version_command>(*this, L.Ptr); 3277 } 3278 3279 MachO::entry_point_command 3280 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 3281 return getStruct<MachO::entry_point_command>(*this, L.Ptr); 3282 } 3283 3284 MachO::encryption_info_command 3285 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 3286 return getStruct<MachO::encryption_info_command>(*this, L.Ptr); 3287 } 3288 3289 MachO::encryption_info_command_64 3290 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 3291 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr); 3292 } 3293 3294 MachO::sub_framework_command 3295 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 3296 return getStruct<MachO::sub_framework_command>(*this, L.Ptr); 3297 } 3298 3299 MachO::sub_umbrella_command 3300 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 3301 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr); 3302 } 3303 3304 MachO::sub_library_command 3305 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 3306 return getStruct<MachO::sub_library_command>(*this, L.Ptr); 3307 } 3308 3309 MachO::sub_client_command 3310 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 3311 return getStruct<MachO::sub_client_command>(*this, L.Ptr); 3312 } 3313 3314 MachO::routines_command 3315 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 3316 return getStruct<MachO::routines_command>(*this, L.Ptr); 3317 } 3318 3319 MachO::routines_command_64 3320 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 3321 return getStruct<MachO::routines_command_64>(*this, L.Ptr); 3322 } 3323 3324 MachO::thread_command 3325 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 3326 return getStruct<MachO::thread_command>(*this, L.Ptr); 3327 } 3328 3329 MachO::any_relocation_info 3330 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 3331 DataRefImpl Sec; 3332 Sec.d.a = Rel.d.a; 3333 uint32_t Offset; 3334 if (is64Bit()) { 3335 MachO::section_64 Sect = getSection64(Sec); 3336 Offset = Sect.reloff; 3337 } else { 3338 MachO::section Sect = getSection(Sec); 3339 Offset = Sect.reloff; 3340 } 3341 3342 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 3343 getPtr(*this, Offset)) + Rel.d.b; 3344 return getStruct<MachO::any_relocation_info>( 3345 *this, reinterpret_cast<const char *>(P)); 3346 } 3347 3348 MachO::data_in_code_entry 3349 MachOObjectFile::getDice(DataRefImpl Rel) const { 3350 const char *P = reinterpret_cast<const char *>(Rel.p); 3351 return getStruct<MachO::data_in_code_entry>(*this, P); 3352 } 3353 3354 const MachO::mach_header &MachOObjectFile::getHeader() const { 3355 return Header; 3356 } 3357 3358 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 3359 assert(is64Bit()); 3360 return Header64; 3361 } 3362 3363 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 3364 const MachO::dysymtab_command &DLC, 3365 unsigned Index) const { 3366 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 3367 return getStruct<uint32_t>(*this, getPtr(*this, Offset)); 3368 } 3369 3370 MachO::data_in_code_entry 3371 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 3372 unsigned Index) const { 3373 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 3374 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset)); 3375 } 3376 3377 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 3378 if (SymtabLoadCmd) 3379 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd); 3380 3381 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 3382 MachO::symtab_command Cmd; 3383 Cmd.cmd = MachO::LC_SYMTAB; 3384 Cmd.cmdsize = sizeof(MachO::symtab_command); 3385 Cmd.symoff = 0; 3386 Cmd.nsyms = 0; 3387 Cmd.stroff = 0; 3388 Cmd.strsize = 0; 3389 return Cmd; 3390 } 3391 3392 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 3393 if (DysymtabLoadCmd) 3394 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd); 3395 3396 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 3397 MachO::dysymtab_command Cmd; 3398 Cmd.cmd = MachO::LC_DYSYMTAB; 3399 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 3400 Cmd.ilocalsym = 0; 3401 Cmd.nlocalsym = 0; 3402 Cmd.iextdefsym = 0; 3403 Cmd.nextdefsym = 0; 3404 Cmd.iundefsym = 0; 3405 Cmd.nundefsym = 0; 3406 Cmd.tocoff = 0; 3407 Cmd.ntoc = 0; 3408 Cmd.modtaboff = 0; 3409 Cmd.nmodtab = 0; 3410 Cmd.extrefsymoff = 0; 3411 Cmd.nextrefsyms = 0; 3412 Cmd.indirectsymoff = 0; 3413 Cmd.nindirectsyms = 0; 3414 Cmd.extreloff = 0; 3415 Cmd.nextrel = 0; 3416 Cmd.locreloff = 0; 3417 Cmd.nlocrel = 0; 3418 return Cmd; 3419 } 3420 3421 MachO::linkedit_data_command 3422 MachOObjectFile::getDataInCodeLoadCommand() const { 3423 if (DataInCodeLoadCmd) 3424 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd); 3425 3426 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 3427 MachO::linkedit_data_command Cmd; 3428 Cmd.cmd = MachO::LC_DATA_IN_CODE; 3429 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3430 Cmd.dataoff = 0; 3431 Cmd.datasize = 0; 3432 return Cmd; 3433 } 3434 3435 MachO::linkedit_data_command 3436 MachOObjectFile::getLinkOptHintsLoadCommand() const { 3437 if (LinkOptHintsLoadCmd) 3438 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd); 3439 3440 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 3441 // fields. 3442 MachO::linkedit_data_command Cmd; 3443 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 3444 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3445 Cmd.dataoff = 0; 3446 Cmd.datasize = 0; 3447 return Cmd; 3448 } 3449 3450 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 3451 if (!DyldInfoLoadCmd) 3452 return None; 3453 3454 MachO::dyld_info_command DyldInfo = 3455 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 3456 const uint8_t *Ptr = 3457 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off)); 3458 return makeArrayRef(Ptr, DyldInfo.rebase_size); 3459 } 3460 3461 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 3462 if (!DyldInfoLoadCmd) 3463 return None; 3464 3465 MachO::dyld_info_command DyldInfo = 3466 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 3467 const uint8_t *Ptr = 3468 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off)); 3469 return makeArrayRef(Ptr, DyldInfo.bind_size); 3470 } 3471 3472 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 3473 if (!DyldInfoLoadCmd) 3474 return None; 3475 3476 MachO::dyld_info_command DyldInfo = 3477 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 3478 const uint8_t *Ptr = 3479 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off)); 3480 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 3481 } 3482 3483 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 3484 if (!DyldInfoLoadCmd) 3485 return None; 3486 3487 MachO::dyld_info_command DyldInfo = 3488 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 3489 const uint8_t *Ptr = 3490 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off)); 3491 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 3492 } 3493 3494 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 3495 if (!DyldInfoLoadCmd) 3496 return None; 3497 3498 MachO::dyld_info_command DyldInfo = 3499 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 3500 const uint8_t *Ptr = 3501 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off)); 3502 return makeArrayRef(Ptr, DyldInfo.export_size); 3503 } 3504 3505 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 3506 if (!UuidLoadCmd) 3507 return None; 3508 // Returning a pointer is fine as uuid doesn't need endian swapping. 3509 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 3510 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 3511 } 3512 3513 StringRef MachOObjectFile::getStringTableData() const { 3514 MachO::symtab_command S = getSymtabLoadCommand(); 3515 return getData().substr(S.stroff, S.strsize); 3516 } 3517 3518 bool MachOObjectFile::is64Bit() const { 3519 return getType() == getMachOType(false, true) || 3520 getType() == getMachOType(true, true); 3521 } 3522 3523 void MachOObjectFile::ReadULEB128s(uint64_t Index, 3524 SmallVectorImpl<uint64_t> &Out) const { 3525 DataExtractor extractor(ObjectFile::getData(), true, 0); 3526 3527 uint32_t offset = Index; 3528 uint64_t data = 0; 3529 while (uint64_t delta = extractor.getULEB128(&offset)) { 3530 data += delta; 3531 Out.push_back(data); 3532 } 3533 } 3534 3535 bool MachOObjectFile::isRelocatableObject() const { 3536 return getHeader().filetype == MachO::MH_OBJECT; 3537 } 3538 3539 Expected<std::unique_ptr<MachOObjectFile>> 3540 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, 3541 uint32_t UniversalCputype, 3542 uint32_t UniversalIndex) { 3543 StringRef Magic = Buffer.getBuffer().slice(0, 4); 3544 if (Magic == "\xFE\xED\xFA\xCE") 3545 return MachOObjectFile::create(Buffer, false, false, 3546 UniversalCputype, UniversalIndex); 3547 if (Magic == "\xCE\xFA\xED\xFE") 3548 return MachOObjectFile::create(Buffer, true, false, 3549 UniversalCputype, UniversalIndex); 3550 if (Magic == "\xFE\xED\xFA\xCF") 3551 return MachOObjectFile::create(Buffer, false, true, 3552 UniversalCputype, UniversalIndex); 3553 if (Magic == "\xCF\xFA\xED\xFE") 3554 return MachOObjectFile::create(Buffer, true, true, 3555 UniversalCputype, UniversalIndex); 3556 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 3557 object_error::invalid_file_type); 3558 } 3559