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