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