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