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