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