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