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