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_POWERPC) { 974 if (flavor == MachO::PPC_THREAD_STATE) { 975 if (count != MachO::PPC_THREAD_STATE_COUNT) 976 return malformedError("load command " + Twine(LoadCommandIndex) + 977 " count not PPC_THREAD_STATE_COUNT for " 978 "flavor number " + Twine(nflavor) + " which is " 979 "a PPC_THREAD_STATE flavor in " + CmdName + 980 " command"); 981 if (state + sizeof(MachO::ppc_thread_state32_t) > end) 982 return malformedError("load command " + Twine(LoadCommandIndex) + 983 " PPC_THREAD_STATE extends past end of " 984 "command in " + CmdName + " command"); 985 state += sizeof(MachO::ppc_thread_state32_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 { 993 return malformedError("unknown cputype (" + Twine(cputype) + ") load " 994 "command " + Twine(LoadCommandIndex) + " for " + 995 CmdName + " command can't be checked"); 996 } 997 nflavor++; 998 } 999 return Error::success(); 1000 } 1001 1002 static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, 1003 const MachOObjectFile::LoadCommandInfo 1004 &Load, 1005 uint32_t LoadCommandIndex, 1006 const char **LoadCmd, 1007 std::list<MachOElement> &Elements) { 1008 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command)) 1009 return malformedError("load command " + Twine(LoadCommandIndex) + 1010 " LC_TWOLEVEL_HINTS has incorrect cmdsize"); 1011 if (*LoadCmd != nullptr) 1012 return malformedError("more than one LC_TWOLEVEL_HINTS command"); 1013 MachO::twolevel_hints_command Hints = 1014 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr); 1015 uint64_t FileSize = Obj->getData().size(); 1016 if (Hints.offset > FileSize) 1017 return malformedError("offset field of LC_TWOLEVEL_HINTS command " + 1018 Twine(LoadCommandIndex) + " extends past the end of " 1019 "the file"); 1020 uint64_t BigSize = Hints.nhints; 1021 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint); 1022 BigSize += Hints.offset; 1023 if (BigSize > FileSize) 1024 return malformedError("offset field plus nhints times sizeof(struct " 1025 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " + 1026 Twine(LoadCommandIndex) + " extends past the end of " 1027 "the file"); 1028 if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints * 1029 sizeof(MachO::twolevel_hint), 1030 "two level hints")) 1031 return Err; 1032 *LoadCmd = Load.Ptr; 1033 return Error::success(); 1034 } 1035 1036 // Returns true if the libObject code does not support the load command and its 1037 // contents. The cmd value it is treated as an unknown load command but with 1038 // an error message that says the cmd value is obsolete. 1039 static bool isLoadCommandObsolete(uint32_t cmd) { 1040 if (cmd == MachO::LC_SYMSEG || 1041 cmd == MachO::LC_LOADFVMLIB || 1042 cmd == MachO::LC_IDFVMLIB || 1043 cmd == MachO::LC_IDENT || 1044 cmd == MachO::LC_FVMFILE || 1045 cmd == MachO::LC_PREPAGE || 1046 cmd == MachO::LC_PREBOUND_DYLIB || 1047 cmd == MachO::LC_TWOLEVEL_HINTS || 1048 cmd == MachO::LC_PREBIND_CKSUM) 1049 return true; 1050 return false; 1051 } 1052 1053 Expected<std::unique_ptr<MachOObjectFile>> 1054 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, 1055 bool Is64Bits, uint32_t UniversalCputype, 1056 uint32_t UniversalIndex) { 1057 Error Err; 1058 std::unique_ptr<MachOObjectFile> Obj( 1059 new MachOObjectFile(std::move(Object), IsLittleEndian, 1060 Is64Bits, Err, UniversalCputype, 1061 UniversalIndex)); 1062 if (Err) 1063 return std::move(Err); 1064 return std::move(Obj); 1065 } 1066 1067 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 1068 bool Is64bits, Error &Err, 1069 uint32_t UniversalCputype, 1070 uint32_t UniversalIndex) 1071 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 1072 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 1073 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 1074 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 1075 HasPageZeroSegment(false) { 1076 ErrorAsOutParameter ErrAsOutParam(&Err); 1077 uint64_t SizeOfHeaders; 1078 uint32_t cputype; 1079 if (is64Bit()) { 1080 parseHeader(this, Header64, Err); 1081 SizeOfHeaders = sizeof(MachO::mach_header_64); 1082 cputype = Header64.cputype; 1083 } else { 1084 parseHeader(this, Header, Err); 1085 SizeOfHeaders = sizeof(MachO::mach_header); 1086 cputype = Header.cputype; 1087 } 1088 if (Err) 1089 return; 1090 SizeOfHeaders += getHeader().sizeofcmds; 1091 if (getData().data() + SizeOfHeaders > getData().end()) { 1092 Err = malformedError("load commands extend past the end of the file"); 1093 return; 1094 } 1095 if (UniversalCputype != 0 && cputype != UniversalCputype) { 1096 Err = malformedError("universal header architecture: " + 1097 Twine(UniversalIndex) + "'s cputype does not match " 1098 "object file's mach header"); 1099 return; 1100 } 1101 std::list<MachOElement> Elements; 1102 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"}); 1103 1104 uint32_t LoadCommandCount = getHeader().ncmds; 1105 LoadCommandInfo Load; 1106 if (LoadCommandCount != 0) { 1107 if (auto LoadOrErr = getFirstLoadCommandInfo(this)) 1108 Load = *LoadOrErr; 1109 else { 1110 Err = LoadOrErr.takeError(); 1111 return; 1112 } 1113 } 1114 1115 const char *DyldIdLoadCmd = nullptr; 1116 const char *FuncStartsLoadCmd = nullptr; 1117 const char *SplitInfoLoadCmd = nullptr; 1118 const char *CodeSignDrsLoadCmd = nullptr; 1119 const char *CodeSignLoadCmd = nullptr; 1120 const char *VersLoadCmd = nullptr; 1121 const char *SourceLoadCmd = nullptr; 1122 const char *EntryPointLoadCmd = nullptr; 1123 const char *EncryptLoadCmd = nullptr; 1124 const char *RoutinesLoadCmd = nullptr; 1125 const char *UnixThreadLoadCmd = nullptr; 1126 const char *TwoLevelHintsLoadCmd = nullptr; 1127 for (unsigned I = 0; I < LoadCommandCount; ++I) { 1128 if (is64Bit()) { 1129 if (Load.C.cmdsize % 8 != 0) { 1130 // We have a hack here to allow 64-bit Mach-O core files to have 1131 // LC_THREAD commands that are only a multiple of 4 and not 8 to be 1132 // allowed since the macOS kernel produces them. 1133 if (getHeader().filetype != MachO::MH_CORE || 1134 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { 1135 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 1136 "multiple of 8"); 1137 return; 1138 } 1139 } 1140 } else { 1141 if (Load.C.cmdsize % 4 != 0) { 1142 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 1143 "multiple of 4"); 1144 return; 1145 } 1146 } 1147 LoadCommands.push_back(Load); 1148 if (Load.C.cmd == MachO::LC_SYMTAB) { 1149 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd, Elements))) 1150 return; 1151 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 1152 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd, 1153 Elements))) 1154 return; 1155 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 1156 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd, 1157 "LC_DATA_IN_CODE", Elements, 1158 "data in code info"))) 1159 return; 1160 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 1161 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, 1162 "LC_LINKER_OPTIMIZATION_HINT", 1163 Elements, "linker optimization " 1164 "hints"))) 1165 return; 1166 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) { 1167 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd, 1168 "LC_FUNCTION_STARTS", Elements, 1169 "function starts data"))) 1170 return; 1171 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) { 1172 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd, 1173 "LC_SEGMENT_SPLIT_INFO", Elements, 1174 "split info data"))) 1175 return; 1176 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) { 1177 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd, 1178 "LC_DYLIB_CODE_SIGN_DRS", Elements, 1179 "code signing RDs data"))) 1180 return; 1181 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) { 1182 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd, 1183 "LC_CODE_SIGNATURE", Elements, 1184 "code signature data"))) 1185 return; 1186 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { 1187 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1188 "LC_DYLD_INFO", Elements))) 1189 return; 1190 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 1191 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1192 "LC_DYLD_INFO_ONLY", Elements))) 1193 return; 1194 } else if (Load.C.cmd == MachO::LC_UUID) { 1195 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { 1196 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " 1197 "cmdsize"); 1198 return; 1199 } 1200 if (UuidLoadCmd) { 1201 Err = malformedError("more than one LC_UUID command"); 1202 return; 1203 } 1204 UuidLoadCmd = Load.Ptr; 1205 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1206 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64, 1207 MachO::section_64>( 1208 this, Load, Sections, HasPageZeroSegment, I, 1209 "LC_SEGMENT_64", SizeOfHeaders, Elements))) 1210 return; 1211 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1212 if ((Err = parseSegmentLoadCommand<MachO::segment_command, 1213 MachO::section>( 1214 this, Load, Sections, HasPageZeroSegment, I, 1215 "LC_SEGMENT", SizeOfHeaders, Elements))) 1216 return; 1217 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) { 1218 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd))) 1219 return; 1220 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) { 1221 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB"))) 1222 return; 1223 Libraries.push_back(Load.Ptr); 1224 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) { 1225 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB"))) 1226 return; 1227 Libraries.push_back(Load.Ptr); 1228 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) { 1229 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB"))) 1230 return; 1231 Libraries.push_back(Load.Ptr); 1232 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) { 1233 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB"))) 1234 return; 1235 Libraries.push_back(Load.Ptr); 1236 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 1237 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB"))) 1238 return; 1239 Libraries.push_back(Load.Ptr); 1240 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) { 1241 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER"))) 1242 return; 1243 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) { 1244 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER"))) 1245 return; 1246 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 1247 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT"))) 1248 return; 1249 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) { 1250 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1251 "LC_VERSION_MIN_MACOSX"))) 1252 return; 1253 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { 1254 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1255 "LC_VERSION_MIN_IPHONEOS"))) 1256 return; 1257 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) { 1258 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1259 "LC_VERSION_MIN_TVOS"))) 1260 return; 1261 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 1262 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1263 "LC_VERSION_MIN_WATCHOS"))) 1264 return; 1265 } else if (Load.C.cmd == MachO::LC_RPATH) { 1266 if ((Err = checkRpathCommand(this, Load, I))) 1267 return; 1268 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) { 1269 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) { 1270 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) + 1271 " has incorrect cmdsize"); 1272 return; 1273 } 1274 if (SourceLoadCmd) { 1275 Err = malformedError("more than one LC_SOURCE_VERSION command"); 1276 return; 1277 } 1278 SourceLoadCmd = Load.Ptr; 1279 } else if (Load.C.cmd == MachO::LC_MAIN) { 1280 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) { 1281 Err = malformedError("LC_MAIN command " + Twine(I) + 1282 " has incorrect cmdsize"); 1283 return; 1284 } 1285 if (EntryPointLoadCmd) { 1286 Err = malformedError("more than one LC_MAIN command"); 1287 return; 1288 } 1289 EntryPointLoadCmd = Load.Ptr; 1290 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) { 1291 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) { 1292 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) + 1293 " has incorrect cmdsize"); 1294 return; 1295 } 1296 MachO::encryption_info_command E = 1297 getStruct<MachO::encryption_info_command>(this, Load.Ptr); 1298 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1299 &EncryptLoadCmd, "LC_ENCRYPTION_INFO"))) 1300 return; 1301 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 1302 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) { 1303 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) + 1304 " has incorrect cmdsize"); 1305 return; 1306 } 1307 MachO::encryption_info_command_64 E = 1308 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr); 1309 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1310 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64"))) 1311 return; 1312 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) { 1313 if ((Err = checkLinkerOptCommand(this, Load, I))) 1314 return; 1315 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) { 1316 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) { 1317 Err = malformedError("load command " + Twine(I) + 1318 " LC_SUB_FRAMEWORK cmdsize too small"); 1319 return; 1320 } 1321 MachO::sub_framework_command S = 1322 getStruct<MachO::sub_framework_command>(this, Load.Ptr); 1323 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK", 1324 sizeof(MachO::sub_framework_command), 1325 "sub_framework_command", S.umbrella, 1326 "umbrella"))) 1327 return; 1328 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) { 1329 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) { 1330 Err = malformedError("load command " + Twine(I) + 1331 " LC_SUB_UMBRELLA cmdsize too small"); 1332 return; 1333 } 1334 MachO::sub_umbrella_command S = 1335 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr); 1336 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA", 1337 sizeof(MachO::sub_umbrella_command), 1338 "sub_umbrella_command", S.sub_umbrella, 1339 "sub_umbrella"))) 1340 return; 1341 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) { 1342 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) { 1343 Err = malformedError("load command " + Twine(I) + 1344 " LC_SUB_LIBRARY cmdsize too small"); 1345 return; 1346 } 1347 MachO::sub_library_command S = 1348 getStruct<MachO::sub_library_command>(this, Load.Ptr); 1349 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY", 1350 sizeof(MachO::sub_library_command), 1351 "sub_library_command", S.sub_library, 1352 "sub_library"))) 1353 return; 1354 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) { 1355 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) { 1356 Err = malformedError("load command " + Twine(I) + 1357 " LC_SUB_CLIENT cmdsize too small"); 1358 return; 1359 } 1360 MachO::sub_client_command S = 1361 getStruct<MachO::sub_client_command>(this, Load.Ptr); 1362 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT", 1363 sizeof(MachO::sub_client_command), 1364 "sub_client_command", S.client, "client"))) 1365 return; 1366 } else if (Load.C.cmd == MachO::LC_ROUTINES) { 1367 if (Load.C.cmdsize != sizeof(MachO::routines_command)) { 1368 Err = malformedError("LC_ROUTINES command " + Twine(I) + 1369 " has incorrect cmdsize"); 1370 return; 1371 } 1372 if (RoutinesLoadCmd) { 1373 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 " 1374 "command"); 1375 return; 1376 } 1377 RoutinesLoadCmd = Load.Ptr; 1378 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) { 1379 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) { 1380 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) + 1381 " has incorrect cmdsize"); 1382 return; 1383 } 1384 if (RoutinesLoadCmd) { 1385 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES " 1386 "command"); 1387 return; 1388 } 1389 RoutinesLoadCmd = Load.Ptr; 1390 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) { 1391 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD"))) 1392 return; 1393 if (UnixThreadLoadCmd) { 1394 Err = malformedError("more than one LC_UNIXTHREAD command"); 1395 return; 1396 } 1397 UnixThreadLoadCmd = Load.Ptr; 1398 } else if (Load.C.cmd == MachO::LC_THREAD) { 1399 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD"))) 1400 return; 1401 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported. 1402 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) { 1403 if ((Err = checkTwoLevelHintsCommand(this, Load, I, 1404 &TwoLevelHintsLoadCmd, Elements))) 1405 return; 1406 } else if (isLoadCommandObsolete(Load.C.cmd)) { 1407 Err = malformedError("load command " + Twine(I) + " for cmd value of: " + 1408 Twine(Load.C.cmd) + " is obsolete and not " 1409 "supported"); 1410 return; 1411 } 1412 // TODO: generate a error for unknown load commands by default. But still 1413 // need work out an approach to allow or not allow unknown values like this 1414 // as an option for some uses like lldb. 1415 if (I < LoadCommandCount - 1) { 1416 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) 1417 Load = *LoadOrErr; 1418 else { 1419 Err = LoadOrErr.takeError(); 1420 return; 1421 } 1422 } 1423 } 1424 if (!SymtabLoadCmd) { 1425 if (DysymtabLoadCmd) { 1426 Err = malformedError("contains LC_DYSYMTAB load command without a " 1427 "LC_SYMTAB load command"); 1428 return; 1429 } 1430 } else if (DysymtabLoadCmd) { 1431 MachO::symtab_command Symtab = 1432 getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1433 MachO::dysymtab_command Dysymtab = 1434 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1435 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1436 Err = malformedError("ilocalsym in LC_DYSYMTAB load command " 1437 "extends past the end of the symbol table"); 1438 return; 1439 } 1440 uint64_t BigSize = Dysymtab.ilocalsym; 1441 BigSize += Dysymtab.nlocalsym; 1442 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { 1443 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " 1444 "command extends past the end of the symbol table"); 1445 return; 1446 } 1447 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1448 Err = malformedError("nextdefsym in LC_DYSYMTAB load command " 1449 "extends past the end of the symbol table"); 1450 return; 1451 } 1452 BigSize = Dysymtab.iextdefsym; 1453 BigSize += Dysymtab.nextdefsym; 1454 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { 1455 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " 1456 "load command extends past the end of the symbol " 1457 "table"); 1458 return; 1459 } 1460 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { 1461 Err = malformedError("nundefsym in LC_DYSYMTAB load command " 1462 "extends past the end of the symbol table"); 1463 return; 1464 } 1465 BigSize = Dysymtab.iundefsym; 1466 BigSize += Dysymtab.nundefsym; 1467 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { 1468 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " 1469 " command extends past the end of the symbol table"); 1470 return; 1471 } 1472 } 1473 if ((getHeader().filetype == MachO::MH_DYLIB || 1474 getHeader().filetype == MachO::MH_DYLIB_STUB) && 1475 DyldIdLoadCmd == nullptr) { 1476 Err = malformedError("no LC_ID_DYLIB load command in dynamic library " 1477 "filetype"); 1478 return; 1479 } 1480 assert(LoadCommands.size() == LoadCommandCount); 1481 1482 Err = Error::success(); 1483 } 1484 1485 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1486 unsigned SymbolTableEntrySize = is64Bit() ? 1487 sizeof(MachO::nlist_64) : 1488 sizeof(MachO::nlist); 1489 Symb.p += SymbolTableEntrySize; 1490 } 1491 1492 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 1493 StringRef StringTable = getStringTableData(); 1494 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1495 const char *Start = &StringTable.data()[Entry.n_strx]; 1496 if (Start < getData().begin() || Start >= getData().end()) { 1497 return malformedError("bad string index: " + Twine(Entry.n_strx) + 1498 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1499 } 1500 return StringRef(Start); 1501 } 1502 1503 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 1504 DataRefImpl DRI = Sec.getRawDataRefImpl(); 1505 uint32_t Flags = getSectionFlags(this, DRI); 1506 return Flags & MachO::SECTION_TYPE; 1507 } 1508 1509 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 1510 if (is64Bit()) { 1511 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 1512 return Entry.n_value; 1513 } 1514 MachO::nlist Entry = getSymbolTableEntry(Sym); 1515 return Entry.n_value; 1516 } 1517 1518 // getIndirectName() returns the name of the alias'ed symbol who's string table 1519 // index is in the n_value field. 1520 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 1521 StringRef &Res) const { 1522 StringRef StringTable = getStringTableData(); 1523 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1524 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 1525 return object_error::parse_failed; 1526 uint64_t NValue = getNValue(Symb); 1527 if (NValue >= StringTable.size()) 1528 return object_error::parse_failed; 1529 const char *Start = &StringTable.data()[NValue]; 1530 Res = StringRef(Start); 1531 return std::error_code(); 1532 } 1533 1534 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { 1535 return getNValue(Sym); 1536 } 1537 1538 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { 1539 return getSymbolValue(Sym); 1540 } 1541 1542 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 1543 uint32_t flags = getSymbolFlags(DRI); 1544 if (flags & SymbolRef::SF_Common) { 1545 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1546 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 1547 } 1548 return 0; 1549 } 1550 1551 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 1552 return getNValue(DRI); 1553 } 1554 1555 Expected<SymbolRef::Type> 1556 MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 1557 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1558 uint8_t n_type = Entry.n_type; 1559 1560 // If this is a STAB debugging symbol, we can do nothing more. 1561 if (n_type & MachO::N_STAB) 1562 return SymbolRef::ST_Debug; 1563 1564 switch (n_type & MachO::N_TYPE) { 1565 case MachO::N_UNDF : 1566 return SymbolRef::ST_Unknown; 1567 case MachO::N_SECT : 1568 Expected<section_iterator> SecOrError = getSymbolSection(Symb); 1569 if (!SecOrError) 1570 return SecOrError.takeError(); 1571 section_iterator Sec = *SecOrError; 1572 if (Sec->isData() || Sec->isBSS()) 1573 return SymbolRef::ST_Data; 1574 return SymbolRef::ST_Function; 1575 } 1576 return SymbolRef::ST_Other; 1577 } 1578 1579 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 1580 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1581 1582 uint8_t MachOType = Entry.n_type; 1583 uint16_t MachOFlags = Entry.n_desc; 1584 1585 uint32_t Result = SymbolRef::SF_None; 1586 1587 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 1588 Result |= SymbolRef::SF_Indirect; 1589 1590 if (MachOType & MachO::N_STAB) 1591 Result |= SymbolRef::SF_FormatSpecific; 1592 1593 if (MachOType & MachO::N_EXT) { 1594 Result |= SymbolRef::SF_Global; 1595 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 1596 if (getNValue(DRI)) 1597 Result |= SymbolRef::SF_Common; 1598 else 1599 Result |= SymbolRef::SF_Undefined; 1600 } 1601 1602 if (!(MachOType & MachO::N_PEXT)) 1603 Result |= SymbolRef::SF_Exported; 1604 } 1605 1606 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 1607 Result |= SymbolRef::SF_Weak; 1608 1609 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 1610 Result |= SymbolRef::SF_Thumb; 1611 1612 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 1613 Result |= SymbolRef::SF_Absolute; 1614 1615 return Result; 1616 } 1617 1618 Expected<section_iterator> 1619 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { 1620 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1621 uint8_t index = Entry.n_sect; 1622 1623 if (index == 0) 1624 return section_end(); 1625 DataRefImpl DRI; 1626 DRI.d.a = index - 1; 1627 if (DRI.d.a >= Sections.size()){ 1628 return malformedError("bad section index: " + Twine((int)index) + 1629 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1630 } 1631 return section_iterator(SectionRef(DRI, this)); 1632 } 1633 1634 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 1635 MachO::nlist_base Entry = 1636 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 1637 return Entry.n_sect - 1; 1638 } 1639 1640 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 1641 Sec.d.a++; 1642 } 1643 1644 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 1645 StringRef &Result) const { 1646 ArrayRef<char> Raw = getSectionRawName(Sec); 1647 Result = parseSegmentOrSectionName(Raw.data()); 1648 return std::error_code(); 1649 } 1650 1651 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 1652 if (is64Bit()) 1653 return getSection64(Sec).addr; 1654 return getSection(Sec).addr; 1655 } 1656 1657 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 1658 // In the case if a malformed Mach-O file where the section offset is past 1659 // the end of the file or some part of the section size is past the end of 1660 // the file return a size of zero or a size that covers the rest of the file 1661 // but does not extend past the end of the file. 1662 uint32_t SectOffset, SectType; 1663 uint64_t SectSize; 1664 1665 if (is64Bit()) { 1666 MachO::section_64 Sect = getSection64(Sec); 1667 SectOffset = Sect.offset; 1668 SectSize = Sect.size; 1669 SectType = Sect.flags & MachO::SECTION_TYPE; 1670 } else { 1671 MachO::section Sect = getSection(Sec); 1672 SectOffset = Sect.offset; 1673 SectSize = Sect.size; 1674 SectType = Sect.flags & MachO::SECTION_TYPE; 1675 } 1676 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL) 1677 return SectSize; 1678 uint64_t FileSize = getData().size(); 1679 if (SectOffset > FileSize) 1680 return 0; 1681 if (FileSize - SectOffset < SectSize) 1682 return FileSize - SectOffset; 1683 return SectSize; 1684 } 1685 1686 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 1687 StringRef &Res) const { 1688 uint32_t Offset; 1689 uint64_t Size; 1690 1691 if (is64Bit()) { 1692 MachO::section_64 Sect = getSection64(Sec); 1693 Offset = Sect.offset; 1694 Size = Sect.size; 1695 } else { 1696 MachO::section Sect = getSection(Sec); 1697 Offset = Sect.offset; 1698 Size = Sect.size; 1699 } 1700 1701 Res = this->getData().substr(Offset, Size); 1702 return std::error_code(); 1703 } 1704 1705 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1706 uint32_t Align; 1707 if (is64Bit()) { 1708 MachO::section_64 Sect = getSection64(Sec); 1709 Align = Sect.align; 1710 } else { 1711 MachO::section Sect = getSection(Sec); 1712 Align = Sect.align; 1713 } 1714 1715 return uint64_t(1) << Align; 1716 } 1717 1718 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1719 return false; 1720 } 1721 1722 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 1723 uint32_t Flags = getSectionFlags(this, Sec); 1724 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 1725 } 1726 1727 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 1728 uint32_t Flags = getSectionFlags(this, Sec); 1729 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1730 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1731 !(SectionType == MachO::S_ZEROFILL || 1732 SectionType == MachO::S_GB_ZEROFILL); 1733 } 1734 1735 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 1736 uint32_t Flags = getSectionFlags(this, Sec); 1737 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1738 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1739 (SectionType == MachO::S_ZEROFILL || 1740 SectionType == MachO::S_GB_ZEROFILL); 1741 } 1742 1743 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 1744 return Sec.getRawDataRefImpl().d.a; 1745 } 1746 1747 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 1748 // FIXME: Unimplemented. 1749 return false; 1750 } 1751 1752 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { 1753 StringRef SegmentName = getSectionFinalSegmentName(Sec); 1754 StringRef SectName; 1755 if (!getSectionName(Sec, SectName)) 1756 return (SegmentName == "__LLVM" && SectName == "__bitcode"); 1757 return false; 1758 } 1759 1760 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1761 DataRefImpl Ret; 1762 Ret.d.a = Sec.d.a; 1763 Ret.d.b = 0; 1764 return relocation_iterator(RelocationRef(Ret, this)); 1765 } 1766 1767 relocation_iterator 1768 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1769 uint32_t Num; 1770 if (is64Bit()) { 1771 MachO::section_64 Sect = getSection64(Sec); 1772 Num = Sect.nreloc; 1773 } else { 1774 MachO::section Sect = getSection(Sec); 1775 Num = Sect.nreloc; 1776 } 1777 1778 DataRefImpl Ret; 1779 Ret.d.a = Sec.d.a; 1780 Ret.d.b = Num; 1781 return relocation_iterator(RelocationRef(Ret, this)); 1782 } 1783 1784 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1785 ++Rel.d.b; 1786 } 1787 1788 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1789 assert(getHeader().filetype == MachO::MH_OBJECT && 1790 "Only implemented for MH_OBJECT"); 1791 MachO::any_relocation_info RE = getRelocation(Rel); 1792 return getAnyRelocationAddress(RE); 1793 } 1794 1795 symbol_iterator 1796 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1797 MachO::any_relocation_info RE = getRelocation(Rel); 1798 if (isRelocationScattered(RE)) 1799 return symbol_end(); 1800 1801 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1802 bool isExtern = getPlainRelocationExternal(RE); 1803 if (!isExtern) 1804 return symbol_end(); 1805 1806 MachO::symtab_command S = getSymtabLoadCommand(); 1807 unsigned SymbolTableEntrySize = is64Bit() ? 1808 sizeof(MachO::nlist_64) : 1809 sizeof(MachO::nlist); 1810 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1811 DataRefImpl Sym; 1812 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1813 return symbol_iterator(SymbolRef(Sym, this)); 1814 } 1815 1816 section_iterator 1817 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 1818 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 1819 } 1820 1821 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 1822 MachO::any_relocation_info RE = getRelocation(Rel); 1823 return getAnyRelocationType(RE); 1824 } 1825 1826 void MachOObjectFile::getRelocationTypeName( 1827 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1828 StringRef res; 1829 uint64_t RType = getRelocationType(Rel); 1830 1831 unsigned Arch = this->getArch(); 1832 1833 switch (Arch) { 1834 case Triple::x86: { 1835 static const char *const Table[] = { 1836 "GENERIC_RELOC_VANILLA", 1837 "GENERIC_RELOC_PAIR", 1838 "GENERIC_RELOC_SECTDIFF", 1839 "GENERIC_RELOC_PB_LA_PTR", 1840 "GENERIC_RELOC_LOCAL_SECTDIFF", 1841 "GENERIC_RELOC_TLV" }; 1842 1843 if (RType > 5) 1844 res = "Unknown"; 1845 else 1846 res = Table[RType]; 1847 break; 1848 } 1849 case Triple::x86_64: { 1850 static const char *const Table[] = { 1851 "X86_64_RELOC_UNSIGNED", 1852 "X86_64_RELOC_SIGNED", 1853 "X86_64_RELOC_BRANCH", 1854 "X86_64_RELOC_GOT_LOAD", 1855 "X86_64_RELOC_GOT", 1856 "X86_64_RELOC_SUBTRACTOR", 1857 "X86_64_RELOC_SIGNED_1", 1858 "X86_64_RELOC_SIGNED_2", 1859 "X86_64_RELOC_SIGNED_4", 1860 "X86_64_RELOC_TLV" }; 1861 1862 if (RType > 9) 1863 res = "Unknown"; 1864 else 1865 res = Table[RType]; 1866 break; 1867 } 1868 case Triple::arm: { 1869 static const char *const Table[] = { 1870 "ARM_RELOC_VANILLA", 1871 "ARM_RELOC_PAIR", 1872 "ARM_RELOC_SECTDIFF", 1873 "ARM_RELOC_LOCAL_SECTDIFF", 1874 "ARM_RELOC_PB_LA_PTR", 1875 "ARM_RELOC_BR24", 1876 "ARM_THUMB_RELOC_BR22", 1877 "ARM_THUMB_32BIT_BRANCH", 1878 "ARM_RELOC_HALF", 1879 "ARM_RELOC_HALF_SECTDIFF" }; 1880 1881 if (RType > 9) 1882 res = "Unknown"; 1883 else 1884 res = Table[RType]; 1885 break; 1886 } 1887 case Triple::aarch64: { 1888 static const char *const Table[] = { 1889 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 1890 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 1891 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 1892 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 1893 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 1894 "ARM64_RELOC_ADDEND" 1895 }; 1896 1897 if (RType >= array_lengthof(Table)) 1898 res = "Unknown"; 1899 else 1900 res = Table[RType]; 1901 break; 1902 } 1903 case Triple::ppc: { 1904 static const char *const Table[] = { 1905 "PPC_RELOC_VANILLA", 1906 "PPC_RELOC_PAIR", 1907 "PPC_RELOC_BR14", 1908 "PPC_RELOC_BR24", 1909 "PPC_RELOC_HI16", 1910 "PPC_RELOC_LO16", 1911 "PPC_RELOC_HA16", 1912 "PPC_RELOC_LO14", 1913 "PPC_RELOC_SECTDIFF", 1914 "PPC_RELOC_PB_LA_PTR", 1915 "PPC_RELOC_HI16_SECTDIFF", 1916 "PPC_RELOC_LO16_SECTDIFF", 1917 "PPC_RELOC_HA16_SECTDIFF", 1918 "PPC_RELOC_JBSR", 1919 "PPC_RELOC_LO14_SECTDIFF", 1920 "PPC_RELOC_LOCAL_SECTDIFF" }; 1921 1922 if (RType > 15) 1923 res = "Unknown"; 1924 else 1925 res = Table[RType]; 1926 break; 1927 } 1928 case Triple::UnknownArch: 1929 res = "Unknown"; 1930 break; 1931 } 1932 Result.append(res.begin(), res.end()); 1933 } 1934 1935 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 1936 MachO::any_relocation_info RE = getRelocation(Rel); 1937 return getAnyRelocationLength(RE); 1938 } 1939 1940 // 1941 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1942 // guess on what the short name is. Then name is returned as a substring of the 1943 // StringRef Name passed in. The name of the dynamic library is recognized as 1944 // a framework if it has one of the two following forms: 1945 // Foo.framework/Versions/A/Foo 1946 // Foo.framework/Foo 1947 // Where A and Foo can be any string. And may contain a trailing suffix 1948 // starting with an underbar. If the Name is recognized as a framework then 1949 // isFramework is set to true else it is set to false. If the Name has a 1950 // suffix then Suffix is set to the substring in Name that contains the suffix 1951 // else it is set to a NULL StringRef. 1952 // 1953 // The Name of the dynamic library is recognized as a library name if it has 1954 // one of the two following forms: 1955 // libFoo.A.dylib 1956 // libFoo.dylib 1957 // The library may have a suffix trailing the name Foo of the form: 1958 // libFoo_profile.A.dylib 1959 // libFoo_profile.dylib 1960 // 1961 // The Name of the dynamic library is also recognized as a library name if it 1962 // has the following form: 1963 // Foo.qtx 1964 // 1965 // If the Name of the dynamic library is none of the forms above then a NULL 1966 // StringRef is returned. 1967 // 1968 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1969 bool &isFramework, 1970 StringRef &Suffix) { 1971 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1972 size_t a, b, c, d, Idx; 1973 1974 isFramework = false; 1975 Suffix = StringRef(); 1976 1977 // Pull off the last component and make Foo point to it 1978 a = Name.rfind('/'); 1979 if (a == Name.npos || a == 0) 1980 goto guess_library; 1981 Foo = Name.slice(a+1, Name.npos); 1982 1983 // Look for a suffix starting with a '_' 1984 Idx = Foo.rfind('_'); 1985 if (Idx != Foo.npos && Foo.size() >= 2) { 1986 Suffix = Foo.slice(Idx, Foo.npos); 1987 Foo = Foo.slice(0, Idx); 1988 } 1989 1990 // First look for the form Foo.framework/Foo 1991 b = Name.rfind('/', a); 1992 if (b == Name.npos) 1993 Idx = 0; 1994 else 1995 Idx = b+1; 1996 F = Name.slice(Idx, Idx + Foo.size()); 1997 DotFramework = Name.slice(Idx + Foo.size(), 1998 Idx + Foo.size() + sizeof(".framework/")-1); 1999 if (F == Foo && DotFramework == ".framework/") { 2000 isFramework = true; 2001 return Foo; 2002 } 2003 2004 // Next look for the form Foo.framework/Versions/A/Foo 2005 if (b == Name.npos) 2006 goto guess_library; 2007 c = Name.rfind('/', b); 2008 if (c == Name.npos || c == 0) 2009 goto guess_library; 2010 V = Name.slice(c+1, Name.npos); 2011 if (!V.startswith("Versions/")) 2012 goto guess_library; 2013 d = Name.rfind('/', c); 2014 if (d == Name.npos) 2015 Idx = 0; 2016 else 2017 Idx = d+1; 2018 F = Name.slice(Idx, Idx + Foo.size()); 2019 DotFramework = Name.slice(Idx + Foo.size(), 2020 Idx + Foo.size() + sizeof(".framework/")-1); 2021 if (F == Foo && DotFramework == ".framework/") { 2022 isFramework = true; 2023 return Foo; 2024 } 2025 2026 guess_library: 2027 // pull off the suffix after the "." and make a point to it 2028 a = Name.rfind('.'); 2029 if (a == Name.npos || a == 0) 2030 return StringRef(); 2031 Dylib = Name.slice(a, Name.npos); 2032 if (Dylib != ".dylib") 2033 goto guess_qtx; 2034 2035 // First pull off the version letter for the form Foo.A.dylib if any. 2036 if (a >= 3) { 2037 Dot = Name.slice(a-2, a-1); 2038 if (Dot == ".") 2039 a = a - 2; 2040 } 2041 2042 b = Name.rfind('/', a); 2043 if (b == Name.npos) 2044 b = 0; 2045 else 2046 b = b+1; 2047 // ignore any suffix after an underbar like Foo_profile.A.dylib 2048 Idx = Name.find('_', b); 2049 if (Idx != Name.npos && Idx != b) { 2050 Lib = Name.slice(b, Idx); 2051 Suffix = Name.slice(Idx, a); 2052 } 2053 else 2054 Lib = Name.slice(b, a); 2055 // There are incorrect library names of the form: 2056 // libATS.A_profile.dylib so check for these. 2057 if (Lib.size() >= 3) { 2058 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 2059 if (Dot == ".") 2060 Lib = Lib.slice(0, Lib.size()-2); 2061 } 2062 return Lib; 2063 2064 guess_qtx: 2065 Qtx = Name.slice(a, Name.npos); 2066 if (Qtx != ".qtx") 2067 return StringRef(); 2068 b = Name.rfind('/', a); 2069 if (b == Name.npos) 2070 Lib = Name.slice(0, a); 2071 else 2072 Lib = Name.slice(b+1, a); 2073 // There are library names of the form: QT.A.qtx so check for these. 2074 if (Lib.size() >= 3) { 2075 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 2076 if (Dot == ".") 2077 Lib = Lib.slice(0, Lib.size()-2); 2078 } 2079 return Lib; 2080 } 2081 2082 // getLibraryShortNameByIndex() is used to get the short name of the library 2083 // for an undefined symbol in a linked Mach-O binary that was linked with the 2084 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 2085 // It is passed the index (0 - based) of the library as translated from 2086 // GET_LIBRARY_ORDINAL (1 - based). 2087 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 2088 StringRef &Res) const { 2089 if (Index >= Libraries.size()) 2090 return object_error::parse_failed; 2091 2092 // If the cache of LibrariesShortNames is not built up do that first for 2093 // all the Libraries. 2094 if (LibrariesShortNames.size() == 0) { 2095 for (unsigned i = 0; i < Libraries.size(); i++) { 2096 MachO::dylib_command D = 2097 getStruct<MachO::dylib_command>(this, Libraries[i]); 2098 if (D.dylib.name >= D.cmdsize) 2099 return object_error::parse_failed; 2100 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 2101 StringRef Name = StringRef(P); 2102 if (D.dylib.name+Name.size() >= D.cmdsize) 2103 return object_error::parse_failed; 2104 StringRef Suffix; 2105 bool isFramework; 2106 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 2107 if (shortName.empty()) 2108 LibrariesShortNames.push_back(Name); 2109 else 2110 LibrariesShortNames.push_back(shortName); 2111 } 2112 } 2113 2114 Res = LibrariesShortNames[Index]; 2115 return std::error_code(); 2116 } 2117 2118 section_iterator 2119 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 2120 DataRefImpl Sec; 2121 Sec.d.a = Rel->getRawDataRefImpl().d.a; 2122 return section_iterator(SectionRef(Sec, this)); 2123 } 2124 2125 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 2126 DataRefImpl DRI; 2127 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2128 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2129 return basic_symbol_iterator(SymbolRef(DRI, this)); 2130 2131 return getSymbolByIndex(0); 2132 } 2133 2134 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 2135 DataRefImpl DRI; 2136 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2137 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2138 return basic_symbol_iterator(SymbolRef(DRI, this)); 2139 2140 unsigned SymbolTableEntrySize = is64Bit() ? 2141 sizeof(MachO::nlist_64) : 2142 sizeof(MachO::nlist); 2143 unsigned Offset = Symtab.symoff + 2144 Symtab.nsyms * SymbolTableEntrySize; 2145 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2146 return basic_symbol_iterator(SymbolRef(DRI, this)); 2147 } 2148 2149 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 2150 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2151 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 2152 report_fatal_error("Requested symbol index is out of range."); 2153 unsigned SymbolTableEntrySize = 2154 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2155 DataRefImpl DRI; 2156 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 2157 DRI.p += Index * SymbolTableEntrySize; 2158 return basic_symbol_iterator(SymbolRef(DRI, this)); 2159 } 2160 2161 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 2162 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2163 if (!SymtabLoadCmd) 2164 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 2165 unsigned SymbolTableEntrySize = 2166 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2167 DataRefImpl DRIstart; 2168 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 2169 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 2170 return Index; 2171 } 2172 2173 section_iterator MachOObjectFile::section_begin() const { 2174 DataRefImpl DRI; 2175 return section_iterator(SectionRef(DRI, this)); 2176 } 2177 2178 section_iterator MachOObjectFile::section_end() const { 2179 DataRefImpl DRI; 2180 DRI.d.a = Sections.size(); 2181 return section_iterator(SectionRef(DRI, this)); 2182 } 2183 2184 uint8_t MachOObjectFile::getBytesInAddress() const { 2185 return is64Bit() ? 8 : 4; 2186 } 2187 2188 StringRef MachOObjectFile::getFileFormatName() const { 2189 unsigned CPUType = getCPUType(this); 2190 if (!is64Bit()) { 2191 switch (CPUType) { 2192 case llvm::MachO::CPU_TYPE_I386: 2193 return "Mach-O 32-bit i386"; 2194 case llvm::MachO::CPU_TYPE_ARM: 2195 return "Mach-O arm"; 2196 case llvm::MachO::CPU_TYPE_POWERPC: 2197 return "Mach-O 32-bit ppc"; 2198 default: 2199 return "Mach-O 32-bit unknown"; 2200 } 2201 } 2202 2203 switch (CPUType) { 2204 case llvm::MachO::CPU_TYPE_X86_64: 2205 return "Mach-O 64-bit x86-64"; 2206 case llvm::MachO::CPU_TYPE_ARM64: 2207 return "Mach-O arm64"; 2208 case llvm::MachO::CPU_TYPE_POWERPC64: 2209 return "Mach-O 64-bit ppc64"; 2210 default: 2211 return "Mach-O 64-bit unknown"; 2212 } 2213 } 2214 2215 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 2216 switch (CPUType) { 2217 case llvm::MachO::CPU_TYPE_I386: 2218 return Triple::x86; 2219 case llvm::MachO::CPU_TYPE_X86_64: 2220 return Triple::x86_64; 2221 case llvm::MachO::CPU_TYPE_ARM: 2222 return Triple::arm; 2223 case llvm::MachO::CPU_TYPE_ARM64: 2224 return Triple::aarch64; 2225 case llvm::MachO::CPU_TYPE_POWERPC: 2226 return Triple::ppc; 2227 case llvm::MachO::CPU_TYPE_POWERPC64: 2228 return Triple::ppc64; 2229 default: 2230 return Triple::UnknownArch; 2231 } 2232 } 2233 2234 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 2235 const char **McpuDefault) { 2236 if (McpuDefault) 2237 *McpuDefault = nullptr; 2238 2239 switch (CPUType) { 2240 case MachO::CPU_TYPE_I386: 2241 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2242 case MachO::CPU_SUBTYPE_I386_ALL: 2243 return Triple("i386-apple-darwin"); 2244 default: 2245 return Triple(); 2246 } 2247 case MachO::CPU_TYPE_X86_64: 2248 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2249 case MachO::CPU_SUBTYPE_X86_64_ALL: 2250 return Triple("x86_64-apple-darwin"); 2251 case MachO::CPU_SUBTYPE_X86_64_H: 2252 return Triple("x86_64h-apple-darwin"); 2253 default: 2254 return Triple(); 2255 } 2256 case MachO::CPU_TYPE_ARM: 2257 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2258 case MachO::CPU_SUBTYPE_ARM_V4T: 2259 return Triple("armv4t-apple-darwin"); 2260 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2261 return Triple("armv5e-apple-darwin"); 2262 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2263 return Triple("xscale-apple-darwin"); 2264 case MachO::CPU_SUBTYPE_ARM_V6: 2265 return Triple("armv6-apple-darwin"); 2266 case MachO::CPU_SUBTYPE_ARM_V6M: 2267 if (McpuDefault) 2268 *McpuDefault = "cortex-m0"; 2269 return Triple("armv6m-apple-darwin"); 2270 case MachO::CPU_SUBTYPE_ARM_V7: 2271 return Triple("armv7-apple-darwin"); 2272 case MachO::CPU_SUBTYPE_ARM_V7EM: 2273 if (McpuDefault) 2274 *McpuDefault = "cortex-m4"; 2275 return Triple("thumbv7em-apple-darwin"); 2276 case MachO::CPU_SUBTYPE_ARM_V7K: 2277 return Triple("armv7k-apple-darwin"); 2278 case MachO::CPU_SUBTYPE_ARM_V7M: 2279 if (McpuDefault) 2280 *McpuDefault = "cortex-m3"; 2281 return Triple("thumbv7m-apple-darwin"); 2282 case MachO::CPU_SUBTYPE_ARM_V7S: 2283 return Triple("armv7s-apple-darwin"); 2284 default: 2285 return Triple(); 2286 } 2287 case MachO::CPU_TYPE_ARM64: 2288 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2289 case MachO::CPU_SUBTYPE_ARM64_ALL: 2290 return Triple("arm64-apple-darwin"); 2291 default: 2292 return Triple(); 2293 } 2294 case MachO::CPU_TYPE_POWERPC: 2295 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2296 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2297 return Triple("ppc-apple-darwin"); 2298 default: 2299 return Triple(); 2300 } 2301 case MachO::CPU_TYPE_POWERPC64: 2302 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2303 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2304 return Triple("ppc64-apple-darwin"); 2305 default: 2306 return Triple(); 2307 } 2308 default: 2309 return Triple(); 2310 } 2311 } 2312 2313 Triple MachOObjectFile::getHostArch() { 2314 return Triple(sys::getDefaultTargetTriple()); 2315 } 2316 2317 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2318 return StringSwitch<bool>(ArchFlag) 2319 .Case("i386", true) 2320 .Case("x86_64", true) 2321 .Case("x86_64h", true) 2322 .Case("armv4t", true) 2323 .Case("arm", true) 2324 .Case("armv5e", true) 2325 .Case("armv6", true) 2326 .Case("armv6m", true) 2327 .Case("armv7", true) 2328 .Case("armv7em", true) 2329 .Case("armv7k", true) 2330 .Case("armv7m", true) 2331 .Case("armv7s", true) 2332 .Case("arm64", true) 2333 .Case("ppc", true) 2334 .Case("ppc64", true) 2335 .Default(false); 2336 } 2337 2338 unsigned MachOObjectFile::getArch() const { 2339 return getArch(getCPUType(this)); 2340 } 2341 2342 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2343 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2344 } 2345 2346 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2347 DataRefImpl DRI; 2348 DRI.d.a = Index; 2349 return section_rel_begin(DRI); 2350 } 2351 2352 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2353 DataRefImpl DRI; 2354 DRI.d.a = Index; 2355 return section_rel_end(DRI); 2356 } 2357 2358 dice_iterator MachOObjectFile::begin_dices() const { 2359 DataRefImpl DRI; 2360 if (!DataInCodeLoadCmd) 2361 return dice_iterator(DiceRef(DRI, this)); 2362 2363 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2364 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 2365 return dice_iterator(DiceRef(DRI, this)); 2366 } 2367 2368 dice_iterator MachOObjectFile::end_dices() const { 2369 DataRefImpl DRI; 2370 if (!DataInCodeLoadCmd) 2371 return dice_iterator(DiceRef(DRI, this)); 2372 2373 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2374 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2375 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2376 return dice_iterator(DiceRef(DRI, this)); 2377 } 2378 2379 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 2380 : Trie(T), Malformed(false), Done(false) {} 2381 2382 void ExportEntry::moveToFirst() { 2383 pushNode(0); 2384 pushDownUntilBottom(); 2385 } 2386 2387 void ExportEntry::moveToEnd() { 2388 Stack.clear(); 2389 Done = true; 2390 } 2391 2392 bool ExportEntry::operator==(const ExportEntry &Other) const { 2393 // Common case, one at end, other iterating from begin. 2394 if (Done || Other.Done) 2395 return (Done == Other.Done); 2396 // Not equal if different stack sizes. 2397 if (Stack.size() != Other.Stack.size()) 2398 return false; 2399 // Not equal if different cumulative strings. 2400 if (!CumulativeString.equals(Other.CumulativeString)) 2401 return false; 2402 // Equal if all nodes in both stacks match. 2403 for (unsigned i=0; i < Stack.size(); ++i) { 2404 if (Stack[i].Start != Other.Stack[i].Start) 2405 return false; 2406 } 2407 return true; 2408 } 2409 2410 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 2411 unsigned Count; 2412 uint64_t Result = decodeULEB128(Ptr, &Count); 2413 Ptr += Count; 2414 if (Ptr > Trie.end()) { 2415 Ptr = Trie.end(); 2416 Malformed = true; 2417 } 2418 return Result; 2419 } 2420 2421 StringRef ExportEntry::name() const { 2422 return CumulativeString; 2423 } 2424 2425 uint64_t ExportEntry::flags() const { 2426 return Stack.back().Flags; 2427 } 2428 2429 uint64_t ExportEntry::address() const { 2430 return Stack.back().Address; 2431 } 2432 2433 uint64_t ExportEntry::other() const { 2434 return Stack.back().Other; 2435 } 2436 2437 StringRef ExportEntry::otherName() const { 2438 const char* ImportName = Stack.back().ImportName; 2439 if (ImportName) 2440 return StringRef(ImportName); 2441 return StringRef(); 2442 } 2443 2444 uint32_t ExportEntry::nodeOffset() const { 2445 return Stack.back().Start - Trie.begin(); 2446 } 2447 2448 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2449 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 2450 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 2451 ParentStringLength(0), IsExportNode(false) {} 2452 2453 void ExportEntry::pushNode(uint64_t offset) { 2454 const uint8_t *Ptr = Trie.begin() + offset; 2455 NodeState State(Ptr); 2456 uint64_t ExportInfoSize = readULEB128(State.Current); 2457 State.IsExportNode = (ExportInfoSize != 0); 2458 const uint8_t* Children = State.Current + ExportInfoSize; 2459 if (State.IsExportNode) { 2460 State.Flags = readULEB128(State.Current); 2461 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2462 State.Address = 0; 2463 State.Other = readULEB128(State.Current); // dylib ordinal 2464 State.ImportName = reinterpret_cast<const char*>(State.Current); 2465 } else { 2466 State.Address = readULEB128(State.Current); 2467 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 2468 State.Other = readULEB128(State.Current); 2469 } 2470 } 2471 State.ChildCount = *Children; 2472 State.Current = Children + 1; 2473 State.NextChildIndex = 0; 2474 State.ParentStringLength = CumulativeString.size(); 2475 Stack.push_back(State); 2476 } 2477 2478 void ExportEntry::pushDownUntilBottom() { 2479 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2480 NodeState &Top = Stack.back(); 2481 CumulativeString.resize(Top.ParentStringLength); 2482 for (;*Top.Current != 0; Top.Current++) { 2483 char C = *Top.Current; 2484 CumulativeString.push_back(C); 2485 } 2486 Top.Current += 1; 2487 uint64_t childNodeIndex = readULEB128(Top.Current); 2488 Top.NextChildIndex += 1; 2489 pushNode(childNodeIndex); 2490 } 2491 if (!Stack.back().IsExportNode) { 2492 Malformed = true; 2493 moveToEnd(); 2494 } 2495 } 2496 2497 // We have a trie data structure and need a way to walk it that is compatible 2498 // with the C++ iterator model. The solution is a non-recursive depth first 2499 // traversal where the iterator contains a stack of parent nodes along with a 2500 // string that is the accumulation of all edge strings along the parent chain 2501 // to this point. 2502 // 2503 // There is one "export" node for each exported symbol. But because some 2504 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2505 // node may have child nodes too. 2506 // 2507 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2508 // child until hitting a node with no children (which is an export node or 2509 // else the trie is malformed). On the way down, each node is pushed on the 2510 // stack ivar. If there is no more ways down, it pops up one and tries to go 2511 // down a sibling path until a childless node is reached. 2512 void ExportEntry::moveNext() { 2513 if (Stack.empty() || !Stack.back().IsExportNode) { 2514 Malformed = true; 2515 moveToEnd(); 2516 return; 2517 } 2518 2519 Stack.pop_back(); 2520 while (!Stack.empty()) { 2521 NodeState &Top = Stack.back(); 2522 if (Top.NextChildIndex < Top.ChildCount) { 2523 pushDownUntilBottom(); 2524 // Now at the next export node. 2525 return; 2526 } else { 2527 if (Top.IsExportNode) { 2528 // This node has no children but is itself an export node. 2529 CumulativeString.resize(Top.ParentStringLength); 2530 return; 2531 } 2532 Stack.pop_back(); 2533 } 2534 } 2535 Done = true; 2536 } 2537 2538 iterator_range<export_iterator> 2539 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 2540 ExportEntry Start(Trie); 2541 if (Trie.size() == 0) 2542 Start.moveToEnd(); 2543 else 2544 Start.moveToFirst(); 2545 2546 ExportEntry Finish(Trie); 2547 Finish.moveToEnd(); 2548 2549 return make_range(export_iterator(Start), export_iterator(Finish)); 2550 } 2551 2552 iterator_range<export_iterator> MachOObjectFile::exports() const { 2553 return exports(getDyldInfoExportsTrie()); 2554 } 2555 2556 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 2557 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2558 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 2559 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 2560 2561 void MachORebaseEntry::moveToFirst() { 2562 Ptr = Opcodes.begin(); 2563 moveNext(); 2564 } 2565 2566 void MachORebaseEntry::moveToEnd() { 2567 Ptr = Opcodes.end(); 2568 RemainingLoopCount = 0; 2569 Done = true; 2570 } 2571 2572 void MachORebaseEntry::moveNext() { 2573 // If in the middle of some loop, move to next rebasing in loop. 2574 SegmentOffset += AdvanceAmount; 2575 if (RemainingLoopCount) { 2576 --RemainingLoopCount; 2577 return; 2578 } 2579 if (Ptr == Opcodes.end()) { 2580 Done = true; 2581 return; 2582 } 2583 bool More = true; 2584 while (More && !Malformed) { 2585 // Parse next opcode and set up next loop. 2586 uint8_t Byte = *Ptr++; 2587 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2588 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2589 switch (Opcode) { 2590 case MachO::REBASE_OPCODE_DONE: 2591 More = false; 2592 Done = true; 2593 moveToEnd(); 2594 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 2595 break; 2596 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2597 RebaseType = ImmValue; 2598 DEBUG_WITH_TYPE( 2599 "mach-o-rebase", 2600 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2601 << "RebaseType=" << (int) RebaseType << "\n"); 2602 break; 2603 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2604 SegmentIndex = ImmValue; 2605 SegmentOffset = readULEB128(); 2606 DEBUG_WITH_TYPE( 2607 "mach-o-rebase", 2608 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2609 << "SegmentIndex=" << SegmentIndex << ", " 2610 << format("SegmentOffset=0x%06X", SegmentOffset) 2611 << "\n"); 2612 break; 2613 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 2614 SegmentOffset += readULEB128(); 2615 DEBUG_WITH_TYPE("mach-o-rebase", 2616 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 2617 << format("SegmentOffset=0x%06X", 2618 SegmentOffset) << "\n"); 2619 break; 2620 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 2621 SegmentOffset += ImmValue * PointerSize; 2622 DEBUG_WITH_TYPE("mach-o-rebase", 2623 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 2624 << format("SegmentOffset=0x%06X", 2625 SegmentOffset) << "\n"); 2626 break; 2627 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 2628 AdvanceAmount = PointerSize; 2629 RemainingLoopCount = ImmValue - 1; 2630 DEBUG_WITH_TYPE( 2631 "mach-o-rebase", 2632 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 2633 << format("SegmentOffset=0x%06X", SegmentOffset) 2634 << ", AdvanceAmount=" << AdvanceAmount 2635 << ", RemainingLoopCount=" << RemainingLoopCount 2636 << "\n"); 2637 return; 2638 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 2639 AdvanceAmount = PointerSize; 2640 RemainingLoopCount = readULEB128() - 1; 2641 DEBUG_WITH_TYPE( 2642 "mach-o-rebase", 2643 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 2644 << format("SegmentOffset=0x%06X", SegmentOffset) 2645 << ", AdvanceAmount=" << AdvanceAmount 2646 << ", RemainingLoopCount=" << RemainingLoopCount 2647 << "\n"); 2648 return; 2649 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2650 AdvanceAmount = readULEB128() + PointerSize; 2651 RemainingLoopCount = 0; 2652 DEBUG_WITH_TYPE( 2653 "mach-o-rebase", 2654 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2655 << format("SegmentOffset=0x%06X", SegmentOffset) 2656 << ", AdvanceAmount=" << AdvanceAmount 2657 << ", RemainingLoopCount=" << RemainingLoopCount 2658 << "\n"); 2659 return; 2660 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2661 RemainingLoopCount = readULEB128() - 1; 2662 AdvanceAmount = readULEB128() + PointerSize; 2663 DEBUG_WITH_TYPE( 2664 "mach-o-rebase", 2665 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2666 << format("SegmentOffset=0x%06X", SegmentOffset) 2667 << ", AdvanceAmount=" << AdvanceAmount 2668 << ", RemainingLoopCount=" << RemainingLoopCount 2669 << "\n"); 2670 return; 2671 default: 2672 Malformed = true; 2673 } 2674 } 2675 } 2676 2677 uint64_t MachORebaseEntry::readULEB128() { 2678 unsigned Count; 2679 uint64_t Result = decodeULEB128(Ptr, &Count); 2680 Ptr += Count; 2681 if (Ptr > Opcodes.end()) { 2682 Ptr = Opcodes.end(); 2683 Malformed = true; 2684 } 2685 return Result; 2686 } 2687 2688 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2689 2690 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2691 2692 StringRef MachORebaseEntry::typeName() const { 2693 switch (RebaseType) { 2694 case MachO::REBASE_TYPE_POINTER: 2695 return "pointer"; 2696 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2697 return "text abs32"; 2698 case MachO::REBASE_TYPE_TEXT_PCREL32: 2699 return "text rel32"; 2700 } 2701 return "unknown"; 2702 } 2703 2704 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2705 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2706 return (Ptr == Other.Ptr) && 2707 (RemainingLoopCount == Other.RemainingLoopCount) && 2708 (Done == Other.Done); 2709 } 2710 2711 iterator_range<rebase_iterator> 2712 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2713 MachORebaseEntry Start(Opcodes, is64); 2714 Start.moveToFirst(); 2715 2716 MachORebaseEntry Finish(Opcodes, is64); 2717 Finish.moveToEnd(); 2718 2719 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2720 } 2721 2722 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2723 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2724 } 2725 2726 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2727 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2728 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2729 BindType(0), PointerSize(is64Bit ? 8 : 4), 2730 TableKind(BK), Malformed(false), Done(false) {} 2731 2732 void MachOBindEntry::moveToFirst() { 2733 Ptr = Opcodes.begin(); 2734 moveNext(); 2735 } 2736 2737 void MachOBindEntry::moveToEnd() { 2738 Ptr = Opcodes.end(); 2739 RemainingLoopCount = 0; 2740 Done = true; 2741 } 2742 2743 void MachOBindEntry::moveNext() { 2744 // If in the middle of some loop, move to next binding in loop. 2745 SegmentOffset += AdvanceAmount; 2746 if (RemainingLoopCount) { 2747 --RemainingLoopCount; 2748 return; 2749 } 2750 if (Ptr == Opcodes.end()) { 2751 Done = true; 2752 return; 2753 } 2754 bool More = true; 2755 while (More && !Malformed) { 2756 // Parse next opcode and set up next loop. 2757 uint8_t Byte = *Ptr++; 2758 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2759 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2760 int8_t SignExtended; 2761 const uint8_t *SymStart; 2762 switch (Opcode) { 2763 case MachO::BIND_OPCODE_DONE: 2764 if (TableKind == Kind::Lazy) { 2765 // Lazying bindings have a DONE opcode between entries. Need to ignore 2766 // it to advance to next entry. But need not if this is last entry. 2767 bool NotLastEntry = false; 2768 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2769 if (*P) { 2770 NotLastEntry = true; 2771 } 2772 } 2773 if (NotLastEntry) 2774 break; 2775 } 2776 More = false; 2777 Done = true; 2778 moveToEnd(); 2779 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2780 break; 2781 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2782 Ordinal = ImmValue; 2783 DEBUG_WITH_TYPE( 2784 "mach-o-bind", 2785 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2786 << "Ordinal=" << Ordinal << "\n"); 2787 break; 2788 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2789 Ordinal = readULEB128(); 2790 DEBUG_WITH_TYPE( 2791 "mach-o-bind", 2792 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2793 << "Ordinal=" << Ordinal << "\n"); 2794 break; 2795 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2796 if (ImmValue) { 2797 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2798 Ordinal = SignExtended; 2799 } else 2800 Ordinal = 0; 2801 DEBUG_WITH_TYPE( 2802 "mach-o-bind", 2803 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2804 << "Ordinal=" << Ordinal << "\n"); 2805 break; 2806 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2807 Flags = ImmValue; 2808 SymStart = Ptr; 2809 while (*Ptr) { 2810 ++Ptr; 2811 } 2812 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2813 Ptr-SymStart); 2814 ++Ptr; 2815 DEBUG_WITH_TYPE( 2816 "mach-o-bind", 2817 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2818 << "SymbolName=" << SymbolName << "\n"); 2819 if (TableKind == Kind::Weak) { 2820 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2821 return; 2822 } 2823 break; 2824 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2825 BindType = ImmValue; 2826 DEBUG_WITH_TYPE( 2827 "mach-o-bind", 2828 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2829 << "BindType=" << (int)BindType << "\n"); 2830 break; 2831 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2832 Addend = readSLEB128(); 2833 if (TableKind == Kind::Lazy) 2834 Malformed = true; 2835 DEBUG_WITH_TYPE( 2836 "mach-o-bind", 2837 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2838 << "Addend=" << Addend << "\n"); 2839 break; 2840 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2841 SegmentIndex = ImmValue; 2842 SegmentOffset = readULEB128(); 2843 DEBUG_WITH_TYPE( 2844 "mach-o-bind", 2845 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2846 << "SegmentIndex=" << SegmentIndex << ", " 2847 << format("SegmentOffset=0x%06X", SegmentOffset) 2848 << "\n"); 2849 break; 2850 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2851 SegmentOffset += readULEB128(); 2852 DEBUG_WITH_TYPE("mach-o-bind", 2853 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2854 << format("SegmentOffset=0x%06X", 2855 SegmentOffset) << "\n"); 2856 break; 2857 case MachO::BIND_OPCODE_DO_BIND: 2858 AdvanceAmount = PointerSize; 2859 RemainingLoopCount = 0; 2860 DEBUG_WITH_TYPE("mach-o-bind", 2861 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2862 << format("SegmentOffset=0x%06X", 2863 SegmentOffset) << "\n"); 2864 return; 2865 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2866 AdvanceAmount = readULEB128() + PointerSize; 2867 RemainingLoopCount = 0; 2868 if (TableKind == Kind::Lazy) 2869 Malformed = true; 2870 DEBUG_WITH_TYPE( 2871 "mach-o-bind", 2872 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2873 << format("SegmentOffset=0x%06X", SegmentOffset) 2874 << ", AdvanceAmount=" << AdvanceAmount 2875 << ", RemainingLoopCount=" << RemainingLoopCount 2876 << "\n"); 2877 return; 2878 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2879 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2880 RemainingLoopCount = 0; 2881 if (TableKind == Kind::Lazy) 2882 Malformed = true; 2883 DEBUG_WITH_TYPE("mach-o-bind", 2884 llvm::dbgs() 2885 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2886 << format("SegmentOffset=0x%06X", 2887 SegmentOffset) << "\n"); 2888 return; 2889 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2890 RemainingLoopCount = readULEB128() - 1; 2891 AdvanceAmount = readULEB128() + PointerSize; 2892 if (TableKind == Kind::Lazy) 2893 Malformed = true; 2894 DEBUG_WITH_TYPE( 2895 "mach-o-bind", 2896 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2897 << format("SegmentOffset=0x%06X", SegmentOffset) 2898 << ", AdvanceAmount=" << AdvanceAmount 2899 << ", RemainingLoopCount=" << RemainingLoopCount 2900 << "\n"); 2901 return; 2902 default: 2903 Malformed = true; 2904 } 2905 } 2906 } 2907 2908 uint64_t MachOBindEntry::readULEB128() { 2909 unsigned Count; 2910 uint64_t Result = decodeULEB128(Ptr, &Count); 2911 Ptr += Count; 2912 if (Ptr > Opcodes.end()) { 2913 Ptr = Opcodes.end(); 2914 Malformed = true; 2915 } 2916 return Result; 2917 } 2918 2919 int64_t MachOBindEntry::readSLEB128() { 2920 unsigned Count; 2921 int64_t Result = decodeSLEB128(Ptr, &Count); 2922 Ptr += Count; 2923 if (Ptr > Opcodes.end()) { 2924 Ptr = Opcodes.end(); 2925 Malformed = true; 2926 } 2927 return Result; 2928 } 2929 2930 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 2931 2932 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 2933 2934 StringRef MachOBindEntry::typeName() const { 2935 switch (BindType) { 2936 case MachO::BIND_TYPE_POINTER: 2937 return "pointer"; 2938 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 2939 return "text abs32"; 2940 case MachO::BIND_TYPE_TEXT_PCREL32: 2941 return "text rel32"; 2942 } 2943 return "unknown"; 2944 } 2945 2946 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 2947 2948 int64_t MachOBindEntry::addend() const { return Addend; } 2949 2950 uint32_t MachOBindEntry::flags() const { return Flags; } 2951 2952 int MachOBindEntry::ordinal() const { return Ordinal; } 2953 2954 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 2955 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2956 return (Ptr == Other.Ptr) && 2957 (RemainingLoopCount == Other.RemainingLoopCount) && 2958 (Done == Other.Done); 2959 } 2960 2961 iterator_range<bind_iterator> 2962 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 2963 MachOBindEntry::Kind BKind) { 2964 MachOBindEntry Start(Opcodes, is64, BKind); 2965 Start.moveToFirst(); 2966 2967 MachOBindEntry Finish(Opcodes, is64, BKind); 2968 Finish.moveToEnd(); 2969 2970 return make_range(bind_iterator(Start), bind_iterator(Finish)); 2971 } 2972 2973 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 2974 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 2975 MachOBindEntry::Kind::Regular); 2976 } 2977 2978 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 2979 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 2980 MachOBindEntry::Kind::Lazy); 2981 } 2982 2983 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 2984 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 2985 MachOBindEntry::Kind::Weak); 2986 } 2987 2988 MachOObjectFile::load_command_iterator 2989 MachOObjectFile::begin_load_commands() const { 2990 return LoadCommands.begin(); 2991 } 2992 2993 MachOObjectFile::load_command_iterator 2994 MachOObjectFile::end_load_commands() const { 2995 return LoadCommands.end(); 2996 } 2997 2998 iterator_range<MachOObjectFile::load_command_iterator> 2999 MachOObjectFile::load_commands() const { 3000 return make_range(begin_load_commands(), end_load_commands()); 3001 } 3002 3003 StringRef 3004 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 3005 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 3006 return parseSegmentOrSectionName(Raw.data()); 3007 } 3008 3009 ArrayRef<char> 3010 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 3011 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3012 const section_base *Base = 3013 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3014 return makeArrayRef(Base->sectname); 3015 } 3016 3017 ArrayRef<char> 3018 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 3019 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3020 const section_base *Base = 3021 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3022 return makeArrayRef(Base->segname); 3023 } 3024 3025 bool 3026 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 3027 const { 3028 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 3029 return false; 3030 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 3031 } 3032 3033 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 3034 const MachO::any_relocation_info &RE) const { 3035 if (isLittleEndian()) 3036 return RE.r_word1 & 0xffffff; 3037 return RE.r_word1 >> 8; 3038 } 3039 3040 bool MachOObjectFile::getPlainRelocationExternal( 3041 const MachO::any_relocation_info &RE) const { 3042 if (isLittleEndian()) 3043 return (RE.r_word1 >> 27) & 1; 3044 return (RE.r_word1 >> 4) & 1; 3045 } 3046 3047 bool MachOObjectFile::getScatteredRelocationScattered( 3048 const MachO::any_relocation_info &RE) const { 3049 return RE.r_word0 >> 31; 3050 } 3051 3052 uint32_t MachOObjectFile::getScatteredRelocationValue( 3053 const MachO::any_relocation_info &RE) const { 3054 return RE.r_word1; 3055 } 3056 3057 uint32_t MachOObjectFile::getScatteredRelocationType( 3058 const MachO::any_relocation_info &RE) const { 3059 return (RE.r_word0 >> 24) & 0xf; 3060 } 3061 3062 unsigned MachOObjectFile::getAnyRelocationAddress( 3063 const MachO::any_relocation_info &RE) const { 3064 if (isRelocationScattered(RE)) 3065 return getScatteredRelocationAddress(RE); 3066 return getPlainRelocationAddress(RE); 3067 } 3068 3069 unsigned MachOObjectFile::getAnyRelocationPCRel( 3070 const MachO::any_relocation_info &RE) const { 3071 if (isRelocationScattered(RE)) 3072 return getScatteredRelocationPCRel(this, RE); 3073 return getPlainRelocationPCRel(this, RE); 3074 } 3075 3076 unsigned MachOObjectFile::getAnyRelocationLength( 3077 const MachO::any_relocation_info &RE) const { 3078 if (isRelocationScattered(RE)) 3079 return getScatteredRelocationLength(RE); 3080 return getPlainRelocationLength(this, RE); 3081 } 3082 3083 unsigned 3084 MachOObjectFile::getAnyRelocationType( 3085 const MachO::any_relocation_info &RE) const { 3086 if (isRelocationScattered(RE)) 3087 return getScatteredRelocationType(RE); 3088 return getPlainRelocationType(this, RE); 3089 } 3090 3091 SectionRef 3092 MachOObjectFile::getAnyRelocationSection( 3093 const MachO::any_relocation_info &RE) const { 3094 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 3095 return *section_end(); 3096 unsigned SecNum = getPlainRelocationSymbolNum(RE); 3097 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 3098 return *section_end(); 3099 DataRefImpl DRI; 3100 DRI.d.a = SecNum - 1; 3101 return SectionRef(DRI, this); 3102 } 3103 3104 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 3105 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3106 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 3107 } 3108 3109 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 3110 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3111 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 3112 } 3113 3114 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 3115 unsigned Index) const { 3116 const char *Sec = getSectionPtr(this, L, Index); 3117 return getStruct<MachO::section>(this, Sec); 3118 } 3119 3120 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 3121 unsigned Index) const { 3122 const char *Sec = getSectionPtr(this, L, Index); 3123 return getStruct<MachO::section_64>(this, Sec); 3124 } 3125 3126 MachO::nlist 3127 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 3128 const char *P = reinterpret_cast<const char *>(DRI.p); 3129 return getStruct<MachO::nlist>(this, P); 3130 } 3131 3132 MachO::nlist_64 3133 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 3134 const char *P = reinterpret_cast<const char *>(DRI.p); 3135 return getStruct<MachO::nlist_64>(this, P); 3136 } 3137 3138 MachO::linkedit_data_command 3139 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 3140 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 3141 } 3142 3143 MachO::segment_command 3144 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 3145 return getStruct<MachO::segment_command>(this, L.Ptr); 3146 } 3147 3148 MachO::segment_command_64 3149 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 3150 return getStruct<MachO::segment_command_64>(this, L.Ptr); 3151 } 3152 3153 MachO::linker_option_command 3154 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 3155 return getStruct<MachO::linker_option_command>(this, L.Ptr); 3156 } 3157 3158 MachO::version_min_command 3159 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 3160 return getStruct<MachO::version_min_command>(this, L.Ptr); 3161 } 3162 3163 MachO::dylib_command 3164 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 3165 return getStruct<MachO::dylib_command>(this, L.Ptr); 3166 } 3167 3168 MachO::dyld_info_command 3169 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 3170 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 3171 } 3172 3173 MachO::dylinker_command 3174 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 3175 return getStruct<MachO::dylinker_command>(this, L.Ptr); 3176 } 3177 3178 MachO::uuid_command 3179 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 3180 return getStruct<MachO::uuid_command>(this, L.Ptr); 3181 } 3182 3183 MachO::rpath_command 3184 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 3185 return getStruct<MachO::rpath_command>(this, L.Ptr); 3186 } 3187 3188 MachO::source_version_command 3189 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 3190 return getStruct<MachO::source_version_command>(this, L.Ptr); 3191 } 3192 3193 MachO::entry_point_command 3194 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 3195 return getStruct<MachO::entry_point_command>(this, L.Ptr); 3196 } 3197 3198 MachO::encryption_info_command 3199 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 3200 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 3201 } 3202 3203 MachO::encryption_info_command_64 3204 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 3205 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 3206 } 3207 3208 MachO::sub_framework_command 3209 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 3210 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 3211 } 3212 3213 MachO::sub_umbrella_command 3214 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 3215 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 3216 } 3217 3218 MachO::sub_library_command 3219 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 3220 return getStruct<MachO::sub_library_command>(this, L.Ptr); 3221 } 3222 3223 MachO::sub_client_command 3224 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 3225 return getStruct<MachO::sub_client_command>(this, L.Ptr); 3226 } 3227 3228 MachO::routines_command 3229 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 3230 return getStruct<MachO::routines_command>(this, L.Ptr); 3231 } 3232 3233 MachO::routines_command_64 3234 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 3235 return getStruct<MachO::routines_command_64>(this, L.Ptr); 3236 } 3237 3238 MachO::thread_command 3239 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 3240 return getStruct<MachO::thread_command>(this, L.Ptr); 3241 } 3242 3243 MachO::any_relocation_info 3244 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 3245 DataRefImpl Sec; 3246 Sec.d.a = Rel.d.a; 3247 uint32_t Offset; 3248 if (is64Bit()) { 3249 MachO::section_64 Sect = getSection64(Sec); 3250 Offset = Sect.reloff; 3251 } else { 3252 MachO::section Sect = getSection(Sec); 3253 Offset = Sect.reloff; 3254 } 3255 3256 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 3257 getPtr(this, Offset)) + Rel.d.b; 3258 return getStruct<MachO::any_relocation_info>( 3259 this, reinterpret_cast<const char *>(P)); 3260 } 3261 3262 MachO::data_in_code_entry 3263 MachOObjectFile::getDice(DataRefImpl Rel) const { 3264 const char *P = reinterpret_cast<const char *>(Rel.p); 3265 return getStruct<MachO::data_in_code_entry>(this, P); 3266 } 3267 3268 const MachO::mach_header &MachOObjectFile::getHeader() const { 3269 return Header; 3270 } 3271 3272 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 3273 assert(is64Bit()); 3274 return Header64; 3275 } 3276 3277 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 3278 const MachO::dysymtab_command &DLC, 3279 unsigned Index) const { 3280 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 3281 return getStruct<uint32_t>(this, getPtr(this, Offset)); 3282 } 3283 3284 MachO::data_in_code_entry 3285 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 3286 unsigned Index) const { 3287 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 3288 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 3289 } 3290 3291 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 3292 if (SymtabLoadCmd) 3293 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 3294 3295 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 3296 MachO::symtab_command Cmd; 3297 Cmd.cmd = MachO::LC_SYMTAB; 3298 Cmd.cmdsize = sizeof(MachO::symtab_command); 3299 Cmd.symoff = 0; 3300 Cmd.nsyms = 0; 3301 Cmd.stroff = 0; 3302 Cmd.strsize = 0; 3303 return Cmd; 3304 } 3305 3306 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 3307 if (DysymtabLoadCmd) 3308 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 3309 3310 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 3311 MachO::dysymtab_command Cmd; 3312 Cmd.cmd = MachO::LC_DYSYMTAB; 3313 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 3314 Cmd.ilocalsym = 0; 3315 Cmd.nlocalsym = 0; 3316 Cmd.iextdefsym = 0; 3317 Cmd.nextdefsym = 0; 3318 Cmd.iundefsym = 0; 3319 Cmd.nundefsym = 0; 3320 Cmd.tocoff = 0; 3321 Cmd.ntoc = 0; 3322 Cmd.modtaboff = 0; 3323 Cmd.nmodtab = 0; 3324 Cmd.extrefsymoff = 0; 3325 Cmd.nextrefsyms = 0; 3326 Cmd.indirectsymoff = 0; 3327 Cmd.nindirectsyms = 0; 3328 Cmd.extreloff = 0; 3329 Cmd.nextrel = 0; 3330 Cmd.locreloff = 0; 3331 Cmd.nlocrel = 0; 3332 return Cmd; 3333 } 3334 3335 MachO::linkedit_data_command 3336 MachOObjectFile::getDataInCodeLoadCommand() const { 3337 if (DataInCodeLoadCmd) 3338 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 3339 3340 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 3341 MachO::linkedit_data_command Cmd; 3342 Cmd.cmd = MachO::LC_DATA_IN_CODE; 3343 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3344 Cmd.dataoff = 0; 3345 Cmd.datasize = 0; 3346 return Cmd; 3347 } 3348 3349 MachO::linkedit_data_command 3350 MachOObjectFile::getLinkOptHintsLoadCommand() const { 3351 if (LinkOptHintsLoadCmd) 3352 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 3353 3354 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 3355 // fields. 3356 MachO::linkedit_data_command Cmd; 3357 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 3358 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3359 Cmd.dataoff = 0; 3360 Cmd.datasize = 0; 3361 return Cmd; 3362 } 3363 3364 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 3365 if (!DyldInfoLoadCmd) 3366 return None; 3367 3368 MachO::dyld_info_command DyldInfo = 3369 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3370 const uint8_t *Ptr = 3371 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 3372 return makeArrayRef(Ptr, DyldInfo.rebase_size); 3373 } 3374 3375 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 3376 if (!DyldInfoLoadCmd) 3377 return None; 3378 3379 MachO::dyld_info_command DyldInfo = 3380 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3381 const uint8_t *Ptr = 3382 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 3383 return makeArrayRef(Ptr, DyldInfo.bind_size); 3384 } 3385 3386 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 3387 if (!DyldInfoLoadCmd) 3388 return None; 3389 3390 MachO::dyld_info_command DyldInfo = 3391 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3392 const uint8_t *Ptr = 3393 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 3394 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 3395 } 3396 3397 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 3398 if (!DyldInfoLoadCmd) 3399 return None; 3400 3401 MachO::dyld_info_command DyldInfo = 3402 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3403 const uint8_t *Ptr = 3404 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 3405 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 3406 } 3407 3408 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 3409 if (!DyldInfoLoadCmd) 3410 return None; 3411 3412 MachO::dyld_info_command DyldInfo = 3413 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3414 const uint8_t *Ptr = 3415 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 3416 return makeArrayRef(Ptr, DyldInfo.export_size); 3417 } 3418 3419 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 3420 if (!UuidLoadCmd) 3421 return None; 3422 // Returning a pointer is fine as uuid doesn't need endian swapping. 3423 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 3424 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 3425 } 3426 3427 StringRef MachOObjectFile::getStringTableData() const { 3428 MachO::symtab_command S = getSymtabLoadCommand(); 3429 return getData().substr(S.stroff, S.strsize); 3430 } 3431 3432 bool MachOObjectFile::is64Bit() const { 3433 return getType() == getMachOType(false, true) || 3434 getType() == getMachOType(true, true); 3435 } 3436 3437 void MachOObjectFile::ReadULEB128s(uint64_t Index, 3438 SmallVectorImpl<uint64_t> &Out) const { 3439 DataExtractor extractor(ObjectFile::getData(), true, 0); 3440 3441 uint32_t offset = Index; 3442 uint64_t data = 0; 3443 while (uint64_t delta = extractor.getULEB128(&offset)) { 3444 data += delta; 3445 Out.push_back(data); 3446 } 3447 } 3448 3449 bool MachOObjectFile::isRelocatableObject() const { 3450 return getHeader().filetype == MachO::MH_OBJECT; 3451 } 3452 3453 Expected<std::unique_ptr<MachOObjectFile>> 3454 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, 3455 uint32_t UniversalCputype, 3456 uint32_t UniversalIndex) { 3457 StringRef Magic = Buffer.getBuffer().slice(0, 4); 3458 if (Magic == "\xFE\xED\xFA\xCE") 3459 return MachOObjectFile::create(Buffer, false, false, 3460 UniversalCputype, UniversalIndex); 3461 if (Magic == "\xCE\xFA\xED\xFE") 3462 return MachOObjectFile::create(Buffer, true, false, 3463 UniversalCputype, UniversalIndex); 3464 if (Magic == "\xFE\xED\xFA\xCF") 3465 return MachOObjectFile::create(Buffer, false, true, 3466 UniversalCputype, UniversalIndex); 3467 if (Magic == "\xCF\xFA\xED\xFE") 3468 return MachOObjectFile::create(Buffer, true, true, 3469 UniversalCputype, UniversalIndex); 3470 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 3471 object_error::invalid_file_type); 3472 } 3473