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