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