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