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 *= Hints.nhints * 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 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1932 DataRefImpl Ret; 1933 Ret.d.a = Sec.d.a; 1934 Ret.d.b = 0; 1935 return relocation_iterator(RelocationRef(Ret, this)); 1936 } 1937 1938 relocation_iterator 1939 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1940 uint32_t Num; 1941 if (is64Bit()) { 1942 MachO::section_64 Sect = getSection64(Sec); 1943 Num = Sect.nreloc; 1944 } else { 1945 MachO::section Sect = getSection(Sec); 1946 Num = Sect.nreloc; 1947 } 1948 1949 DataRefImpl Ret; 1950 Ret.d.a = Sec.d.a; 1951 Ret.d.b = Num; 1952 return relocation_iterator(RelocationRef(Ret, this)); 1953 } 1954 1955 relocation_iterator MachOObjectFile::extrel_begin() const { 1956 DataRefImpl Ret; 1957 Ret.d.a = 0; // Would normally be a section index. 1958 Ret.d.b = 0; // Index into the external relocations 1959 return relocation_iterator(RelocationRef(Ret, this)); 1960 } 1961 1962 relocation_iterator MachOObjectFile::extrel_end() const { 1963 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); 1964 DataRefImpl Ret; 1965 Ret.d.a = 0; // Would normally be a section index. 1966 Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations 1967 return relocation_iterator(RelocationRef(Ret, this)); 1968 } 1969 1970 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1971 ++Rel.d.b; 1972 } 1973 1974 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1975 assert((getHeader().filetype == MachO::MH_OBJECT || 1976 getHeader().filetype == MachO::MH_KEXT_BUNDLE) && 1977 "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE"); 1978 MachO::any_relocation_info RE = getRelocation(Rel); 1979 return getAnyRelocationAddress(RE); 1980 } 1981 1982 symbol_iterator 1983 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1984 MachO::any_relocation_info RE = getRelocation(Rel); 1985 if (isRelocationScattered(RE)) 1986 return symbol_end(); 1987 1988 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1989 bool isExtern = getPlainRelocationExternal(RE); 1990 if (!isExtern) 1991 return symbol_end(); 1992 1993 MachO::symtab_command S = getSymtabLoadCommand(); 1994 unsigned SymbolTableEntrySize = is64Bit() ? 1995 sizeof(MachO::nlist_64) : 1996 sizeof(MachO::nlist); 1997 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1998 DataRefImpl Sym; 1999 Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset)); 2000 return symbol_iterator(SymbolRef(Sym, this)); 2001 } 2002 2003 section_iterator 2004 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 2005 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 2006 } 2007 2008 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 2009 MachO::any_relocation_info RE = getRelocation(Rel); 2010 return getAnyRelocationType(RE); 2011 } 2012 2013 void MachOObjectFile::getRelocationTypeName( 2014 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 2015 StringRef res; 2016 uint64_t RType = getRelocationType(Rel); 2017 2018 unsigned Arch = this->getArch(); 2019 2020 switch (Arch) { 2021 case Triple::x86: { 2022 static const char *const Table[] = { 2023 "GENERIC_RELOC_VANILLA", 2024 "GENERIC_RELOC_PAIR", 2025 "GENERIC_RELOC_SECTDIFF", 2026 "GENERIC_RELOC_PB_LA_PTR", 2027 "GENERIC_RELOC_LOCAL_SECTDIFF", 2028 "GENERIC_RELOC_TLV" }; 2029 2030 if (RType > 5) 2031 res = "Unknown"; 2032 else 2033 res = Table[RType]; 2034 break; 2035 } 2036 case Triple::x86_64: { 2037 static const char *const Table[] = { 2038 "X86_64_RELOC_UNSIGNED", 2039 "X86_64_RELOC_SIGNED", 2040 "X86_64_RELOC_BRANCH", 2041 "X86_64_RELOC_GOT_LOAD", 2042 "X86_64_RELOC_GOT", 2043 "X86_64_RELOC_SUBTRACTOR", 2044 "X86_64_RELOC_SIGNED_1", 2045 "X86_64_RELOC_SIGNED_2", 2046 "X86_64_RELOC_SIGNED_4", 2047 "X86_64_RELOC_TLV" }; 2048 2049 if (RType > 9) 2050 res = "Unknown"; 2051 else 2052 res = Table[RType]; 2053 break; 2054 } 2055 case Triple::arm: { 2056 static const char *const Table[] = { 2057 "ARM_RELOC_VANILLA", 2058 "ARM_RELOC_PAIR", 2059 "ARM_RELOC_SECTDIFF", 2060 "ARM_RELOC_LOCAL_SECTDIFF", 2061 "ARM_RELOC_PB_LA_PTR", 2062 "ARM_RELOC_BR24", 2063 "ARM_THUMB_RELOC_BR22", 2064 "ARM_THUMB_32BIT_BRANCH", 2065 "ARM_RELOC_HALF", 2066 "ARM_RELOC_HALF_SECTDIFF" }; 2067 2068 if (RType > 9) 2069 res = "Unknown"; 2070 else 2071 res = Table[RType]; 2072 break; 2073 } 2074 case Triple::aarch64: { 2075 static const char *const Table[] = { 2076 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 2077 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 2078 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 2079 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 2080 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 2081 "ARM64_RELOC_ADDEND" 2082 }; 2083 2084 if (RType >= array_lengthof(Table)) 2085 res = "Unknown"; 2086 else 2087 res = Table[RType]; 2088 break; 2089 } 2090 case Triple::ppc: { 2091 static const char *const Table[] = { 2092 "PPC_RELOC_VANILLA", 2093 "PPC_RELOC_PAIR", 2094 "PPC_RELOC_BR14", 2095 "PPC_RELOC_BR24", 2096 "PPC_RELOC_HI16", 2097 "PPC_RELOC_LO16", 2098 "PPC_RELOC_HA16", 2099 "PPC_RELOC_LO14", 2100 "PPC_RELOC_SECTDIFF", 2101 "PPC_RELOC_PB_LA_PTR", 2102 "PPC_RELOC_HI16_SECTDIFF", 2103 "PPC_RELOC_LO16_SECTDIFF", 2104 "PPC_RELOC_HA16_SECTDIFF", 2105 "PPC_RELOC_JBSR", 2106 "PPC_RELOC_LO14_SECTDIFF", 2107 "PPC_RELOC_LOCAL_SECTDIFF" }; 2108 2109 if (RType > 15) 2110 res = "Unknown"; 2111 else 2112 res = Table[RType]; 2113 break; 2114 } 2115 case Triple::UnknownArch: 2116 res = "Unknown"; 2117 break; 2118 } 2119 Result.append(res.begin(), res.end()); 2120 } 2121 2122 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 2123 MachO::any_relocation_info RE = getRelocation(Rel); 2124 return getAnyRelocationLength(RE); 2125 } 2126 2127 // 2128 // guessLibraryShortName() is passed a name of a dynamic library and returns a 2129 // guess on what the short name is. Then name is returned as a substring of the 2130 // StringRef Name passed in. The name of the dynamic library is recognized as 2131 // a framework if it has one of the two following forms: 2132 // Foo.framework/Versions/A/Foo 2133 // Foo.framework/Foo 2134 // Where A and Foo can be any string. And may contain a trailing suffix 2135 // starting with an underbar. If the Name is recognized as a framework then 2136 // isFramework is set to true else it is set to false. If the Name has a 2137 // suffix then Suffix is set to the substring in Name that contains the suffix 2138 // else it is set to a NULL StringRef. 2139 // 2140 // The Name of the dynamic library is recognized as a library name if it has 2141 // one of the two following forms: 2142 // libFoo.A.dylib 2143 // libFoo.dylib 2144 // The library may have a suffix trailing the name Foo of the form: 2145 // libFoo_profile.A.dylib 2146 // libFoo_profile.dylib 2147 // 2148 // The Name of the dynamic library is also recognized as a library name if it 2149 // has the following form: 2150 // Foo.qtx 2151 // 2152 // If the Name of the dynamic library is none of the forms above then a NULL 2153 // StringRef is returned. 2154 // 2155 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 2156 bool &isFramework, 2157 StringRef &Suffix) { 2158 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 2159 size_t a, b, c, d, Idx; 2160 2161 isFramework = false; 2162 Suffix = StringRef(); 2163 2164 // Pull off the last component and make Foo point to it 2165 a = Name.rfind('/'); 2166 if (a == Name.npos || a == 0) 2167 goto guess_library; 2168 Foo = Name.slice(a+1, Name.npos); 2169 2170 // Look for a suffix starting with a '_' 2171 Idx = Foo.rfind('_'); 2172 if (Idx != Foo.npos && Foo.size() >= 2) { 2173 Suffix = Foo.slice(Idx, Foo.npos); 2174 Foo = Foo.slice(0, Idx); 2175 } 2176 2177 // First look for the form Foo.framework/Foo 2178 b = Name.rfind('/', a); 2179 if (b == Name.npos) 2180 Idx = 0; 2181 else 2182 Idx = b+1; 2183 F = Name.slice(Idx, Idx + Foo.size()); 2184 DotFramework = Name.slice(Idx + Foo.size(), 2185 Idx + Foo.size() + sizeof(".framework/")-1); 2186 if (F == Foo && DotFramework == ".framework/") { 2187 isFramework = true; 2188 return Foo; 2189 } 2190 2191 // Next look for the form Foo.framework/Versions/A/Foo 2192 if (b == Name.npos) 2193 goto guess_library; 2194 c = Name.rfind('/', b); 2195 if (c == Name.npos || c == 0) 2196 goto guess_library; 2197 V = Name.slice(c+1, Name.npos); 2198 if (!V.startswith("Versions/")) 2199 goto guess_library; 2200 d = Name.rfind('/', c); 2201 if (d == Name.npos) 2202 Idx = 0; 2203 else 2204 Idx = d+1; 2205 F = Name.slice(Idx, Idx + Foo.size()); 2206 DotFramework = Name.slice(Idx + Foo.size(), 2207 Idx + Foo.size() + sizeof(".framework/")-1); 2208 if (F == Foo && DotFramework == ".framework/") { 2209 isFramework = true; 2210 return Foo; 2211 } 2212 2213 guess_library: 2214 // pull off the suffix after the "." and make a point to it 2215 a = Name.rfind('.'); 2216 if (a == Name.npos || a == 0) 2217 return StringRef(); 2218 Dylib = Name.slice(a, Name.npos); 2219 if (Dylib != ".dylib") 2220 goto guess_qtx; 2221 2222 // First pull off the version letter for the form Foo.A.dylib if any. 2223 if (a >= 3) { 2224 Dot = Name.slice(a-2, a-1); 2225 if (Dot == ".") 2226 a = a - 2; 2227 } 2228 2229 b = Name.rfind('/', a); 2230 if (b == Name.npos) 2231 b = 0; 2232 else 2233 b = b+1; 2234 // ignore any suffix after an underbar like Foo_profile.A.dylib 2235 Idx = Name.find('_', b); 2236 if (Idx != Name.npos && Idx != b) { 2237 Lib = Name.slice(b, Idx); 2238 Suffix = Name.slice(Idx, a); 2239 } 2240 else 2241 Lib = Name.slice(b, a); 2242 // There are incorrect library names of the form: 2243 // libATS.A_profile.dylib so check for these. 2244 if (Lib.size() >= 3) { 2245 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 2246 if (Dot == ".") 2247 Lib = Lib.slice(0, Lib.size()-2); 2248 } 2249 return Lib; 2250 2251 guess_qtx: 2252 Qtx = Name.slice(a, Name.npos); 2253 if (Qtx != ".qtx") 2254 return StringRef(); 2255 b = Name.rfind('/', a); 2256 if (b == Name.npos) 2257 Lib = Name.slice(0, a); 2258 else 2259 Lib = Name.slice(b+1, a); 2260 // There are library names of the form: QT.A.qtx so check for these. 2261 if (Lib.size() >= 3) { 2262 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 2263 if (Dot == ".") 2264 Lib = Lib.slice(0, Lib.size()-2); 2265 } 2266 return Lib; 2267 } 2268 2269 // getLibraryShortNameByIndex() is used to get the short name of the library 2270 // for an undefined symbol in a linked Mach-O binary that was linked with the 2271 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 2272 // It is passed the index (0 - based) of the library as translated from 2273 // GET_LIBRARY_ORDINAL (1 - based). 2274 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 2275 StringRef &Res) const { 2276 if (Index >= Libraries.size()) 2277 return object_error::parse_failed; 2278 2279 // If the cache of LibrariesShortNames is not built up do that first for 2280 // all the Libraries. 2281 if (LibrariesShortNames.size() == 0) { 2282 for (unsigned i = 0; i < Libraries.size(); i++) { 2283 MachO::dylib_command D = 2284 getStruct<MachO::dylib_command>(*this, Libraries[i]); 2285 if (D.dylib.name >= D.cmdsize) 2286 return object_error::parse_failed; 2287 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 2288 StringRef Name = StringRef(P); 2289 if (D.dylib.name+Name.size() >= D.cmdsize) 2290 return object_error::parse_failed; 2291 StringRef Suffix; 2292 bool isFramework; 2293 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 2294 if (shortName.empty()) 2295 LibrariesShortNames.push_back(Name); 2296 else 2297 LibrariesShortNames.push_back(shortName); 2298 } 2299 } 2300 2301 Res = LibrariesShortNames[Index]; 2302 return std::error_code(); 2303 } 2304 2305 uint32_t MachOObjectFile::getLibraryCount() const { 2306 return Libraries.size(); 2307 } 2308 2309 section_iterator 2310 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 2311 DataRefImpl Sec; 2312 Sec.d.a = Rel->getRawDataRefImpl().d.a; 2313 return section_iterator(SectionRef(Sec, this)); 2314 } 2315 2316 basic_symbol_iterator MachOObjectFile::symbol_begin() const { 2317 DataRefImpl DRI; 2318 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2319 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2320 return basic_symbol_iterator(SymbolRef(DRI, this)); 2321 2322 return getSymbolByIndex(0); 2323 } 2324 2325 basic_symbol_iterator MachOObjectFile::symbol_end() const { 2326 DataRefImpl DRI; 2327 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2328 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2329 return basic_symbol_iterator(SymbolRef(DRI, this)); 2330 2331 unsigned SymbolTableEntrySize = is64Bit() ? 2332 sizeof(MachO::nlist_64) : 2333 sizeof(MachO::nlist); 2334 unsigned Offset = Symtab.symoff + 2335 Symtab.nsyms * SymbolTableEntrySize; 2336 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset)); 2337 return basic_symbol_iterator(SymbolRef(DRI, this)); 2338 } 2339 2340 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 2341 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2342 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 2343 report_fatal_error("Requested symbol index is out of range."); 2344 unsigned SymbolTableEntrySize = 2345 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2346 DataRefImpl DRI; 2347 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff)); 2348 DRI.p += Index * SymbolTableEntrySize; 2349 return basic_symbol_iterator(SymbolRef(DRI, this)); 2350 } 2351 2352 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 2353 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2354 if (!SymtabLoadCmd) 2355 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 2356 unsigned SymbolTableEntrySize = 2357 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2358 DataRefImpl DRIstart; 2359 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff)); 2360 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 2361 return Index; 2362 } 2363 2364 section_iterator MachOObjectFile::section_begin() const { 2365 DataRefImpl DRI; 2366 return section_iterator(SectionRef(DRI, this)); 2367 } 2368 2369 section_iterator MachOObjectFile::section_end() const { 2370 DataRefImpl DRI; 2371 DRI.d.a = Sections.size(); 2372 return section_iterator(SectionRef(DRI, this)); 2373 } 2374 2375 uint8_t MachOObjectFile::getBytesInAddress() const { 2376 return is64Bit() ? 8 : 4; 2377 } 2378 2379 StringRef MachOObjectFile::getFileFormatName() const { 2380 unsigned CPUType = getCPUType(*this); 2381 if (!is64Bit()) { 2382 switch (CPUType) { 2383 case MachO::CPU_TYPE_I386: 2384 return "Mach-O 32-bit i386"; 2385 case MachO::CPU_TYPE_ARM: 2386 return "Mach-O arm"; 2387 case MachO::CPU_TYPE_POWERPC: 2388 return "Mach-O 32-bit ppc"; 2389 default: 2390 return "Mach-O 32-bit unknown"; 2391 } 2392 } 2393 2394 switch (CPUType) { 2395 case MachO::CPU_TYPE_X86_64: 2396 return "Mach-O 64-bit x86-64"; 2397 case MachO::CPU_TYPE_ARM64: 2398 return "Mach-O arm64"; 2399 case MachO::CPU_TYPE_POWERPC64: 2400 return "Mach-O 64-bit ppc64"; 2401 default: 2402 return "Mach-O 64-bit unknown"; 2403 } 2404 } 2405 2406 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 2407 switch (CPUType) { 2408 case MachO::CPU_TYPE_I386: 2409 return Triple::x86; 2410 case MachO::CPU_TYPE_X86_64: 2411 return Triple::x86_64; 2412 case MachO::CPU_TYPE_ARM: 2413 return Triple::arm; 2414 case MachO::CPU_TYPE_ARM64: 2415 return Triple::aarch64; 2416 case MachO::CPU_TYPE_POWERPC: 2417 return Triple::ppc; 2418 case MachO::CPU_TYPE_POWERPC64: 2419 return Triple::ppc64; 2420 default: 2421 return Triple::UnknownArch; 2422 } 2423 } 2424 2425 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 2426 const char **McpuDefault, 2427 const char **ArchFlag) { 2428 if (McpuDefault) 2429 *McpuDefault = nullptr; 2430 if (ArchFlag) 2431 *ArchFlag = nullptr; 2432 2433 switch (CPUType) { 2434 case MachO::CPU_TYPE_I386: 2435 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2436 case MachO::CPU_SUBTYPE_I386_ALL: 2437 if (ArchFlag) 2438 *ArchFlag = "i386"; 2439 return Triple("i386-apple-darwin"); 2440 default: 2441 return Triple(); 2442 } 2443 case MachO::CPU_TYPE_X86_64: 2444 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2445 case MachO::CPU_SUBTYPE_X86_64_ALL: 2446 if (ArchFlag) 2447 *ArchFlag = "x86_64"; 2448 return Triple("x86_64-apple-darwin"); 2449 case MachO::CPU_SUBTYPE_X86_64_H: 2450 if (ArchFlag) 2451 *ArchFlag = "x86_64h"; 2452 return Triple("x86_64h-apple-darwin"); 2453 default: 2454 return Triple(); 2455 } 2456 case MachO::CPU_TYPE_ARM: 2457 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2458 case MachO::CPU_SUBTYPE_ARM_V4T: 2459 if (ArchFlag) 2460 *ArchFlag = "armv4t"; 2461 return Triple("armv4t-apple-darwin"); 2462 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2463 if (ArchFlag) 2464 *ArchFlag = "armv5e"; 2465 return Triple("armv5e-apple-darwin"); 2466 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2467 if (ArchFlag) 2468 *ArchFlag = "xscale"; 2469 return Triple("xscale-apple-darwin"); 2470 case MachO::CPU_SUBTYPE_ARM_V6: 2471 if (ArchFlag) 2472 *ArchFlag = "armv6"; 2473 return Triple("armv6-apple-darwin"); 2474 case MachO::CPU_SUBTYPE_ARM_V6M: 2475 if (McpuDefault) 2476 *McpuDefault = "cortex-m0"; 2477 if (ArchFlag) 2478 *ArchFlag = "armv6m"; 2479 return Triple("armv6m-apple-darwin"); 2480 case MachO::CPU_SUBTYPE_ARM_V7: 2481 if (ArchFlag) 2482 *ArchFlag = "armv7"; 2483 return Triple("armv7-apple-darwin"); 2484 case MachO::CPU_SUBTYPE_ARM_V7EM: 2485 if (McpuDefault) 2486 *McpuDefault = "cortex-m4"; 2487 if (ArchFlag) 2488 *ArchFlag = "armv7em"; 2489 return Triple("thumbv7em-apple-darwin"); 2490 case MachO::CPU_SUBTYPE_ARM_V7K: 2491 if (McpuDefault) 2492 *McpuDefault = "cortex-a7"; 2493 if (ArchFlag) 2494 *ArchFlag = "armv7k"; 2495 return Triple("armv7k-apple-darwin"); 2496 case MachO::CPU_SUBTYPE_ARM_V7M: 2497 if (McpuDefault) 2498 *McpuDefault = "cortex-m3"; 2499 if (ArchFlag) 2500 *ArchFlag = "armv7m"; 2501 return Triple("thumbv7m-apple-darwin"); 2502 case MachO::CPU_SUBTYPE_ARM_V7S: 2503 if (McpuDefault) 2504 *McpuDefault = "cortex-a7"; 2505 if (ArchFlag) 2506 *ArchFlag = "armv7s"; 2507 return Triple("armv7s-apple-darwin"); 2508 default: 2509 return Triple(); 2510 } 2511 case MachO::CPU_TYPE_ARM64: 2512 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2513 case MachO::CPU_SUBTYPE_ARM64_ALL: 2514 if (McpuDefault) 2515 *McpuDefault = "cyclone"; 2516 if (ArchFlag) 2517 *ArchFlag = "arm64"; 2518 return Triple("arm64-apple-darwin"); 2519 default: 2520 return Triple(); 2521 } 2522 case MachO::CPU_TYPE_POWERPC: 2523 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2524 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2525 if (ArchFlag) 2526 *ArchFlag = "ppc"; 2527 return Triple("ppc-apple-darwin"); 2528 default: 2529 return Triple(); 2530 } 2531 case MachO::CPU_TYPE_POWERPC64: 2532 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2533 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2534 if (ArchFlag) 2535 *ArchFlag = "ppc64"; 2536 return Triple("ppc64-apple-darwin"); 2537 default: 2538 return Triple(); 2539 } 2540 default: 2541 return Triple(); 2542 } 2543 } 2544 2545 Triple MachOObjectFile::getHostArch() { 2546 return Triple(sys::getDefaultTargetTriple()); 2547 } 2548 2549 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2550 return StringSwitch<bool>(ArchFlag) 2551 .Case("i386", true) 2552 .Case("x86_64", true) 2553 .Case("x86_64h", true) 2554 .Case("armv4t", true) 2555 .Case("arm", true) 2556 .Case("armv5e", true) 2557 .Case("armv6", true) 2558 .Case("armv6m", true) 2559 .Case("armv7", true) 2560 .Case("armv7em", true) 2561 .Case("armv7k", true) 2562 .Case("armv7m", true) 2563 .Case("armv7s", true) 2564 .Case("arm64", true) 2565 .Case("ppc", true) 2566 .Case("ppc64", true) 2567 .Default(false); 2568 } 2569 2570 unsigned MachOObjectFile::getArch() const { 2571 return getArch(getCPUType(*this)); 2572 } 2573 2574 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2575 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2576 } 2577 2578 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2579 DataRefImpl DRI; 2580 DRI.d.a = Index; 2581 return section_rel_begin(DRI); 2582 } 2583 2584 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2585 DataRefImpl DRI; 2586 DRI.d.a = Index; 2587 return section_rel_end(DRI); 2588 } 2589 2590 dice_iterator MachOObjectFile::begin_dices() const { 2591 DataRefImpl DRI; 2592 if (!DataInCodeLoadCmd) 2593 return dice_iterator(DiceRef(DRI, this)); 2594 2595 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2596 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff)); 2597 return dice_iterator(DiceRef(DRI, this)); 2598 } 2599 2600 dice_iterator MachOObjectFile::end_dices() const { 2601 DataRefImpl DRI; 2602 if (!DataInCodeLoadCmd) 2603 return dice_iterator(DiceRef(DRI, this)); 2604 2605 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2606 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2607 DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset)); 2608 return dice_iterator(DiceRef(DRI, this)); 2609 } 2610 2611 ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O, 2612 ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {} 2613 2614 void ExportEntry::moveToFirst() { 2615 ErrorAsOutParameter ErrAsOutParam(E); 2616 pushNode(0); 2617 if (*E) 2618 return; 2619 pushDownUntilBottom(); 2620 } 2621 2622 void ExportEntry::moveToEnd() { 2623 Stack.clear(); 2624 Done = true; 2625 } 2626 2627 bool ExportEntry::operator==(const ExportEntry &Other) const { 2628 // Common case, one at end, other iterating from begin. 2629 if (Done || Other.Done) 2630 return (Done == Other.Done); 2631 // Not equal if different stack sizes. 2632 if (Stack.size() != Other.Stack.size()) 2633 return false; 2634 // Not equal if different cumulative strings. 2635 if (!CumulativeString.equals(Other.CumulativeString)) 2636 return false; 2637 // Equal if all nodes in both stacks match. 2638 for (unsigned i=0; i < Stack.size(); ++i) { 2639 if (Stack[i].Start != Other.Stack[i].Start) 2640 return false; 2641 } 2642 return true; 2643 } 2644 2645 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) { 2646 unsigned Count; 2647 uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error); 2648 Ptr += Count; 2649 if (Ptr > Trie.end()) 2650 Ptr = Trie.end(); 2651 return Result; 2652 } 2653 2654 StringRef ExportEntry::name() const { 2655 return CumulativeString; 2656 } 2657 2658 uint64_t ExportEntry::flags() const { 2659 return Stack.back().Flags; 2660 } 2661 2662 uint64_t ExportEntry::address() const { 2663 return Stack.back().Address; 2664 } 2665 2666 uint64_t ExportEntry::other() const { 2667 return Stack.back().Other; 2668 } 2669 2670 StringRef ExportEntry::otherName() const { 2671 const char* ImportName = Stack.back().ImportName; 2672 if (ImportName) 2673 return StringRef(ImportName); 2674 return StringRef(); 2675 } 2676 2677 uint32_t ExportEntry::nodeOffset() const { 2678 return Stack.back().Start - Trie.begin(); 2679 } 2680 2681 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2682 : Start(Ptr), Current(Ptr) {} 2683 2684 void ExportEntry::pushNode(uint64_t offset) { 2685 ErrorAsOutParameter ErrAsOutParam(E); 2686 const uint8_t *Ptr = Trie.begin() + offset; 2687 NodeState State(Ptr); 2688 const char *error; 2689 uint64_t ExportInfoSize = readULEB128(State.Current, &error); 2690 if (error) { 2691 *E = malformedError("export info size " + Twine(error) + 2692 " in export trie data at node: 0x" + 2693 Twine::utohexstr(offset)); 2694 moveToEnd(); 2695 return; 2696 } 2697 State.IsExportNode = (ExportInfoSize != 0); 2698 const uint8_t* Children = State.Current + ExportInfoSize; 2699 if (Children > Trie.end()) { 2700 *E = malformedError( 2701 "export info size: 0x" + Twine::utohexstr(ExportInfoSize) + 2702 " in export trie data at node: 0x" + Twine::utohexstr(offset) + 2703 " too big and extends past end of trie data"); 2704 moveToEnd(); 2705 return; 2706 } 2707 if (State.IsExportNode) { 2708 const uint8_t *ExportStart = State.Current; 2709 State.Flags = readULEB128(State.Current, &error); 2710 if (error) { 2711 *E = malformedError("flags " + Twine(error) + 2712 " in export trie data at node: 0x" + 2713 Twine::utohexstr(offset)); 2714 moveToEnd(); 2715 return; 2716 } 2717 uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK; 2718 if (State.Flags != 0 && 2719 (Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR && 2720 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE && 2721 Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL)) { 2722 *E = malformedError( 2723 "unsupported exported symbol kind: " + Twine((int)Kind) + 2724 " in flags: 0x" + Twine::utohexstr(State.Flags) + 2725 " in export trie data at node: 0x" + Twine::utohexstr(offset)); 2726 moveToEnd(); 2727 return; 2728 } 2729 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2730 State.Address = 0; 2731 State.Other = readULEB128(State.Current, &error); // dylib ordinal 2732 if (error) { 2733 *E = malformedError("dylib ordinal of re-export " + Twine(error) + 2734 " in export trie data at node: 0x" + 2735 Twine::utohexstr(offset)); 2736 moveToEnd(); 2737 return; 2738 } 2739 if (O != nullptr) { 2740 if (State.Other > O->getLibraryCount()) { 2741 *E = malformedError( 2742 "bad library ordinal: " + Twine((int)State.Other) + " (max " + 2743 Twine((int)O->getLibraryCount()) + 2744 ") in export trie data at node: 0x" + Twine::utohexstr(offset)); 2745 moveToEnd(); 2746 return; 2747 } 2748 } 2749 State.ImportName = reinterpret_cast<const char*>(State.Current); 2750 if (*State.ImportName == '\0') { 2751 State.Current++; 2752 } else { 2753 const uint8_t *End = State.Current + 1; 2754 if (End >= Trie.end()) { 2755 *E = malformedError("import name of re-export in export trie data at " 2756 "node: 0x" + 2757 Twine::utohexstr(offset) + 2758 " starts past end of trie data"); 2759 moveToEnd(); 2760 return; 2761 } 2762 while(*End != '\0' && End < Trie.end()) 2763 End++; 2764 if (*End != '\0') { 2765 *E = malformedError("import name of re-export in export trie data at " 2766 "node: 0x" + 2767 Twine::utohexstr(offset) + 2768 " extends past end of trie data"); 2769 moveToEnd(); 2770 return; 2771 } 2772 State.Current = End + 1; 2773 } 2774 } else { 2775 State.Address = readULEB128(State.Current, &error); 2776 if (error) { 2777 *E = malformedError("address " + Twine(error) + 2778 " in export trie data at node: 0x" + 2779 Twine::utohexstr(offset)); 2780 moveToEnd(); 2781 return; 2782 } 2783 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) { 2784 State.Other = readULEB128(State.Current, &error); 2785 if (error) { 2786 *E = malformedError("resolver of stub and resolver " + Twine(error) + 2787 " in export trie data at node: 0x" + 2788 Twine::utohexstr(offset)); 2789 moveToEnd(); 2790 return; 2791 } 2792 } 2793 } 2794 if(ExportStart + ExportInfoSize != State.Current) { 2795 *E = malformedError( 2796 "inconsistant export info size: 0x" + 2797 Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" + 2798 Twine::utohexstr(State.Current - ExportStart) + 2799 " in export trie data at node: 0x" + Twine::utohexstr(offset)); 2800 moveToEnd(); 2801 return; 2802 } 2803 } 2804 State.ChildCount = *Children; 2805 if (State.ChildCount != 0 && Children + 1 >= Trie.end()) { 2806 *E = malformedError("byte for count of childern in export trie data at " 2807 "node: 0x" + 2808 Twine::utohexstr(offset) + 2809 " extends past end of trie data"); 2810 moveToEnd(); 2811 return; 2812 } 2813 State.Current = Children + 1; 2814 State.NextChildIndex = 0; 2815 State.ParentStringLength = CumulativeString.size(); 2816 Stack.push_back(State); 2817 } 2818 2819 void ExportEntry::pushDownUntilBottom() { 2820 ErrorAsOutParameter ErrAsOutParam(E); 2821 const char *error; 2822 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2823 NodeState &Top = Stack.back(); 2824 CumulativeString.resize(Top.ParentStringLength); 2825 for (;*Top.Current != 0 && Top.Current < Trie.end(); Top.Current++) { 2826 char C = *Top.Current; 2827 CumulativeString.push_back(C); 2828 } 2829 if (Top.Current >= Trie.end()) { 2830 *E = malformedError("edge sub-string in export trie data at node: 0x" + 2831 Twine::utohexstr(Top.Start - Trie.begin()) + 2832 " for child #" + Twine((int)Top.NextChildIndex) + 2833 " extends past end of trie data"); 2834 moveToEnd(); 2835 return; 2836 } 2837 Top.Current += 1; 2838 uint64_t childNodeIndex = readULEB128(Top.Current, &error); 2839 if (error) { 2840 *E = malformedError("child node offset " + Twine(error) + 2841 " in export trie data at node: 0x" + 2842 Twine::utohexstr(Top.Start - Trie.begin())); 2843 moveToEnd(); 2844 return; 2845 } 2846 for (const NodeState &node : nodes()) { 2847 if (node.Start == Trie.begin() + childNodeIndex){ 2848 *E = malformedError("loop in childern in export trie data at node: 0x" + 2849 Twine::utohexstr(Top.Start - Trie.begin()) + 2850 " back to node: 0x" + 2851 Twine::utohexstr(childNodeIndex)); 2852 moveToEnd(); 2853 return; 2854 } 2855 } 2856 Top.NextChildIndex += 1; 2857 pushNode(childNodeIndex); 2858 if (*E) 2859 return; 2860 } 2861 if (!Stack.back().IsExportNode) { 2862 *E = malformedError("node is not an export node in export trie data at " 2863 "node: 0x" + 2864 Twine::utohexstr(Stack.back().Start - Trie.begin())); 2865 moveToEnd(); 2866 return; 2867 } 2868 } 2869 2870 // We have a trie data structure and need a way to walk it that is compatible 2871 // with the C++ iterator model. The solution is a non-recursive depth first 2872 // traversal where the iterator contains a stack of parent nodes along with a 2873 // string that is the accumulation of all edge strings along the parent chain 2874 // to this point. 2875 // 2876 // There is one "export" node for each exported symbol. But because some 2877 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2878 // node may have child nodes too. 2879 // 2880 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2881 // child until hitting a node with no children (which is an export node or 2882 // else the trie is malformed). On the way down, each node is pushed on the 2883 // stack ivar. If there is no more ways down, it pops up one and tries to go 2884 // down a sibling path until a childless node is reached. 2885 void ExportEntry::moveNext() { 2886 assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack"); 2887 if (!Stack.back().IsExportNode) { 2888 *E = malformedError("node is not an export node in export trie data at " 2889 "node: 0x" + 2890 Twine::utohexstr(Stack.back().Start - Trie.begin())); 2891 moveToEnd(); 2892 return; 2893 } 2894 2895 Stack.pop_back(); 2896 while (!Stack.empty()) { 2897 NodeState &Top = Stack.back(); 2898 if (Top.NextChildIndex < Top.ChildCount) { 2899 pushDownUntilBottom(); 2900 // Now at the next export node. 2901 return; 2902 } else { 2903 if (Top.IsExportNode) { 2904 // This node has no children but is itself an export node. 2905 CumulativeString.resize(Top.ParentStringLength); 2906 return; 2907 } 2908 Stack.pop_back(); 2909 } 2910 } 2911 Done = true; 2912 } 2913 2914 iterator_range<export_iterator> 2915 MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie, 2916 const MachOObjectFile *O) { 2917 ExportEntry Start(&E, O, Trie); 2918 if (Trie.empty()) 2919 Start.moveToEnd(); 2920 else 2921 Start.moveToFirst(); 2922 2923 ExportEntry Finish(&E, O, Trie); 2924 Finish.moveToEnd(); 2925 2926 return make_range(export_iterator(Start), export_iterator(Finish)); 2927 } 2928 2929 iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const { 2930 return exports(Err, getDyldInfoExportsTrie(), this); 2931 } 2932 2933 MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O, 2934 ArrayRef<uint8_t> Bytes, bool is64Bit) 2935 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), 2936 PointerSize(is64Bit ? 8 : 4) {} 2937 2938 void MachORebaseEntry::moveToFirst() { 2939 Ptr = Opcodes.begin(); 2940 moveNext(); 2941 } 2942 2943 void MachORebaseEntry::moveToEnd() { 2944 Ptr = Opcodes.end(); 2945 RemainingLoopCount = 0; 2946 Done = true; 2947 } 2948 2949 void MachORebaseEntry::moveNext() { 2950 ErrorAsOutParameter ErrAsOutParam(E); 2951 // If in the middle of some loop, move to next rebasing in loop. 2952 SegmentOffset += AdvanceAmount; 2953 if (RemainingLoopCount) { 2954 --RemainingLoopCount; 2955 return; 2956 } 2957 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to 2958 // pointer size. Therefore it is possible to reach the end without ever having 2959 // seen REBASE_OPCODE_DONE. 2960 if (Ptr == Opcodes.end()) { 2961 Done = true; 2962 return; 2963 } 2964 bool More = true; 2965 while (More) { 2966 // Parse next opcode and set up next loop. 2967 const uint8_t *OpcodeStart = Ptr; 2968 uint8_t Byte = *Ptr++; 2969 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2970 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2971 uint32_t Count, Skip; 2972 const char *error = nullptr; 2973 switch (Opcode) { 2974 case MachO::REBASE_OPCODE_DONE: 2975 More = false; 2976 Done = true; 2977 moveToEnd(); 2978 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n"); 2979 break; 2980 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2981 RebaseType = ImmValue; 2982 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) { 2983 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " + 2984 Twine((int)RebaseType) + " for opcode at: 0x" + 2985 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 2986 moveToEnd(); 2987 return; 2988 } 2989 DEBUG_WITH_TYPE( 2990 "mach-o-rebase", 2991 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2992 << "RebaseType=" << (int) RebaseType << "\n"); 2993 break; 2994 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2995 SegmentIndex = ImmValue; 2996 SegmentOffset = readULEB128(&error); 2997 if (error) { 2998 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 2999 Twine(error) + " for opcode at: 0x" + 3000 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3001 moveToEnd(); 3002 return; 3003 } 3004 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3005 true); 3006 if (error) { 3007 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 3008 Twine(error) + " for opcode at: 0x" + 3009 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3010 moveToEnd(); 3011 return; 3012 } 3013 DEBUG_WITH_TYPE( 3014 "mach-o-rebase", 3015 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 3016 << "SegmentIndex=" << SegmentIndex << ", " 3017 << format("SegmentOffset=0x%06X", SegmentOffset) 3018 << "\n"); 3019 break; 3020 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 3021 SegmentOffset += readULEB128(&error); 3022 if (error) { 3023 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) + 3024 " 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_ADD_ADDR_ULEB " + Twine(error) + 3033 " for opcode at: 0x" + 3034 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3035 moveToEnd(); 3036 return; 3037 } 3038 DEBUG_WITH_TYPE("mach-o-rebase", 3039 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 3040 << format("SegmentOffset=0x%06X", 3041 SegmentOffset) << "\n"); 3042 break; 3043 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 3044 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3045 true); 3046 if (error) { 3047 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " + 3048 Twine(error) + " for opcode at: 0x" + 3049 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3050 moveToEnd(); 3051 return; 3052 } 3053 SegmentOffset += ImmValue * PointerSize; 3054 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3055 false); 3056 if (error) { 3057 *E = 3058 malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " 3059 " (after adding immediate times the pointer size) " + 3060 Twine(error) + " for opcode at: 0x" + 3061 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3062 moveToEnd(); 3063 return; 3064 } 3065 DEBUG_WITH_TYPE("mach-o-rebase", 3066 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 3067 << format("SegmentOffset=0x%06X", 3068 SegmentOffset) << "\n"); 3069 break; 3070 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 3071 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3072 true); 3073 if (error) { 3074 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " + 3075 Twine(error) + " for opcode at: 0x" + 3076 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3077 moveToEnd(); 3078 return; 3079 } 3080 AdvanceAmount = PointerSize; 3081 Skip = 0; 3082 Count = ImmValue; 3083 if (ImmValue != 0) 3084 RemainingLoopCount = ImmValue - 1; 3085 else 3086 RemainingLoopCount = 0; 3087 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3088 SegmentIndex, SegmentOffset); 3089 if (error) { 3090 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " + 3091 Twine(error) + " for opcode at: 0x" + 3092 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3093 moveToEnd(); 3094 return; 3095 } 3096 DEBUG_WITH_TYPE( 3097 "mach-o-rebase", 3098 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 3099 << format("SegmentOffset=0x%06X", SegmentOffset) 3100 << ", AdvanceAmount=" << AdvanceAmount 3101 << ", RemainingLoopCount=" << RemainingLoopCount 3102 << "\n"); 3103 return; 3104 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 3105 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3106 true); 3107 if (error) { 3108 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " + 3109 Twine(error) + " for opcode at: 0x" + 3110 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3111 moveToEnd(); 3112 return; 3113 } 3114 AdvanceAmount = PointerSize; 3115 Skip = 0; 3116 Count = readULEB128(&error); 3117 if (error) { 3118 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " + 3119 Twine(error) + " for opcode at: 0x" + 3120 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3121 moveToEnd(); 3122 return; 3123 } 3124 if (Count != 0) 3125 RemainingLoopCount = Count - 1; 3126 else 3127 RemainingLoopCount = 0; 3128 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3129 SegmentIndex, SegmentOffset); 3130 if (error) { 3131 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " + 3132 Twine(error) + " for opcode at: 0x" + 3133 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3134 moveToEnd(); 3135 return; 3136 } 3137 DEBUG_WITH_TYPE( 3138 "mach-o-rebase", 3139 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 3140 << format("SegmentOffset=0x%06X", SegmentOffset) 3141 << ", AdvanceAmount=" << AdvanceAmount 3142 << ", RemainingLoopCount=" << RemainingLoopCount 3143 << "\n"); 3144 return; 3145 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 3146 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3147 true); 3148 if (error) { 3149 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " + 3150 Twine(error) + " for opcode at: 0x" + 3151 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3152 moveToEnd(); 3153 return; 3154 } 3155 Skip = readULEB128(&error); 3156 if (error) { 3157 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " + 3158 Twine(error) + " for opcode at: 0x" + 3159 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3160 moveToEnd(); 3161 return; 3162 } 3163 AdvanceAmount = Skip + PointerSize; 3164 Count = 1; 3165 RemainingLoopCount = 0; 3166 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3167 SegmentIndex, SegmentOffset); 3168 if (error) { 3169 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " + 3170 Twine(error) + " for opcode at: 0x" + 3171 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3172 moveToEnd(); 3173 return; 3174 } 3175 DEBUG_WITH_TYPE( 3176 "mach-o-rebase", 3177 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 3178 << format("SegmentOffset=0x%06X", SegmentOffset) 3179 << ", AdvanceAmount=" << AdvanceAmount 3180 << ", RemainingLoopCount=" << RemainingLoopCount 3181 << "\n"); 3182 return; 3183 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 3184 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3185 true); 3186 if (error) { 3187 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3188 "ULEB " + 3189 Twine(error) + " for opcode at: 0x" + 3190 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3191 moveToEnd(); 3192 return; 3193 } 3194 Count = readULEB128(&error); 3195 if (error) { 3196 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3197 "ULEB " + 3198 Twine(error) + " for opcode at: 0x" + 3199 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3200 moveToEnd(); 3201 return; 3202 } 3203 if (Count != 0) 3204 RemainingLoopCount = Count - 1; 3205 else 3206 RemainingLoopCount = 0; 3207 Skip = readULEB128(&error); 3208 if (error) { 3209 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3210 "ULEB " + 3211 Twine(error) + " for opcode at: 0x" + 3212 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3213 moveToEnd(); 3214 return; 3215 } 3216 AdvanceAmount = Skip + PointerSize; 3217 3218 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3219 SegmentIndex, SegmentOffset); 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 DEBUG_WITH_TYPE( 3229 "mach-o-rebase", 3230 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 3231 << format("SegmentOffset=0x%06X", SegmentOffset) 3232 << ", AdvanceAmount=" << AdvanceAmount 3233 << ", RemainingLoopCount=" << RemainingLoopCount 3234 << "\n"); 3235 return; 3236 default: 3237 *E = malformedError("bad rebase info (bad opcode value 0x" + 3238 Twine::utohexstr(Opcode) + " for opcode at: 0x" + 3239 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3240 moveToEnd(); 3241 return; 3242 } 3243 } 3244 } 3245 3246 uint64_t MachORebaseEntry::readULEB128(const char **error) { 3247 unsigned Count; 3248 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error); 3249 Ptr += Count; 3250 if (Ptr > Opcodes.end()) 3251 Ptr = Opcodes.end(); 3252 return Result; 3253 } 3254 3255 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 3256 3257 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 3258 3259 StringRef MachORebaseEntry::typeName() const { 3260 switch (RebaseType) { 3261 case MachO::REBASE_TYPE_POINTER: 3262 return "pointer"; 3263 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 3264 return "text abs32"; 3265 case MachO::REBASE_TYPE_TEXT_PCREL32: 3266 return "text rel32"; 3267 } 3268 return "unknown"; 3269 } 3270 3271 // For use with the SegIndex of a checked Mach-O Rebase entry 3272 // to get the segment name. 3273 StringRef MachORebaseEntry::segmentName() const { 3274 return O->BindRebaseSegmentName(SegmentIndex); 3275 } 3276 3277 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry 3278 // to get the section name. 3279 StringRef MachORebaseEntry::sectionName() const { 3280 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset); 3281 } 3282 3283 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry 3284 // to get the address. 3285 uint64_t MachORebaseEntry::address() const { 3286 return O->BindRebaseAddress(SegmentIndex, SegmentOffset); 3287 } 3288 3289 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 3290 #ifdef EXPENSIVE_CHECKS 3291 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 3292 #else 3293 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files"); 3294 #endif 3295 return (Ptr == Other.Ptr) && 3296 (RemainingLoopCount == Other.RemainingLoopCount) && 3297 (Done == Other.Done); 3298 } 3299 3300 iterator_range<rebase_iterator> 3301 MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O, 3302 ArrayRef<uint8_t> Opcodes, bool is64) { 3303 if (O->BindRebaseSectionTable == nullptr) 3304 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O); 3305 MachORebaseEntry Start(&Err, O, Opcodes, is64); 3306 Start.moveToFirst(); 3307 3308 MachORebaseEntry Finish(&Err, O, Opcodes, is64); 3309 Finish.moveToEnd(); 3310 3311 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 3312 } 3313 3314 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) { 3315 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit()); 3316 } 3317 3318 MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O, 3319 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 3320 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), 3321 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {} 3322 3323 void MachOBindEntry::moveToFirst() { 3324 Ptr = Opcodes.begin(); 3325 moveNext(); 3326 } 3327 3328 void MachOBindEntry::moveToEnd() { 3329 Ptr = Opcodes.end(); 3330 RemainingLoopCount = 0; 3331 Done = true; 3332 } 3333 3334 void MachOBindEntry::moveNext() { 3335 ErrorAsOutParameter ErrAsOutParam(E); 3336 // If in the middle of some loop, move to next binding in loop. 3337 SegmentOffset += AdvanceAmount; 3338 if (RemainingLoopCount) { 3339 --RemainingLoopCount; 3340 return; 3341 } 3342 // BIND_OPCODE_DONE is only used for padding if we are not aligned to 3343 // pointer size. Therefore it is possible to reach the end without ever having 3344 // seen BIND_OPCODE_DONE. 3345 if (Ptr == Opcodes.end()) { 3346 Done = true; 3347 return; 3348 } 3349 bool More = true; 3350 while (More) { 3351 // Parse next opcode and set up next loop. 3352 const uint8_t *OpcodeStart = Ptr; 3353 uint8_t Byte = *Ptr++; 3354 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 3355 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 3356 int8_t SignExtended; 3357 const uint8_t *SymStart; 3358 uint32_t Count, Skip; 3359 const char *error = nullptr; 3360 switch (Opcode) { 3361 case MachO::BIND_OPCODE_DONE: 3362 if (TableKind == Kind::Lazy) { 3363 // Lazying bindings have a DONE opcode between entries. Need to ignore 3364 // it to advance to next entry. But need not if this is last entry. 3365 bool NotLastEntry = false; 3366 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 3367 if (*P) { 3368 NotLastEntry = true; 3369 } 3370 } 3371 if (NotLastEntry) 3372 break; 3373 } 3374 More = false; 3375 moveToEnd(); 3376 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n"); 3377 break; 3378 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 3379 if (TableKind == Kind::Weak) { 3380 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in " 3381 "weak bind table for opcode at: 0x" + 3382 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3383 moveToEnd(); 3384 return; 3385 } 3386 Ordinal = ImmValue; 3387 LibraryOrdinalSet = true; 3388 if (ImmValue > O->getLibraryCount()) { 3389 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad " 3390 "library ordinal: " + 3391 Twine((int)ImmValue) + " (max " + 3392 Twine((int)O->getLibraryCount()) + 3393 ") for opcode at: 0x" + 3394 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3395 moveToEnd(); 3396 return; 3397 } 3398 DEBUG_WITH_TYPE( 3399 "mach-o-bind", 3400 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 3401 << "Ordinal=" << Ordinal << "\n"); 3402 break; 3403 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 3404 if (TableKind == Kind::Weak) { 3405 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in " 3406 "weak bind table for opcode at: 0x" + 3407 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3408 moveToEnd(); 3409 return; 3410 } 3411 Ordinal = readULEB128(&error); 3412 LibraryOrdinalSet = true; 3413 if (error) { 3414 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " + 3415 Twine(error) + " for opcode at: 0x" + 3416 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3417 moveToEnd(); 3418 return; 3419 } 3420 if (Ordinal > (int)O->getLibraryCount()) { 3421 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad " 3422 "library ordinal: " + 3423 Twine((int)Ordinal) + " (max " + 3424 Twine((int)O->getLibraryCount()) + 3425 ") for opcode at: 0x" + 3426 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3427 moveToEnd(); 3428 return; 3429 } 3430 DEBUG_WITH_TYPE( 3431 "mach-o-bind", 3432 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 3433 << "Ordinal=" << Ordinal << "\n"); 3434 break; 3435 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 3436 if (TableKind == Kind::Weak) { 3437 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in " 3438 "weak bind table for opcode at: 0x" + 3439 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3440 moveToEnd(); 3441 return; 3442 } 3443 if (ImmValue) { 3444 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 3445 Ordinal = SignExtended; 3446 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) { 3447 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown " 3448 "special ordinal: " + 3449 Twine((int)Ordinal) + " for opcode at: 0x" + 3450 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3451 moveToEnd(); 3452 return; 3453 } 3454 } else 3455 Ordinal = 0; 3456 LibraryOrdinalSet = true; 3457 DEBUG_WITH_TYPE( 3458 "mach-o-bind", 3459 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 3460 << "Ordinal=" << Ordinal << "\n"); 3461 break; 3462 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 3463 Flags = ImmValue; 3464 SymStart = Ptr; 3465 while (*Ptr && (Ptr < Opcodes.end())) { 3466 ++Ptr; 3467 } 3468 if (Ptr == Opcodes.end()) { 3469 *E = malformedError( 3470 "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM " 3471 "symbol name extends past opcodes for opcode at: 0x" + 3472 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3473 moveToEnd(); 3474 return; 3475 } 3476 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 3477 Ptr-SymStart); 3478 ++Ptr; 3479 DEBUG_WITH_TYPE( 3480 "mach-o-bind", 3481 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 3482 << "SymbolName=" << SymbolName << "\n"); 3483 if (TableKind == Kind::Weak) { 3484 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 3485 return; 3486 } 3487 break; 3488 case MachO::BIND_OPCODE_SET_TYPE_IMM: 3489 BindType = ImmValue; 3490 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) { 3491 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " + 3492 Twine((int)ImmValue) + " for opcode at: 0x" + 3493 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3494 moveToEnd(); 3495 return; 3496 } 3497 DEBUG_WITH_TYPE( 3498 "mach-o-bind", 3499 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 3500 << "BindType=" << (int)BindType << "\n"); 3501 break; 3502 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 3503 Addend = readSLEB128(&error); 3504 if (error) { 3505 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) + 3506 " for opcode at: 0x" + 3507 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3508 moveToEnd(); 3509 return; 3510 } 3511 DEBUG_WITH_TYPE( 3512 "mach-o-bind", 3513 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 3514 << "Addend=" << Addend << "\n"); 3515 break; 3516 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 3517 SegmentIndex = ImmValue; 3518 SegmentOffset = readULEB128(&error); 3519 if (error) { 3520 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 3521 Twine(error) + " for opcode at: 0x" + 3522 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3523 moveToEnd(); 3524 return; 3525 } 3526 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3527 if (error) { 3528 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 3529 Twine(error) + " for opcode at: 0x" + 3530 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3531 moveToEnd(); 3532 return; 3533 } 3534 DEBUG_WITH_TYPE( 3535 "mach-o-bind", 3536 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 3537 << "SegmentIndex=" << SegmentIndex << ", " 3538 << format("SegmentOffset=0x%06X", SegmentOffset) 3539 << "\n"); 3540 break; 3541 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 3542 SegmentOffset += readULEB128(&error); 3543 if (error) { 3544 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) + 3545 " for opcode at: 0x" + 3546 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3547 moveToEnd(); 3548 return; 3549 } 3550 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3551 if (error) { 3552 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) + 3553 " for opcode at: 0x" + 3554 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3555 moveToEnd(); 3556 return; 3557 } 3558 DEBUG_WITH_TYPE("mach-o-bind", 3559 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 3560 << format("SegmentOffset=0x%06X", 3561 SegmentOffset) << "\n"); 3562 break; 3563 case MachO::BIND_OPCODE_DO_BIND: 3564 AdvanceAmount = PointerSize; 3565 RemainingLoopCount = 0; 3566 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3567 if (error) { 3568 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) + 3569 " for opcode at: 0x" + 3570 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3571 moveToEnd(); 3572 return; 3573 } 3574 if (SymbolName == StringRef()) { 3575 *E = malformedError( 3576 "for BIND_OPCODE_DO_BIND missing preceding " 3577 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" + 3578 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3579 moveToEnd(); 3580 return; 3581 } 3582 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3583 *E = 3584 malformedError("for BIND_OPCODE_DO_BIND missing preceding " 3585 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" + 3586 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3587 moveToEnd(); 3588 return; 3589 } 3590 DEBUG_WITH_TYPE("mach-o-bind", 3591 dbgs() << "BIND_OPCODE_DO_BIND: " 3592 << format("SegmentOffset=0x%06X", 3593 SegmentOffset) << "\n"); 3594 return; 3595 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 3596 if (TableKind == Kind::Lazy) { 3597 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in " 3598 "lazy bind table for opcode at: 0x" + 3599 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3600 moveToEnd(); 3601 return; 3602 } 3603 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3604 if (error) { 3605 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " + 3606 Twine(error) + " for opcode at: 0x" + 3607 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3608 moveToEnd(); 3609 return; 3610 } 3611 if (SymbolName == StringRef()) { 3612 *E = malformedError( 3613 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing " 3614 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode " 3615 "at: 0x" + 3616 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3617 moveToEnd(); 3618 return; 3619 } 3620 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3621 *E = malformedError( 3622 "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing " 3623 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" + 3624 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3625 moveToEnd(); 3626 return; 3627 } 3628 AdvanceAmount = readULEB128(&error) + PointerSize; 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 // Note, this is not really an error until the next bind but make no sense 3637 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another 3638 // bind operation. 3639 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset + 3640 AdvanceAmount, false); 3641 if (error) { 3642 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding " 3643 "ULEB) " + 3644 Twine(error) + " for opcode at: 0x" + 3645 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3646 moveToEnd(); 3647 return; 3648 } 3649 RemainingLoopCount = 0; 3650 DEBUG_WITH_TYPE( 3651 "mach-o-bind", 3652 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 3653 << format("SegmentOffset=0x%06X", SegmentOffset) 3654 << ", AdvanceAmount=" << AdvanceAmount 3655 << ", RemainingLoopCount=" << RemainingLoopCount 3656 << "\n"); 3657 return; 3658 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 3659 if (TableKind == Kind::Lazy) { 3660 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not " 3661 "allowed in lazy bind table for opcode at: 0x" + 3662 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3663 moveToEnd(); 3664 return; 3665 } 3666 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3667 if (error) { 3668 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " + 3669 Twine(error) + " for opcode at: 0x" + 3670 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3671 moveToEnd(); 3672 return; 3673 } 3674 if (SymbolName == StringRef()) { 3675 *E = malformedError( 3676 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " 3677 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for " 3678 "opcode at: 0x" + 3679 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3680 moveToEnd(); 3681 return; 3682 } 3683 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3684 *E = malformedError( 3685 "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " 3686 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode " 3687 "at: 0x" + 3688 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3689 moveToEnd(); 3690 return; 3691 } 3692 AdvanceAmount = ImmValue * PointerSize + PointerSize; 3693 RemainingLoopCount = 0; 3694 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset + 3695 AdvanceAmount, false); 3696 if (error) { 3697 *E = 3698 malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " 3699 " (after adding immediate times the pointer size) " + 3700 Twine(error) + " for opcode at: 0x" + 3701 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3702 moveToEnd(); 3703 return; 3704 } 3705 DEBUG_WITH_TYPE("mach-o-bind", 3706 dbgs() 3707 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 3708 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n"); 3709 return; 3710 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 3711 if (TableKind == Kind::Lazy) { 3712 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not " 3713 "allowed in lazy bind table for opcode at: 0x" + 3714 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3715 moveToEnd(); 3716 return; 3717 } 3718 Count = readULEB128(&error); 3719 if (Count != 0) 3720 RemainingLoopCount = Count - 1; 3721 else 3722 RemainingLoopCount = 0; 3723 if (error) { 3724 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3725 " (count value) " + 3726 Twine(error) + " for opcode at: 0x" + 3727 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3728 moveToEnd(); 3729 return; 3730 } 3731 Skip = readULEB128(&error); 3732 AdvanceAmount = Skip + PointerSize; 3733 if (error) { 3734 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3735 " (skip value) " + 3736 Twine(error) + " for opcode at: 0x" + 3737 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3738 moveToEnd(); 3739 return; 3740 } 3741 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3742 if (error) { 3743 *E = 3744 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " + 3745 Twine(error) + " for opcode at: 0x" + 3746 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3747 moveToEnd(); 3748 return; 3749 } 3750 if (SymbolName == StringRef()) { 3751 *E = malformedError( 3752 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3753 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for " 3754 "opcode at: 0x" + 3755 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3756 moveToEnd(); 3757 return; 3758 } 3759 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3760 *E = malformedError( 3761 "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3762 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode " 3763 "at: 0x" + 3764 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3765 moveToEnd(); 3766 return; 3767 } 3768 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize, 3769 SegmentIndex, SegmentOffset); 3770 if (error) { 3771 *E = 3772 malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " + 3773 Twine(error) + " for opcode at: 0x" + 3774 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3775 moveToEnd(); 3776 return; 3777 } 3778 DEBUG_WITH_TYPE( 3779 "mach-o-bind", 3780 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 3781 << format("SegmentOffset=0x%06X", SegmentOffset) 3782 << ", AdvanceAmount=" << AdvanceAmount 3783 << ", RemainingLoopCount=" << RemainingLoopCount 3784 << "\n"); 3785 return; 3786 default: 3787 *E = malformedError("bad bind info (bad opcode value 0x" + 3788 Twine::utohexstr(Opcode) + " for opcode at: 0x" + 3789 Twine::utohexstr(OpcodeStart - Opcodes.begin())); 3790 moveToEnd(); 3791 return; 3792 } 3793 } 3794 } 3795 3796 uint64_t MachOBindEntry::readULEB128(const char **error) { 3797 unsigned Count; 3798 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error); 3799 Ptr += Count; 3800 if (Ptr > Opcodes.end()) 3801 Ptr = Opcodes.end(); 3802 return Result; 3803 } 3804 3805 int64_t MachOBindEntry::readSLEB128(const char **error) { 3806 unsigned Count; 3807 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error); 3808 Ptr += Count; 3809 if (Ptr > Opcodes.end()) 3810 Ptr = Opcodes.end(); 3811 return Result; 3812 } 3813 3814 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 3815 3816 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 3817 3818 StringRef MachOBindEntry::typeName() const { 3819 switch (BindType) { 3820 case MachO::BIND_TYPE_POINTER: 3821 return "pointer"; 3822 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 3823 return "text abs32"; 3824 case MachO::BIND_TYPE_TEXT_PCREL32: 3825 return "text rel32"; 3826 } 3827 return "unknown"; 3828 } 3829 3830 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 3831 3832 int64_t MachOBindEntry::addend() const { return Addend; } 3833 3834 uint32_t MachOBindEntry::flags() const { return Flags; } 3835 3836 int MachOBindEntry::ordinal() const { return Ordinal; } 3837 3838 // For use with the SegIndex of a checked Mach-O Bind entry 3839 // to get the segment name. 3840 StringRef MachOBindEntry::segmentName() const { 3841 return O->BindRebaseSegmentName(SegmentIndex); 3842 } 3843 3844 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry 3845 // to get the section name. 3846 StringRef MachOBindEntry::sectionName() const { 3847 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset); 3848 } 3849 3850 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry 3851 // to get the address. 3852 uint64_t MachOBindEntry::address() const { 3853 return O->BindRebaseAddress(SegmentIndex, SegmentOffset); 3854 } 3855 3856 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 3857 #ifdef EXPENSIVE_CHECKS 3858 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 3859 #else 3860 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files"); 3861 #endif 3862 return (Ptr == Other.Ptr) && 3863 (RemainingLoopCount == Other.RemainingLoopCount) && 3864 (Done == Other.Done); 3865 } 3866 3867 // Build table of sections so SegIndex/SegOffset pairs can be translated. 3868 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) { 3869 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0; 3870 StringRef CurSegName; 3871 uint64_t CurSegAddress; 3872 for (const SectionRef &Section : Obj->sections()) { 3873 SectionInfo Info; 3874 Section.getName(Info.SectionName); 3875 Info.Address = Section.getAddress(); 3876 Info.Size = Section.getSize(); 3877 Info.SegmentName = 3878 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl()); 3879 if (!Info.SegmentName.equals(CurSegName)) { 3880 ++CurSegIndex; 3881 CurSegName = Info.SegmentName; 3882 CurSegAddress = Info.Address; 3883 } 3884 Info.SegmentIndex = CurSegIndex - 1; 3885 Info.OffsetInSegment = Info.Address - CurSegAddress; 3886 Info.SegmentStartAddress = CurSegAddress; 3887 Sections.push_back(Info); 3888 } 3889 MaxSegIndex = CurSegIndex; 3890 } 3891 3892 // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to 3893 // validate a MachOBindEntry or MachORebaseEntry. 3894 const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex, 3895 uint64_t SegOffset, 3896 bool endInvalid) { 3897 if (SegIndex == -1) 3898 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"; 3899 if (SegIndex >= MaxSegIndex) 3900 return "bad segIndex (too large)"; 3901 for (const SectionInfo &SI : Sections) { 3902 if (SI.SegmentIndex != SegIndex) 3903 continue; 3904 if (SI.OffsetInSegment > SegOffset) 3905 continue; 3906 if (SegOffset > (SI.OffsetInSegment + SI.Size)) 3907 continue; 3908 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size)) 3909 continue; 3910 return nullptr; 3911 } 3912 return "bad segOffset, too large"; 3913 } 3914 3915 // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for 3916 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in 3917 // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for 3918 // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have 3919 // been already checked. 3920 const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip, 3921 uint8_t PointerSize, 3922 int32_t SegIndex, 3923 uint64_t SegOffset) { 3924 const SectionInfo &SI = findSection(SegIndex, SegOffset); 3925 uint64_t addr = SI.SegmentStartAddress + SegOffset; 3926 if (addr >= SI.Address + SI.Size) 3927 return "bad segOffset, too large"; 3928 uint64_t i = 0; 3929 if (Count > 1) 3930 i = (Skip + PointerSize) * (Count - 1); 3931 else if (Count == 1) 3932 i = Skip + PointerSize; 3933 if (addr + i >= SI.Address + SI.Size) { 3934 // For rebase opcodes they can step from one section to another. 3935 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress; 3936 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false); 3937 if (error) 3938 return "bad count and skip, too large"; 3939 } 3940 return nullptr; 3941 } 3942 3943 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry 3944 // to get the segment name. 3945 StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) { 3946 for (const SectionInfo &SI : Sections) { 3947 if (SI.SegmentIndex == SegIndex) 3948 return SI.SegmentName; 3949 } 3950 llvm_unreachable("invalid SegIndex"); 3951 } 3952 3953 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase 3954 // to get the SectionInfo. 3955 const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection( 3956 int32_t SegIndex, uint64_t SegOffset) { 3957 for (const SectionInfo &SI : Sections) { 3958 if (SI.SegmentIndex != SegIndex) 3959 continue; 3960 if (SI.OffsetInSegment > SegOffset) 3961 continue; 3962 if (SegOffset >= (SI.OffsetInSegment + SI.Size)) 3963 continue; 3964 return SI; 3965 } 3966 llvm_unreachable("SegIndex and SegOffset not in any section"); 3967 } 3968 3969 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase 3970 // entry to get the section name. 3971 StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex, 3972 uint64_t SegOffset) { 3973 return findSection(SegIndex, SegOffset).SectionName; 3974 } 3975 3976 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase 3977 // entry to get the address. 3978 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) { 3979 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg); 3980 return SI.SegmentStartAddress + OffsetInSeg; 3981 } 3982 3983 iterator_range<bind_iterator> 3984 MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O, 3985 ArrayRef<uint8_t> Opcodes, bool is64, 3986 MachOBindEntry::Kind BKind) { 3987 if (O->BindRebaseSectionTable == nullptr) 3988 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O); 3989 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind); 3990 Start.moveToFirst(); 3991 3992 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind); 3993 Finish.moveToEnd(); 3994 3995 return make_range(bind_iterator(Start), bind_iterator(Finish)); 3996 } 3997 3998 iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) { 3999 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(), 4000 MachOBindEntry::Kind::Regular); 4001 } 4002 4003 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) { 4004 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(), 4005 MachOBindEntry::Kind::Lazy); 4006 } 4007 4008 iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) { 4009 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(), 4010 MachOBindEntry::Kind::Weak); 4011 } 4012 4013 MachOObjectFile::load_command_iterator 4014 MachOObjectFile::begin_load_commands() const { 4015 return LoadCommands.begin(); 4016 } 4017 4018 MachOObjectFile::load_command_iterator 4019 MachOObjectFile::end_load_commands() const { 4020 return LoadCommands.end(); 4021 } 4022 4023 iterator_range<MachOObjectFile::load_command_iterator> 4024 MachOObjectFile::load_commands() const { 4025 return make_range(begin_load_commands(), end_load_commands()); 4026 } 4027 4028 StringRef 4029 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 4030 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 4031 return parseSegmentOrSectionName(Raw.data()); 4032 } 4033 4034 ArrayRef<char> 4035 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 4036 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 4037 const section_base *Base = 4038 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 4039 return makeArrayRef(Base->sectname); 4040 } 4041 4042 ArrayRef<char> 4043 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 4044 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 4045 const section_base *Base = 4046 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 4047 return makeArrayRef(Base->segname); 4048 } 4049 4050 bool 4051 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 4052 const { 4053 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64) 4054 return false; 4055 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 4056 } 4057 4058 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 4059 const MachO::any_relocation_info &RE) const { 4060 if (isLittleEndian()) 4061 return RE.r_word1 & 0xffffff; 4062 return RE.r_word1 >> 8; 4063 } 4064 4065 bool MachOObjectFile::getPlainRelocationExternal( 4066 const MachO::any_relocation_info &RE) const { 4067 if (isLittleEndian()) 4068 return (RE.r_word1 >> 27) & 1; 4069 return (RE.r_word1 >> 4) & 1; 4070 } 4071 4072 bool MachOObjectFile::getScatteredRelocationScattered( 4073 const MachO::any_relocation_info &RE) const { 4074 return RE.r_word0 >> 31; 4075 } 4076 4077 uint32_t MachOObjectFile::getScatteredRelocationValue( 4078 const MachO::any_relocation_info &RE) const { 4079 return RE.r_word1; 4080 } 4081 4082 uint32_t MachOObjectFile::getScatteredRelocationType( 4083 const MachO::any_relocation_info &RE) const { 4084 return (RE.r_word0 >> 24) & 0xf; 4085 } 4086 4087 unsigned MachOObjectFile::getAnyRelocationAddress( 4088 const MachO::any_relocation_info &RE) const { 4089 if (isRelocationScattered(RE)) 4090 return getScatteredRelocationAddress(RE); 4091 return getPlainRelocationAddress(RE); 4092 } 4093 4094 unsigned MachOObjectFile::getAnyRelocationPCRel( 4095 const MachO::any_relocation_info &RE) const { 4096 if (isRelocationScattered(RE)) 4097 return getScatteredRelocationPCRel(RE); 4098 return getPlainRelocationPCRel(*this, RE); 4099 } 4100 4101 unsigned MachOObjectFile::getAnyRelocationLength( 4102 const MachO::any_relocation_info &RE) const { 4103 if (isRelocationScattered(RE)) 4104 return getScatteredRelocationLength(RE); 4105 return getPlainRelocationLength(*this, RE); 4106 } 4107 4108 unsigned 4109 MachOObjectFile::getAnyRelocationType( 4110 const MachO::any_relocation_info &RE) const { 4111 if (isRelocationScattered(RE)) 4112 return getScatteredRelocationType(RE); 4113 return getPlainRelocationType(*this, RE); 4114 } 4115 4116 SectionRef 4117 MachOObjectFile::getAnyRelocationSection( 4118 const MachO::any_relocation_info &RE) const { 4119 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 4120 return *section_end(); 4121 unsigned SecNum = getPlainRelocationSymbolNum(RE); 4122 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 4123 return *section_end(); 4124 DataRefImpl DRI; 4125 DRI.d.a = SecNum - 1; 4126 return SectionRef(DRI, this); 4127 } 4128 4129 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 4130 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 4131 return getStruct<MachO::section>(*this, Sections[DRI.d.a]); 4132 } 4133 4134 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 4135 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 4136 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]); 4137 } 4138 4139 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 4140 unsigned Index) const { 4141 const char *Sec = getSectionPtr(*this, L, Index); 4142 return getStruct<MachO::section>(*this, Sec); 4143 } 4144 4145 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 4146 unsigned Index) const { 4147 const char *Sec = getSectionPtr(*this, L, Index); 4148 return getStruct<MachO::section_64>(*this, Sec); 4149 } 4150 4151 MachO::nlist 4152 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 4153 const char *P = reinterpret_cast<const char *>(DRI.p); 4154 return getStruct<MachO::nlist>(*this, P); 4155 } 4156 4157 MachO::nlist_64 4158 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 4159 const char *P = reinterpret_cast<const char *>(DRI.p); 4160 return getStruct<MachO::nlist_64>(*this, P); 4161 } 4162 4163 MachO::linkedit_data_command 4164 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 4165 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr); 4166 } 4167 4168 MachO::segment_command 4169 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 4170 return getStruct<MachO::segment_command>(*this, L.Ptr); 4171 } 4172 4173 MachO::segment_command_64 4174 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 4175 return getStruct<MachO::segment_command_64>(*this, L.Ptr); 4176 } 4177 4178 MachO::linker_option_command 4179 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 4180 return getStruct<MachO::linker_option_command>(*this, L.Ptr); 4181 } 4182 4183 MachO::version_min_command 4184 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 4185 return getStruct<MachO::version_min_command>(*this, L.Ptr); 4186 } 4187 4188 MachO::note_command 4189 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const { 4190 return getStruct<MachO::note_command>(*this, L.Ptr); 4191 } 4192 4193 MachO::build_version_command 4194 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const { 4195 return getStruct<MachO::build_version_command>(*this, L.Ptr); 4196 } 4197 4198 MachO::build_tool_version 4199 MachOObjectFile::getBuildToolVersion(unsigned index) const { 4200 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]); 4201 } 4202 4203 MachO::dylib_command 4204 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 4205 return getStruct<MachO::dylib_command>(*this, L.Ptr); 4206 } 4207 4208 MachO::dyld_info_command 4209 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 4210 return getStruct<MachO::dyld_info_command>(*this, L.Ptr); 4211 } 4212 4213 MachO::dylinker_command 4214 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 4215 return getStruct<MachO::dylinker_command>(*this, L.Ptr); 4216 } 4217 4218 MachO::uuid_command 4219 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 4220 return getStruct<MachO::uuid_command>(*this, L.Ptr); 4221 } 4222 4223 MachO::rpath_command 4224 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 4225 return getStruct<MachO::rpath_command>(*this, L.Ptr); 4226 } 4227 4228 MachO::source_version_command 4229 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 4230 return getStruct<MachO::source_version_command>(*this, L.Ptr); 4231 } 4232 4233 MachO::entry_point_command 4234 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 4235 return getStruct<MachO::entry_point_command>(*this, L.Ptr); 4236 } 4237 4238 MachO::encryption_info_command 4239 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 4240 return getStruct<MachO::encryption_info_command>(*this, L.Ptr); 4241 } 4242 4243 MachO::encryption_info_command_64 4244 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 4245 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr); 4246 } 4247 4248 MachO::sub_framework_command 4249 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 4250 return getStruct<MachO::sub_framework_command>(*this, L.Ptr); 4251 } 4252 4253 MachO::sub_umbrella_command 4254 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 4255 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr); 4256 } 4257 4258 MachO::sub_library_command 4259 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 4260 return getStruct<MachO::sub_library_command>(*this, L.Ptr); 4261 } 4262 4263 MachO::sub_client_command 4264 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 4265 return getStruct<MachO::sub_client_command>(*this, L.Ptr); 4266 } 4267 4268 MachO::routines_command 4269 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 4270 return getStruct<MachO::routines_command>(*this, L.Ptr); 4271 } 4272 4273 MachO::routines_command_64 4274 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 4275 return getStruct<MachO::routines_command_64>(*this, L.Ptr); 4276 } 4277 4278 MachO::thread_command 4279 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 4280 return getStruct<MachO::thread_command>(*this, L.Ptr); 4281 } 4282 4283 MachO::any_relocation_info 4284 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 4285 uint32_t Offset; 4286 if (getHeader().filetype == MachO::MH_OBJECT) { 4287 DataRefImpl Sec; 4288 Sec.d.a = Rel.d.a; 4289 if (is64Bit()) { 4290 MachO::section_64 Sect = getSection64(Sec); 4291 Offset = Sect.reloff; 4292 } else { 4293 MachO::section Sect = getSection(Sec); 4294 Offset = Sect.reloff; 4295 } 4296 } else { 4297 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); 4298 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations 4299 } 4300 4301 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 4302 getPtr(*this, Offset)) + Rel.d.b; 4303 return getStruct<MachO::any_relocation_info>( 4304 *this, reinterpret_cast<const char *>(P)); 4305 } 4306 4307 MachO::data_in_code_entry 4308 MachOObjectFile::getDice(DataRefImpl Rel) const { 4309 const char *P = reinterpret_cast<const char *>(Rel.p); 4310 return getStruct<MachO::data_in_code_entry>(*this, P); 4311 } 4312 4313 const MachO::mach_header &MachOObjectFile::getHeader() const { 4314 return Header; 4315 } 4316 4317 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 4318 assert(is64Bit()); 4319 return Header64; 4320 } 4321 4322 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 4323 const MachO::dysymtab_command &DLC, 4324 unsigned Index) const { 4325 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 4326 return getStruct<uint32_t>(*this, getPtr(*this, Offset)); 4327 } 4328 4329 MachO::data_in_code_entry 4330 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 4331 unsigned Index) const { 4332 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 4333 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset)); 4334 } 4335 4336 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 4337 if (SymtabLoadCmd) 4338 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd); 4339 4340 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 4341 MachO::symtab_command Cmd; 4342 Cmd.cmd = MachO::LC_SYMTAB; 4343 Cmd.cmdsize = sizeof(MachO::symtab_command); 4344 Cmd.symoff = 0; 4345 Cmd.nsyms = 0; 4346 Cmd.stroff = 0; 4347 Cmd.strsize = 0; 4348 return Cmd; 4349 } 4350 4351 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 4352 if (DysymtabLoadCmd) 4353 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd); 4354 4355 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 4356 MachO::dysymtab_command Cmd; 4357 Cmd.cmd = MachO::LC_DYSYMTAB; 4358 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 4359 Cmd.ilocalsym = 0; 4360 Cmd.nlocalsym = 0; 4361 Cmd.iextdefsym = 0; 4362 Cmd.nextdefsym = 0; 4363 Cmd.iundefsym = 0; 4364 Cmd.nundefsym = 0; 4365 Cmd.tocoff = 0; 4366 Cmd.ntoc = 0; 4367 Cmd.modtaboff = 0; 4368 Cmd.nmodtab = 0; 4369 Cmd.extrefsymoff = 0; 4370 Cmd.nextrefsyms = 0; 4371 Cmd.indirectsymoff = 0; 4372 Cmd.nindirectsyms = 0; 4373 Cmd.extreloff = 0; 4374 Cmd.nextrel = 0; 4375 Cmd.locreloff = 0; 4376 Cmd.nlocrel = 0; 4377 return Cmd; 4378 } 4379 4380 MachO::linkedit_data_command 4381 MachOObjectFile::getDataInCodeLoadCommand() const { 4382 if (DataInCodeLoadCmd) 4383 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd); 4384 4385 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 4386 MachO::linkedit_data_command Cmd; 4387 Cmd.cmd = MachO::LC_DATA_IN_CODE; 4388 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 4389 Cmd.dataoff = 0; 4390 Cmd.datasize = 0; 4391 return Cmd; 4392 } 4393 4394 MachO::linkedit_data_command 4395 MachOObjectFile::getLinkOptHintsLoadCommand() const { 4396 if (LinkOptHintsLoadCmd) 4397 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd); 4398 4399 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 4400 // fields. 4401 MachO::linkedit_data_command Cmd; 4402 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 4403 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 4404 Cmd.dataoff = 0; 4405 Cmd.datasize = 0; 4406 return Cmd; 4407 } 4408 4409 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 4410 if (!DyldInfoLoadCmd) 4411 return None; 4412 4413 MachO::dyld_info_command DyldInfo = 4414 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4415 const uint8_t *Ptr = 4416 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off)); 4417 return makeArrayRef(Ptr, DyldInfo.rebase_size); 4418 } 4419 4420 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 4421 if (!DyldInfoLoadCmd) 4422 return None; 4423 4424 MachO::dyld_info_command DyldInfo = 4425 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4426 const uint8_t *Ptr = 4427 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off)); 4428 return makeArrayRef(Ptr, DyldInfo.bind_size); 4429 } 4430 4431 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 4432 if (!DyldInfoLoadCmd) 4433 return None; 4434 4435 MachO::dyld_info_command DyldInfo = 4436 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4437 const uint8_t *Ptr = 4438 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off)); 4439 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 4440 } 4441 4442 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 4443 if (!DyldInfoLoadCmd) 4444 return None; 4445 4446 MachO::dyld_info_command DyldInfo = 4447 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4448 const uint8_t *Ptr = 4449 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off)); 4450 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 4451 } 4452 4453 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 4454 if (!DyldInfoLoadCmd) 4455 return None; 4456 4457 MachO::dyld_info_command DyldInfo = 4458 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4459 const uint8_t *Ptr = 4460 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off)); 4461 return makeArrayRef(Ptr, DyldInfo.export_size); 4462 } 4463 4464 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 4465 if (!UuidLoadCmd) 4466 return None; 4467 // Returning a pointer is fine as uuid doesn't need endian swapping. 4468 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 4469 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 4470 } 4471 4472 StringRef MachOObjectFile::getStringTableData() const { 4473 MachO::symtab_command S = getSymtabLoadCommand(); 4474 return getData().substr(S.stroff, S.strsize); 4475 } 4476 4477 bool MachOObjectFile::is64Bit() const { 4478 return getType() == getMachOType(false, true) || 4479 getType() == getMachOType(true, true); 4480 } 4481 4482 void MachOObjectFile::ReadULEB128s(uint64_t Index, 4483 SmallVectorImpl<uint64_t> &Out) const { 4484 DataExtractor extractor(ObjectFile::getData(), true, 0); 4485 4486 uint32_t offset = Index; 4487 uint64_t data = 0; 4488 while (uint64_t delta = extractor.getULEB128(&offset)) { 4489 data += delta; 4490 Out.push_back(data); 4491 } 4492 } 4493 4494 bool MachOObjectFile::isRelocatableObject() const { 4495 return getHeader().filetype == MachO::MH_OBJECT; 4496 } 4497 4498 Expected<std::unique_ptr<MachOObjectFile>> 4499 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, 4500 uint32_t UniversalCputype, 4501 uint32_t UniversalIndex) { 4502 StringRef Magic = Buffer.getBuffer().slice(0, 4); 4503 if (Magic == "\xFE\xED\xFA\xCE") 4504 return MachOObjectFile::create(Buffer, false, false, 4505 UniversalCputype, UniversalIndex); 4506 if (Magic == "\xCE\xFA\xED\xFE") 4507 return MachOObjectFile::create(Buffer, true, false, 4508 UniversalCputype, UniversalIndex); 4509 if (Magic == "\xFE\xED\xFA\xCF") 4510 return MachOObjectFile::create(Buffer, false, true, 4511 UniversalCputype, UniversalIndex); 4512 if (Magic == "\xCF\xFA\xED\xFE") 4513 return MachOObjectFile::create(Buffer, true, true, 4514 UniversalCputype, UniversalIndex); 4515 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 4516 object_error::invalid_file_type); 4517 } 4518 4519 StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const { 4520 return StringSwitch<StringRef>(Name) 4521 .Case("debug_str_offs", "debug_str_offsets") 4522 .Default(Name); 4523 } 4524