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 Expected<std::unique_ptr<MachOObjectFile>> 629 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, 630 bool Is64Bits) { 631 Error Err; 632 std::unique_ptr<MachOObjectFile> Obj( 633 new MachOObjectFile(std::move(Object), IsLittleEndian, 634 Is64Bits, Err)); 635 if (Err) 636 return std::move(Err); 637 return std::move(Obj); 638 } 639 640 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 641 bool Is64bits, Error &Err) 642 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 643 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 644 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 645 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 646 HasPageZeroSegment(false) { 647 ErrorAsOutParameter ErrAsOutParam(&Err); 648 uint64_t SizeOfHeaders; 649 if (is64Bit()) { 650 parseHeader(this, Header64, Err); 651 SizeOfHeaders = sizeof(MachO::mach_header_64); 652 } else { 653 parseHeader(this, Header, Err); 654 SizeOfHeaders = sizeof(MachO::mach_header); 655 } 656 if (Err) 657 return; 658 SizeOfHeaders += getHeader().sizeofcmds; 659 if (getData().data() + SizeOfHeaders > getData().end()) { 660 Err = malformedError("load commands extend past the end of the file"); 661 return; 662 } 663 664 uint32_t LoadCommandCount = getHeader().ncmds; 665 LoadCommandInfo Load; 666 if (LoadCommandCount != 0) { 667 if (auto LoadOrErr = getFirstLoadCommandInfo(this)) 668 Load = *LoadOrErr; 669 else { 670 Err = LoadOrErr.takeError(); 671 return; 672 } 673 } 674 675 const char *DyldIdLoadCmd = nullptr; 676 for (unsigned I = 0; I < LoadCommandCount; ++I) { 677 if (is64Bit()) { 678 if (Load.C.cmdsize % 8 != 0) { 679 // We have a hack here to allow 64-bit Mach-O core files to have 680 // LC_THREAD commands that are only a multiple of 4 and not 8 to be 681 // allowed since the macOS kernel produces them. 682 if (getHeader().filetype != MachO::MH_CORE || 683 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { 684 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 685 "multiple of 8"); 686 return; 687 } 688 } 689 } else { 690 if (Load.C.cmdsize % 4 != 0) { 691 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 692 "multiple of 4"); 693 return; 694 } 695 } 696 LoadCommands.push_back(Load); 697 if (Load.C.cmd == MachO::LC_SYMTAB) { 698 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd))) 699 return; 700 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 701 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd))) 702 return; 703 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 704 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd, 705 "LC_DATA_IN_CODE"))) 706 return; 707 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 708 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, 709 "LC_LINKER_OPTIMIZATION_HINT"))) 710 return; 711 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { 712 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 713 "LC_DYLD_INFO"))) 714 return; 715 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 716 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 717 "LC_DYLD_INFO_ONLY"))) 718 return; 719 } else if (Load.C.cmd == MachO::LC_UUID) { 720 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { 721 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " 722 "cmdsize"); 723 return; 724 } 725 if (UuidLoadCmd) { 726 Err = malformedError("more than one LC_UUID command"); 727 return; 728 } 729 UuidLoadCmd = Load.Ptr; 730 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 731 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64, 732 MachO::section_64>( 733 this, Load, Sections, HasPageZeroSegment, I, 734 "LC_SEGMENT_64", SizeOfHeaders))) 735 return; 736 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 737 if ((Err = parseSegmentLoadCommand<MachO::segment_command, 738 MachO::section>( 739 this, Load, Sections, HasPageZeroSegment, I, 740 "LC_SEGMENT", SizeOfHeaders))) 741 return; 742 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) { 743 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd))) 744 return; 745 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) { 746 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB"))) 747 return; 748 Libraries.push_back(Load.Ptr); 749 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) { 750 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB"))) 751 return; 752 Libraries.push_back(Load.Ptr); 753 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) { 754 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB"))) 755 return; 756 Libraries.push_back(Load.Ptr); 757 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) { 758 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB"))) 759 return; 760 Libraries.push_back(Load.Ptr); 761 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 762 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB"))) 763 return; 764 Libraries.push_back(Load.Ptr); 765 } 766 if (I < LoadCommandCount - 1) { 767 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) 768 Load = *LoadOrErr; 769 else { 770 Err = LoadOrErr.takeError(); 771 return; 772 } 773 } 774 } 775 if (!SymtabLoadCmd) { 776 if (DysymtabLoadCmd) { 777 Err = malformedError("contains LC_DYSYMTAB load command without a " 778 "LC_SYMTAB load command"); 779 return; 780 } 781 } else if (DysymtabLoadCmd) { 782 MachO::symtab_command Symtab = 783 getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 784 MachO::dysymtab_command Dysymtab = 785 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 786 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 787 Err = malformedError("ilocalsym in LC_DYSYMTAB load command " 788 "extends past the end of the symbol table"); 789 return; 790 } 791 uint64_t BigSize = Dysymtab.ilocalsym; 792 BigSize += Dysymtab.nlocalsym; 793 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { 794 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " 795 "command extends past the end of the symbol table"); 796 return; 797 } 798 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 799 Err = malformedError("nextdefsym in LC_DYSYMTAB load command " 800 "extends past the end of the symbol table"); 801 return; 802 } 803 BigSize = Dysymtab.iextdefsym; 804 BigSize += Dysymtab.nextdefsym; 805 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { 806 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " 807 "load command extends past the end of the symbol " 808 "table"); 809 return; 810 } 811 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { 812 Err = malformedError("nundefsym in LC_DYSYMTAB load command " 813 "extends past the end of the symbol table"); 814 return; 815 } 816 BigSize = Dysymtab.iundefsym; 817 BigSize += Dysymtab.nundefsym; 818 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { 819 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " 820 " command extends past the end of the symbol table"); 821 return; 822 } 823 } 824 if ((getHeader().filetype == MachO::MH_DYLIB || 825 getHeader().filetype == MachO::MH_DYLIB_STUB) && 826 DyldIdLoadCmd == nullptr) { 827 Err = malformedError("no LC_ID_DYLIB load command in dynamic library " 828 "filetype"); 829 return; 830 } 831 assert(LoadCommands.size() == LoadCommandCount); 832 833 Err = Error::success(); 834 } 835 836 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 837 unsigned SymbolTableEntrySize = is64Bit() ? 838 sizeof(MachO::nlist_64) : 839 sizeof(MachO::nlist); 840 Symb.p += SymbolTableEntrySize; 841 } 842 843 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 844 StringRef StringTable = getStringTableData(); 845 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 846 const char *Start = &StringTable.data()[Entry.n_strx]; 847 if (Start < getData().begin() || Start >= getData().end()) { 848 return malformedError("bad string index: " + Twine(Entry.n_strx) + 849 " for symbol at index " + Twine(getSymbolIndex(Symb))); 850 } 851 return StringRef(Start); 852 } 853 854 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 855 DataRefImpl DRI = Sec.getRawDataRefImpl(); 856 uint32_t Flags = getSectionFlags(this, DRI); 857 return Flags & MachO::SECTION_TYPE; 858 } 859 860 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 861 if (is64Bit()) { 862 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 863 return Entry.n_value; 864 } 865 MachO::nlist Entry = getSymbolTableEntry(Sym); 866 return Entry.n_value; 867 } 868 869 // getIndirectName() returns the name of the alias'ed symbol who's string table 870 // index is in the n_value field. 871 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 872 StringRef &Res) const { 873 StringRef StringTable = getStringTableData(); 874 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 875 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 876 return object_error::parse_failed; 877 uint64_t NValue = getNValue(Symb); 878 if (NValue >= StringTable.size()) 879 return object_error::parse_failed; 880 const char *Start = &StringTable.data()[NValue]; 881 Res = StringRef(Start); 882 return std::error_code(); 883 } 884 885 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { 886 return getNValue(Sym); 887 } 888 889 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { 890 return getSymbolValue(Sym); 891 } 892 893 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 894 uint32_t flags = getSymbolFlags(DRI); 895 if (flags & SymbolRef::SF_Common) { 896 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 897 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 898 } 899 return 0; 900 } 901 902 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 903 return getNValue(DRI); 904 } 905 906 Expected<SymbolRef::Type> 907 MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 908 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 909 uint8_t n_type = Entry.n_type; 910 911 // If this is a STAB debugging symbol, we can do nothing more. 912 if (n_type & MachO::N_STAB) 913 return SymbolRef::ST_Debug; 914 915 switch (n_type & MachO::N_TYPE) { 916 case MachO::N_UNDF : 917 return SymbolRef::ST_Unknown; 918 case MachO::N_SECT : 919 Expected<section_iterator> SecOrError = getSymbolSection(Symb); 920 if (!SecOrError) 921 return SecOrError.takeError(); 922 section_iterator Sec = *SecOrError; 923 if (Sec->isData() || Sec->isBSS()) 924 return SymbolRef::ST_Data; 925 return SymbolRef::ST_Function; 926 } 927 return SymbolRef::ST_Other; 928 } 929 930 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 931 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 932 933 uint8_t MachOType = Entry.n_type; 934 uint16_t MachOFlags = Entry.n_desc; 935 936 uint32_t Result = SymbolRef::SF_None; 937 938 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 939 Result |= SymbolRef::SF_Indirect; 940 941 if (MachOType & MachO::N_STAB) 942 Result |= SymbolRef::SF_FormatSpecific; 943 944 if (MachOType & MachO::N_EXT) { 945 Result |= SymbolRef::SF_Global; 946 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 947 if (getNValue(DRI)) 948 Result |= SymbolRef::SF_Common; 949 else 950 Result |= SymbolRef::SF_Undefined; 951 } 952 953 if (!(MachOType & MachO::N_PEXT)) 954 Result |= SymbolRef::SF_Exported; 955 } 956 957 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 958 Result |= SymbolRef::SF_Weak; 959 960 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 961 Result |= SymbolRef::SF_Thumb; 962 963 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 964 Result |= SymbolRef::SF_Absolute; 965 966 return Result; 967 } 968 969 Expected<section_iterator> 970 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { 971 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 972 uint8_t index = Entry.n_sect; 973 974 if (index == 0) 975 return section_end(); 976 DataRefImpl DRI; 977 DRI.d.a = index - 1; 978 if (DRI.d.a >= Sections.size()){ 979 return malformedError("bad section index: " + Twine((int)index) + 980 " for symbol at index " + Twine(getSymbolIndex(Symb))); 981 } 982 return section_iterator(SectionRef(DRI, this)); 983 } 984 985 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 986 MachO::nlist_base Entry = 987 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 988 return Entry.n_sect - 1; 989 } 990 991 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 992 Sec.d.a++; 993 } 994 995 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 996 StringRef &Result) const { 997 ArrayRef<char> Raw = getSectionRawName(Sec); 998 Result = parseSegmentOrSectionName(Raw.data()); 999 return std::error_code(); 1000 } 1001 1002 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 1003 if (is64Bit()) 1004 return getSection64(Sec).addr; 1005 return getSection(Sec).addr; 1006 } 1007 1008 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 1009 // In the case if a malformed Mach-O file where the section offset is past 1010 // the end of the file or some part of the section size is past the end of 1011 // the file return a size of zero or a size that covers the rest of the file 1012 // but does not extend past the end of the file. 1013 uint32_t SectOffset, SectType; 1014 uint64_t SectSize; 1015 1016 if (is64Bit()) { 1017 MachO::section_64 Sect = getSection64(Sec); 1018 SectOffset = Sect.offset; 1019 SectSize = Sect.size; 1020 SectType = Sect.flags & MachO::SECTION_TYPE; 1021 } else { 1022 MachO::section Sect = getSection(Sec); 1023 SectOffset = Sect.offset; 1024 SectSize = Sect.size; 1025 SectType = Sect.flags & MachO::SECTION_TYPE; 1026 } 1027 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL) 1028 return SectSize; 1029 uint64_t FileSize = getData().size(); 1030 if (SectOffset > FileSize) 1031 return 0; 1032 if (FileSize - SectOffset < SectSize) 1033 return FileSize - SectOffset; 1034 return SectSize; 1035 } 1036 1037 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 1038 StringRef &Res) const { 1039 uint32_t Offset; 1040 uint64_t Size; 1041 1042 if (is64Bit()) { 1043 MachO::section_64 Sect = getSection64(Sec); 1044 Offset = Sect.offset; 1045 Size = Sect.size; 1046 } else { 1047 MachO::section Sect = getSection(Sec); 1048 Offset = Sect.offset; 1049 Size = Sect.size; 1050 } 1051 1052 Res = this->getData().substr(Offset, Size); 1053 return std::error_code(); 1054 } 1055 1056 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1057 uint32_t Align; 1058 if (is64Bit()) { 1059 MachO::section_64 Sect = getSection64(Sec); 1060 Align = Sect.align; 1061 } else { 1062 MachO::section Sect = getSection(Sec); 1063 Align = Sect.align; 1064 } 1065 1066 return uint64_t(1) << Align; 1067 } 1068 1069 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1070 return false; 1071 } 1072 1073 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 1074 uint32_t Flags = getSectionFlags(this, Sec); 1075 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 1076 } 1077 1078 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 1079 uint32_t Flags = getSectionFlags(this, Sec); 1080 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1081 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1082 !(SectionType == MachO::S_ZEROFILL || 1083 SectionType == MachO::S_GB_ZEROFILL); 1084 } 1085 1086 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 1087 uint32_t Flags = getSectionFlags(this, Sec); 1088 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1089 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1090 (SectionType == MachO::S_ZEROFILL || 1091 SectionType == MachO::S_GB_ZEROFILL); 1092 } 1093 1094 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 1095 return Sec.getRawDataRefImpl().d.a; 1096 } 1097 1098 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 1099 // FIXME: Unimplemented. 1100 return false; 1101 } 1102 1103 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { 1104 StringRef SegmentName = getSectionFinalSegmentName(Sec); 1105 StringRef SectName; 1106 if (!getSectionName(Sec, SectName)) 1107 return (SegmentName == "__LLVM" && SectName == "__bitcode"); 1108 return false; 1109 } 1110 1111 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1112 DataRefImpl Ret; 1113 Ret.d.a = Sec.d.a; 1114 Ret.d.b = 0; 1115 return relocation_iterator(RelocationRef(Ret, this)); 1116 } 1117 1118 relocation_iterator 1119 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1120 uint32_t Num; 1121 if (is64Bit()) { 1122 MachO::section_64 Sect = getSection64(Sec); 1123 Num = Sect.nreloc; 1124 } else { 1125 MachO::section Sect = getSection(Sec); 1126 Num = Sect.nreloc; 1127 } 1128 1129 DataRefImpl Ret; 1130 Ret.d.a = Sec.d.a; 1131 Ret.d.b = Num; 1132 return relocation_iterator(RelocationRef(Ret, this)); 1133 } 1134 1135 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1136 ++Rel.d.b; 1137 } 1138 1139 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1140 assert(getHeader().filetype == MachO::MH_OBJECT && 1141 "Only implemented for MH_OBJECT"); 1142 MachO::any_relocation_info RE = getRelocation(Rel); 1143 return getAnyRelocationAddress(RE); 1144 } 1145 1146 symbol_iterator 1147 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1148 MachO::any_relocation_info RE = getRelocation(Rel); 1149 if (isRelocationScattered(RE)) 1150 return symbol_end(); 1151 1152 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1153 bool isExtern = getPlainRelocationExternal(RE); 1154 if (!isExtern) 1155 return symbol_end(); 1156 1157 MachO::symtab_command S = getSymtabLoadCommand(); 1158 unsigned SymbolTableEntrySize = is64Bit() ? 1159 sizeof(MachO::nlist_64) : 1160 sizeof(MachO::nlist); 1161 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1162 DataRefImpl Sym; 1163 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1164 return symbol_iterator(SymbolRef(Sym, this)); 1165 } 1166 1167 section_iterator 1168 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 1169 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 1170 } 1171 1172 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 1173 MachO::any_relocation_info RE = getRelocation(Rel); 1174 return getAnyRelocationType(RE); 1175 } 1176 1177 void MachOObjectFile::getRelocationTypeName( 1178 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1179 StringRef res; 1180 uint64_t RType = getRelocationType(Rel); 1181 1182 unsigned Arch = this->getArch(); 1183 1184 switch (Arch) { 1185 case Triple::x86: { 1186 static const char *const Table[] = { 1187 "GENERIC_RELOC_VANILLA", 1188 "GENERIC_RELOC_PAIR", 1189 "GENERIC_RELOC_SECTDIFF", 1190 "GENERIC_RELOC_PB_LA_PTR", 1191 "GENERIC_RELOC_LOCAL_SECTDIFF", 1192 "GENERIC_RELOC_TLV" }; 1193 1194 if (RType > 5) 1195 res = "Unknown"; 1196 else 1197 res = Table[RType]; 1198 break; 1199 } 1200 case Triple::x86_64: { 1201 static const char *const Table[] = { 1202 "X86_64_RELOC_UNSIGNED", 1203 "X86_64_RELOC_SIGNED", 1204 "X86_64_RELOC_BRANCH", 1205 "X86_64_RELOC_GOT_LOAD", 1206 "X86_64_RELOC_GOT", 1207 "X86_64_RELOC_SUBTRACTOR", 1208 "X86_64_RELOC_SIGNED_1", 1209 "X86_64_RELOC_SIGNED_2", 1210 "X86_64_RELOC_SIGNED_4", 1211 "X86_64_RELOC_TLV" }; 1212 1213 if (RType > 9) 1214 res = "Unknown"; 1215 else 1216 res = Table[RType]; 1217 break; 1218 } 1219 case Triple::arm: { 1220 static const char *const Table[] = { 1221 "ARM_RELOC_VANILLA", 1222 "ARM_RELOC_PAIR", 1223 "ARM_RELOC_SECTDIFF", 1224 "ARM_RELOC_LOCAL_SECTDIFF", 1225 "ARM_RELOC_PB_LA_PTR", 1226 "ARM_RELOC_BR24", 1227 "ARM_THUMB_RELOC_BR22", 1228 "ARM_THUMB_32BIT_BRANCH", 1229 "ARM_RELOC_HALF", 1230 "ARM_RELOC_HALF_SECTDIFF" }; 1231 1232 if (RType > 9) 1233 res = "Unknown"; 1234 else 1235 res = Table[RType]; 1236 break; 1237 } 1238 case Triple::aarch64: { 1239 static const char *const Table[] = { 1240 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 1241 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 1242 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 1243 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 1244 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 1245 "ARM64_RELOC_ADDEND" 1246 }; 1247 1248 if (RType >= array_lengthof(Table)) 1249 res = "Unknown"; 1250 else 1251 res = Table[RType]; 1252 break; 1253 } 1254 case Triple::ppc: { 1255 static const char *const Table[] = { 1256 "PPC_RELOC_VANILLA", 1257 "PPC_RELOC_PAIR", 1258 "PPC_RELOC_BR14", 1259 "PPC_RELOC_BR24", 1260 "PPC_RELOC_HI16", 1261 "PPC_RELOC_LO16", 1262 "PPC_RELOC_HA16", 1263 "PPC_RELOC_LO14", 1264 "PPC_RELOC_SECTDIFF", 1265 "PPC_RELOC_PB_LA_PTR", 1266 "PPC_RELOC_HI16_SECTDIFF", 1267 "PPC_RELOC_LO16_SECTDIFF", 1268 "PPC_RELOC_HA16_SECTDIFF", 1269 "PPC_RELOC_JBSR", 1270 "PPC_RELOC_LO14_SECTDIFF", 1271 "PPC_RELOC_LOCAL_SECTDIFF" }; 1272 1273 if (RType > 15) 1274 res = "Unknown"; 1275 else 1276 res = Table[RType]; 1277 break; 1278 } 1279 case Triple::UnknownArch: 1280 res = "Unknown"; 1281 break; 1282 } 1283 Result.append(res.begin(), res.end()); 1284 } 1285 1286 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 1287 MachO::any_relocation_info RE = getRelocation(Rel); 1288 return getAnyRelocationLength(RE); 1289 } 1290 1291 // 1292 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1293 // guess on what the short name is. Then name is returned as a substring of the 1294 // StringRef Name passed in. The name of the dynamic library is recognized as 1295 // a framework if it has one of the two following forms: 1296 // Foo.framework/Versions/A/Foo 1297 // Foo.framework/Foo 1298 // Where A and Foo can be any string. And may contain a trailing suffix 1299 // starting with an underbar. If the Name is recognized as a framework then 1300 // isFramework is set to true else it is set to false. If the Name has a 1301 // suffix then Suffix is set to the substring in Name that contains the suffix 1302 // else it is set to a NULL StringRef. 1303 // 1304 // The Name of the dynamic library is recognized as a library name if it has 1305 // one of the two following forms: 1306 // libFoo.A.dylib 1307 // libFoo.dylib 1308 // The library may have a suffix trailing the name Foo of the form: 1309 // libFoo_profile.A.dylib 1310 // libFoo_profile.dylib 1311 // 1312 // The Name of the dynamic library is also recognized as a library name if it 1313 // has the following form: 1314 // Foo.qtx 1315 // 1316 // If the Name of the dynamic library is none of the forms above then a NULL 1317 // StringRef is returned. 1318 // 1319 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1320 bool &isFramework, 1321 StringRef &Suffix) { 1322 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1323 size_t a, b, c, d, Idx; 1324 1325 isFramework = false; 1326 Suffix = StringRef(); 1327 1328 // Pull off the last component and make Foo point to it 1329 a = Name.rfind('/'); 1330 if (a == Name.npos || a == 0) 1331 goto guess_library; 1332 Foo = Name.slice(a+1, Name.npos); 1333 1334 // Look for a suffix starting with a '_' 1335 Idx = Foo.rfind('_'); 1336 if (Idx != Foo.npos && Foo.size() >= 2) { 1337 Suffix = Foo.slice(Idx, Foo.npos); 1338 Foo = Foo.slice(0, Idx); 1339 } 1340 1341 // First look for the form Foo.framework/Foo 1342 b = Name.rfind('/', a); 1343 if (b == Name.npos) 1344 Idx = 0; 1345 else 1346 Idx = b+1; 1347 F = Name.slice(Idx, Idx + Foo.size()); 1348 DotFramework = Name.slice(Idx + Foo.size(), 1349 Idx + Foo.size() + sizeof(".framework/")-1); 1350 if (F == Foo && DotFramework == ".framework/") { 1351 isFramework = true; 1352 return Foo; 1353 } 1354 1355 // Next look for the form Foo.framework/Versions/A/Foo 1356 if (b == Name.npos) 1357 goto guess_library; 1358 c = Name.rfind('/', b); 1359 if (c == Name.npos || c == 0) 1360 goto guess_library; 1361 V = Name.slice(c+1, Name.npos); 1362 if (!V.startswith("Versions/")) 1363 goto guess_library; 1364 d = Name.rfind('/', c); 1365 if (d == Name.npos) 1366 Idx = 0; 1367 else 1368 Idx = d+1; 1369 F = Name.slice(Idx, Idx + Foo.size()); 1370 DotFramework = Name.slice(Idx + Foo.size(), 1371 Idx + Foo.size() + sizeof(".framework/")-1); 1372 if (F == Foo && DotFramework == ".framework/") { 1373 isFramework = true; 1374 return Foo; 1375 } 1376 1377 guess_library: 1378 // pull off the suffix after the "." and make a point to it 1379 a = Name.rfind('.'); 1380 if (a == Name.npos || a == 0) 1381 return StringRef(); 1382 Dylib = Name.slice(a, Name.npos); 1383 if (Dylib != ".dylib") 1384 goto guess_qtx; 1385 1386 // First pull off the version letter for the form Foo.A.dylib if any. 1387 if (a >= 3) { 1388 Dot = Name.slice(a-2, a-1); 1389 if (Dot == ".") 1390 a = a - 2; 1391 } 1392 1393 b = Name.rfind('/', a); 1394 if (b == Name.npos) 1395 b = 0; 1396 else 1397 b = b+1; 1398 // ignore any suffix after an underbar like Foo_profile.A.dylib 1399 Idx = Name.find('_', b); 1400 if (Idx != Name.npos && Idx != b) { 1401 Lib = Name.slice(b, Idx); 1402 Suffix = Name.slice(Idx, a); 1403 } 1404 else 1405 Lib = Name.slice(b, a); 1406 // There are incorrect library names of the form: 1407 // libATS.A_profile.dylib so check for these. 1408 if (Lib.size() >= 3) { 1409 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1410 if (Dot == ".") 1411 Lib = Lib.slice(0, Lib.size()-2); 1412 } 1413 return Lib; 1414 1415 guess_qtx: 1416 Qtx = Name.slice(a, Name.npos); 1417 if (Qtx != ".qtx") 1418 return StringRef(); 1419 b = Name.rfind('/', a); 1420 if (b == Name.npos) 1421 Lib = Name.slice(0, a); 1422 else 1423 Lib = Name.slice(b+1, a); 1424 // There are library names of the form: QT.A.qtx so check for these. 1425 if (Lib.size() >= 3) { 1426 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1427 if (Dot == ".") 1428 Lib = Lib.slice(0, Lib.size()-2); 1429 } 1430 return Lib; 1431 } 1432 1433 // getLibraryShortNameByIndex() is used to get the short name of the library 1434 // for an undefined symbol in a linked Mach-O binary that was linked with the 1435 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1436 // It is passed the index (0 - based) of the library as translated from 1437 // GET_LIBRARY_ORDINAL (1 - based). 1438 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1439 StringRef &Res) const { 1440 if (Index >= Libraries.size()) 1441 return object_error::parse_failed; 1442 1443 // If the cache of LibrariesShortNames is not built up do that first for 1444 // all the Libraries. 1445 if (LibrariesShortNames.size() == 0) { 1446 for (unsigned i = 0; i < Libraries.size(); i++) { 1447 MachO::dylib_command D = 1448 getStruct<MachO::dylib_command>(this, Libraries[i]); 1449 if (D.dylib.name >= D.cmdsize) 1450 return object_error::parse_failed; 1451 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1452 StringRef Name = StringRef(P); 1453 if (D.dylib.name+Name.size() >= D.cmdsize) 1454 return object_error::parse_failed; 1455 StringRef Suffix; 1456 bool isFramework; 1457 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1458 if (shortName.empty()) 1459 LibrariesShortNames.push_back(Name); 1460 else 1461 LibrariesShortNames.push_back(shortName); 1462 } 1463 } 1464 1465 Res = LibrariesShortNames[Index]; 1466 return std::error_code(); 1467 } 1468 1469 section_iterator 1470 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 1471 DataRefImpl Sec; 1472 Sec.d.a = Rel->getRawDataRefImpl().d.a; 1473 return section_iterator(SectionRef(Sec, this)); 1474 } 1475 1476 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1477 DataRefImpl DRI; 1478 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1479 if (!SymtabLoadCmd || Symtab.nsyms == 0) 1480 return basic_symbol_iterator(SymbolRef(DRI, this)); 1481 1482 return getSymbolByIndex(0); 1483 } 1484 1485 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1486 DataRefImpl DRI; 1487 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1488 if (!SymtabLoadCmd || Symtab.nsyms == 0) 1489 return basic_symbol_iterator(SymbolRef(DRI, this)); 1490 1491 unsigned SymbolTableEntrySize = is64Bit() ? 1492 sizeof(MachO::nlist_64) : 1493 sizeof(MachO::nlist); 1494 unsigned Offset = Symtab.symoff + 1495 Symtab.nsyms * SymbolTableEntrySize; 1496 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1497 return basic_symbol_iterator(SymbolRef(DRI, this)); 1498 } 1499 1500 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1501 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1502 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 1503 report_fatal_error("Requested symbol index is out of range."); 1504 unsigned SymbolTableEntrySize = 1505 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1506 DataRefImpl DRI; 1507 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1508 DRI.p += Index * SymbolTableEntrySize; 1509 return basic_symbol_iterator(SymbolRef(DRI, this)); 1510 } 1511 1512 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 1513 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1514 if (!SymtabLoadCmd) 1515 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 1516 unsigned SymbolTableEntrySize = 1517 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1518 DataRefImpl DRIstart; 1519 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1520 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 1521 return Index; 1522 } 1523 1524 section_iterator MachOObjectFile::section_begin() const { 1525 DataRefImpl DRI; 1526 return section_iterator(SectionRef(DRI, this)); 1527 } 1528 1529 section_iterator MachOObjectFile::section_end() const { 1530 DataRefImpl DRI; 1531 DRI.d.a = Sections.size(); 1532 return section_iterator(SectionRef(DRI, this)); 1533 } 1534 1535 uint8_t MachOObjectFile::getBytesInAddress() const { 1536 return is64Bit() ? 8 : 4; 1537 } 1538 1539 StringRef MachOObjectFile::getFileFormatName() const { 1540 unsigned CPUType = getCPUType(this); 1541 if (!is64Bit()) { 1542 switch (CPUType) { 1543 case llvm::MachO::CPU_TYPE_I386: 1544 return "Mach-O 32-bit i386"; 1545 case llvm::MachO::CPU_TYPE_ARM: 1546 return "Mach-O arm"; 1547 case llvm::MachO::CPU_TYPE_POWERPC: 1548 return "Mach-O 32-bit ppc"; 1549 default: 1550 return "Mach-O 32-bit unknown"; 1551 } 1552 } 1553 1554 switch (CPUType) { 1555 case llvm::MachO::CPU_TYPE_X86_64: 1556 return "Mach-O 64-bit x86-64"; 1557 case llvm::MachO::CPU_TYPE_ARM64: 1558 return "Mach-O arm64"; 1559 case llvm::MachO::CPU_TYPE_POWERPC64: 1560 return "Mach-O 64-bit ppc64"; 1561 default: 1562 return "Mach-O 64-bit unknown"; 1563 } 1564 } 1565 1566 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1567 switch (CPUType) { 1568 case llvm::MachO::CPU_TYPE_I386: 1569 return Triple::x86; 1570 case llvm::MachO::CPU_TYPE_X86_64: 1571 return Triple::x86_64; 1572 case llvm::MachO::CPU_TYPE_ARM: 1573 return Triple::arm; 1574 case llvm::MachO::CPU_TYPE_ARM64: 1575 return Triple::aarch64; 1576 case llvm::MachO::CPU_TYPE_POWERPC: 1577 return Triple::ppc; 1578 case llvm::MachO::CPU_TYPE_POWERPC64: 1579 return Triple::ppc64; 1580 default: 1581 return Triple::UnknownArch; 1582 } 1583 } 1584 1585 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 1586 const char **McpuDefault) { 1587 if (McpuDefault) 1588 *McpuDefault = nullptr; 1589 1590 switch (CPUType) { 1591 case MachO::CPU_TYPE_I386: 1592 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1593 case MachO::CPU_SUBTYPE_I386_ALL: 1594 return Triple("i386-apple-darwin"); 1595 default: 1596 return Triple(); 1597 } 1598 case MachO::CPU_TYPE_X86_64: 1599 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1600 case MachO::CPU_SUBTYPE_X86_64_ALL: 1601 return Triple("x86_64-apple-darwin"); 1602 case MachO::CPU_SUBTYPE_X86_64_H: 1603 return Triple("x86_64h-apple-darwin"); 1604 default: 1605 return Triple(); 1606 } 1607 case MachO::CPU_TYPE_ARM: 1608 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1609 case MachO::CPU_SUBTYPE_ARM_V4T: 1610 return Triple("armv4t-apple-darwin"); 1611 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1612 return Triple("armv5e-apple-darwin"); 1613 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1614 return Triple("xscale-apple-darwin"); 1615 case MachO::CPU_SUBTYPE_ARM_V6: 1616 return Triple("armv6-apple-darwin"); 1617 case MachO::CPU_SUBTYPE_ARM_V6M: 1618 if (McpuDefault) 1619 *McpuDefault = "cortex-m0"; 1620 return Triple("armv6m-apple-darwin"); 1621 case MachO::CPU_SUBTYPE_ARM_V7: 1622 return Triple("armv7-apple-darwin"); 1623 case MachO::CPU_SUBTYPE_ARM_V7EM: 1624 if (McpuDefault) 1625 *McpuDefault = "cortex-m4"; 1626 return Triple("thumbv7em-apple-darwin"); 1627 case MachO::CPU_SUBTYPE_ARM_V7K: 1628 return Triple("armv7k-apple-darwin"); 1629 case MachO::CPU_SUBTYPE_ARM_V7M: 1630 if (McpuDefault) 1631 *McpuDefault = "cortex-m3"; 1632 return Triple("thumbv7m-apple-darwin"); 1633 case MachO::CPU_SUBTYPE_ARM_V7S: 1634 return Triple("armv7s-apple-darwin"); 1635 default: 1636 return Triple(); 1637 } 1638 case MachO::CPU_TYPE_ARM64: 1639 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1640 case MachO::CPU_SUBTYPE_ARM64_ALL: 1641 return Triple("arm64-apple-darwin"); 1642 default: 1643 return Triple(); 1644 } 1645 case MachO::CPU_TYPE_POWERPC: 1646 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1647 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1648 return Triple("ppc-apple-darwin"); 1649 default: 1650 return Triple(); 1651 } 1652 case MachO::CPU_TYPE_POWERPC64: 1653 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1654 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1655 return Triple("ppc64-apple-darwin"); 1656 default: 1657 return Triple(); 1658 } 1659 default: 1660 return Triple(); 1661 } 1662 } 1663 1664 Triple MachOObjectFile::getHostArch() { 1665 return Triple(sys::getDefaultTargetTriple()); 1666 } 1667 1668 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 1669 return StringSwitch<bool>(ArchFlag) 1670 .Case("i386", true) 1671 .Case("x86_64", true) 1672 .Case("x86_64h", true) 1673 .Case("armv4t", true) 1674 .Case("arm", true) 1675 .Case("armv5e", true) 1676 .Case("armv6", true) 1677 .Case("armv6m", true) 1678 .Case("armv7", true) 1679 .Case("armv7em", true) 1680 .Case("armv7k", true) 1681 .Case("armv7m", true) 1682 .Case("armv7s", true) 1683 .Case("arm64", true) 1684 .Case("ppc", true) 1685 .Case("ppc64", true) 1686 .Default(false); 1687 } 1688 1689 unsigned MachOObjectFile::getArch() const { 1690 return getArch(getCPUType(this)); 1691 } 1692 1693 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 1694 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 1695 } 1696 1697 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 1698 DataRefImpl DRI; 1699 DRI.d.a = Index; 1700 return section_rel_begin(DRI); 1701 } 1702 1703 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 1704 DataRefImpl DRI; 1705 DRI.d.a = Index; 1706 return section_rel_end(DRI); 1707 } 1708 1709 dice_iterator MachOObjectFile::begin_dices() const { 1710 DataRefImpl DRI; 1711 if (!DataInCodeLoadCmd) 1712 return dice_iterator(DiceRef(DRI, this)); 1713 1714 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1715 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 1716 return dice_iterator(DiceRef(DRI, this)); 1717 } 1718 1719 dice_iterator MachOObjectFile::end_dices() const { 1720 DataRefImpl DRI; 1721 if (!DataInCodeLoadCmd) 1722 return dice_iterator(DiceRef(DRI, this)); 1723 1724 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 1725 unsigned Offset = DicLC.dataoff + DicLC.datasize; 1726 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1727 return dice_iterator(DiceRef(DRI, this)); 1728 } 1729 1730 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 1731 : Trie(T), Malformed(false), Done(false) {} 1732 1733 void ExportEntry::moveToFirst() { 1734 pushNode(0); 1735 pushDownUntilBottom(); 1736 } 1737 1738 void ExportEntry::moveToEnd() { 1739 Stack.clear(); 1740 Done = true; 1741 } 1742 1743 bool ExportEntry::operator==(const ExportEntry &Other) const { 1744 // Common case, one at end, other iterating from begin. 1745 if (Done || Other.Done) 1746 return (Done == Other.Done); 1747 // Not equal if different stack sizes. 1748 if (Stack.size() != Other.Stack.size()) 1749 return false; 1750 // Not equal if different cumulative strings. 1751 if (!CumulativeString.equals(Other.CumulativeString)) 1752 return false; 1753 // Equal if all nodes in both stacks match. 1754 for (unsigned i=0; i < Stack.size(); ++i) { 1755 if (Stack[i].Start != Other.Stack[i].Start) 1756 return false; 1757 } 1758 return true; 1759 } 1760 1761 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 1762 unsigned Count; 1763 uint64_t Result = decodeULEB128(Ptr, &Count); 1764 Ptr += Count; 1765 if (Ptr > Trie.end()) { 1766 Ptr = Trie.end(); 1767 Malformed = true; 1768 } 1769 return Result; 1770 } 1771 1772 StringRef ExportEntry::name() const { 1773 return CumulativeString; 1774 } 1775 1776 uint64_t ExportEntry::flags() const { 1777 return Stack.back().Flags; 1778 } 1779 1780 uint64_t ExportEntry::address() const { 1781 return Stack.back().Address; 1782 } 1783 1784 uint64_t ExportEntry::other() const { 1785 return Stack.back().Other; 1786 } 1787 1788 StringRef ExportEntry::otherName() const { 1789 const char* ImportName = Stack.back().ImportName; 1790 if (ImportName) 1791 return StringRef(ImportName); 1792 return StringRef(); 1793 } 1794 1795 uint32_t ExportEntry::nodeOffset() const { 1796 return Stack.back().Start - Trie.begin(); 1797 } 1798 1799 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 1800 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 1801 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 1802 ParentStringLength(0), IsExportNode(false) {} 1803 1804 void ExportEntry::pushNode(uint64_t offset) { 1805 const uint8_t *Ptr = Trie.begin() + offset; 1806 NodeState State(Ptr); 1807 uint64_t ExportInfoSize = readULEB128(State.Current); 1808 State.IsExportNode = (ExportInfoSize != 0); 1809 const uint8_t* Children = State.Current + ExportInfoSize; 1810 if (State.IsExportNode) { 1811 State.Flags = readULEB128(State.Current); 1812 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 1813 State.Address = 0; 1814 State.Other = readULEB128(State.Current); // dylib ordinal 1815 State.ImportName = reinterpret_cast<const char*>(State.Current); 1816 } else { 1817 State.Address = readULEB128(State.Current); 1818 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 1819 State.Other = readULEB128(State.Current); 1820 } 1821 } 1822 State.ChildCount = *Children; 1823 State.Current = Children + 1; 1824 State.NextChildIndex = 0; 1825 State.ParentStringLength = CumulativeString.size(); 1826 Stack.push_back(State); 1827 } 1828 1829 void ExportEntry::pushDownUntilBottom() { 1830 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 1831 NodeState &Top = Stack.back(); 1832 CumulativeString.resize(Top.ParentStringLength); 1833 for (;*Top.Current != 0; Top.Current++) { 1834 char C = *Top.Current; 1835 CumulativeString.push_back(C); 1836 } 1837 Top.Current += 1; 1838 uint64_t childNodeIndex = readULEB128(Top.Current); 1839 Top.NextChildIndex += 1; 1840 pushNode(childNodeIndex); 1841 } 1842 if (!Stack.back().IsExportNode) { 1843 Malformed = true; 1844 moveToEnd(); 1845 } 1846 } 1847 1848 // We have a trie data structure and need a way to walk it that is compatible 1849 // with the C++ iterator model. The solution is a non-recursive depth first 1850 // traversal where the iterator contains a stack of parent nodes along with a 1851 // string that is the accumulation of all edge strings along the parent chain 1852 // to this point. 1853 // 1854 // There is one "export" node for each exported symbol. But because some 1855 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 1856 // node may have child nodes too. 1857 // 1858 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 1859 // child until hitting a node with no children (which is an export node or 1860 // else the trie is malformed). On the way down, each node is pushed on the 1861 // stack ivar. If there is no more ways down, it pops up one and tries to go 1862 // down a sibling path until a childless node is reached. 1863 void ExportEntry::moveNext() { 1864 if (Stack.empty() || !Stack.back().IsExportNode) { 1865 Malformed = true; 1866 moveToEnd(); 1867 return; 1868 } 1869 1870 Stack.pop_back(); 1871 while (!Stack.empty()) { 1872 NodeState &Top = Stack.back(); 1873 if (Top.NextChildIndex < Top.ChildCount) { 1874 pushDownUntilBottom(); 1875 // Now at the next export node. 1876 return; 1877 } else { 1878 if (Top.IsExportNode) { 1879 // This node has no children but is itself an export node. 1880 CumulativeString.resize(Top.ParentStringLength); 1881 return; 1882 } 1883 Stack.pop_back(); 1884 } 1885 } 1886 Done = true; 1887 } 1888 1889 iterator_range<export_iterator> 1890 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 1891 ExportEntry Start(Trie); 1892 if (Trie.size() == 0) 1893 Start.moveToEnd(); 1894 else 1895 Start.moveToFirst(); 1896 1897 ExportEntry Finish(Trie); 1898 Finish.moveToEnd(); 1899 1900 return make_range(export_iterator(Start), export_iterator(Finish)); 1901 } 1902 1903 iterator_range<export_iterator> MachOObjectFile::exports() const { 1904 return exports(getDyldInfoExportsTrie()); 1905 } 1906 1907 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 1908 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 1909 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 1910 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 1911 1912 void MachORebaseEntry::moveToFirst() { 1913 Ptr = Opcodes.begin(); 1914 moveNext(); 1915 } 1916 1917 void MachORebaseEntry::moveToEnd() { 1918 Ptr = Opcodes.end(); 1919 RemainingLoopCount = 0; 1920 Done = true; 1921 } 1922 1923 void MachORebaseEntry::moveNext() { 1924 // If in the middle of some loop, move to next rebasing in loop. 1925 SegmentOffset += AdvanceAmount; 1926 if (RemainingLoopCount) { 1927 --RemainingLoopCount; 1928 return; 1929 } 1930 if (Ptr == Opcodes.end()) { 1931 Done = true; 1932 return; 1933 } 1934 bool More = true; 1935 while (More && !Malformed) { 1936 // Parse next opcode and set up next loop. 1937 uint8_t Byte = *Ptr++; 1938 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 1939 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 1940 switch (Opcode) { 1941 case MachO::REBASE_OPCODE_DONE: 1942 More = false; 1943 Done = true; 1944 moveToEnd(); 1945 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 1946 break; 1947 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 1948 RebaseType = ImmValue; 1949 DEBUG_WITH_TYPE( 1950 "mach-o-rebase", 1951 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 1952 << "RebaseType=" << (int) RebaseType << "\n"); 1953 break; 1954 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 1955 SegmentIndex = ImmValue; 1956 SegmentOffset = readULEB128(); 1957 DEBUG_WITH_TYPE( 1958 "mach-o-rebase", 1959 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 1960 << "SegmentIndex=" << SegmentIndex << ", " 1961 << format("SegmentOffset=0x%06X", SegmentOffset) 1962 << "\n"); 1963 break; 1964 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 1965 SegmentOffset += readULEB128(); 1966 DEBUG_WITH_TYPE("mach-o-rebase", 1967 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 1968 << format("SegmentOffset=0x%06X", 1969 SegmentOffset) << "\n"); 1970 break; 1971 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 1972 SegmentOffset += ImmValue * PointerSize; 1973 DEBUG_WITH_TYPE("mach-o-rebase", 1974 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 1975 << format("SegmentOffset=0x%06X", 1976 SegmentOffset) << "\n"); 1977 break; 1978 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 1979 AdvanceAmount = PointerSize; 1980 RemainingLoopCount = ImmValue - 1; 1981 DEBUG_WITH_TYPE( 1982 "mach-o-rebase", 1983 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 1984 << format("SegmentOffset=0x%06X", SegmentOffset) 1985 << ", AdvanceAmount=" << AdvanceAmount 1986 << ", RemainingLoopCount=" << RemainingLoopCount 1987 << "\n"); 1988 return; 1989 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 1990 AdvanceAmount = PointerSize; 1991 RemainingLoopCount = readULEB128() - 1; 1992 DEBUG_WITH_TYPE( 1993 "mach-o-rebase", 1994 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 1995 << format("SegmentOffset=0x%06X", SegmentOffset) 1996 << ", AdvanceAmount=" << AdvanceAmount 1997 << ", RemainingLoopCount=" << RemainingLoopCount 1998 << "\n"); 1999 return; 2000 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2001 AdvanceAmount = readULEB128() + PointerSize; 2002 RemainingLoopCount = 0; 2003 DEBUG_WITH_TYPE( 2004 "mach-o-rebase", 2005 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2006 << format("SegmentOffset=0x%06X", SegmentOffset) 2007 << ", AdvanceAmount=" << AdvanceAmount 2008 << ", RemainingLoopCount=" << RemainingLoopCount 2009 << "\n"); 2010 return; 2011 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2012 RemainingLoopCount = readULEB128() - 1; 2013 AdvanceAmount = readULEB128() + PointerSize; 2014 DEBUG_WITH_TYPE( 2015 "mach-o-rebase", 2016 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2017 << format("SegmentOffset=0x%06X", SegmentOffset) 2018 << ", AdvanceAmount=" << AdvanceAmount 2019 << ", RemainingLoopCount=" << RemainingLoopCount 2020 << "\n"); 2021 return; 2022 default: 2023 Malformed = true; 2024 } 2025 } 2026 } 2027 2028 uint64_t MachORebaseEntry::readULEB128() { 2029 unsigned Count; 2030 uint64_t Result = decodeULEB128(Ptr, &Count); 2031 Ptr += Count; 2032 if (Ptr > Opcodes.end()) { 2033 Ptr = Opcodes.end(); 2034 Malformed = true; 2035 } 2036 return Result; 2037 } 2038 2039 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2040 2041 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2042 2043 StringRef MachORebaseEntry::typeName() const { 2044 switch (RebaseType) { 2045 case MachO::REBASE_TYPE_POINTER: 2046 return "pointer"; 2047 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2048 return "text abs32"; 2049 case MachO::REBASE_TYPE_TEXT_PCREL32: 2050 return "text rel32"; 2051 } 2052 return "unknown"; 2053 } 2054 2055 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2056 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2057 return (Ptr == Other.Ptr) && 2058 (RemainingLoopCount == Other.RemainingLoopCount) && 2059 (Done == Other.Done); 2060 } 2061 2062 iterator_range<rebase_iterator> 2063 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2064 MachORebaseEntry Start(Opcodes, is64); 2065 Start.moveToFirst(); 2066 2067 MachORebaseEntry Finish(Opcodes, is64); 2068 Finish.moveToEnd(); 2069 2070 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2071 } 2072 2073 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2074 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2075 } 2076 2077 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2078 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2079 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2080 BindType(0), PointerSize(is64Bit ? 8 : 4), 2081 TableKind(BK), Malformed(false), Done(false) {} 2082 2083 void MachOBindEntry::moveToFirst() { 2084 Ptr = Opcodes.begin(); 2085 moveNext(); 2086 } 2087 2088 void MachOBindEntry::moveToEnd() { 2089 Ptr = Opcodes.end(); 2090 RemainingLoopCount = 0; 2091 Done = true; 2092 } 2093 2094 void MachOBindEntry::moveNext() { 2095 // If in the middle of some loop, move to next binding in loop. 2096 SegmentOffset += AdvanceAmount; 2097 if (RemainingLoopCount) { 2098 --RemainingLoopCount; 2099 return; 2100 } 2101 if (Ptr == Opcodes.end()) { 2102 Done = true; 2103 return; 2104 } 2105 bool More = true; 2106 while (More && !Malformed) { 2107 // Parse next opcode and set up next loop. 2108 uint8_t Byte = *Ptr++; 2109 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2110 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2111 int8_t SignExtended; 2112 const uint8_t *SymStart; 2113 switch (Opcode) { 2114 case MachO::BIND_OPCODE_DONE: 2115 if (TableKind == Kind::Lazy) { 2116 // Lazying bindings have a DONE opcode between entries. Need to ignore 2117 // it to advance to next entry. But need not if this is last entry. 2118 bool NotLastEntry = false; 2119 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2120 if (*P) { 2121 NotLastEntry = true; 2122 } 2123 } 2124 if (NotLastEntry) 2125 break; 2126 } 2127 More = false; 2128 Done = true; 2129 moveToEnd(); 2130 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2131 break; 2132 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2133 Ordinal = ImmValue; 2134 DEBUG_WITH_TYPE( 2135 "mach-o-bind", 2136 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2137 << "Ordinal=" << Ordinal << "\n"); 2138 break; 2139 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2140 Ordinal = readULEB128(); 2141 DEBUG_WITH_TYPE( 2142 "mach-o-bind", 2143 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2144 << "Ordinal=" << Ordinal << "\n"); 2145 break; 2146 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2147 if (ImmValue) { 2148 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2149 Ordinal = SignExtended; 2150 } else 2151 Ordinal = 0; 2152 DEBUG_WITH_TYPE( 2153 "mach-o-bind", 2154 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2155 << "Ordinal=" << Ordinal << "\n"); 2156 break; 2157 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2158 Flags = ImmValue; 2159 SymStart = Ptr; 2160 while (*Ptr) { 2161 ++Ptr; 2162 } 2163 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2164 Ptr-SymStart); 2165 ++Ptr; 2166 DEBUG_WITH_TYPE( 2167 "mach-o-bind", 2168 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2169 << "SymbolName=" << SymbolName << "\n"); 2170 if (TableKind == Kind::Weak) { 2171 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2172 return; 2173 } 2174 break; 2175 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2176 BindType = ImmValue; 2177 DEBUG_WITH_TYPE( 2178 "mach-o-bind", 2179 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2180 << "BindType=" << (int)BindType << "\n"); 2181 break; 2182 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2183 Addend = readSLEB128(); 2184 if (TableKind == Kind::Lazy) 2185 Malformed = true; 2186 DEBUG_WITH_TYPE( 2187 "mach-o-bind", 2188 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2189 << "Addend=" << Addend << "\n"); 2190 break; 2191 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2192 SegmentIndex = ImmValue; 2193 SegmentOffset = readULEB128(); 2194 DEBUG_WITH_TYPE( 2195 "mach-o-bind", 2196 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2197 << "SegmentIndex=" << SegmentIndex << ", " 2198 << format("SegmentOffset=0x%06X", SegmentOffset) 2199 << "\n"); 2200 break; 2201 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2202 SegmentOffset += readULEB128(); 2203 DEBUG_WITH_TYPE("mach-o-bind", 2204 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2205 << format("SegmentOffset=0x%06X", 2206 SegmentOffset) << "\n"); 2207 break; 2208 case MachO::BIND_OPCODE_DO_BIND: 2209 AdvanceAmount = PointerSize; 2210 RemainingLoopCount = 0; 2211 DEBUG_WITH_TYPE("mach-o-bind", 2212 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2213 << format("SegmentOffset=0x%06X", 2214 SegmentOffset) << "\n"); 2215 return; 2216 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2217 AdvanceAmount = readULEB128() + PointerSize; 2218 RemainingLoopCount = 0; 2219 if (TableKind == Kind::Lazy) 2220 Malformed = true; 2221 DEBUG_WITH_TYPE( 2222 "mach-o-bind", 2223 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2224 << format("SegmentOffset=0x%06X", SegmentOffset) 2225 << ", AdvanceAmount=" << AdvanceAmount 2226 << ", RemainingLoopCount=" << RemainingLoopCount 2227 << "\n"); 2228 return; 2229 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2230 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2231 RemainingLoopCount = 0; 2232 if (TableKind == Kind::Lazy) 2233 Malformed = true; 2234 DEBUG_WITH_TYPE("mach-o-bind", 2235 llvm::dbgs() 2236 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2237 << format("SegmentOffset=0x%06X", 2238 SegmentOffset) << "\n"); 2239 return; 2240 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2241 RemainingLoopCount = readULEB128() - 1; 2242 AdvanceAmount = readULEB128() + PointerSize; 2243 if (TableKind == Kind::Lazy) 2244 Malformed = true; 2245 DEBUG_WITH_TYPE( 2246 "mach-o-bind", 2247 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2248 << format("SegmentOffset=0x%06X", SegmentOffset) 2249 << ", AdvanceAmount=" << AdvanceAmount 2250 << ", RemainingLoopCount=" << RemainingLoopCount 2251 << "\n"); 2252 return; 2253 default: 2254 Malformed = true; 2255 } 2256 } 2257 } 2258 2259 uint64_t MachOBindEntry::readULEB128() { 2260 unsigned Count; 2261 uint64_t Result = decodeULEB128(Ptr, &Count); 2262 Ptr += Count; 2263 if (Ptr > Opcodes.end()) { 2264 Ptr = Opcodes.end(); 2265 Malformed = true; 2266 } 2267 return Result; 2268 } 2269 2270 int64_t MachOBindEntry::readSLEB128() { 2271 unsigned Count; 2272 int64_t Result = decodeSLEB128(Ptr, &Count); 2273 Ptr += Count; 2274 if (Ptr > Opcodes.end()) { 2275 Ptr = Opcodes.end(); 2276 Malformed = true; 2277 } 2278 return Result; 2279 } 2280 2281 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 2282 2283 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 2284 2285 StringRef MachOBindEntry::typeName() const { 2286 switch (BindType) { 2287 case MachO::BIND_TYPE_POINTER: 2288 return "pointer"; 2289 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 2290 return "text abs32"; 2291 case MachO::BIND_TYPE_TEXT_PCREL32: 2292 return "text rel32"; 2293 } 2294 return "unknown"; 2295 } 2296 2297 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 2298 2299 int64_t MachOBindEntry::addend() const { return Addend; } 2300 2301 uint32_t MachOBindEntry::flags() const { return Flags; } 2302 2303 int MachOBindEntry::ordinal() const { return Ordinal; } 2304 2305 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 2306 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2307 return (Ptr == Other.Ptr) && 2308 (RemainingLoopCount == Other.RemainingLoopCount) && 2309 (Done == Other.Done); 2310 } 2311 2312 iterator_range<bind_iterator> 2313 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 2314 MachOBindEntry::Kind BKind) { 2315 MachOBindEntry Start(Opcodes, is64, BKind); 2316 Start.moveToFirst(); 2317 2318 MachOBindEntry Finish(Opcodes, is64, BKind); 2319 Finish.moveToEnd(); 2320 2321 return make_range(bind_iterator(Start), bind_iterator(Finish)); 2322 } 2323 2324 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 2325 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 2326 MachOBindEntry::Kind::Regular); 2327 } 2328 2329 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 2330 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 2331 MachOBindEntry::Kind::Lazy); 2332 } 2333 2334 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 2335 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 2336 MachOBindEntry::Kind::Weak); 2337 } 2338 2339 MachOObjectFile::load_command_iterator 2340 MachOObjectFile::begin_load_commands() const { 2341 return LoadCommands.begin(); 2342 } 2343 2344 MachOObjectFile::load_command_iterator 2345 MachOObjectFile::end_load_commands() const { 2346 return LoadCommands.end(); 2347 } 2348 2349 iterator_range<MachOObjectFile::load_command_iterator> 2350 MachOObjectFile::load_commands() const { 2351 return make_range(begin_load_commands(), end_load_commands()); 2352 } 2353 2354 StringRef 2355 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 2356 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 2357 return parseSegmentOrSectionName(Raw.data()); 2358 } 2359 2360 ArrayRef<char> 2361 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 2362 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2363 const section_base *Base = 2364 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2365 return makeArrayRef(Base->sectname); 2366 } 2367 2368 ArrayRef<char> 2369 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 2370 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2371 const section_base *Base = 2372 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2373 return makeArrayRef(Base->segname); 2374 } 2375 2376 bool 2377 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 2378 const { 2379 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 2380 return false; 2381 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 2382 } 2383 2384 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 2385 const MachO::any_relocation_info &RE) const { 2386 if (isLittleEndian()) 2387 return RE.r_word1 & 0xffffff; 2388 return RE.r_word1 >> 8; 2389 } 2390 2391 bool MachOObjectFile::getPlainRelocationExternal( 2392 const MachO::any_relocation_info &RE) const { 2393 if (isLittleEndian()) 2394 return (RE.r_word1 >> 27) & 1; 2395 return (RE.r_word1 >> 4) & 1; 2396 } 2397 2398 bool MachOObjectFile::getScatteredRelocationScattered( 2399 const MachO::any_relocation_info &RE) const { 2400 return RE.r_word0 >> 31; 2401 } 2402 2403 uint32_t MachOObjectFile::getScatteredRelocationValue( 2404 const MachO::any_relocation_info &RE) const { 2405 return RE.r_word1; 2406 } 2407 2408 uint32_t MachOObjectFile::getScatteredRelocationType( 2409 const MachO::any_relocation_info &RE) const { 2410 return (RE.r_word0 >> 24) & 0xf; 2411 } 2412 2413 unsigned MachOObjectFile::getAnyRelocationAddress( 2414 const MachO::any_relocation_info &RE) const { 2415 if (isRelocationScattered(RE)) 2416 return getScatteredRelocationAddress(RE); 2417 return getPlainRelocationAddress(RE); 2418 } 2419 2420 unsigned MachOObjectFile::getAnyRelocationPCRel( 2421 const MachO::any_relocation_info &RE) const { 2422 if (isRelocationScattered(RE)) 2423 return getScatteredRelocationPCRel(this, RE); 2424 return getPlainRelocationPCRel(this, RE); 2425 } 2426 2427 unsigned MachOObjectFile::getAnyRelocationLength( 2428 const MachO::any_relocation_info &RE) const { 2429 if (isRelocationScattered(RE)) 2430 return getScatteredRelocationLength(RE); 2431 return getPlainRelocationLength(this, RE); 2432 } 2433 2434 unsigned 2435 MachOObjectFile::getAnyRelocationType( 2436 const MachO::any_relocation_info &RE) const { 2437 if (isRelocationScattered(RE)) 2438 return getScatteredRelocationType(RE); 2439 return getPlainRelocationType(this, RE); 2440 } 2441 2442 SectionRef 2443 MachOObjectFile::getAnyRelocationSection( 2444 const MachO::any_relocation_info &RE) const { 2445 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 2446 return *section_end(); 2447 unsigned SecNum = getPlainRelocationSymbolNum(RE); 2448 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 2449 return *section_end(); 2450 DataRefImpl DRI; 2451 DRI.d.a = SecNum - 1; 2452 return SectionRef(DRI, this); 2453 } 2454 2455 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 2456 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 2457 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 2458 } 2459 2460 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 2461 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 2462 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 2463 } 2464 2465 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 2466 unsigned Index) const { 2467 const char *Sec = getSectionPtr(this, L, Index); 2468 return getStruct<MachO::section>(this, Sec); 2469 } 2470 2471 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 2472 unsigned Index) const { 2473 const char *Sec = getSectionPtr(this, L, Index); 2474 return getStruct<MachO::section_64>(this, Sec); 2475 } 2476 2477 MachO::nlist 2478 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 2479 const char *P = reinterpret_cast<const char *>(DRI.p); 2480 return getStruct<MachO::nlist>(this, P); 2481 } 2482 2483 MachO::nlist_64 2484 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 2485 const char *P = reinterpret_cast<const char *>(DRI.p); 2486 return getStruct<MachO::nlist_64>(this, P); 2487 } 2488 2489 MachO::linkedit_data_command 2490 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 2491 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 2492 } 2493 2494 MachO::segment_command 2495 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 2496 return getStruct<MachO::segment_command>(this, L.Ptr); 2497 } 2498 2499 MachO::segment_command_64 2500 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 2501 return getStruct<MachO::segment_command_64>(this, L.Ptr); 2502 } 2503 2504 MachO::linker_option_command 2505 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 2506 return getStruct<MachO::linker_option_command>(this, L.Ptr); 2507 } 2508 2509 MachO::version_min_command 2510 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 2511 return getStruct<MachO::version_min_command>(this, L.Ptr); 2512 } 2513 2514 MachO::dylib_command 2515 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 2516 return getStruct<MachO::dylib_command>(this, L.Ptr); 2517 } 2518 2519 MachO::dyld_info_command 2520 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 2521 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 2522 } 2523 2524 MachO::dylinker_command 2525 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 2526 return getStruct<MachO::dylinker_command>(this, L.Ptr); 2527 } 2528 2529 MachO::uuid_command 2530 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 2531 return getStruct<MachO::uuid_command>(this, L.Ptr); 2532 } 2533 2534 MachO::rpath_command 2535 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 2536 return getStruct<MachO::rpath_command>(this, L.Ptr); 2537 } 2538 2539 MachO::source_version_command 2540 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 2541 return getStruct<MachO::source_version_command>(this, L.Ptr); 2542 } 2543 2544 MachO::entry_point_command 2545 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 2546 return getStruct<MachO::entry_point_command>(this, L.Ptr); 2547 } 2548 2549 MachO::encryption_info_command 2550 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 2551 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 2552 } 2553 2554 MachO::encryption_info_command_64 2555 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 2556 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 2557 } 2558 2559 MachO::sub_framework_command 2560 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 2561 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 2562 } 2563 2564 MachO::sub_umbrella_command 2565 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 2566 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 2567 } 2568 2569 MachO::sub_library_command 2570 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 2571 return getStruct<MachO::sub_library_command>(this, L.Ptr); 2572 } 2573 2574 MachO::sub_client_command 2575 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 2576 return getStruct<MachO::sub_client_command>(this, L.Ptr); 2577 } 2578 2579 MachO::routines_command 2580 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 2581 return getStruct<MachO::routines_command>(this, L.Ptr); 2582 } 2583 2584 MachO::routines_command_64 2585 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 2586 return getStruct<MachO::routines_command_64>(this, L.Ptr); 2587 } 2588 2589 MachO::thread_command 2590 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 2591 return getStruct<MachO::thread_command>(this, L.Ptr); 2592 } 2593 2594 MachO::any_relocation_info 2595 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 2596 DataRefImpl Sec; 2597 Sec.d.a = Rel.d.a; 2598 uint32_t Offset; 2599 if (is64Bit()) { 2600 MachO::section_64 Sect = getSection64(Sec); 2601 Offset = Sect.reloff; 2602 } else { 2603 MachO::section Sect = getSection(Sec); 2604 Offset = Sect.reloff; 2605 } 2606 2607 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 2608 getPtr(this, Offset)) + Rel.d.b; 2609 return getStruct<MachO::any_relocation_info>( 2610 this, reinterpret_cast<const char *>(P)); 2611 } 2612 2613 MachO::data_in_code_entry 2614 MachOObjectFile::getDice(DataRefImpl Rel) const { 2615 const char *P = reinterpret_cast<const char *>(Rel.p); 2616 return getStruct<MachO::data_in_code_entry>(this, P); 2617 } 2618 2619 const MachO::mach_header &MachOObjectFile::getHeader() const { 2620 return Header; 2621 } 2622 2623 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 2624 assert(is64Bit()); 2625 return Header64; 2626 } 2627 2628 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 2629 const MachO::dysymtab_command &DLC, 2630 unsigned Index) const { 2631 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 2632 return getStruct<uint32_t>(this, getPtr(this, Offset)); 2633 } 2634 2635 MachO::data_in_code_entry 2636 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 2637 unsigned Index) const { 2638 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 2639 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 2640 } 2641 2642 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 2643 if (SymtabLoadCmd) 2644 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 2645 2646 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 2647 MachO::symtab_command Cmd; 2648 Cmd.cmd = MachO::LC_SYMTAB; 2649 Cmd.cmdsize = sizeof(MachO::symtab_command); 2650 Cmd.symoff = 0; 2651 Cmd.nsyms = 0; 2652 Cmd.stroff = 0; 2653 Cmd.strsize = 0; 2654 return Cmd; 2655 } 2656 2657 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 2658 if (DysymtabLoadCmd) 2659 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 2660 2661 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 2662 MachO::dysymtab_command Cmd; 2663 Cmd.cmd = MachO::LC_DYSYMTAB; 2664 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 2665 Cmd.ilocalsym = 0; 2666 Cmd.nlocalsym = 0; 2667 Cmd.iextdefsym = 0; 2668 Cmd.nextdefsym = 0; 2669 Cmd.iundefsym = 0; 2670 Cmd.nundefsym = 0; 2671 Cmd.tocoff = 0; 2672 Cmd.ntoc = 0; 2673 Cmd.modtaboff = 0; 2674 Cmd.nmodtab = 0; 2675 Cmd.extrefsymoff = 0; 2676 Cmd.nextrefsyms = 0; 2677 Cmd.indirectsymoff = 0; 2678 Cmd.nindirectsyms = 0; 2679 Cmd.extreloff = 0; 2680 Cmd.nextrel = 0; 2681 Cmd.locreloff = 0; 2682 Cmd.nlocrel = 0; 2683 return Cmd; 2684 } 2685 2686 MachO::linkedit_data_command 2687 MachOObjectFile::getDataInCodeLoadCommand() const { 2688 if (DataInCodeLoadCmd) 2689 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 2690 2691 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 2692 MachO::linkedit_data_command Cmd; 2693 Cmd.cmd = MachO::LC_DATA_IN_CODE; 2694 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 2695 Cmd.dataoff = 0; 2696 Cmd.datasize = 0; 2697 return Cmd; 2698 } 2699 2700 MachO::linkedit_data_command 2701 MachOObjectFile::getLinkOptHintsLoadCommand() const { 2702 if (LinkOptHintsLoadCmd) 2703 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 2704 2705 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 2706 // fields. 2707 MachO::linkedit_data_command Cmd; 2708 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 2709 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 2710 Cmd.dataoff = 0; 2711 Cmd.datasize = 0; 2712 return Cmd; 2713 } 2714 2715 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 2716 if (!DyldInfoLoadCmd) 2717 return None; 2718 2719 MachO::dyld_info_command DyldInfo = 2720 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2721 const uint8_t *Ptr = 2722 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 2723 return makeArrayRef(Ptr, DyldInfo.rebase_size); 2724 } 2725 2726 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 2727 if (!DyldInfoLoadCmd) 2728 return None; 2729 2730 MachO::dyld_info_command DyldInfo = 2731 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2732 const uint8_t *Ptr = 2733 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 2734 return makeArrayRef(Ptr, DyldInfo.bind_size); 2735 } 2736 2737 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 2738 if (!DyldInfoLoadCmd) 2739 return None; 2740 2741 MachO::dyld_info_command DyldInfo = 2742 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2743 const uint8_t *Ptr = 2744 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 2745 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 2746 } 2747 2748 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 2749 if (!DyldInfoLoadCmd) 2750 return None; 2751 2752 MachO::dyld_info_command DyldInfo = 2753 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2754 const uint8_t *Ptr = 2755 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 2756 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 2757 } 2758 2759 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 2760 if (!DyldInfoLoadCmd) 2761 return None; 2762 2763 MachO::dyld_info_command DyldInfo = 2764 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 2765 const uint8_t *Ptr = 2766 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 2767 return makeArrayRef(Ptr, DyldInfo.export_size); 2768 } 2769 2770 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 2771 if (!UuidLoadCmd) 2772 return None; 2773 // Returning a pointer is fine as uuid doesn't need endian swapping. 2774 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 2775 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 2776 } 2777 2778 StringRef MachOObjectFile::getStringTableData() const { 2779 MachO::symtab_command S = getSymtabLoadCommand(); 2780 return getData().substr(S.stroff, S.strsize); 2781 } 2782 2783 bool MachOObjectFile::is64Bit() const { 2784 return getType() == getMachOType(false, true) || 2785 getType() == getMachOType(true, true); 2786 } 2787 2788 void MachOObjectFile::ReadULEB128s(uint64_t Index, 2789 SmallVectorImpl<uint64_t> &Out) const { 2790 DataExtractor extractor(ObjectFile::getData(), true, 0); 2791 2792 uint32_t offset = Index; 2793 uint64_t data = 0; 2794 while (uint64_t delta = extractor.getULEB128(&offset)) { 2795 data += delta; 2796 Out.push_back(data); 2797 } 2798 } 2799 2800 bool MachOObjectFile::isRelocatableObject() const { 2801 return getHeader().filetype == MachO::MH_OBJECT; 2802 } 2803 2804 Expected<std::unique_ptr<MachOObjectFile>> 2805 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 2806 StringRef Magic = Buffer.getBuffer().slice(0, 4); 2807 if (Magic == "\xFE\xED\xFA\xCE") 2808 return MachOObjectFile::create(Buffer, false, false); 2809 if (Magic == "\xCE\xFA\xED\xFE") 2810 return MachOObjectFile::create(Buffer, true, false); 2811 if (Magic == "\xFE\xED\xFA\xCF") 2812 return MachOObjectFile::create(Buffer, false, true); 2813 if (Magic == "\xCF\xFA\xED\xFE") 2814 return MachOObjectFile::create(Buffer, true, true); 2815 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 2816 object_error::invalid_file_type); 2817 } 2818