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