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