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