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