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