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