LLVM API Documentation
00001 //===- MachOObjectFile.cpp - Mach-O object file binding ---------*- C++ -*-===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file defines the MachOObjectFile class, which binds the MachOObject 00011 // class to the generic ObjectFile wrapper. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/Object/MachO.h" 00016 #include "llvm/ADT/STLExtras.h" 00017 #include "llvm/ADT/StringSwitch.h" 00018 #include "llvm/ADT/Triple.h" 00019 #include "llvm/Support/DataExtractor.h" 00020 #include "llvm/Support/Debug.h" 00021 #include "llvm/Support/Format.h" 00022 #include "llvm/Support/Host.h" 00023 #include "llvm/Support/LEB128.h" 00024 #include "llvm/Support/MachO.h" 00025 #include "llvm/Support/MemoryBuffer.h" 00026 #include "llvm/Support/raw_ostream.h" 00027 #include <cctype> 00028 #include <cstring> 00029 #include <limits> 00030 00031 using namespace llvm; 00032 using namespace object; 00033 00034 namespace { 00035 struct section_base { 00036 char sectname[16]; 00037 char segname[16]; 00038 }; 00039 } 00040 00041 template<typename T> 00042 static T getStruct(const MachOObjectFile *O, const char *P) { 00043 T Cmd; 00044 memcpy(&Cmd, P, sizeof(T)); 00045 if (O->isLittleEndian() != sys::IsLittleEndianHost) 00046 MachO::swapStruct(Cmd); 00047 return Cmd; 00048 } 00049 00050 static uint32_t 00051 getSegmentLoadCommandNumSections(const MachOObjectFile *O, 00052 const MachOObjectFile::LoadCommandInfo &L) { 00053 if (O->is64Bit()) { 00054 MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 00055 return S.nsects; 00056 } 00057 MachO::segment_command S = O->getSegmentLoadCommand(L); 00058 return S.nsects; 00059 } 00060 00061 static bool isPageZeroSegment(const MachOObjectFile *O, 00062 const MachOObjectFile::LoadCommandInfo &L) { 00063 if (O->is64Bit()) { 00064 MachO::segment_command_64 S = O->getSegment64LoadCommand(L); 00065 return StringRef("__PAGEZERO").equals(S.segname); 00066 } 00067 MachO::segment_command S = O->getSegmentLoadCommand(L); 00068 return StringRef("__PAGEZERO").equals(S.segname); 00069 } 00070 00071 00072 static const char * 00073 getSectionPtr(const MachOObjectFile *O, MachOObjectFile::LoadCommandInfo L, 00074 unsigned Sec) { 00075 uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr); 00076 00077 bool Is64 = O->is64Bit(); 00078 unsigned SegmentLoadSize = Is64 ? sizeof(MachO::segment_command_64) : 00079 sizeof(MachO::segment_command); 00080 unsigned SectionSize = Is64 ? sizeof(MachO::section_64) : 00081 sizeof(MachO::section); 00082 00083 uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize; 00084 return reinterpret_cast<const char*>(SectionAddr); 00085 } 00086 00087 static const char *getPtr(const MachOObjectFile *O, size_t Offset) { 00088 return O->getData().substr(Offset, 1).data(); 00089 } 00090 00091 static MachO::nlist_base 00092 getSymbolTableEntryBase(const MachOObjectFile *O, DataRefImpl DRI) { 00093 const char *P = reinterpret_cast<const char *>(DRI.p); 00094 return getStruct<MachO::nlist_base>(O, P); 00095 } 00096 00097 static StringRef parseSegmentOrSectionName(const char *P) { 00098 if (P[15] == 0) 00099 // Null terminated. 00100 return P; 00101 // Not null terminated, so this is a 16 char string. 00102 return StringRef(P, 16); 00103 } 00104 00105 // Helper to advance a section or symbol iterator multiple increments at a time. 00106 template<class T> 00107 static void advance(T &it, size_t Val) { 00108 while (Val--) 00109 ++it; 00110 } 00111 00112 static unsigned getCPUType(const MachOObjectFile *O) { 00113 return O->getHeader().cputype; 00114 } 00115 00116 static void printRelocationTargetName(const MachOObjectFile *O, 00117 const MachO::any_relocation_info &RE, 00118 raw_string_ostream &fmt) { 00119 bool IsScattered = O->isRelocationScattered(RE); 00120 00121 // Target of a scattered relocation is an address. In the interest of 00122 // generating pretty output, scan through the symbol table looking for a 00123 // symbol that aligns with that address. If we find one, print it. 00124 // Otherwise, we just print the hex address of the target. 00125 if (IsScattered) { 00126 uint32_t Val = O->getPlainRelocationSymbolNum(RE); 00127 00128 for (const SymbolRef &Symbol : O->symbols()) { 00129 std::error_code ec; 00130 uint64_t Addr; 00131 StringRef Name; 00132 00133 if ((ec = Symbol.getAddress(Addr))) 00134 report_fatal_error(ec.message()); 00135 if (Addr != Val) 00136 continue; 00137 if ((ec = Symbol.getName(Name))) 00138 report_fatal_error(ec.message()); 00139 fmt << Name; 00140 return; 00141 } 00142 00143 // If we couldn't find a symbol that this relocation refers to, try 00144 // to find a section beginning instead. 00145 for (const SectionRef &Section : O->sections()) { 00146 std::error_code ec; 00147 uint64_t Addr; 00148 StringRef Name; 00149 00150 if ((ec = Section.getAddress(Addr))) 00151 report_fatal_error(ec.message()); 00152 if (Addr != Val) 00153 continue; 00154 if ((ec = Section.getName(Name))) 00155 report_fatal_error(ec.message()); 00156 fmt << Name; 00157 return; 00158 } 00159 00160 fmt << format("0x%x", Val); 00161 return; 00162 } 00163 00164 StringRef S; 00165 bool isExtern = O->getPlainRelocationExternal(RE); 00166 uint64_t Val = O->getPlainRelocationSymbolNum(RE); 00167 00168 if (isExtern) { 00169 symbol_iterator SI = O->symbol_begin(); 00170 advance(SI, Val); 00171 SI->getName(S); 00172 } else { 00173 section_iterator SI = O->section_begin(); 00174 // Adjust for the fact that sections are 1-indexed. 00175 advance(SI, Val - 1); 00176 SI->getName(S); 00177 } 00178 00179 fmt << S; 00180 } 00181 00182 static uint32_t 00183 getPlainRelocationAddress(const MachO::any_relocation_info &RE) { 00184 return RE.r_word0; 00185 } 00186 00187 static unsigned 00188 getScatteredRelocationAddress(const MachO::any_relocation_info &RE) { 00189 return RE.r_word0 & 0xffffff; 00190 } 00191 00192 static bool getPlainRelocationPCRel(const MachOObjectFile *O, 00193 const MachO::any_relocation_info &RE) { 00194 if (O->isLittleEndian()) 00195 return (RE.r_word1 >> 24) & 1; 00196 return (RE.r_word1 >> 7) & 1; 00197 } 00198 00199 static bool 00200 getScatteredRelocationPCRel(const MachOObjectFile *O, 00201 const MachO::any_relocation_info &RE) { 00202 return (RE.r_word0 >> 30) & 1; 00203 } 00204 00205 static unsigned getPlainRelocationLength(const MachOObjectFile *O, 00206 const MachO::any_relocation_info &RE) { 00207 if (O->isLittleEndian()) 00208 return (RE.r_word1 >> 25) & 3; 00209 return (RE.r_word1 >> 5) & 3; 00210 } 00211 00212 static unsigned 00213 getScatteredRelocationLength(const MachO::any_relocation_info &RE) { 00214 return (RE.r_word0 >> 28) & 3; 00215 } 00216 00217 static unsigned getPlainRelocationType(const MachOObjectFile *O, 00218 const MachO::any_relocation_info &RE) { 00219 if (O->isLittleEndian()) 00220 return RE.r_word1 >> 28; 00221 return RE.r_word1 & 0xf; 00222 } 00223 00224 static unsigned 00225 getScatteredRelocationType(const MachO::any_relocation_info &RE) { 00226 return (RE.r_word0 >> 24) & 0xf; 00227 } 00228 00229 static uint32_t getSectionFlags(const MachOObjectFile *O, 00230 DataRefImpl Sec) { 00231 if (O->is64Bit()) { 00232 MachO::section_64 Sect = O->getSection64(Sec); 00233 return Sect.flags; 00234 } 00235 MachO::section Sect = O->getSection(Sec); 00236 return Sect.flags; 00237 } 00238 00239 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian, 00240 bool Is64bits, std::error_code &EC) 00241 : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object), 00242 SymtabLoadCmd(nullptr), DysymtabLoadCmd(nullptr), 00243 DataInCodeLoadCmd(nullptr), DyldInfoLoadCmd(nullptr), 00244 HasPageZeroSegment(false) { 00245 uint32_t LoadCommandCount = this->getHeader().ncmds; 00246 MachO::LoadCommandType SegmentLoadType = is64Bit() ? 00247 MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT; 00248 00249 MachOObjectFile::LoadCommandInfo Load = getFirstLoadCommandInfo(); 00250 for (unsigned I = 0; ; ++I) { 00251 if (Load.C.cmd == MachO::LC_SYMTAB) { 00252 assert(!SymtabLoadCmd && "Multiple symbol tables"); 00253 SymtabLoadCmd = Load.Ptr; 00254 } else if (Load.C.cmd == MachO::LC_DYSYMTAB) { 00255 assert(!DysymtabLoadCmd && "Multiple dynamic symbol tables"); 00256 DysymtabLoadCmd = Load.Ptr; 00257 } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) { 00258 assert(!DataInCodeLoadCmd && "Multiple data in code tables"); 00259 DataInCodeLoadCmd = Load.Ptr; 00260 } else if (Load.C.cmd == MachO::LC_DYLD_INFO || 00261 Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) { 00262 assert(!DyldInfoLoadCmd && "Multiple dyldinfo load commands"); 00263 DyldInfoLoadCmd = Load.Ptr; 00264 } else if (Load.C.cmd == SegmentLoadType) { 00265 uint32_t NumSections = getSegmentLoadCommandNumSections(this, Load); 00266 for (unsigned J = 0; J < NumSections; ++J) { 00267 const char *Sec = getSectionPtr(this, Load, J); 00268 Sections.push_back(Sec); 00269 } 00270 if (isPageZeroSegment(this, Load)) 00271 HasPageZeroSegment = true; 00272 } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB || 00273 Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB || 00274 Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB || 00275 Load.C.cmd == MachO::LC_REEXPORT_DYLIB || 00276 Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) { 00277 Libraries.push_back(Load.Ptr); 00278 } 00279 00280 if (I == LoadCommandCount - 1) 00281 break; 00282 else 00283 Load = getNextLoadCommandInfo(Load); 00284 } 00285 } 00286 00287 void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const { 00288 unsigned SymbolTableEntrySize = is64Bit() ? 00289 sizeof(MachO::nlist_64) : 00290 sizeof(MachO::nlist); 00291 Symb.p += SymbolTableEntrySize; 00292 } 00293 00294 std::error_code MachOObjectFile::getSymbolName(DataRefImpl Symb, 00295 StringRef &Res) const { 00296 StringRef StringTable = getStringTableData(); 00297 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 00298 const char *Start = &StringTable.data()[Entry.n_strx]; 00299 Res = StringRef(Start); 00300 return object_error::success; 00301 } 00302 00303 // getIndirectName() returns the name of the alias'ed symbol who's string table 00304 // index is in the n_value field. 00305 std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb, 00306 StringRef &Res) const { 00307 StringRef StringTable = getStringTableData(); 00308 uint64_t NValue; 00309 if (is64Bit()) { 00310 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 00311 NValue = Entry.n_value; 00312 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 00313 return object_error::parse_failed; 00314 } else { 00315 MachO::nlist Entry = getSymbolTableEntry(Symb); 00316 NValue = Entry.n_value; 00317 if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR) 00318 return object_error::parse_failed; 00319 } 00320 if (NValue >= StringTable.size()) 00321 return object_error::parse_failed; 00322 const char *Start = &StringTable.data()[NValue]; 00323 Res = StringRef(Start); 00324 return object_error::success; 00325 } 00326 00327 std::error_code MachOObjectFile::getSymbolAddress(DataRefImpl Symb, 00328 uint64_t &Res) const { 00329 if (is64Bit()) { 00330 MachO::nlist_64 Entry = getSymbol64TableEntry(Symb); 00331 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 00332 Entry.n_value == 0) 00333 Res = UnknownAddressOrSize; 00334 else 00335 Res = Entry.n_value; 00336 } else { 00337 MachO::nlist Entry = getSymbolTableEntry(Symb); 00338 if ((Entry.n_type & MachO::N_TYPE) == MachO::N_UNDF && 00339 Entry.n_value == 0) 00340 Res = UnknownAddressOrSize; 00341 else 00342 Res = Entry.n_value; 00343 } 00344 return object_error::success; 00345 } 00346 00347 std::error_code MachOObjectFile::getSymbolAlignment(DataRefImpl DRI, 00348 uint32_t &Result) const { 00349 uint32_t flags = getSymbolFlags(DRI); 00350 if (flags & SymbolRef::SF_Common) { 00351 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 00352 Result = 1 << MachO::GET_COMM_ALIGN(Entry.n_desc); 00353 } else { 00354 Result = 0; 00355 } 00356 return object_error::success; 00357 } 00358 00359 std::error_code MachOObjectFile::getSymbolSize(DataRefImpl DRI, 00360 uint64_t &Result) const { 00361 uint64_t BeginOffset; 00362 uint64_t EndOffset = 0; 00363 uint8_t SectionIndex; 00364 00365 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 00366 uint64_t Value; 00367 getSymbolAddress(DRI, Value); 00368 if (Value == UnknownAddressOrSize) { 00369 Result = UnknownAddressOrSize; 00370 return object_error::success; 00371 } 00372 00373 BeginOffset = Value; 00374 00375 SectionIndex = Entry.n_sect; 00376 if (!SectionIndex) { 00377 uint32_t flags = getSymbolFlags(DRI); 00378 if (flags & SymbolRef::SF_Common) 00379 Result = Value; 00380 else 00381 Result = UnknownAddressOrSize; 00382 return object_error::success; 00383 } 00384 // Unfortunately symbols are unsorted so we need to touch all 00385 // symbols from load command 00386 for (const SymbolRef &Symbol : symbols()) { 00387 DataRefImpl DRI = Symbol.getRawDataRefImpl(); 00388 Entry = getSymbolTableEntryBase(this, DRI); 00389 getSymbolAddress(DRI, Value); 00390 if (Value == UnknownAddressOrSize) 00391 continue; 00392 if (Entry.n_sect == SectionIndex && Value > BeginOffset) 00393 if (!EndOffset || Value < EndOffset) 00394 EndOffset = Value; 00395 } 00396 if (!EndOffset) { 00397 uint64_t Size; 00398 DataRefImpl Sec; 00399 Sec.d.a = SectionIndex-1; 00400 getSectionSize(Sec, Size); 00401 getSectionAddress(Sec, EndOffset); 00402 EndOffset += Size; 00403 } 00404 Result = EndOffset - BeginOffset; 00405 return object_error::success; 00406 } 00407 00408 std::error_code MachOObjectFile::getSymbolType(DataRefImpl Symb, 00409 SymbolRef::Type &Res) const { 00410 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 00411 uint8_t n_type = Entry.n_type; 00412 00413 Res = SymbolRef::ST_Other; 00414 00415 // If this is a STAB debugging symbol, we can do nothing more. 00416 if (n_type & MachO::N_STAB) { 00417 Res = SymbolRef::ST_Debug; 00418 return object_error::success; 00419 } 00420 00421 switch (n_type & MachO::N_TYPE) { 00422 case MachO::N_UNDF : 00423 Res = SymbolRef::ST_Unknown; 00424 break; 00425 case MachO::N_SECT : 00426 Res = SymbolRef::ST_Function; 00427 break; 00428 } 00429 return object_error::success; 00430 } 00431 00432 uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const { 00433 MachO::nlist_base Entry = getSymbolTableEntryBase(this, DRI); 00434 00435 uint8_t MachOType = Entry.n_type; 00436 uint16_t MachOFlags = Entry.n_desc; 00437 00438 uint32_t Result = SymbolRef::SF_None; 00439 00440 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) 00441 Result |= SymbolRef::SF_Undefined; 00442 00443 if ((MachOType & MachO::N_TYPE) == MachO::N_INDR) 00444 Result |= SymbolRef::SF_Indirect; 00445 00446 if (MachOType & MachO::N_STAB) 00447 Result |= SymbolRef::SF_FormatSpecific; 00448 00449 if (MachOType & MachO::N_EXT) { 00450 Result |= SymbolRef::SF_Global; 00451 if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) { 00452 uint64_t Value; 00453 getSymbolAddress(DRI, Value); 00454 if (Value && Value != UnknownAddressOrSize) 00455 Result |= SymbolRef::SF_Common; 00456 } 00457 } 00458 00459 if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 00460 Result |= SymbolRef::SF_Weak; 00461 00462 if (MachOFlags & (MachO::N_ARM_THUMB_DEF)) 00463 Result |= SymbolRef::SF_Thumb; 00464 00465 if ((MachOType & MachO::N_TYPE) == MachO::N_ABS) 00466 Result |= SymbolRef::SF_Absolute; 00467 00468 return Result; 00469 } 00470 00471 std::error_code MachOObjectFile::getSymbolSection(DataRefImpl Symb, 00472 section_iterator &Res) const { 00473 MachO::nlist_base Entry = getSymbolTableEntryBase(this, Symb); 00474 uint8_t index = Entry.n_sect; 00475 00476 if (index == 0) { 00477 Res = section_end(); 00478 } else { 00479 DataRefImpl DRI; 00480 DRI.d.a = index - 1; 00481 Res = section_iterator(SectionRef(DRI, this)); 00482 } 00483 00484 return object_error::success; 00485 } 00486 00487 void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const { 00488 Sec.d.a++; 00489 } 00490 00491 std::error_code MachOObjectFile::getSectionName(DataRefImpl Sec, 00492 StringRef &Result) const { 00493 ArrayRef<char> Raw = getSectionRawName(Sec); 00494 Result = parseSegmentOrSectionName(Raw.data()); 00495 return object_error::success; 00496 } 00497 00498 std::error_code MachOObjectFile::getSectionAddress(DataRefImpl Sec, 00499 uint64_t &Res) const { 00500 if (is64Bit()) { 00501 MachO::section_64 Sect = getSection64(Sec); 00502 Res = Sect.addr; 00503 } else { 00504 MachO::section Sect = getSection(Sec); 00505 Res = Sect.addr; 00506 } 00507 return object_error::success; 00508 } 00509 00510 std::error_code MachOObjectFile::getSectionSize(DataRefImpl Sec, 00511 uint64_t &Res) const { 00512 if (is64Bit()) { 00513 MachO::section_64 Sect = getSection64(Sec); 00514 Res = Sect.size; 00515 } else { 00516 MachO::section Sect = getSection(Sec); 00517 Res = Sect.size; 00518 } 00519 00520 return object_error::success; 00521 } 00522 00523 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec, 00524 StringRef &Res) const { 00525 uint32_t Offset; 00526 uint64_t Size; 00527 00528 if (is64Bit()) { 00529 MachO::section_64 Sect = getSection64(Sec); 00530 Offset = Sect.offset; 00531 Size = Sect.size; 00532 } else { 00533 MachO::section Sect = getSection(Sec); 00534 Offset = Sect.offset; 00535 Size = Sect.size; 00536 } 00537 00538 Res = this->getData().substr(Offset, Size); 00539 return object_error::success; 00540 } 00541 00542 std::error_code MachOObjectFile::getSectionAlignment(DataRefImpl Sec, 00543 uint64_t &Res) const { 00544 uint32_t Align; 00545 if (is64Bit()) { 00546 MachO::section_64 Sect = getSection64(Sec); 00547 Align = Sect.align; 00548 } else { 00549 MachO::section Sect = getSection(Sec); 00550 Align = Sect.align; 00551 } 00552 00553 Res = uint64_t(1) << Align; 00554 return object_error::success; 00555 } 00556 00557 std::error_code MachOObjectFile::isSectionText(DataRefImpl Sec, 00558 bool &Res) const { 00559 uint32_t Flags = getSectionFlags(this, Sec); 00560 Res = Flags & MachO::S_ATTR_PURE_INSTRUCTIONS; 00561 return object_error::success; 00562 } 00563 00564 std::error_code MachOObjectFile::isSectionData(DataRefImpl Sec, 00565 bool &Result) const { 00566 uint32_t Flags = getSectionFlags(this, Sec); 00567 unsigned SectionType = Flags & MachO::SECTION_TYPE; 00568 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 00569 !(SectionType == MachO::S_ZEROFILL || 00570 SectionType == MachO::S_GB_ZEROFILL); 00571 return object_error::success; 00572 } 00573 00574 std::error_code MachOObjectFile::isSectionBSS(DataRefImpl Sec, 00575 bool &Result) const { 00576 uint32_t Flags = getSectionFlags(this, Sec); 00577 unsigned SectionType = Flags & MachO::SECTION_TYPE; 00578 Result = !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) && 00579 (SectionType == MachO::S_ZEROFILL || 00580 SectionType == MachO::S_GB_ZEROFILL); 00581 return object_error::success; 00582 } 00583 00584 std::error_code 00585 MachOObjectFile::isSectionRequiredForExecution(DataRefImpl Sec, 00586 bool &Result) const { 00587 // FIXME: Unimplemented. 00588 Result = true; 00589 return object_error::success; 00590 } 00591 00592 std::error_code MachOObjectFile::isSectionVirtual(DataRefImpl Sec, 00593 bool &Result) const { 00594 // FIXME: Unimplemented. 00595 Result = false; 00596 return object_error::success; 00597 } 00598 00599 std::error_code MachOObjectFile::isSectionZeroInit(DataRefImpl Sec, 00600 bool &Res) const { 00601 uint32_t Flags = getSectionFlags(this, Sec); 00602 unsigned SectionType = Flags & MachO::SECTION_TYPE; 00603 Res = SectionType == MachO::S_ZEROFILL || 00604 SectionType == MachO::S_GB_ZEROFILL; 00605 return object_error::success; 00606 } 00607 00608 std::error_code MachOObjectFile::isSectionReadOnlyData(DataRefImpl Sec, 00609 bool &Result) const { 00610 // Consider using the code from isSectionText to look for __const sections. 00611 // Alternately, emit S_ATTR_PURE_INSTRUCTIONS and/or S_ATTR_SOME_INSTRUCTIONS 00612 // to use section attributes to distinguish code from data. 00613 00614 // FIXME: Unimplemented. 00615 Result = false; 00616 return object_error::success; 00617 } 00618 00619 std::error_code MachOObjectFile::sectionContainsSymbol(DataRefImpl Sec, 00620 DataRefImpl Symb, 00621 bool &Result) const { 00622 SymbolRef::Type ST; 00623 this->getSymbolType(Symb, ST); 00624 if (ST == SymbolRef::ST_Unknown) { 00625 Result = false; 00626 return object_error::success; 00627 } 00628 00629 uint64_t SectBegin, SectEnd; 00630 getSectionAddress(Sec, SectBegin); 00631 getSectionSize(Sec, SectEnd); 00632 SectEnd += SectBegin; 00633 00634 uint64_t SymAddr; 00635 getSymbolAddress(Symb, SymAddr); 00636 Result = (SymAddr >= SectBegin) && (SymAddr < SectEnd); 00637 00638 return object_error::success; 00639 } 00640 00641 relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const { 00642 DataRefImpl Ret; 00643 Ret.d.a = Sec.d.a; 00644 Ret.d.b = 0; 00645 return relocation_iterator(RelocationRef(Ret, this)); 00646 } 00647 00648 relocation_iterator 00649 MachOObjectFile::section_rel_end(DataRefImpl Sec) const { 00650 uint32_t Num; 00651 if (is64Bit()) { 00652 MachO::section_64 Sect = getSection64(Sec); 00653 Num = Sect.nreloc; 00654 } else { 00655 MachO::section Sect = getSection(Sec); 00656 Num = Sect.nreloc; 00657 } 00658 00659 DataRefImpl Ret; 00660 Ret.d.a = Sec.d.a; 00661 Ret.d.b = Num; 00662 return relocation_iterator(RelocationRef(Ret, this)); 00663 } 00664 00665 void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const { 00666 ++Rel.d.b; 00667 } 00668 00669 std::error_code MachOObjectFile::getRelocationAddress(DataRefImpl Rel, 00670 uint64_t &Res) const { 00671 uint64_t Offset; 00672 getRelocationOffset(Rel, Offset); 00673 00674 DataRefImpl Sec; 00675 Sec.d.a = Rel.d.a; 00676 uint64_t SecAddress; 00677 getSectionAddress(Sec, SecAddress); 00678 Res = SecAddress + Offset; 00679 return object_error::success; 00680 } 00681 00682 std::error_code MachOObjectFile::getRelocationOffset(DataRefImpl Rel, 00683 uint64_t &Res) const { 00684 assert(getHeader().filetype == MachO::MH_OBJECT && 00685 "Only implemented for MH_OBJECT"); 00686 MachO::any_relocation_info RE = getRelocation(Rel); 00687 Res = getAnyRelocationAddress(RE); 00688 return object_error::success; 00689 } 00690 00691 symbol_iterator 00692 MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const { 00693 MachO::any_relocation_info RE = getRelocation(Rel); 00694 if (isRelocationScattered(RE)) 00695 return symbol_end(); 00696 00697 uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE); 00698 bool isExtern = getPlainRelocationExternal(RE); 00699 if (!isExtern) 00700 return symbol_end(); 00701 00702 MachO::symtab_command S = getSymtabLoadCommand(); 00703 unsigned SymbolTableEntrySize = is64Bit() ? 00704 sizeof(MachO::nlist_64) : 00705 sizeof(MachO::nlist); 00706 uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize; 00707 DataRefImpl Sym; 00708 Sym.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 00709 return symbol_iterator(SymbolRef(Sym, this)); 00710 } 00711 00712 std::error_code MachOObjectFile::getRelocationType(DataRefImpl Rel, 00713 uint64_t &Res) const { 00714 MachO::any_relocation_info RE = getRelocation(Rel); 00715 Res = getAnyRelocationType(RE); 00716 return object_error::success; 00717 } 00718 00719 std::error_code 00720 MachOObjectFile::getRelocationTypeName(DataRefImpl Rel, 00721 SmallVectorImpl<char> &Result) const { 00722 StringRef res; 00723 uint64_t RType; 00724 getRelocationType(Rel, RType); 00725 00726 unsigned Arch = this->getArch(); 00727 00728 switch (Arch) { 00729 case Triple::x86: { 00730 static const char *const Table[] = { 00731 "GENERIC_RELOC_VANILLA", 00732 "GENERIC_RELOC_PAIR", 00733 "GENERIC_RELOC_SECTDIFF", 00734 "GENERIC_RELOC_PB_LA_PTR", 00735 "GENERIC_RELOC_LOCAL_SECTDIFF", 00736 "GENERIC_RELOC_TLV" }; 00737 00738 if (RType > 5) 00739 res = "Unknown"; 00740 else 00741 res = Table[RType]; 00742 break; 00743 } 00744 case Triple::x86_64: { 00745 static const char *const Table[] = { 00746 "X86_64_RELOC_UNSIGNED", 00747 "X86_64_RELOC_SIGNED", 00748 "X86_64_RELOC_BRANCH", 00749 "X86_64_RELOC_GOT_LOAD", 00750 "X86_64_RELOC_GOT", 00751 "X86_64_RELOC_SUBTRACTOR", 00752 "X86_64_RELOC_SIGNED_1", 00753 "X86_64_RELOC_SIGNED_2", 00754 "X86_64_RELOC_SIGNED_4", 00755 "X86_64_RELOC_TLV" }; 00756 00757 if (RType > 9) 00758 res = "Unknown"; 00759 else 00760 res = Table[RType]; 00761 break; 00762 } 00763 case Triple::arm: { 00764 static const char *const Table[] = { 00765 "ARM_RELOC_VANILLA", 00766 "ARM_RELOC_PAIR", 00767 "ARM_RELOC_SECTDIFF", 00768 "ARM_RELOC_LOCAL_SECTDIFF", 00769 "ARM_RELOC_PB_LA_PTR", 00770 "ARM_RELOC_BR24", 00771 "ARM_THUMB_RELOC_BR22", 00772 "ARM_THUMB_32BIT_BRANCH", 00773 "ARM_RELOC_HALF", 00774 "ARM_RELOC_HALF_SECTDIFF" }; 00775 00776 if (RType > 9) 00777 res = "Unknown"; 00778 else 00779 res = Table[RType]; 00780 break; 00781 } 00782 case Triple::aarch64: { 00783 static const char *const Table[] = { 00784 "ARM64_RELOC_UNSIGNED", "ARM64_RELOC_SUBTRACTOR", 00785 "ARM64_RELOC_BRANCH26", "ARM64_RELOC_PAGE21", 00786 "ARM64_RELOC_PAGEOFF12", "ARM64_RELOC_GOT_LOAD_PAGE21", 00787 "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT", 00788 "ARM64_RELOC_TLVP_LOAD_PAGE21", "ARM64_RELOC_TLVP_LOAD_PAGEOFF12", 00789 "ARM64_RELOC_ADDEND" 00790 }; 00791 00792 if (RType >= array_lengthof(Table)) 00793 res = "Unknown"; 00794 else 00795 res = Table[RType]; 00796 break; 00797 } 00798 case Triple::ppc: { 00799 static const char *const Table[] = { 00800 "PPC_RELOC_VANILLA", 00801 "PPC_RELOC_PAIR", 00802 "PPC_RELOC_BR14", 00803 "PPC_RELOC_BR24", 00804 "PPC_RELOC_HI16", 00805 "PPC_RELOC_LO16", 00806 "PPC_RELOC_HA16", 00807 "PPC_RELOC_LO14", 00808 "PPC_RELOC_SECTDIFF", 00809 "PPC_RELOC_PB_LA_PTR", 00810 "PPC_RELOC_HI16_SECTDIFF", 00811 "PPC_RELOC_LO16_SECTDIFF", 00812 "PPC_RELOC_HA16_SECTDIFF", 00813 "PPC_RELOC_JBSR", 00814 "PPC_RELOC_LO14_SECTDIFF", 00815 "PPC_RELOC_LOCAL_SECTDIFF" }; 00816 00817 if (RType > 15) 00818 res = "Unknown"; 00819 else 00820 res = Table[RType]; 00821 break; 00822 } 00823 case Triple::UnknownArch: 00824 res = "Unknown"; 00825 break; 00826 } 00827 Result.append(res.begin(), res.end()); 00828 return object_error::success; 00829 } 00830 00831 std::error_code 00832 MachOObjectFile::getRelocationValueString(DataRefImpl Rel, 00833 SmallVectorImpl<char> &Result) const { 00834 MachO::any_relocation_info RE = getRelocation(Rel); 00835 00836 unsigned Arch = this->getArch(); 00837 00838 std::string fmtbuf; 00839 raw_string_ostream fmt(fmtbuf); 00840 unsigned Type = this->getAnyRelocationType(RE); 00841 bool IsPCRel = this->getAnyRelocationPCRel(RE); 00842 00843 // Determine any addends that should be displayed with the relocation. 00844 // These require decoding the relocation type, which is triple-specific. 00845 00846 // X86_64 has entirely custom relocation types. 00847 if (Arch == Triple::x86_64) { 00848 bool isPCRel = getAnyRelocationPCRel(RE); 00849 00850 switch (Type) { 00851 case MachO::X86_64_RELOC_GOT_LOAD: 00852 case MachO::X86_64_RELOC_GOT: { 00853 printRelocationTargetName(this, RE, fmt); 00854 fmt << "@GOT"; 00855 if (isPCRel) fmt << "PCREL"; 00856 break; 00857 } 00858 case MachO::X86_64_RELOC_SUBTRACTOR: { 00859 DataRefImpl RelNext = Rel; 00860 moveRelocationNext(RelNext); 00861 MachO::any_relocation_info RENext = getRelocation(RelNext); 00862 00863 // X86_64_RELOC_SUBTRACTOR must be followed by a relocation of type 00864 // X86_64_RELOC_UNSIGNED. 00865 // NOTE: Scattered relocations don't exist on x86_64. 00866 unsigned RType = getAnyRelocationType(RENext); 00867 if (RType != MachO::X86_64_RELOC_UNSIGNED) 00868 report_fatal_error("Expected X86_64_RELOC_UNSIGNED after " 00869 "X86_64_RELOC_SUBTRACTOR."); 00870 00871 // The X86_64_RELOC_UNSIGNED contains the minuend symbol; 00872 // X86_64_RELOC_SUBTRACTOR contains the subtrahend. 00873 printRelocationTargetName(this, RENext, fmt); 00874 fmt << "-"; 00875 printRelocationTargetName(this, RE, fmt); 00876 break; 00877 } 00878 case MachO::X86_64_RELOC_TLV: 00879 printRelocationTargetName(this, RE, fmt); 00880 fmt << "@TLV"; 00881 if (isPCRel) fmt << "P"; 00882 break; 00883 case MachO::X86_64_RELOC_SIGNED_1: 00884 printRelocationTargetName(this, RE, fmt); 00885 fmt << "-1"; 00886 break; 00887 case MachO::X86_64_RELOC_SIGNED_2: 00888 printRelocationTargetName(this, RE, fmt); 00889 fmt << "-2"; 00890 break; 00891 case MachO::X86_64_RELOC_SIGNED_4: 00892 printRelocationTargetName(this, RE, fmt); 00893 fmt << "-4"; 00894 break; 00895 default: 00896 printRelocationTargetName(this, RE, fmt); 00897 break; 00898 } 00899 // X86 and ARM share some relocation types in common. 00900 } else if (Arch == Triple::x86 || Arch == Triple::arm || 00901 Arch == Triple::ppc) { 00902 // Generic relocation types... 00903 switch (Type) { 00904 case MachO::GENERIC_RELOC_PAIR: // prints no info 00905 return object_error::success; 00906 case MachO::GENERIC_RELOC_SECTDIFF: { 00907 DataRefImpl RelNext = Rel; 00908 moveRelocationNext(RelNext); 00909 MachO::any_relocation_info RENext = getRelocation(RelNext); 00910 00911 // X86 sect diff's must be followed by a relocation of type 00912 // GENERIC_RELOC_PAIR. 00913 unsigned RType = getAnyRelocationType(RENext); 00914 00915 if (RType != MachO::GENERIC_RELOC_PAIR) 00916 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 00917 "GENERIC_RELOC_SECTDIFF."); 00918 00919 printRelocationTargetName(this, RE, fmt); 00920 fmt << "-"; 00921 printRelocationTargetName(this, RENext, fmt); 00922 break; 00923 } 00924 } 00925 00926 if (Arch == Triple::x86 || Arch == Triple::ppc) { 00927 switch (Type) { 00928 case MachO::GENERIC_RELOC_LOCAL_SECTDIFF: { 00929 DataRefImpl RelNext = Rel; 00930 moveRelocationNext(RelNext); 00931 MachO::any_relocation_info RENext = getRelocation(RelNext); 00932 00933 // X86 sect diff's must be followed by a relocation of type 00934 // GENERIC_RELOC_PAIR. 00935 unsigned RType = getAnyRelocationType(RENext); 00936 if (RType != MachO::GENERIC_RELOC_PAIR) 00937 report_fatal_error("Expected GENERIC_RELOC_PAIR after " 00938 "GENERIC_RELOC_LOCAL_SECTDIFF."); 00939 00940 printRelocationTargetName(this, RE, fmt); 00941 fmt << "-"; 00942 printRelocationTargetName(this, RENext, fmt); 00943 break; 00944 } 00945 case MachO::GENERIC_RELOC_TLV: { 00946 printRelocationTargetName(this, RE, fmt); 00947 fmt << "@TLV"; 00948 if (IsPCRel) fmt << "P"; 00949 break; 00950 } 00951 default: 00952 printRelocationTargetName(this, RE, fmt); 00953 } 00954 } else { // ARM-specific relocations 00955 switch (Type) { 00956 case MachO::ARM_RELOC_HALF: 00957 case MachO::ARM_RELOC_HALF_SECTDIFF: { 00958 // Half relocations steal a bit from the length field to encode 00959 // whether this is an upper16 or a lower16 relocation. 00960 bool isUpper = getAnyRelocationLength(RE) >> 1; 00961 00962 if (isUpper) 00963 fmt << ":upper16:("; 00964 else 00965 fmt << ":lower16:("; 00966 printRelocationTargetName(this, RE, fmt); 00967 00968 DataRefImpl RelNext = Rel; 00969 moveRelocationNext(RelNext); 00970 MachO::any_relocation_info RENext = getRelocation(RelNext); 00971 00972 // ARM half relocs must be followed by a relocation of type 00973 // ARM_RELOC_PAIR. 00974 unsigned RType = getAnyRelocationType(RENext); 00975 if (RType != MachO::ARM_RELOC_PAIR) 00976 report_fatal_error("Expected ARM_RELOC_PAIR after " 00977 "ARM_RELOC_HALF"); 00978 00979 // NOTE: The half of the target virtual address is stashed in the 00980 // address field of the secondary relocation, but we can't reverse 00981 // engineer the constant offset from it without decoding the movw/movt 00982 // instruction to find the other half in its immediate field. 00983 00984 // ARM_RELOC_HALF_SECTDIFF encodes the second section in the 00985 // symbol/section pointer of the follow-on relocation. 00986 if (Type == MachO::ARM_RELOC_HALF_SECTDIFF) { 00987 fmt << "-"; 00988 printRelocationTargetName(this, RENext, fmt); 00989 } 00990 00991 fmt << ")"; 00992 break; 00993 } 00994 default: { 00995 printRelocationTargetName(this, RE, fmt); 00996 } 00997 } 00998 } 00999 } else 01000 printRelocationTargetName(this, RE, fmt); 01001 01002 fmt.flush(); 01003 Result.append(fmtbuf.begin(), fmtbuf.end()); 01004 return object_error::success; 01005 } 01006 01007 std::error_code MachOObjectFile::getRelocationHidden(DataRefImpl Rel, 01008 bool &Result) const { 01009 unsigned Arch = getArch(); 01010 uint64_t Type; 01011 getRelocationType(Rel, Type); 01012 01013 Result = false; 01014 01015 // On arches that use the generic relocations, GENERIC_RELOC_PAIR 01016 // is always hidden. 01017 if (Arch == Triple::x86 || Arch == Triple::arm || Arch == Triple::ppc) { 01018 if (Type == MachO::GENERIC_RELOC_PAIR) Result = true; 01019 } else if (Arch == Triple::x86_64) { 01020 // On x86_64, X86_64_RELOC_UNSIGNED is hidden only when it follows 01021 // an X86_64_RELOC_SUBTRACTOR. 01022 if (Type == MachO::X86_64_RELOC_UNSIGNED && Rel.d.a > 0) { 01023 DataRefImpl RelPrev = Rel; 01024 RelPrev.d.a--; 01025 uint64_t PrevType; 01026 getRelocationType(RelPrev, PrevType); 01027 if (PrevType == MachO::X86_64_RELOC_SUBTRACTOR) 01028 Result = true; 01029 } 01030 } 01031 01032 return object_error::success; 01033 } 01034 01035 // 01036 // guessLibraryShortName() is passed a name of a dynamic library and returns a 01037 // guess on what the short name is. Then name is returned as a substring of the 01038 // StringRef Name passed in. The name of the dynamic library is recognized as 01039 // a framework if it has one of the two following forms: 01040 // Foo.framework/Versions/A/Foo 01041 // Foo.framework/Foo 01042 // Where A and Foo can be any string. And may contain a trailing suffix 01043 // starting with an underbar. If the Name is recognized as a framework then 01044 // isFramework is set to true else it is set to false. If the Name has a 01045 // suffix then Suffix is set to the substring in Name that contains the suffix 01046 // else it is set to a NULL StringRef. 01047 // 01048 // The Name of the dynamic library is recognized as a library name if it has 01049 // one of the two following forms: 01050 // libFoo.A.dylib 01051 // libFoo.dylib 01052 // The library may have a suffix trailing the name Foo of the form: 01053 // libFoo_profile.A.dylib 01054 // libFoo_profile.dylib 01055 // 01056 // The Name of the dynamic library is also recognized as a library name if it 01057 // has the following form: 01058 // Foo.qtx 01059 // 01060 // If the Name of the dynamic library is none of the forms above then a NULL 01061 // StringRef is returned. 01062 // 01063 StringRef MachOObjectFile::guessLibraryShortName(StringRef Name, 01064 bool &isFramework, 01065 StringRef &Suffix) { 01066 StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx; 01067 size_t a, b, c, d, Idx; 01068 01069 isFramework = false; 01070 Suffix = StringRef(); 01071 01072 // Pull off the last component and make Foo point to it 01073 a = Name.rfind('/'); 01074 if (a == Name.npos || a == 0) 01075 goto guess_library; 01076 Foo = Name.slice(a+1, Name.npos); 01077 01078 // Look for a suffix starting with a '_' 01079 Idx = Foo.rfind('_'); 01080 if (Idx != Foo.npos && Foo.size() >= 2) { 01081 Suffix = Foo.slice(Idx, Foo.npos); 01082 Foo = Foo.slice(0, Idx); 01083 } 01084 01085 // First look for the form Foo.framework/Foo 01086 b = Name.rfind('/', a); 01087 if (b == Name.npos) 01088 Idx = 0; 01089 else 01090 Idx = b+1; 01091 F = Name.slice(Idx, Idx + Foo.size()); 01092 DotFramework = Name.slice(Idx + Foo.size(), 01093 Idx + Foo.size() + sizeof(".framework/")-1); 01094 if (F == Foo && DotFramework == ".framework/") { 01095 isFramework = true; 01096 return Foo; 01097 } 01098 01099 // Next look for the form Foo.framework/Versions/A/Foo 01100 if (b == Name.npos) 01101 goto guess_library; 01102 c = Name.rfind('/', b); 01103 if (c == Name.npos || c == 0) 01104 goto guess_library; 01105 V = Name.slice(c+1, Name.npos); 01106 if (!V.startswith("Versions/")) 01107 goto guess_library; 01108 d = Name.rfind('/', c); 01109 if (d == Name.npos) 01110 Idx = 0; 01111 else 01112 Idx = d+1; 01113 F = Name.slice(Idx, Idx + Foo.size()); 01114 DotFramework = Name.slice(Idx + Foo.size(), 01115 Idx + Foo.size() + sizeof(".framework/")-1); 01116 if (F == Foo && DotFramework == ".framework/") { 01117 isFramework = true; 01118 return Foo; 01119 } 01120 01121 guess_library: 01122 // pull off the suffix after the "." and make a point to it 01123 a = Name.rfind('.'); 01124 if (a == Name.npos || a == 0) 01125 return StringRef(); 01126 Dylib = Name.slice(a, Name.npos); 01127 if (Dylib != ".dylib") 01128 goto guess_qtx; 01129 01130 // First pull off the version letter for the form Foo.A.dylib if any. 01131 if (a >= 3) { 01132 Dot = Name.slice(a-2, a-1); 01133 if (Dot == ".") 01134 a = a - 2; 01135 } 01136 01137 b = Name.rfind('/', a); 01138 if (b == Name.npos) 01139 b = 0; 01140 else 01141 b = b+1; 01142 // ignore any suffix after an underbar like Foo_profile.A.dylib 01143 Idx = Name.find('_', b); 01144 if (Idx != Name.npos && Idx != b) { 01145 Lib = Name.slice(b, Idx); 01146 Suffix = Name.slice(Idx, a); 01147 } 01148 else 01149 Lib = Name.slice(b, a); 01150 // There are incorrect library names of the form: 01151 // libATS.A_profile.dylib so check for these. 01152 if (Lib.size() >= 3) { 01153 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 01154 if (Dot == ".") 01155 Lib = Lib.slice(0, Lib.size()-2); 01156 } 01157 return Lib; 01158 01159 guess_qtx: 01160 Qtx = Name.slice(a, Name.npos); 01161 if (Qtx != ".qtx") 01162 return StringRef(); 01163 b = Name.rfind('/', a); 01164 if (b == Name.npos) 01165 Lib = Name.slice(0, a); 01166 else 01167 Lib = Name.slice(b+1, a); 01168 // There are library names of the form: QT.A.qtx so check for these. 01169 if (Lib.size() >= 3) { 01170 Dot = Lib.slice(Lib.size()-2, Lib.size()-1); 01171 if (Dot == ".") 01172 Lib = Lib.slice(0, Lib.size()-2); 01173 } 01174 return Lib; 01175 } 01176 01177 // getLibraryShortNameByIndex() is used to get the short name of the library 01178 // for an undefined symbol in a linked Mach-O binary that was linked with the 01179 // normal two-level namespace default (that is MH_TWOLEVEL in the header). 01180 // It is passed the index (0 - based) of the library as translated from 01181 // GET_LIBRARY_ORDINAL (1 - based). 01182 std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index, 01183 StringRef &Res) const { 01184 if (Index >= Libraries.size()) 01185 return object_error::parse_failed; 01186 01187 // If the cache of LibrariesShortNames is not built up do that first for 01188 // all the Libraries. 01189 if (LibrariesShortNames.size() == 0) { 01190 for (unsigned i = 0; i < Libraries.size(); i++) { 01191 MachO::dylib_command D = 01192 getStruct<MachO::dylib_command>(this, Libraries[i]); 01193 if (D.dylib.name >= D.cmdsize) 01194 return object_error::parse_failed; 01195 const char *P = (const char *)(Libraries[i]) + D.dylib.name; 01196 StringRef Name = StringRef(P); 01197 if (D.dylib.name+Name.size() >= D.cmdsize) 01198 return object_error::parse_failed; 01199 StringRef Suffix; 01200 bool isFramework; 01201 StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix); 01202 if (shortName.empty()) 01203 LibrariesShortNames.push_back(Name); 01204 else 01205 LibrariesShortNames.push_back(shortName); 01206 } 01207 } 01208 01209 Res = LibrariesShortNames[Index]; 01210 return object_error::success; 01211 } 01212 01213 basic_symbol_iterator MachOObjectFile::symbol_begin_impl() const { 01214 return getSymbolByIndex(0); 01215 } 01216 01217 basic_symbol_iterator MachOObjectFile::symbol_end_impl() const { 01218 DataRefImpl DRI; 01219 if (!SymtabLoadCmd) 01220 return basic_symbol_iterator(SymbolRef(DRI, this)); 01221 01222 MachO::symtab_command Symtab = getSymtabLoadCommand(); 01223 unsigned SymbolTableEntrySize = is64Bit() ? 01224 sizeof(MachO::nlist_64) : 01225 sizeof(MachO::nlist); 01226 unsigned Offset = Symtab.symoff + 01227 Symtab.nsyms * SymbolTableEntrySize; 01228 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 01229 return basic_symbol_iterator(SymbolRef(DRI, this)); 01230 } 01231 01232 basic_symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const { 01233 DataRefImpl DRI; 01234 if (!SymtabLoadCmd) 01235 return basic_symbol_iterator(SymbolRef(DRI, this)); 01236 01237 MachO::symtab_command Symtab = getSymtabLoadCommand(); 01238 assert(Index < Symtab.nsyms && "Requested symbol index is out of range."); 01239 unsigned SymbolTableEntrySize = 01240 is64Bit() ? sizeof(MachO::nlist_64) : sizeof(MachO::nlist); 01241 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Symtab.symoff)); 01242 DRI.p += Index * SymbolTableEntrySize; 01243 return basic_symbol_iterator(SymbolRef(DRI, this)); 01244 } 01245 01246 section_iterator MachOObjectFile::section_begin() const { 01247 DataRefImpl DRI; 01248 return section_iterator(SectionRef(DRI, this)); 01249 } 01250 01251 section_iterator MachOObjectFile::section_end() const { 01252 DataRefImpl DRI; 01253 DRI.d.a = Sections.size(); 01254 return section_iterator(SectionRef(DRI, this)); 01255 } 01256 01257 uint8_t MachOObjectFile::getBytesInAddress() const { 01258 return is64Bit() ? 8 : 4; 01259 } 01260 01261 StringRef MachOObjectFile::getFileFormatName() const { 01262 unsigned CPUType = getCPUType(this); 01263 if (!is64Bit()) { 01264 switch (CPUType) { 01265 case llvm::MachO::CPU_TYPE_I386: 01266 return "Mach-O 32-bit i386"; 01267 case llvm::MachO::CPU_TYPE_ARM: 01268 return "Mach-O arm"; 01269 case llvm::MachO::CPU_TYPE_POWERPC: 01270 return "Mach-O 32-bit ppc"; 01271 default: 01272 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) == 0 && 01273 "64-bit object file when we're not 64-bit?"); 01274 return "Mach-O 32-bit unknown"; 01275 } 01276 } 01277 01278 // Make sure the cpu type has the correct mask. 01279 assert((CPUType & llvm::MachO::CPU_ARCH_ABI64) 01280 == llvm::MachO::CPU_ARCH_ABI64 && 01281 "32-bit object file when we're 64-bit?"); 01282 01283 switch (CPUType) { 01284 case llvm::MachO::CPU_TYPE_X86_64: 01285 return "Mach-O 64-bit x86-64"; 01286 case llvm::MachO::CPU_TYPE_ARM64: 01287 return "Mach-O arm64"; 01288 case llvm::MachO::CPU_TYPE_POWERPC64: 01289 return "Mach-O 64-bit ppc64"; 01290 default: 01291 return "Mach-O 64-bit unknown"; 01292 } 01293 } 01294 01295 Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) { 01296 switch (CPUType) { 01297 case llvm::MachO::CPU_TYPE_I386: 01298 return Triple::x86; 01299 case llvm::MachO::CPU_TYPE_X86_64: 01300 return Triple::x86_64; 01301 case llvm::MachO::CPU_TYPE_ARM: 01302 return Triple::arm; 01303 case llvm::MachO::CPU_TYPE_ARM64: 01304 return Triple::aarch64; 01305 case llvm::MachO::CPU_TYPE_POWERPC: 01306 return Triple::ppc; 01307 case llvm::MachO::CPU_TYPE_POWERPC64: 01308 return Triple::ppc64; 01309 default: 01310 return Triple::UnknownArch; 01311 } 01312 } 01313 01314 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, 01315 const char **McpuDefault) { 01316 if (McpuDefault) 01317 *McpuDefault = nullptr; 01318 01319 switch (CPUType) { 01320 case MachO::CPU_TYPE_I386: 01321 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01322 case MachO::CPU_SUBTYPE_I386_ALL: 01323 return Triple("i386-apple-darwin"); 01324 default: 01325 return Triple(); 01326 } 01327 case MachO::CPU_TYPE_X86_64: 01328 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01329 case MachO::CPU_SUBTYPE_X86_64_ALL: 01330 return Triple("x86_64-apple-darwin"); 01331 case MachO::CPU_SUBTYPE_X86_64_H: 01332 return Triple("x86_64h-apple-darwin"); 01333 default: 01334 return Triple(); 01335 } 01336 case MachO::CPU_TYPE_ARM: 01337 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01338 case MachO::CPU_SUBTYPE_ARM_V4T: 01339 return Triple("armv4t-apple-darwin"); 01340 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 01341 return Triple("armv5e-apple-darwin"); 01342 case MachO::CPU_SUBTYPE_ARM_XSCALE: 01343 return Triple("xscale-apple-darwin"); 01344 case MachO::CPU_SUBTYPE_ARM_V6: 01345 return Triple("armv6-apple-darwin"); 01346 case MachO::CPU_SUBTYPE_ARM_V6M: 01347 if (McpuDefault) 01348 *McpuDefault = "cortex-m0"; 01349 return Triple("armv6m-apple-darwin"); 01350 case MachO::CPU_SUBTYPE_ARM_V7: 01351 return Triple("armv7-apple-darwin"); 01352 case MachO::CPU_SUBTYPE_ARM_V7EM: 01353 if (McpuDefault) 01354 *McpuDefault = "cortex-m4"; 01355 return Triple("armv7em-apple-darwin"); 01356 case MachO::CPU_SUBTYPE_ARM_V7K: 01357 return Triple("armv7k-apple-darwin"); 01358 case MachO::CPU_SUBTYPE_ARM_V7M: 01359 if (McpuDefault) 01360 *McpuDefault = "cortex-m3"; 01361 return Triple("armv7m-apple-darwin"); 01362 case MachO::CPU_SUBTYPE_ARM_V7S: 01363 return Triple("armv7s-apple-darwin"); 01364 default: 01365 return Triple(); 01366 } 01367 case MachO::CPU_TYPE_ARM64: 01368 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01369 case MachO::CPU_SUBTYPE_ARM64_ALL: 01370 return Triple("arm64-apple-darwin"); 01371 default: 01372 return Triple(); 01373 } 01374 case MachO::CPU_TYPE_POWERPC: 01375 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01376 case MachO::CPU_SUBTYPE_POWERPC_ALL: 01377 return Triple("ppc-apple-darwin"); 01378 default: 01379 return Triple(); 01380 } 01381 case MachO::CPU_TYPE_POWERPC64: 01382 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01383 case MachO::CPU_SUBTYPE_POWERPC_ALL: 01384 return Triple("ppc64-apple-darwin"); 01385 default: 01386 return Triple(); 01387 } 01388 default: 01389 return Triple(); 01390 } 01391 } 01392 01393 Triple MachOObjectFile::getThumbArch(uint32_t CPUType, uint32_t CPUSubType, 01394 const char **McpuDefault) { 01395 if (McpuDefault) 01396 *McpuDefault = nullptr; 01397 01398 switch (CPUType) { 01399 case MachO::CPU_TYPE_ARM: 01400 switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) { 01401 case MachO::CPU_SUBTYPE_ARM_V4T: 01402 return Triple("thumbv4t-apple-darwin"); 01403 case MachO::CPU_SUBTYPE_ARM_V5TEJ: 01404 return Triple("thumbv5e-apple-darwin"); 01405 case MachO::CPU_SUBTYPE_ARM_XSCALE: 01406 return Triple("xscale-apple-darwin"); 01407 case MachO::CPU_SUBTYPE_ARM_V6: 01408 return Triple("thumbv6-apple-darwin"); 01409 case MachO::CPU_SUBTYPE_ARM_V6M: 01410 if (McpuDefault) 01411 *McpuDefault = "cortex-m0"; 01412 return Triple("thumbv6m-apple-darwin"); 01413 case MachO::CPU_SUBTYPE_ARM_V7: 01414 return Triple("thumbv7-apple-darwin"); 01415 case MachO::CPU_SUBTYPE_ARM_V7EM: 01416 if (McpuDefault) 01417 *McpuDefault = "cortex-m4"; 01418 return Triple("thumbv7em-apple-darwin"); 01419 case MachO::CPU_SUBTYPE_ARM_V7K: 01420 return Triple("thumbv7k-apple-darwin"); 01421 case MachO::CPU_SUBTYPE_ARM_V7M: 01422 if (McpuDefault) 01423 *McpuDefault = "cortex-m3"; 01424 return Triple("thumbv7m-apple-darwin"); 01425 case MachO::CPU_SUBTYPE_ARM_V7S: 01426 return Triple("thumbv7s-apple-darwin"); 01427 default: 01428 return Triple(); 01429 } 01430 default: 01431 return Triple(); 01432 } 01433 } 01434 01435 Triple MachOObjectFile::getArch(uint32_t CPUType, uint32_t CPUSubType, 01436 const char **McpuDefault, 01437 Triple *ThumbTriple) { 01438 Triple T = MachOObjectFile::getArch(CPUType, CPUSubType, McpuDefault); 01439 *ThumbTriple = MachOObjectFile::getThumbArch(CPUType, CPUSubType, 01440 McpuDefault); 01441 return T; 01442 } 01443 01444 Triple MachOObjectFile::getHostArch() { 01445 return Triple(sys::getDefaultTargetTriple()); 01446 } 01447 01448 bool MachOObjectFile::isValidArch(StringRef ArchFlag) { 01449 return StringSwitch<bool>(ArchFlag) 01450 .Case("i386", true) 01451 .Case("x86_64", true) 01452 .Case("x86_64h", true) 01453 .Case("armv4t", true) 01454 .Case("arm", true) 01455 .Case("armv5e", true) 01456 .Case("armv6", true) 01457 .Case("armv6m", true) 01458 .Case("armv7em", true) 01459 .Case("armv7k", true) 01460 .Case("armv7m", true) 01461 .Case("armv7s", true) 01462 .Case("arm64", true) 01463 .Case("ppc", true) 01464 .Case("ppc64", true) 01465 .Default(false); 01466 } 01467 01468 unsigned MachOObjectFile::getArch() const { 01469 return getArch(getCPUType(this)); 01470 } 01471 01472 Triple MachOObjectFile::getArch(const char **McpuDefault, 01473 Triple *ThumbTriple) const { 01474 Triple T; 01475 if (is64Bit()) { 01476 MachO::mach_header_64 H_64; 01477 H_64 = getHeader64(); 01478 T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype, McpuDefault); 01479 *ThumbTriple = MachOObjectFile::getThumbArch(H_64.cputype, H_64.cpusubtype, 01480 McpuDefault); 01481 } else { 01482 MachO::mach_header H; 01483 H = getHeader(); 01484 T = MachOObjectFile::getArch(H.cputype, H.cpusubtype, McpuDefault); 01485 *ThumbTriple = MachOObjectFile::getThumbArch(H.cputype, H.cpusubtype, 01486 McpuDefault); 01487 } 01488 return T; 01489 } 01490 01491 relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const { 01492 DataRefImpl DRI; 01493 DRI.d.a = Index; 01494 return section_rel_begin(DRI); 01495 } 01496 01497 relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const { 01498 DataRefImpl DRI; 01499 DRI.d.a = Index; 01500 return section_rel_end(DRI); 01501 } 01502 01503 dice_iterator MachOObjectFile::begin_dices() const { 01504 DataRefImpl DRI; 01505 if (!DataInCodeLoadCmd) 01506 return dice_iterator(DiceRef(DRI, this)); 01507 01508 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 01509 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, DicLC.dataoff)); 01510 return dice_iterator(DiceRef(DRI, this)); 01511 } 01512 01513 dice_iterator MachOObjectFile::end_dices() const { 01514 DataRefImpl DRI; 01515 if (!DataInCodeLoadCmd) 01516 return dice_iterator(DiceRef(DRI, this)); 01517 01518 MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand(); 01519 unsigned Offset = DicLC.dataoff + DicLC.datasize; 01520 DRI.p = reinterpret_cast<uintptr_t>(getPtr(this, Offset)); 01521 return dice_iterator(DiceRef(DRI, this)); 01522 } 01523 01524 ExportEntry::ExportEntry(ArrayRef<uint8_t> T) 01525 : Trie(T), Malformed(false), Done(false) { } 01526 01527 void ExportEntry::moveToFirst() { 01528 pushNode(0); 01529 pushDownUntilBottom(); 01530 } 01531 01532 void ExportEntry::moveToEnd() { 01533 Stack.clear(); 01534 Done = true; 01535 } 01536 01537 bool ExportEntry::operator==(const ExportEntry &Other) const { 01538 // Common case, one at end, other iterating from begin. 01539 if (Done || Other.Done) 01540 return (Done == Other.Done); 01541 // Not equal if different stack sizes. 01542 if (Stack.size() != Other.Stack.size()) 01543 return false; 01544 // Not equal if different cumulative strings. 01545 if (!CumulativeString.str().equals(Other.CumulativeString.str())) 01546 return false; 01547 // Equal if all nodes in both stacks match. 01548 for (unsigned i=0; i < Stack.size(); ++i) { 01549 if (Stack[i].Start != Other.Stack[i].Start) 01550 return false; 01551 } 01552 return true; 01553 } 01554 01555 uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr) { 01556 unsigned Count; 01557 uint64_t Result = decodeULEB128(Ptr, &Count); 01558 Ptr += Count; 01559 if (Ptr > Trie.end()) { 01560 Ptr = Trie.end(); 01561 Malformed = true; 01562 } 01563 return Result; 01564 } 01565 01566 StringRef ExportEntry::name() const { 01567 return CumulativeString.str(); 01568 } 01569 01570 uint64_t ExportEntry::flags() const { 01571 return Stack.back().Flags; 01572 } 01573 01574 uint64_t ExportEntry::address() const { 01575 return Stack.back().Address; 01576 } 01577 01578 uint64_t ExportEntry::other() const { 01579 return Stack.back().Other; 01580 } 01581 01582 StringRef ExportEntry::otherName() const { 01583 const char* ImportName = Stack.back().ImportName; 01584 if (ImportName) 01585 return StringRef(ImportName); 01586 return StringRef(); 01587 } 01588 01589 uint32_t ExportEntry::nodeOffset() const { 01590 return Stack.back().Start - Trie.begin(); 01591 } 01592 01593 ExportEntry::NodeState::NodeState(const uint8_t *Ptr) 01594 : Start(Ptr), Current(Ptr), Flags(0), Address(0), Other(0), 01595 ImportName(nullptr), ChildCount(0), NextChildIndex(0), 01596 ParentStringLength(0), IsExportNode(false) { 01597 } 01598 01599 void ExportEntry::pushNode(uint64_t offset) { 01600 const uint8_t *Ptr = Trie.begin() + offset; 01601 NodeState State(Ptr); 01602 uint64_t ExportInfoSize = readULEB128(State.Current); 01603 State.IsExportNode = (ExportInfoSize != 0); 01604 const uint8_t* Children = State.Current + ExportInfoSize; 01605 if (State.IsExportNode) { 01606 State.Flags = readULEB128(State.Current); 01607 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) { 01608 State.Address = 0; 01609 State.Other = readULEB128(State.Current); // dylib ordinal 01610 State.ImportName = reinterpret_cast<const char*>(State.Current); 01611 } else { 01612 State.Address = readULEB128(State.Current); 01613 if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) 01614 State.Other = readULEB128(State.Current); 01615 } 01616 } 01617 State.ChildCount = *Children; 01618 State.Current = Children + 1; 01619 State.NextChildIndex = 0; 01620 State.ParentStringLength = CumulativeString.size(); 01621 Stack.push_back(State); 01622 } 01623 01624 void ExportEntry::pushDownUntilBottom() { 01625 while (Stack.back().NextChildIndex < Stack.back().ChildCount) { 01626 NodeState &Top = Stack.back(); 01627 CumulativeString.resize(Top.ParentStringLength); 01628 for (;*Top.Current != 0; Top.Current++) { 01629 char C = *Top.Current; 01630 CumulativeString.push_back(C); 01631 } 01632 Top.Current += 1; 01633 uint64_t childNodeIndex = readULEB128(Top.Current); 01634 Top.NextChildIndex += 1; 01635 pushNode(childNodeIndex); 01636 } 01637 if (!Stack.back().IsExportNode) { 01638 Malformed = true; 01639 moveToEnd(); 01640 } 01641 } 01642 01643 // We have a trie data structure and need a way to walk it that is compatible 01644 // with the C++ iterator model. The solution is a non-recursive depth first 01645 // traversal where the iterator contains a stack of parent nodes along with a 01646 // string that is the accumulation of all edge strings along the parent chain 01647 // to this point. 01648 // 01649 // There is one “export” node for each exported symbol. But because some 01650 // symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export 01651 // node may have child nodes too. 01652 // 01653 // The algorithm for moveNext() is to keep moving down the leftmost unvisited 01654 // child until hitting a node with no children (which is an export node or 01655 // else the trie is malformed). On the way down, each node is pushed on the 01656 // stack ivar. If there is no more ways down, it pops up one and tries to go 01657 // down a sibling path until a childless node is reached. 01658 void ExportEntry::moveNext() { 01659 if (Stack.empty() || !Stack.back().IsExportNode) { 01660 Malformed = true; 01661 moveToEnd(); 01662 return; 01663 } 01664 01665 Stack.pop_back(); 01666 while (!Stack.empty()) { 01667 NodeState &Top = Stack.back(); 01668 if (Top.NextChildIndex < Top.ChildCount) { 01669 pushDownUntilBottom(); 01670 // Now at the next export node. 01671 return; 01672 } else { 01673 if (Top.IsExportNode) { 01674 // This node has no children but is itself an export node. 01675 CumulativeString.resize(Top.ParentStringLength); 01676 return; 01677 } 01678 Stack.pop_back(); 01679 } 01680 } 01681 Done = true; 01682 } 01683 01684 iterator_range<export_iterator> 01685 MachOObjectFile::exports(ArrayRef<uint8_t> Trie) { 01686 ExportEntry Start(Trie); 01687 Start.moveToFirst(); 01688 01689 ExportEntry Finish(Trie); 01690 Finish.moveToEnd(); 01691 01692 return iterator_range<export_iterator>(export_iterator(Start), 01693 export_iterator(Finish)); 01694 } 01695 01696 iterator_range<export_iterator> MachOObjectFile::exports() const { 01697 return exports(getDyldInfoExportsTrie()); 01698 } 01699 01700 01701 MachORebaseEntry::MachORebaseEntry(ArrayRef<uint8_t> Bytes, bool is64Bit) 01702 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 01703 RemainingLoopCount(0), AdvanceAmount(0), RebaseType(0), 01704 PointerSize(is64Bit ? 8 : 4), Malformed(false), Done(false) {} 01705 01706 void MachORebaseEntry::moveToFirst() { 01707 Ptr = Opcodes.begin(); 01708 moveNext(); 01709 } 01710 01711 void MachORebaseEntry::moveToEnd() { 01712 Ptr = Opcodes.end(); 01713 RemainingLoopCount = 0; 01714 Done = true; 01715 } 01716 01717 void MachORebaseEntry::moveNext() { 01718 // If in the middle of some loop, move to next rebasing in loop. 01719 SegmentOffset += AdvanceAmount; 01720 if (RemainingLoopCount) { 01721 --RemainingLoopCount; 01722 return; 01723 } 01724 if (Ptr == Opcodes.end()) { 01725 Done = true; 01726 return; 01727 } 01728 bool More = true; 01729 while (More && !Malformed) { 01730 // Parse next opcode and set up next loop. 01731 uint8_t Byte = *Ptr++; 01732 uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK; 01733 uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK; 01734 switch (Opcode) { 01735 case MachO::REBASE_OPCODE_DONE: 01736 More = false; 01737 Done = true; 01738 moveToEnd(); 01739 DEBUG_WITH_TYPE("mach-o-rebase", llvm::dbgs() << "REBASE_OPCODE_DONE\n"); 01740 break; 01741 case MachO::REBASE_OPCODE_SET_TYPE_IMM: 01742 RebaseType = ImmValue; 01743 DEBUG_WITH_TYPE( 01744 "mach-o-rebase", 01745 llvm::dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: " 01746 << "RebaseType=" << (int) RebaseType << "\n"); 01747 break; 01748 case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 01749 SegmentIndex = ImmValue; 01750 SegmentOffset = readULEB128(); 01751 DEBUG_WITH_TYPE( 01752 "mach-o-rebase", 01753 llvm::dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 01754 << "SegmentIndex=" << SegmentIndex << ", " 01755 << format("SegmentOffset=0x%06X", SegmentOffset) 01756 << "\n"); 01757 break; 01758 case MachO::REBASE_OPCODE_ADD_ADDR_ULEB: 01759 SegmentOffset += readULEB128(); 01760 DEBUG_WITH_TYPE("mach-o-rebase", 01761 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: " 01762 << format("SegmentOffset=0x%06X", 01763 SegmentOffset) << "\n"); 01764 break; 01765 case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED: 01766 SegmentOffset += ImmValue * PointerSize; 01767 DEBUG_WITH_TYPE("mach-o-rebase", 01768 llvm::dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: " 01769 << format("SegmentOffset=0x%06X", 01770 SegmentOffset) << "\n"); 01771 break; 01772 case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES: 01773 AdvanceAmount = PointerSize; 01774 RemainingLoopCount = ImmValue - 1; 01775 DEBUG_WITH_TYPE( 01776 "mach-o-rebase", 01777 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: " 01778 << format("SegmentOffset=0x%06X", SegmentOffset) 01779 << ", AdvanceAmount=" << AdvanceAmount 01780 << ", RemainingLoopCount=" << RemainingLoopCount 01781 << "\n"); 01782 return; 01783 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES: 01784 AdvanceAmount = PointerSize; 01785 RemainingLoopCount = readULEB128() - 1; 01786 DEBUG_WITH_TYPE( 01787 "mach-o-rebase", 01788 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: " 01789 << format("SegmentOffset=0x%06X", SegmentOffset) 01790 << ", AdvanceAmount=" << AdvanceAmount 01791 << ", RemainingLoopCount=" << RemainingLoopCount 01792 << "\n"); 01793 return; 01794 case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: 01795 AdvanceAmount = readULEB128() + PointerSize; 01796 RemainingLoopCount = 0; 01797 DEBUG_WITH_TYPE( 01798 "mach-o-rebase", 01799 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: " 01800 << format("SegmentOffset=0x%06X", SegmentOffset) 01801 << ", AdvanceAmount=" << AdvanceAmount 01802 << ", RemainingLoopCount=" << RemainingLoopCount 01803 << "\n"); 01804 return; 01805 case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: 01806 RemainingLoopCount = readULEB128() - 1; 01807 AdvanceAmount = readULEB128() + PointerSize; 01808 DEBUG_WITH_TYPE( 01809 "mach-o-rebase", 01810 llvm::dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: " 01811 << format("SegmentOffset=0x%06X", SegmentOffset) 01812 << ", AdvanceAmount=" << AdvanceAmount 01813 << ", RemainingLoopCount=" << RemainingLoopCount 01814 << "\n"); 01815 return; 01816 default: 01817 Malformed = true; 01818 } 01819 } 01820 } 01821 01822 uint64_t MachORebaseEntry::readULEB128() { 01823 unsigned Count; 01824 uint64_t Result = decodeULEB128(Ptr, &Count); 01825 Ptr += Count; 01826 if (Ptr > Opcodes.end()) { 01827 Ptr = Opcodes.end(); 01828 Malformed = true; 01829 } 01830 return Result; 01831 } 01832 01833 uint32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; } 01834 01835 uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; } 01836 01837 StringRef MachORebaseEntry::typeName() const { 01838 switch (RebaseType) { 01839 case MachO::REBASE_TYPE_POINTER: 01840 return "pointer"; 01841 case MachO::REBASE_TYPE_TEXT_ABSOLUTE32: 01842 return "text abs32"; 01843 case MachO::REBASE_TYPE_TEXT_PCREL32: 01844 return "text rel32"; 01845 } 01846 return "unknown"; 01847 } 01848 01849 bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const { 01850 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 01851 return (Ptr == Other.Ptr) && 01852 (RemainingLoopCount == Other.RemainingLoopCount) && 01853 (Done == Other.Done); 01854 } 01855 01856 iterator_range<rebase_iterator> 01857 MachOObjectFile::rebaseTable(ArrayRef<uint8_t> Opcodes, bool is64) { 01858 MachORebaseEntry Start(Opcodes, is64); 01859 Start.moveToFirst(); 01860 01861 MachORebaseEntry Finish(Opcodes, is64); 01862 Finish.moveToEnd(); 01863 01864 return iterator_range<rebase_iterator>(rebase_iterator(Start), 01865 rebase_iterator(Finish)); 01866 } 01867 01868 iterator_range<rebase_iterator> MachOObjectFile::rebaseTable() const { 01869 return rebaseTable(getDyldInfoRebaseOpcodes(), is64Bit()); 01870 } 01871 01872 01873 MachOBindEntry::MachOBindEntry(ArrayRef<uint8_t> Bytes, bool is64Bit, 01874 Kind BK) 01875 : Opcodes(Bytes), Ptr(Bytes.begin()), SegmentOffset(0), SegmentIndex(0), 01876 Ordinal(0), Flags(0), Addend(0), RemainingLoopCount(0), AdvanceAmount(0), 01877 BindType(0), PointerSize(is64Bit ? 8 : 4), 01878 TableKind(BK), Malformed(false), Done(false) {} 01879 01880 void MachOBindEntry::moveToFirst() { 01881 Ptr = Opcodes.begin(); 01882 moveNext(); 01883 } 01884 01885 void MachOBindEntry::moveToEnd() { 01886 Ptr = Opcodes.end(); 01887 RemainingLoopCount = 0; 01888 Done = true; 01889 } 01890 01891 void MachOBindEntry::moveNext() { 01892 // If in the middle of some loop, move to next binding in loop. 01893 SegmentOffset += AdvanceAmount; 01894 if (RemainingLoopCount) { 01895 --RemainingLoopCount; 01896 return; 01897 } 01898 if (Ptr == Opcodes.end()) { 01899 Done = true; 01900 return; 01901 } 01902 bool More = true; 01903 while (More && !Malformed) { 01904 // Parse next opcode and set up next loop. 01905 uint8_t Byte = *Ptr++; 01906 uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK; 01907 uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK; 01908 int8_t SignExtended; 01909 const uint8_t *SymStart; 01910 switch (Opcode) { 01911 case MachO::BIND_OPCODE_DONE: 01912 if (TableKind == Kind::Lazy) { 01913 // Lazying bindings have a DONE opcode between entries. Need to ignore 01914 // it to advance to next entry. But need not if this is last entry. 01915 bool NotLastEntry = false; 01916 for (const uint8_t *P = Ptr; P < Opcodes.end(); ++P) { 01917 if (*P) { 01918 NotLastEntry = true; 01919 } 01920 } 01921 if (NotLastEntry) 01922 break; 01923 } 01924 More = false; 01925 Done = true; 01926 moveToEnd(); 01927 DEBUG_WITH_TYPE("mach-o-bind", llvm::dbgs() << "BIND_OPCODE_DONE\n"); 01928 break; 01929 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: 01930 Ordinal = ImmValue; 01931 DEBUG_WITH_TYPE( 01932 "mach-o-bind", 01933 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: " 01934 << "Ordinal=" << Ordinal << "\n"); 01935 break; 01936 case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: 01937 Ordinal = readULEB128(); 01938 DEBUG_WITH_TYPE( 01939 "mach-o-bind", 01940 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: " 01941 << "Ordinal=" << Ordinal << "\n"); 01942 break; 01943 case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: 01944 if (ImmValue) { 01945 SignExtended = MachO::BIND_OPCODE_MASK | ImmValue; 01946 Ordinal = SignExtended; 01947 } else 01948 Ordinal = 0; 01949 DEBUG_WITH_TYPE( 01950 "mach-o-bind", 01951 llvm::dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: " 01952 << "Ordinal=" << Ordinal << "\n"); 01953 break; 01954 case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: 01955 Flags = ImmValue; 01956 SymStart = Ptr; 01957 while (*Ptr) { 01958 ++Ptr; 01959 } 01960 SymbolName = StringRef(reinterpret_cast<const char*>(SymStart), 01961 Ptr-SymStart); 01962 ++Ptr; 01963 DEBUG_WITH_TYPE( 01964 "mach-o-bind", 01965 llvm::dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: " 01966 << "SymbolName=" << SymbolName << "\n"); 01967 if (TableKind == Kind::Weak) { 01968 if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) 01969 return; 01970 } 01971 break; 01972 case MachO::BIND_OPCODE_SET_TYPE_IMM: 01973 BindType = ImmValue; 01974 DEBUG_WITH_TYPE( 01975 "mach-o-bind", 01976 llvm::dbgs() << "BIND_OPCODE_SET_TYPE_IMM: " 01977 << "BindType=" << (int)BindType << "\n"); 01978 break; 01979 case MachO::BIND_OPCODE_SET_ADDEND_SLEB: 01980 Addend = readSLEB128(); 01981 if (TableKind == Kind::Lazy) 01982 Malformed = true; 01983 DEBUG_WITH_TYPE( 01984 "mach-o-bind", 01985 llvm::dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: " 01986 << "Addend=" << Addend << "\n"); 01987 break; 01988 case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: 01989 SegmentIndex = ImmValue; 01990 SegmentOffset = readULEB128(); 01991 DEBUG_WITH_TYPE( 01992 "mach-o-bind", 01993 llvm::dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: " 01994 << "SegmentIndex=" << SegmentIndex << ", " 01995 << format("SegmentOffset=0x%06X", SegmentOffset) 01996 << "\n"); 01997 break; 01998 case MachO::BIND_OPCODE_ADD_ADDR_ULEB: 01999 SegmentOffset += readULEB128(); 02000 DEBUG_WITH_TYPE("mach-o-bind", 02001 llvm::dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: " 02002 << format("SegmentOffset=0x%06X", 02003 SegmentOffset) << "\n"); 02004 break; 02005 case MachO::BIND_OPCODE_DO_BIND: 02006 AdvanceAmount = PointerSize; 02007 RemainingLoopCount = 0; 02008 DEBUG_WITH_TYPE("mach-o-bind", 02009 llvm::dbgs() << "BIND_OPCODE_DO_BIND: " 02010 << format("SegmentOffset=0x%06X", 02011 SegmentOffset) << "\n"); 02012 return; 02013 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: 02014 AdvanceAmount = readULEB128(); 02015 RemainingLoopCount = 0; 02016 if (TableKind == Kind::Lazy) 02017 Malformed = true; 02018 DEBUG_WITH_TYPE( 02019 "mach-o-bind", 02020 llvm::dbgs() << "BIND_OPCODE_DO_BIND_IMM_TIMES: " 02021 << format("SegmentOffset=0x%06X", SegmentOffset) 02022 << ", AdvanceAmount=" << AdvanceAmount 02023 << ", RemainingLoopCount=" << RemainingLoopCount 02024 << "\n"); 02025 return; 02026 case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: 02027 AdvanceAmount = ImmValue * PointerSize; 02028 RemainingLoopCount = 0; 02029 if (TableKind == Kind::Lazy) 02030 Malformed = true; 02031 DEBUG_WITH_TYPE("mach-o-bind", 02032 llvm::dbgs() 02033 << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: " 02034 << format("SegmentOffset=0x%06X", 02035 SegmentOffset) << "\n"); 02036 return; 02037 case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: 02038 RemainingLoopCount = readULEB128() - 1; 02039 AdvanceAmount = readULEB128() + PointerSize; 02040 if (TableKind == Kind::Lazy) 02041 Malformed = true; 02042 DEBUG_WITH_TYPE( 02043 "mach-o-bind", 02044 llvm::dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: " 02045 << format("SegmentOffset=0x%06X", SegmentOffset) 02046 << ", AdvanceAmount=" << AdvanceAmount 02047 << ", RemainingLoopCount=" << RemainingLoopCount 02048 << "\n"); 02049 return; 02050 default: 02051 Malformed = true; 02052 } 02053 } 02054 } 02055 02056 uint64_t MachOBindEntry::readULEB128() { 02057 unsigned Count; 02058 uint64_t Result = decodeULEB128(Ptr, &Count); 02059 Ptr += Count; 02060 if (Ptr > Opcodes.end()) { 02061 Ptr = Opcodes.end(); 02062 Malformed = true; 02063 } 02064 return Result; 02065 } 02066 02067 int64_t MachOBindEntry::readSLEB128() { 02068 unsigned Count; 02069 int64_t Result = decodeSLEB128(Ptr, &Count); 02070 Ptr += Count; 02071 if (Ptr > Opcodes.end()) { 02072 Ptr = Opcodes.end(); 02073 Malformed = true; 02074 } 02075 return Result; 02076 } 02077 02078 02079 uint32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; } 02080 02081 uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; } 02082 02083 StringRef MachOBindEntry::typeName() const { 02084 switch (BindType) { 02085 case MachO::BIND_TYPE_POINTER: 02086 return "pointer"; 02087 case MachO::BIND_TYPE_TEXT_ABSOLUTE32: 02088 return "text abs32"; 02089 case MachO::BIND_TYPE_TEXT_PCREL32: 02090 return "text rel32"; 02091 } 02092 return "unknown"; 02093 } 02094 02095 StringRef MachOBindEntry::symbolName() const { return SymbolName; } 02096 02097 int64_t MachOBindEntry::addend() const { return Addend; } 02098 02099 uint32_t MachOBindEntry::flags() const { return Flags; } 02100 02101 int MachOBindEntry::ordinal() const { return Ordinal; } 02102 02103 bool MachOBindEntry::operator==(const MachOBindEntry &Other) const { 02104 assert(Opcodes == Other.Opcodes && "compare iterators of different files"); 02105 return (Ptr == Other.Ptr) && 02106 (RemainingLoopCount == Other.RemainingLoopCount) && 02107 (Done == Other.Done); 02108 } 02109 02110 iterator_range<bind_iterator> 02111 MachOObjectFile::bindTable(ArrayRef<uint8_t> Opcodes, bool is64, 02112 MachOBindEntry::Kind BKind) { 02113 MachOBindEntry Start(Opcodes, is64, BKind); 02114 Start.moveToFirst(); 02115 02116 MachOBindEntry Finish(Opcodes, is64, BKind); 02117 Finish.moveToEnd(); 02118 02119 return iterator_range<bind_iterator>(bind_iterator(Start), 02120 bind_iterator(Finish)); 02121 } 02122 02123 iterator_range<bind_iterator> MachOObjectFile::bindTable() const { 02124 return bindTable(getDyldInfoBindOpcodes(), is64Bit(), 02125 MachOBindEntry::Kind::Regular); 02126 } 02127 02128 iterator_range<bind_iterator> MachOObjectFile::lazyBindTable() const { 02129 return bindTable(getDyldInfoLazyBindOpcodes(), is64Bit(), 02130 MachOBindEntry::Kind::Lazy); 02131 } 02132 02133 iterator_range<bind_iterator> MachOObjectFile::weakBindTable() const { 02134 return bindTable(getDyldInfoWeakBindOpcodes(), is64Bit(), 02135 MachOBindEntry::Kind::Weak); 02136 } 02137 02138 StringRef 02139 MachOObjectFile::getSectionFinalSegmentName(DataRefImpl Sec) const { 02140 ArrayRef<char> Raw = getSectionRawFinalSegmentName(Sec); 02141 return parseSegmentOrSectionName(Raw.data()); 02142 } 02143 02144 ArrayRef<char> 02145 MachOObjectFile::getSectionRawName(DataRefImpl Sec) const { 02146 const section_base *Base = 02147 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 02148 return makeArrayRef(Base->sectname); 02149 } 02150 02151 ArrayRef<char> 02152 MachOObjectFile::getSectionRawFinalSegmentName(DataRefImpl Sec) const { 02153 const section_base *Base = 02154 reinterpret_cast<const section_base *>(Sections[Sec.d.a]); 02155 return makeArrayRef(Base->segname); 02156 } 02157 02158 bool 02159 MachOObjectFile::isRelocationScattered(const MachO::any_relocation_info &RE) 02160 const { 02161 if (getCPUType(this) == MachO::CPU_TYPE_X86_64) 02162 return false; 02163 return getPlainRelocationAddress(RE) & MachO::R_SCATTERED; 02164 } 02165 02166 unsigned MachOObjectFile::getPlainRelocationSymbolNum( 02167 const MachO::any_relocation_info &RE) const { 02168 if (isLittleEndian()) 02169 return RE.r_word1 & 0xffffff; 02170 return RE.r_word1 >> 8; 02171 } 02172 02173 bool MachOObjectFile::getPlainRelocationExternal( 02174 const MachO::any_relocation_info &RE) const { 02175 if (isLittleEndian()) 02176 return (RE.r_word1 >> 27) & 1; 02177 return (RE.r_word1 >> 4) & 1; 02178 } 02179 02180 bool MachOObjectFile::getScatteredRelocationScattered( 02181 const MachO::any_relocation_info &RE) const { 02182 return RE.r_word0 >> 31; 02183 } 02184 02185 uint32_t MachOObjectFile::getScatteredRelocationValue( 02186 const MachO::any_relocation_info &RE) const { 02187 return RE.r_word1; 02188 } 02189 02190 unsigned MachOObjectFile::getAnyRelocationAddress( 02191 const MachO::any_relocation_info &RE) const { 02192 if (isRelocationScattered(RE)) 02193 return getScatteredRelocationAddress(RE); 02194 return getPlainRelocationAddress(RE); 02195 } 02196 02197 unsigned MachOObjectFile::getAnyRelocationPCRel( 02198 const MachO::any_relocation_info &RE) const { 02199 if (isRelocationScattered(RE)) 02200 return getScatteredRelocationPCRel(this, RE); 02201 return getPlainRelocationPCRel(this, RE); 02202 } 02203 02204 unsigned MachOObjectFile::getAnyRelocationLength( 02205 const MachO::any_relocation_info &RE) const { 02206 if (isRelocationScattered(RE)) 02207 return getScatteredRelocationLength(RE); 02208 return getPlainRelocationLength(this, RE); 02209 } 02210 02211 unsigned 02212 MachOObjectFile::getAnyRelocationType( 02213 const MachO::any_relocation_info &RE) const { 02214 if (isRelocationScattered(RE)) 02215 return getScatteredRelocationType(RE); 02216 return getPlainRelocationType(this, RE); 02217 } 02218 02219 SectionRef 02220 MachOObjectFile::getRelocationSection( 02221 const MachO::any_relocation_info &RE) const { 02222 if (isRelocationScattered(RE) || getPlainRelocationExternal(RE)) 02223 return *section_end(); 02224 unsigned SecNum = getPlainRelocationSymbolNum(RE) - 1; 02225 DataRefImpl DRI; 02226 DRI.d.a = SecNum; 02227 return SectionRef(DRI, this); 02228 } 02229 02230 MachOObjectFile::LoadCommandInfo 02231 MachOObjectFile::getFirstLoadCommandInfo() const { 02232 MachOObjectFile::LoadCommandInfo Load; 02233 02234 unsigned HeaderSize = is64Bit() ? sizeof(MachO::mach_header_64) : 02235 sizeof(MachO::mach_header); 02236 Load.Ptr = getPtr(this, HeaderSize); 02237 Load.C = getStruct<MachO::load_command>(this, Load.Ptr); 02238 return Load; 02239 } 02240 02241 MachOObjectFile::LoadCommandInfo 02242 MachOObjectFile::getNextLoadCommandInfo(const LoadCommandInfo &L) const { 02243 MachOObjectFile::LoadCommandInfo Next; 02244 Next.Ptr = L.Ptr + L.C.cmdsize; 02245 Next.C = getStruct<MachO::load_command>(this, Next.Ptr); 02246 return Next; 02247 } 02248 02249 MachO::section MachOObjectFile::getSection(DataRefImpl DRI) const { 02250 return getStruct<MachO::section>(this, Sections[DRI.d.a]); 02251 } 02252 02253 MachO::section_64 MachOObjectFile::getSection64(DataRefImpl DRI) const { 02254 return getStruct<MachO::section_64>(this, Sections[DRI.d.a]); 02255 } 02256 02257 MachO::section MachOObjectFile::getSection(const LoadCommandInfo &L, 02258 unsigned Index) const { 02259 const char *Sec = getSectionPtr(this, L, Index); 02260 return getStruct<MachO::section>(this, Sec); 02261 } 02262 02263 MachO::section_64 MachOObjectFile::getSection64(const LoadCommandInfo &L, 02264 unsigned Index) const { 02265 const char *Sec = getSectionPtr(this, L, Index); 02266 return getStruct<MachO::section_64>(this, Sec); 02267 } 02268 02269 MachO::nlist 02270 MachOObjectFile::getSymbolTableEntry(DataRefImpl DRI) const { 02271 const char *P = reinterpret_cast<const char *>(DRI.p); 02272 return getStruct<MachO::nlist>(this, P); 02273 } 02274 02275 MachO::nlist_64 02276 MachOObjectFile::getSymbol64TableEntry(DataRefImpl DRI) const { 02277 const char *P = reinterpret_cast<const char *>(DRI.p); 02278 return getStruct<MachO::nlist_64>(this, P); 02279 } 02280 02281 MachO::linkedit_data_command 02282 MachOObjectFile::getLinkeditDataLoadCommand(const LoadCommandInfo &L) const { 02283 return getStruct<MachO::linkedit_data_command>(this, L.Ptr); 02284 } 02285 02286 MachO::segment_command 02287 MachOObjectFile::getSegmentLoadCommand(const LoadCommandInfo &L) const { 02288 return getStruct<MachO::segment_command>(this, L.Ptr); 02289 } 02290 02291 MachO::segment_command_64 02292 MachOObjectFile::getSegment64LoadCommand(const LoadCommandInfo &L) const { 02293 return getStruct<MachO::segment_command_64>(this, L.Ptr); 02294 } 02295 02296 MachO::linker_options_command 02297 MachOObjectFile::getLinkerOptionsLoadCommand(const LoadCommandInfo &L) const { 02298 return getStruct<MachO::linker_options_command>(this, L.Ptr); 02299 } 02300 02301 MachO::version_min_command 02302 MachOObjectFile::getVersionMinLoadCommand(const LoadCommandInfo &L) const { 02303 return getStruct<MachO::version_min_command>(this, L.Ptr); 02304 } 02305 02306 MachO::dylib_command 02307 MachOObjectFile::getDylibIDLoadCommand(const LoadCommandInfo &L) const { 02308 return getStruct<MachO::dylib_command>(this, L.Ptr); 02309 } 02310 02311 MachO::dyld_info_command 02312 MachOObjectFile::getDyldInfoLoadCommand(const LoadCommandInfo &L) const { 02313 return getStruct<MachO::dyld_info_command>(this, L.Ptr); 02314 } 02315 02316 MachO::dylinker_command 02317 MachOObjectFile::getDylinkerCommand(const LoadCommandInfo &L) const { 02318 return getStruct<MachO::dylinker_command>(this, L.Ptr); 02319 } 02320 02321 MachO::uuid_command 02322 MachOObjectFile::getUuidCommand(const LoadCommandInfo &L) const { 02323 return getStruct<MachO::uuid_command>(this, L.Ptr); 02324 } 02325 02326 MachO::source_version_command 02327 MachOObjectFile::getSourceVersionCommand(const LoadCommandInfo &L) const { 02328 return getStruct<MachO::source_version_command>(this, L.Ptr); 02329 } 02330 02331 MachO::entry_point_command 02332 MachOObjectFile::getEntryPointCommand(const LoadCommandInfo &L) const { 02333 return getStruct<MachO::entry_point_command>(this, L.Ptr); 02334 } 02335 02336 02337 MachO::any_relocation_info 02338 MachOObjectFile::getRelocation(DataRefImpl Rel) const { 02339 DataRefImpl Sec; 02340 Sec.d.a = Rel.d.a; 02341 uint32_t Offset; 02342 if (is64Bit()) { 02343 MachO::section_64 Sect = getSection64(Sec); 02344 Offset = Sect.reloff; 02345 } else { 02346 MachO::section Sect = getSection(Sec); 02347 Offset = Sect.reloff; 02348 } 02349 02350 auto P = reinterpret_cast<const MachO::any_relocation_info *>( 02351 getPtr(this, Offset)) + Rel.d.b; 02352 return getStruct<MachO::any_relocation_info>( 02353 this, reinterpret_cast<const char *>(P)); 02354 } 02355 02356 MachO::data_in_code_entry 02357 MachOObjectFile::getDice(DataRefImpl Rel) const { 02358 const char *P = reinterpret_cast<const char *>(Rel.p); 02359 return getStruct<MachO::data_in_code_entry>(this, P); 02360 } 02361 02362 MachO::mach_header MachOObjectFile::getHeader() const { 02363 return getStruct<MachO::mach_header>(this, getPtr(this, 0)); 02364 } 02365 02366 MachO::mach_header_64 MachOObjectFile::getHeader64() const { 02367 return getStruct<MachO::mach_header_64>(this, getPtr(this, 0)); 02368 } 02369 02370 uint32_t MachOObjectFile::getIndirectSymbolTableEntry( 02371 const MachO::dysymtab_command &DLC, 02372 unsigned Index) const { 02373 uint64_t Offset = DLC.indirectsymoff + Index * sizeof(uint32_t); 02374 return getStruct<uint32_t>(this, getPtr(this, Offset)); 02375 } 02376 02377 MachO::data_in_code_entry 02378 MachOObjectFile::getDataInCodeTableEntry(uint32_t DataOffset, 02379 unsigned Index) const { 02380 uint64_t Offset = DataOffset + Index * sizeof(MachO::data_in_code_entry); 02381 return getStruct<MachO::data_in_code_entry>(this, getPtr(this, Offset)); 02382 } 02383 02384 MachO::symtab_command MachOObjectFile::getSymtabLoadCommand() const { 02385 return getStruct<MachO::symtab_command>(this, SymtabLoadCmd); 02386 } 02387 02388 MachO::dysymtab_command MachOObjectFile::getDysymtabLoadCommand() const { 02389 return getStruct<MachO::dysymtab_command>(this, DysymtabLoadCmd); 02390 } 02391 02392 MachO::linkedit_data_command 02393 MachOObjectFile::getDataInCodeLoadCommand() const { 02394 if (DataInCodeLoadCmd) 02395 return getStruct<MachO::linkedit_data_command>(this, DataInCodeLoadCmd); 02396 02397 // If there is no DataInCodeLoadCmd return a load command with zero'ed fields. 02398 MachO::linkedit_data_command Cmd; 02399 Cmd.cmd = MachO::LC_DATA_IN_CODE; 02400 Cmd.cmdsize = sizeof(MachO::linkedit_data_command); 02401 Cmd.dataoff = 0; 02402 Cmd.datasize = 0; 02403 return Cmd; 02404 } 02405 02406 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoRebaseOpcodes() const { 02407 if (!DyldInfoLoadCmd) 02408 return ArrayRef<uint8_t>(); 02409 02410 MachO::dyld_info_command DyldInfo 02411 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 02412 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 02413 getPtr(this, DyldInfo.rebase_off)); 02414 return ArrayRef<uint8_t>(Ptr, DyldInfo.rebase_size); 02415 } 02416 02417 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoBindOpcodes() const { 02418 if (!DyldInfoLoadCmd) 02419 return ArrayRef<uint8_t>(); 02420 02421 MachO::dyld_info_command DyldInfo 02422 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 02423 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 02424 getPtr(this, DyldInfo.bind_off)); 02425 return ArrayRef<uint8_t>(Ptr, DyldInfo.bind_size); 02426 } 02427 02428 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoWeakBindOpcodes() const { 02429 if (!DyldInfoLoadCmd) 02430 return ArrayRef<uint8_t>(); 02431 02432 MachO::dyld_info_command DyldInfo 02433 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 02434 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 02435 getPtr(this, DyldInfo.weak_bind_off)); 02436 return ArrayRef<uint8_t>(Ptr, DyldInfo.weak_bind_size); 02437 } 02438 02439 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoLazyBindOpcodes() const { 02440 if (!DyldInfoLoadCmd) 02441 return ArrayRef<uint8_t>(); 02442 02443 MachO::dyld_info_command DyldInfo 02444 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 02445 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 02446 getPtr(this, DyldInfo.lazy_bind_off)); 02447 return ArrayRef<uint8_t>(Ptr, DyldInfo.lazy_bind_size); 02448 } 02449 02450 ArrayRef<uint8_t> MachOObjectFile::getDyldInfoExportsTrie() const { 02451 if (!DyldInfoLoadCmd) 02452 return ArrayRef<uint8_t>(); 02453 02454 MachO::dyld_info_command DyldInfo 02455 = getStruct<MachO::dyld_info_command>(this, DyldInfoLoadCmd); 02456 const uint8_t *Ptr = reinterpret_cast<const uint8_t*>( 02457 getPtr(this, DyldInfo.export_off)); 02458 return ArrayRef<uint8_t>(Ptr, DyldInfo.export_size); 02459 } 02460 02461 02462 StringRef MachOObjectFile::getStringTableData() const { 02463 MachO::symtab_command S = getSymtabLoadCommand(); 02464 return getData().substr(S.stroff, S.strsize); 02465 } 02466 02467 bool MachOObjectFile::is64Bit() const { 02468 return getType() == getMachOType(false, true) || 02469 getType() == getMachOType(true, true); 02470 } 02471 02472 void MachOObjectFile::ReadULEB128s(uint64_t Index, 02473 SmallVectorImpl<uint64_t> &Out) const { 02474 DataExtractor extractor(ObjectFile::getData(), true, 0); 02475 02476 uint32_t offset = Index; 02477 uint64_t data = 0; 02478 while (uint64_t delta = extractor.getULEB128(&offset)) { 02479 data += delta; 02480 Out.push_back(data); 02481 } 02482 } 02483 02484 bool MachOObjectFile::isRelocatableObject() const { 02485 return getHeader().filetype == MachO::MH_OBJECT; 02486 } 02487 02488 ErrorOr<std::unique_ptr<MachOObjectFile>> 02489 ObjectFile::createMachOObjectFile(MemoryBufferRef Buffer) { 02490 StringRef Magic = Buffer.getBuffer().slice(0, 4); 02491 std::error_code EC; 02492 std::unique_ptr<MachOObjectFile> Ret; 02493 if (Magic == "\xFE\xED\xFA\xCE") 02494 Ret.reset(new MachOObjectFile(Buffer, false, false, EC)); 02495 else if (Magic == "\xCE\xFA\xED\xFE") 02496 Ret.reset(new MachOObjectFile(Buffer, true, false, EC)); 02497 else if (Magic == "\xFE\xED\xFA\xCF") 02498 Ret.reset(new MachOObjectFile(Buffer, false, true, EC)); 02499 else if (Magic == "\xCF\xFA\xED\xFE") 02500 Ret.reset(new MachOObjectFile(Buffer, true, true, EC)); 02501 else 02502 return object_error::parse_failed; 02503 02504 if (EC) 02505 return EC; 02506 return std::move(Ret); 02507 } 02508