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