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