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