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