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