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 // Helper to advance a section or symbol iterator multiple increments at a time. 110 template<class T> 111 static void advance(T &it, size_t Val) { 112 while (Val--) 113 ++it; 114 } 115 116 static unsigned getCPUType(const MachOObjectFile *O) { 117 return O->getHeader().cputype; 118 } 119 120 static uint32_t 121 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 122 return RE.r_word0; 123 } 124 125 static unsigned 126 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 127 return RE.r_word0 & 0xffffff; 128 } 129 130 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 131 const MachO::any_relocation_info &RE) { 132 if (O->isLittleEndian()) 133 return (RE.r_word1 >> 24) & 1; 134 return (RE.r_word1 >> 7) & 1; 135 } 136 137 static bool 138 getScatteredRelocationPCRel(const MachOObjectFile *O, 139 const MachO::any_relocation_info &RE) { 140 return (RE.r_word0 >> 30) & 1; 141 } 142 143 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 144 const MachO::any_relocation_info &RE) { 145 if (O->isLittleEndian()) 146 return (RE.r_word1 >> 25) & 3; 147 return (RE.r_word1 >> 5) & 3; 148 } 149 150 static unsigned 151 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 152 return (RE.r_word0 >> 28) & 3; 153 } 154 155 static unsigned getPlainRelocationType(const MachOObjectFile *O, 156 const MachO::any_relocation_info &RE) { 157 if (O->isLittleEndian()) 158 return RE.r_word1 >> 28; 159 return RE.r_word1 & 0xf; 160 } 161 162 static uint32_t getSectionFlags(const MachOObjectFile *O, 163 DataRefImpl Sec) { 164 if (O->is64Bit()) { 165 MachO::section_64 Sect = O->getSection64(Sec); 166 return Sect.flags; 167 } 168 MachO::section Sect = O->getSection(Sec); 169 return Sect.flags; 170 } 171 172 static Expected<MachOObjectFile::LoadCommandInfo> 173 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr, 174 uint32_t LoadCommandIndex) { 175 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) { 176 if (CmdOrErr->cmdsize < 8) 177 return malformedError("load command " + Twine(LoadCommandIndex) + 178 " with size less than 8 bytes"); 179 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr}); 180 } else 181 return CmdOrErr.takeError(); 182 } 183 184 static Expected<MachOObjectFile::LoadCommandInfo> 185 getFirstLoadCommandInfo(const MachOObjectFile *Obj) { 186 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 187 : sizeof(MachO::mach_header); 188 if (sizeof(MachO::load_command) > Obj->getHeader().sizeofcmds) 189 return malformedError("load command 0 extends past the end all load " 190 "commands in the file"); 191 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0); 192 } 193 194 static Expected<MachOObjectFile::LoadCommandInfo> 195 getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex, 196 const MachOObjectFile::LoadCommandInfo &L) { 197 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 198 : sizeof(MachO::mach_header); 199 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) > 200 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds) 201 return malformedError("load command " + Twine(LoadCommandIndex + 1) + 202 " extends past the end all load commands in the file"); 203 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1); 204 } 205 206 template <typename T> 207 static void parseHeader(const MachOObjectFile *Obj, T &Header, 208 Error &Err) { 209 if (sizeof(T) > Obj->getData().size()) { 210 Err = malformedError("the mach header extends past the end of the " 211 "file"); 212 return; 213 } 214 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0))) 215 Header = *HeaderOrErr; 216 else 217 Err = HeaderOrErr.takeError(); 218 } 219 220 // This is used to check for overlapping of Mach-O elements. 221 struct MachOElement { 222 uint64_t Offset; 223 uint64_t Size; 224 const char *Name; 225 }; 226 227 static Error checkOverlappingElement(std::list<MachOElement> &Elements, 228 uint64_t Offset, uint64_t Size, 229 const char *Name) { 230 if (Size == 0) 231 return Error::success(); 232 233 for (auto it=Elements.begin() ; it != Elements.end(); ++it) { 234 auto E = *it; 235 if ((Offset >= E.Offset && Offset < E.Offset + E.Size) || 236 (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) || 237 (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size)) 238 return malformedError(Twine(Name) + " at offset " + Twine(Offset) + 239 " with a size of " + Twine(Size) + ", overlaps " + 240 E.Name + " at offset " + Twine(E.Offset) + " with " 241 "a size of " + Twine(E.Size)); 242 auto nt = it; 243 nt++; 244 if (nt != Elements.end()) { 245 auto N = *nt; 246 if (Offset + Size <= N.Offset) { 247 Elements.insert(nt, {Offset, Size, Name}); 248 return Error::success(); 249 } 250 } 251 } 252 Elements.push_back({Offset, Size, Name}); 253 return Error::success(); 254 } 255 256 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all 257 // sections to \param Sections, and optionally sets 258 // \param IsPageZeroSegment to true. 259 template <typename Segment, typename Section> 260 static Error parseSegmentLoadCommand( 261 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, 262 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment, 263 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders) { 264 const unsigned SegmentLoadSize = sizeof(Segment); 265 if (Load.C.cmdsize < SegmentLoadSize) 266 return malformedError("load command " + Twine(LoadCommandIndex) + 267 " " + CmdName + " cmdsize too small"); 268 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) { 269 Segment S = SegOrErr.get(); 270 const unsigned SectionSize = sizeof(Section); 271 uint64_t FileSize = Obj->getData().size(); 272 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize || 273 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) 274 return malformedError("load command " + Twine(LoadCommandIndex) + 275 " inconsistent cmdsize in " + CmdName + 276 " for the number of sections"); 277 for (unsigned J = 0; J < S.nsects; ++J) { 278 const char *Sec = getSectionPtr(Obj, Load, J); 279 Sections.push_back(Sec); 280 Section s = getStruct<Section>(Obj, Sec); 281 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 282 Obj->getHeader().filetype != MachO::MH_DSYM && 283 s.flags != MachO::S_ZEROFILL && 284 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 285 s.offset > FileSize) 286 return malformedError("offset field of section " + Twine(J) + " in " + 287 CmdName + " command " + Twine(LoadCommandIndex) + 288 " extends past the end of the file"); 289 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 290 Obj->getHeader().filetype != MachO::MH_DSYM && 291 s.flags != MachO::S_ZEROFILL && 292 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 && 293 s.offset < SizeOfHeaders && s.size != 0) 294 return malformedError("offset field of section " + Twine(J) + " in " + 295 CmdName + " command " + Twine(LoadCommandIndex) + 296 " not past the headers of the file"); 297 uint64_t BigSize = s.offset; 298 BigSize += s.size; 299 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 300 Obj->getHeader().filetype != MachO::MH_DSYM && 301 s.flags != MachO::S_ZEROFILL && 302 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 303 BigSize > FileSize) 304 return malformedError("offset field plus size field of section " + 305 Twine(J) + " in " + CmdName + " command " + 306 Twine(LoadCommandIndex) + 307 " extends past the end of the file"); 308 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 309 Obj->getHeader().filetype != MachO::MH_DSYM && 310 s.flags != MachO::S_ZEROFILL && 311 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 312 s.size > S.filesize) 313 return malformedError("size field of section " + 314 Twine(J) + " in " + CmdName + " command " + 315 Twine(LoadCommandIndex) + 316 " greater than the segment"); 317 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 318 Obj->getHeader().filetype != MachO::MH_DSYM && s.size != 0 && 319 s.addr < S.vmaddr) 320 return malformedError("addr field of section " + Twine(J) + " in " + 321 CmdName + " command " + Twine(LoadCommandIndex) + 322 " less than the segment's vmaddr"); 323 BigSize = s.addr; 324 BigSize += s.size; 325 uint64_t BigEnd = S.vmaddr; 326 BigEnd += S.vmsize; 327 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd) 328 return malformedError("addr field plus size of section " + Twine(J) + 329 " in " + CmdName + " command " + 330 Twine(LoadCommandIndex) + 331 " greater than than " 332 "the segment's vmaddr plus vmsize"); 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 } 347 if (S.fileoff > FileSize) 348 return malformedError("load command " + Twine(LoadCommandIndex) + 349 " fileoff field in " + CmdName + 350 " extends past the end of the file"); 351 uint64_t BigSize = S.fileoff; 352 BigSize += S.filesize; 353 if (BigSize > FileSize) 354 return malformedError("load command " + Twine(LoadCommandIndex) + 355 " fileoff field plus filesize field in " + 356 CmdName + " extends past the end of the file"); 357 if (S.vmsize != 0 && S.filesize > S.vmsize) 358 return malformedError("load command " + Twine(LoadCommandIndex) + 359 " fileoff field in " + CmdName + 360 " greater than vmsize field"); 361 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); 362 } else 363 return SegOrErr.takeError(); 364 365 return Error::success(); 366 } 367 368 static Error checkSymtabCommand(const MachOObjectFile *Obj, 369 const MachOObjectFile::LoadCommandInfo &Load, 370 uint32_t LoadCommandIndex, 371 const char **SymtabLoadCmd, 372 std::list<MachOElement> &Elements) { 373 if (Load.C.cmdsize < sizeof(MachO::symtab_command)) 374 return malformedError("load command " + Twine(LoadCommandIndex) + 375 " LC_SYMTAB cmdsize too small"); 376 if (*SymtabLoadCmd != nullptr) 377 return malformedError("more than one LC_SYMTAB command"); 378 MachO::symtab_command Symtab = 379 getStruct<MachO::symtab_command>(Obj, Load.Ptr); 380 if (Symtab.cmdsize != sizeof(MachO::symtab_command)) 381 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) + 382 " has incorrect cmdsize"); 383 uint64_t FileSize = Obj->getData().size(); 384 if (Symtab.symoff > FileSize) 385 return malformedError("symoff field of LC_SYMTAB command " + 386 Twine(LoadCommandIndex) + " extends past the end " 387 "of the file"); 388 uint64_t SymtabSize = Symtab.nsyms; 389 const char *struct_nlist_name; 390 if (Obj->is64Bit()) { 391 SymtabSize *= sizeof(MachO::nlist_64); 392 struct_nlist_name = "struct nlist_64"; 393 } else { 394 SymtabSize *= sizeof(MachO::nlist); 395 struct_nlist_name = "struct nlist"; 396 } 397 uint64_t BigSize = SymtabSize; 398 BigSize += Symtab.symoff; 399 if (BigSize > FileSize) 400 return malformedError("symoff field plus nsyms field times sizeof(" + 401 Twine(struct_nlist_name) + ") of LC_SYMTAB command " + 402 Twine(LoadCommandIndex) + " extends past the end " 403 "of the file"); 404 if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize, 405 "symbol table")) 406 return Err; 407 if (Symtab.stroff > FileSize) 408 return malformedError("stroff field of LC_SYMTAB command " + 409 Twine(LoadCommandIndex) + " extends past the end " 410 "of the file"); 411 BigSize = Symtab.stroff; 412 BigSize += Symtab.strsize; 413 if (BigSize > FileSize) 414 return malformedError("stroff field plus strsize field of LC_SYMTAB " 415 "command " + Twine(LoadCommandIndex) + " extends " 416 "past the end of the file"); 417 if (Error Err = checkOverlappingElement(Elements, Symtab.stroff, 418 Symtab.strsize, "string table")) 419 return Err; 420 *SymtabLoadCmd = Load.Ptr; 421 return Error::success(); 422 } 423 424 static Error checkDysymtabCommand(const MachOObjectFile *Obj, 425 const MachOObjectFile::LoadCommandInfo &Load, 426 uint32_t LoadCommandIndex, 427 const char **DysymtabLoadCmd) { 428 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command)) 429 return malformedError("load command " + Twine(LoadCommandIndex) + 430 " LC_DYSYMTAB cmdsize too small"); 431 if (*DysymtabLoadCmd != nullptr) 432 return malformedError("more than one LC_DYSYMTAB command"); 433 MachO::dysymtab_command Dysymtab = 434 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr); 435 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command)) 436 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) + 437 " has incorrect cmdsize"); 438 uint64_t FileSize = Obj->getData().size(); 439 if (Dysymtab.tocoff > FileSize) 440 return malformedError("tocoff field of LC_DYSYMTAB command " + 441 Twine(LoadCommandIndex) + " extends past the end of " 442 "the file"); 443 uint64_t BigSize = Dysymtab.ntoc; 444 BigSize *= sizeof(MachO::dylib_table_of_contents); 445 BigSize += Dysymtab.tocoff; 446 if (BigSize > FileSize) 447 return malformedError("tocoff field plus ntoc field times sizeof(struct " 448 "dylib_table_of_contents) of LC_DYSYMTAB command " + 449 Twine(LoadCommandIndex) + " extends past the end of " 450 "the file"); 451 if (Dysymtab.modtaboff > FileSize) 452 return malformedError("modtaboff field of LC_DYSYMTAB command " + 453 Twine(LoadCommandIndex) + " extends past the end of " 454 "the file"); 455 BigSize = Dysymtab.nmodtab; 456 const char *struct_dylib_module_name; 457 if (Obj->is64Bit()) { 458 BigSize *= sizeof(MachO::dylib_module_64); 459 struct_dylib_module_name = "struct dylib_module_64"; 460 } else { 461 BigSize *= sizeof(MachO::dylib_module); 462 struct_dylib_module_name = "struct dylib_module"; 463 } 464 BigSize += Dysymtab.modtaboff; 465 if (BigSize > FileSize) 466 return malformedError("modtaboff field plus nmodtab field times sizeof(" + 467 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB " 468 "command " + Twine(LoadCommandIndex) + " extends " 469 "past the end of the file"); 470 if (Dysymtab.extrefsymoff > FileSize) 471 return malformedError("extrefsymoff field of LC_DYSYMTAB command " + 472 Twine(LoadCommandIndex) + " extends past the end of " 473 "the file"); 474 BigSize = Dysymtab.nextrefsyms; 475 BigSize *= sizeof(MachO::dylib_reference); 476 BigSize += Dysymtab.extrefsymoff; 477 if (BigSize > FileSize) 478 return malformedError("extrefsymoff field plus nextrefsyms field times " 479 "sizeof(struct dylib_reference) of LC_DYSYMTAB " 480 "command " + Twine(LoadCommandIndex) + " extends " 481 "past the end of the file"); 482 if (Dysymtab.indirectsymoff > FileSize) 483 return malformedError("indirectsymoff field of LC_DYSYMTAB command " + 484 Twine(LoadCommandIndex) + " extends past the end of " 485 "the file"); 486 BigSize = Dysymtab.nindirectsyms; 487 BigSize *= sizeof(uint32_t); 488 BigSize += Dysymtab.indirectsymoff; 489 if (BigSize > FileSize) 490 return malformedError("indirectsymoff field plus nindirectsyms field times " 491 "sizeof(uint32_t) of LC_DYSYMTAB command " + 492 Twine(LoadCommandIndex) + " extends past the end of " 493 "the file"); 494 if (Dysymtab.extreloff > FileSize) 495 return malformedError("extreloff field of LC_DYSYMTAB command " + 496 Twine(LoadCommandIndex) + " extends past the end of " 497 "the file"); 498 BigSize = Dysymtab.nextrel; 499 BigSize *= sizeof(MachO::relocation_info); 500 BigSize += Dysymtab.extreloff; 501 if (BigSize > FileSize) 502 return malformedError("extreloff field plus nextrel field times sizeof" 503 "(struct relocation_info) of LC_DYSYMTAB command " + 504 Twine(LoadCommandIndex) + " extends past the end of " 505 "the file"); 506 if (Dysymtab.locreloff > FileSize) 507 return malformedError("locreloff field of LC_DYSYMTAB command " + 508 Twine(LoadCommandIndex) + " extends past the end of " 509 "the file"); 510 BigSize = Dysymtab.nlocrel; 511 BigSize *= sizeof(MachO::relocation_info); 512 BigSize += Dysymtab.locreloff; 513 if (BigSize > FileSize) 514 return malformedError("locreloff field plus nlocrel field times sizeof" 515 "(struct relocation_info) of LC_DYSYMTAB command " + 516 Twine(LoadCommandIndex) + " extends past the end of " 517 "the file"); 518 *DysymtabLoadCmd = Load.Ptr; 519 return Error::success(); 520 } 521 522 static Error checkLinkeditDataCommand(const MachOObjectFile *Obj, 523 const MachOObjectFile::LoadCommandInfo &Load, 524 uint32_t LoadCommandIndex, 525 const char **LoadCmd, const char *CmdName) { 526 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command)) 527 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 528 CmdName + " cmdsize too small"); 529 if (*LoadCmd != nullptr) 530 return malformedError("more than one " + Twine(CmdName) + " command"); 531 MachO::linkedit_data_command LinkData = 532 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr); 533 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command)) 534 return malformedError(Twine(CmdName) + " command " + 535 Twine(LoadCommandIndex) + " has incorrect cmdsize"); 536 uint64_t FileSize = Obj->getData().size(); 537 if (LinkData.dataoff > FileSize) 538 return malformedError("dataoff field of " + Twine(CmdName) + " command " + 539 Twine(LoadCommandIndex) + " extends past the end of " 540 "the file"); 541 uint64_t BigSize = LinkData.dataoff; 542 BigSize += LinkData.datasize; 543 if (BigSize > FileSize) 544 return malformedError("dataoff field plus datasize field of " + 545 Twine(CmdName) + " command " + 546 Twine(LoadCommandIndex) + " extends past the end of " 547 "the file"); 548 *LoadCmd = Load.Ptr; 549 return Error::success(); 550 } 551 552 static Error checkDyldInfoCommand(const MachOObjectFile *Obj, 553 const MachOObjectFile::LoadCommandInfo &Load, 554 uint32_t LoadCommandIndex, 555 const char **LoadCmd, const char *CmdName) { 556 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command)) 557 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 558 CmdName + " cmdsize too small"); 559 if (*LoadCmd != nullptr) 560 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY " 561 "command"); 562 MachO::dyld_info_command DyldInfo = 563 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr); 564 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command)) 565 return malformedError(Twine(CmdName) + " command " + 566 Twine(LoadCommandIndex) + " has incorrect cmdsize"); 567 uint64_t FileSize = Obj->getData().size(); 568 if (DyldInfo.rebase_off > FileSize) 569 return malformedError("rebase_off field of " + Twine(CmdName) + 570 " command " + Twine(LoadCommandIndex) + " extends " 571 "past the end of the file"); 572 uint64_t BigSize = DyldInfo.rebase_off; 573 BigSize += DyldInfo.rebase_size; 574 if (BigSize > FileSize) 575 return malformedError("rebase_off field plus rebase_size field of " + 576 Twine(CmdName) + " command " + 577 Twine(LoadCommandIndex) + " extends past the end of " 578 "the file"); 579 if (DyldInfo.bind_off > FileSize) 580 return malformedError("bind_off field of " + Twine(CmdName) + 581 " command " + Twine(LoadCommandIndex) + " extends " 582 "past the end of the file"); 583 BigSize = DyldInfo.bind_off; 584 BigSize += DyldInfo.bind_size; 585 if (BigSize > FileSize) 586 return malformedError("bind_off field plus bind_size field of " + 587 Twine(CmdName) + " command " + 588 Twine(LoadCommandIndex) + " extends past the end of " 589 "the file"); 590 if (DyldInfo.weak_bind_off > FileSize) 591 return malformedError("weak_bind_off field of " + Twine(CmdName) + 592 " command " + Twine(LoadCommandIndex) + " extends " 593 "past the end of the file"); 594 BigSize = DyldInfo.weak_bind_off; 595 BigSize += DyldInfo.weak_bind_size; 596 if (BigSize > FileSize) 597 return malformedError("weak_bind_off field plus weak_bind_size field of " + 598 Twine(CmdName) + " command " + 599 Twine(LoadCommandIndex) + " extends past the end of " 600 "the file"); 601 if (DyldInfo.lazy_bind_off > FileSize) 602 return malformedError("lazy_bind_off field of " + Twine(CmdName) + 603 " command " + Twine(LoadCommandIndex) + " extends " 604 "past the end of the file"); 605 BigSize = DyldInfo.lazy_bind_off; 606 BigSize += DyldInfo.lazy_bind_size; 607 if (BigSize > FileSize) 608 return malformedError("lazy_bind_off field plus lazy_bind_size field of " + 609 Twine(CmdName) + " command " + 610 Twine(LoadCommandIndex) + " extends past the end of " 611 "the file"); 612 if (DyldInfo.export_off > FileSize) 613 return malformedError("export_off field of " + Twine(CmdName) + 614 " command " + Twine(LoadCommandIndex) + " extends " 615 "past the end of the file"); 616 BigSize = DyldInfo.export_off; 617 BigSize += DyldInfo.export_size; 618 if (BigSize > FileSize) 619 return malformedError("export_off field plus export_size field of " + 620 Twine(CmdName) + " command " + 621 Twine(LoadCommandIndex) + " extends past the end of " 622 "the file"); 623 *LoadCmd = Load.Ptr; 624 return Error::success(); 625 } 626 627 static Error checkDylibCommand(const MachOObjectFile *Obj, 628 const MachOObjectFile::LoadCommandInfo &Load, 629 uint32_t LoadCommandIndex, const char *CmdName) { 630 if (Load.C.cmdsize < sizeof(MachO::dylib_command)) 631 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 632 CmdName + " cmdsize too small"); 633 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr); 634 if (D.dylib.name < sizeof(MachO::dylib_command)) 635 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 636 CmdName + " name.offset field too small, not past " 637 "the end of the dylib_command struct"); 638 if (D.dylib.name >= D.cmdsize) 639 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 640 CmdName + " name.offset field extends past the end " 641 "of the load command"); 642 // Make sure there is a null between the starting offset of the name and 643 // the end of the load command. 644 uint32_t i; 645 const char *P = (const char *)Load.Ptr; 646 for (i = D.dylib.name; i < D.cmdsize; i++) 647 if (P[i] == '\0') 648 break; 649 if (i >= D.cmdsize) 650 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 651 CmdName + " library name extends past the end of the " 652 "load command"); 653 return Error::success(); 654 } 655 656 static Error checkDylibIdCommand(const MachOObjectFile *Obj, 657 const MachOObjectFile::LoadCommandInfo &Load, 658 uint32_t LoadCommandIndex, 659 const char **LoadCmd) { 660 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex, 661 "LC_ID_DYLIB")) 662 return Err; 663 if (*LoadCmd != nullptr) 664 return malformedError("more than one LC_ID_DYLIB command"); 665 if (Obj->getHeader().filetype != MachO::MH_DYLIB && 666 Obj->getHeader().filetype != MachO::MH_DYLIB_STUB) 667 return malformedError("LC_ID_DYLIB load command in non-dynamic library " 668 "file type"); 669 *LoadCmd = Load.Ptr; 670 return Error::success(); 671 } 672 673 static Error checkDyldCommand(const MachOObjectFile *Obj, 674 const MachOObjectFile::LoadCommandInfo &Load, 675 uint32_t LoadCommandIndex, const char *CmdName) { 676 if (Load.C.cmdsize < sizeof(MachO::dylinker_command)) 677 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 678 CmdName + " cmdsize too small"); 679 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr); 680 if (D.name < sizeof(MachO::dylinker_command)) 681 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 682 CmdName + " name.offset field too small, not past " 683 "the end of the dylinker_command struct"); 684 if (D.name >= D.cmdsize) 685 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 686 CmdName + " name.offset field extends past the end " 687 "of the load command"); 688 // Make sure there is a null between the starting offset of the name and 689 // the end of the load command. 690 uint32_t i; 691 const char *P = (const char *)Load.Ptr; 692 for (i = D.name; i < D.cmdsize; i++) 693 if (P[i] == '\0') 694 break; 695 if (i >= D.cmdsize) 696 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 697 CmdName + " dyld name extends past the end of the " 698 "load command"); 699 return Error::success(); 700 } 701 702 static Error checkVersCommand(const MachOObjectFile *Obj, 703 const MachOObjectFile::LoadCommandInfo &Load, 704 uint32_t LoadCommandIndex, 705 const char **LoadCmd, const char *CmdName) { 706 if (Load.C.cmdsize != sizeof(MachO::version_min_command)) 707 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 708 CmdName + " has incorrect cmdsize"); 709 if (*LoadCmd != nullptr) 710 return malformedError("more than one LC_VERSION_MIN_MACOSX, " 711 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or " 712 "LC_VERSION_MIN_WATCHOS command"); 713 *LoadCmd = Load.Ptr; 714 return Error::success(); 715 } 716 717 static Error checkRpathCommand(const MachOObjectFile *Obj, 718 const MachOObjectFile::LoadCommandInfo &Load, 719 uint32_t LoadCommandIndex) { 720 if (Load.C.cmdsize < sizeof(MachO::rpath_command)) 721 return malformedError("load command " + Twine(LoadCommandIndex) + 722 " LC_RPATH cmdsize too small"); 723 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr); 724 if (R.path < sizeof(MachO::rpath_command)) 725 return malformedError("load command " + Twine(LoadCommandIndex) + 726 " LC_RPATH path.offset field too small, not past " 727 "the end of the rpath_command struct"); 728 if (R.path >= R.cmdsize) 729 return malformedError("load command " + Twine(LoadCommandIndex) + 730 " LC_RPATH path.offset field extends past the end " 731 "of the load command"); 732 // Make sure there is a null between the starting offset of the path and 733 // the end of the load command. 734 uint32_t i; 735 const char *P = (const char *)Load.Ptr; 736 for (i = R.path; i < R.cmdsize; i++) 737 if (P[i] == '\0') 738 break; 739 if (i >= R.cmdsize) 740 return malformedError("load command " + Twine(LoadCommandIndex) + 741 " LC_RPATH library name extends past the end of the " 742 "load command"); 743 return Error::success(); 744 } 745 746 static Error checkEncryptCommand(const MachOObjectFile *Obj, 747 const MachOObjectFile::LoadCommandInfo &Load, 748 uint32_t LoadCommandIndex, 749 uint64_t cryptoff, uint64_t cryptsize, 750 const char **LoadCmd, const char *CmdName) { 751 if (*LoadCmd != nullptr) 752 return malformedError("more than one LC_ENCRYPTION_INFO and or " 753 "LC_ENCRYPTION_INFO_64 command"); 754 uint64_t FileSize = Obj->getData().size(); 755 if (cryptoff > FileSize) 756 return malformedError("cryptoff field of " + Twine(CmdName) + 757 " command " + Twine(LoadCommandIndex) + " extends " 758 "past the end of the file"); 759 uint64_t BigSize = cryptoff; 760 BigSize += cryptsize; 761 if (BigSize > FileSize) 762 return malformedError("cryptoff field plus cryptsize field of " + 763 Twine(CmdName) + " command " + 764 Twine(LoadCommandIndex) + " extends past the end of " 765 "the file"); 766 *LoadCmd = Load.Ptr; 767 return Error::success(); 768 } 769 770 static Error checkLinkerOptCommand(const MachOObjectFile *Obj, 771 const MachOObjectFile::LoadCommandInfo &Load, 772 uint32_t LoadCommandIndex) { 773 if (Load.C.cmdsize < sizeof(MachO::linker_option_command)) 774 return malformedError("load command " + Twine(LoadCommandIndex) + 775 " LC_LINKER_OPTION cmdsize too small"); 776 MachO::linker_option_command L = 777 getStruct<MachO::linker_option_command>(Obj, Load.Ptr); 778 // Make sure the count of strings is correct. 779 const char *string = (const char *)Load.Ptr + 780 sizeof(struct MachO::linker_option_command); 781 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command); 782 uint32_t i = 0; 783 while (left > 0) { 784 while (*string == '\0' && left > 0) { 785 string++; 786 left--; 787 } 788 if (left > 0) { 789 i++; 790 uint32_t NullPos = StringRef(string, left).find('\0'); 791 uint32_t len = std::min(NullPos, left) + 1; 792 string += len; 793 left -= len; 794 } 795 } 796 if (L.count != i) 797 return malformedError("load command " + Twine(LoadCommandIndex) + 798 " LC_LINKER_OPTION string count " + Twine(L.count) + 799 " does not match number of strings"); 800 return Error::success(); 801 } 802 803 static Error checkSubCommand(const MachOObjectFile *Obj, 804 const MachOObjectFile::LoadCommandInfo &Load, 805 uint32_t LoadCommandIndex, const char *CmdName, 806 size_t SizeOfCmd, const char *CmdStructName, 807 uint32_t PathOffset, const char *PathFieldName) { 808 if (PathOffset < SizeOfCmd) 809 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 810 CmdName + " " + PathFieldName + ".offset field too " 811 "small, not past the end of the " + CmdStructName); 812 if (PathOffset >= Load.C.cmdsize) 813 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 814 CmdName + " " + PathFieldName + ".offset field " 815 "extends past the end of the load command"); 816 // Make sure there is a null between the starting offset of the path and 817 // the end of the load command. 818 uint32_t i; 819 const char *P = (const char *)Load.Ptr; 820 for (i = PathOffset; i < Load.C.cmdsize; i++) 821 if (P[i] == '\0') 822 break; 823 if (i >= Load.C.cmdsize) 824 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 825 CmdName + " " + PathFieldName + " name extends past " 826 "the end of the load command"); 827 return Error::success(); 828 } 829 830 static Error checkThreadCommand(const MachOObjectFile *Obj, 831 const MachOObjectFile::LoadCommandInfo &Load, 832 uint32_t LoadCommandIndex, 833 const char *CmdName) { 834 if (Load.C.cmdsize < sizeof(MachO::thread_command)) 835 return malformedError("load command " + Twine(LoadCommandIndex) + 836 CmdName + " cmdsize too small"); 837 MachO::thread_command T = 838 getStruct<MachO::thread_command>(Obj, Load.Ptr); 839 const char *state = Load.Ptr + sizeof(MachO::thread_command); 840 const char *end = Load.Ptr + T.cmdsize; 841 uint32_t nflavor = 0; 842 uint32_t cputype = getCPUType(Obj); 843 while (state < end) { 844 if(state + sizeof(uint32_t) > end) 845 return malformedError("load command " + Twine(LoadCommandIndex) + 846 "flavor in " + CmdName + " extends past end of " 847 "command"); 848 uint32_t flavor; 849 memcpy(&flavor, state, sizeof(uint32_t)); 850 if (Obj->isLittleEndian() != sys::IsLittleEndianHost) 851 sys::swapByteOrder(flavor); 852 state += sizeof(uint32_t); 853 854 if(state + sizeof(uint32_t) > end) 855 return malformedError("load command " + Twine(LoadCommandIndex) + 856 " count in " + CmdName + " extends past end of " 857 "command"); 858 uint32_t count; 859 memcpy(&count, state, sizeof(uint32_t)); 860 if (Obj->isLittleEndian() != sys::IsLittleEndianHost) 861 sys::swapByteOrder(count); 862 state += sizeof(uint32_t); 863 864 if (cputype == MachO::CPU_TYPE_X86_64) { 865 if (flavor == MachO::x86_THREAD_STATE64) { 866 if (count != MachO::x86_THREAD_STATE64_COUNT) 867 return malformedError("load command " + Twine(LoadCommandIndex) + 868 " count not x86_THREAD_STATE64_COUNT for " 869 "flavor number " + Twine(nflavor) + " which is " 870 "a x86_THREAD_STATE64 flavor in " + CmdName + 871 " command"); 872 if (state + sizeof(MachO::x86_thread_state64_t) > end) 873 return malformedError("load command " + Twine(LoadCommandIndex) + 874 " x86_THREAD_STATE64 extends past end of " 875 "command in " + CmdName + " command"); 876 state += sizeof(MachO::x86_thread_state64_t); 877 } else { 878 return malformedError("load command " + Twine(LoadCommandIndex) + 879 " unknown flavor (" + Twine(flavor) + ") for " 880 "flavor number " + Twine(nflavor) + " in " + 881 CmdName + " command"); 882 } 883 } else if (cputype == MachO::CPU_TYPE_ARM) { 884 if (flavor == MachO::ARM_THREAD_STATE) { 885 if (count != MachO::ARM_THREAD_STATE_COUNT) 886 return malformedError("load command " + Twine(LoadCommandIndex) + 887 " count not ARM_THREAD_STATE_COUNT for " 888 "flavor number " + Twine(nflavor) + " which is " 889 "a ARM_THREAD_STATE flavor in " + CmdName + 890 " command"); 891 if (state + sizeof(MachO::arm_thread_state32_t) > end) 892 return malformedError("load command " + Twine(LoadCommandIndex) + 893 " ARM_THREAD_STATE extends past end of " 894 "command in " + CmdName + " command"); 895 state += sizeof(MachO::arm_thread_state32_t); 896 } else { 897 return malformedError("load command " + Twine(LoadCommandIndex) + 898 " unknown flavor (" + Twine(flavor) + ") for " 899 "flavor number " + Twine(nflavor) + " in " + 900 CmdName + " command"); 901 } 902 } else if (cputype == MachO::CPU_TYPE_POWERPC) { 903 if (flavor == MachO::PPC_THREAD_STATE) { 904 if (count != MachO::PPC_THREAD_STATE_COUNT) 905 return malformedError("load command " + Twine(LoadCommandIndex) + 906 " count not PPC_THREAD_STATE_COUNT for " 907 "flavor number " + Twine(nflavor) + " which is " 908 "a PPC_THREAD_STATE flavor in " + CmdName + 909 " command"); 910 if (state + sizeof(MachO::ppc_thread_state32_t) > end) 911 return malformedError("load command " + Twine(LoadCommandIndex) + 912 " PPC_THREAD_STATE extends past end of " 913 "command in " + CmdName + " command"); 914 state += sizeof(MachO::ppc_thread_state32_t); 915 } else { 916 return malformedError("load command " + Twine(LoadCommandIndex) + 917 " unknown flavor (" + Twine(flavor) + ") for " 918 "flavor number " + Twine(nflavor) + " in " + 919 CmdName + " command"); 920 } 921 } else { 922 return malformedError("unknown cputype (" + Twine(cputype) + ") load " 923 "command " + Twine(LoadCommandIndex) + " for " + 924 CmdName + " command can't be checked"); 925 } 926 nflavor++; 927 } 928 return Error::success(); 929 } 930 931 static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, 932 const MachOObjectFile::LoadCommandInfo 933 &Load, 934 uint32_t LoadCommandIndex, 935 const char **LoadCmd) { 936 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command)) 937 return malformedError("load command " + Twine(LoadCommandIndex) + 938 " LC_TWOLEVEL_HINTS has incorrect cmdsize"); 939 if (*LoadCmd != nullptr) 940 return malformedError("more than one LC_TWOLEVEL_HINTS command"); 941 MachO::twolevel_hints_command Hints = 942 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr); 943 uint64_t FileSize = Obj->getData().size(); 944 if (Hints.offset > FileSize) 945 return malformedError("offset field of LC_TWOLEVEL_HINTS command " + 946 Twine(LoadCommandIndex) + " extends past the end of " 947 "the file"); 948 uint64_t BigSize = Hints.nhints; 949 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint); 950 BigSize += Hints.offset; 951 if (BigSize > FileSize) 952 return malformedError("offset field plus nhints times sizeof(struct " 953 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " + 954 Twine(LoadCommandIndex) + " extends past the end of " 955 "the file"); 956 *LoadCmd = Load.Ptr; 957 return Error::success(); 958 } 959 960 // Returns true if the libObject code does not support the load command and its 961 // contents. The cmd value it is treated as an unknown load command but with 962 // an error message that says the cmd value is obsolete. 963 static bool isLoadCommandObsolete(uint32_t cmd) { 964 if (cmd == MachO::LC_SYMSEG || 965 cmd == MachO::LC_LOADFVMLIB || 966 cmd == MachO::LC_IDFVMLIB || 967 cmd == MachO::LC_IDENT || 968 cmd == MachO::LC_FVMFILE || 969 cmd == MachO::LC_PREPAGE || 970 cmd == MachO::LC_PREBOUND_DYLIB || 971 cmd == MachO::LC_TWOLEVEL_HINTS || 972 cmd == MachO::LC_PREBIND_CKSUM) 973 return true; 974 return false; 975 } 976 977 Expected<std::unique_ptr<MachOObjectFile>> 978 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, 979 bool Is64Bits, uint32_t UniversalCputype, 980 uint32_t UniversalIndex) { 981 Error Err; 982 std::unique_ptr<MachOObjectFile> Obj( 983 new MachOObjectFile(std::move(Object), IsLittleEndian, 984 Is64Bits, Err, UniversalCputype, 985 UniversalIndex)); 986 if (Err) 987 return std::move(Err); 988 return std::move(Obj); 989 } 990 991 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 992 bool Is64bits, Error &Err, 993 uint32_t UniversalCputype, 994 uint32_t UniversalIndex) 995 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 996 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 997 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 998 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 999 HasPageZeroSegment(false) { 1000 ErrorAsOutParameter ErrAsOutParam(&Err); 1001 uint64_t SizeOfHeaders; 1002 uint32_t cputype; 1003 if (is64Bit()) { 1004 parseHeader(this, Header64, Err); 1005 SizeOfHeaders = sizeof(MachO::mach_header_64); 1006 cputype = Header64.cputype; 1007 } else { 1008 parseHeader(this, Header, Err); 1009 SizeOfHeaders = sizeof(MachO::mach_header); 1010 cputype = Header.cputype; 1011 } 1012 if (Err) 1013 return; 1014 SizeOfHeaders += getHeader().sizeofcmds; 1015 if (getData().data() + SizeOfHeaders > getData().end()) { 1016 Err = malformedError("load commands extend past the end of the file"); 1017 return; 1018 } 1019 if (UniversalCputype != 0 && cputype != UniversalCputype) { 1020 Err = malformedError("universal header architecture: " + 1021 Twine(UniversalIndex) + "'s cputype does not match " 1022 "object file's mach header"); 1023 return; 1024 } 1025 std::list<MachOElement> Elements; 1026 Elements.push_back({0, SizeOfHeaders, "Mach-O headers"}); 1027 1028 uint32_t LoadCommandCount = getHeader().ncmds; 1029 LoadCommandInfo Load; 1030 if (LoadCommandCount != 0) { 1031 if (auto LoadOrErr = getFirstLoadCommandInfo(this)) 1032 Load = *LoadOrErr; 1033 else { 1034 Err = LoadOrErr.takeError(); 1035 return; 1036 } 1037 } 1038 1039 const char *DyldIdLoadCmd = nullptr; 1040 const char *FuncStartsLoadCmd = nullptr; 1041 const char *SplitInfoLoadCmd = nullptr; 1042 const char *CodeSignDrsLoadCmd = nullptr; 1043 const char *CodeSignLoadCmd = nullptr; 1044 const char *VersLoadCmd = nullptr; 1045 const char *SourceLoadCmd = nullptr; 1046 const char *EntryPointLoadCmd = nullptr; 1047 const char *EncryptLoadCmd = nullptr; 1048 const char *RoutinesLoadCmd = nullptr; 1049 const char *UnixThreadLoadCmd = nullptr; 1050 const char *TwoLevelHintsLoadCmd = nullptr; 1051 for (unsigned I = 0; I < LoadCommandCount; ++I) { 1052 if (is64Bit()) { 1053 if (Load.C.cmdsize % 8 != 0) { 1054 // We have a hack here to allow 64-bit Mach-O core files to have 1055 // LC_THREAD commands that are only a multiple of 4 and not 8 to be 1056 // allowed since the macOS kernel produces them. 1057 if (getHeader().filetype != MachO::MH_CORE || 1058 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { 1059 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 1060 "multiple of 8"); 1061 return; 1062 } 1063 } 1064 } else { 1065 if (Load.C.cmdsize % 4 != 0) { 1066 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 1067 "multiple of 4"); 1068 return; 1069 } 1070 } 1071 LoadCommands.push_back(Load); 1072 if (Load.C.cmd == MachO::LC_SYMTAB) { 1073 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd, Elements))) 1074 return; 1075 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 1076 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd))) 1077 return; 1078 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 1079 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd, 1080 "LC_DATA_IN_CODE"))) 1081 return; 1082 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 1083 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, 1084 "LC_LINKER_OPTIMIZATION_HINT"))) 1085 return; 1086 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) { 1087 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd, 1088 "LC_FUNCTION_STARTS"))) 1089 return; 1090 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) { 1091 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd, 1092 "LC_SEGMENT_SPLIT_INFO"))) 1093 return; 1094 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) { 1095 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd, 1096 "LC_DYLIB_CODE_SIGN_DRS"))) 1097 return; 1098 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) { 1099 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd, 1100 "LC_CODE_SIGNATURE"))) 1101 return; 1102 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { 1103 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1104 "LC_DYLD_INFO"))) 1105 return; 1106 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 1107 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1108 "LC_DYLD_INFO_ONLY"))) 1109 return; 1110 } else if (Load.C.cmd == MachO::LC_UUID) { 1111 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { 1112 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " 1113 "cmdsize"); 1114 return; 1115 } 1116 if (UuidLoadCmd) { 1117 Err = malformedError("more than one LC_UUID command"); 1118 return; 1119 } 1120 UuidLoadCmd = Load.Ptr; 1121 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1122 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64, 1123 MachO::section_64>( 1124 this, Load, Sections, HasPageZeroSegment, I, 1125 "LC_SEGMENT_64", SizeOfHeaders))) 1126 return; 1127 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1128 if ((Err = parseSegmentLoadCommand<MachO::segment_command, 1129 MachO::section>( 1130 this, Load, Sections, HasPageZeroSegment, I, 1131 "LC_SEGMENT", SizeOfHeaders))) 1132 return; 1133 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) { 1134 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd))) 1135 return; 1136 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) { 1137 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB"))) 1138 return; 1139 Libraries.push_back(Load.Ptr); 1140 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) { 1141 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB"))) 1142 return; 1143 Libraries.push_back(Load.Ptr); 1144 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) { 1145 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB"))) 1146 return; 1147 Libraries.push_back(Load.Ptr); 1148 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) { 1149 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB"))) 1150 return; 1151 Libraries.push_back(Load.Ptr); 1152 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 1153 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB"))) 1154 return; 1155 Libraries.push_back(Load.Ptr); 1156 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) { 1157 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER"))) 1158 return; 1159 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) { 1160 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER"))) 1161 return; 1162 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 1163 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT"))) 1164 return; 1165 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) { 1166 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1167 "LC_VERSION_MIN_MACOSX"))) 1168 return; 1169 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { 1170 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1171 "LC_VERSION_MIN_IPHONEOS"))) 1172 return; 1173 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) { 1174 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1175 "LC_VERSION_MIN_TVOS"))) 1176 return; 1177 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 1178 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1179 "LC_VERSION_MIN_WATCHOS"))) 1180 return; 1181 } else if (Load.C.cmd == MachO::LC_RPATH) { 1182 if ((Err = checkRpathCommand(this, Load, I))) 1183 return; 1184 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) { 1185 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) { 1186 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) + 1187 " has incorrect cmdsize"); 1188 return; 1189 } 1190 if (SourceLoadCmd) { 1191 Err = malformedError("more than one LC_SOURCE_VERSION command"); 1192 return; 1193 } 1194 SourceLoadCmd = Load.Ptr; 1195 } else if (Load.C.cmd == MachO::LC_MAIN) { 1196 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) { 1197 Err = malformedError("LC_MAIN command " + Twine(I) + 1198 " has incorrect cmdsize"); 1199 return; 1200 } 1201 if (EntryPointLoadCmd) { 1202 Err = malformedError("more than one LC_MAIN command"); 1203 return; 1204 } 1205 EntryPointLoadCmd = Load.Ptr; 1206 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) { 1207 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) { 1208 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) + 1209 " has incorrect cmdsize"); 1210 return; 1211 } 1212 MachO::encryption_info_command E = 1213 getStruct<MachO::encryption_info_command>(this, Load.Ptr); 1214 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1215 &EncryptLoadCmd, "LC_ENCRYPTION_INFO"))) 1216 return; 1217 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 1218 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) { 1219 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) + 1220 " has incorrect cmdsize"); 1221 return; 1222 } 1223 MachO::encryption_info_command_64 E = 1224 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr); 1225 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1226 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64"))) 1227 return; 1228 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) { 1229 if ((Err = checkLinkerOptCommand(this, Load, I))) 1230 return; 1231 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) { 1232 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) { 1233 Err = malformedError("load command " + Twine(I) + 1234 " LC_SUB_FRAMEWORK cmdsize too small"); 1235 return; 1236 } 1237 MachO::sub_framework_command S = 1238 getStruct<MachO::sub_framework_command>(this, Load.Ptr); 1239 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK", 1240 sizeof(MachO::sub_framework_command), 1241 "sub_framework_command", S.umbrella, 1242 "umbrella"))) 1243 return; 1244 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) { 1245 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) { 1246 Err = malformedError("load command " + Twine(I) + 1247 " LC_SUB_UMBRELLA cmdsize too small"); 1248 return; 1249 } 1250 MachO::sub_umbrella_command S = 1251 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr); 1252 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA", 1253 sizeof(MachO::sub_umbrella_command), 1254 "sub_umbrella_command", S.sub_umbrella, 1255 "sub_umbrella"))) 1256 return; 1257 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) { 1258 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) { 1259 Err = malformedError("load command " + Twine(I) + 1260 " LC_SUB_LIBRARY cmdsize too small"); 1261 return; 1262 } 1263 MachO::sub_library_command S = 1264 getStruct<MachO::sub_library_command>(this, Load.Ptr); 1265 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY", 1266 sizeof(MachO::sub_library_command), 1267 "sub_library_command", S.sub_library, 1268 "sub_library"))) 1269 return; 1270 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) { 1271 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) { 1272 Err = malformedError("load command " + Twine(I) + 1273 " LC_SUB_CLIENT cmdsize too small"); 1274 return; 1275 } 1276 MachO::sub_client_command S = 1277 getStruct<MachO::sub_client_command>(this, Load.Ptr); 1278 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT", 1279 sizeof(MachO::sub_client_command), 1280 "sub_client_command", S.client, "client"))) 1281 return; 1282 } else if (Load.C.cmd == MachO::LC_ROUTINES) { 1283 if (Load.C.cmdsize != sizeof(MachO::routines_command)) { 1284 Err = malformedError("LC_ROUTINES command " + Twine(I) + 1285 " has incorrect cmdsize"); 1286 return; 1287 } 1288 if (RoutinesLoadCmd) { 1289 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 " 1290 "command"); 1291 return; 1292 } 1293 RoutinesLoadCmd = Load.Ptr; 1294 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) { 1295 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) { 1296 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) + 1297 " has incorrect cmdsize"); 1298 return; 1299 } 1300 if (RoutinesLoadCmd) { 1301 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES " 1302 "command"); 1303 return; 1304 } 1305 RoutinesLoadCmd = Load.Ptr; 1306 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) { 1307 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD"))) 1308 return; 1309 if (UnixThreadLoadCmd) { 1310 Err = malformedError("more than one LC_UNIXTHREAD command"); 1311 return; 1312 } 1313 UnixThreadLoadCmd = Load.Ptr; 1314 } else if (Load.C.cmd == MachO::LC_THREAD) { 1315 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD"))) 1316 return; 1317 // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported. 1318 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) { 1319 if ((Err = checkTwoLevelHintsCommand(this, Load, I, 1320 &TwoLevelHintsLoadCmd))) 1321 return; 1322 } else if (isLoadCommandObsolete(Load.C.cmd)) { 1323 Err = malformedError("load command " + Twine(I) + " for cmd value of: " + 1324 Twine(Load.C.cmd) + " is obsolete and not " 1325 "supported"); 1326 return; 1327 } 1328 // TODO: generate a error for unknown load commands by default. But still 1329 // need work out an approach to allow or not allow unknown values like this 1330 // as an option for some uses like lldb. 1331 if (I < LoadCommandCount - 1) { 1332 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) 1333 Load = *LoadOrErr; 1334 else { 1335 Err = LoadOrErr.takeError(); 1336 return; 1337 } 1338 } 1339 } 1340 if (!SymtabLoadCmd) { 1341 if (DysymtabLoadCmd) { 1342 Err = malformedError("contains LC_DYSYMTAB load command without a " 1343 "LC_SYMTAB load command"); 1344 return; 1345 } 1346 } else if (DysymtabLoadCmd) { 1347 MachO::symtab_command Symtab = 1348 getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1349 MachO::dysymtab_command Dysymtab = 1350 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1351 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1352 Err = malformedError("ilocalsym in LC_DYSYMTAB load command " 1353 "extends past the end of the symbol table"); 1354 return; 1355 } 1356 uint64_t BigSize = Dysymtab.ilocalsym; 1357 BigSize += Dysymtab.nlocalsym; 1358 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { 1359 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " 1360 "command extends past the end of the symbol table"); 1361 return; 1362 } 1363 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1364 Err = malformedError("nextdefsym in LC_DYSYMTAB load command " 1365 "extends past the end of the symbol table"); 1366 return; 1367 } 1368 BigSize = Dysymtab.iextdefsym; 1369 BigSize += Dysymtab.nextdefsym; 1370 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { 1371 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " 1372 "load command extends past the end of the symbol " 1373 "table"); 1374 return; 1375 } 1376 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { 1377 Err = malformedError("nundefsym in LC_DYSYMTAB load command " 1378 "extends past the end of the symbol table"); 1379 return; 1380 } 1381 BigSize = Dysymtab.iundefsym; 1382 BigSize += Dysymtab.nundefsym; 1383 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { 1384 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " 1385 " command extends past the end of the symbol table"); 1386 return; 1387 } 1388 } 1389 if ((getHeader().filetype == MachO::MH_DYLIB || 1390 getHeader().filetype == MachO::MH_DYLIB_STUB) && 1391 DyldIdLoadCmd == nullptr) { 1392 Err = malformedError("no LC_ID_DYLIB load command in dynamic library " 1393 "filetype"); 1394 return; 1395 } 1396 assert(LoadCommands.size() == LoadCommandCount); 1397 1398 Err = Error::success(); 1399 } 1400 1401 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1402 unsigned SymbolTableEntrySize = is64Bit() ? 1403 sizeof(MachO::nlist_64) : 1404 sizeof(MachO::nlist); 1405 Symb.p += SymbolTableEntrySize; 1406 } 1407 1408 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 1409 StringRef StringTable = getStringTableData(); 1410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1411 const char *Start = &StringTable.data()[Entry.n_strx]; 1412 if (Start < getData().begin() || Start >= getData().end()) { 1413 return malformedError("bad string index: " + Twine(Entry.n_strx) + 1414 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1415 } 1416 return StringRef(Start); 1417 } 1418 1419 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 1420 DataRefImpl DRI = Sec.getRawDataRefImpl(); 1421 uint32_t Flags = getSectionFlags(this, DRI); 1422 return Flags & MachO::SECTION_TYPE; 1423 } 1424 1425 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 1426 if (is64Bit()) { 1427 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 1428 return Entry.n_value; 1429 } 1430 MachO::nlist Entry = getSymbolTableEntry(Sym); 1431 return Entry.n_value; 1432 } 1433 1434 // getIndirectName() returns the name of the alias'ed symbol who's string table 1435 // index is in the n_value field. 1436 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 1437 StringRef &Res) const { 1438 StringRef StringTable = getStringTableData(); 1439 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1440 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 1441 return object_error::parse_failed; 1442 uint64_t NValue = getNValue(Symb); 1443 if (NValue >= StringTable.size()) 1444 return object_error::parse_failed; 1445 const char *Start = &StringTable.data()[NValue]; 1446 Res = StringRef(Start); 1447 return std::error_code(); 1448 } 1449 1450 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { 1451 return getNValue(Sym); 1452 } 1453 1454 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { 1455 return getSymbolValue(Sym); 1456 } 1457 1458 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 1459 uint32_t flags = getSymbolFlags(DRI); 1460 if (flags & SymbolRef::SF_Common) { 1461 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1462 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 1463 } 1464 return 0; 1465 } 1466 1467 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 1468 return getNValue(DRI); 1469 } 1470 1471 Expected<SymbolRef::Type> 1472 MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 1473 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1474 uint8_t n_type = Entry.n_type; 1475 1476 // If this is a STAB debugging symbol, we can do nothing more. 1477 if (n_type & MachO::N_STAB) 1478 return SymbolRef::ST_Debug; 1479 1480 switch (n_type & MachO::N_TYPE) { 1481 case MachO::N_UNDF : 1482 return SymbolRef::ST_Unknown; 1483 case MachO::N_SECT : 1484 Expected<section_iterator> SecOrError = getSymbolSection(Symb); 1485 if (!SecOrError) 1486 return SecOrError.takeError(); 1487 section_iterator Sec = *SecOrError; 1488 if (Sec->isData() || Sec->isBSS()) 1489 return SymbolRef::ST_Data; 1490 return SymbolRef::ST_Function; 1491 } 1492 return SymbolRef::ST_Other; 1493 } 1494 1495 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 1496 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1497 1498 uint8_t MachOType = Entry.n_type; 1499 uint16_t MachOFlags = Entry.n_desc; 1500 1501 uint32_t Result = SymbolRef::SF_None; 1502 1503 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 1504 Result |= SymbolRef::SF_Indirect; 1505 1506 if (MachOType & MachO::N_STAB) 1507 Result |= SymbolRef::SF_FormatSpecific; 1508 1509 if (MachOType & MachO::N_EXT) { 1510 Result |= SymbolRef::SF_Global; 1511 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 1512 if (getNValue(DRI)) 1513 Result |= SymbolRef::SF_Common; 1514 else 1515 Result |= SymbolRef::SF_Undefined; 1516 } 1517 1518 if (!(MachOType & MachO::N_PEXT)) 1519 Result |= SymbolRef::SF_Exported; 1520 } 1521 1522 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 1523 Result |= SymbolRef::SF_Weak; 1524 1525 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 1526 Result |= SymbolRef::SF_Thumb; 1527 1528 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 1529 Result |= SymbolRef::SF_Absolute; 1530 1531 return Result; 1532 } 1533 1534 Expected<section_iterator> 1535 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { 1536 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1537 uint8_t index = Entry.n_sect; 1538 1539 if (index == 0) 1540 return section_end(); 1541 DataRefImpl DRI; 1542 DRI.d.a = index - 1; 1543 if (DRI.d.a >= Sections.size()){ 1544 return malformedError("bad section index: " + Twine((int)index) + 1545 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1546 } 1547 return section_iterator(SectionRef(DRI, this)); 1548 } 1549 1550 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 1551 MachO::nlist_base Entry = 1552 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 1553 return Entry.n_sect - 1; 1554 } 1555 1556 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 1557 Sec.d.a++; 1558 } 1559 1560 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 1561 StringRef &Result) const { 1562 ArrayRef<char> Raw = getSectionRawName(Sec); 1563 Result = parseSegmentOrSectionName(Raw.data()); 1564 return std::error_code(); 1565 } 1566 1567 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 1568 if (is64Bit()) 1569 return getSection64(Sec).addr; 1570 return getSection(Sec).addr; 1571 } 1572 1573 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 1574 // In the case if a malformed Mach-O file where the section offset is past 1575 // the end of the file or some part of the section size is past the end of 1576 // the file return a size of zero or a size that covers the rest of the file 1577 // but does not extend past the end of the file. 1578 uint32_t SectOffset, SectType; 1579 uint64_t SectSize; 1580 1581 if (is64Bit()) { 1582 MachO::section_64 Sect = getSection64(Sec); 1583 SectOffset = Sect.offset; 1584 SectSize = Sect.size; 1585 SectType = Sect.flags & MachO::SECTION_TYPE; 1586 } else { 1587 MachO::section Sect = getSection(Sec); 1588 SectOffset = Sect.offset; 1589 SectSize = Sect.size; 1590 SectType = Sect.flags & MachO::SECTION_TYPE; 1591 } 1592 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL) 1593 return SectSize; 1594 uint64_t FileSize = getData().size(); 1595 if (SectOffset > FileSize) 1596 return 0; 1597 if (FileSize - SectOffset < SectSize) 1598 return FileSize - SectOffset; 1599 return SectSize; 1600 } 1601 1602 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 1603 StringRef &Res) const { 1604 uint32_t Offset; 1605 uint64_t Size; 1606 1607 if (is64Bit()) { 1608 MachO::section_64 Sect = getSection64(Sec); 1609 Offset = Sect.offset; 1610 Size = Sect.size; 1611 } else { 1612 MachO::section Sect = getSection(Sec); 1613 Offset = Sect.offset; 1614 Size = Sect.size; 1615 } 1616 1617 Res = this->getData().substr(Offset, Size); 1618 return std::error_code(); 1619 } 1620 1621 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1622 uint32_t Align; 1623 if (is64Bit()) { 1624 MachO::section_64 Sect = getSection64(Sec); 1625 Align = Sect.align; 1626 } else { 1627 MachO::section Sect = getSection(Sec); 1628 Align = Sect.align; 1629 } 1630 1631 return uint64_t(1) << Align; 1632 } 1633 1634 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1635 return false; 1636 } 1637 1638 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 1639 uint32_t Flags = getSectionFlags(this, Sec); 1640 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 1641 } 1642 1643 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 1644 uint32_t Flags = getSectionFlags(this, Sec); 1645 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1646 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1647 !(SectionType == MachO::S_ZEROFILL || 1648 SectionType == MachO::S_GB_ZEROFILL); 1649 } 1650 1651 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 1652 uint32_t Flags = getSectionFlags(this, Sec); 1653 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1654 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1655 (SectionType == MachO::S_ZEROFILL || 1656 SectionType == MachO::S_GB_ZEROFILL); 1657 } 1658 1659 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 1660 return Sec.getRawDataRefImpl().d.a; 1661 } 1662 1663 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 1664 // FIXME: Unimplemented. 1665 return false; 1666 } 1667 1668 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { 1669 StringRef SegmentName = getSectionFinalSegmentName(Sec); 1670 StringRef SectName; 1671 if (!getSectionName(Sec, SectName)) 1672 return (SegmentName == "__LLVM" && SectName == "__bitcode"); 1673 return false; 1674 } 1675 1676 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1677 DataRefImpl Ret; 1678 Ret.d.a = Sec.d.a; 1679 Ret.d.b = 0; 1680 return relocation_iterator(RelocationRef(Ret, this)); 1681 } 1682 1683 relocation_iterator 1684 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1685 uint32_t Num; 1686 if (is64Bit()) { 1687 MachO::section_64 Sect = getSection64(Sec); 1688 Num = Sect.nreloc; 1689 } else { 1690 MachO::section Sect = getSection(Sec); 1691 Num = Sect.nreloc; 1692 } 1693 1694 DataRefImpl Ret; 1695 Ret.d.a = Sec.d.a; 1696 Ret.d.b = Num; 1697 return relocation_iterator(RelocationRef(Ret, this)); 1698 } 1699 1700 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1701 ++Rel.d.b; 1702 } 1703 1704 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1705 assert(getHeader().filetype == MachO::MH_OBJECT && 1706 "Only implemented for MH_OBJECT"); 1707 MachO::any_relocation_info RE = getRelocation(Rel); 1708 return getAnyRelocationAddress(RE); 1709 } 1710 1711 symbol_iterator 1712 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1713 MachO::any_relocation_info RE = getRelocation(Rel); 1714 if (isRelocationScattered(RE)) 1715 return symbol_end(); 1716 1717 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1718 bool isExtern = getPlainRelocationExternal(RE); 1719 if (!isExtern) 1720 return symbol_end(); 1721 1722 MachO::symtab_command S = getSymtabLoadCommand(); 1723 unsigned SymbolTableEntrySize = is64Bit() ? 1724 sizeof(MachO::nlist_64) : 1725 sizeof(MachO::nlist); 1726 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1727 DataRefImpl Sym; 1728 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1729 return symbol_iterator(SymbolRef(Sym, this)); 1730 } 1731 1732 section_iterator 1733 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 1734 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 1735 } 1736 1737 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 1738 MachO::any_relocation_info RE = getRelocation(Rel); 1739 return getAnyRelocationType(RE); 1740 } 1741 1742 void MachOObjectFile::getRelocationTypeName( 1743 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1744 StringRef res; 1745 uint64_t RType = getRelocationType(Rel); 1746 1747 unsigned Arch = this->getArch(); 1748 1749 switch (Arch) { 1750 case Triple::x86: { 1751 static const char *const Table[] = { 1752 "GENERIC_RELOC_VANILLA", 1753 "GENERIC_RELOC_PAIR", 1754 "GENERIC_RELOC_SECTDIFF", 1755 "GENERIC_RELOC_PB_LA_PTR", 1756 "GENERIC_RELOC_LOCAL_SECTDIFF", 1757 "GENERIC_RELOC_TLV" }; 1758 1759 if (RType > 5) 1760 res = "Unknown"; 1761 else 1762 res = Table[RType]; 1763 break; 1764 } 1765 case Triple::x86_64: { 1766 static const char *const Table[] = { 1767 "X86_64_RELOC_UNSIGNED", 1768 "X86_64_RELOC_SIGNED", 1769 "X86_64_RELOC_BRANCH", 1770 "X86_64_RELOC_GOT_LOAD", 1771 "X86_64_RELOC_GOT", 1772 "X86_64_RELOC_SUBTRACTOR", 1773 "X86_64_RELOC_SIGNED_1", 1774 "X86_64_RELOC_SIGNED_2", 1775 "X86_64_RELOC_SIGNED_4", 1776 "X86_64_RELOC_TLV" }; 1777 1778 if (RType > 9) 1779 res = "Unknown"; 1780 else 1781 res = Table[RType]; 1782 break; 1783 } 1784 case Triple::arm: { 1785 static const char *const Table[] = { 1786 "ARM_RELOC_VANILLA", 1787 "ARM_RELOC_PAIR", 1788 "ARM_RELOC_SECTDIFF", 1789 "ARM_RELOC_LOCAL_SECTDIFF", 1790 "ARM_RELOC_PB_LA_PTR", 1791 "ARM_RELOC_BR24", 1792 "ARM_THUMB_RELOC_BR22", 1793 "ARM_THUMB_32BIT_BRANCH", 1794 "ARM_RELOC_HALF", 1795 "ARM_RELOC_HALF_SECTDIFF" }; 1796 1797 if (RType > 9) 1798 res = "Unknown"; 1799 else 1800 res = Table[RType]; 1801 break; 1802 } 1803 case Triple::aarch64: { 1804 static const char *const Table[] = { 1805 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 1806 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 1807 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 1808 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 1809 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 1810 "ARM64_RELOC_ADDEND" 1811 }; 1812 1813 if (RType >= array_lengthof(Table)) 1814 res = "Unknown"; 1815 else 1816 res = Table[RType]; 1817 break; 1818 } 1819 case Triple::ppc: { 1820 static const char *const Table[] = { 1821 "PPC_RELOC_VANILLA", 1822 "PPC_RELOC_PAIR", 1823 "PPC_RELOC_BR14", 1824 "PPC_RELOC_BR24", 1825 "PPC_RELOC_HI16", 1826 "PPC_RELOC_LO16", 1827 "PPC_RELOC_HA16", 1828 "PPC_RELOC_LO14", 1829 "PPC_RELOC_SECTDIFF", 1830 "PPC_RELOC_PB_LA_PTR", 1831 "PPC_RELOC_HI16_SECTDIFF", 1832 "PPC_RELOC_LO16_SECTDIFF", 1833 "PPC_RELOC_HA16_SECTDIFF", 1834 "PPC_RELOC_JBSR", 1835 "PPC_RELOC_LO14_SECTDIFF", 1836 "PPC_RELOC_LOCAL_SECTDIFF" }; 1837 1838 if (RType > 15) 1839 res = "Unknown"; 1840 else 1841 res = Table[RType]; 1842 break; 1843 } 1844 case Triple::UnknownArch: 1845 res = "Unknown"; 1846 break; 1847 } 1848 Result.append(res.begin(), res.end()); 1849 } 1850 1851 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 1852 MachO::any_relocation_info RE = getRelocation(Rel); 1853 return getAnyRelocationLength(RE); 1854 } 1855 1856 // 1857 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1858 // guess on what the short name is. Then name is returned as a substring of the 1859 // StringRef Name passed in. The name of the dynamic library is recognized as 1860 // a framework if it has one of the two following forms: 1861 // Foo.framework/Versions/A/Foo 1862 // Foo.framework/Foo 1863 // Where A and Foo can be any string. And may contain a trailing suffix 1864 // starting with an underbar. If the Name is recognized as a framework then 1865 // isFramework is set to true else it is set to false. If the Name has a 1866 // suffix then Suffix is set to the substring in Name that contains the suffix 1867 // else it is set to a NULL StringRef. 1868 // 1869 // The Name of the dynamic library is recognized as a library name if it has 1870 // one of the two following forms: 1871 // libFoo.A.dylib 1872 // libFoo.dylib 1873 // The library may have a suffix trailing the name Foo of the form: 1874 // libFoo_profile.A.dylib 1875 // libFoo_profile.dylib 1876 // 1877 // The Name of the dynamic library is also recognized as a library name if it 1878 // has the following form: 1879 // Foo.qtx 1880 // 1881 // If the Name of the dynamic library is none of the forms above then a NULL 1882 // StringRef is returned. 1883 // 1884 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1885 bool &isFramework, 1886 StringRef &Suffix) { 1887 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1888 size_t a, b, c, d, Idx; 1889 1890 isFramework = false; 1891 Suffix = StringRef(); 1892 1893 // Pull off the last component and make Foo point to it 1894 a = Name.rfind('/'); 1895 if (a == Name.npos || a == 0) 1896 goto guess_library; 1897 Foo = Name.slice(a+1, Name.npos); 1898 1899 // Look for a suffix starting with a '_' 1900 Idx = Foo.rfind('_'); 1901 if (Idx != Foo.npos && Foo.size() >= 2) { 1902 Suffix = Foo.slice(Idx, Foo.npos); 1903 Foo = Foo.slice(0, Idx); 1904 } 1905 1906 // First look for the form Foo.framework/Foo 1907 b = Name.rfind('/', a); 1908 if (b == Name.npos) 1909 Idx = 0; 1910 else 1911 Idx = b+1; 1912 F = Name.slice(Idx, Idx + Foo.size()); 1913 DotFramework = Name.slice(Idx + Foo.size(), 1914 Idx + Foo.size() + sizeof(".framework/")-1); 1915 if (F == Foo && DotFramework == ".framework/") { 1916 isFramework = true; 1917 return Foo; 1918 } 1919 1920 // Next look for the form Foo.framework/Versions/A/Foo 1921 if (b == Name.npos) 1922 goto guess_library; 1923 c = Name.rfind('/', b); 1924 if (c == Name.npos || c == 0) 1925 goto guess_library; 1926 V = Name.slice(c+1, Name.npos); 1927 if (!V.startswith("Versions/")) 1928 goto guess_library; 1929 d = Name.rfind('/', c); 1930 if (d == Name.npos) 1931 Idx = 0; 1932 else 1933 Idx = d+1; 1934 F = Name.slice(Idx, Idx + Foo.size()); 1935 DotFramework = Name.slice(Idx + Foo.size(), 1936 Idx + Foo.size() + sizeof(".framework/")-1); 1937 if (F == Foo && DotFramework == ".framework/") { 1938 isFramework = true; 1939 return Foo; 1940 } 1941 1942 guess_library: 1943 // pull off the suffix after the "." and make a point to it 1944 a = Name.rfind('.'); 1945 if (a == Name.npos || a == 0) 1946 return StringRef(); 1947 Dylib = Name.slice(a, Name.npos); 1948 if (Dylib != ".dylib") 1949 goto guess_qtx; 1950 1951 // First pull off the version letter for the form Foo.A.dylib if any. 1952 if (a >= 3) { 1953 Dot = Name.slice(a-2, a-1); 1954 if (Dot == ".") 1955 a = a - 2; 1956 } 1957 1958 b = Name.rfind('/', a); 1959 if (b == Name.npos) 1960 b = 0; 1961 else 1962 b = b+1; 1963 // ignore any suffix after an underbar like Foo_profile.A.dylib 1964 Idx = Name.find('_', b); 1965 if (Idx != Name.npos && Idx != b) { 1966 Lib = Name.slice(b, Idx); 1967 Suffix = Name.slice(Idx, a); 1968 } 1969 else 1970 Lib = Name.slice(b, a); 1971 // There are incorrect library names of the form: 1972 // libATS.A_profile.dylib so check for these. 1973 if (Lib.size() >= 3) { 1974 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1975 if (Dot == ".") 1976 Lib = Lib.slice(0, Lib.size()-2); 1977 } 1978 return Lib; 1979 1980 guess_qtx: 1981 Qtx = Name.slice(a, Name.npos); 1982 if (Qtx != ".qtx") 1983 return StringRef(); 1984 b = Name.rfind('/', a); 1985 if (b == Name.npos) 1986 Lib = Name.slice(0, a); 1987 else 1988 Lib = Name.slice(b+1, a); 1989 // There are library names of the form: QT.A.qtx so check for these. 1990 if (Lib.size() >= 3) { 1991 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1992 if (Dot == ".") 1993 Lib = Lib.slice(0, Lib.size()-2); 1994 } 1995 return Lib; 1996 } 1997 1998 // getLibraryShortNameByIndex() is used to get the short name of the library 1999 // for an undefined symbol in a linked Mach-O binary that was linked with the 2000 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 2001 // It is passed the index (0 - based) of the library as translated from 2002 // GET_LIBRARY_ORDINAL (1 - based). 2003 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 2004 StringRef &Res) const { 2005 if (Index >= Libraries.size()) 2006 return object_error::parse_failed; 2007 2008 // If the cache of LibrariesShortNames is not built up do that first for 2009 // all the Libraries. 2010 if (LibrariesShortNames.size() == 0) { 2011 for (unsigned i = 0; i < Libraries.size(); i++) { 2012 MachO::dylib_command D = 2013 getStruct<MachO::dylib_command>(this, Libraries[i]); 2014 if (D.dylib.name >= D.cmdsize) 2015 return object_error::parse_failed; 2016 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 2017 StringRef Name = StringRef(P); 2018 if (D.dylib.name+Name.size() >= D.cmdsize) 2019 return object_error::parse_failed; 2020 StringRef Suffix; 2021 bool isFramework; 2022 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 2023 if (shortName.empty()) 2024 LibrariesShortNames.push_back(Name); 2025 else 2026 LibrariesShortNames.push_back(shortName); 2027 } 2028 } 2029 2030 Res = LibrariesShortNames[Index]; 2031 return std::error_code(); 2032 } 2033 2034 section_iterator 2035 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 2036 DataRefImpl Sec; 2037 Sec.d.a = Rel->getRawDataRefImpl().d.a; 2038 return section_iterator(SectionRef(Sec, this)); 2039 } 2040 2041 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 2042 DataRefImpl DRI; 2043 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2044 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2045 return basic_symbol_iterator(SymbolRef(DRI, this)); 2046 2047 return getSymbolByIndex(0); 2048 } 2049 2050 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 2051 DataRefImpl DRI; 2052 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2053 if (!SymtabLoadCmd || Symtab.nsyms == 0) 2054 return basic_symbol_iterator(SymbolRef(DRI, this)); 2055 2056 unsigned SymbolTableEntrySize = is64Bit() ? 2057 sizeof(MachO::nlist_64) : 2058 sizeof(MachO::nlist); 2059 unsigned Offset = Symtab.symoff + 2060 Symtab.nsyms * SymbolTableEntrySize; 2061 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2062 return basic_symbol_iterator(SymbolRef(DRI, this)); 2063 } 2064 2065 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 2066 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2067 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 2068 report_fatal_error("Requested symbol index is out of range."); 2069 unsigned SymbolTableEntrySize = 2070 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2071 DataRefImpl DRI; 2072 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 2073 DRI.p += Index * SymbolTableEntrySize; 2074 return basic_symbol_iterator(SymbolRef(DRI, this)); 2075 } 2076 2077 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 2078 MachO::symtab_command Symtab = getSymtabLoadCommand(); 2079 if (!SymtabLoadCmd) 2080 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 2081 unsigned SymbolTableEntrySize = 2082 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 2083 DataRefImpl DRIstart; 2084 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 2085 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 2086 return Index; 2087 } 2088 2089 section_iterator MachOObjectFile::section_begin() const { 2090 DataRefImpl DRI; 2091 return section_iterator(SectionRef(DRI, this)); 2092 } 2093 2094 section_iterator MachOObjectFile::section_end() const { 2095 DataRefImpl DRI; 2096 DRI.d.a = Sections.size(); 2097 return section_iterator(SectionRef(DRI, this)); 2098 } 2099 2100 uint8_t MachOObjectFile::getBytesInAddress() const { 2101 return is64Bit() ? 8 : 4; 2102 } 2103 2104 StringRef MachOObjectFile::getFileFormatName() const { 2105 unsigned CPUType = getCPUType(this); 2106 if (!is64Bit()) { 2107 switch (CPUType) { 2108 case llvm::MachO::CPU_TYPE_I386: 2109 return "Mach-O 32-bit i386"; 2110 case llvm::MachO::CPU_TYPE_ARM: 2111 return "Mach-O arm"; 2112 case llvm::MachO::CPU_TYPE_POWERPC: 2113 return "Mach-O 32-bit ppc"; 2114 default: 2115 return "Mach-O 32-bit unknown"; 2116 } 2117 } 2118 2119 switch (CPUType) { 2120 case llvm::MachO::CPU_TYPE_X86_64: 2121 return "Mach-O 64-bit x86-64"; 2122 case llvm::MachO::CPU_TYPE_ARM64: 2123 return "Mach-O arm64"; 2124 case llvm::MachO::CPU_TYPE_POWERPC64: 2125 return "Mach-O 64-bit ppc64"; 2126 default: 2127 return "Mach-O 64-bit unknown"; 2128 } 2129 } 2130 2131 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 2132 switch (CPUType) { 2133 case llvm::MachO::CPU_TYPE_I386: 2134 return Triple::x86; 2135 case llvm::MachO::CPU_TYPE_X86_64: 2136 return Triple::x86_64; 2137 case llvm::MachO::CPU_TYPE_ARM: 2138 return Triple::arm; 2139 case llvm::MachO::CPU_TYPE_ARM64: 2140 return Triple::aarch64; 2141 case llvm::MachO::CPU_TYPE_POWERPC: 2142 return Triple::ppc; 2143 case llvm::MachO::CPU_TYPE_POWERPC64: 2144 return Triple::ppc64; 2145 default: 2146 return Triple::UnknownArch; 2147 } 2148 } 2149 2150 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 2151 const char **McpuDefault) { 2152 if (McpuDefault) 2153 *McpuDefault = nullptr; 2154 2155 switch (CPUType) { 2156 case MachO::CPU_TYPE_I386: 2157 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2158 case MachO::CPU_SUBTYPE_I386_ALL: 2159 return Triple("i386-apple-darwin"); 2160 default: 2161 return Triple(); 2162 } 2163 case MachO::CPU_TYPE_X86_64: 2164 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2165 case MachO::CPU_SUBTYPE_X86_64_ALL: 2166 return Triple("x86_64-apple-darwin"); 2167 case MachO::CPU_SUBTYPE_X86_64_H: 2168 return Triple("x86_64h-apple-darwin"); 2169 default: 2170 return Triple(); 2171 } 2172 case MachO::CPU_TYPE_ARM: 2173 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2174 case MachO::CPU_SUBTYPE_ARM_V4T: 2175 return Triple("armv4t-apple-darwin"); 2176 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2177 return Triple("armv5e-apple-darwin"); 2178 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2179 return Triple("xscale-apple-darwin"); 2180 case MachO::CPU_SUBTYPE_ARM_V6: 2181 return Triple("armv6-apple-darwin"); 2182 case MachO::CPU_SUBTYPE_ARM_V6M: 2183 if (McpuDefault) 2184 *McpuDefault = "cortex-m0"; 2185 return Triple("armv6m-apple-darwin"); 2186 case MachO::CPU_SUBTYPE_ARM_V7: 2187 return Triple("armv7-apple-darwin"); 2188 case MachO::CPU_SUBTYPE_ARM_V7EM: 2189 if (McpuDefault) 2190 *McpuDefault = "cortex-m4"; 2191 return Triple("thumbv7em-apple-darwin"); 2192 case MachO::CPU_SUBTYPE_ARM_V7K: 2193 return Triple("armv7k-apple-darwin"); 2194 case MachO::CPU_SUBTYPE_ARM_V7M: 2195 if (McpuDefault) 2196 *McpuDefault = "cortex-m3"; 2197 return Triple("thumbv7m-apple-darwin"); 2198 case MachO::CPU_SUBTYPE_ARM_V7S: 2199 return Triple("armv7s-apple-darwin"); 2200 default: 2201 return Triple(); 2202 } 2203 case MachO::CPU_TYPE_ARM64: 2204 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2205 case MachO::CPU_SUBTYPE_ARM64_ALL: 2206 return Triple("arm64-apple-darwin"); 2207 default: 2208 return Triple(); 2209 } 2210 case MachO::CPU_TYPE_POWERPC: 2211 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2212 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2213 return Triple("ppc-apple-darwin"); 2214 default: 2215 return Triple(); 2216 } 2217 case MachO::CPU_TYPE_POWERPC64: 2218 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2219 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2220 return Triple("ppc64-apple-darwin"); 2221 default: 2222 return Triple(); 2223 } 2224 default: 2225 return Triple(); 2226 } 2227 } 2228 2229 Triple MachOObjectFile::getHostArch() { 2230 return Triple(sys::getDefaultTargetTriple()); 2231 } 2232 2233 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2234 return StringSwitch<bool>(ArchFlag) 2235 .Case("i386", true) 2236 .Case("x86_64", true) 2237 .Case("x86_64h", true) 2238 .Case("armv4t", true) 2239 .Case("arm", true) 2240 .Case("armv5e", true) 2241 .Case("armv6", true) 2242 .Case("armv6m", true) 2243 .Case("armv7", true) 2244 .Case("armv7em", true) 2245 .Case("armv7k", true) 2246 .Case("armv7m", true) 2247 .Case("armv7s", true) 2248 .Case("arm64", true) 2249 .Case("ppc", true) 2250 .Case("ppc64", true) 2251 .Default(false); 2252 } 2253 2254 unsigned MachOObjectFile::getArch() const { 2255 return getArch(getCPUType(this)); 2256 } 2257 2258 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2259 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2260 } 2261 2262 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2263 DataRefImpl DRI; 2264 DRI.d.a = Index; 2265 return section_rel_begin(DRI); 2266 } 2267 2268 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2269 DataRefImpl DRI; 2270 DRI.d.a = Index; 2271 return section_rel_end(DRI); 2272 } 2273 2274 dice_iterator MachOObjectFile::begin_dices() const { 2275 DataRefImpl DRI; 2276 if (!DataInCodeLoadCmd) 2277 return dice_iterator(DiceRef(DRI, this)); 2278 2279 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2280 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 2281 return dice_iterator(DiceRef(DRI, this)); 2282 } 2283 2284 dice_iterator MachOObjectFile::end_dices() const { 2285 DataRefImpl DRI; 2286 if (!DataInCodeLoadCmd) 2287 return dice_iterator(DiceRef(DRI, this)); 2288 2289 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2290 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2291 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2292 return dice_iterator(DiceRef(DRI, this)); 2293 } 2294 2295 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 2296 : Trie(T), Malformed(false), Done(false) {} 2297 2298 void ExportEntry::moveToFirst() { 2299 pushNode(0); 2300 pushDownUntilBottom(); 2301 } 2302 2303 void ExportEntry::moveToEnd() { 2304 Stack.clear(); 2305 Done = true; 2306 } 2307 2308 bool ExportEntry::operator==(const ExportEntry &Other) const { 2309 // Common case, one at end, other iterating from begin. 2310 if (Done || Other.Done) 2311 return (Done == Other.Done); 2312 // Not equal if different stack sizes. 2313 if (Stack.size() != Other.Stack.size()) 2314 return false; 2315 // Not equal if different cumulative strings. 2316 if (!CumulativeString.equals(Other.CumulativeString)) 2317 return false; 2318 // Equal if all nodes in both stacks match. 2319 for (unsigned i=0; i < Stack.size(); ++i) { 2320 if (Stack[i].Start != Other.Stack[i].Start) 2321 return false; 2322 } 2323 return true; 2324 } 2325 2326 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 2327 unsigned Count; 2328 uint64_t Result = decodeULEB128(Ptr, &Count); 2329 Ptr += Count; 2330 if (Ptr > Trie.end()) { 2331 Ptr = Trie.end(); 2332 Malformed = true; 2333 } 2334 return Result; 2335 } 2336 2337 StringRef ExportEntry::name() const { 2338 return CumulativeString; 2339 } 2340 2341 uint64_t ExportEntry::flags() const { 2342 return Stack.back().Flags; 2343 } 2344 2345 uint64_t ExportEntry::address() const { 2346 return Stack.back().Address; 2347 } 2348 2349 uint64_t ExportEntry::other() const { 2350 return Stack.back().Other; 2351 } 2352 2353 StringRef ExportEntry::otherName() const { 2354 const char* ImportName = Stack.back().ImportName; 2355 if (ImportName) 2356 return StringRef(ImportName); 2357 return StringRef(); 2358 } 2359 2360 uint32_t ExportEntry::nodeOffset() const { 2361 return Stack.back().Start - Trie.begin(); 2362 } 2363 2364 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2365 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 2366 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 2367 ParentStringLength(0), IsExportNode(false) {} 2368 2369 void ExportEntry::pushNode(uint64_t offset) { 2370 const uint8_t *Ptr = Trie.begin() + offset; 2371 NodeState State(Ptr); 2372 uint64_t ExportInfoSize = readULEB128(State.Current); 2373 State.IsExportNode = (ExportInfoSize != 0); 2374 const uint8_t* Children = State.Current + ExportInfoSize; 2375 if (State.IsExportNode) { 2376 State.Flags = readULEB128(State.Current); 2377 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2378 State.Address = 0; 2379 State.Other = readULEB128(State.Current); // dylib ordinal 2380 State.ImportName = reinterpret_cast<const char*>(State.Current); 2381 } else { 2382 State.Address = readULEB128(State.Current); 2383 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 2384 State.Other = readULEB128(State.Current); 2385 } 2386 } 2387 State.ChildCount = *Children; 2388 State.Current = Children + 1; 2389 State.NextChildIndex = 0; 2390 State.ParentStringLength = CumulativeString.size(); 2391 Stack.push_back(State); 2392 } 2393 2394 void ExportEntry::pushDownUntilBottom() { 2395 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2396 NodeState &Top = Stack.back(); 2397 CumulativeString.resize(Top.ParentStringLength); 2398 for (;*Top.Current != 0; Top.Current++) { 2399 char C = *Top.Current; 2400 CumulativeString.push_back(C); 2401 } 2402 Top.Current += 1; 2403 uint64_t childNodeIndex = readULEB128(Top.Current); 2404 Top.NextChildIndex += 1; 2405 pushNode(childNodeIndex); 2406 } 2407 if (!Stack.back().IsExportNode) { 2408 Malformed = true; 2409 moveToEnd(); 2410 } 2411 } 2412 2413 // We have a trie data structure and need a way to walk it that is compatible 2414 // with the C++ iterator model. The solution is a non-recursive depth first 2415 // traversal where the iterator contains a stack of parent nodes along with a 2416 // string that is the accumulation of all edge strings along the parent chain 2417 // to this point. 2418 // 2419 // There is one "export" node for each exported symbol. But because some 2420 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2421 // node may have child nodes too. 2422 // 2423 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2424 // child until hitting a node with no children (which is an export node or 2425 // else the trie is malformed). On the way down, each node is pushed on the 2426 // stack ivar. If there is no more ways down, it pops up one and tries to go 2427 // down a sibling path until a childless node is reached. 2428 void ExportEntry::moveNext() { 2429 if (Stack.empty() || !Stack.back().IsExportNode) { 2430 Malformed = true; 2431 moveToEnd(); 2432 return; 2433 } 2434 2435 Stack.pop_back(); 2436 while (!Stack.empty()) { 2437 NodeState &Top = Stack.back(); 2438 if (Top.NextChildIndex < Top.ChildCount) { 2439 pushDownUntilBottom(); 2440 // Now at the next export node. 2441 return; 2442 } else { 2443 if (Top.IsExportNode) { 2444 // This node has no children but is itself an export node. 2445 CumulativeString.resize(Top.ParentStringLength); 2446 return; 2447 } 2448 Stack.pop_back(); 2449 } 2450 } 2451 Done = true; 2452 } 2453 2454 iterator_range<export_iterator> 2455 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 2456 ExportEntry Start(Trie); 2457 if (Trie.size() == 0) 2458 Start.moveToEnd(); 2459 else 2460 Start.moveToFirst(); 2461 2462 ExportEntry Finish(Trie); 2463 Finish.moveToEnd(); 2464 2465 return make_range(export_iterator(Start), export_iterator(Finish)); 2466 } 2467 2468 iterator_range<export_iterator> MachOObjectFile::exports() const { 2469 return exports(getDyldInfoExportsTrie()); 2470 } 2471 2472 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 2473 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2474 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 2475 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 2476 2477 void MachORebaseEntry::moveToFirst() { 2478 Ptr = Opcodes.begin(); 2479 moveNext(); 2480 } 2481 2482 void MachORebaseEntry::moveToEnd() { 2483 Ptr = Opcodes.end(); 2484 RemainingLoopCount = 0; 2485 Done = true; 2486 } 2487 2488 void MachORebaseEntry::moveNext() { 2489 // If in the middle of some loop, move to next rebasing in loop. 2490 SegmentOffset += AdvanceAmount; 2491 if (RemainingLoopCount) { 2492 --RemainingLoopCount; 2493 return; 2494 } 2495 if (Ptr == Opcodes.end()) { 2496 Done = true; 2497 return; 2498 } 2499 bool More = true; 2500 while (More && !Malformed) { 2501 // Parse next opcode and set up next loop. 2502 uint8_t Byte = *Ptr++; 2503 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2504 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2505 switch (Opcode) { 2506 case MachO::REBASE_OPCODE_DONE: 2507 More = false; 2508 Done = true; 2509 moveToEnd(); 2510 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 2511 break; 2512 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2513 RebaseType = ImmValue; 2514 DEBUG_WITH_TYPE( 2515 "mach-o-rebase", 2516 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2517 << "RebaseType=" << (int) RebaseType << "\n"); 2518 break; 2519 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2520 SegmentIndex = ImmValue; 2521 SegmentOffset = readULEB128(); 2522 DEBUG_WITH_TYPE( 2523 "mach-o-rebase", 2524 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2525 << "SegmentIndex=" << SegmentIndex << ", " 2526 << format("SegmentOffset=0x%06X", SegmentOffset) 2527 << "\n"); 2528 break; 2529 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 2530 SegmentOffset += readULEB128(); 2531 DEBUG_WITH_TYPE("mach-o-rebase", 2532 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 2533 << format("SegmentOffset=0x%06X", 2534 SegmentOffset) << "\n"); 2535 break; 2536 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 2537 SegmentOffset += ImmValue * PointerSize; 2538 DEBUG_WITH_TYPE("mach-o-rebase", 2539 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 2540 << format("SegmentOffset=0x%06X", 2541 SegmentOffset) << "\n"); 2542 break; 2543 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 2544 AdvanceAmount = PointerSize; 2545 RemainingLoopCount = ImmValue - 1; 2546 DEBUG_WITH_TYPE( 2547 "mach-o-rebase", 2548 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 2549 << format("SegmentOffset=0x%06X", SegmentOffset) 2550 << ", AdvanceAmount=" << AdvanceAmount 2551 << ", RemainingLoopCount=" << RemainingLoopCount 2552 << "\n"); 2553 return; 2554 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 2555 AdvanceAmount = PointerSize; 2556 RemainingLoopCount = readULEB128() - 1; 2557 DEBUG_WITH_TYPE( 2558 "mach-o-rebase", 2559 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 2560 << format("SegmentOffset=0x%06X", SegmentOffset) 2561 << ", AdvanceAmount=" << AdvanceAmount 2562 << ", RemainingLoopCount=" << RemainingLoopCount 2563 << "\n"); 2564 return; 2565 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2566 AdvanceAmount = readULEB128() + PointerSize; 2567 RemainingLoopCount = 0; 2568 DEBUG_WITH_TYPE( 2569 "mach-o-rebase", 2570 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2571 << format("SegmentOffset=0x%06X", SegmentOffset) 2572 << ", AdvanceAmount=" << AdvanceAmount 2573 << ", RemainingLoopCount=" << RemainingLoopCount 2574 << "\n"); 2575 return; 2576 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2577 RemainingLoopCount = readULEB128() - 1; 2578 AdvanceAmount = readULEB128() + PointerSize; 2579 DEBUG_WITH_TYPE( 2580 "mach-o-rebase", 2581 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2582 << format("SegmentOffset=0x%06X", SegmentOffset) 2583 << ", AdvanceAmount=" << AdvanceAmount 2584 << ", RemainingLoopCount=" << RemainingLoopCount 2585 << "\n"); 2586 return; 2587 default: 2588 Malformed = true; 2589 } 2590 } 2591 } 2592 2593 uint64_t MachORebaseEntry::readULEB128() { 2594 unsigned Count; 2595 uint64_t Result = decodeULEB128(Ptr, &Count); 2596 Ptr += Count; 2597 if (Ptr > Opcodes.end()) { 2598 Ptr = Opcodes.end(); 2599 Malformed = true; 2600 } 2601 return Result; 2602 } 2603 2604 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2605 2606 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2607 2608 StringRef MachORebaseEntry::typeName() const { 2609 switch (RebaseType) { 2610 case MachO::REBASE_TYPE_POINTER: 2611 return "pointer"; 2612 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2613 return "text abs32"; 2614 case MachO::REBASE_TYPE_TEXT_PCREL32: 2615 return "text rel32"; 2616 } 2617 return "unknown"; 2618 } 2619 2620 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2621 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2622 return (Ptr == Other.Ptr) && 2623 (RemainingLoopCount == Other.RemainingLoopCount) && 2624 (Done == Other.Done); 2625 } 2626 2627 iterator_range<rebase_iterator> 2628 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2629 MachORebaseEntry Start(Opcodes, is64); 2630 Start.moveToFirst(); 2631 2632 MachORebaseEntry Finish(Opcodes, is64); 2633 Finish.moveToEnd(); 2634 2635 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2636 } 2637 2638 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2639 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2640 } 2641 2642 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2643 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2644 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2645 BindType(0), PointerSize(is64Bit ? 8 : 4), 2646 TableKind(BK), Malformed(false), Done(false) {} 2647 2648 void MachOBindEntry::moveToFirst() { 2649 Ptr = Opcodes.begin(); 2650 moveNext(); 2651 } 2652 2653 void MachOBindEntry::moveToEnd() { 2654 Ptr = Opcodes.end(); 2655 RemainingLoopCount = 0; 2656 Done = true; 2657 } 2658 2659 void MachOBindEntry::moveNext() { 2660 // If in the middle of some loop, move to next binding in loop. 2661 SegmentOffset += AdvanceAmount; 2662 if (RemainingLoopCount) { 2663 --RemainingLoopCount; 2664 return; 2665 } 2666 if (Ptr == Opcodes.end()) { 2667 Done = true; 2668 return; 2669 } 2670 bool More = true; 2671 while (More && !Malformed) { 2672 // Parse next opcode and set up next loop. 2673 uint8_t Byte = *Ptr++; 2674 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2675 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2676 int8_t SignExtended; 2677 const uint8_t *SymStart; 2678 switch (Opcode) { 2679 case MachO::BIND_OPCODE_DONE: 2680 if (TableKind == Kind::Lazy) { 2681 // Lazying bindings have a DONE opcode between entries. Need to ignore 2682 // it to advance to next entry. But need not if this is last entry. 2683 bool NotLastEntry = false; 2684 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2685 if (*P) { 2686 NotLastEntry = true; 2687 } 2688 } 2689 if (NotLastEntry) 2690 break; 2691 } 2692 More = false; 2693 Done = true; 2694 moveToEnd(); 2695 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2696 break; 2697 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2698 Ordinal = ImmValue; 2699 DEBUG_WITH_TYPE( 2700 "mach-o-bind", 2701 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2702 << "Ordinal=" << Ordinal << "\n"); 2703 break; 2704 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2705 Ordinal = readULEB128(); 2706 DEBUG_WITH_TYPE( 2707 "mach-o-bind", 2708 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2709 << "Ordinal=" << Ordinal << "\n"); 2710 break; 2711 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2712 if (ImmValue) { 2713 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2714 Ordinal = SignExtended; 2715 } else 2716 Ordinal = 0; 2717 DEBUG_WITH_TYPE( 2718 "mach-o-bind", 2719 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2720 << "Ordinal=" << Ordinal << "\n"); 2721 break; 2722 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2723 Flags = ImmValue; 2724 SymStart = Ptr; 2725 while (*Ptr) { 2726 ++Ptr; 2727 } 2728 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2729 Ptr-SymStart); 2730 ++Ptr; 2731 DEBUG_WITH_TYPE( 2732 "mach-o-bind", 2733 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2734 << "SymbolName=" << SymbolName << "\n"); 2735 if (TableKind == Kind::Weak) { 2736 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2737 return; 2738 } 2739 break; 2740 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2741 BindType = ImmValue; 2742 DEBUG_WITH_TYPE( 2743 "mach-o-bind", 2744 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2745 << "BindType=" << (int)BindType << "\n"); 2746 break; 2747 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2748 Addend = readSLEB128(); 2749 if (TableKind == Kind::Lazy) 2750 Malformed = true; 2751 DEBUG_WITH_TYPE( 2752 "mach-o-bind", 2753 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2754 << "Addend=" << Addend << "\n"); 2755 break; 2756 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2757 SegmentIndex = ImmValue; 2758 SegmentOffset = readULEB128(); 2759 DEBUG_WITH_TYPE( 2760 "mach-o-bind", 2761 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2762 << "SegmentIndex=" << SegmentIndex << ", " 2763 << format("SegmentOffset=0x%06X", SegmentOffset) 2764 << "\n"); 2765 break; 2766 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2767 SegmentOffset += readULEB128(); 2768 DEBUG_WITH_TYPE("mach-o-bind", 2769 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2770 << format("SegmentOffset=0x%06X", 2771 SegmentOffset) << "\n"); 2772 break; 2773 case MachO::BIND_OPCODE_DO_BIND: 2774 AdvanceAmount = PointerSize; 2775 RemainingLoopCount = 0; 2776 DEBUG_WITH_TYPE("mach-o-bind", 2777 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2778 << format("SegmentOffset=0x%06X", 2779 SegmentOffset) << "\n"); 2780 return; 2781 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2782 AdvanceAmount = readULEB128() + PointerSize; 2783 RemainingLoopCount = 0; 2784 if (TableKind == Kind::Lazy) 2785 Malformed = true; 2786 DEBUG_WITH_TYPE( 2787 "mach-o-bind", 2788 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2789 << format("SegmentOffset=0x%06X", SegmentOffset) 2790 << ", AdvanceAmount=" << AdvanceAmount 2791 << ", RemainingLoopCount=" << RemainingLoopCount 2792 << "\n"); 2793 return; 2794 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2795 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2796 RemainingLoopCount = 0; 2797 if (TableKind == Kind::Lazy) 2798 Malformed = true; 2799 DEBUG_WITH_TYPE("mach-o-bind", 2800 llvm::dbgs() 2801 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2802 << format("SegmentOffset=0x%06X", 2803 SegmentOffset) << "\n"); 2804 return; 2805 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2806 RemainingLoopCount = readULEB128() - 1; 2807 AdvanceAmount = readULEB128() + PointerSize; 2808 if (TableKind == Kind::Lazy) 2809 Malformed = true; 2810 DEBUG_WITH_TYPE( 2811 "mach-o-bind", 2812 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2813 << format("SegmentOffset=0x%06X", SegmentOffset) 2814 << ", AdvanceAmount=" << AdvanceAmount 2815 << ", RemainingLoopCount=" << RemainingLoopCount 2816 << "\n"); 2817 return; 2818 default: 2819 Malformed = true; 2820 } 2821 } 2822 } 2823 2824 uint64_t MachOBindEntry::readULEB128() { 2825 unsigned Count; 2826 uint64_t Result = decodeULEB128(Ptr, &Count); 2827 Ptr += Count; 2828 if (Ptr > Opcodes.end()) { 2829 Ptr = Opcodes.end(); 2830 Malformed = true; 2831 } 2832 return Result; 2833 } 2834 2835 int64_t MachOBindEntry::readSLEB128() { 2836 unsigned Count; 2837 int64_t Result = decodeSLEB128(Ptr, &Count); 2838 Ptr += Count; 2839 if (Ptr > Opcodes.end()) { 2840 Ptr = Opcodes.end(); 2841 Malformed = true; 2842 } 2843 return Result; 2844 } 2845 2846 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 2847 2848 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 2849 2850 StringRef MachOBindEntry::typeName() const { 2851 switch (BindType) { 2852 case MachO::BIND_TYPE_POINTER: 2853 return "pointer"; 2854 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 2855 return "text abs32"; 2856 case MachO::BIND_TYPE_TEXT_PCREL32: 2857 return "text rel32"; 2858 } 2859 return "unknown"; 2860 } 2861 2862 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 2863 2864 int64_t MachOBindEntry::addend() const { return Addend; } 2865 2866 uint32_t MachOBindEntry::flags() const { return Flags; } 2867 2868 int MachOBindEntry::ordinal() const { return Ordinal; } 2869 2870 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 2871 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2872 return (Ptr == Other.Ptr) && 2873 (RemainingLoopCount == Other.RemainingLoopCount) && 2874 (Done == Other.Done); 2875 } 2876 2877 iterator_range<bind_iterator> 2878 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 2879 MachOBindEntry::Kind BKind) { 2880 MachOBindEntry Start(Opcodes, is64, BKind); 2881 Start.moveToFirst(); 2882 2883 MachOBindEntry Finish(Opcodes, is64, BKind); 2884 Finish.moveToEnd(); 2885 2886 return make_range(bind_iterator(Start), bind_iterator(Finish)); 2887 } 2888 2889 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 2890 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 2891 MachOBindEntry::Kind::Regular); 2892 } 2893 2894 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 2895 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 2896 MachOBindEntry::Kind::Lazy); 2897 } 2898 2899 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 2900 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 2901 MachOBindEntry::Kind::Weak); 2902 } 2903 2904 MachOObjectFile::load_command_iterator 2905 MachOObjectFile::begin_load_commands() const { 2906 return LoadCommands.begin(); 2907 } 2908 2909 MachOObjectFile::load_command_iterator 2910 MachOObjectFile::end_load_commands() const { 2911 return LoadCommands.end(); 2912 } 2913 2914 iterator_range<MachOObjectFile::load_command_iterator> 2915 MachOObjectFile::load_commands() const { 2916 return make_range(begin_load_commands(), end_load_commands()); 2917 } 2918 2919 StringRef 2920 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 2921 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 2922 return parseSegmentOrSectionName(Raw.data()); 2923 } 2924 2925 ArrayRef<char> 2926 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 2927 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2928 const section_base *Base = 2929 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2930 return makeArrayRef(Base->sectname); 2931 } 2932 2933 ArrayRef<char> 2934 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 2935 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2936 const section_base *Base = 2937 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2938 return makeArrayRef(Base->segname); 2939 } 2940 2941 bool 2942 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 2943 const { 2944 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 2945 return false; 2946 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 2947 } 2948 2949 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 2950 const MachO::any_relocation_info &RE) const { 2951 if (isLittleEndian()) 2952 return RE.r_word1 & 0xffffff; 2953 return RE.r_word1 >> 8; 2954 } 2955 2956 bool MachOObjectFile::getPlainRelocationExternal( 2957 const MachO::any_relocation_info &RE) const { 2958 if (isLittleEndian()) 2959 return (RE.r_word1 >> 27) & 1; 2960 return (RE.r_word1 >> 4) & 1; 2961 } 2962 2963 bool MachOObjectFile::getScatteredRelocationScattered( 2964 const MachO::any_relocation_info &RE) const { 2965 return RE.r_word0 >> 31; 2966 } 2967 2968 uint32_t MachOObjectFile::getScatteredRelocationValue( 2969 const MachO::any_relocation_info &RE) const { 2970 return RE.r_word1; 2971 } 2972 2973 uint32_t MachOObjectFile::getScatteredRelocationType( 2974 const MachO::any_relocation_info &RE) const { 2975 return (RE.r_word0 >> 24) & 0xf; 2976 } 2977 2978 unsigned MachOObjectFile::getAnyRelocationAddress( 2979 const MachO::any_relocation_info &RE) const { 2980 if (isRelocationScattered(RE)) 2981 return getScatteredRelocationAddress(RE); 2982 return getPlainRelocationAddress(RE); 2983 } 2984 2985 unsigned MachOObjectFile::getAnyRelocationPCRel( 2986 const MachO::any_relocation_info &RE) const { 2987 if (isRelocationScattered(RE)) 2988 return getScatteredRelocationPCRel(this, RE); 2989 return getPlainRelocationPCRel(this, RE); 2990 } 2991 2992 unsigned MachOObjectFile::getAnyRelocationLength( 2993 const MachO::any_relocation_info &RE) const { 2994 if (isRelocationScattered(RE)) 2995 return getScatteredRelocationLength(RE); 2996 return getPlainRelocationLength(this, RE); 2997 } 2998 2999 unsigned 3000 MachOObjectFile::getAnyRelocationType( 3001 const MachO::any_relocation_info &RE) const { 3002 if (isRelocationScattered(RE)) 3003 return getScatteredRelocationType(RE); 3004 return getPlainRelocationType(this, RE); 3005 } 3006 3007 SectionRef 3008 MachOObjectFile::getAnyRelocationSection( 3009 const MachO::any_relocation_info &RE) const { 3010 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 3011 return *section_end(); 3012 unsigned SecNum = getPlainRelocationSymbolNum(RE); 3013 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 3014 return *section_end(); 3015 DataRefImpl DRI; 3016 DRI.d.a = SecNum - 1; 3017 return SectionRef(DRI, this); 3018 } 3019 3020 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 3021 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3022 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 3023 } 3024 3025 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 3026 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 3027 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 3028 } 3029 3030 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 3031 unsigned Index) const { 3032 const char *Sec = getSectionPtr(this, L, Index); 3033 return getStruct<MachO::section>(this, Sec); 3034 } 3035 3036 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 3037 unsigned Index) const { 3038 const char *Sec = getSectionPtr(this, L, Index); 3039 return getStruct<MachO::section_64>(this, Sec); 3040 } 3041 3042 MachO::nlist 3043 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 3044 const char *P = reinterpret_cast<const char *>(DRI.p); 3045 return getStruct<MachO::nlist>(this, P); 3046 } 3047 3048 MachO::nlist_64 3049 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 3050 const char *P = reinterpret_cast<const char *>(DRI.p); 3051 return getStruct<MachO::nlist_64>(this, P); 3052 } 3053 3054 MachO::linkedit_data_command 3055 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 3056 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 3057 } 3058 3059 MachO::segment_command 3060 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 3061 return getStruct<MachO::segment_command>(this, L.Ptr); 3062 } 3063 3064 MachO::segment_command_64 3065 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 3066 return getStruct<MachO::segment_command_64>(this, L.Ptr); 3067 } 3068 3069 MachO::linker_option_command 3070 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 3071 return getStruct<MachO::linker_option_command>(this, L.Ptr); 3072 } 3073 3074 MachO::version_min_command 3075 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 3076 return getStruct<MachO::version_min_command>(this, L.Ptr); 3077 } 3078 3079 MachO::dylib_command 3080 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 3081 return getStruct<MachO::dylib_command>(this, L.Ptr); 3082 } 3083 3084 MachO::dyld_info_command 3085 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 3086 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 3087 } 3088 3089 MachO::dylinker_command 3090 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 3091 return getStruct<MachO::dylinker_command>(this, L.Ptr); 3092 } 3093 3094 MachO::uuid_command 3095 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 3096 return getStruct<MachO::uuid_command>(this, L.Ptr); 3097 } 3098 3099 MachO::rpath_command 3100 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 3101 return getStruct<MachO::rpath_command>(this, L.Ptr); 3102 } 3103 3104 MachO::source_version_command 3105 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 3106 return getStruct<MachO::source_version_command>(this, L.Ptr); 3107 } 3108 3109 MachO::entry_point_command 3110 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 3111 return getStruct<MachO::entry_point_command>(this, L.Ptr); 3112 } 3113 3114 MachO::encryption_info_command 3115 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 3116 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 3117 } 3118 3119 MachO::encryption_info_command_64 3120 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 3121 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 3122 } 3123 3124 MachO::sub_framework_command 3125 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 3126 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 3127 } 3128 3129 MachO::sub_umbrella_command 3130 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 3131 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 3132 } 3133 3134 MachO::sub_library_command 3135 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 3136 return getStruct<MachO::sub_library_command>(this, L.Ptr); 3137 } 3138 3139 MachO::sub_client_command 3140 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 3141 return getStruct<MachO::sub_client_command>(this, L.Ptr); 3142 } 3143 3144 MachO::routines_command 3145 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 3146 return getStruct<MachO::routines_command>(this, L.Ptr); 3147 } 3148 3149 MachO::routines_command_64 3150 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 3151 return getStruct<MachO::routines_command_64>(this, L.Ptr); 3152 } 3153 3154 MachO::thread_command 3155 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 3156 return getStruct<MachO::thread_command>(this, L.Ptr); 3157 } 3158 3159 MachO::any_relocation_info 3160 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 3161 DataRefImpl Sec; 3162 Sec.d.a = Rel.d.a; 3163 uint32_t Offset; 3164 if (is64Bit()) { 3165 MachO::section_64 Sect = getSection64(Sec); 3166 Offset = Sect.reloff; 3167 } else { 3168 MachO::section Sect = getSection(Sec); 3169 Offset = Sect.reloff; 3170 } 3171 3172 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 3173 getPtr(this, Offset)) + Rel.d.b; 3174 return getStruct<MachO::any_relocation_info>( 3175 this, reinterpret_cast<const char *>(P)); 3176 } 3177 3178 MachO::data_in_code_entry 3179 MachOObjectFile::getDice(DataRefImpl Rel) const { 3180 const char *P = reinterpret_cast<const char *>(Rel.p); 3181 return getStruct<MachO::data_in_code_entry>(this, P); 3182 } 3183 3184 const MachO::mach_header &MachOObjectFile::getHeader() const { 3185 return Header; 3186 } 3187 3188 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 3189 assert(is64Bit()); 3190 return Header64; 3191 } 3192 3193 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 3194 const MachO::dysymtab_command &DLC, 3195 unsigned Index) const { 3196 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 3197 return getStruct<uint32_t>(this, getPtr(this, Offset)); 3198 } 3199 3200 MachO::data_in_code_entry 3201 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 3202 unsigned Index) const { 3203 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 3204 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 3205 } 3206 3207 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 3208 if (SymtabLoadCmd) 3209 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 3210 3211 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 3212 MachO::symtab_command Cmd; 3213 Cmd.cmd = MachO::LC_SYMTAB; 3214 Cmd.cmdsize = sizeof(MachO::symtab_command); 3215 Cmd.symoff = 0; 3216 Cmd.nsyms = 0; 3217 Cmd.stroff = 0; 3218 Cmd.strsize = 0; 3219 return Cmd; 3220 } 3221 3222 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 3223 if (DysymtabLoadCmd) 3224 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 3225 3226 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 3227 MachO::dysymtab_command Cmd; 3228 Cmd.cmd = MachO::LC_DYSYMTAB; 3229 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 3230 Cmd.ilocalsym = 0; 3231 Cmd.nlocalsym = 0; 3232 Cmd.iextdefsym = 0; 3233 Cmd.nextdefsym = 0; 3234 Cmd.iundefsym = 0; 3235 Cmd.nundefsym = 0; 3236 Cmd.tocoff = 0; 3237 Cmd.ntoc = 0; 3238 Cmd.modtaboff = 0; 3239 Cmd.nmodtab = 0; 3240 Cmd.extrefsymoff = 0; 3241 Cmd.nextrefsyms = 0; 3242 Cmd.indirectsymoff = 0; 3243 Cmd.nindirectsyms = 0; 3244 Cmd.extreloff = 0; 3245 Cmd.nextrel = 0; 3246 Cmd.locreloff = 0; 3247 Cmd.nlocrel = 0; 3248 return Cmd; 3249 } 3250 3251 MachO::linkedit_data_command 3252 MachOObjectFile::getDataInCodeLoadCommand() const { 3253 if (DataInCodeLoadCmd) 3254 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 3255 3256 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 3257 MachO::linkedit_data_command Cmd; 3258 Cmd.cmd = MachO::LC_DATA_IN_CODE; 3259 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3260 Cmd.dataoff = 0; 3261 Cmd.datasize = 0; 3262 return Cmd; 3263 } 3264 3265 MachO::linkedit_data_command 3266 MachOObjectFile::getLinkOptHintsLoadCommand() const { 3267 if (LinkOptHintsLoadCmd) 3268 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 3269 3270 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 3271 // fields. 3272 MachO::linkedit_data_command Cmd; 3273 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 3274 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3275 Cmd.dataoff = 0; 3276 Cmd.datasize = 0; 3277 return Cmd; 3278 } 3279 3280 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 3281 if (!DyldInfoLoadCmd) 3282 return None; 3283 3284 MachO::dyld_info_command DyldInfo = 3285 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3286 const uint8_t *Ptr = 3287 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 3288 return makeArrayRef(Ptr, DyldInfo.rebase_size); 3289 } 3290 3291 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 3292 if (!DyldInfoLoadCmd) 3293 return None; 3294 3295 MachO::dyld_info_command DyldInfo = 3296 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3297 const uint8_t *Ptr = 3298 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 3299 return makeArrayRef(Ptr, DyldInfo.bind_size); 3300 } 3301 3302 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 3303 if (!DyldInfoLoadCmd) 3304 return None; 3305 3306 MachO::dyld_info_command DyldInfo = 3307 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3308 const uint8_t *Ptr = 3309 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 3310 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 3311 } 3312 3313 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 3314 if (!DyldInfoLoadCmd) 3315 return None; 3316 3317 MachO::dyld_info_command DyldInfo = 3318 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3319 const uint8_t *Ptr = 3320 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 3321 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 3322 } 3323 3324 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 3325 if (!DyldInfoLoadCmd) 3326 return None; 3327 3328 MachO::dyld_info_command DyldInfo = 3329 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3330 const uint8_t *Ptr = 3331 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 3332 return makeArrayRef(Ptr, DyldInfo.export_size); 3333 } 3334 3335 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 3336 if (!UuidLoadCmd) 3337 return None; 3338 // Returning a pointer is fine as uuid doesn't need endian swapping. 3339 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 3340 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 3341 } 3342 3343 StringRef MachOObjectFile::getStringTableData() const { 3344 MachO::symtab_command S = getSymtabLoadCommand(); 3345 return getData().substr(S.stroff, S.strsize); 3346 } 3347 3348 bool MachOObjectFile::is64Bit() const { 3349 return getType() == getMachOType(false, true) || 3350 getType() == getMachOType(true, true); 3351 } 3352 3353 void MachOObjectFile::ReadULEB128s(uint64_t Index, 3354 SmallVectorImpl<uint64_t> &Out) const { 3355 DataExtractor extractor(ObjectFile::getData(), true, 0); 3356 3357 uint32_t offset = Index; 3358 uint64_t data = 0; 3359 while (uint64_t delta = extractor.getULEB128(&offset)) { 3360 data += delta; 3361 Out.push_back(data); 3362 } 3363 } 3364 3365 bool MachOObjectFile::isRelocatableObject() const { 3366 return getHeader().filetype == MachO::MH_OBJECT; 3367 } 3368 3369 Expected<std::unique_ptr<MachOObjectFile>> 3370 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer, 3371 uint32_t UniversalCputype, 3372 uint32_t UniversalIndex) { 3373 StringRef Magic = Buffer.getBuffer().slice(0, 4); 3374 if (Magic == "\xFE\xED\xFA\xCE") 3375 return MachOObjectFile::create(Buffer, false, false, 3376 UniversalCputype, UniversalIndex); 3377 if (Magic == "\xCE\xFA\xED\xFE") 3378 return MachOObjectFile::create(Buffer, true, false, 3379 UniversalCputype, UniversalIndex); 3380 if (Magic == "\xFE\xED\xFA\xCF") 3381 return MachOObjectFile::create(Buffer, false, true, 3382 UniversalCputype, UniversalIndex); 3383 if (Magic == "\xCF\xFA\xED\xFE") 3384 return MachOObjectFile::create(Buffer, true, true, 3385 UniversalCputype, UniversalIndex); 3386 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 3387 object_error::invalid_file_type); 3388 } 3389