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