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