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