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