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, 2912 const MachOObjectFile *O) const { 2913 return exports(Err, getDyldInfoExportsTrie(), O); 2914 } 2915 2916 MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O, 2917 ArrayRef<uint8_t> Bytes, bool is64Bit) 2918 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), 2919 PointerSize(is64Bit ? 8 : 4) {} 2920 2921 void MachORebaseEntry::moveToFirst() { 2922 Ptr = Opcodes.begin(); 2923 moveNext(); 2924 } 2925 2926 void MachORebaseEntry::moveToEnd() { 2927 Ptr = Opcodes.end(); 2928 RemainingLoopCount = 0; 2929 Done = true; 2930 } 2931 2932 void MachORebaseEntry::moveNext() { 2933 ErrorAsOutParameter ErrAsOutParam(E); 2934 // If in the middle of some loop, move to next rebasing in loop. 2935 SegmentOffset += AdvanceAmount; 2936 if (RemainingLoopCount) { 2937 --RemainingLoopCount; 2938 return; 2939 } 2940 // REBASE_OPCODE_DONE is only used for padding if we are not aligned to 2941 // pointer size. Therefore it is possible to reach the end without ever having 2942 // seen REBASE_OPCODE_DONE. 2943 if (Ptr == Opcodes.end()) { 2944 Done = true; 2945 return; 2946 } 2947 bool More = true; 2948 while (More) { 2949 // Parse next opcode and set up next loop. 2950 const uint8_t *OpcodeStart = Ptr; 2951 uint8_t Byte = *Ptr++; 2952 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2953 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2954 uint32_t Count, Skip; 2955 const char *error = nullptr; 2956 switch (Opcode) { 2957 case MachO::REBASE_OPCODE_DONE: 2958 More = false; 2959 Done = true; 2960 moveToEnd(); 2961 DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n"); 2962 break; 2963 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2964 RebaseType = ImmValue; 2965 if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) { 2966 *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " + 2967 Twine((int)RebaseType) + " for opcode at: 0x" + 2968 utohexstr(OpcodeStart - Opcodes.begin())); 2969 moveToEnd(); 2970 return; 2971 } 2972 DEBUG_WITH_TYPE( 2973 "mach-o-rebase", 2974 dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2975 << "RebaseType=" << (int) RebaseType << "\n"); 2976 break; 2977 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2978 SegmentIndex = ImmValue; 2979 SegmentOffset = readULEB128(&error); 2980 if (error) { 2981 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 2982 Twine(error) + " for opcode at: 0x" + 2983 utohexstr(OpcodeStart - Opcodes.begin())); 2984 moveToEnd(); 2985 return; 2986 } 2987 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 2988 true); 2989 if (error) { 2990 *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 2991 Twine(error) + " for opcode at: 0x" + 2992 utohexstr(OpcodeStart - Opcodes.begin())); 2993 moveToEnd(); 2994 return; 2995 } 2996 DEBUG_WITH_TYPE( 2997 "mach-o-rebase", 2998 dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2999 << "SegmentIndex=" << SegmentIndex << ", " 3000 << format("SegmentOffset=0x%06X", SegmentOffset) 3001 << "\n"); 3002 break; 3003 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 3004 SegmentOffset += readULEB128(&error); 3005 if (error) { 3006 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + 3007 Twine(error) + " for opcode at: 0x" + 3008 utohexstr(OpcodeStart - Opcodes.begin())); 3009 moveToEnd(); 3010 return; 3011 } 3012 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3013 true); 3014 if (error) { 3015 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + 3016 Twine(error) + " for opcode at: 0x" + 3017 utohexstr(OpcodeStart - Opcodes.begin())); 3018 moveToEnd(); 3019 return; 3020 } 3021 DEBUG_WITH_TYPE("mach-o-rebase", 3022 dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 3023 << format("SegmentOffset=0x%06X", 3024 SegmentOffset) << "\n"); 3025 break; 3026 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 3027 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3028 true); 3029 if (error) { 3030 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " + 3031 Twine(error) + " for opcode at: 0x" + 3032 utohexstr(OpcodeStart - Opcodes.begin())); 3033 moveToEnd(); 3034 return; 3035 } 3036 SegmentOffset += ImmValue * PointerSize; 3037 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3038 false); 3039 if (error) { 3040 *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " 3041 " (after adding immediate times the pointer size) " + 3042 Twine(error) + " for opcode at: 0x" + 3043 utohexstr(OpcodeStart - Opcodes.begin())); 3044 moveToEnd(); 3045 return; 3046 } 3047 DEBUG_WITH_TYPE("mach-o-rebase", 3048 dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 3049 << format("SegmentOffset=0x%06X", 3050 SegmentOffset) << "\n"); 3051 break; 3052 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 3053 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3054 true); 3055 if (error) { 3056 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " + 3057 Twine(error) + " for opcode at: 0x" + 3058 utohexstr(OpcodeStart - Opcodes.begin())); 3059 moveToEnd(); 3060 return; 3061 } 3062 AdvanceAmount = PointerSize; 3063 Skip = 0; 3064 Count = ImmValue; 3065 if (ImmValue != 0) 3066 RemainingLoopCount = ImmValue - 1; 3067 else 3068 RemainingLoopCount = 0; 3069 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3070 SegmentIndex, SegmentOffset); 3071 if (error) { 3072 *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " 3073 + Twine(error) + " for opcode at: 0x" + 3074 utohexstr(OpcodeStart - Opcodes.begin())); 3075 moveToEnd(); 3076 return; 3077 } 3078 DEBUG_WITH_TYPE( 3079 "mach-o-rebase", 3080 dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 3081 << format("SegmentOffset=0x%06X", SegmentOffset) 3082 << ", AdvanceAmount=" << AdvanceAmount 3083 << ", RemainingLoopCount=" << RemainingLoopCount 3084 << "\n"); 3085 return; 3086 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 3087 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3088 true); 3089 if (error) { 3090 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " + 3091 Twine(error) + " for opcode at: 0x" + 3092 utohexstr(OpcodeStart - Opcodes.begin())); 3093 moveToEnd(); 3094 return; 3095 } 3096 AdvanceAmount = PointerSize; 3097 Skip = 0; 3098 Count = readULEB128(&error); 3099 if (error) { 3100 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " + 3101 Twine(error) + " for opcode at: 0x" + 3102 utohexstr(OpcodeStart - Opcodes.begin())); 3103 moveToEnd(); 3104 return; 3105 } 3106 if (Count != 0) 3107 RemainingLoopCount = Count - 1; 3108 else 3109 RemainingLoopCount = 0; 3110 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3111 SegmentIndex, SegmentOffset); 3112 if (error) { 3113 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " 3114 + Twine(error) + " for opcode at: 0x" + 3115 utohexstr(OpcodeStart - Opcodes.begin())); 3116 moveToEnd(); 3117 return; 3118 } 3119 DEBUG_WITH_TYPE( 3120 "mach-o-rebase", 3121 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 3122 << format("SegmentOffset=0x%06X", SegmentOffset) 3123 << ", AdvanceAmount=" << AdvanceAmount 3124 << ", RemainingLoopCount=" << RemainingLoopCount 3125 << "\n"); 3126 return; 3127 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 3128 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3129 true); 3130 if (error) { 3131 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " + 3132 Twine(error) + " for opcode at: 0x" + 3133 utohexstr(OpcodeStart - Opcodes.begin())); 3134 moveToEnd(); 3135 return; 3136 } 3137 Skip = readULEB128(&error); 3138 if (error) { 3139 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " + 3140 Twine(error) + " for opcode at: 0x" + 3141 utohexstr(OpcodeStart - Opcodes.begin())); 3142 moveToEnd(); 3143 return; 3144 } 3145 AdvanceAmount = Skip + PointerSize; 3146 Count = 1; 3147 RemainingLoopCount = 0; 3148 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3149 SegmentIndex, SegmentOffset); 3150 if (error) { 3151 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " 3152 + Twine(error) + " for opcode at: 0x" + 3153 utohexstr(OpcodeStart - Opcodes.begin())); 3154 moveToEnd(); 3155 return; 3156 } 3157 DEBUG_WITH_TYPE( 3158 "mach-o-rebase", 3159 dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 3160 << format("SegmentOffset=0x%06X", SegmentOffset) 3161 << ", AdvanceAmount=" << AdvanceAmount 3162 << ", RemainingLoopCount=" << RemainingLoopCount 3163 << "\n"); 3164 return; 3165 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 3166 error = O->RebaseEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, 3167 true); 3168 if (error) { 3169 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3170 "ULEB " + Twine(error) + " for opcode at: 0x" + 3171 utohexstr(OpcodeStart - Opcodes.begin())); 3172 moveToEnd(); 3173 return; 3174 } 3175 Count = readULEB128(&error); 3176 if (error) { 3177 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3178 "ULEB " + Twine(error) + " for opcode at: 0x" + 3179 utohexstr(OpcodeStart - Opcodes.begin())); 3180 moveToEnd(); 3181 return; 3182 } 3183 if (Count != 0) 3184 RemainingLoopCount = Count - 1; 3185 else 3186 RemainingLoopCount = 0; 3187 Skip = readULEB128(&error); 3188 if (error) { 3189 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3190 "ULEB " + Twine(error) + " for opcode at: 0x" + 3191 utohexstr(OpcodeStart - Opcodes.begin())); 3192 moveToEnd(); 3193 return; 3194 } 3195 AdvanceAmount = Skip + PointerSize; 3196 3197 error = O->RebaseEntryCheckCountAndSkip(Count, Skip, PointerSize, 3198 SegmentIndex, SegmentOffset); 3199 if (error) { 3200 *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_" 3201 "ULEB " + Twine(error) + " for opcode at: 0x" + 3202 utohexstr(OpcodeStart - Opcodes.begin())); 3203 moveToEnd(); 3204 return; 3205 } 3206 DEBUG_WITH_TYPE( 3207 "mach-o-rebase", 3208 dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 3209 << format("SegmentOffset=0x%06X", SegmentOffset) 3210 << ", AdvanceAmount=" << AdvanceAmount 3211 << ", RemainingLoopCount=" << RemainingLoopCount 3212 << "\n"); 3213 return; 3214 default: 3215 *E = malformedError("bad rebase info (bad opcode value 0x" + 3216 utohexstr(Opcode) + " for opcode at: 0x" + 3217 utohexstr(OpcodeStart - Opcodes.begin())); 3218 moveToEnd(); 3219 return; 3220 } 3221 } 3222 } 3223 3224 uint64_t MachORebaseEntry::readULEB128(const char **error) { 3225 unsigned Count; 3226 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error); 3227 Ptr += Count; 3228 if (Ptr > Opcodes.end()) 3229 Ptr = Opcodes.end(); 3230 return Result; 3231 } 3232 3233 int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 3234 3235 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 3236 3237 StringRef MachORebaseEntry::typeName() const { 3238 switch (RebaseType) { 3239 case MachO::REBASE_TYPE_POINTER: 3240 return "pointer"; 3241 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 3242 return "text abs32"; 3243 case MachO::REBASE_TYPE_TEXT_PCREL32: 3244 return "text rel32"; 3245 } 3246 return "unknown"; 3247 } 3248 3249 // For use with the SegIndex of a checked Mach-O Rebase entry 3250 // to get the segment name. 3251 StringRef MachORebaseEntry::segmentName() const { 3252 return O->BindRebaseSegmentName(SegmentIndex); 3253 } 3254 3255 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry 3256 // to get the section name. 3257 StringRef MachORebaseEntry::sectionName() const { 3258 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset); 3259 } 3260 3261 // For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry 3262 // to get the address. 3263 uint64_t MachORebaseEntry::address() const { 3264 return O->BindRebaseAddress(SegmentIndex, SegmentOffset); 3265 } 3266 3267 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 3268 #ifdef EXPENSIVE_CHECKS 3269 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 3270 #else 3271 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files"); 3272 #endif 3273 return (Ptr == Other.Ptr) && 3274 (RemainingLoopCount == Other.RemainingLoopCount) && 3275 (Done == Other.Done); 3276 } 3277 3278 iterator_range<rebase_iterator> 3279 MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O, 3280 ArrayRef<uint8_t> Opcodes, bool is64) { 3281 if (O->BindRebaseSectionTable == nullptr) 3282 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O); 3283 MachORebaseEntry Start(&Err, O, Opcodes, is64); 3284 Start.moveToFirst(); 3285 3286 MachORebaseEntry Finish(&Err, O, Opcodes, is64); 3287 Finish.moveToEnd(); 3288 3289 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 3290 } 3291 3292 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) { 3293 return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit()); 3294 } 3295 3296 MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O, 3297 ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 3298 : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()), 3299 PointerSize(is64Bit ? 8 : 4), TableKind(BK) {} 3300 3301 void MachOBindEntry::moveToFirst() { 3302 Ptr = Opcodes.begin(); 3303 moveNext(); 3304 } 3305 3306 void MachOBindEntry::moveToEnd() { 3307 Ptr = Opcodes.end(); 3308 RemainingLoopCount = 0; 3309 Done = true; 3310 } 3311 3312 void MachOBindEntry::moveNext() { 3313 ErrorAsOutParameter ErrAsOutParam(E); 3314 // If in the middle of some loop, move to next binding in loop. 3315 SegmentOffset += AdvanceAmount; 3316 if (RemainingLoopCount) { 3317 --RemainingLoopCount; 3318 return; 3319 } 3320 // BIND_OPCODE_DONE is only used for padding if we are not aligned to 3321 // pointer size. Therefore it is possible to reach the end without ever having 3322 // seen BIND_OPCODE_DONE. 3323 if (Ptr == Opcodes.end()) { 3324 Done = true; 3325 return; 3326 } 3327 bool More = true; 3328 while (More) { 3329 // Parse next opcode and set up next loop. 3330 const uint8_t *OpcodeStart = Ptr; 3331 uint8_t Byte = *Ptr++; 3332 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 3333 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 3334 int8_t SignExtended; 3335 const uint8_t *SymStart; 3336 uint32_t Count, Skip; 3337 const char *error = nullptr; 3338 switch (Opcode) { 3339 case MachO::BIND_OPCODE_DONE: 3340 if (TableKind == Kind::Lazy) { 3341 // Lazying bindings have a DONE opcode between entries. Need to ignore 3342 // it to advance to next entry. But need not if this is last entry. 3343 bool NotLastEntry = false; 3344 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 3345 if (*P) { 3346 NotLastEntry = true; 3347 } 3348 } 3349 if (NotLastEntry) 3350 break; 3351 } 3352 More = false; 3353 moveToEnd(); 3354 DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n"); 3355 break; 3356 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 3357 if (TableKind == Kind::Weak) { 3358 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in " 3359 "weak bind table for opcode at: 0x" + 3360 utohexstr(OpcodeStart - Opcodes.begin())); 3361 moveToEnd(); 3362 return; 3363 } 3364 Ordinal = ImmValue; 3365 LibraryOrdinalSet = true; 3366 if (ImmValue > O->getLibraryCount()) { 3367 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad " 3368 "library ordinal: " + Twine((int)ImmValue) + " (max " + 3369 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" + 3370 utohexstr(OpcodeStart - Opcodes.begin())); 3371 moveToEnd(); 3372 return; 3373 } 3374 DEBUG_WITH_TYPE( 3375 "mach-o-bind", 3376 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 3377 << "Ordinal=" << Ordinal << "\n"); 3378 break; 3379 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 3380 if (TableKind == Kind::Weak) { 3381 *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in " 3382 "weak bind table for opcode at: 0x" + 3383 utohexstr(OpcodeStart - Opcodes.begin())); 3384 moveToEnd(); 3385 return; 3386 } 3387 Ordinal = readULEB128(&error); 3388 LibraryOrdinalSet = true; 3389 if (error) { 3390 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " + 3391 Twine(error) + " for opcode at: 0x" + 3392 utohexstr(OpcodeStart - Opcodes.begin())); 3393 moveToEnd(); 3394 return; 3395 } 3396 if (Ordinal > (int)O->getLibraryCount()) { 3397 *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad " 3398 "library ordinal: " + Twine((int)Ordinal) + " (max " + 3399 Twine((int)O->getLibraryCount()) + ") for opcode at: 0x" + 3400 utohexstr(OpcodeStart - Opcodes.begin())); 3401 moveToEnd(); 3402 return; 3403 } 3404 DEBUG_WITH_TYPE( 3405 "mach-o-bind", 3406 dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 3407 << "Ordinal=" << Ordinal << "\n"); 3408 break; 3409 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 3410 if (TableKind == Kind::Weak) { 3411 *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in " 3412 "weak bind table for opcode at: 0x" + 3413 utohexstr(OpcodeStart - Opcodes.begin())); 3414 moveToEnd(); 3415 return; 3416 } 3417 if (ImmValue) { 3418 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 3419 Ordinal = SignExtended; 3420 if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) { 3421 *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown " 3422 "special ordinal: " + Twine((int)Ordinal) + " for opcode at: " 3423 "0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3424 moveToEnd(); 3425 return; 3426 } 3427 } else 3428 Ordinal = 0; 3429 LibraryOrdinalSet = true; 3430 DEBUG_WITH_TYPE( 3431 "mach-o-bind", 3432 dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 3433 << "Ordinal=" << Ordinal << "\n"); 3434 break; 3435 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 3436 Flags = ImmValue; 3437 SymStart = Ptr; 3438 while (*Ptr && (Ptr < Opcodes.end())) { 3439 ++Ptr; 3440 } 3441 if (Ptr == Opcodes.end()) { 3442 *E = malformedError("for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM " 3443 "symbol name extends past opcodes for opcode at: 0x" + 3444 utohexstr(OpcodeStart - Opcodes.begin())); 3445 moveToEnd(); 3446 return; 3447 } 3448 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 3449 Ptr-SymStart); 3450 ++Ptr; 3451 DEBUG_WITH_TYPE( 3452 "mach-o-bind", 3453 dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 3454 << "SymbolName=" << SymbolName << "\n"); 3455 if (TableKind == Kind::Weak) { 3456 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 3457 return; 3458 } 3459 break; 3460 case MachO::BIND_OPCODE_SET_TYPE_IMM: 3461 BindType = ImmValue; 3462 if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) { 3463 *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " + 3464 Twine((int)ImmValue) + " for opcode at: 0x" + 3465 utohexstr(OpcodeStart - Opcodes.begin())); 3466 moveToEnd(); 3467 return; 3468 } 3469 DEBUG_WITH_TYPE( 3470 "mach-o-bind", 3471 dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 3472 << "BindType=" << (int)BindType << "\n"); 3473 break; 3474 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 3475 Addend = readSLEB128(&error); 3476 if (error) { 3477 *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + 3478 Twine(error) + " for opcode at: 0x" + 3479 utohexstr(OpcodeStart - Opcodes.begin())); 3480 moveToEnd(); 3481 return; 3482 } 3483 DEBUG_WITH_TYPE( 3484 "mach-o-bind", 3485 dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 3486 << "Addend=" << Addend << "\n"); 3487 break; 3488 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 3489 SegmentIndex = ImmValue; 3490 SegmentOffset = readULEB128(&error); 3491 if (error) { 3492 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 3493 Twine(error) + " for opcode at: 0x" + 3494 utohexstr(OpcodeStart - Opcodes.begin())); 3495 moveToEnd(); 3496 return; 3497 } 3498 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3499 if (error) { 3500 *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " + 3501 Twine(error) + " for opcode at: 0x" + 3502 utohexstr(OpcodeStart - Opcodes.begin())); 3503 moveToEnd(); 3504 return; 3505 } 3506 DEBUG_WITH_TYPE( 3507 "mach-o-bind", 3508 dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 3509 << "SegmentIndex=" << SegmentIndex << ", " 3510 << format("SegmentOffset=0x%06X", SegmentOffset) 3511 << "\n"); 3512 break; 3513 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 3514 SegmentOffset += readULEB128(&error); 3515 if (error) { 3516 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + 3517 Twine(error) + " for opcode at: 0x" + 3518 utohexstr(OpcodeStart - Opcodes.begin())); 3519 moveToEnd(); 3520 return; 3521 } 3522 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3523 if (error) { 3524 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + 3525 Twine(error) + " for opcode at: 0x" + 3526 utohexstr(OpcodeStart - Opcodes.begin())); 3527 moveToEnd(); 3528 return; 3529 } 3530 DEBUG_WITH_TYPE("mach-o-bind", 3531 dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 3532 << format("SegmentOffset=0x%06X", 3533 SegmentOffset) << "\n"); 3534 break; 3535 case MachO::BIND_OPCODE_DO_BIND: 3536 AdvanceAmount = PointerSize; 3537 RemainingLoopCount = 0; 3538 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3539 if (error) { 3540 *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) + 3541 " for opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3542 moveToEnd(); 3543 return; 3544 } 3545 if (SymbolName == StringRef()) { 3546 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding " 3547 "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" + 3548 utohexstr(OpcodeStart - Opcodes.begin())); 3549 moveToEnd(); 3550 return; 3551 } 3552 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3553 *E = malformedError("for BIND_OPCODE_DO_BIND missing preceding " 3554 "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" + 3555 utohexstr(OpcodeStart - Opcodes.begin())); 3556 moveToEnd(); 3557 return; 3558 } 3559 DEBUG_WITH_TYPE("mach-o-bind", 3560 dbgs() << "BIND_OPCODE_DO_BIND: " 3561 << format("SegmentOffset=0x%06X", 3562 SegmentOffset) << "\n"); 3563 return; 3564 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 3565 if (TableKind == Kind::Lazy) { 3566 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in " 3567 "lazy bind table for opcode at: 0x" + 3568 utohexstr(OpcodeStart - Opcodes.begin())); 3569 moveToEnd(); 3570 return; 3571 } 3572 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3573 if (error) { 3574 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " + 3575 Twine(error) + " for opcode at: 0x" + 3576 utohexstr(OpcodeStart - Opcodes.begin())); 3577 moveToEnd(); 3578 return; 3579 } 3580 if (SymbolName == StringRef()) { 3581 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing " 3582 "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode " 3583 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3584 moveToEnd(); 3585 return; 3586 } 3587 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3588 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing " 3589 "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" + 3590 utohexstr(OpcodeStart - Opcodes.begin())); 3591 moveToEnd(); 3592 return; 3593 } 3594 AdvanceAmount = readULEB128(&error) + PointerSize; 3595 if (error) { 3596 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " + 3597 Twine(error) + " for opcode at: 0x" + 3598 utohexstr(OpcodeStart - Opcodes.begin())); 3599 moveToEnd(); 3600 return; 3601 } 3602 // Note, this is not really an error until the next bind but make no sense 3603 // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another 3604 // bind operation. 3605 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset + 3606 AdvanceAmount, false); 3607 if (error) { 3608 *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding " 3609 "ULEB) " + Twine(error) + " for opcode at: 0x" + 3610 utohexstr(OpcodeStart - Opcodes.begin())); 3611 moveToEnd(); 3612 return; 3613 } 3614 RemainingLoopCount = 0; 3615 DEBUG_WITH_TYPE( 3616 "mach-o-bind", 3617 dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 3618 << format("SegmentOffset=0x%06X", SegmentOffset) 3619 << ", AdvanceAmount=" << AdvanceAmount 3620 << ", RemainingLoopCount=" << RemainingLoopCount 3621 << "\n"); 3622 return; 3623 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 3624 if (TableKind == Kind::Lazy) { 3625 *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not " 3626 "allowed in lazy bind table for opcode at: 0x" + 3627 utohexstr(OpcodeStart - Opcodes.begin())); 3628 moveToEnd(); 3629 return; 3630 } 3631 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3632 if (error) { 3633 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " + 3634 Twine(error) + " for opcode at: 0x" + 3635 utohexstr(OpcodeStart - Opcodes.begin())); 3636 moveToEnd(); 3637 return; 3638 } 3639 if (SymbolName == StringRef()) { 3640 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " 3641 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for " 3642 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3643 moveToEnd(); 3644 return; 3645 } 3646 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3647 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " 3648 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode " 3649 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3650 moveToEnd(); 3651 return; 3652 } 3653 AdvanceAmount = ImmValue * PointerSize + PointerSize; 3654 RemainingLoopCount = 0; 3655 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset + 3656 AdvanceAmount, false); 3657 if (error) { 3658 *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " 3659 " (after adding immediate times the pointer size) " + 3660 Twine(error) + " for opcode at: 0x" + 3661 utohexstr(OpcodeStart - Opcodes.begin())); 3662 moveToEnd(); 3663 return; 3664 } 3665 DEBUG_WITH_TYPE("mach-o-bind", 3666 dbgs() 3667 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 3668 << format("SegmentOffset=0x%06X", SegmentOffset) << "\n"); 3669 return; 3670 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 3671 if (TableKind == Kind::Lazy) { 3672 *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not " 3673 "allowed in lazy bind table for opcode at: 0x" + 3674 utohexstr(OpcodeStart - Opcodes.begin())); 3675 moveToEnd(); 3676 return; 3677 } 3678 Count = readULEB128(&error); 3679 if (Count != 0) 3680 RemainingLoopCount = Count - 1; 3681 else 3682 RemainingLoopCount = 0; 3683 if (error) { 3684 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3685 " (count value) " + Twine(error) + " for opcode at" 3686 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3687 moveToEnd(); 3688 return; 3689 } 3690 Skip = readULEB128(&error); 3691 AdvanceAmount = Skip + PointerSize; 3692 if (error) { 3693 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3694 " (skip value) " + Twine(error) + " for opcode at" 3695 ": 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3696 moveToEnd(); 3697 return; 3698 } 3699 error = O->BindEntryCheckSegAndOffset(SegmentIndex, SegmentOffset, true); 3700 if (error) { 3701 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3702 + Twine(error) + " for opcode at: 0x" + 3703 utohexstr(OpcodeStart - Opcodes.begin())); 3704 moveToEnd(); 3705 return; 3706 } 3707 if (SymbolName == StringRef()) { 3708 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3709 "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for " 3710 "opcode at: 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3711 moveToEnd(); 3712 return; 3713 } 3714 if (!LibraryOrdinalSet && TableKind != Kind::Weak) { 3715 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3716 "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode " 3717 "at: 0x" + utohexstr(OpcodeStart - Opcodes.begin())); 3718 moveToEnd(); 3719 return; 3720 } 3721 error = O->BindEntryCheckCountAndSkip(Count, Skip, PointerSize, 3722 SegmentIndex, SegmentOffset); 3723 if (error) { 3724 *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " 3725 + Twine(error) + " for opcode at: 0x" + 3726 utohexstr(OpcodeStart - Opcodes.begin())); 3727 moveToEnd(); 3728 return; 3729 } 3730 DEBUG_WITH_TYPE( 3731 "mach-o-bind", 3732 dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 3733 << format("SegmentOffset=0x%06X", SegmentOffset) 3734 << ", AdvanceAmount=" << AdvanceAmount 3735 << ", RemainingLoopCount=" << RemainingLoopCount 3736 << "\n"); 3737 return; 3738 default: 3739 *E = malformedError("bad bind info (bad opcode value 0x" + 3740 utohexstr(Opcode) + " for opcode at: 0x" + 3741 utohexstr(OpcodeStart - Opcodes.begin())); 3742 moveToEnd(); 3743 return; 3744 } 3745 } 3746 } 3747 3748 uint64_t MachOBindEntry::readULEB128(const char **error) { 3749 unsigned Count; 3750 uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error); 3751 Ptr += Count; 3752 if (Ptr > Opcodes.end()) 3753 Ptr = Opcodes.end(); 3754 return Result; 3755 } 3756 3757 int64_t MachOBindEntry::readSLEB128(const char **error) { 3758 unsigned Count; 3759 int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error); 3760 Ptr += Count; 3761 if (Ptr > Opcodes.end()) 3762 Ptr = Opcodes.end(); 3763 return Result; 3764 } 3765 3766 int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 3767 3768 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 3769 3770 StringRef MachOBindEntry::typeName() const { 3771 switch (BindType) { 3772 case MachO::BIND_TYPE_POINTER: 3773 return "pointer"; 3774 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 3775 return "text abs32"; 3776 case MachO::BIND_TYPE_TEXT_PCREL32: 3777 return "text rel32"; 3778 } 3779 return "unknown"; 3780 } 3781 3782 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 3783 3784 int64_t MachOBindEntry::addend() const { return Addend; } 3785 3786 uint32_t MachOBindEntry::flags() const { return Flags; } 3787 3788 int MachOBindEntry::ordinal() const { return Ordinal; } 3789 3790 // For use with the SegIndex of a checked Mach-O Bind entry 3791 // to get the segment name. 3792 StringRef MachOBindEntry::segmentName() const { 3793 return O->BindRebaseSegmentName(SegmentIndex); 3794 } 3795 3796 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry 3797 // to get the section name. 3798 StringRef MachOBindEntry::sectionName() const { 3799 return O->BindRebaseSectionName(SegmentIndex, SegmentOffset); 3800 } 3801 3802 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry 3803 // to get the address. 3804 uint64_t MachOBindEntry::address() const { 3805 return O->BindRebaseAddress(SegmentIndex, SegmentOffset); 3806 } 3807 3808 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 3809 #ifdef EXPENSIVE_CHECKS 3810 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 3811 #else 3812 assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files"); 3813 #endif 3814 return (Ptr == Other.Ptr) && 3815 (RemainingLoopCount == Other.RemainingLoopCount) && 3816 (Done == Other.Done); 3817 } 3818 3819 // Build table of sections so SegIndex/SegOffset pairs can be translated. 3820 BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) { 3821 uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 1 : 0; 3822 StringRef CurSegName; 3823 uint64_t CurSegAddress; 3824 for (const SectionRef &Section : Obj->sections()) { 3825 SectionInfo Info; 3826 Section.getName(Info.SectionName); 3827 Info.Address = Section.getAddress(); 3828 Info.Size = Section.getSize(); 3829 Info.SegmentName = 3830 Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl()); 3831 if (!Info.SegmentName.equals(CurSegName)) { 3832 ++CurSegIndex; 3833 CurSegName = Info.SegmentName; 3834 CurSegAddress = Info.Address; 3835 } 3836 Info.SegmentIndex = CurSegIndex - 1; 3837 Info.OffsetInSegment = Info.Address - CurSegAddress; 3838 Info.SegmentStartAddress = CurSegAddress; 3839 Sections.push_back(Info); 3840 } 3841 MaxSegIndex = CurSegIndex; 3842 } 3843 3844 // For use with a SegIndex,SegOffset pair in MachOBindEntry::moveNext() to 3845 // validate a MachOBindEntry or MachORebaseEntry. 3846 const char * BindRebaseSegInfo::checkSegAndOffset(int32_t SegIndex, 3847 uint64_t SegOffset, 3848 bool endInvalid) { 3849 if (SegIndex == -1) 3850 return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"; 3851 if (SegIndex >= MaxSegIndex) 3852 return "bad segIndex (too large)"; 3853 for (const SectionInfo &SI : Sections) { 3854 if (SI.SegmentIndex != SegIndex) 3855 continue; 3856 if (SI.OffsetInSegment > SegOffset) 3857 continue; 3858 if (SegOffset > (SI.OffsetInSegment + SI.Size)) 3859 continue; 3860 if (endInvalid && SegOffset >= (SI.OffsetInSegment + SI.Size)) 3861 continue; 3862 return nullptr; 3863 } 3864 return "bad segOffset, too large"; 3865 } 3866 3867 // For use in MachOBindEntry::moveNext() to validate a MachOBindEntry for 3868 // the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode and for use in 3869 // MachORebaseEntry::moveNext() to validate a MachORebaseEntry for 3870 // REBASE_OPCODE_DO_*_TIMES* opcodes. The SegIndex and SegOffset must have 3871 // been already checked. 3872 const char * BindRebaseSegInfo::checkCountAndSkip(uint32_t Count, uint32_t Skip, 3873 uint8_t PointerSize, 3874 int32_t SegIndex, 3875 uint64_t SegOffset) { 3876 const SectionInfo &SI = findSection(SegIndex, SegOffset); 3877 uint64_t addr = SI.SegmentStartAddress + SegOffset; 3878 if (addr >= SI.Address + SI.Size) 3879 return "bad segOffset, too large"; 3880 uint64_t i = 0; 3881 if (Count > 1) 3882 i = (Skip + PointerSize) * (Count - 1); 3883 else if (Count == 1) 3884 i = Skip + PointerSize; 3885 if (addr + i >= SI.Address + SI.Size) { 3886 // For rebase opcodes they can step from one section to another. 3887 uint64_t TrailingSegOffset = (addr + i) - SI.SegmentStartAddress; 3888 const char *error = checkSegAndOffset(SegIndex, TrailingSegOffset, false); 3889 if (error) 3890 return "bad count and skip, too large"; 3891 } 3892 return nullptr; 3893 } 3894 3895 // For use with the SegIndex of a checked Mach-O Bind or Rebase entry 3896 // to get the segment name. 3897 StringRef BindRebaseSegInfo::segmentName(int32_t SegIndex) { 3898 for (const SectionInfo &SI : Sections) { 3899 if (SI.SegmentIndex == SegIndex) 3900 return SI.SegmentName; 3901 } 3902 llvm_unreachable("invalid SegIndex"); 3903 } 3904 3905 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase 3906 // to get the SectionInfo. 3907 const BindRebaseSegInfo::SectionInfo &BindRebaseSegInfo::findSection( 3908 int32_t SegIndex, uint64_t SegOffset) { 3909 for (const SectionInfo &SI : Sections) { 3910 if (SI.SegmentIndex != SegIndex) 3911 continue; 3912 if (SI.OffsetInSegment > SegOffset) 3913 continue; 3914 if (SegOffset >= (SI.OffsetInSegment + SI.Size)) 3915 continue; 3916 return SI; 3917 } 3918 llvm_unreachable("SegIndex and SegOffset not in any section"); 3919 } 3920 3921 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase 3922 // entry to get the section name. 3923 StringRef BindRebaseSegInfo::sectionName(int32_t SegIndex, 3924 uint64_t SegOffset) { 3925 return findSection(SegIndex, SegOffset).SectionName; 3926 } 3927 3928 // For use with a SegIndex,SegOffset pair from a checked Mach-O Bind or Rebase 3929 // entry to get the address. 3930 uint64_t BindRebaseSegInfo::address(uint32_t SegIndex, uint64_t OffsetInSeg) { 3931 const SectionInfo &SI = findSection(SegIndex, OffsetInSeg); 3932 return SI.SegmentStartAddress + OffsetInSeg; 3933 } 3934 3935 iterator_range<bind_iterator> 3936 MachOObjectFile::bindTable(Error &Err, MachOObjectFile *O, 3937 ArrayRef<uint8_t> Opcodes, bool is64, 3938 MachOBindEntry::Kind BKind) { 3939 if (O->BindRebaseSectionTable == nullptr) 3940 O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O); 3941 MachOBindEntry Start(&Err, O, Opcodes, is64, BKind); 3942 Start.moveToFirst(); 3943 3944 MachOBindEntry Finish(&Err, O, Opcodes, is64, BKind); 3945 Finish.moveToEnd(); 3946 3947 return make_range(bind_iterator(Start), bind_iterator(Finish)); 3948 } 3949 3950 iterator_range<bind_iterator> MachOObjectFile::bindTable(Error &Err) { 3951 return bindTable(Err, this, getDyldInfoBindOpcodes(), is64Bit(), 3952 MachOBindEntry::Kind::Regular); 3953 } 3954 3955 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable(Error &Err) { 3956 return bindTable(Err, this, getDyldInfoLazyBindOpcodes(), is64Bit(), 3957 MachOBindEntry::Kind::Lazy); 3958 } 3959 3960 iterator_range<bind_iterator> MachOObjectFile::weakBindTable(Error &Err) { 3961 return bindTable(Err, this, getDyldInfoWeakBindOpcodes(), is64Bit(), 3962 MachOBindEntry::Kind::Weak); 3963 } 3964 3965 MachOObjectFile::load_command_iterator 3966 MachOObjectFile::begin_load_commands() const { 3967 return LoadCommands.begin(); 3968 } 3969 3970 MachOObjectFile::load_command_iterator 3971 MachOObjectFile::end_load_commands() const { 3972 return LoadCommands.end(); 3973 } 3974 3975 iterator_range<MachOObjectFile::load_command_iterator> 3976 MachOObjectFile::load_commands() const { 3977 return make_range(begin_load_commands(), end_load_commands()); 3978 } 3979 3980 StringRef 3981 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 3982 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 3983 return parseSegmentOrSectionName(Raw.data()); 3984 } 3985 3986 ArrayRef<char> 3987 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 3988 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3989 const section_base *Base = 3990 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3991 return makeArrayRef(Base->sectname); 3992 } 3993 3994 ArrayRef<char> 3995 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 3996 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 3997 const section_base *Base = 3998 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 3999 return makeArrayRef(Base->segname); 4000 } 4001 4002 bool 4003 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 4004 const { 4005 if (getCPUType(*this) == MachO::CPU_TYPE_X86_64) 4006 return false; 4007 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 4008 } 4009 4010 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 4011 const MachO::any_relocation_info &RE) const { 4012 if (isLittleEndian()) 4013 return RE.r_word1 & 0xffffff; 4014 return RE.r_word1 >> 8; 4015 } 4016 4017 bool MachOObjectFile::getPlainRelocationExternal( 4018 const MachO::any_relocation_info &RE) const { 4019 if (isLittleEndian()) 4020 return (RE.r_word1 >> 27) & 1; 4021 return (RE.r_word1 >> 4) & 1; 4022 } 4023 4024 bool MachOObjectFile::getScatteredRelocationScattered( 4025 const MachO::any_relocation_info &RE) const { 4026 return RE.r_word0 >> 31; 4027 } 4028 4029 uint32_t MachOObjectFile::getScatteredRelocationValue( 4030 const MachO::any_relocation_info &RE) const { 4031 return RE.r_word1; 4032 } 4033 4034 uint32_t MachOObjectFile::getScatteredRelocationType( 4035 const MachO::any_relocation_info &RE) const { 4036 return (RE.r_word0 >> 24) & 0xf; 4037 } 4038 4039 unsigned MachOObjectFile::getAnyRelocationAddress( 4040 const MachO::any_relocation_info &RE) const { 4041 if (isRelocationScattered(RE)) 4042 return getScatteredRelocationAddress(RE); 4043 return getPlainRelocationAddress(RE); 4044 } 4045 4046 unsigned MachOObjectFile::getAnyRelocationPCRel( 4047 const MachO::any_relocation_info &RE) const { 4048 if (isRelocationScattered(RE)) 4049 return getScatteredRelocationPCRel(RE); 4050 return getPlainRelocationPCRel(*this, RE); 4051 } 4052 4053 unsigned MachOObjectFile::getAnyRelocationLength( 4054 const MachO::any_relocation_info &RE) const { 4055 if (isRelocationScattered(RE)) 4056 return getScatteredRelocationLength(RE); 4057 return getPlainRelocationLength(*this, RE); 4058 } 4059 4060 unsigned 4061 MachOObjectFile::getAnyRelocationType( 4062 const MachO::any_relocation_info &RE) const { 4063 if (isRelocationScattered(RE)) 4064 return getScatteredRelocationType(RE); 4065 return getPlainRelocationType(*this, RE); 4066 } 4067 4068 SectionRef 4069 MachOObjectFile::getAnyRelocationSection( 4070 const MachO::any_relocation_info &RE) const { 4071 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 4072 return *section_end(); 4073 unsigned SecNum = getPlainRelocationSymbolNum(RE); 4074 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 4075 return *section_end(); 4076 DataRefImpl DRI; 4077 DRI.d.a = SecNum - 1; 4078 return SectionRef(DRI, this); 4079 } 4080 4081 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 4082 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 4083 return getStruct<MachO::section>(*this, Sections[DRI.d.a]); 4084 } 4085 4086 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 4087 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 4088 return getStruct<MachO::section_64>(*this, Sections[DRI.d.a]); 4089 } 4090 4091 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 4092 unsigned Index) const { 4093 const char *Sec = getSectionPtr(*this, L, Index); 4094 return getStruct<MachO::section>(*this, Sec); 4095 } 4096 4097 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 4098 unsigned Index) const { 4099 const char *Sec = getSectionPtr(*this, L, Index); 4100 return getStruct<MachO::section_64>(*this, Sec); 4101 } 4102 4103 MachO::nlist 4104 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 4105 const char *P = reinterpret_cast<const char *>(DRI.p); 4106 return getStruct<MachO::nlist>(*this, P); 4107 } 4108 4109 MachO::nlist_64 4110 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 4111 const char *P = reinterpret_cast<const char *>(DRI.p); 4112 return getStruct<MachO::nlist_64>(*this, P); 4113 } 4114 4115 MachO::linkedit_data_command 4116 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 4117 return getStruct<MachO::linkedit_data_command>(*this, L.Ptr); 4118 } 4119 4120 MachO::segment_command 4121 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 4122 return getStruct<MachO::segment_command>(*this, L.Ptr); 4123 } 4124 4125 MachO::segment_command_64 4126 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 4127 return getStruct<MachO::segment_command_64>(*this, L.Ptr); 4128 } 4129 4130 MachO::linker_option_command 4131 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 4132 return getStruct<MachO::linker_option_command>(*this, L.Ptr); 4133 } 4134 4135 MachO::version_min_command 4136 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 4137 return getStruct<MachO::version_min_command>(*this, L.Ptr); 4138 } 4139 4140 MachO::note_command 4141 MachOObjectFile::getNoteLoadCommand(const LoadCommandInfo &L) const { 4142 return getStruct<MachO::note_command>(*this, L.Ptr); 4143 } 4144 4145 MachO::build_version_command 4146 MachOObjectFile::getBuildVersionLoadCommand(const LoadCommandInfo &L) const { 4147 return getStruct<MachO::build_version_command>(*this, L.Ptr); 4148 } 4149 4150 MachO::build_tool_version 4151 MachOObjectFile::getBuildToolVersion(unsigned index) const { 4152 return getStruct<MachO::build_tool_version>(*this, BuildTools[index]); 4153 } 4154 4155 MachO::dylib_command 4156 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 4157 return getStruct<MachO::dylib_command>(*this, L.Ptr); 4158 } 4159 4160 MachO::dyld_info_command 4161 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 4162 return getStruct<MachO::dyld_info_command>(*this, L.Ptr); 4163 } 4164 4165 MachO::dylinker_command 4166 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 4167 return getStruct<MachO::dylinker_command>(*this, L.Ptr); 4168 } 4169 4170 MachO::uuid_command 4171 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 4172 return getStruct<MachO::uuid_command>(*this, L.Ptr); 4173 } 4174 4175 MachO::rpath_command 4176 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 4177 return getStruct<MachO::rpath_command>(*this, L.Ptr); 4178 } 4179 4180 MachO::source_version_command 4181 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 4182 return getStruct<MachO::source_version_command>(*this, L.Ptr); 4183 } 4184 4185 MachO::entry_point_command 4186 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 4187 return getStruct<MachO::entry_point_command>(*this, L.Ptr); 4188 } 4189 4190 MachO::encryption_info_command 4191 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 4192 return getStruct<MachO::encryption_info_command>(*this, L.Ptr); 4193 } 4194 4195 MachO::encryption_info_command_64 4196 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 4197 return getStruct<MachO::encryption_info_command_64>(*this, L.Ptr); 4198 } 4199 4200 MachO::sub_framework_command 4201 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 4202 return getStruct<MachO::sub_framework_command>(*this, L.Ptr); 4203 } 4204 4205 MachO::sub_umbrella_command 4206 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 4207 return getStruct<MachO::sub_umbrella_command>(*this, L.Ptr); 4208 } 4209 4210 MachO::sub_library_command 4211 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 4212 return getStruct<MachO::sub_library_command>(*this, L.Ptr); 4213 } 4214 4215 MachO::sub_client_command 4216 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 4217 return getStruct<MachO::sub_client_command>(*this, L.Ptr); 4218 } 4219 4220 MachO::routines_command 4221 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 4222 return getStruct<MachO::routines_command>(*this, L.Ptr); 4223 } 4224 4225 MachO::routines_command_64 4226 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 4227 return getStruct<MachO::routines_command_64>(*this, L.Ptr); 4228 } 4229 4230 MachO::thread_command 4231 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 4232 return getStruct<MachO::thread_command>(*this, L.Ptr); 4233 } 4234 4235 MachO::any_relocation_info 4236 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 4237 uint32_t Offset; 4238 if (getHeader().filetype == MachO::MH_OBJECT) { 4239 DataRefImpl Sec; 4240 Sec.d.a = Rel.d.a; 4241 if (is64Bit()) { 4242 MachO::section_64 Sect = getSection64(Sec); 4243 Offset = Sect.reloff; 4244 } else { 4245 MachO::section Sect = getSection(Sec); 4246 Offset = Sect.reloff; 4247 } 4248 } else { 4249 MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand(); 4250 Offset = DysymtabLoadCmd.extreloff; // Offset to the external relocations 4251 } 4252 4253 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 4254 getPtr(*this, Offset)) + Rel.d.b; 4255 return getStruct<MachO::any_relocation_info>( 4256 *this, reinterpret_cast<const char *>(P)); 4257 } 4258 4259 MachO::data_in_code_entry 4260 MachOObjectFile::getDice(DataRefImpl Rel) const { 4261 const char *P = reinterpret_cast<const char *>(Rel.p); 4262 return getStruct<MachO::data_in_code_entry>(*this, P); 4263 } 4264 4265 const MachO::mach_header &MachOObjectFile::getHeader() const { 4266 return Header; 4267 } 4268 4269 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 4270 assert(is64Bit()); 4271 return Header64; 4272 } 4273 4274 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 4275 const MachO::dysymtab_command &DLC, 4276 unsigned Index) const { 4277 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 4278 return getStruct<uint32_t>(*this, getPtr(*this, Offset)); 4279 } 4280 4281 MachO::data_in_code_entry 4282 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 4283 unsigned Index) const { 4284 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 4285 return getStruct<MachO::data_in_code_entry>(*this, getPtr(*this, Offset)); 4286 } 4287 4288 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 4289 if (SymtabLoadCmd) 4290 return getStruct<MachO::symtab_command>(*this, SymtabLoadCmd); 4291 4292 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 4293 MachO::symtab_command Cmd; 4294 Cmd.cmd = MachO::LC_SYMTAB; 4295 Cmd.cmdsize = sizeof(MachO::symtab_command); 4296 Cmd.symoff = 0; 4297 Cmd.nsyms = 0; 4298 Cmd.stroff = 0; 4299 Cmd.strsize = 0; 4300 return Cmd; 4301 } 4302 4303 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 4304 if (DysymtabLoadCmd) 4305 return getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd); 4306 4307 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 4308 MachO::dysymtab_command Cmd; 4309 Cmd.cmd = MachO::LC_DYSYMTAB; 4310 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 4311 Cmd.ilocalsym = 0; 4312 Cmd.nlocalsym = 0; 4313 Cmd.iextdefsym = 0; 4314 Cmd.nextdefsym = 0; 4315 Cmd.iundefsym = 0; 4316 Cmd.nundefsym = 0; 4317 Cmd.tocoff = 0; 4318 Cmd.ntoc = 0; 4319 Cmd.modtaboff = 0; 4320 Cmd.nmodtab = 0; 4321 Cmd.extrefsymoff = 0; 4322 Cmd.nextrefsyms = 0; 4323 Cmd.indirectsymoff = 0; 4324 Cmd.nindirectsyms = 0; 4325 Cmd.extreloff = 0; 4326 Cmd.nextrel = 0; 4327 Cmd.locreloff = 0; 4328 Cmd.nlocrel = 0; 4329 return Cmd; 4330 } 4331 4332 MachO::linkedit_data_command 4333 MachOObjectFile::getDataInCodeLoadCommand() const { 4334 if (DataInCodeLoadCmd) 4335 return getStruct<MachO::linkedit_data_command>(*this, DataInCodeLoadCmd); 4336 4337 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 4338 MachO::linkedit_data_command Cmd; 4339 Cmd.cmd = MachO::LC_DATA_IN_CODE; 4340 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 4341 Cmd.dataoff = 0; 4342 Cmd.datasize = 0; 4343 return Cmd; 4344 } 4345 4346 MachO::linkedit_data_command 4347 MachOObjectFile::getLinkOptHintsLoadCommand() const { 4348 if (LinkOptHintsLoadCmd) 4349 return getStruct<MachO::linkedit_data_command>(*this, LinkOptHintsLoadCmd); 4350 4351 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 4352 // fields. 4353 MachO::linkedit_data_command Cmd; 4354 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 4355 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 4356 Cmd.dataoff = 0; 4357 Cmd.datasize = 0; 4358 return Cmd; 4359 } 4360 4361 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 4362 if (!DyldInfoLoadCmd) 4363 return None; 4364 4365 MachO::dyld_info_command DyldInfo = 4366 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4367 const uint8_t *Ptr = 4368 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.rebase_off)); 4369 return makeArrayRef(Ptr, DyldInfo.rebase_size); 4370 } 4371 4372 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 4373 if (!DyldInfoLoadCmd) 4374 return None; 4375 4376 MachO::dyld_info_command DyldInfo = 4377 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4378 const uint8_t *Ptr = 4379 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.bind_off)); 4380 return makeArrayRef(Ptr, DyldInfo.bind_size); 4381 } 4382 4383 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 4384 if (!DyldInfoLoadCmd) 4385 return None; 4386 4387 MachO::dyld_info_command DyldInfo = 4388 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4389 const uint8_t *Ptr = 4390 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.weak_bind_off)); 4391 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 4392 } 4393 4394 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 4395 if (!DyldInfoLoadCmd) 4396 return None; 4397 4398 MachO::dyld_info_command DyldInfo = 4399 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4400 const uint8_t *Ptr = 4401 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.lazy_bind_off)); 4402 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 4403 } 4404 4405 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 4406 if (!DyldInfoLoadCmd) 4407 return None; 4408 4409 MachO::dyld_info_command DyldInfo = 4410 getStruct<MachO::dyld_info_command>(*this, DyldInfoLoadCmd); 4411 const uint8_t *Ptr = 4412 reinterpret_cast<const uint8_t *>(getPtr(*this, DyldInfo.export_off)); 4413 return makeArrayRef(Ptr, DyldInfo.export_size); 4414 } 4415 4416 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 4417 if (!UuidLoadCmd) 4418 return None; 4419 // Returning a pointer is fine as uuid doesn't need endian swapping. 4420 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 4421 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 4422 } 4423 4424 StringRef MachOObjectFile::getStringTableData() const { 4425 MachO::symtab_command S = getSymtabLoadCommand(); 4426 return getData().substr(S.stroff, S.strsize); 4427 } 4428 4429 bool MachOObjectFile::is64Bit() const { 4430 return getType() == getMachOType(false, true) || 4431 getType() == getMachOType(true, true); 4432 } 4433 4434 void MachOObjectFile::ReadULEB128s(uint64_t Index, 4435 SmallVectorImpl<uint64_t> &Out) const { 4436 DataExtractor extractor(ObjectFile::getData(), true, 0); 4437 4438 uint32_t offset = Index; 4439 uint64_t data = 0; 4440 while (uint64_t delta = extractor.getULEB128(&offset)) { 4441 data += delta; 4442 Out.push_back(data); 4443 } 4444 } 4445 4446 bool MachOObjectFile::isRelocatableObject() const { 4447 return getHeader().filetype == MachO::MH_OBJECT; 4448 } 4449 4450 Expected<std::unique_ptr<MachOObjectFile>> 4451 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, 4452 uint32_t UniversalCputype, 4453 uint32_t UniversalIndex) { 4454 StringRef Magic = Buffer.getBuffer().slice(0, 4); 4455 if (Magic == "\xFE\xED\xFA\xCE") 4456 return MachOObjectFile::create(Buffer, false, false, 4457 UniversalCputype, UniversalIndex); 4458 if (Magic == "\xCE\xFA\xED\xFE") 4459 return MachOObjectFile::create(Buffer, true, false, 4460 UniversalCputype, UniversalIndex); 4461 if (Magic == "\xFE\xED\xFA\xCF") 4462 return MachOObjectFile::create(Buffer, false, true, 4463 UniversalCputype, UniversalIndex); 4464 if (Magic == "\xCF\xFA\xED\xFE") 4465 return MachOObjectFile::create(Buffer, true, true, 4466 UniversalCputype, UniversalIndex); 4467 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 4468 object_error::invalid_file_type); 4469 } 4470 4471 StringRef MachOObjectFile::mapDebugSectionName(StringRef Name) const { 4472 return StringSwitch<StringRef>(Name) 4473 .Case("debug_str_offs", "debug_str_offsets") 4474 .Default(Name); 4475 } 4476