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 static Error checkTwoLevelHintsCommand(const MachOObjectFile *Obj, 887 const MachOObjectFile::LoadCommandInfo 888 &Load, 889 uint32_t LoadCommandIndex, 890 const char **LoadCmd) { 891 if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command)) 892 return malformedError("load command " + Twine(LoadCommandIndex) + 893 " LC_TWOLEVEL_HINTS has incorrect cmdsize"); 894 if (*LoadCmd != nullptr) 895 return malformedError("more than one LC_TWOLEVEL_HINTS command"); 896 MachO::twolevel_hints_command Hints = 897 getStruct<MachO::twolevel_hints_command>(Obj, Load.Ptr); 898 uint64_t FileSize = Obj->getData().size(); 899 if (Hints.offset > FileSize) 900 return malformedError("offset field of LC_TWOLEVEL_HINTS command " + 901 Twine(LoadCommandIndex) + " extends past the end of " 902 "the file"); 903 uint64_t BigSize = Hints.nhints; 904 BigSize *= Hints.nhints * sizeof(MachO::twolevel_hint); 905 BigSize += Hints.offset; 906 if (BigSize > FileSize) 907 return malformedError("offset field plus nhints times sizeof(struct " 908 "twolevel_hint) field of LC_TWOLEVEL_HINTS command " + 909 Twine(LoadCommandIndex) + " extends past the end of " 910 "the file"); 911 *LoadCmd = Load.Ptr; 912 return Error::success(); 913 } 914 915 Expected<std::unique_ptr<MachOObjectFile>> 916 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, 917 bool Is64Bits) { 918 Error Err; 919 std::unique_ptr<MachOObjectFile> Obj( 920 new MachOObjectFile(std::move(Object), IsLittleEndian, 921 Is64Bits, Err)); 922 if (Err) 923 return std::move(Err); 924 return std::move(Obj); 925 } 926 927 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 928 bool Is64bits, Error &Err) 929 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 930 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 931 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 932 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 933 HasPageZeroSegment(false) { 934 ErrorAsOutParameter ErrAsOutParam(&Err); 935 uint64_t SizeOfHeaders; 936 if (is64Bit()) { 937 parseHeader(this, Header64, Err); 938 SizeOfHeaders = sizeof(MachO::mach_header_64); 939 } else { 940 parseHeader(this, Header, Err); 941 SizeOfHeaders = sizeof(MachO::mach_header); 942 } 943 if (Err) 944 return; 945 SizeOfHeaders += getHeader().sizeofcmds; 946 if (getData().data() + SizeOfHeaders > getData().end()) { 947 Err = malformedError("load commands extend past the end of the file"); 948 return; 949 } 950 951 uint32_t LoadCommandCount = getHeader().ncmds; 952 LoadCommandInfo Load; 953 if (LoadCommandCount != 0) { 954 if (auto LoadOrErr = getFirstLoadCommandInfo(this)) 955 Load = *LoadOrErr; 956 else { 957 Err = LoadOrErr.takeError(); 958 return; 959 } 960 } 961 962 const char *DyldIdLoadCmd = nullptr; 963 const char *FuncStartsLoadCmd = nullptr; 964 const char *SplitInfoLoadCmd = nullptr; 965 const char *CodeSignDrsLoadCmd = nullptr; 966 const char *CodeSignLoadCmd = nullptr; 967 const char *VersLoadCmd = nullptr; 968 const char *SourceLoadCmd = nullptr; 969 const char *EntryPointLoadCmd = nullptr; 970 const char *EncryptLoadCmd = nullptr; 971 const char *RoutinesLoadCmd = nullptr; 972 const char *UnixThreadLoadCmd = nullptr; 973 const char *TwoLevelHintsLoadCmd = nullptr; 974 for (unsigned I = 0; I < LoadCommandCount; ++I) { 975 if (is64Bit()) { 976 if (Load.C.cmdsize % 8 != 0) { 977 // We have a hack here to allow 64-bit Mach-O core files to have 978 // LC_THREAD commands that are only a multiple of 4 and not 8 to be 979 // allowed since the macOS kernel produces them. 980 if (getHeader().filetype != MachO::MH_CORE || 981 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { 982 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 983 "multiple of 8"); 984 return; 985 } 986 } 987 } else { 988 if (Load.C.cmdsize % 4 != 0) { 989 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 990 "multiple of 4"); 991 return; 992 } 993 } 994 LoadCommands.push_back(Load); 995 if (Load.C.cmd == MachO::LC_SYMTAB) { 996 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd))) 997 return; 998 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 999 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd))) 1000 return; 1001 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 1002 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd, 1003 "LC_DATA_IN_CODE"))) 1004 return; 1005 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 1006 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, 1007 "LC_LINKER_OPTIMIZATION_HINT"))) 1008 return; 1009 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) { 1010 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd, 1011 "LC_FUNCTION_STARTS"))) 1012 return; 1013 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) { 1014 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd, 1015 "LC_SEGMENT_SPLIT_INFO"))) 1016 return; 1017 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) { 1018 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd, 1019 "LC_DYLIB_CODE_SIGN_DRS"))) 1020 return; 1021 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) { 1022 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd, 1023 "LC_CODE_SIGNATURE"))) 1024 return; 1025 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { 1026 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1027 "LC_DYLD_INFO"))) 1028 return; 1029 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 1030 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 1031 "LC_DYLD_INFO_ONLY"))) 1032 return; 1033 } else if (Load.C.cmd == MachO::LC_UUID) { 1034 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { 1035 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " 1036 "cmdsize"); 1037 return; 1038 } 1039 if (UuidLoadCmd) { 1040 Err = malformedError("more than one LC_UUID command"); 1041 return; 1042 } 1043 UuidLoadCmd = Load.Ptr; 1044 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 1045 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64, 1046 MachO::section_64>( 1047 this, Load, Sections, HasPageZeroSegment, I, 1048 "LC_SEGMENT_64", SizeOfHeaders))) 1049 return; 1050 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 1051 if ((Err = parseSegmentLoadCommand<MachO::segment_command, 1052 MachO::section>( 1053 this, Load, Sections, HasPageZeroSegment, I, 1054 "LC_SEGMENT", SizeOfHeaders))) 1055 return; 1056 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) { 1057 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd))) 1058 return; 1059 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) { 1060 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB"))) 1061 return; 1062 Libraries.push_back(Load.Ptr); 1063 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) { 1064 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB"))) 1065 return; 1066 Libraries.push_back(Load.Ptr); 1067 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) { 1068 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB"))) 1069 return; 1070 Libraries.push_back(Load.Ptr); 1071 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) { 1072 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB"))) 1073 return; 1074 Libraries.push_back(Load.Ptr); 1075 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 1076 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB"))) 1077 return; 1078 Libraries.push_back(Load.Ptr); 1079 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) { 1080 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER"))) 1081 return; 1082 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) { 1083 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER"))) 1084 return; 1085 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 1086 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT"))) 1087 return; 1088 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) { 1089 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1090 "LC_VERSION_MIN_MACOSX"))) 1091 return; 1092 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { 1093 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1094 "LC_VERSION_MIN_IPHONEOS"))) 1095 return; 1096 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) { 1097 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1098 "LC_VERSION_MIN_TVOS"))) 1099 return; 1100 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 1101 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 1102 "LC_VERSION_MIN_WATCHOS"))) 1103 return; 1104 } else if (Load.C.cmd == MachO::LC_RPATH) { 1105 if ((Err = checkRpathCommand(this, Load, I))) 1106 return; 1107 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) { 1108 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) { 1109 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) + 1110 " has incorrect cmdsize"); 1111 return; 1112 } 1113 if (SourceLoadCmd) { 1114 Err = malformedError("more than one LC_SOURCE_VERSION command"); 1115 return; 1116 } 1117 SourceLoadCmd = Load.Ptr; 1118 } else if (Load.C.cmd == MachO::LC_MAIN) { 1119 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) { 1120 Err = malformedError("LC_MAIN command " + Twine(I) + 1121 " has incorrect cmdsize"); 1122 return; 1123 } 1124 if (EntryPointLoadCmd) { 1125 Err = malformedError("more than one LC_MAIN command"); 1126 return; 1127 } 1128 EntryPointLoadCmd = Load.Ptr; 1129 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) { 1130 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) { 1131 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) + 1132 " has incorrect cmdsize"); 1133 return; 1134 } 1135 MachO::encryption_info_command E = 1136 getStruct<MachO::encryption_info_command>(this, Load.Ptr); 1137 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1138 &EncryptLoadCmd, "LC_ENCRYPTION_INFO"))) 1139 return; 1140 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 1141 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) { 1142 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) + 1143 " has incorrect cmdsize"); 1144 return; 1145 } 1146 MachO::encryption_info_command_64 E = 1147 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr); 1148 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1149 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64"))) 1150 return; 1151 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) { 1152 if ((Err = checkLinkerOptCommand(this, Load, I))) 1153 return; 1154 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) { 1155 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) { 1156 Err = malformedError("load command " + Twine(I) + 1157 " LC_SUB_FRAMEWORK cmdsize too small"); 1158 return; 1159 } 1160 MachO::sub_framework_command S = 1161 getStruct<MachO::sub_framework_command>(this, Load.Ptr); 1162 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK", 1163 sizeof(MachO::sub_framework_command), 1164 "sub_framework_command", S.umbrella, 1165 "umbrella"))) 1166 return; 1167 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) { 1168 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) { 1169 Err = malformedError("load command " + Twine(I) + 1170 " LC_SUB_UMBRELLA cmdsize too small"); 1171 return; 1172 } 1173 MachO::sub_umbrella_command S = 1174 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr); 1175 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA", 1176 sizeof(MachO::sub_umbrella_command), 1177 "sub_umbrella_command", S.sub_umbrella, 1178 "sub_umbrella"))) 1179 return; 1180 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) { 1181 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) { 1182 Err = malformedError("load command " + Twine(I) + 1183 " LC_SUB_LIBRARY cmdsize too small"); 1184 return; 1185 } 1186 MachO::sub_library_command S = 1187 getStruct<MachO::sub_library_command>(this, Load.Ptr); 1188 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY", 1189 sizeof(MachO::sub_library_command), 1190 "sub_library_command", S.sub_library, 1191 "sub_library"))) 1192 return; 1193 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) { 1194 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) { 1195 Err = malformedError("load command " + Twine(I) + 1196 " LC_SUB_CLIENT cmdsize too small"); 1197 return; 1198 } 1199 MachO::sub_client_command S = 1200 getStruct<MachO::sub_client_command>(this, Load.Ptr); 1201 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT", 1202 sizeof(MachO::sub_client_command), 1203 "sub_client_command", S.client, "client"))) 1204 return; 1205 } else if (Load.C.cmd == MachO::LC_ROUTINES) { 1206 if (Load.C.cmdsize != sizeof(MachO::routines_command)) { 1207 Err = malformedError("LC_ROUTINES command " + Twine(I) + 1208 " has incorrect cmdsize"); 1209 return; 1210 } 1211 if (RoutinesLoadCmd) { 1212 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 " 1213 "command"); 1214 return; 1215 } 1216 RoutinesLoadCmd = Load.Ptr; 1217 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) { 1218 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) { 1219 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) + 1220 " has incorrect cmdsize"); 1221 return; 1222 } 1223 if (RoutinesLoadCmd) { 1224 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES " 1225 "command"); 1226 return; 1227 } 1228 RoutinesLoadCmd = Load.Ptr; 1229 } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) { 1230 if ((Err = checkThreadCommand(this, Load, I, "LC_UNIXTHREAD"))) 1231 return; 1232 if (UnixThreadLoadCmd) { 1233 Err = malformedError("more than one LC_UNIXTHREAD command"); 1234 return; 1235 } 1236 UnixThreadLoadCmd = Load.Ptr; 1237 } else if (Load.C.cmd == MachO::LC_THREAD) { 1238 if ((Err = checkThreadCommand(this, Load, I, "LC_THREAD"))) 1239 return; 1240 } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) { 1241 if ((Err = checkTwoLevelHintsCommand(this, Load, I, 1242 &TwoLevelHintsLoadCmd))) 1243 return; 1244 } 1245 if (I < LoadCommandCount - 1) { 1246 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) 1247 Load = *LoadOrErr; 1248 else { 1249 Err = LoadOrErr.takeError(); 1250 return; 1251 } 1252 } 1253 } 1254 if (!SymtabLoadCmd) { 1255 if (DysymtabLoadCmd) { 1256 Err = malformedError("contains LC_DYSYMTAB load command without a " 1257 "LC_SYMTAB load command"); 1258 return; 1259 } 1260 } else if (DysymtabLoadCmd) { 1261 MachO::symtab_command Symtab = 1262 getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1263 MachO::dysymtab_command Dysymtab = 1264 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1265 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1266 Err = malformedError("ilocalsym in LC_DYSYMTAB load command " 1267 "extends past the end of the symbol table"); 1268 return; 1269 } 1270 uint64_t BigSize = Dysymtab.ilocalsym; 1271 BigSize += Dysymtab.nlocalsym; 1272 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { 1273 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " 1274 "command extends past the end of the symbol table"); 1275 return; 1276 } 1277 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1278 Err = malformedError("nextdefsym in LC_DYSYMTAB load command " 1279 "extends past the end of the symbol table"); 1280 return; 1281 } 1282 BigSize = Dysymtab.iextdefsym; 1283 BigSize += Dysymtab.nextdefsym; 1284 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { 1285 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " 1286 "load command extends past the end of the symbol " 1287 "table"); 1288 return; 1289 } 1290 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { 1291 Err = malformedError("nundefsym in LC_DYSYMTAB load command " 1292 "extends past the end of the symbol table"); 1293 return; 1294 } 1295 BigSize = Dysymtab.iundefsym; 1296 BigSize += Dysymtab.nundefsym; 1297 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { 1298 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " 1299 " command extends past the end of the symbol table"); 1300 return; 1301 } 1302 } 1303 if ((getHeader().filetype == MachO::MH_DYLIB || 1304 getHeader().filetype == MachO::MH_DYLIB_STUB) && 1305 DyldIdLoadCmd == nullptr) { 1306 Err = malformedError("no LC_ID_DYLIB load command in dynamic library " 1307 "filetype"); 1308 return; 1309 } 1310 assert(LoadCommands.size() == LoadCommandCount); 1311 1312 Err = Error::success(); 1313 } 1314 1315 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1316 unsigned SymbolTableEntrySize = is64Bit() ? 1317 sizeof(MachO::nlist_64) : 1318 sizeof(MachO::nlist); 1319 Symb.p += SymbolTableEntrySize; 1320 } 1321 1322 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 1323 StringRef StringTable = getStringTableData(); 1324 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1325 const char *Start = &StringTable.data()[Entry.n_strx]; 1326 if (Start < getData().begin() || Start >= getData().end()) { 1327 return malformedError("bad string index: " + Twine(Entry.n_strx) + 1328 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1329 } 1330 return StringRef(Start); 1331 } 1332 1333 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 1334 DataRefImpl DRI = Sec.getRawDataRefImpl(); 1335 uint32_t Flags = getSectionFlags(this, DRI); 1336 return Flags & MachO::SECTION_TYPE; 1337 } 1338 1339 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 1340 if (is64Bit()) { 1341 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 1342 return Entry.n_value; 1343 } 1344 MachO::nlist Entry = getSymbolTableEntry(Sym); 1345 return Entry.n_value; 1346 } 1347 1348 // getIndirectName() returns the name of the alias'ed symbol who's string table 1349 // index is in the n_value field. 1350 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 1351 StringRef &Res) const { 1352 StringRef StringTable = getStringTableData(); 1353 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1354 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 1355 return object_error::parse_failed; 1356 uint64_t NValue = getNValue(Symb); 1357 if (NValue >= StringTable.size()) 1358 return object_error::parse_failed; 1359 const char *Start = &StringTable.data()[NValue]; 1360 Res = StringRef(Start); 1361 return std::error_code(); 1362 } 1363 1364 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { 1365 return getNValue(Sym); 1366 } 1367 1368 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { 1369 return getSymbolValue(Sym); 1370 } 1371 1372 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 1373 uint32_t flags = getSymbolFlags(DRI); 1374 if (flags & SymbolRef::SF_Common) { 1375 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1376 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 1377 } 1378 return 0; 1379 } 1380 1381 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 1382 return getNValue(DRI); 1383 } 1384 1385 Expected<SymbolRef::Type> 1386 MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 1387 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1388 uint8_t n_type = Entry.n_type; 1389 1390 // If this is a STAB debugging symbol, we can do nothing more. 1391 if (n_type & MachO::N_STAB) 1392 return SymbolRef::ST_Debug; 1393 1394 switch (n_type & MachO::N_TYPE) { 1395 case MachO::N_UNDF : 1396 return SymbolRef::ST_Unknown; 1397 case MachO::N_SECT : 1398 Expected<section_iterator> SecOrError = getSymbolSection(Symb); 1399 if (!SecOrError) 1400 return SecOrError.takeError(); 1401 section_iterator Sec = *SecOrError; 1402 if (Sec->isData() || Sec->isBSS()) 1403 return SymbolRef::ST_Data; 1404 return SymbolRef::ST_Function; 1405 } 1406 return SymbolRef::ST_Other; 1407 } 1408 1409 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 1410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1411 1412 uint8_t MachOType = Entry.n_type; 1413 uint16_t MachOFlags = Entry.n_desc; 1414 1415 uint32_t Result = SymbolRef::SF_None; 1416 1417 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 1418 Result |= SymbolRef::SF_Indirect; 1419 1420 if (MachOType & MachO::N_STAB) 1421 Result |= SymbolRef::SF_FormatSpecific; 1422 1423 if (MachOType & MachO::N_EXT) { 1424 Result |= SymbolRef::SF_Global; 1425 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 1426 if (getNValue(DRI)) 1427 Result |= SymbolRef::SF_Common; 1428 else 1429 Result |= SymbolRef::SF_Undefined; 1430 } 1431 1432 if (!(MachOType & MachO::N_PEXT)) 1433 Result |= SymbolRef::SF_Exported; 1434 } 1435 1436 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 1437 Result |= SymbolRef::SF_Weak; 1438 1439 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 1440 Result |= SymbolRef::SF_Thumb; 1441 1442 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 1443 Result |= SymbolRef::SF_Absolute; 1444 1445 return Result; 1446 } 1447 1448 Expected<section_iterator> 1449 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { 1450 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1451 uint8_t index = Entry.n_sect; 1452 1453 if (index == 0) 1454 return section_end(); 1455 DataRefImpl DRI; 1456 DRI.d.a = index - 1; 1457 if (DRI.d.a >= Sections.size()){ 1458 return malformedError("bad section index: " + Twine((int)index) + 1459 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1460 } 1461 return section_iterator(SectionRef(DRI, this)); 1462 } 1463 1464 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 1465 MachO::nlist_base Entry = 1466 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 1467 return Entry.n_sect - 1; 1468 } 1469 1470 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 1471 Sec.d.a++; 1472 } 1473 1474 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 1475 StringRef &Result) const { 1476 ArrayRef<char> Raw = getSectionRawName(Sec); 1477 Result = parseSegmentOrSectionName(Raw.data()); 1478 return std::error_code(); 1479 } 1480 1481 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 1482 if (is64Bit()) 1483 return getSection64(Sec).addr; 1484 return getSection(Sec).addr; 1485 } 1486 1487 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 1488 // In the case if a malformed Mach-O file where the section offset is past 1489 // the end of the file or some part of the section size is past the end of 1490 // the file return a size of zero or a size that covers the rest of the file 1491 // but does not extend past the end of the file. 1492 uint32_t SectOffset, SectType; 1493 uint64_t SectSize; 1494 1495 if (is64Bit()) { 1496 MachO::section_64 Sect = getSection64(Sec); 1497 SectOffset = Sect.offset; 1498 SectSize = Sect.size; 1499 SectType = Sect.flags & MachO::SECTION_TYPE; 1500 } else { 1501 MachO::section Sect = getSection(Sec); 1502 SectOffset = Sect.offset; 1503 SectSize = Sect.size; 1504 SectType = Sect.flags & MachO::SECTION_TYPE; 1505 } 1506 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL) 1507 return SectSize; 1508 uint64_t FileSize = getData().size(); 1509 if (SectOffset > FileSize) 1510 return 0; 1511 if (FileSize - SectOffset < SectSize) 1512 return FileSize - SectOffset; 1513 return SectSize; 1514 } 1515 1516 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 1517 StringRef &Res) const { 1518 uint32_t Offset; 1519 uint64_t Size; 1520 1521 if (is64Bit()) { 1522 MachO::section_64 Sect = getSection64(Sec); 1523 Offset = Sect.offset; 1524 Size = Sect.size; 1525 } else { 1526 MachO::section Sect = getSection(Sec); 1527 Offset = Sect.offset; 1528 Size = Sect.size; 1529 } 1530 1531 Res = this->getData().substr(Offset, Size); 1532 return std::error_code(); 1533 } 1534 1535 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1536 uint32_t Align; 1537 if (is64Bit()) { 1538 MachO::section_64 Sect = getSection64(Sec); 1539 Align = Sect.align; 1540 } else { 1541 MachO::section Sect = getSection(Sec); 1542 Align = Sect.align; 1543 } 1544 1545 return uint64_t(1) << Align; 1546 } 1547 1548 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1549 return false; 1550 } 1551 1552 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 1553 uint32_t Flags = getSectionFlags(this, Sec); 1554 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 1555 } 1556 1557 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 1558 uint32_t Flags = getSectionFlags(this, Sec); 1559 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1560 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1561 !(SectionType == MachO::S_ZEROFILL || 1562 SectionType == MachO::S_GB_ZEROFILL); 1563 } 1564 1565 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 1566 uint32_t Flags = getSectionFlags(this, Sec); 1567 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1568 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1569 (SectionType == MachO::S_ZEROFILL || 1570 SectionType == MachO::S_GB_ZEROFILL); 1571 } 1572 1573 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 1574 return Sec.getRawDataRefImpl().d.a; 1575 } 1576 1577 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 1578 // FIXME: Unimplemented. 1579 return false; 1580 } 1581 1582 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { 1583 StringRef SegmentName = getSectionFinalSegmentName(Sec); 1584 StringRef SectName; 1585 if (!getSectionName(Sec, SectName)) 1586 return (SegmentName == "__LLVM" && SectName == "__bitcode"); 1587 return false; 1588 } 1589 1590 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1591 DataRefImpl Ret; 1592 Ret.d.a = Sec.d.a; 1593 Ret.d.b = 0; 1594 return relocation_iterator(RelocationRef(Ret, this)); 1595 } 1596 1597 relocation_iterator 1598 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1599 uint32_t Num; 1600 if (is64Bit()) { 1601 MachO::section_64 Sect = getSection64(Sec); 1602 Num = Sect.nreloc; 1603 } else { 1604 MachO::section Sect = getSection(Sec); 1605 Num = Sect.nreloc; 1606 } 1607 1608 DataRefImpl Ret; 1609 Ret.d.a = Sec.d.a; 1610 Ret.d.b = Num; 1611 return relocation_iterator(RelocationRef(Ret, this)); 1612 } 1613 1614 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1615 ++Rel.d.b; 1616 } 1617 1618 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1619 assert(getHeader().filetype == MachO::MH_OBJECT && 1620 "Only implemented for MH_OBJECT"); 1621 MachO::any_relocation_info RE = getRelocation(Rel); 1622 return getAnyRelocationAddress(RE); 1623 } 1624 1625 symbol_iterator 1626 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1627 MachO::any_relocation_info RE = getRelocation(Rel); 1628 if (isRelocationScattered(RE)) 1629 return symbol_end(); 1630 1631 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1632 bool isExtern = getPlainRelocationExternal(RE); 1633 if (!isExtern) 1634 return symbol_end(); 1635 1636 MachO::symtab_command S = getSymtabLoadCommand(); 1637 unsigned SymbolTableEntrySize = is64Bit() ? 1638 sizeof(MachO::nlist_64) : 1639 sizeof(MachO::nlist); 1640 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1641 DataRefImpl Sym; 1642 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1643 return symbol_iterator(SymbolRef(Sym, this)); 1644 } 1645 1646 section_iterator 1647 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 1648 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 1649 } 1650 1651 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 1652 MachO::any_relocation_info RE = getRelocation(Rel); 1653 return getAnyRelocationType(RE); 1654 } 1655 1656 void MachOObjectFile::getRelocationTypeName( 1657 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1658 StringRef res; 1659 uint64_t RType = getRelocationType(Rel); 1660 1661 unsigned Arch = this->getArch(); 1662 1663 switch (Arch) { 1664 case Triple::x86: { 1665 static const char *const Table[] = { 1666 "GENERIC_RELOC_VANILLA", 1667 "GENERIC_RELOC_PAIR", 1668 "GENERIC_RELOC_SECTDIFF", 1669 "GENERIC_RELOC_PB_LA_PTR", 1670 "GENERIC_RELOC_LOCAL_SECTDIFF", 1671 "GENERIC_RELOC_TLV" }; 1672 1673 if (RType > 5) 1674 res = "Unknown"; 1675 else 1676 res = Table[RType]; 1677 break; 1678 } 1679 case Triple::x86_64: { 1680 static const char *const Table[] = { 1681 "X86_64_RELOC_UNSIGNED", 1682 "X86_64_RELOC_SIGNED", 1683 "X86_64_RELOC_BRANCH", 1684 "X86_64_RELOC_GOT_LOAD", 1685 "X86_64_RELOC_GOT", 1686 "X86_64_RELOC_SUBTRACTOR", 1687 "X86_64_RELOC_SIGNED_1", 1688 "X86_64_RELOC_SIGNED_2", 1689 "X86_64_RELOC_SIGNED_4", 1690 "X86_64_RELOC_TLV" }; 1691 1692 if (RType > 9) 1693 res = "Unknown"; 1694 else 1695 res = Table[RType]; 1696 break; 1697 } 1698 case Triple::arm: { 1699 static const char *const Table[] = { 1700 "ARM_RELOC_VANILLA", 1701 "ARM_RELOC_PAIR", 1702 "ARM_RELOC_SECTDIFF", 1703 "ARM_RELOC_LOCAL_SECTDIFF", 1704 "ARM_RELOC_PB_LA_PTR", 1705 "ARM_RELOC_BR24", 1706 "ARM_THUMB_RELOC_BR22", 1707 "ARM_THUMB_32BIT_BRANCH", 1708 "ARM_RELOC_HALF", 1709 "ARM_RELOC_HALF_SECTDIFF" }; 1710 1711 if (RType > 9) 1712 res = "Unknown"; 1713 else 1714 res = Table[RType]; 1715 break; 1716 } 1717 case Triple::aarch64: { 1718 static const char *const Table[] = { 1719 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 1720 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 1721 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 1722 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 1723 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 1724 "ARM64_RELOC_ADDEND" 1725 }; 1726 1727 if (RType >= array_lengthof(Table)) 1728 res = "Unknown"; 1729 else 1730 res = Table[RType]; 1731 break; 1732 } 1733 case Triple::ppc: { 1734 static const char *const Table[] = { 1735 "PPC_RELOC_VANILLA", 1736 "PPC_RELOC_PAIR", 1737 "PPC_RELOC_BR14", 1738 "PPC_RELOC_BR24", 1739 "PPC_RELOC_HI16", 1740 "PPC_RELOC_LO16", 1741 "PPC_RELOC_HA16", 1742 "PPC_RELOC_LO14", 1743 "PPC_RELOC_SECTDIFF", 1744 "PPC_RELOC_PB_LA_PTR", 1745 "PPC_RELOC_HI16_SECTDIFF", 1746 "PPC_RELOC_LO16_SECTDIFF", 1747 "PPC_RELOC_HA16_SECTDIFF", 1748 "PPC_RELOC_JBSR", 1749 "PPC_RELOC_LO14_SECTDIFF", 1750 "PPC_RELOC_LOCAL_SECTDIFF" }; 1751 1752 if (RType > 15) 1753 res = "Unknown"; 1754 else 1755 res = Table[RType]; 1756 break; 1757 } 1758 case Triple::UnknownArch: 1759 res = "Unknown"; 1760 break; 1761 } 1762 Result.append(res.begin(), res.end()); 1763 } 1764 1765 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 1766 MachO::any_relocation_info RE = getRelocation(Rel); 1767 return getAnyRelocationLength(RE); 1768 } 1769 1770 // 1771 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1772 // guess on what the short name is. Then name is returned as a substring of the 1773 // StringRef Name passed in. The name of the dynamic library is recognized as 1774 // a framework if it has one of the two following forms: 1775 // Foo.framework/Versions/A/Foo 1776 // Foo.framework/Foo 1777 // Where A and Foo can be any string. And may contain a trailing suffix 1778 // starting with an underbar. If the Name is recognized as a framework then 1779 // isFramework is set to true else it is set to false. If the Name has a 1780 // suffix then Suffix is set to the substring in Name that contains the suffix 1781 // else it is set to a NULL StringRef. 1782 // 1783 // The Name of the dynamic library is recognized as a library name if it has 1784 // one of the two following forms: 1785 // libFoo.A.dylib 1786 // libFoo.dylib 1787 // The library may have a suffix trailing the name Foo of the form: 1788 // libFoo_profile.A.dylib 1789 // libFoo_profile.dylib 1790 // 1791 // The Name of the dynamic library is also recognized as a library name if it 1792 // has the following form: 1793 // Foo.qtx 1794 // 1795 // If the Name of the dynamic library is none of the forms above then a NULL 1796 // StringRef is returned. 1797 // 1798 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1799 bool &isFramework, 1800 StringRef &Suffix) { 1801 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1802 size_t a, b, c, d, Idx; 1803 1804 isFramework = false; 1805 Suffix = StringRef(); 1806 1807 // Pull off the last component and make Foo point to it 1808 a = Name.rfind('/'); 1809 if (a == Name.npos || a == 0) 1810 goto guess_library; 1811 Foo = Name.slice(a+1, Name.npos); 1812 1813 // Look for a suffix starting with a '_' 1814 Idx = Foo.rfind('_'); 1815 if (Idx != Foo.npos && Foo.size() >= 2) { 1816 Suffix = Foo.slice(Idx, Foo.npos); 1817 Foo = Foo.slice(0, Idx); 1818 } 1819 1820 // First look for the form Foo.framework/Foo 1821 b = Name.rfind('/', a); 1822 if (b == Name.npos) 1823 Idx = 0; 1824 else 1825 Idx = b+1; 1826 F = Name.slice(Idx, Idx + Foo.size()); 1827 DotFramework = Name.slice(Idx + Foo.size(), 1828 Idx + Foo.size() + sizeof(".framework/")-1); 1829 if (F == Foo && DotFramework == ".framework/") { 1830 isFramework = true; 1831 return Foo; 1832 } 1833 1834 // Next look for the form Foo.framework/Versions/A/Foo 1835 if (b == Name.npos) 1836 goto guess_library; 1837 c = Name.rfind('/', b); 1838 if (c == Name.npos || c == 0) 1839 goto guess_library; 1840 V = Name.slice(c+1, Name.npos); 1841 if (!V.startswith("Versions/")) 1842 goto guess_library; 1843 d = Name.rfind('/', c); 1844 if (d == Name.npos) 1845 Idx = 0; 1846 else 1847 Idx = d+1; 1848 F = Name.slice(Idx, Idx + Foo.size()); 1849 DotFramework = Name.slice(Idx + Foo.size(), 1850 Idx + Foo.size() + sizeof(".framework/")-1); 1851 if (F == Foo && DotFramework == ".framework/") { 1852 isFramework = true; 1853 return Foo; 1854 } 1855 1856 guess_library: 1857 // pull off the suffix after the "." and make a point to it 1858 a = Name.rfind('.'); 1859 if (a == Name.npos || a == 0) 1860 return StringRef(); 1861 Dylib = Name.slice(a, Name.npos); 1862 if (Dylib != ".dylib") 1863 goto guess_qtx; 1864 1865 // First pull off the version letter for the form Foo.A.dylib if any. 1866 if (a >= 3) { 1867 Dot = Name.slice(a-2, a-1); 1868 if (Dot == ".") 1869 a = a - 2; 1870 } 1871 1872 b = Name.rfind('/', a); 1873 if (b == Name.npos) 1874 b = 0; 1875 else 1876 b = b+1; 1877 // ignore any suffix after an underbar like Foo_profile.A.dylib 1878 Idx = Name.find('_', b); 1879 if (Idx != Name.npos && Idx != b) { 1880 Lib = Name.slice(b, Idx); 1881 Suffix = Name.slice(Idx, a); 1882 } 1883 else 1884 Lib = Name.slice(b, a); 1885 // There are incorrect library names of the form: 1886 // libATS.A_profile.dylib so check for these. 1887 if (Lib.size() >= 3) { 1888 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1889 if (Dot == ".") 1890 Lib = Lib.slice(0, Lib.size()-2); 1891 } 1892 return Lib; 1893 1894 guess_qtx: 1895 Qtx = Name.slice(a, Name.npos); 1896 if (Qtx != ".qtx") 1897 return StringRef(); 1898 b = Name.rfind('/', a); 1899 if (b == Name.npos) 1900 Lib = Name.slice(0, a); 1901 else 1902 Lib = Name.slice(b+1, a); 1903 // There are library names of the form: QT.A.qtx so check for these. 1904 if (Lib.size() >= 3) { 1905 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1906 if (Dot == ".") 1907 Lib = Lib.slice(0, Lib.size()-2); 1908 } 1909 return Lib; 1910 } 1911 1912 // getLibraryShortNameByIndex() is used to get the short name of the library 1913 // for an undefined symbol in a linked Mach-O binary that was linked with the 1914 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1915 // It is passed the index (0 - based) of the library as translated from 1916 // GET_LIBRARY_ORDINAL (1 - based). 1917 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1918 StringRef &Res) const { 1919 if (Index >= Libraries.size()) 1920 return object_error::parse_failed; 1921 1922 // If the cache of LibrariesShortNames is not built up do that first for 1923 // all the Libraries. 1924 if (LibrariesShortNames.size() == 0) { 1925 for (unsigned i = 0; i < Libraries.size(); i++) { 1926 MachO::dylib_command D = 1927 getStruct<MachO::dylib_command>(this, Libraries[i]); 1928 if (D.dylib.name >= D.cmdsize) 1929 return object_error::parse_failed; 1930 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1931 StringRef Name = StringRef(P); 1932 if (D.dylib.name+Name.size() >= D.cmdsize) 1933 return object_error::parse_failed; 1934 StringRef Suffix; 1935 bool isFramework; 1936 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1937 if (shortName.empty()) 1938 LibrariesShortNames.push_back(Name); 1939 else 1940 LibrariesShortNames.push_back(shortName); 1941 } 1942 } 1943 1944 Res = LibrariesShortNames[Index]; 1945 return std::error_code(); 1946 } 1947 1948 section_iterator 1949 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 1950 DataRefImpl Sec; 1951 Sec.d.a = Rel->getRawDataRefImpl().d.a; 1952 return section_iterator(SectionRef(Sec, this)); 1953 } 1954 1955 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1956 DataRefImpl DRI; 1957 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1958 if (!SymtabLoadCmd || Symtab.nsyms == 0) 1959 return basic_symbol_iterator(SymbolRef(DRI, this)); 1960 1961 return getSymbolByIndex(0); 1962 } 1963 1964 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1965 DataRefImpl DRI; 1966 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1967 if (!SymtabLoadCmd || Symtab.nsyms == 0) 1968 return basic_symbol_iterator(SymbolRef(DRI, this)); 1969 1970 unsigned SymbolTableEntrySize = is64Bit() ? 1971 sizeof(MachO::nlist_64) : 1972 sizeof(MachO::nlist); 1973 unsigned Offset = Symtab.symoff + 1974 Symtab.nsyms * SymbolTableEntrySize; 1975 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1976 return basic_symbol_iterator(SymbolRef(DRI, this)); 1977 } 1978 1979 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1980 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1981 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 1982 report_fatal_error("Requested symbol index is out of range."); 1983 unsigned SymbolTableEntrySize = 1984 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1985 DataRefImpl DRI; 1986 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1987 DRI.p += Index * SymbolTableEntrySize; 1988 return basic_symbol_iterator(SymbolRef(DRI, this)); 1989 } 1990 1991 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 1992 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1993 if (!SymtabLoadCmd) 1994 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 1995 unsigned SymbolTableEntrySize = 1996 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1997 DataRefImpl DRIstart; 1998 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1999 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 2000 return Index; 2001 } 2002 2003 section_iterator MachOObjectFile::section_begin() const { 2004 DataRefImpl DRI; 2005 return section_iterator(SectionRef(DRI, this)); 2006 } 2007 2008 section_iterator MachOObjectFile::section_end() const { 2009 DataRefImpl DRI; 2010 DRI.d.a = Sections.size(); 2011 return section_iterator(SectionRef(DRI, this)); 2012 } 2013 2014 uint8_t MachOObjectFile::getBytesInAddress() const { 2015 return is64Bit() ? 8 : 4; 2016 } 2017 2018 StringRef MachOObjectFile::getFileFormatName() const { 2019 unsigned CPUType = getCPUType(this); 2020 if (!is64Bit()) { 2021 switch (CPUType) { 2022 case llvm::MachO::CPU_TYPE_I386: 2023 return "Mach-O 32-bit i386"; 2024 case llvm::MachO::CPU_TYPE_ARM: 2025 return "Mach-O arm"; 2026 case llvm::MachO::CPU_TYPE_POWERPC: 2027 return "Mach-O 32-bit ppc"; 2028 default: 2029 return "Mach-O 32-bit unknown"; 2030 } 2031 } 2032 2033 switch (CPUType) { 2034 case llvm::MachO::CPU_TYPE_X86_64: 2035 return "Mach-O 64-bit x86-64"; 2036 case llvm::MachO::CPU_TYPE_ARM64: 2037 return "Mach-O arm64"; 2038 case llvm::MachO::CPU_TYPE_POWERPC64: 2039 return "Mach-O 64-bit ppc64"; 2040 default: 2041 return "Mach-O 64-bit unknown"; 2042 } 2043 } 2044 2045 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 2046 switch (CPUType) { 2047 case llvm::MachO::CPU_TYPE_I386: 2048 return Triple::x86; 2049 case llvm::MachO::CPU_TYPE_X86_64: 2050 return Triple::x86_64; 2051 case llvm::MachO::CPU_TYPE_ARM: 2052 return Triple::arm; 2053 case llvm::MachO::CPU_TYPE_ARM64: 2054 return Triple::aarch64; 2055 case llvm::MachO::CPU_TYPE_POWERPC: 2056 return Triple::ppc; 2057 case llvm::MachO::CPU_TYPE_POWERPC64: 2058 return Triple::ppc64; 2059 default: 2060 return Triple::UnknownArch; 2061 } 2062 } 2063 2064 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 2065 const char **McpuDefault) { 2066 if (McpuDefault) 2067 *McpuDefault = nullptr; 2068 2069 switch (CPUType) { 2070 case MachO::CPU_TYPE_I386: 2071 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2072 case MachO::CPU_SUBTYPE_I386_ALL: 2073 return Triple("i386-apple-darwin"); 2074 default: 2075 return Triple(); 2076 } 2077 case MachO::CPU_TYPE_X86_64: 2078 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2079 case MachO::CPU_SUBTYPE_X86_64_ALL: 2080 return Triple("x86_64-apple-darwin"); 2081 case MachO::CPU_SUBTYPE_X86_64_H: 2082 return Triple("x86_64h-apple-darwin"); 2083 default: 2084 return Triple(); 2085 } 2086 case MachO::CPU_TYPE_ARM: 2087 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2088 case MachO::CPU_SUBTYPE_ARM_V4T: 2089 return Triple("armv4t-apple-darwin"); 2090 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 2091 return Triple("armv5e-apple-darwin"); 2092 case MachO::CPU_SUBTYPE_ARM_XSCALE: 2093 return Triple("xscale-apple-darwin"); 2094 case MachO::CPU_SUBTYPE_ARM_V6: 2095 return Triple("armv6-apple-darwin"); 2096 case MachO::CPU_SUBTYPE_ARM_V6M: 2097 if (McpuDefault) 2098 *McpuDefault = "cortex-m0"; 2099 return Triple("armv6m-apple-darwin"); 2100 case MachO::CPU_SUBTYPE_ARM_V7: 2101 return Triple("armv7-apple-darwin"); 2102 case MachO::CPU_SUBTYPE_ARM_V7EM: 2103 if (McpuDefault) 2104 *McpuDefault = "cortex-m4"; 2105 return Triple("thumbv7em-apple-darwin"); 2106 case MachO::CPU_SUBTYPE_ARM_V7K: 2107 return Triple("armv7k-apple-darwin"); 2108 case MachO::CPU_SUBTYPE_ARM_V7M: 2109 if (McpuDefault) 2110 *McpuDefault = "cortex-m3"; 2111 return Triple("thumbv7m-apple-darwin"); 2112 case MachO::CPU_SUBTYPE_ARM_V7S: 2113 return Triple("armv7s-apple-darwin"); 2114 default: 2115 return Triple(); 2116 } 2117 case MachO::CPU_TYPE_ARM64: 2118 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2119 case MachO::CPU_SUBTYPE_ARM64_ALL: 2120 return Triple("arm64-apple-darwin"); 2121 default: 2122 return Triple(); 2123 } 2124 case MachO::CPU_TYPE_POWERPC: 2125 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2126 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2127 return Triple("ppc-apple-darwin"); 2128 default: 2129 return Triple(); 2130 } 2131 case MachO::CPU_TYPE_POWERPC64: 2132 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 2133 case MachO::CPU_SUBTYPE_POWERPC_ALL: 2134 return Triple("ppc64-apple-darwin"); 2135 default: 2136 return Triple(); 2137 } 2138 default: 2139 return Triple(); 2140 } 2141 } 2142 2143 Triple MachOObjectFile::getHostArch() { 2144 return Triple(sys::getDefaultTargetTriple()); 2145 } 2146 2147 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2148 return StringSwitch<bool>(ArchFlag) 2149 .Case("i386", true) 2150 .Case("x86_64", true) 2151 .Case("x86_64h", true) 2152 .Case("armv4t", true) 2153 .Case("arm", true) 2154 .Case("armv5e", true) 2155 .Case("armv6", true) 2156 .Case("armv6m", true) 2157 .Case("armv7", true) 2158 .Case("armv7em", true) 2159 .Case("armv7k", true) 2160 .Case("armv7m", true) 2161 .Case("armv7s", true) 2162 .Case("arm64", true) 2163 .Case("ppc", true) 2164 .Case("ppc64", true) 2165 .Default(false); 2166 } 2167 2168 unsigned MachOObjectFile::getArch() const { 2169 return getArch(getCPUType(this)); 2170 } 2171 2172 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2173 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2174 } 2175 2176 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2177 DataRefImpl DRI; 2178 DRI.d.a = Index; 2179 return section_rel_begin(DRI); 2180 } 2181 2182 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2183 DataRefImpl DRI; 2184 DRI.d.a = Index; 2185 return section_rel_end(DRI); 2186 } 2187 2188 dice_iterator MachOObjectFile::begin_dices() const { 2189 DataRefImpl DRI; 2190 if (!DataInCodeLoadCmd) 2191 return dice_iterator(DiceRef(DRI, this)); 2192 2193 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2194 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 2195 return dice_iterator(DiceRef(DRI, this)); 2196 } 2197 2198 dice_iterator MachOObjectFile::end_dices() const { 2199 DataRefImpl DRI; 2200 if (!DataInCodeLoadCmd) 2201 return dice_iterator(DiceRef(DRI, this)); 2202 2203 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2204 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2205 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2206 return dice_iterator(DiceRef(DRI, this)); 2207 } 2208 2209 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 2210 : Trie(T), Malformed(false), Done(false) {} 2211 2212 void ExportEntry::moveToFirst() { 2213 pushNode(0); 2214 pushDownUntilBottom(); 2215 } 2216 2217 void ExportEntry::moveToEnd() { 2218 Stack.clear(); 2219 Done = true; 2220 } 2221 2222 bool ExportEntry::operator==(const ExportEntry &Other) const { 2223 // Common case, one at end, other iterating from begin. 2224 if (Done || Other.Done) 2225 return (Done == Other.Done); 2226 // Not equal if different stack sizes. 2227 if (Stack.size() != Other.Stack.size()) 2228 return false; 2229 // Not equal if different cumulative strings. 2230 if (!CumulativeString.equals(Other.CumulativeString)) 2231 return false; 2232 // Equal if all nodes in both stacks match. 2233 for (unsigned i=0; i < Stack.size(); ++i) { 2234 if (Stack[i].Start != Other.Stack[i].Start) 2235 return false; 2236 } 2237 return true; 2238 } 2239 2240 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 2241 unsigned Count; 2242 uint64_t Result = decodeULEB128(Ptr, &Count); 2243 Ptr += Count; 2244 if (Ptr > Trie.end()) { 2245 Ptr = Trie.end(); 2246 Malformed = true; 2247 } 2248 return Result; 2249 } 2250 2251 StringRef ExportEntry::name() const { 2252 return CumulativeString; 2253 } 2254 2255 uint64_t ExportEntry::flags() const { 2256 return Stack.back().Flags; 2257 } 2258 2259 uint64_t ExportEntry::address() const { 2260 return Stack.back().Address; 2261 } 2262 2263 uint64_t ExportEntry::other() const { 2264 return Stack.back().Other; 2265 } 2266 2267 StringRef ExportEntry::otherName() const { 2268 const char* ImportName = Stack.back().ImportName; 2269 if (ImportName) 2270 return StringRef(ImportName); 2271 return StringRef(); 2272 } 2273 2274 uint32_t ExportEntry::nodeOffset() const { 2275 return Stack.back().Start - Trie.begin(); 2276 } 2277 2278 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2279 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 2280 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 2281 ParentStringLength(0), IsExportNode(false) {} 2282 2283 void ExportEntry::pushNode(uint64_t offset) { 2284 const uint8_t *Ptr = Trie.begin() + offset; 2285 NodeState State(Ptr); 2286 uint64_t ExportInfoSize = readULEB128(State.Current); 2287 State.IsExportNode = (ExportInfoSize != 0); 2288 const uint8_t* Children = State.Current + ExportInfoSize; 2289 if (State.IsExportNode) { 2290 State.Flags = readULEB128(State.Current); 2291 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2292 State.Address = 0; 2293 State.Other = readULEB128(State.Current); // dylib ordinal 2294 State.ImportName = reinterpret_cast<const char*>(State.Current); 2295 } else { 2296 State.Address = readULEB128(State.Current); 2297 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 2298 State.Other = readULEB128(State.Current); 2299 } 2300 } 2301 State.ChildCount = *Children; 2302 State.Current = Children + 1; 2303 State.NextChildIndex = 0; 2304 State.ParentStringLength = CumulativeString.size(); 2305 Stack.push_back(State); 2306 } 2307 2308 void ExportEntry::pushDownUntilBottom() { 2309 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2310 NodeState &Top = Stack.back(); 2311 CumulativeString.resize(Top.ParentStringLength); 2312 for (;*Top.Current != 0; Top.Current++) { 2313 char C = *Top.Current; 2314 CumulativeString.push_back(C); 2315 } 2316 Top.Current += 1; 2317 uint64_t childNodeIndex = readULEB128(Top.Current); 2318 Top.NextChildIndex += 1; 2319 pushNode(childNodeIndex); 2320 } 2321 if (!Stack.back().IsExportNode) { 2322 Malformed = true; 2323 moveToEnd(); 2324 } 2325 } 2326 2327 // We have a trie data structure and need a way to walk it that is compatible 2328 // with the C++ iterator model. The solution is a non-recursive depth first 2329 // traversal where the iterator contains a stack of parent nodes along with a 2330 // string that is the accumulation of all edge strings along the parent chain 2331 // to this point. 2332 // 2333 // There is one "export" node for each exported symbol. But because some 2334 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2335 // node may have child nodes too. 2336 // 2337 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2338 // child until hitting a node with no children (which is an export node or 2339 // else the trie is malformed). On the way down, each node is pushed on the 2340 // stack ivar. If there is no more ways down, it pops up one and tries to go 2341 // down a sibling path until a childless node is reached. 2342 void ExportEntry::moveNext() { 2343 if (Stack.empty() || !Stack.back().IsExportNode) { 2344 Malformed = true; 2345 moveToEnd(); 2346 return; 2347 } 2348 2349 Stack.pop_back(); 2350 while (!Stack.empty()) { 2351 NodeState &Top = Stack.back(); 2352 if (Top.NextChildIndex < Top.ChildCount) { 2353 pushDownUntilBottom(); 2354 // Now at the next export node. 2355 return; 2356 } else { 2357 if (Top.IsExportNode) { 2358 // This node has no children but is itself an export node. 2359 CumulativeString.resize(Top.ParentStringLength); 2360 return; 2361 } 2362 Stack.pop_back(); 2363 } 2364 } 2365 Done = true; 2366 } 2367 2368 iterator_range<export_iterator> 2369 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 2370 ExportEntry Start(Trie); 2371 if (Trie.size() == 0) 2372 Start.moveToEnd(); 2373 else 2374 Start.moveToFirst(); 2375 2376 ExportEntry Finish(Trie); 2377 Finish.moveToEnd(); 2378 2379 return make_range(export_iterator(Start), export_iterator(Finish)); 2380 } 2381 2382 iterator_range<export_iterator> MachOObjectFile::exports() const { 2383 return exports(getDyldInfoExportsTrie()); 2384 } 2385 2386 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 2387 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2388 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 2389 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 2390 2391 void MachORebaseEntry::moveToFirst() { 2392 Ptr = Opcodes.begin(); 2393 moveNext(); 2394 } 2395 2396 void MachORebaseEntry::moveToEnd() { 2397 Ptr = Opcodes.end(); 2398 RemainingLoopCount = 0; 2399 Done = true; 2400 } 2401 2402 void MachORebaseEntry::moveNext() { 2403 // If in the middle of some loop, move to next rebasing in loop. 2404 SegmentOffset += AdvanceAmount; 2405 if (RemainingLoopCount) { 2406 --RemainingLoopCount; 2407 return; 2408 } 2409 if (Ptr == Opcodes.end()) { 2410 Done = true; 2411 return; 2412 } 2413 bool More = true; 2414 while (More && !Malformed) { 2415 // Parse next opcode and set up next loop. 2416 uint8_t Byte = *Ptr++; 2417 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2418 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2419 switch (Opcode) { 2420 case MachO::REBASE_OPCODE_DONE: 2421 More = false; 2422 Done = true; 2423 moveToEnd(); 2424 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 2425 break; 2426 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2427 RebaseType = ImmValue; 2428 DEBUG_WITH_TYPE( 2429 "mach-o-rebase", 2430 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2431 << "RebaseType=" << (int) RebaseType << "\n"); 2432 break; 2433 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2434 SegmentIndex = ImmValue; 2435 SegmentOffset = readULEB128(); 2436 DEBUG_WITH_TYPE( 2437 "mach-o-rebase", 2438 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2439 << "SegmentIndex=" << SegmentIndex << ", " 2440 << format("SegmentOffset=0x%06X", SegmentOffset) 2441 << "\n"); 2442 break; 2443 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 2444 SegmentOffset += readULEB128(); 2445 DEBUG_WITH_TYPE("mach-o-rebase", 2446 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 2447 << format("SegmentOffset=0x%06X", 2448 SegmentOffset) << "\n"); 2449 break; 2450 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 2451 SegmentOffset += ImmValue * PointerSize; 2452 DEBUG_WITH_TYPE("mach-o-rebase", 2453 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 2454 << format("SegmentOffset=0x%06X", 2455 SegmentOffset) << "\n"); 2456 break; 2457 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 2458 AdvanceAmount = PointerSize; 2459 RemainingLoopCount = ImmValue - 1; 2460 DEBUG_WITH_TYPE( 2461 "mach-o-rebase", 2462 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 2463 << format("SegmentOffset=0x%06X", SegmentOffset) 2464 << ", AdvanceAmount=" << AdvanceAmount 2465 << ", RemainingLoopCount=" << RemainingLoopCount 2466 << "\n"); 2467 return; 2468 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 2469 AdvanceAmount = PointerSize; 2470 RemainingLoopCount = readULEB128() - 1; 2471 DEBUG_WITH_TYPE( 2472 "mach-o-rebase", 2473 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 2474 << format("SegmentOffset=0x%06X", SegmentOffset) 2475 << ", AdvanceAmount=" << AdvanceAmount 2476 << ", RemainingLoopCount=" << RemainingLoopCount 2477 << "\n"); 2478 return; 2479 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2480 AdvanceAmount = readULEB128() + PointerSize; 2481 RemainingLoopCount = 0; 2482 DEBUG_WITH_TYPE( 2483 "mach-o-rebase", 2484 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2485 << format("SegmentOffset=0x%06X", SegmentOffset) 2486 << ", AdvanceAmount=" << AdvanceAmount 2487 << ", RemainingLoopCount=" << RemainingLoopCount 2488 << "\n"); 2489 return; 2490 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2491 RemainingLoopCount = readULEB128() - 1; 2492 AdvanceAmount = readULEB128() + PointerSize; 2493 DEBUG_WITH_TYPE( 2494 "mach-o-rebase", 2495 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2496 << format("SegmentOffset=0x%06X", SegmentOffset) 2497 << ", AdvanceAmount=" << AdvanceAmount 2498 << ", RemainingLoopCount=" << RemainingLoopCount 2499 << "\n"); 2500 return; 2501 default: 2502 Malformed = true; 2503 } 2504 } 2505 } 2506 2507 uint64_t MachORebaseEntry::readULEB128() { 2508 unsigned Count; 2509 uint64_t Result = decodeULEB128(Ptr, &Count); 2510 Ptr += Count; 2511 if (Ptr > Opcodes.end()) { 2512 Ptr = Opcodes.end(); 2513 Malformed = true; 2514 } 2515 return Result; 2516 } 2517 2518 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2519 2520 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2521 2522 StringRef MachORebaseEntry::typeName() const { 2523 switch (RebaseType) { 2524 case MachO::REBASE_TYPE_POINTER: 2525 return "pointer"; 2526 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2527 return "text abs32"; 2528 case MachO::REBASE_TYPE_TEXT_PCREL32: 2529 return "text rel32"; 2530 } 2531 return "unknown"; 2532 } 2533 2534 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2535 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2536 return (Ptr == Other.Ptr) && 2537 (RemainingLoopCount == Other.RemainingLoopCount) && 2538 (Done == Other.Done); 2539 } 2540 2541 iterator_range<rebase_iterator> 2542 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2543 MachORebaseEntry Start(Opcodes, is64); 2544 Start.moveToFirst(); 2545 2546 MachORebaseEntry Finish(Opcodes, is64); 2547 Finish.moveToEnd(); 2548 2549 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2550 } 2551 2552 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2553 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2554 } 2555 2556 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2557 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2558 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2559 BindType(0), PointerSize(is64Bit ? 8 : 4), 2560 TableKind(BK), Malformed(false), Done(false) {} 2561 2562 void MachOBindEntry::moveToFirst() { 2563 Ptr = Opcodes.begin(); 2564 moveNext(); 2565 } 2566 2567 void MachOBindEntry::moveToEnd() { 2568 Ptr = Opcodes.end(); 2569 RemainingLoopCount = 0; 2570 Done = true; 2571 } 2572 2573 void MachOBindEntry::moveNext() { 2574 // If in the middle of some loop, move to next binding in loop. 2575 SegmentOffset += AdvanceAmount; 2576 if (RemainingLoopCount) { 2577 --RemainingLoopCount; 2578 return; 2579 } 2580 if (Ptr == Opcodes.end()) { 2581 Done = true; 2582 return; 2583 } 2584 bool More = true; 2585 while (More && !Malformed) { 2586 // Parse next opcode and set up next loop. 2587 uint8_t Byte = *Ptr++; 2588 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2589 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2590 int8_t SignExtended; 2591 const uint8_t *SymStart; 2592 switch (Opcode) { 2593 case MachO::BIND_OPCODE_DONE: 2594 if (TableKind == Kind::Lazy) { 2595 // Lazying bindings have a DONE opcode between entries. Need to ignore 2596 // it to advance to next entry. But need not if this is last entry. 2597 bool NotLastEntry = false; 2598 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2599 if (*P) { 2600 NotLastEntry = true; 2601 } 2602 } 2603 if (NotLastEntry) 2604 break; 2605 } 2606 More = false; 2607 Done = true; 2608 moveToEnd(); 2609 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2610 break; 2611 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2612 Ordinal = ImmValue; 2613 DEBUG_WITH_TYPE( 2614 "mach-o-bind", 2615 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2616 << "Ordinal=" << Ordinal << "\n"); 2617 break; 2618 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2619 Ordinal = readULEB128(); 2620 DEBUG_WITH_TYPE( 2621 "mach-o-bind", 2622 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2623 << "Ordinal=" << Ordinal << "\n"); 2624 break; 2625 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2626 if (ImmValue) { 2627 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2628 Ordinal = SignExtended; 2629 } else 2630 Ordinal = 0; 2631 DEBUG_WITH_TYPE( 2632 "mach-o-bind", 2633 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2634 << "Ordinal=" << Ordinal << "\n"); 2635 break; 2636 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2637 Flags = ImmValue; 2638 SymStart = Ptr; 2639 while (*Ptr) { 2640 ++Ptr; 2641 } 2642 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2643 Ptr-SymStart); 2644 ++Ptr; 2645 DEBUG_WITH_TYPE( 2646 "mach-o-bind", 2647 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2648 << "SymbolName=" << SymbolName << "\n"); 2649 if (TableKind == Kind::Weak) { 2650 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2651 return; 2652 } 2653 break; 2654 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2655 BindType = ImmValue; 2656 DEBUG_WITH_TYPE( 2657 "mach-o-bind", 2658 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2659 << "BindType=" << (int)BindType << "\n"); 2660 break; 2661 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2662 Addend = readSLEB128(); 2663 if (TableKind == Kind::Lazy) 2664 Malformed = true; 2665 DEBUG_WITH_TYPE( 2666 "mach-o-bind", 2667 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2668 << "Addend=" << Addend << "\n"); 2669 break; 2670 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2671 SegmentIndex = ImmValue; 2672 SegmentOffset = readULEB128(); 2673 DEBUG_WITH_TYPE( 2674 "mach-o-bind", 2675 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2676 << "SegmentIndex=" << SegmentIndex << ", " 2677 << format("SegmentOffset=0x%06X", SegmentOffset) 2678 << "\n"); 2679 break; 2680 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2681 SegmentOffset += readULEB128(); 2682 DEBUG_WITH_TYPE("mach-o-bind", 2683 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2684 << format("SegmentOffset=0x%06X", 2685 SegmentOffset) << "\n"); 2686 break; 2687 case MachO::BIND_OPCODE_DO_BIND: 2688 AdvanceAmount = PointerSize; 2689 RemainingLoopCount = 0; 2690 DEBUG_WITH_TYPE("mach-o-bind", 2691 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2692 << format("SegmentOffset=0x%06X", 2693 SegmentOffset) << "\n"); 2694 return; 2695 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2696 AdvanceAmount = readULEB128() + PointerSize; 2697 RemainingLoopCount = 0; 2698 if (TableKind == Kind::Lazy) 2699 Malformed = true; 2700 DEBUG_WITH_TYPE( 2701 "mach-o-bind", 2702 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2703 << format("SegmentOffset=0x%06X", SegmentOffset) 2704 << ", AdvanceAmount=" << AdvanceAmount 2705 << ", RemainingLoopCount=" << RemainingLoopCount 2706 << "\n"); 2707 return; 2708 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2709 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2710 RemainingLoopCount = 0; 2711 if (TableKind == Kind::Lazy) 2712 Malformed = true; 2713 DEBUG_WITH_TYPE("mach-o-bind", 2714 llvm::dbgs() 2715 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2716 << format("SegmentOffset=0x%06X", 2717 SegmentOffset) << "\n"); 2718 return; 2719 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2720 RemainingLoopCount = readULEB128() - 1; 2721 AdvanceAmount = readULEB128() + PointerSize; 2722 if (TableKind == Kind::Lazy) 2723 Malformed = true; 2724 DEBUG_WITH_TYPE( 2725 "mach-o-bind", 2726 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2727 << format("SegmentOffset=0x%06X", SegmentOffset) 2728 << ", AdvanceAmount=" << AdvanceAmount 2729 << ", RemainingLoopCount=" << RemainingLoopCount 2730 << "\n"); 2731 return; 2732 default: 2733 Malformed = true; 2734 } 2735 } 2736 } 2737 2738 uint64_t MachOBindEntry::readULEB128() { 2739 unsigned Count; 2740 uint64_t Result = decodeULEB128(Ptr, &Count); 2741 Ptr += Count; 2742 if (Ptr > Opcodes.end()) { 2743 Ptr = Opcodes.end(); 2744 Malformed = true; 2745 } 2746 return Result; 2747 } 2748 2749 int64_t MachOBindEntry::readSLEB128() { 2750 unsigned Count; 2751 int64_t Result = decodeSLEB128(Ptr, &Count); 2752 Ptr += Count; 2753 if (Ptr > Opcodes.end()) { 2754 Ptr = Opcodes.end(); 2755 Malformed = true; 2756 } 2757 return Result; 2758 } 2759 2760 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 2761 2762 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 2763 2764 StringRef MachOBindEntry::typeName() const { 2765 switch (BindType) { 2766 case MachO::BIND_TYPE_POINTER: 2767 return "pointer"; 2768 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 2769 return "text abs32"; 2770 case MachO::BIND_TYPE_TEXT_PCREL32: 2771 return "text rel32"; 2772 } 2773 return "unknown"; 2774 } 2775 2776 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 2777 2778 int64_t MachOBindEntry::addend() const { return Addend; } 2779 2780 uint32_t MachOBindEntry::flags() const { return Flags; } 2781 2782 int MachOBindEntry::ordinal() const { return Ordinal; } 2783 2784 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 2785 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2786 return (Ptr == Other.Ptr) && 2787 (RemainingLoopCount == Other.RemainingLoopCount) && 2788 (Done == Other.Done); 2789 } 2790 2791 iterator_range<bind_iterator> 2792 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 2793 MachOBindEntry::Kind BKind) { 2794 MachOBindEntry Start(Opcodes, is64, BKind); 2795 Start.moveToFirst(); 2796 2797 MachOBindEntry Finish(Opcodes, is64, BKind); 2798 Finish.moveToEnd(); 2799 2800 return make_range(bind_iterator(Start), bind_iterator(Finish)); 2801 } 2802 2803 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 2804 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 2805 MachOBindEntry::Kind::Regular); 2806 } 2807 2808 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 2809 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 2810 MachOBindEntry::Kind::Lazy); 2811 } 2812 2813 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 2814 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 2815 MachOBindEntry::Kind::Weak); 2816 } 2817 2818 MachOObjectFile::load_command_iterator 2819 MachOObjectFile::begin_load_commands() const { 2820 return LoadCommands.begin(); 2821 } 2822 2823 MachOObjectFile::load_command_iterator 2824 MachOObjectFile::end_load_commands() const { 2825 return LoadCommands.end(); 2826 } 2827 2828 iterator_range<MachOObjectFile::load_command_iterator> 2829 MachOObjectFile::load_commands() const { 2830 return make_range(begin_load_commands(), end_load_commands()); 2831 } 2832 2833 StringRef 2834 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 2835 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 2836 return parseSegmentOrSectionName(Raw.data()); 2837 } 2838 2839 ArrayRef<char> 2840 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 2841 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2842 const section_base *Base = 2843 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2844 return makeArrayRef(Base->sectname); 2845 } 2846 2847 ArrayRef<char> 2848 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 2849 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2850 const section_base *Base = 2851 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2852 return makeArrayRef(Base->segname); 2853 } 2854 2855 bool 2856 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 2857 const { 2858 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 2859 return false; 2860 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 2861 } 2862 2863 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 2864 const MachO::any_relocation_info &RE) const { 2865 if (isLittleEndian()) 2866 return RE.r_word1 & 0xffffff; 2867 return RE.r_word1 >> 8; 2868 } 2869 2870 bool MachOObjectFile::getPlainRelocationExternal( 2871 const MachO::any_relocation_info &RE) const { 2872 if (isLittleEndian()) 2873 return (RE.r_word1 >> 27) & 1; 2874 return (RE.r_word1 >> 4) & 1; 2875 } 2876 2877 bool MachOObjectFile::getScatteredRelocationScattered( 2878 const MachO::any_relocation_info &RE) const { 2879 return RE.r_word0 >> 31; 2880 } 2881 2882 uint32_t MachOObjectFile::getScatteredRelocationValue( 2883 const MachO::any_relocation_info &RE) const { 2884 return RE.r_word1; 2885 } 2886 2887 uint32_t MachOObjectFile::getScatteredRelocationType( 2888 const MachO::any_relocation_info &RE) const { 2889 return (RE.r_word0 >> 24) & 0xf; 2890 } 2891 2892 unsigned MachOObjectFile::getAnyRelocationAddress( 2893 const MachO::any_relocation_info &RE) const { 2894 if (isRelocationScattered(RE)) 2895 return getScatteredRelocationAddress(RE); 2896 return getPlainRelocationAddress(RE); 2897 } 2898 2899 unsigned MachOObjectFile::getAnyRelocationPCRel( 2900 const MachO::any_relocation_info &RE) const { 2901 if (isRelocationScattered(RE)) 2902 return getScatteredRelocationPCRel(this, RE); 2903 return getPlainRelocationPCRel(this, RE); 2904 } 2905 2906 unsigned MachOObjectFile::getAnyRelocationLength( 2907 const MachO::any_relocation_info &RE) const { 2908 if (isRelocationScattered(RE)) 2909 return getScatteredRelocationLength(RE); 2910 return getPlainRelocationLength(this, RE); 2911 } 2912 2913 unsigned 2914 MachOObjectFile::getAnyRelocationType( 2915 const MachO::any_relocation_info &RE) const { 2916 if (isRelocationScattered(RE)) 2917 return getScatteredRelocationType(RE); 2918 return getPlainRelocationType(this, RE); 2919 } 2920 2921 SectionRef 2922 MachOObjectFile::getAnyRelocationSection( 2923 const MachO::any_relocation_info &RE) const { 2924 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 2925 return *section_end(); 2926 unsigned SecNum = getPlainRelocationSymbolNum(RE); 2927 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 2928 return *section_end(); 2929 DataRefImpl DRI; 2930 DRI.d.a = SecNum - 1; 2931 return SectionRef(DRI, this); 2932 } 2933 2934 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 2935 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 2936 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 2937 } 2938 2939 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 2940 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 2941 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 2942 } 2943 2944 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 2945 unsigned Index) const { 2946 const char *Sec = getSectionPtr(this, L, Index); 2947 return getStruct<MachO::section>(this, Sec); 2948 } 2949 2950 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 2951 unsigned Index) const { 2952 const char *Sec = getSectionPtr(this, L, Index); 2953 return getStruct<MachO::section_64>(this, Sec); 2954 } 2955 2956 MachO::nlist 2957 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 2958 const char *P = reinterpret_cast<const char *>(DRI.p); 2959 return getStruct<MachO::nlist>(this, P); 2960 } 2961 2962 MachO::nlist_64 2963 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 2964 const char *P = reinterpret_cast<const char *>(DRI.p); 2965 return getStruct<MachO::nlist_64>(this, P); 2966 } 2967 2968 MachO::linkedit_data_command 2969 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 2970 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 2971 } 2972 2973 MachO::segment_command 2974 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 2975 return getStruct<MachO::segment_command>(this, L.Ptr); 2976 } 2977 2978 MachO::segment_command_64 2979 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 2980 return getStruct<MachO::segment_command_64>(this, L.Ptr); 2981 } 2982 2983 MachO::linker_option_command 2984 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 2985 return getStruct<MachO::linker_option_command>(this, L.Ptr); 2986 } 2987 2988 MachO::version_min_command 2989 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 2990 return getStruct<MachO::version_min_command>(this, L.Ptr); 2991 } 2992 2993 MachO::dylib_command 2994 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 2995 return getStruct<MachO::dylib_command>(this, L.Ptr); 2996 } 2997 2998 MachO::dyld_info_command 2999 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 3000 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 3001 } 3002 3003 MachO::dylinker_command 3004 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 3005 return getStruct<MachO::dylinker_command>(this, L.Ptr); 3006 } 3007 3008 MachO::uuid_command 3009 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 3010 return getStruct<MachO::uuid_command>(this, L.Ptr); 3011 } 3012 3013 MachO::rpath_command 3014 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 3015 return getStruct<MachO::rpath_command>(this, L.Ptr); 3016 } 3017 3018 MachO::source_version_command 3019 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 3020 return getStruct<MachO::source_version_command>(this, L.Ptr); 3021 } 3022 3023 MachO::entry_point_command 3024 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 3025 return getStruct<MachO::entry_point_command>(this, L.Ptr); 3026 } 3027 3028 MachO::encryption_info_command 3029 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 3030 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 3031 } 3032 3033 MachO::encryption_info_command_64 3034 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 3035 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 3036 } 3037 3038 MachO::sub_framework_command 3039 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 3040 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 3041 } 3042 3043 MachO::sub_umbrella_command 3044 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 3045 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 3046 } 3047 3048 MachO::sub_library_command 3049 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 3050 return getStruct<MachO::sub_library_command>(this, L.Ptr); 3051 } 3052 3053 MachO::sub_client_command 3054 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 3055 return getStruct<MachO::sub_client_command>(this, L.Ptr); 3056 } 3057 3058 MachO::routines_command 3059 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 3060 return getStruct<MachO::routines_command>(this, L.Ptr); 3061 } 3062 3063 MachO::routines_command_64 3064 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 3065 return getStruct<MachO::routines_command_64>(this, L.Ptr); 3066 } 3067 3068 MachO::thread_command 3069 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 3070 return getStruct<MachO::thread_command>(this, L.Ptr); 3071 } 3072 3073 MachO::any_relocation_info 3074 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 3075 DataRefImpl Sec; 3076 Sec.d.a = Rel.d.a; 3077 uint32_t Offset; 3078 if (is64Bit()) { 3079 MachO::section_64 Sect = getSection64(Sec); 3080 Offset = Sect.reloff; 3081 } else { 3082 MachO::section Sect = getSection(Sec); 3083 Offset = Sect.reloff; 3084 } 3085 3086 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 3087 getPtr(this, Offset)) + Rel.d.b; 3088 return getStruct<MachO::any_relocation_info>( 3089 this, reinterpret_cast<const char *>(P)); 3090 } 3091 3092 MachO::data_in_code_entry 3093 MachOObjectFile::getDice(DataRefImpl Rel) const { 3094 const char *P = reinterpret_cast<const char *>(Rel.p); 3095 return getStruct<MachO::data_in_code_entry>(this, P); 3096 } 3097 3098 const MachO::mach_header &MachOObjectFile::getHeader() const { 3099 return Header; 3100 } 3101 3102 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 3103 assert(is64Bit()); 3104 return Header64; 3105 } 3106 3107 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 3108 const MachO::dysymtab_command &DLC, 3109 unsigned Index) const { 3110 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 3111 return getStruct<uint32_t>(this, getPtr(this, Offset)); 3112 } 3113 3114 MachO::data_in_code_entry 3115 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 3116 unsigned Index) const { 3117 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 3118 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 3119 } 3120 3121 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 3122 if (SymtabLoadCmd) 3123 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 3124 3125 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 3126 MachO::symtab_command Cmd; 3127 Cmd.cmd = MachO::LC_SYMTAB; 3128 Cmd.cmdsize = sizeof(MachO::symtab_command); 3129 Cmd.symoff = 0; 3130 Cmd.nsyms = 0; 3131 Cmd.stroff = 0; 3132 Cmd.strsize = 0; 3133 return Cmd; 3134 } 3135 3136 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 3137 if (DysymtabLoadCmd) 3138 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 3139 3140 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 3141 MachO::dysymtab_command Cmd; 3142 Cmd.cmd = MachO::LC_DYSYMTAB; 3143 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 3144 Cmd.ilocalsym = 0; 3145 Cmd.nlocalsym = 0; 3146 Cmd.iextdefsym = 0; 3147 Cmd.nextdefsym = 0; 3148 Cmd.iundefsym = 0; 3149 Cmd.nundefsym = 0; 3150 Cmd.tocoff = 0; 3151 Cmd.ntoc = 0; 3152 Cmd.modtaboff = 0; 3153 Cmd.nmodtab = 0; 3154 Cmd.extrefsymoff = 0; 3155 Cmd.nextrefsyms = 0; 3156 Cmd.indirectsymoff = 0; 3157 Cmd.nindirectsyms = 0; 3158 Cmd.extreloff = 0; 3159 Cmd.nextrel = 0; 3160 Cmd.locreloff = 0; 3161 Cmd.nlocrel = 0; 3162 return Cmd; 3163 } 3164 3165 MachO::linkedit_data_command 3166 MachOObjectFile::getDataInCodeLoadCommand() const { 3167 if (DataInCodeLoadCmd) 3168 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 3169 3170 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 3171 MachO::linkedit_data_command Cmd; 3172 Cmd.cmd = MachO::LC_DATA_IN_CODE; 3173 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3174 Cmd.dataoff = 0; 3175 Cmd.datasize = 0; 3176 return Cmd; 3177 } 3178 3179 MachO::linkedit_data_command 3180 MachOObjectFile::getLinkOptHintsLoadCommand() const { 3181 if (LinkOptHintsLoadCmd) 3182 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 3183 3184 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 3185 // fields. 3186 MachO::linkedit_data_command Cmd; 3187 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 3188 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3189 Cmd.dataoff = 0; 3190 Cmd.datasize = 0; 3191 return Cmd; 3192 } 3193 3194 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 3195 if (!DyldInfoLoadCmd) 3196 return None; 3197 3198 MachO::dyld_info_command DyldInfo = 3199 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3200 const uint8_t *Ptr = 3201 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 3202 return makeArrayRef(Ptr, DyldInfo.rebase_size); 3203 } 3204 3205 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 3206 if (!DyldInfoLoadCmd) 3207 return None; 3208 3209 MachO::dyld_info_command DyldInfo = 3210 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3211 const uint8_t *Ptr = 3212 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 3213 return makeArrayRef(Ptr, DyldInfo.bind_size); 3214 } 3215 3216 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 3217 if (!DyldInfoLoadCmd) 3218 return None; 3219 3220 MachO::dyld_info_command DyldInfo = 3221 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3222 const uint8_t *Ptr = 3223 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 3224 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 3225 } 3226 3227 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 3228 if (!DyldInfoLoadCmd) 3229 return None; 3230 3231 MachO::dyld_info_command DyldInfo = 3232 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3233 const uint8_t *Ptr = 3234 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 3235 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 3236 } 3237 3238 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 3239 if (!DyldInfoLoadCmd) 3240 return None; 3241 3242 MachO::dyld_info_command DyldInfo = 3243 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3244 const uint8_t *Ptr = 3245 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 3246 return makeArrayRef(Ptr, DyldInfo.export_size); 3247 } 3248 3249 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 3250 if (!UuidLoadCmd) 3251 return None; 3252 // Returning a pointer is fine as uuid doesn't need endian swapping. 3253 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 3254 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 3255 } 3256 3257 StringRef MachOObjectFile::getStringTableData() const { 3258 MachO::symtab_command S = getSymtabLoadCommand(); 3259 return getData().substr(S.stroff, S.strsize); 3260 } 3261 3262 bool MachOObjectFile::is64Bit() const { 3263 return getType() == getMachOType(false, true) || 3264 getType() == getMachOType(true, true); 3265 } 3266 3267 void MachOObjectFile::ReadULEB128s(uint64_t Index, 3268 SmallVectorImpl<uint64_t> &Out) const { 3269 DataExtractor extractor(ObjectFile::getData(), true, 0); 3270 3271 uint32_t offset = Index; 3272 uint64_t data = 0; 3273 while (uint64_t delta = extractor.getULEB128(&offset)) { 3274 data += delta; 3275 Out.push_back(data); 3276 } 3277 } 3278 3279 bool MachOObjectFile::isRelocatableObject() const { 3280 return getHeader().filetype == MachO::MH_OBJECT; 3281 } 3282 3283 Expected<std::unique_ptr<MachOObjectFile>> 3284 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 3285 StringRef Magic = Buffer.getBuffer().slice(0, 4); 3286 if (Magic == "\xFE\xED\xFA\xCE") 3287 return MachOObjectFile::create(Buffer, false, false); 3288 if (Magic == "\xCE\xFA\xED\xFE") 3289 return MachOObjectFile::create(Buffer, true, false); 3290 if (Magic == "\xFE\xED\xFA\xCF") 3291 return MachOObjectFile::create(Buffer, false, true); 3292 if (Magic == "\xCF\xFA\xED\xFE") 3293 return MachOObjectFile::create(Buffer, true, true); 3294 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 3295 object_error::invalid_file_type); 3296 } 3297