1 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the MachOObjectFile class, which binds the MachOObject 11 // class to the generic ObjectFile wrapper. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/Object/MachO.h" 16 #include "llvm/ADT/STLExtras.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/ADT/Triple.h" 19 #include "llvm/Support/DataExtractor.h" 20 #include "llvm/Support/Debug.h" 21 #include "llvm/Support/Format.h" 22 #include "llvm/Support/Host.h" 23 #include "llvm/Support/LEB128.h" 24 #include "llvm/Support/MachO.h" 25 #include "llvm/Support/MemoryBuffer.h" 26 #include "llvm/Support/raw_ostream.h" 27 #include <cctype> 28 #include <cstring> 29 #include <limits> 30 31 using namespace llvm; 32 using namespace object; 33 34 namespace { 35 struct section_base { 36 char sectname[16]; 37 char segname[16]; 38 }; 39 } 40 41 static Error 42 malformedError(Twine Msg) { 43 std::string StringMsg = "truncated or malformed object (" + Msg.str() + ")"; 44 return make_error<GenericBinaryError>(std::move(StringMsg), 45 object_error::parse_failed); 46 } 47 48 // FIXME: Replace all uses of this function with getStructOrErr. 49 template <typename T> 50 static T getStruct(const MachOObjectFile *O, const char *P) { 51 // Don't read before the beginning or past the end of the file 52 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) 53 report_fatal_error("Malformed MachO file."); 54 55 T Cmd; 56 memcpy(&Cmd, P, sizeof(T)); 57 if (O->isLittleEndian() != sys::IsLittleEndianHost) 58 MachO::swapStruct(Cmd); 59 return Cmd; 60 } 61 62 template <typename T> 63 static Expected<T> getStructOrErr(const MachOObjectFile *O, const char *P) { 64 // Don't read before the beginning or past the end of the file 65 if (P < O->getData().begin() || P + sizeof(T) > O->getData().end()) 66 return malformedError("Structure read out-of-range"); 67 68 T Cmd; 69 memcpy(&Cmd, P, sizeof(T)); 70 if (O->isLittleEndian() != sys::IsLittleEndianHost) 71 MachO::swapStruct(Cmd); 72 return Cmd; 73 } 74 75 static const char * 76 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 77 unsigned Sec) { 78 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 79 80 bool Is64 = O->is64Bit(); 81 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 82 sizeof(MachO::segment_command); 83 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 84 sizeof(MachO::section); 85 86 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 87 return reinterpret_cast<const char*>(SectionAddr); 88 } 89 90 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 91 return O->getData().substr(Offset, 1).data(); 92 } 93 94 static MachO::nlist_base 95 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 96 const char *P = reinterpret_cast<const char *>(DRI.p); 97 return getStruct<MachO::nlist_base>(O, P); 98 } 99 100 static StringRef parseSegmentOrSectionName(const char *P) { 101 if (P[15] == 0) 102 // Null terminated. 103 return P; 104 // Not null terminated, so this is a 16 char string. 105 return StringRef(P, 16); 106 } 107 108 // Helper to advance a section or symbol iterator multiple increments at a time. 109 template<class T> 110 static void advance(T &it, size_t Val) { 111 while (Val--) 112 ++it; 113 } 114 115 static unsigned getCPUType(const MachOObjectFile *O) { 116 return O->getHeader().cputype; 117 } 118 119 static uint32_t 120 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 121 return RE.r_word0; 122 } 123 124 static unsigned 125 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 126 return RE.r_word0 & 0xffffff; 127 } 128 129 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 130 const MachO::any_relocation_info &RE) { 131 if (O->isLittleEndian()) 132 return (RE.r_word1 >> 24) & 1; 133 return (RE.r_word1 >> 7) & 1; 134 } 135 136 static bool 137 getScatteredRelocationPCRel(const MachOObjectFile *O, 138 const MachO::any_relocation_info &RE) { 139 return (RE.r_word0 >> 30) & 1; 140 } 141 142 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 143 const MachO::any_relocation_info &RE) { 144 if (O->isLittleEndian()) 145 return (RE.r_word1 >> 25) & 3; 146 return (RE.r_word1 >> 5) & 3; 147 } 148 149 static unsigned 150 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 151 return (RE.r_word0 >> 28) & 3; 152 } 153 154 static unsigned getPlainRelocationType(const MachOObjectFile *O, 155 const MachO::any_relocation_info &RE) { 156 if (O->isLittleEndian()) 157 return RE.r_word1 >> 28; 158 return RE.r_word1 & 0xf; 159 } 160 161 static uint32_t getSectionFlags(const MachOObjectFile *O, 162 DataRefImpl Sec) { 163 if (O->is64Bit()) { 164 MachO::section_64 Sect = O->getSection64(Sec); 165 return Sect.flags; 166 } 167 MachO::section Sect = O->getSection(Sec); 168 return Sect.flags; 169 } 170 171 static Expected<MachOObjectFile::LoadCommandInfo> 172 getLoadCommandInfo(const MachOObjectFile *Obj, const char *Ptr, 173 uint32_t LoadCommandIndex) { 174 if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) { 175 if (CmdOrErr->cmdsize < 8) 176 return malformedError("load command " + Twine(LoadCommandIndex) + 177 " with size less than 8 bytes"); 178 return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr}); 179 } else 180 return CmdOrErr.takeError(); 181 } 182 183 static Expected<MachOObjectFile::LoadCommandInfo> 184 getFirstLoadCommandInfo(const MachOObjectFile *Obj) { 185 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 186 : sizeof(MachO::mach_header); 187 if (sizeof(MachO::load_command) > Obj->getHeader().sizeofcmds) 188 return malformedError("load command 0 extends past the end all load " 189 "commands in the file"); 190 return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0); 191 } 192 193 static Expected<MachOObjectFile::LoadCommandInfo> 194 getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex, 195 const MachOObjectFile::LoadCommandInfo &L) { 196 unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64) 197 : sizeof(MachO::mach_header); 198 if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) > 199 Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds) 200 return malformedError("load command " + Twine(LoadCommandIndex + 1) + 201 " extends past the end all load commands in the file"); 202 return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1); 203 } 204 205 template <typename T> 206 static void parseHeader(const MachOObjectFile *Obj, T &Header, 207 Error &Err) { 208 if (sizeof(T) > Obj->getData().size()) { 209 Err = malformedError("the mach header extends past the end of the " 210 "file"); 211 return; 212 } 213 if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0))) 214 Header = *HeaderOrErr; 215 else 216 Err = HeaderOrErr.takeError(); 217 } 218 219 // Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all 220 // sections to \param Sections, and optionally sets 221 // \param IsPageZeroSegment to true. 222 template <typename Segment, typename Section> 223 static Error parseSegmentLoadCommand( 224 const MachOObjectFile *Obj, const MachOObjectFile::LoadCommandInfo &Load, 225 SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment, 226 uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders) { 227 const unsigned SegmentLoadSize = sizeof(Segment); 228 if (Load.C.cmdsize < SegmentLoadSize) 229 return malformedError("load command " + Twine(LoadCommandIndex) + 230 " " + CmdName + " cmdsize too small"); 231 if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) { 232 Segment S = SegOrErr.get(); 233 const unsigned SectionSize = sizeof(Section); 234 uint64_t FileSize = Obj->getData().size(); 235 if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize || 236 S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize) 237 return malformedError("load command " + Twine(LoadCommandIndex) + 238 " inconsistent cmdsize in " + CmdName + 239 " for the number of sections"); 240 for (unsigned J = 0; J < S.nsects; ++J) { 241 const char *Sec = getSectionPtr(Obj, Load, J); 242 Sections.push_back(Sec); 243 Section s = getStruct<Section>(Obj, Sec); 244 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 245 Obj->getHeader().filetype != MachO::MH_DSYM && 246 s.flags != MachO::S_ZEROFILL && 247 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 248 s.offset > FileSize) 249 return malformedError("offset field of section " + Twine(J) + " in " + 250 CmdName + " command " + Twine(LoadCommandIndex) + 251 " extends past the end of the file"); 252 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 253 Obj->getHeader().filetype != MachO::MH_DSYM && 254 s.flags != MachO::S_ZEROFILL && 255 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && S.fileoff == 0 && 256 s.offset < SizeOfHeaders && s.size != 0) 257 return malformedError("offset field of section " + Twine(J) + " in " + 258 CmdName + " command " + Twine(LoadCommandIndex) + 259 " not past the headers of the file"); 260 uint64_t BigSize = s.offset; 261 BigSize += s.size; 262 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 263 Obj->getHeader().filetype != MachO::MH_DSYM && 264 s.flags != MachO::S_ZEROFILL && 265 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 266 BigSize > FileSize) 267 return malformedError("offset field plus size field of section " + 268 Twine(J) + " in " + CmdName + " command " + 269 Twine(LoadCommandIndex) + 270 " extends past the end of the file"); 271 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 272 Obj->getHeader().filetype != MachO::MH_DSYM && 273 s.flags != MachO::S_ZEROFILL && 274 s.flags != MachO::S_THREAD_LOCAL_ZEROFILL && 275 s.size > S.filesize) 276 return malformedError("size field of section " + 277 Twine(J) + " in " + CmdName + " command " + 278 Twine(LoadCommandIndex) + 279 " greater than the segment"); 280 if (Obj->getHeader().filetype != MachO::MH_DYLIB_STUB && 281 Obj->getHeader().filetype != MachO::MH_DSYM && s.size != 0 && 282 s.addr < S.vmaddr) 283 return malformedError("addr field of section " + Twine(J) + " in " + 284 CmdName + " command " + Twine(LoadCommandIndex) + 285 " less than the segment's vmaddr"); 286 BigSize = s.addr; 287 BigSize += s.size; 288 uint64_t BigEnd = S.vmaddr; 289 BigEnd += S.vmsize; 290 if (S.vmsize != 0 && s.size != 0 && BigSize > BigEnd) 291 return malformedError("addr field plus size of section " + Twine(J) + 292 " in " + CmdName + " command " + 293 Twine(LoadCommandIndex) + 294 " greater than than " 295 "the segment's vmaddr plus vmsize"); 296 if (s.reloff > FileSize) 297 return malformedError("reloff field of section " + Twine(J) + " in " + 298 CmdName + " command " + Twine(LoadCommandIndex) + 299 " extends past the end of the file"); 300 BigSize = s.nreloc; 301 BigSize *= sizeof(struct MachO::relocation_info); 302 BigSize += s.reloff; 303 if (BigSize > FileSize) 304 return malformedError("reloff field plus nreloc field times sizeof(" 305 "struct relocation_info) of section " + 306 Twine(J) + " in " + CmdName + " command " + 307 Twine(LoadCommandIndex) + 308 " extends past the end of the file"); 309 } 310 if (S.fileoff > FileSize) 311 return malformedError("load command " + Twine(LoadCommandIndex) + 312 " fileoff field in " + CmdName + 313 " extends past the end of the file"); 314 uint64_t BigSize = S.fileoff; 315 BigSize += S.filesize; 316 if (BigSize > FileSize) 317 return malformedError("load command " + Twine(LoadCommandIndex) + 318 " fileoff field plus filesize field in " + 319 CmdName + " extends past the end of the file"); 320 if (S.vmsize != 0 && S.filesize > S.vmsize) 321 return malformedError("load command " + Twine(LoadCommandIndex) + 322 " fileoff field in " + CmdName + 323 " greater than vmsize field"); 324 IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname); 325 } else 326 return SegOrErr.takeError(); 327 328 return Error::success(); 329 } 330 331 static Error checkSymtabCommand(const MachOObjectFile *Obj, 332 const MachOObjectFile::LoadCommandInfo &Load, 333 uint32_t LoadCommandIndex, 334 const char **SymtabLoadCmd) { 335 if (Load.C.cmdsize < sizeof(MachO::symtab_command)) 336 return malformedError("load command " + Twine(LoadCommandIndex) + 337 " LC_SYMTAB cmdsize too small"); 338 if (*SymtabLoadCmd != nullptr) 339 return malformedError("more than one LC_SYMTAB command"); 340 MachO::symtab_command Symtab = 341 getStruct<MachO::symtab_command>(Obj, Load.Ptr); 342 if (Symtab.cmdsize != sizeof(MachO::symtab_command)) 343 return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) + 344 " has incorrect cmdsize"); 345 uint64_t FileSize = Obj->getData().size(); 346 if (Symtab.symoff > FileSize) 347 return malformedError("symoff field of LC_SYMTAB command " + 348 Twine(LoadCommandIndex) + " extends past the end " 349 "of the file"); 350 uint64_t BigSize = Symtab.nsyms; 351 const char *struct_nlist_name; 352 if (Obj->is64Bit()) { 353 BigSize *= sizeof(MachO::nlist_64); 354 struct_nlist_name = "struct nlist_64"; 355 } else { 356 BigSize *= sizeof(MachO::nlist); 357 struct_nlist_name = "struct nlist"; 358 } 359 BigSize += Symtab.symoff; 360 if (BigSize > FileSize) 361 return malformedError("symoff field plus nsyms field times sizeof(" + 362 Twine(struct_nlist_name) + ") of LC_SYMTAB command " + 363 Twine(LoadCommandIndex) + " extends past the end " 364 "of the file"); 365 if (Symtab.stroff > FileSize) 366 return malformedError("stroff field of LC_SYMTAB command " + 367 Twine(LoadCommandIndex) + " extends past the end " 368 "of the file"); 369 BigSize = Symtab.stroff; 370 BigSize += Symtab.strsize; 371 if (BigSize > FileSize) 372 return malformedError("stroff field plus strsize field of LC_SYMTAB " 373 "command " + Twine(LoadCommandIndex) + " extends " 374 "past the end of the file"); 375 *SymtabLoadCmd = Load.Ptr; 376 return Error::success(); 377 } 378 379 static Error checkDysymtabCommand(const MachOObjectFile *Obj, 380 const MachOObjectFile::LoadCommandInfo &Load, 381 uint32_t LoadCommandIndex, 382 const char **DysymtabLoadCmd) { 383 if (Load.C.cmdsize < sizeof(MachO::dysymtab_command)) 384 return malformedError("load command " + Twine(LoadCommandIndex) + 385 " LC_DYSYMTAB cmdsize too small"); 386 if (*DysymtabLoadCmd != nullptr) 387 return malformedError("more than one LC_DYSYMTAB command"); 388 MachO::dysymtab_command Dysymtab = 389 getStruct<MachO::dysymtab_command>(Obj, Load.Ptr); 390 if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command)) 391 return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) + 392 " has incorrect cmdsize"); 393 uint64_t FileSize = Obj->getData().size(); 394 if (Dysymtab.tocoff > FileSize) 395 return malformedError("tocoff field of LC_DYSYMTAB command " + 396 Twine(LoadCommandIndex) + " extends past the end of " 397 "the file"); 398 uint64_t BigSize = Dysymtab.ntoc; 399 BigSize *= sizeof(MachO::dylib_table_of_contents); 400 BigSize += Dysymtab.tocoff; 401 if (BigSize > FileSize) 402 return malformedError("tocoff field plus ntoc field times sizeof(struct " 403 "dylib_table_of_contents) of LC_DYSYMTAB command " + 404 Twine(LoadCommandIndex) + " extends past the end of " 405 "the file"); 406 if (Dysymtab.modtaboff > FileSize) 407 return malformedError("modtaboff field of LC_DYSYMTAB command " + 408 Twine(LoadCommandIndex) + " extends past the end of " 409 "the file"); 410 BigSize = Dysymtab.nmodtab; 411 const char *struct_dylib_module_name; 412 if (Obj->is64Bit()) { 413 BigSize *= sizeof(MachO::dylib_module_64); 414 struct_dylib_module_name = "struct dylib_module_64"; 415 } else { 416 BigSize *= sizeof(MachO::dylib_module); 417 struct_dylib_module_name = "struct dylib_module"; 418 } 419 BigSize += Dysymtab.modtaboff; 420 if (BigSize > FileSize) 421 return malformedError("modtaboff field plus nmodtab field times sizeof(" + 422 Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB " 423 "command " + Twine(LoadCommandIndex) + " extends " 424 "past the end of the file"); 425 if (Dysymtab.extrefsymoff > FileSize) 426 return malformedError("extrefsymoff field of LC_DYSYMTAB command " + 427 Twine(LoadCommandIndex) + " extends past the end of " 428 "the file"); 429 BigSize = Dysymtab.nextrefsyms; 430 BigSize *= sizeof(MachO::dylib_reference); 431 BigSize += Dysymtab.extrefsymoff; 432 if (BigSize > FileSize) 433 return malformedError("extrefsymoff field plus nextrefsyms field times " 434 "sizeof(struct dylib_reference) of LC_DYSYMTAB " 435 "command " + Twine(LoadCommandIndex) + " extends " 436 "past the end of the file"); 437 if (Dysymtab.indirectsymoff > FileSize) 438 return malformedError("indirectsymoff field of LC_DYSYMTAB command " + 439 Twine(LoadCommandIndex) + " extends past the end of " 440 "the file"); 441 BigSize = Dysymtab.nindirectsyms; 442 BigSize *= sizeof(uint32_t); 443 BigSize += Dysymtab.indirectsymoff; 444 if (BigSize > FileSize) 445 return malformedError("indirectsymoff field plus nindirectsyms field times " 446 "sizeof(uint32_t) of LC_DYSYMTAB command " + 447 Twine(LoadCommandIndex) + " extends past the end of " 448 "the file"); 449 if (Dysymtab.extreloff > FileSize) 450 return malformedError("extreloff field of LC_DYSYMTAB command " + 451 Twine(LoadCommandIndex) + " extends past the end of " 452 "the file"); 453 BigSize = Dysymtab.nextrel; 454 BigSize *= sizeof(MachO::relocation_info); 455 BigSize += Dysymtab.extreloff; 456 if (BigSize > FileSize) 457 return malformedError("extreloff field plus nextrel field times sizeof" 458 "(struct relocation_info) of LC_DYSYMTAB command " + 459 Twine(LoadCommandIndex) + " extends past the end of " 460 "the file"); 461 if (Dysymtab.locreloff > FileSize) 462 return malformedError("locreloff field of LC_DYSYMTAB command " + 463 Twine(LoadCommandIndex) + " extends past the end of " 464 "the file"); 465 BigSize = Dysymtab.nlocrel; 466 BigSize *= sizeof(MachO::relocation_info); 467 BigSize += Dysymtab.locreloff; 468 if (BigSize > FileSize) 469 return malformedError("locreloff field plus nlocrel field times sizeof" 470 "(struct relocation_info) of LC_DYSYMTAB command " + 471 Twine(LoadCommandIndex) + " extends past the end of " 472 "the file"); 473 *DysymtabLoadCmd = Load.Ptr; 474 return Error::success(); 475 } 476 477 static Error checkLinkeditDataCommand(const MachOObjectFile *Obj, 478 const MachOObjectFile::LoadCommandInfo &Load, 479 uint32_t LoadCommandIndex, 480 const char **LoadCmd, const char *CmdName) { 481 if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command)) 482 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 483 CmdName + " cmdsize too small"); 484 if (*LoadCmd != nullptr) 485 return malformedError("more than one " + Twine(CmdName) + " command"); 486 MachO::linkedit_data_command LinkData = 487 getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr); 488 if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command)) 489 return malformedError(Twine(CmdName) + " command " + 490 Twine(LoadCommandIndex) + " has incorrect cmdsize"); 491 uint64_t FileSize = Obj->getData().size(); 492 if (LinkData.dataoff > FileSize) 493 return malformedError("dataoff field of " + Twine(CmdName) + " command " + 494 Twine(LoadCommandIndex) + " extends past the end of " 495 "the file"); 496 uint64_t BigSize = LinkData.dataoff; 497 BigSize += LinkData.datasize; 498 if (BigSize > FileSize) 499 return malformedError("dataoff field plus datasize field of " + 500 Twine(CmdName) + " command " + 501 Twine(LoadCommandIndex) + " extends past the end of " 502 "the file"); 503 *LoadCmd = Load.Ptr; 504 return Error::success(); 505 } 506 507 static Error checkDyldInfoCommand(const MachOObjectFile *Obj, 508 const MachOObjectFile::LoadCommandInfo &Load, 509 uint32_t LoadCommandIndex, 510 const char **LoadCmd, const char *CmdName) { 511 if (Load.C.cmdsize < sizeof(MachO::dyld_info_command)) 512 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 513 CmdName + " cmdsize too small"); 514 if (*LoadCmd != nullptr) 515 return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY " 516 "command"); 517 MachO::dyld_info_command DyldInfo = 518 getStruct<MachO::dyld_info_command>(Obj, Load.Ptr); 519 if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command)) 520 return malformedError(Twine(CmdName) + " command " + 521 Twine(LoadCommandIndex) + " has incorrect cmdsize"); 522 uint64_t FileSize = Obj->getData().size(); 523 if (DyldInfo.rebase_off > FileSize) 524 return malformedError("rebase_off field of " + Twine(CmdName) + 525 " command " + Twine(LoadCommandIndex) + " extends " 526 "past the end of the file"); 527 uint64_t BigSize = DyldInfo.rebase_off; 528 BigSize += DyldInfo.rebase_size; 529 if (BigSize > FileSize) 530 return malformedError("rebase_off field plus rebase_size field of " + 531 Twine(CmdName) + " command " + 532 Twine(LoadCommandIndex) + " extends past the end of " 533 "the file"); 534 if (DyldInfo.bind_off > FileSize) 535 return malformedError("bind_off field of " + Twine(CmdName) + 536 " command " + Twine(LoadCommandIndex) + " extends " 537 "past the end of the file"); 538 BigSize = DyldInfo.bind_off; 539 BigSize += DyldInfo.bind_size; 540 if (BigSize > FileSize) 541 return malformedError("bind_off field plus bind_size field of " + 542 Twine(CmdName) + " command " + 543 Twine(LoadCommandIndex) + " extends past the end of " 544 "the file"); 545 if (DyldInfo.weak_bind_off > FileSize) 546 return malformedError("weak_bind_off field of " + Twine(CmdName) + 547 " command " + Twine(LoadCommandIndex) + " extends " 548 "past the end of the file"); 549 BigSize = DyldInfo.weak_bind_off; 550 BigSize += DyldInfo.weak_bind_size; 551 if (BigSize > FileSize) 552 return malformedError("weak_bind_off field plus weak_bind_size field of " + 553 Twine(CmdName) + " command " + 554 Twine(LoadCommandIndex) + " extends past the end of " 555 "the file"); 556 if (DyldInfo.lazy_bind_off > FileSize) 557 return malformedError("lazy_bind_off field of " + Twine(CmdName) + 558 " command " + Twine(LoadCommandIndex) + " extends " 559 "past the end of the file"); 560 BigSize = DyldInfo.lazy_bind_off; 561 BigSize += DyldInfo.lazy_bind_size; 562 if (BigSize > FileSize) 563 return malformedError("lazy_bind_off field plus lazy_bind_size field of " + 564 Twine(CmdName) + " command " + 565 Twine(LoadCommandIndex) + " extends past the end of " 566 "the file"); 567 if (DyldInfo.export_off > FileSize) 568 return malformedError("export_off field of " + Twine(CmdName) + 569 " command " + Twine(LoadCommandIndex) + " extends " 570 "past the end of the file"); 571 BigSize = DyldInfo.export_off; 572 BigSize += DyldInfo.export_size; 573 if (BigSize > FileSize) 574 return malformedError("export_off field plus export_size field of " + 575 Twine(CmdName) + " command " + 576 Twine(LoadCommandIndex) + " extends past the end of " 577 "the file"); 578 *LoadCmd = Load.Ptr; 579 return Error::success(); 580 } 581 582 static Error checkDylibCommand(const MachOObjectFile *Obj, 583 const MachOObjectFile::LoadCommandInfo &Load, 584 uint32_t LoadCommandIndex, const char *CmdName) { 585 if (Load.C.cmdsize < sizeof(MachO::dylib_command)) 586 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 587 CmdName + " cmdsize too small"); 588 MachO::dylib_command D = getStruct<MachO::dylib_command>(Obj, Load.Ptr); 589 if (D.dylib.name < sizeof(MachO::dylib_command)) 590 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 591 CmdName + " name.offset field too small, not past " 592 "the end of the dylib_command struct"); 593 if (D.dylib.name >= D.cmdsize) 594 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 595 CmdName + " name.offset field extends past the end " 596 "of the load command"); 597 // Make sure there is a null between the starting offset of the name and 598 // the end of the load command. 599 uint32_t i; 600 const char *P = (const char *)Load.Ptr; 601 for (i = D.dylib.name; i < D.cmdsize; i++) 602 if (P[i] == '\0') 603 break; 604 if (i >= D.cmdsize) 605 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 606 CmdName + " library name extends past the end of the " 607 "load command"); 608 return Error::success(); 609 } 610 611 static Error checkDylibIdCommand(const MachOObjectFile *Obj, 612 const MachOObjectFile::LoadCommandInfo &Load, 613 uint32_t LoadCommandIndex, 614 const char **LoadCmd) { 615 if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex, 616 "LC_ID_DYLIB")) 617 return Err; 618 if (*LoadCmd != nullptr) 619 return malformedError("more than one LC_ID_DYLIB command"); 620 if (Obj->getHeader().filetype != MachO::MH_DYLIB && 621 Obj->getHeader().filetype != MachO::MH_DYLIB_STUB) 622 return malformedError("LC_ID_DYLIB load command in non-dynamic library " 623 "file type"); 624 *LoadCmd = Load.Ptr; 625 return Error::success(); 626 } 627 628 static Error checkDyldCommand(const MachOObjectFile *Obj, 629 const MachOObjectFile::LoadCommandInfo &Load, 630 uint32_t LoadCommandIndex, const char *CmdName) { 631 if (Load.C.cmdsize < sizeof(MachO::dylinker_command)) 632 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 633 CmdName + " cmdsize too small"); 634 MachO::dylinker_command D = getStruct<MachO::dylinker_command>(Obj, Load.Ptr); 635 if (D.name < sizeof(MachO::dylinker_command)) 636 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 637 CmdName + " name.offset field too small, not past " 638 "the end of the dylinker_command struct"); 639 if (D.name >= D.cmdsize) 640 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 641 CmdName + " name.offset field extends past the end " 642 "of the load command"); 643 // Make sure there is a null between the starting offset of the name and 644 // the end of the load command. 645 uint32_t i; 646 const char *P = (const char *)Load.Ptr; 647 for (i = D.name; i < D.cmdsize; i++) 648 if (P[i] == '\0') 649 break; 650 if (i >= D.cmdsize) 651 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 652 CmdName + " dyld name extends past the end of the " 653 "load command"); 654 return Error::success(); 655 } 656 657 static Error checkVersCommand(const MachOObjectFile *Obj, 658 const MachOObjectFile::LoadCommandInfo &Load, 659 uint32_t LoadCommandIndex, 660 const char **LoadCmd, const char *CmdName) { 661 if (Load.C.cmdsize != sizeof(MachO::version_min_command)) 662 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 663 CmdName + " has incorrect cmdsize"); 664 if (*LoadCmd != nullptr) 665 return malformedError("more than one LC_VERSION_MIN_MACOSX, " 666 "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or " 667 "LC_VERSION_MIN_WATCHOS command"); 668 *LoadCmd = Load.Ptr; 669 return Error::success(); 670 } 671 672 static Error checkRpathCommand(const MachOObjectFile *Obj, 673 const MachOObjectFile::LoadCommandInfo &Load, 674 uint32_t LoadCommandIndex) { 675 if (Load.C.cmdsize < sizeof(MachO::rpath_command)) 676 return malformedError("load command " + Twine(LoadCommandIndex) + 677 " LC_RPATH cmdsize too small"); 678 MachO::rpath_command R = getStruct<MachO::rpath_command>(Obj, Load.Ptr); 679 if (R.path < sizeof(MachO::rpath_command)) 680 return malformedError("load command " + Twine(LoadCommandIndex) + 681 " LC_RPATH path.offset field too small, not past " 682 "the end of the rpath_command struct"); 683 if (R.path >= R.cmdsize) 684 return malformedError("load command " + Twine(LoadCommandIndex) + 685 " LC_RPATH path.offset field extends past the end " 686 "of the load command"); 687 // Make sure there is a null between the starting offset of the path and 688 // the end of the load command. 689 uint32_t i; 690 const char *P = (const char *)Load.Ptr; 691 for (i = R.path; i < R.cmdsize; i++) 692 if (P[i] == '\0') 693 break; 694 if (i >= R.cmdsize) 695 return malformedError("load command " + Twine(LoadCommandIndex) + 696 " LC_RPATH library name extends past the end of the " 697 "load command"); 698 return Error::success(); 699 } 700 701 static Error checkEncryptCommand(const MachOObjectFile *Obj, 702 const MachOObjectFile::LoadCommandInfo &Load, 703 uint32_t LoadCommandIndex, 704 uint64_t cryptoff, uint64_t cryptsize, 705 const char **LoadCmd, const char *CmdName) { 706 if (*LoadCmd != nullptr) 707 return malformedError("more than one LC_ENCRYPTION_INFO and or " 708 "LC_ENCRYPTION_INFO_64 command"); 709 uint64_t FileSize = Obj->getData().size(); 710 if (cryptoff > FileSize) 711 return malformedError("cryptoff field of " + Twine(CmdName) + 712 " command " + Twine(LoadCommandIndex) + " extends " 713 "past the end of the file"); 714 uint64_t BigSize = cryptoff; 715 BigSize += cryptsize; 716 if (BigSize > FileSize) 717 return malformedError("cryptoff field plus cryptsize field of " + 718 Twine(CmdName) + " command " + 719 Twine(LoadCommandIndex) + " extends past the end of " 720 "the file"); 721 *LoadCmd = Load.Ptr; 722 return Error::success(); 723 } 724 725 static Error checkLinkerOptCommand(const MachOObjectFile *Obj, 726 const MachOObjectFile::LoadCommandInfo &Load, 727 uint32_t LoadCommandIndex) { 728 if (Load.C.cmdsize < sizeof(MachO::linker_option_command)) 729 return malformedError("load command " + Twine(LoadCommandIndex) + 730 " LC_LINKER_OPTION cmdsize too small"); 731 MachO::linker_option_command L = 732 getStruct<MachO::linker_option_command>(Obj, Load.Ptr); 733 // Make sure the count of strings is correct. 734 const char *string = (const char *)Load.Ptr + 735 sizeof(struct MachO::linker_option_command); 736 uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command); 737 uint32_t i = 0; 738 while (left > 0) { 739 while (*string == '\0' && left > 0) { 740 string++; 741 left--; 742 } 743 if (left > 0) { 744 i++; 745 uint32_t NullPos = StringRef(string, left).find('\0'); 746 uint32_t len = std::min(NullPos, left) + 1; 747 string += len; 748 left -= len; 749 } 750 } 751 if (L.count != i) 752 return malformedError("load command " + Twine(LoadCommandIndex) + 753 " LC_LINKER_OPTION string count " + Twine(L.count) + 754 " does not match number of strings"); 755 return Error::success(); 756 } 757 758 static Error checkSubCommand(const MachOObjectFile *Obj, 759 const MachOObjectFile::LoadCommandInfo &Load, 760 uint32_t LoadCommandIndex, const char *CmdName, 761 size_t SizeOfCmd, const char *CmdStructName, 762 uint32_t PathOffset, const char *PathFieldName) { 763 if (PathOffset < SizeOfCmd) 764 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 765 CmdName + " " + PathFieldName + ".offset field too " 766 "small, not past the end of the " + CmdStructName); 767 if (PathOffset >= Load.C.cmdsize) 768 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 769 CmdName + " " + PathFieldName + ".offset field " 770 "extends past the end of the load command"); 771 // Make sure there is a null between the starting offset of the path and 772 // the end of the load command. 773 uint32_t i; 774 const char *P = (const char *)Load.Ptr; 775 for (i = PathOffset; i < Load.C.cmdsize; i++) 776 if (P[i] == '\0') 777 break; 778 if (i >= Load.C.cmdsize) 779 return malformedError("load command " + Twine(LoadCommandIndex) + " " + 780 CmdName + " " + PathFieldName + " name extends past " 781 "the end of the load command"); 782 return Error::success(); 783 } 784 785 Expected<std::unique_ptr<MachOObjectFile>> 786 MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian, 787 bool Is64Bits) { 788 Error Err; 789 std::unique_ptr<MachOObjectFile> Obj( 790 new MachOObjectFile(std::move(Object), IsLittleEndian, 791 Is64Bits, Err)); 792 if (Err) 793 return std::move(Err); 794 return std::move(Obj); 795 } 796 797 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 798 bool Is64bits, Error &Err) 799 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 800 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 801 DataInCodeLoadCmd(nullptr), LinkOptHintsLoadCmd(nullptr), 802 DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr), 803 HasPageZeroSegment(false) { 804 ErrorAsOutParameter ErrAsOutParam(&Err); 805 uint64_t SizeOfHeaders; 806 if (is64Bit()) { 807 parseHeader(this, Header64, Err); 808 SizeOfHeaders = sizeof(MachO::mach_header_64); 809 } else { 810 parseHeader(this, Header, Err); 811 SizeOfHeaders = sizeof(MachO::mach_header); 812 } 813 if (Err) 814 return; 815 SizeOfHeaders += getHeader().sizeofcmds; 816 if (getData().data() + SizeOfHeaders > getData().end()) { 817 Err = malformedError("load commands extend past the end of the file"); 818 return; 819 } 820 821 uint32_t LoadCommandCount = getHeader().ncmds; 822 LoadCommandInfo Load; 823 if (LoadCommandCount != 0) { 824 if (auto LoadOrErr = getFirstLoadCommandInfo(this)) 825 Load = *LoadOrErr; 826 else { 827 Err = LoadOrErr.takeError(); 828 return; 829 } 830 } 831 832 const char *DyldIdLoadCmd = nullptr; 833 const char *FuncStartsLoadCmd = nullptr; 834 const char *SplitInfoLoadCmd = nullptr; 835 const char *CodeSignDrsLoadCmd = nullptr; 836 const char *CodeSignLoadCmd = nullptr; 837 const char *VersLoadCmd = nullptr; 838 const char *SourceLoadCmd = nullptr; 839 const char *EntryPointLoadCmd = nullptr; 840 const char *EncryptLoadCmd = nullptr; 841 const char *RoutinesLoadCmd = nullptr; 842 for (unsigned I = 0; I < LoadCommandCount; ++I) { 843 if (is64Bit()) { 844 if (Load.C.cmdsize % 8 != 0) { 845 // We have a hack here to allow 64-bit Mach-O core files to have 846 // LC_THREAD commands that are only a multiple of 4 and not 8 to be 847 // allowed since the macOS kernel produces them. 848 if (getHeader().filetype != MachO::MH_CORE || 849 Load.C.cmd != MachO::LC_THREAD || Load.C.cmdsize % 4) { 850 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 851 "multiple of 8"); 852 return; 853 } 854 } 855 } else { 856 if (Load.C.cmdsize % 4 != 0) { 857 Err = malformedError("load command " + Twine(I) + " cmdsize not a " 858 "multiple of 4"); 859 return; 860 } 861 } 862 LoadCommands.push_back(Load); 863 if (Load.C.cmd == MachO::LC_SYMTAB) { 864 if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd))) 865 return; 866 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 867 if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd))) 868 return; 869 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 870 if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd, 871 "LC_DATA_IN_CODE"))) 872 return; 873 } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) { 874 if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd, 875 "LC_LINKER_OPTIMIZATION_HINT"))) 876 return; 877 } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) { 878 if ((Err = checkLinkeditDataCommand(this, Load, I, &FuncStartsLoadCmd, 879 "LC_FUNCTION_STARTS"))) 880 return; 881 } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) { 882 if ((Err = checkLinkeditDataCommand(this, Load, I, &SplitInfoLoadCmd, 883 "LC_SEGMENT_SPLIT_INFO"))) 884 return; 885 } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) { 886 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignDrsLoadCmd, 887 "LC_DYLIB_CODE_SIGN_DRS"))) 888 return; 889 } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) { 890 if ((Err = checkLinkeditDataCommand(this, Load, I, &CodeSignLoadCmd, 891 "LC_CODE_SIGNATURE"))) 892 return; 893 } else if (Load.C.cmd == MachO::LC_DYLD_INFO) { 894 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 895 "LC_DYLD_INFO"))) 896 return; 897 } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 898 if ((Err = checkDyldInfoCommand(this, Load, I, &DyldInfoLoadCmd, 899 "LC_DYLD_INFO_ONLY"))) 900 return; 901 } else if (Load.C.cmd == MachO::LC_UUID) { 902 if (Load.C.cmdsize != sizeof(MachO::uuid_command)) { 903 Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect " 904 "cmdsize"); 905 return; 906 } 907 if (UuidLoadCmd) { 908 Err = malformedError("more than one LC_UUID command"); 909 return; 910 } 911 UuidLoadCmd = Load.Ptr; 912 } else if (Load.C.cmd == MachO::LC_SEGMENT_64) { 913 if ((Err = parseSegmentLoadCommand<MachO::segment_command_64, 914 MachO::section_64>( 915 this, Load, Sections, HasPageZeroSegment, I, 916 "LC_SEGMENT_64", SizeOfHeaders))) 917 return; 918 } else if (Load.C.cmd == MachO::LC_SEGMENT) { 919 if ((Err = parseSegmentLoadCommand<MachO::segment_command, 920 MachO::section>( 921 this, Load, Sections, HasPageZeroSegment, I, 922 "LC_SEGMENT", SizeOfHeaders))) 923 return; 924 } else if (Load.C.cmd == MachO::LC_ID_DYLIB) { 925 if ((Err = checkDylibIdCommand(this, Load, I, &DyldIdLoadCmd))) 926 return; 927 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) { 928 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_DYLIB"))) 929 return; 930 Libraries.push_back(Load.Ptr); 931 } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) { 932 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_WEAK_DYLIB"))) 933 return; 934 Libraries.push_back(Load.Ptr); 935 } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) { 936 if ((Err = checkDylibCommand(this, Load, I, "LC_LAZY_LOAD_DYLIB"))) 937 return; 938 Libraries.push_back(Load.Ptr); 939 } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) { 940 if ((Err = checkDylibCommand(this, Load, I, "LC_REEXPORT_DYLIB"))) 941 return; 942 Libraries.push_back(Load.Ptr); 943 } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 944 if ((Err = checkDylibCommand(this, Load, I, "LC_LOAD_UPWARD_DYLIB"))) 945 return; 946 Libraries.push_back(Load.Ptr); 947 } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) { 948 if ((Err = checkDyldCommand(this, Load, I, "LC_ID_DYLINKER"))) 949 return; 950 } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) { 951 if ((Err = checkDyldCommand(this, Load, I, "LC_LOAD_DYLINKER"))) 952 return; 953 } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) { 954 if ((Err = checkDyldCommand(this, Load, I, "LC_DYLD_ENVIRONMENT"))) 955 return; 956 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) { 957 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 958 "LC_VERSION_MIN_MACOSX"))) 959 return; 960 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) { 961 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 962 "LC_VERSION_MIN_IPHONEOS"))) 963 return; 964 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) { 965 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 966 "LC_VERSION_MIN_TVOS"))) 967 return; 968 } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) { 969 if ((Err = checkVersCommand(this, Load, I, &VersLoadCmd, 970 "LC_VERSION_MIN_WATCHOS"))) 971 return; 972 } else if (Load.C.cmd == MachO::LC_RPATH) { 973 if ((Err = checkRpathCommand(this, Load, I))) 974 return; 975 } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) { 976 if (Load.C.cmdsize != sizeof(MachO::source_version_command)) { 977 Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) + 978 " has incorrect cmdsize"); 979 return; 980 } 981 if (SourceLoadCmd) { 982 Err = malformedError("more than one LC_SOURCE_VERSION command"); 983 return; 984 } 985 SourceLoadCmd = Load.Ptr; 986 } else if (Load.C.cmd == MachO::LC_MAIN) { 987 if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) { 988 Err = malformedError("LC_MAIN command " + Twine(I) + 989 " has incorrect cmdsize"); 990 return; 991 } 992 if (EntryPointLoadCmd) { 993 Err = malformedError("more than one LC_MAIN command"); 994 return; 995 } 996 EntryPointLoadCmd = Load.Ptr; 997 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO) { 998 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) { 999 Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) + 1000 " has incorrect cmdsize"); 1001 return; 1002 } 1003 MachO::encryption_info_command E = 1004 getStruct<MachO::encryption_info_command>(this, Load.Ptr); 1005 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1006 &EncryptLoadCmd, "LC_ENCRYPTION_INFO"))) 1007 return; 1008 } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) { 1009 if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) { 1010 Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) + 1011 " has incorrect cmdsize"); 1012 return; 1013 } 1014 MachO::encryption_info_command_64 E = 1015 getStruct<MachO::encryption_info_command_64>(this, Load.Ptr); 1016 if ((Err = checkEncryptCommand(this, Load, I, E.cryptoff, E.cryptsize, 1017 &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64"))) 1018 return; 1019 } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) { 1020 if ((Err = checkLinkerOptCommand(this, Load, I))) 1021 return; 1022 } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) { 1023 if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) { 1024 Err = malformedError("load command " + Twine(I) + 1025 " LC_SUB_FRAMEWORK cmdsize too small"); 1026 return; 1027 } 1028 MachO::sub_framework_command S = 1029 getStruct<MachO::sub_framework_command>(this, Load.Ptr); 1030 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_FRAMEWORK", 1031 sizeof(MachO::sub_framework_command), 1032 "sub_framework_command", S.umbrella, 1033 "umbrella"))) 1034 return; 1035 } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) { 1036 if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) { 1037 Err = malformedError("load command " + Twine(I) + 1038 " LC_SUB_UMBRELLA cmdsize too small"); 1039 return; 1040 } 1041 MachO::sub_umbrella_command S = 1042 getStruct<MachO::sub_umbrella_command>(this, Load.Ptr); 1043 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_UMBRELLA", 1044 sizeof(MachO::sub_umbrella_command), 1045 "sub_umbrella_command", S.sub_umbrella, 1046 "sub_umbrella"))) 1047 return; 1048 } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) { 1049 if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) { 1050 Err = malformedError("load command " + Twine(I) + 1051 " LC_SUB_LIBRARY cmdsize too small"); 1052 return; 1053 } 1054 MachO::sub_library_command S = 1055 getStruct<MachO::sub_library_command>(this, Load.Ptr); 1056 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_LIBRARY", 1057 sizeof(MachO::sub_library_command), 1058 "sub_library_command", S.sub_library, 1059 "sub_library"))) 1060 return; 1061 } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) { 1062 if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) { 1063 Err = malformedError("load command " + Twine(I) + 1064 " LC_SUB_CLIENT cmdsize too small"); 1065 return; 1066 } 1067 MachO::sub_client_command S = 1068 getStruct<MachO::sub_client_command>(this, Load.Ptr); 1069 if ((Err = checkSubCommand(this, Load, I, "LC_SUB_CLIENT", 1070 sizeof(MachO::sub_client_command), 1071 "sub_client_command", S.client, "client"))) 1072 return; 1073 } else if (Load.C.cmd == MachO::LC_ROUTINES) { 1074 if (Load.C.cmdsize != sizeof(MachO::routines_command)) { 1075 Err = malformedError("LC_ROUTINES command " + Twine(I) + 1076 " has incorrect cmdsize"); 1077 return; 1078 } 1079 if (RoutinesLoadCmd) { 1080 Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 " 1081 "command"); 1082 return; 1083 } 1084 RoutinesLoadCmd = Load.Ptr; 1085 } else if (Load.C.cmd == MachO::LC_ROUTINES_64) { 1086 if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) { 1087 Err = malformedError("LC_ROUTINES_64 command " + Twine(I) + 1088 " has incorrect cmdsize"); 1089 return; 1090 } 1091 if (RoutinesLoadCmd) { 1092 Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES " 1093 "command"); 1094 return; 1095 } 1096 RoutinesLoadCmd = Load.Ptr; 1097 } 1098 if (I < LoadCommandCount - 1) { 1099 if (auto LoadOrErr = getNextLoadCommandInfo(this, I, Load)) 1100 Load = *LoadOrErr; 1101 else { 1102 Err = LoadOrErr.takeError(); 1103 return; 1104 } 1105 } 1106 } 1107 if (!SymtabLoadCmd) { 1108 if (DysymtabLoadCmd) { 1109 Err = malformedError("contains LC_DYSYMTAB load command without a " 1110 "LC_SYMTAB load command"); 1111 return; 1112 } 1113 } else if (DysymtabLoadCmd) { 1114 MachO::symtab_command Symtab = 1115 getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 1116 MachO::dysymtab_command Dysymtab = 1117 getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 1118 if (Dysymtab.nlocalsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1119 Err = malformedError("ilocalsym in LC_DYSYMTAB load command " 1120 "extends past the end of the symbol table"); 1121 return; 1122 } 1123 uint64_t BigSize = Dysymtab.ilocalsym; 1124 BigSize += Dysymtab.nlocalsym; 1125 if (Dysymtab.nlocalsym != 0 && BigSize > Symtab.nsyms) { 1126 Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load " 1127 "command extends past the end of the symbol table"); 1128 return; 1129 } 1130 if (Dysymtab.nextdefsym != 0 && Dysymtab.ilocalsym > Symtab.nsyms) { 1131 Err = malformedError("nextdefsym in LC_DYSYMTAB load command " 1132 "extends past the end of the symbol table"); 1133 return; 1134 } 1135 BigSize = Dysymtab.iextdefsym; 1136 BigSize += Dysymtab.nextdefsym; 1137 if (Dysymtab.nextdefsym != 0 && BigSize > Symtab.nsyms) { 1138 Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB " 1139 "load command extends past the end of the symbol " 1140 "table"); 1141 return; 1142 } 1143 if (Dysymtab.nundefsym != 0 && Dysymtab.iundefsym > Symtab.nsyms) { 1144 Err = malformedError("nundefsym in LC_DYSYMTAB load command " 1145 "extends past the end of the symbol table"); 1146 return; 1147 } 1148 BigSize = Dysymtab.iundefsym; 1149 BigSize += Dysymtab.nundefsym; 1150 if (Dysymtab.nundefsym != 0 && BigSize > Symtab.nsyms) { 1151 Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load " 1152 " command extends past the end of the symbol table"); 1153 return; 1154 } 1155 } 1156 if ((getHeader().filetype == MachO::MH_DYLIB || 1157 getHeader().filetype == MachO::MH_DYLIB_STUB) && 1158 DyldIdLoadCmd == nullptr) { 1159 Err = malformedError("no LC_ID_DYLIB load command in dynamic library " 1160 "filetype"); 1161 return; 1162 } 1163 assert(LoadCommands.size() == LoadCommandCount); 1164 1165 Err = Error::success(); 1166 } 1167 1168 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 1169 unsigned SymbolTableEntrySize = is64Bit() ? 1170 sizeof(MachO::nlist_64) : 1171 sizeof(MachO::nlist); 1172 Symb.p += SymbolTableEntrySize; 1173 } 1174 1175 Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const { 1176 StringRef StringTable = getStringTableData(); 1177 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1178 const char *Start = &StringTable.data()[Entry.n_strx]; 1179 if (Start < getData().begin() || Start >= getData().end()) { 1180 return malformedError("bad string index: " + Twine(Entry.n_strx) + 1181 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1182 } 1183 return StringRef(Start); 1184 } 1185 1186 unsigned MachOObjectFile::getSectionType(SectionRef Sec) const { 1187 DataRefImpl DRI = Sec.getRawDataRefImpl(); 1188 uint32_t Flags = getSectionFlags(this, DRI); 1189 return Flags & MachO::SECTION_TYPE; 1190 } 1191 1192 uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const { 1193 if (is64Bit()) { 1194 MachO::nlist_64 Entry = getSymbol64TableEntry(Sym); 1195 return Entry.n_value; 1196 } 1197 MachO::nlist Entry = getSymbolTableEntry(Sym); 1198 return Entry.n_value; 1199 } 1200 1201 // getIndirectName() returns the name of the alias'ed symbol who's string table 1202 // index is in the n_value field. 1203 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 1204 StringRef &Res) const { 1205 StringRef StringTable = getStringTableData(); 1206 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1207 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 1208 return object_error::parse_failed; 1209 uint64_t NValue = getNValue(Symb); 1210 if (NValue >= StringTable.size()) 1211 return object_error::parse_failed; 1212 const char *Start = &StringTable.data()[NValue]; 1213 Res = StringRef(Start); 1214 return std::error_code(); 1215 } 1216 1217 uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const { 1218 return getNValue(Sym); 1219 } 1220 1221 Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const { 1222 return getSymbolValue(Sym); 1223 } 1224 1225 uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const { 1226 uint32_t flags = getSymbolFlags(DRI); 1227 if (flags & SymbolRef::SF_Common) { 1228 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1229 return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 1230 } 1231 return 0; 1232 } 1233 1234 uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const { 1235 return getNValue(DRI); 1236 } 1237 1238 Expected<SymbolRef::Type> 1239 MachOObjectFile::getSymbolType(DataRefImpl Symb) const { 1240 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1241 uint8_t n_type = Entry.n_type; 1242 1243 // If this is a STAB debugging symbol, we can do nothing more. 1244 if (n_type & MachO::N_STAB) 1245 return SymbolRef::ST_Debug; 1246 1247 switch (n_type & MachO::N_TYPE) { 1248 case MachO::N_UNDF : 1249 return SymbolRef::ST_Unknown; 1250 case MachO::N_SECT : 1251 Expected<section_iterator> SecOrError = getSymbolSection(Symb); 1252 if (!SecOrError) 1253 return SecOrError.takeError(); 1254 section_iterator Sec = *SecOrError; 1255 if (Sec->isData() || Sec->isBSS()) 1256 return SymbolRef::ST_Data; 1257 return SymbolRef::ST_Function; 1258 } 1259 return SymbolRef::ST_Other; 1260 } 1261 1262 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 1263 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 1264 1265 uint8_t MachOType = Entry.n_type; 1266 uint16_t MachOFlags = Entry.n_desc; 1267 1268 uint32_t Result = SymbolRef::SF_None; 1269 1270 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 1271 Result |= SymbolRef::SF_Indirect; 1272 1273 if (MachOType & MachO::N_STAB) 1274 Result |= SymbolRef::SF_FormatSpecific; 1275 1276 if (MachOType & MachO::N_EXT) { 1277 Result |= SymbolRef::SF_Global; 1278 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 1279 if (getNValue(DRI)) 1280 Result |= SymbolRef::SF_Common; 1281 else 1282 Result |= SymbolRef::SF_Undefined; 1283 } 1284 1285 if (!(MachOType & MachO::N_PEXT)) 1286 Result |= SymbolRef::SF_Exported; 1287 } 1288 1289 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 1290 Result |= SymbolRef::SF_Weak; 1291 1292 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 1293 Result |= SymbolRef::SF_Thumb; 1294 1295 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 1296 Result |= SymbolRef::SF_Absolute; 1297 1298 return Result; 1299 } 1300 1301 Expected<section_iterator> 1302 MachOObjectFile::getSymbolSection(DataRefImpl Symb) const { 1303 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 1304 uint8_t index = Entry.n_sect; 1305 1306 if (index == 0) 1307 return section_end(); 1308 DataRefImpl DRI; 1309 DRI.d.a = index - 1; 1310 if (DRI.d.a >= Sections.size()){ 1311 return malformedError("bad section index: " + Twine((int)index) + 1312 " for symbol at index " + Twine(getSymbolIndex(Symb))); 1313 } 1314 return section_iterator(SectionRef(DRI, this)); 1315 } 1316 1317 unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const { 1318 MachO::nlist_base Entry = 1319 getSymbolTableEntryBase(this, Sym.getRawDataRefImpl()); 1320 return Entry.n_sect - 1; 1321 } 1322 1323 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 1324 Sec.d.a++; 1325 } 1326 1327 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 1328 StringRef &Result) const { 1329 ArrayRef<char> Raw = getSectionRawName(Sec); 1330 Result = parseSegmentOrSectionName(Raw.data()); 1331 return std::error_code(); 1332 } 1333 1334 uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const { 1335 if (is64Bit()) 1336 return getSection64(Sec).addr; 1337 return getSection(Sec).addr; 1338 } 1339 1340 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const { 1341 // In the case if a malformed Mach-O file where the section offset is past 1342 // the end of the file or some part of the section size is past the end of 1343 // the file return a size of zero or a size that covers the rest of the file 1344 // but does not extend past the end of the file. 1345 uint32_t SectOffset, SectType; 1346 uint64_t SectSize; 1347 1348 if (is64Bit()) { 1349 MachO::section_64 Sect = getSection64(Sec); 1350 SectOffset = Sect.offset; 1351 SectSize = Sect.size; 1352 SectType = Sect.flags & MachO::SECTION_TYPE; 1353 } else { 1354 MachO::section Sect = getSection(Sec); 1355 SectOffset = Sect.offset; 1356 SectSize = Sect.size; 1357 SectType = Sect.flags & MachO::SECTION_TYPE; 1358 } 1359 if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL) 1360 return SectSize; 1361 uint64_t FileSize = getData().size(); 1362 if (SectOffset > FileSize) 1363 return 0; 1364 if (FileSize - SectOffset < SectSize) 1365 return FileSize - SectOffset; 1366 return SectSize; 1367 } 1368 1369 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 1370 StringRef &Res) const { 1371 uint32_t Offset; 1372 uint64_t Size; 1373 1374 if (is64Bit()) { 1375 MachO::section_64 Sect = getSection64(Sec); 1376 Offset = Sect.offset; 1377 Size = Sect.size; 1378 } else { 1379 MachO::section Sect = getSection(Sec); 1380 Offset = Sect.offset; 1381 Size = Sect.size; 1382 } 1383 1384 Res = this->getData().substr(Offset, Size); 1385 return std::error_code(); 1386 } 1387 1388 uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const { 1389 uint32_t Align; 1390 if (is64Bit()) { 1391 MachO::section_64 Sect = getSection64(Sec); 1392 Align = Sect.align; 1393 } else { 1394 MachO::section Sect = getSection(Sec); 1395 Align = Sect.align; 1396 } 1397 1398 return uint64_t(1) << Align; 1399 } 1400 1401 bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const { 1402 return false; 1403 } 1404 1405 bool MachOObjectFile::isSectionText(DataRefImpl Sec) const { 1406 uint32_t Flags = getSectionFlags(this, Sec); 1407 return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 1408 } 1409 1410 bool MachOObjectFile::isSectionData(DataRefImpl Sec) const { 1411 uint32_t Flags = getSectionFlags(this, Sec); 1412 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1413 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1414 !(SectionType == MachO::S_ZEROFILL || 1415 SectionType == MachO::S_GB_ZEROFILL); 1416 } 1417 1418 bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const { 1419 uint32_t Flags = getSectionFlags(this, Sec); 1420 unsigned SectionType = Flags & MachO::SECTION_TYPE; 1421 return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 1422 (SectionType == MachO::S_ZEROFILL || 1423 SectionType == MachO::S_GB_ZEROFILL); 1424 } 1425 1426 unsigned MachOObjectFile::getSectionID(SectionRef Sec) const { 1427 return Sec.getRawDataRefImpl().d.a; 1428 } 1429 1430 bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const { 1431 // FIXME: Unimplemented. 1432 return false; 1433 } 1434 1435 bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const { 1436 StringRef SegmentName = getSectionFinalSegmentName(Sec); 1437 StringRef SectName; 1438 if (!getSectionName(Sec, SectName)) 1439 return (SegmentName == "__LLVM" && SectName == "__bitcode"); 1440 return false; 1441 } 1442 1443 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 1444 DataRefImpl Ret; 1445 Ret.d.a = Sec.d.a; 1446 Ret.d.b = 0; 1447 return relocation_iterator(RelocationRef(Ret, this)); 1448 } 1449 1450 relocation_iterator 1451 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 1452 uint32_t Num; 1453 if (is64Bit()) { 1454 MachO::section_64 Sect = getSection64(Sec); 1455 Num = Sect.nreloc; 1456 } else { 1457 MachO::section Sect = getSection(Sec); 1458 Num = Sect.nreloc; 1459 } 1460 1461 DataRefImpl Ret; 1462 Ret.d.a = Sec.d.a; 1463 Ret.d.b = Num; 1464 return relocation_iterator(RelocationRef(Ret, this)); 1465 } 1466 1467 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 1468 ++Rel.d.b; 1469 } 1470 1471 uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const { 1472 assert(getHeader().filetype == MachO::MH_OBJECT && 1473 "Only implemented for MH_OBJECT"); 1474 MachO::any_relocation_info RE = getRelocation(Rel); 1475 return getAnyRelocationAddress(RE); 1476 } 1477 1478 symbol_iterator 1479 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 1480 MachO::any_relocation_info RE = getRelocation(Rel); 1481 if (isRelocationScattered(RE)) 1482 return symbol_end(); 1483 1484 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 1485 bool isExtern = getPlainRelocationExternal(RE); 1486 if (!isExtern) 1487 return symbol_end(); 1488 1489 MachO::symtab_command S = getSymtabLoadCommand(); 1490 unsigned SymbolTableEntrySize = is64Bit() ? 1491 sizeof(MachO::nlist_64) : 1492 sizeof(MachO::nlist); 1493 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 1494 DataRefImpl Sym; 1495 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1496 return symbol_iterator(SymbolRef(Sym, this)); 1497 } 1498 1499 section_iterator 1500 MachOObjectFile::getRelocationSection(DataRefImpl Rel) const { 1501 return section_iterator(getAnyRelocationSection(getRelocation(Rel))); 1502 } 1503 1504 uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const { 1505 MachO::any_relocation_info RE = getRelocation(Rel); 1506 return getAnyRelocationType(RE); 1507 } 1508 1509 void MachOObjectFile::getRelocationTypeName( 1510 DataRefImpl Rel, SmallVectorImpl<char> &Result) const { 1511 StringRef res; 1512 uint64_t RType = getRelocationType(Rel); 1513 1514 unsigned Arch = this->getArch(); 1515 1516 switch (Arch) { 1517 case Triple::x86: { 1518 static const char *const Table[] = { 1519 "GENERIC_RELOC_VANILLA", 1520 "GENERIC_RELOC_PAIR", 1521 "GENERIC_RELOC_SECTDIFF", 1522 "GENERIC_RELOC_PB_LA_PTR", 1523 "GENERIC_RELOC_LOCAL_SECTDIFF", 1524 "GENERIC_RELOC_TLV" }; 1525 1526 if (RType > 5) 1527 res = "Unknown"; 1528 else 1529 res = Table[RType]; 1530 break; 1531 } 1532 case Triple::x86_64: { 1533 static const char *const Table[] = { 1534 "X86_64_RELOC_UNSIGNED", 1535 "X86_64_RELOC_SIGNED", 1536 "X86_64_RELOC_BRANCH", 1537 "X86_64_RELOC_GOT_LOAD", 1538 "X86_64_RELOC_GOT", 1539 "X86_64_RELOC_SUBTRACTOR", 1540 "X86_64_RELOC_SIGNED_1", 1541 "X86_64_RELOC_SIGNED_2", 1542 "X86_64_RELOC_SIGNED_4", 1543 "X86_64_RELOC_TLV" }; 1544 1545 if (RType > 9) 1546 res = "Unknown"; 1547 else 1548 res = Table[RType]; 1549 break; 1550 } 1551 case Triple::arm: { 1552 static const char *const Table[] = { 1553 "ARM_RELOC_VANILLA", 1554 "ARM_RELOC_PAIR", 1555 "ARM_RELOC_SECTDIFF", 1556 "ARM_RELOC_LOCAL_SECTDIFF", 1557 "ARM_RELOC_PB_LA_PTR", 1558 "ARM_RELOC_BR24", 1559 "ARM_THUMB_RELOC_BR22", 1560 "ARM_THUMB_32BIT_BRANCH", 1561 "ARM_RELOC_HALF", 1562 "ARM_RELOC_HALF_SECTDIFF" }; 1563 1564 if (RType > 9) 1565 res = "Unknown"; 1566 else 1567 res = Table[RType]; 1568 break; 1569 } 1570 case Triple::aarch64: { 1571 static const char *const Table[] = { 1572 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 1573 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 1574 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 1575 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 1576 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 1577 "ARM64_RELOC_ADDEND" 1578 }; 1579 1580 if (RType >= array_lengthof(Table)) 1581 res = "Unknown"; 1582 else 1583 res = Table[RType]; 1584 break; 1585 } 1586 case Triple::ppc: { 1587 static const char *const Table[] = { 1588 "PPC_RELOC_VANILLA", 1589 "PPC_RELOC_PAIR", 1590 "PPC_RELOC_BR14", 1591 "PPC_RELOC_BR24", 1592 "PPC_RELOC_HI16", 1593 "PPC_RELOC_LO16", 1594 "PPC_RELOC_HA16", 1595 "PPC_RELOC_LO14", 1596 "PPC_RELOC_SECTDIFF", 1597 "PPC_RELOC_PB_LA_PTR", 1598 "PPC_RELOC_HI16_SECTDIFF", 1599 "PPC_RELOC_LO16_SECTDIFF", 1600 "PPC_RELOC_HA16_SECTDIFF", 1601 "PPC_RELOC_JBSR", 1602 "PPC_RELOC_LO14_SECTDIFF", 1603 "PPC_RELOC_LOCAL_SECTDIFF" }; 1604 1605 if (RType > 15) 1606 res = "Unknown"; 1607 else 1608 res = Table[RType]; 1609 break; 1610 } 1611 case Triple::UnknownArch: 1612 res = "Unknown"; 1613 break; 1614 } 1615 Result.append(res.begin(), res.end()); 1616 } 1617 1618 uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const { 1619 MachO::any_relocation_info RE = getRelocation(Rel); 1620 return getAnyRelocationLength(RE); 1621 } 1622 1623 // 1624 // guessLibraryShortName() is passed a name of a dynamic library and returns a 1625 // guess on what the short name is. Then name is returned as a substring of the 1626 // StringRef Name passed in. The name of the dynamic library is recognized as 1627 // a framework if it has one of the two following forms: 1628 // Foo.framework/Versions/A/Foo 1629 // Foo.framework/Foo 1630 // Where A and Foo can be any string. And may contain a trailing suffix 1631 // starting with an underbar. If the Name is recognized as a framework then 1632 // isFramework is set to true else it is set to false. If the Name has a 1633 // suffix then Suffix is set to the substring in Name that contains the suffix 1634 // else it is set to a NULL StringRef. 1635 // 1636 // The Name of the dynamic library is recognized as a library name if it has 1637 // one of the two following forms: 1638 // libFoo.A.dylib 1639 // libFoo.dylib 1640 // The library may have a suffix trailing the name Foo of the form: 1641 // libFoo_profile.A.dylib 1642 // libFoo_profile.dylib 1643 // 1644 // The Name of the dynamic library is also recognized as a library name if it 1645 // has the following form: 1646 // Foo.qtx 1647 // 1648 // If the Name of the dynamic library is none of the forms above then a NULL 1649 // StringRef is returned. 1650 // 1651 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 1652 bool &isFramework, 1653 StringRef &Suffix) { 1654 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 1655 size_t a, b, c, d, Idx; 1656 1657 isFramework = false; 1658 Suffix = StringRef(); 1659 1660 // Pull off the last component and make Foo point to it 1661 a = Name.rfind('/'); 1662 if (a == Name.npos || a == 0) 1663 goto guess_library; 1664 Foo = Name.slice(a+1, Name.npos); 1665 1666 // Look for a suffix starting with a '_' 1667 Idx = Foo.rfind('_'); 1668 if (Idx != Foo.npos && Foo.size() >= 2) { 1669 Suffix = Foo.slice(Idx, Foo.npos); 1670 Foo = Foo.slice(0, Idx); 1671 } 1672 1673 // First look for the form Foo.framework/Foo 1674 b = Name.rfind('/', a); 1675 if (b == Name.npos) 1676 Idx = 0; 1677 else 1678 Idx = b+1; 1679 F = Name.slice(Idx, Idx + Foo.size()); 1680 DotFramework = Name.slice(Idx + Foo.size(), 1681 Idx + Foo.size() + sizeof(".framework/")-1); 1682 if (F == Foo && DotFramework == ".framework/") { 1683 isFramework = true; 1684 return Foo; 1685 } 1686 1687 // Next look for the form Foo.framework/Versions/A/Foo 1688 if (b == Name.npos) 1689 goto guess_library; 1690 c = Name.rfind('/', b); 1691 if (c == Name.npos || c == 0) 1692 goto guess_library; 1693 V = Name.slice(c+1, Name.npos); 1694 if (!V.startswith("Versions/")) 1695 goto guess_library; 1696 d = Name.rfind('/', c); 1697 if (d == Name.npos) 1698 Idx = 0; 1699 else 1700 Idx = d+1; 1701 F = Name.slice(Idx, Idx + Foo.size()); 1702 DotFramework = Name.slice(Idx + Foo.size(), 1703 Idx + Foo.size() + sizeof(".framework/")-1); 1704 if (F == Foo && DotFramework == ".framework/") { 1705 isFramework = true; 1706 return Foo; 1707 } 1708 1709 guess_library: 1710 // pull off the suffix after the "." and make a point to it 1711 a = Name.rfind('.'); 1712 if (a == Name.npos || a == 0) 1713 return StringRef(); 1714 Dylib = Name.slice(a, Name.npos); 1715 if (Dylib != ".dylib") 1716 goto guess_qtx; 1717 1718 // First pull off the version letter for the form Foo.A.dylib if any. 1719 if (a >= 3) { 1720 Dot = Name.slice(a-2, a-1); 1721 if (Dot == ".") 1722 a = a - 2; 1723 } 1724 1725 b = Name.rfind('/', a); 1726 if (b == Name.npos) 1727 b = 0; 1728 else 1729 b = b+1; 1730 // ignore any suffix after an underbar like Foo_profile.A.dylib 1731 Idx = Name.find('_', b); 1732 if (Idx != Name.npos && Idx != b) { 1733 Lib = Name.slice(b, Idx); 1734 Suffix = Name.slice(Idx, a); 1735 } 1736 else 1737 Lib = Name.slice(b, a); 1738 // There are incorrect library names of the form: 1739 // libATS.A_profile.dylib so check for these. 1740 if (Lib.size() >= 3) { 1741 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1742 if (Dot == ".") 1743 Lib = Lib.slice(0, Lib.size()-2); 1744 } 1745 return Lib; 1746 1747 guess_qtx: 1748 Qtx = Name.slice(a, Name.npos); 1749 if (Qtx != ".qtx") 1750 return StringRef(); 1751 b = Name.rfind('/', a); 1752 if (b == Name.npos) 1753 Lib = Name.slice(0, a); 1754 else 1755 Lib = Name.slice(b+1, a); 1756 // There are library names of the form: QT.A.qtx so check for these. 1757 if (Lib.size() >= 3) { 1758 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 1759 if (Dot == ".") 1760 Lib = Lib.slice(0, Lib.size()-2); 1761 } 1762 return Lib; 1763 } 1764 1765 // getLibraryShortNameByIndex() is used to get the short name of the library 1766 // for an undefined symbol in a linked Mach-O binary that was linked with the 1767 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 1768 // It is passed the index (0 - based) of the library as translated from 1769 // GET_LIBRARY_ORDINAL (1 - based). 1770 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 1771 StringRef &Res) const { 1772 if (Index >= Libraries.size()) 1773 return object_error::parse_failed; 1774 1775 // If the cache of LibrariesShortNames is not built up do that first for 1776 // all the Libraries. 1777 if (LibrariesShortNames.size() == 0) { 1778 for (unsigned i = 0; i < Libraries.size(); i++) { 1779 MachO::dylib_command D = 1780 getStruct<MachO::dylib_command>(this, Libraries[i]); 1781 if (D.dylib.name >= D.cmdsize) 1782 return object_error::parse_failed; 1783 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 1784 StringRef Name = StringRef(P); 1785 if (D.dylib.name+Name.size() >= D.cmdsize) 1786 return object_error::parse_failed; 1787 StringRef Suffix; 1788 bool isFramework; 1789 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 1790 if (shortName.empty()) 1791 LibrariesShortNames.push_back(Name); 1792 else 1793 LibrariesShortNames.push_back(shortName); 1794 } 1795 } 1796 1797 Res = LibrariesShortNames[Index]; 1798 return std::error_code(); 1799 } 1800 1801 section_iterator 1802 MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const { 1803 DataRefImpl Sec; 1804 Sec.d.a = Rel->getRawDataRefImpl().d.a; 1805 return section_iterator(SectionRef(Sec, this)); 1806 } 1807 1808 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 1809 DataRefImpl DRI; 1810 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1811 if (!SymtabLoadCmd || Symtab.nsyms == 0) 1812 return basic_symbol_iterator(SymbolRef(DRI, this)); 1813 1814 return getSymbolByIndex(0); 1815 } 1816 1817 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 1818 DataRefImpl DRI; 1819 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1820 if (!SymtabLoadCmd || Symtab.nsyms == 0) 1821 return basic_symbol_iterator(SymbolRef(DRI, this)); 1822 1823 unsigned SymbolTableEntrySize = is64Bit() ? 1824 sizeof(MachO::nlist_64) : 1825 sizeof(MachO::nlist); 1826 unsigned Offset = Symtab.symoff + 1827 Symtab.nsyms * SymbolTableEntrySize; 1828 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 1829 return basic_symbol_iterator(SymbolRef(DRI, this)); 1830 } 1831 1832 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 1833 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1834 if (!SymtabLoadCmd || Index >= Symtab.nsyms) 1835 report_fatal_error("Requested symbol index is out of range."); 1836 unsigned SymbolTableEntrySize = 1837 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1838 DataRefImpl DRI; 1839 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1840 DRI.p += Index * SymbolTableEntrySize; 1841 return basic_symbol_iterator(SymbolRef(DRI, this)); 1842 } 1843 1844 uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const { 1845 MachO::symtab_command Symtab = getSymtabLoadCommand(); 1846 if (!SymtabLoadCmd) 1847 report_fatal_error("getSymbolIndex() called with no symbol table symbol"); 1848 unsigned SymbolTableEntrySize = 1849 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 1850 DataRefImpl DRIstart; 1851 DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 1852 uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize; 1853 return Index; 1854 } 1855 1856 section_iterator MachOObjectFile::section_begin() const { 1857 DataRefImpl DRI; 1858 return section_iterator(SectionRef(DRI, this)); 1859 } 1860 1861 section_iterator MachOObjectFile::section_end() const { 1862 DataRefImpl DRI; 1863 DRI.d.a = Sections.size(); 1864 return section_iterator(SectionRef(DRI, this)); 1865 } 1866 1867 uint8_t MachOObjectFile::getBytesInAddress() const { 1868 return is64Bit() ? 8 : 4; 1869 } 1870 1871 StringRef MachOObjectFile::getFileFormatName() const { 1872 unsigned CPUType = getCPUType(this); 1873 if (!is64Bit()) { 1874 switch (CPUType) { 1875 case llvm::MachO::CPU_TYPE_I386: 1876 return "Mach-O 32-bit i386"; 1877 case llvm::MachO::CPU_TYPE_ARM: 1878 return "Mach-O arm"; 1879 case llvm::MachO::CPU_TYPE_POWERPC: 1880 return "Mach-O 32-bit ppc"; 1881 default: 1882 return "Mach-O 32-bit unknown"; 1883 } 1884 } 1885 1886 switch (CPUType) { 1887 case llvm::MachO::CPU_TYPE_X86_64: 1888 return "Mach-O 64-bit x86-64"; 1889 case llvm::MachO::CPU_TYPE_ARM64: 1890 return "Mach-O arm64"; 1891 case llvm::MachO::CPU_TYPE_POWERPC64: 1892 return "Mach-O 64-bit ppc64"; 1893 default: 1894 return "Mach-O 64-bit unknown"; 1895 } 1896 } 1897 1898 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 1899 switch (CPUType) { 1900 case llvm::MachO::CPU_TYPE_I386: 1901 return Triple::x86; 1902 case llvm::MachO::CPU_TYPE_X86_64: 1903 return Triple::x86_64; 1904 case llvm::MachO::CPU_TYPE_ARM: 1905 return Triple::arm; 1906 case llvm::MachO::CPU_TYPE_ARM64: 1907 return Triple::aarch64; 1908 case llvm::MachO::CPU_TYPE_POWERPC: 1909 return Triple::ppc; 1910 case llvm::MachO::CPU_TYPE_POWERPC64: 1911 return Triple::ppc64; 1912 default: 1913 return Triple::UnknownArch; 1914 } 1915 } 1916 1917 Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType, 1918 const char **McpuDefault) { 1919 if (McpuDefault) 1920 *McpuDefault = nullptr; 1921 1922 switch (CPUType) { 1923 case MachO::CPU_TYPE_I386: 1924 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1925 case MachO::CPU_SUBTYPE_I386_ALL: 1926 return Triple("i386-apple-darwin"); 1927 default: 1928 return Triple(); 1929 } 1930 case MachO::CPU_TYPE_X86_64: 1931 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1932 case MachO::CPU_SUBTYPE_X86_64_ALL: 1933 return Triple("x86_64-apple-darwin"); 1934 case MachO::CPU_SUBTYPE_X86_64_H: 1935 return Triple("x86_64h-apple-darwin"); 1936 default: 1937 return Triple(); 1938 } 1939 case MachO::CPU_TYPE_ARM: 1940 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1941 case MachO::CPU_SUBTYPE_ARM_V4T: 1942 return Triple("armv4t-apple-darwin"); 1943 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 1944 return Triple("armv5e-apple-darwin"); 1945 case MachO::CPU_SUBTYPE_ARM_XSCALE: 1946 return Triple("xscale-apple-darwin"); 1947 case MachO::CPU_SUBTYPE_ARM_V6: 1948 return Triple("armv6-apple-darwin"); 1949 case MachO::CPU_SUBTYPE_ARM_V6M: 1950 if (McpuDefault) 1951 *McpuDefault = "cortex-m0"; 1952 return Triple("armv6m-apple-darwin"); 1953 case MachO::CPU_SUBTYPE_ARM_V7: 1954 return Triple("armv7-apple-darwin"); 1955 case MachO::CPU_SUBTYPE_ARM_V7EM: 1956 if (McpuDefault) 1957 *McpuDefault = "cortex-m4"; 1958 return Triple("thumbv7em-apple-darwin"); 1959 case MachO::CPU_SUBTYPE_ARM_V7K: 1960 return Triple("armv7k-apple-darwin"); 1961 case MachO::CPU_SUBTYPE_ARM_V7M: 1962 if (McpuDefault) 1963 *McpuDefault = "cortex-m3"; 1964 return Triple("thumbv7m-apple-darwin"); 1965 case MachO::CPU_SUBTYPE_ARM_V7S: 1966 return Triple("armv7s-apple-darwin"); 1967 default: 1968 return Triple(); 1969 } 1970 case MachO::CPU_TYPE_ARM64: 1971 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1972 case MachO::CPU_SUBTYPE_ARM64_ALL: 1973 return Triple("arm64-apple-darwin"); 1974 default: 1975 return Triple(); 1976 } 1977 case MachO::CPU_TYPE_POWERPC: 1978 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1979 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1980 return Triple("ppc-apple-darwin"); 1981 default: 1982 return Triple(); 1983 } 1984 case MachO::CPU_TYPE_POWERPC64: 1985 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 1986 case MachO::CPU_SUBTYPE_POWERPC_ALL: 1987 return Triple("ppc64-apple-darwin"); 1988 default: 1989 return Triple(); 1990 } 1991 default: 1992 return Triple(); 1993 } 1994 } 1995 1996 Triple MachOObjectFile::getHostArch() { 1997 return Triple(sys::getDefaultTargetTriple()); 1998 } 1999 2000 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 2001 return StringSwitch<bool>(ArchFlag) 2002 .Case("i386", true) 2003 .Case("x86_64", true) 2004 .Case("x86_64h", true) 2005 .Case("armv4t", true) 2006 .Case("arm", true) 2007 .Case("armv5e", true) 2008 .Case("armv6", true) 2009 .Case("armv6m", true) 2010 .Case("armv7", true) 2011 .Case("armv7em", true) 2012 .Case("armv7k", true) 2013 .Case("armv7m", true) 2014 .Case("armv7s", true) 2015 .Case("arm64", true) 2016 .Case("ppc", true) 2017 .Case("ppc64", true) 2018 .Default(false); 2019 } 2020 2021 unsigned MachOObjectFile::getArch() const { 2022 return getArch(getCPUType(this)); 2023 } 2024 2025 Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const { 2026 return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault); 2027 } 2028 2029 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 2030 DataRefImpl DRI; 2031 DRI.d.a = Index; 2032 return section_rel_begin(DRI); 2033 } 2034 2035 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 2036 DataRefImpl DRI; 2037 DRI.d.a = Index; 2038 return section_rel_end(DRI); 2039 } 2040 2041 dice_iterator MachOObjectFile::begin_dices() const { 2042 DataRefImpl DRI; 2043 if (!DataInCodeLoadCmd) 2044 return dice_iterator(DiceRef(DRI, this)); 2045 2046 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2047 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 2048 return dice_iterator(DiceRef(DRI, this)); 2049 } 2050 2051 dice_iterator MachOObjectFile::end_dices() const { 2052 DataRefImpl DRI; 2053 if (!DataInCodeLoadCmd) 2054 return dice_iterator(DiceRef(DRI, this)); 2055 2056 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 2057 unsigned Offset = DicLC.dataoff + DicLC.datasize; 2058 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 2059 return dice_iterator(DiceRef(DRI, this)); 2060 } 2061 2062 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 2063 : Trie(T), Malformed(false), Done(false) {} 2064 2065 void ExportEntry::moveToFirst() { 2066 pushNode(0); 2067 pushDownUntilBottom(); 2068 } 2069 2070 void ExportEntry::moveToEnd() { 2071 Stack.clear(); 2072 Done = true; 2073 } 2074 2075 bool ExportEntry::operator==(const ExportEntry &Other) const { 2076 // Common case, one at end, other iterating from begin. 2077 if (Done || Other.Done) 2078 return (Done == Other.Done); 2079 // Not equal if different stack sizes. 2080 if (Stack.size() != Other.Stack.size()) 2081 return false; 2082 // Not equal if different cumulative strings. 2083 if (!CumulativeString.equals(Other.CumulativeString)) 2084 return false; 2085 // Equal if all nodes in both stacks match. 2086 for (unsigned i=0; i < Stack.size(); ++i) { 2087 if (Stack[i].Start != Other.Stack[i].Start) 2088 return false; 2089 } 2090 return true; 2091 } 2092 2093 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 2094 unsigned Count; 2095 uint64_t Result = decodeULEB128(Ptr, &Count); 2096 Ptr += Count; 2097 if (Ptr > Trie.end()) { 2098 Ptr = Trie.end(); 2099 Malformed = true; 2100 } 2101 return Result; 2102 } 2103 2104 StringRef ExportEntry::name() const { 2105 return CumulativeString; 2106 } 2107 2108 uint64_t ExportEntry::flags() const { 2109 return Stack.back().Flags; 2110 } 2111 2112 uint64_t ExportEntry::address() const { 2113 return Stack.back().Address; 2114 } 2115 2116 uint64_t ExportEntry::other() const { 2117 return Stack.back().Other; 2118 } 2119 2120 StringRef ExportEntry::otherName() const { 2121 const char* ImportName = Stack.back().ImportName; 2122 if (ImportName) 2123 return StringRef(ImportName); 2124 return StringRef(); 2125 } 2126 2127 uint32_t ExportEntry::nodeOffset() const { 2128 return Stack.back().Start - Trie.begin(); 2129 } 2130 2131 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 2132 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 2133 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 2134 ParentStringLength(0), IsExportNode(false) {} 2135 2136 void ExportEntry::pushNode(uint64_t offset) { 2137 const uint8_t *Ptr = Trie.begin() + offset; 2138 NodeState State(Ptr); 2139 uint64_t ExportInfoSize = readULEB128(State.Current); 2140 State.IsExportNode = (ExportInfoSize != 0); 2141 const uint8_t* Children = State.Current + ExportInfoSize; 2142 if (State.IsExportNode) { 2143 State.Flags = readULEB128(State.Current); 2144 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 2145 State.Address = 0; 2146 State.Other = readULEB128(State.Current); // dylib ordinal 2147 State.ImportName = reinterpret_cast<const char*>(State.Current); 2148 } else { 2149 State.Address = readULEB128(State.Current); 2150 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 2151 State.Other = readULEB128(State.Current); 2152 } 2153 } 2154 State.ChildCount = *Children; 2155 State.Current = Children + 1; 2156 State.NextChildIndex = 0; 2157 State.ParentStringLength = CumulativeString.size(); 2158 Stack.push_back(State); 2159 } 2160 2161 void ExportEntry::pushDownUntilBottom() { 2162 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 2163 NodeState &Top = Stack.back(); 2164 CumulativeString.resize(Top.ParentStringLength); 2165 for (;*Top.Current != 0; Top.Current++) { 2166 char C = *Top.Current; 2167 CumulativeString.push_back(C); 2168 } 2169 Top.Current += 1; 2170 uint64_t childNodeIndex = readULEB128(Top.Current); 2171 Top.NextChildIndex += 1; 2172 pushNode(childNodeIndex); 2173 } 2174 if (!Stack.back().IsExportNode) { 2175 Malformed = true; 2176 moveToEnd(); 2177 } 2178 } 2179 2180 // We have a trie data structure and need a way to walk it that is compatible 2181 // with the C++ iterator model. The solution is a non-recursive depth first 2182 // traversal where the iterator contains a stack of parent nodes along with a 2183 // string that is the accumulation of all edge strings along the parent chain 2184 // to this point. 2185 // 2186 // There is one "export" node for each exported symbol. But because some 2187 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 2188 // node may have child nodes too. 2189 // 2190 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 2191 // child until hitting a node with no children (which is an export node or 2192 // else the trie is malformed). On the way down, each node is pushed on the 2193 // stack ivar. If there is no more ways down, it pops up one and tries to go 2194 // down a sibling path until a childless node is reached. 2195 void ExportEntry::moveNext() { 2196 if (Stack.empty() || !Stack.back().IsExportNode) { 2197 Malformed = true; 2198 moveToEnd(); 2199 return; 2200 } 2201 2202 Stack.pop_back(); 2203 while (!Stack.empty()) { 2204 NodeState &Top = Stack.back(); 2205 if (Top.NextChildIndex < Top.ChildCount) { 2206 pushDownUntilBottom(); 2207 // Now at the next export node. 2208 return; 2209 } else { 2210 if (Top.IsExportNode) { 2211 // This node has no children but is itself an export node. 2212 CumulativeString.resize(Top.ParentStringLength); 2213 return; 2214 } 2215 Stack.pop_back(); 2216 } 2217 } 2218 Done = true; 2219 } 2220 2221 iterator_range<export_iterator> 2222 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 2223 ExportEntry Start(Trie); 2224 if (Trie.size() == 0) 2225 Start.moveToEnd(); 2226 else 2227 Start.moveToFirst(); 2228 2229 ExportEntry Finish(Trie); 2230 Finish.moveToEnd(); 2231 2232 return make_range(export_iterator(Start), export_iterator(Finish)); 2233 } 2234 2235 iterator_range<export_iterator> MachOObjectFile::exports() const { 2236 return exports(getDyldInfoExportsTrie()); 2237 } 2238 2239 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 2240 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2241 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 2242 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 2243 2244 void MachORebaseEntry::moveToFirst() { 2245 Ptr = Opcodes.begin(); 2246 moveNext(); 2247 } 2248 2249 void MachORebaseEntry::moveToEnd() { 2250 Ptr = Opcodes.end(); 2251 RemainingLoopCount = 0; 2252 Done = true; 2253 } 2254 2255 void MachORebaseEntry::moveNext() { 2256 // If in the middle of some loop, move to next rebasing in loop. 2257 SegmentOffset += AdvanceAmount; 2258 if (RemainingLoopCount) { 2259 --RemainingLoopCount; 2260 return; 2261 } 2262 if (Ptr == Opcodes.end()) { 2263 Done = true; 2264 return; 2265 } 2266 bool More = true; 2267 while (More && !Malformed) { 2268 // Parse next opcode and set up next loop. 2269 uint8_t Byte = *Ptr++; 2270 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 2271 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 2272 switch (Opcode) { 2273 case MachO::REBASE_OPCODE_DONE: 2274 More = false; 2275 Done = true; 2276 moveToEnd(); 2277 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 2278 break; 2279 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 2280 RebaseType = ImmValue; 2281 DEBUG_WITH_TYPE( 2282 "mach-o-rebase", 2283 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 2284 << "RebaseType=" << (int) RebaseType << "\n"); 2285 break; 2286 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2287 SegmentIndex = ImmValue; 2288 SegmentOffset = readULEB128(); 2289 DEBUG_WITH_TYPE( 2290 "mach-o-rebase", 2291 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2292 << "SegmentIndex=" << SegmentIndex << ", " 2293 << format("SegmentOffset=0x%06X", SegmentOffset) 2294 << "\n"); 2295 break; 2296 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 2297 SegmentOffset += readULEB128(); 2298 DEBUG_WITH_TYPE("mach-o-rebase", 2299 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 2300 << format("SegmentOffset=0x%06X", 2301 SegmentOffset) << "\n"); 2302 break; 2303 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 2304 SegmentOffset += ImmValue * PointerSize; 2305 DEBUG_WITH_TYPE("mach-o-rebase", 2306 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 2307 << format("SegmentOffset=0x%06X", 2308 SegmentOffset) << "\n"); 2309 break; 2310 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 2311 AdvanceAmount = PointerSize; 2312 RemainingLoopCount = ImmValue - 1; 2313 DEBUG_WITH_TYPE( 2314 "mach-o-rebase", 2315 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 2316 << format("SegmentOffset=0x%06X", SegmentOffset) 2317 << ", AdvanceAmount=" << AdvanceAmount 2318 << ", RemainingLoopCount=" << RemainingLoopCount 2319 << "\n"); 2320 return; 2321 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 2322 AdvanceAmount = PointerSize; 2323 RemainingLoopCount = readULEB128() - 1; 2324 DEBUG_WITH_TYPE( 2325 "mach-o-rebase", 2326 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 2327 << format("SegmentOffset=0x%06X", SegmentOffset) 2328 << ", AdvanceAmount=" << AdvanceAmount 2329 << ", RemainingLoopCount=" << RemainingLoopCount 2330 << "\n"); 2331 return; 2332 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 2333 AdvanceAmount = readULEB128() + PointerSize; 2334 RemainingLoopCount = 0; 2335 DEBUG_WITH_TYPE( 2336 "mach-o-rebase", 2337 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 2338 << format("SegmentOffset=0x%06X", SegmentOffset) 2339 << ", AdvanceAmount=" << AdvanceAmount 2340 << ", RemainingLoopCount=" << RemainingLoopCount 2341 << "\n"); 2342 return; 2343 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 2344 RemainingLoopCount = readULEB128() - 1; 2345 AdvanceAmount = readULEB128() + PointerSize; 2346 DEBUG_WITH_TYPE( 2347 "mach-o-rebase", 2348 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 2349 << format("SegmentOffset=0x%06X", SegmentOffset) 2350 << ", AdvanceAmount=" << AdvanceAmount 2351 << ", RemainingLoopCount=" << RemainingLoopCount 2352 << "\n"); 2353 return; 2354 default: 2355 Malformed = true; 2356 } 2357 } 2358 } 2359 2360 uint64_t MachORebaseEntry::readULEB128() { 2361 unsigned Count; 2362 uint64_t Result = decodeULEB128(Ptr, &Count); 2363 Ptr += Count; 2364 if (Ptr > Opcodes.end()) { 2365 Ptr = Opcodes.end(); 2366 Malformed = true; 2367 } 2368 return Result; 2369 } 2370 2371 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 2372 2373 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 2374 2375 StringRef MachORebaseEntry::typeName() const { 2376 switch (RebaseType) { 2377 case MachO::REBASE_TYPE_POINTER: 2378 return "pointer"; 2379 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 2380 return "text abs32"; 2381 case MachO::REBASE_TYPE_TEXT_PCREL32: 2382 return "text rel32"; 2383 } 2384 return "unknown"; 2385 } 2386 2387 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 2388 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2389 return (Ptr == Other.Ptr) && 2390 (RemainingLoopCount == Other.RemainingLoopCount) && 2391 (Done == Other.Done); 2392 } 2393 2394 iterator_range<rebase_iterator> 2395 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 2396 MachORebaseEntry Start(Opcodes, is64); 2397 Start.moveToFirst(); 2398 2399 MachORebaseEntry Finish(Opcodes, is64); 2400 Finish.moveToEnd(); 2401 2402 return make_range(rebase_iterator(Start), rebase_iterator(Finish)); 2403 } 2404 2405 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 2406 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 2407 } 2408 2409 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK) 2410 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 2411 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 2412 BindType(0), PointerSize(is64Bit ? 8 : 4), 2413 TableKind(BK), Malformed(false), Done(false) {} 2414 2415 void MachOBindEntry::moveToFirst() { 2416 Ptr = Opcodes.begin(); 2417 moveNext(); 2418 } 2419 2420 void MachOBindEntry::moveToEnd() { 2421 Ptr = Opcodes.end(); 2422 RemainingLoopCount = 0; 2423 Done = true; 2424 } 2425 2426 void MachOBindEntry::moveNext() { 2427 // If in the middle of some loop, move to next binding in loop. 2428 SegmentOffset += AdvanceAmount; 2429 if (RemainingLoopCount) { 2430 --RemainingLoopCount; 2431 return; 2432 } 2433 if (Ptr == Opcodes.end()) { 2434 Done = true; 2435 return; 2436 } 2437 bool More = true; 2438 while (More && !Malformed) { 2439 // Parse next opcode and set up next loop. 2440 uint8_t Byte = *Ptr++; 2441 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 2442 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 2443 int8_t SignExtended; 2444 const uint8_t *SymStart; 2445 switch (Opcode) { 2446 case MachO::BIND_OPCODE_DONE: 2447 if (TableKind == Kind::Lazy) { 2448 // Lazying bindings have a DONE opcode between entries. Need to ignore 2449 // it to advance to next entry. But need not if this is last entry. 2450 bool NotLastEntry = false; 2451 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 2452 if (*P) { 2453 NotLastEntry = true; 2454 } 2455 } 2456 if (NotLastEntry) 2457 break; 2458 } 2459 More = false; 2460 Done = true; 2461 moveToEnd(); 2462 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 2463 break; 2464 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 2465 Ordinal = ImmValue; 2466 DEBUG_WITH_TYPE( 2467 "mach-o-bind", 2468 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 2469 << "Ordinal=" << Ordinal << "\n"); 2470 break; 2471 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 2472 Ordinal = readULEB128(); 2473 DEBUG_WITH_TYPE( 2474 "mach-o-bind", 2475 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 2476 << "Ordinal=" << Ordinal << "\n"); 2477 break; 2478 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 2479 if (ImmValue) { 2480 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 2481 Ordinal = SignExtended; 2482 } else 2483 Ordinal = 0; 2484 DEBUG_WITH_TYPE( 2485 "mach-o-bind", 2486 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 2487 << "Ordinal=" << Ordinal << "\n"); 2488 break; 2489 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 2490 Flags = ImmValue; 2491 SymStart = Ptr; 2492 while (*Ptr) { 2493 ++Ptr; 2494 } 2495 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 2496 Ptr-SymStart); 2497 ++Ptr; 2498 DEBUG_WITH_TYPE( 2499 "mach-o-bind", 2500 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 2501 << "SymbolName=" << SymbolName << "\n"); 2502 if (TableKind == Kind::Weak) { 2503 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 2504 return; 2505 } 2506 break; 2507 case MachO::BIND_OPCODE_SET_TYPE_IMM: 2508 BindType = ImmValue; 2509 DEBUG_WITH_TYPE( 2510 "mach-o-bind", 2511 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 2512 << "BindType=" << (int)BindType << "\n"); 2513 break; 2514 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 2515 Addend = readSLEB128(); 2516 if (TableKind == Kind::Lazy) 2517 Malformed = true; 2518 DEBUG_WITH_TYPE( 2519 "mach-o-bind", 2520 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 2521 << "Addend=" << Addend << "\n"); 2522 break; 2523 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 2524 SegmentIndex = ImmValue; 2525 SegmentOffset = readULEB128(); 2526 DEBUG_WITH_TYPE( 2527 "mach-o-bind", 2528 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 2529 << "SegmentIndex=" << SegmentIndex << ", " 2530 << format("SegmentOffset=0x%06X", SegmentOffset) 2531 << "\n"); 2532 break; 2533 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 2534 SegmentOffset += readULEB128(); 2535 DEBUG_WITH_TYPE("mach-o-bind", 2536 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 2537 << format("SegmentOffset=0x%06X", 2538 SegmentOffset) << "\n"); 2539 break; 2540 case MachO::BIND_OPCODE_DO_BIND: 2541 AdvanceAmount = PointerSize; 2542 RemainingLoopCount = 0; 2543 DEBUG_WITH_TYPE("mach-o-bind", 2544 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 2545 << format("SegmentOffset=0x%06X", 2546 SegmentOffset) << "\n"); 2547 return; 2548 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 2549 AdvanceAmount = readULEB128() + PointerSize; 2550 RemainingLoopCount = 0; 2551 if (TableKind == Kind::Lazy) 2552 Malformed = true; 2553 DEBUG_WITH_TYPE( 2554 "mach-o-bind", 2555 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: " 2556 << format("SegmentOffset=0x%06X", SegmentOffset) 2557 << ", AdvanceAmount=" << AdvanceAmount 2558 << ", RemainingLoopCount=" << RemainingLoopCount 2559 << "\n"); 2560 return; 2561 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 2562 AdvanceAmount = ImmValue * PointerSize + PointerSize; 2563 RemainingLoopCount = 0; 2564 if (TableKind == Kind::Lazy) 2565 Malformed = true; 2566 DEBUG_WITH_TYPE("mach-o-bind", 2567 llvm::dbgs() 2568 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 2569 << format("SegmentOffset=0x%06X", 2570 SegmentOffset) << "\n"); 2571 return; 2572 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 2573 RemainingLoopCount = readULEB128() - 1; 2574 AdvanceAmount = readULEB128() + PointerSize; 2575 if (TableKind == Kind::Lazy) 2576 Malformed = true; 2577 DEBUG_WITH_TYPE( 2578 "mach-o-bind", 2579 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 2580 << format("SegmentOffset=0x%06X", SegmentOffset) 2581 << ", AdvanceAmount=" << AdvanceAmount 2582 << ", RemainingLoopCount=" << RemainingLoopCount 2583 << "\n"); 2584 return; 2585 default: 2586 Malformed = true; 2587 } 2588 } 2589 } 2590 2591 uint64_t MachOBindEntry::readULEB128() { 2592 unsigned Count; 2593 uint64_t Result = decodeULEB128(Ptr, &Count); 2594 Ptr += Count; 2595 if (Ptr > Opcodes.end()) { 2596 Ptr = Opcodes.end(); 2597 Malformed = true; 2598 } 2599 return Result; 2600 } 2601 2602 int64_t MachOBindEntry::readSLEB128() { 2603 unsigned Count; 2604 int64_t Result = decodeSLEB128(Ptr, &Count); 2605 Ptr += Count; 2606 if (Ptr > Opcodes.end()) { 2607 Ptr = Opcodes.end(); 2608 Malformed = true; 2609 } 2610 return Result; 2611 } 2612 2613 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 2614 2615 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 2616 2617 StringRef MachOBindEntry::typeName() const { 2618 switch (BindType) { 2619 case MachO::BIND_TYPE_POINTER: 2620 return "pointer"; 2621 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 2622 return "text abs32"; 2623 case MachO::BIND_TYPE_TEXT_PCREL32: 2624 return "text rel32"; 2625 } 2626 return "unknown"; 2627 } 2628 2629 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 2630 2631 int64_t MachOBindEntry::addend() const { return Addend; } 2632 2633 uint32_t MachOBindEntry::flags() const { return Flags; } 2634 2635 int MachOBindEntry::ordinal() const { return Ordinal; } 2636 2637 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 2638 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 2639 return (Ptr == Other.Ptr) && 2640 (RemainingLoopCount == Other.RemainingLoopCount) && 2641 (Done == Other.Done); 2642 } 2643 2644 iterator_range<bind_iterator> 2645 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 2646 MachOBindEntry::Kind BKind) { 2647 MachOBindEntry Start(Opcodes, is64, BKind); 2648 Start.moveToFirst(); 2649 2650 MachOBindEntry Finish(Opcodes, is64, BKind); 2651 Finish.moveToEnd(); 2652 2653 return make_range(bind_iterator(Start), bind_iterator(Finish)); 2654 } 2655 2656 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 2657 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 2658 MachOBindEntry::Kind::Regular); 2659 } 2660 2661 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 2662 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 2663 MachOBindEntry::Kind::Lazy); 2664 } 2665 2666 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 2667 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 2668 MachOBindEntry::Kind::Weak); 2669 } 2670 2671 MachOObjectFile::load_command_iterator 2672 MachOObjectFile::begin_load_commands() const { 2673 return LoadCommands.begin(); 2674 } 2675 2676 MachOObjectFile::load_command_iterator 2677 MachOObjectFile::end_load_commands() const { 2678 return LoadCommands.end(); 2679 } 2680 2681 iterator_range<MachOObjectFile::load_command_iterator> 2682 MachOObjectFile::load_commands() const { 2683 return make_range(begin_load_commands(), end_load_commands()); 2684 } 2685 2686 StringRef 2687 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 2688 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 2689 return parseSegmentOrSectionName(Raw.data()); 2690 } 2691 2692 ArrayRef<char> 2693 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 2694 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2695 const section_base *Base = 2696 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2697 return makeArrayRef(Base->sectname); 2698 } 2699 2700 ArrayRef<char> 2701 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 2702 assert(Sec.d.a < Sections.size() && "Should have detected this earlier"); 2703 const section_base *Base = 2704 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 2705 return makeArrayRef(Base->segname); 2706 } 2707 2708 bool 2709 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 2710 const { 2711 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 2712 return false; 2713 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 2714 } 2715 2716 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 2717 const MachO::any_relocation_info &RE) const { 2718 if (isLittleEndian()) 2719 return RE.r_word1 & 0xffffff; 2720 return RE.r_word1 >> 8; 2721 } 2722 2723 bool MachOObjectFile::getPlainRelocationExternal( 2724 const MachO::any_relocation_info &RE) const { 2725 if (isLittleEndian()) 2726 return (RE.r_word1 >> 27) & 1; 2727 return (RE.r_word1 >> 4) & 1; 2728 } 2729 2730 bool MachOObjectFile::getScatteredRelocationScattered( 2731 const MachO::any_relocation_info &RE) const { 2732 return RE.r_word0 >> 31; 2733 } 2734 2735 uint32_t MachOObjectFile::getScatteredRelocationValue( 2736 const MachO::any_relocation_info &RE) const { 2737 return RE.r_word1; 2738 } 2739 2740 uint32_t MachOObjectFile::getScatteredRelocationType( 2741 const MachO::any_relocation_info &RE) const { 2742 return (RE.r_word0 >> 24) & 0xf; 2743 } 2744 2745 unsigned MachOObjectFile::getAnyRelocationAddress( 2746 const MachO::any_relocation_info &RE) const { 2747 if (isRelocationScattered(RE)) 2748 return getScatteredRelocationAddress(RE); 2749 return getPlainRelocationAddress(RE); 2750 } 2751 2752 unsigned MachOObjectFile::getAnyRelocationPCRel( 2753 const MachO::any_relocation_info &RE) const { 2754 if (isRelocationScattered(RE)) 2755 return getScatteredRelocationPCRel(this, RE); 2756 return getPlainRelocationPCRel(this, RE); 2757 } 2758 2759 unsigned MachOObjectFile::getAnyRelocationLength( 2760 const MachO::any_relocation_info &RE) const { 2761 if (isRelocationScattered(RE)) 2762 return getScatteredRelocationLength(RE); 2763 return getPlainRelocationLength(this, RE); 2764 } 2765 2766 unsigned 2767 MachOObjectFile::getAnyRelocationType( 2768 const MachO::any_relocation_info &RE) const { 2769 if (isRelocationScattered(RE)) 2770 return getScatteredRelocationType(RE); 2771 return getPlainRelocationType(this, RE); 2772 } 2773 2774 SectionRef 2775 MachOObjectFile::getAnyRelocationSection( 2776 const MachO::any_relocation_info &RE) const { 2777 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 2778 return *section_end(); 2779 unsigned SecNum = getPlainRelocationSymbolNum(RE); 2780 if (SecNum == MachO::R_ABS || SecNum > Sections.size()) 2781 return *section_end(); 2782 DataRefImpl DRI; 2783 DRI.d.a = SecNum - 1; 2784 return SectionRef(DRI, this); 2785 } 2786 2787 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 2788 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 2789 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 2790 } 2791 2792 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 2793 assert(DRI.d.a < Sections.size() && "Should have detected this earlier"); 2794 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 2795 } 2796 2797 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 2798 unsigned Index) const { 2799 const char *Sec = getSectionPtr(this, L, Index); 2800 return getStruct<MachO::section>(this, Sec); 2801 } 2802 2803 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 2804 unsigned Index) const { 2805 const char *Sec = getSectionPtr(this, L, Index); 2806 return getStruct<MachO::section_64>(this, Sec); 2807 } 2808 2809 MachO::nlist 2810 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 2811 const char *P = reinterpret_cast<const char *>(DRI.p); 2812 return getStruct<MachO::nlist>(this, P); 2813 } 2814 2815 MachO::nlist_64 2816 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 2817 const char *P = reinterpret_cast<const char *>(DRI.p); 2818 return getStruct<MachO::nlist_64>(this, P); 2819 } 2820 2821 MachO::linkedit_data_command 2822 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 2823 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 2824 } 2825 2826 MachO::segment_command 2827 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 2828 return getStruct<MachO::segment_command>(this, L.Ptr); 2829 } 2830 2831 MachO::segment_command_64 2832 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 2833 return getStruct<MachO::segment_command_64>(this, L.Ptr); 2834 } 2835 2836 MachO::linker_option_command 2837 MachOObjectFile::getLinkerOptionLoadCommand(const LoadCommandInfo &L) const { 2838 return getStruct<MachO::linker_option_command>(this, L.Ptr); 2839 } 2840 2841 MachO::version_min_command 2842 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 2843 return getStruct<MachO::version_min_command>(this, L.Ptr); 2844 } 2845 2846 MachO::dylib_command 2847 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 2848 return getStruct<MachO::dylib_command>(this, L.Ptr); 2849 } 2850 2851 MachO::dyld_info_command 2852 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 2853 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 2854 } 2855 2856 MachO::dylinker_command 2857 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 2858 return getStruct<MachO::dylinker_command>(this, L.Ptr); 2859 } 2860 2861 MachO::uuid_command 2862 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 2863 return getStruct<MachO::uuid_command>(this, L.Ptr); 2864 } 2865 2866 MachO::rpath_command 2867 MachOObjectFile::getRpathCommand(const LoadCommandInfo &L) const { 2868 return getStruct<MachO::rpath_command>(this, L.Ptr); 2869 } 2870 2871 MachO::source_version_command 2872 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 2873 return getStruct<MachO::source_version_command>(this, L.Ptr); 2874 } 2875 2876 MachO::entry_point_command 2877 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 2878 return getStruct<MachO::entry_point_command>(this, L.Ptr); 2879 } 2880 2881 MachO::encryption_info_command 2882 MachOObjectFile::getEncryptionInfoCommand(const LoadCommandInfo &L) const { 2883 return getStruct<MachO::encryption_info_command>(this, L.Ptr); 2884 } 2885 2886 MachO::encryption_info_command_64 2887 MachOObjectFile::getEncryptionInfoCommand64(const LoadCommandInfo &L) const { 2888 return getStruct<MachO::encryption_info_command_64>(this, L.Ptr); 2889 } 2890 2891 MachO::sub_framework_command 2892 MachOObjectFile::getSubFrameworkCommand(const LoadCommandInfo &L) const { 2893 return getStruct<MachO::sub_framework_command>(this, L.Ptr); 2894 } 2895 2896 MachO::sub_umbrella_command 2897 MachOObjectFile::getSubUmbrellaCommand(const LoadCommandInfo &L) const { 2898 return getStruct<MachO::sub_umbrella_command>(this, L.Ptr); 2899 } 2900 2901 MachO::sub_library_command 2902 MachOObjectFile::getSubLibraryCommand(const LoadCommandInfo &L) const { 2903 return getStruct<MachO::sub_library_command>(this, L.Ptr); 2904 } 2905 2906 MachO::sub_client_command 2907 MachOObjectFile::getSubClientCommand(const LoadCommandInfo &L) const { 2908 return getStruct<MachO::sub_client_command>(this, L.Ptr); 2909 } 2910 2911 MachO::routines_command 2912 MachOObjectFile::getRoutinesCommand(const LoadCommandInfo &L) const { 2913 return getStruct<MachO::routines_command>(this, L.Ptr); 2914 } 2915 2916 MachO::routines_command_64 2917 MachOObjectFile::getRoutinesCommand64(const LoadCommandInfo &L) const { 2918 return getStruct<MachO::routines_command_64>(this, L.Ptr); 2919 } 2920 2921 MachO::thread_command 2922 MachOObjectFile::getThreadCommand(const LoadCommandInfo &L) const { 2923 return getStruct<MachO::thread_command>(this, L.Ptr); 2924 } 2925 2926 MachO::any_relocation_info 2927 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 2928 DataRefImpl Sec; 2929 Sec.d.a = Rel.d.a; 2930 uint32_t Offset; 2931 if (is64Bit()) { 2932 MachO::section_64 Sect = getSection64(Sec); 2933 Offset = Sect.reloff; 2934 } else { 2935 MachO::section Sect = getSection(Sec); 2936 Offset = Sect.reloff; 2937 } 2938 2939 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 2940 getPtr(this, Offset)) + Rel.d.b; 2941 return getStruct<MachO::any_relocation_info>( 2942 this, reinterpret_cast<const char *>(P)); 2943 } 2944 2945 MachO::data_in_code_entry 2946 MachOObjectFile::getDice(DataRefImpl Rel) const { 2947 const char *P = reinterpret_cast<const char *>(Rel.p); 2948 return getStruct<MachO::data_in_code_entry>(this, P); 2949 } 2950 2951 const MachO::mach_header &MachOObjectFile::getHeader() const { 2952 return Header; 2953 } 2954 2955 const MachO::mach_header_64 &MachOObjectFile::getHeader64() const { 2956 assert(is64Bit()); 2957 return Header64; 2958 } 2959 2960 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 2961 const MachO::dysymtab_command &DLC, 2962 unsigned Index) const { 2963 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 2964 return getStruct<uint32_t>(this, getPtr(this, Offset)); 2965 } 2966 2967 MachO::data_in_code_entry 2968 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 2969 unsigned Index) const { 2970 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 2971 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 2972 } 2973 2974 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 2975 if (SymtabLoadCmd) 2976 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 2977 2978 // If there is no SymtabLoadCmd return a load command with zero'ed fields. 2979 MachO::symtab_command Cmd; 2980 Cmd.cmd = MachO::LC_SYMTAB; 2981 Cmd.cmdsize = sizeof(MachO::symtab_command); 2982 Cmd.symoff = 0; 2983 Cmd.nsyms = 0; 2984 Cmd.stroff = 0; 2985 Cmd.strsize = 0; 2986 return Cmd; 2987 } 2988 2989 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 2990 if (DysymtabLoadCmd) 2991 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 2992 2993 // If there is no DysymtabLoadCmd return a load command with zero'ed fields. 2994 MachO::dysymtab_command Cmd; 2995 Cmd.cmd = MachO::LC_DYSYMTAB; 2996 Cmd.cmdsize = sizeof(MachO::dysymtab_command); 2997 Cmd.ilocalsym = 0; 2998 Cmd.nlocalsym = 0; 2999 Cmd.iextdefsym = 0; 3000 Cmd.nextdefsym = 0; 3001 Cmd.iundefsym = 0; 3002 Cmd.nundefsym = 0; 3003 Cmd.tocoff = 0; 3004 Cmd.ntoc = 0; 3005 Cmd.modtaboff = 0; 3006 Cmd.nmodtab = 0; 3007 Cmd.extrefsymoff = 0; 3008 Cmd.nextrefsyms = 0; 3009 Cmd.indirectsymoff = 0; 3010 Cmd.nindirectsyms = 0; 3011 Cmd.extreloff = 0; 3012 Cmd.nextrel = 0; 3013 Cmd.locreloff = 0; 3014 Cmd.nlocrel = 0; 3015 return Cmd; 3016 } 3017 3018 MachO::linkedit_data_command 3019 MachOObjectFile::getDataInCodeLoadCommand() const { 3020 if (DataInCodeLoadCmd) 3021 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 3022 3023 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 3024 MachO::linkedit_data_command Cmd; 3025 Cmd.cmd = MachO::LC_DATA_IN_CODE; 3026 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3027 Cmd.dataoff = 0; 3028 Cmd.datasize = 0; 3029 return Cmd; 3030 } 3031 3032 MachO::linkedit_data_command 3033 MachOObjectFile::getLinkOptHintsLoadCommand() const { 3034 if (LinkOptHintsLoadCmd) 3035 return getStruct<MachO::linkedit_data_command>(this, LinkOptHintsLoadCmd); 3036 3037 // If there is no LinkOptHintsLoadCmd return a load command with zero'ed 3038 // fields. 3039 MachO::linkedit_data_command Cmd; 3040 Cmd.cmd = MachO::LC_LINKER_OPTIMIZATION_HINT; 3041 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 3042 Cmd.dataoff = 0; 3043 Cmd.datasize = 0; 3044 return Cmd; 3045 } 3046 3047 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 3048 if (!DyldInfoLoadCmd) 3049 return None; 3050 3051 MachO::dyld_info_command DyldInfo = 3052 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3053 const uint8_t *Ptr = 3054 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.rebase_off)); 3055 return makeArrayRef(Ptr, DyldInfo.rebase_size); 3056 } 3057 3058 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 3059 if (!DyldInfoLoadCmd) 3060 return None; 3061 3062 MachO::dyld_info_command DyldInfo = 3063 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3064 const uint8_t *Ptr = 3065 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.bind_off)); 3066 return makeArrayRef(Ptr, DyldInfo.bind_size); 3067 } 3068 3069 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 3070 if (!DyldInfoLoadCmd) 3071 return None; 3072 3073 MachO::dyld_info_command DyldInfo = 3074 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3075 const uint8_t *Ptr = 3076 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.weak_bind_off)); 3077 return makeArrayRef(Ptr, DyldInfo.weak_bind_size); 3078 } 3079 3080 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 3081 if (!DyldInfoLoadCmd) 3082 return None; 3083 3084 MachO::dyld_info_command DyldInfo = 3085 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3086 const uint8_t *Ptr = 3087 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.lazy_bind_off)); 3088 return makeArrayRef(Ptr, DyldInfo.lazy_bind_size); 3089 } 3090 3091 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 3092 if (!DyldInfoLoadCmd) 3093 return None; 3094 3095 MachO::dyld_info_command DyldInfo = 3096 getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 3097 const uint8_t *Ptr = 3098 reinterpret_cast<const uint8_t *>(getPtr(this, DyldInfo.export_off)); 3099 return makeArrayRef(Ptr, DyldInfo.export_size); 3100 } 3101 3102 ArrayRef<uint8_t> MachOObjectFile::getUuid() const { 3103 if (!UuidLoadCmd) 3104 return None; 3105 // Returning a pointer is fine as uuid doesn't need endian swapping. 3106 const char *Ptr = UuidLoadCmd + offsetof(MachO::uuid_command, uuid); 3107 return makeArrayRef(reinterpret_cast<const uint8_t *>(Ptr), 16); 3108 } 3109 3110 StringRef MachOObjectFile::getStringTableData() const { 3111 MachO::symtab_command S = getSymtabLoadCommand(); 3112 return getData().substr(S.stroff, S.strsize); 3113 } 3114 3115 bool MachOObjectFile::is64Bit() const { 3116 return getType() == getMachOType(false, true) || 3117 getType() == getMachOType(true, true); 3118 } 3119 3120 void MachOObjectFile::ReadULEB128s(uint64_t Index, 3121 SmallVectorImpl<uint64_t> &Out) const { 3122 DataExtractor extractor(ObjectFile::getData(), true, 0); 3123 3124 uint32_t offset = Index; 3125 uint64_t data = 0; 3126 while (uint64_t delta = extractor.getULEB128(&offset)) { 3127 data += delta; 3128 Out.push_back(data); 3129 } 3130 } 3131 3132 bool MachOObjectFile::isRelocatableObject() const { 3133 return getHeader().filetype == MachO::MH_OBJECT; 3134 } 3135 3136 Expected<std::unique_ptr<MachOObjectFile>> 3137 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 3138 StringRef Magic = Buffer.getBuffer().slice(0, 4); 3139 if (Magic == "\xFE\xED\xFA\xCE") 3140 return MachOObjectFile::create(Buffer, false, false); 3141 if (Magic == "\xCE\xFA\xED\xFE") 3142 return MachOObjectFile::create(Buffer, true, false); 3143 if (Magic == "\xFE\xED\xFA\xCF") 3144 return MachOObjectFile::create(Buffer, false, true); 3145 if (Magic == "\xCF\xFA\xED\xFE") 3146 return MachOObjectFile::create(Buffer, true, true); 3147 return make_error<GenericBinaryError>("Unrecognized MachO magic number", 3148 object_error::invalid_file_type); 3149 } 3150