// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file // and if it is and there is a list of architecture flags is specified then // check to make sure this Mach-O file is one of those architectures or all // architectures was specificed. If not then an error is generated and this // routine returns false. Else it returns true. static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) { if (isa<MachOObjectFile>(O) && !ArchAll && ArchFlags.size() != 0) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O); bool ArchFound = false; MachO::mach_header H; MachO::mach_header_64 H_64; Triple T; if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); } else { H = MachO->MachOObjectFile::getHeader(); T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); } unsigned i; for (i = 0; i < ArchFlags.size(); ++i) { if (ArchFlags[i] == T.getArchName()) ArchFound = true; break; } if (!ArchFound) { error(ArchFlags[i], "file: " + Filename + " does not contain architecture"); return false; } } return true; }
static error_code getSymbolNMTypeChar(MachOObjectFile &Obj, symbol_iterator I, char &Res) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); char Char; switch (NType & MachO::N_TYPE) { case MachO::N_UNDF: Char = 'u'; break; case MachO::N_ABS: Char = 's'; break; case MachO::N_SECT: { section_iterator Sec = Obj.end_sections(); Obj.getSymbolSection(Symb, Sec); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; Obj.getSectionName(Ref, SectionName); StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); if (SegmentName == "__TEXT" && SectionName == "__text") Char = 't'; else Char = 's'; } break; default: Char = '?'; break; } if (NType & (MachO::N_EXT | MachO::N_PEXT)) Char = toupper(static_cast<unsigned char>(Char)); Res = Char; return object_error::success; }
/// Load the interesting main binary symbols' addresses into /// MainBinarySymbolAddresses. void MachODebugMapParser::loadMainBinarySymbols( const MachOObjectFile &MainBinary) { section_iterator Section = MainBinary.section_end(); MainBinarySymbolAddresses.clear(); for (const auto &Sym : MainBinary.symbols()) { SymbolRef::Type Type = Sym.getType(); // Skip undefined and STAB entries. if ((Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown)) continue; // The only symbols of interest are the global variables. These // are the only ones that need to be queried because the address // of common data won't be described in the debug map. All other // addresses should be fetched for the debug map. if (!(Sym.getFlags() & SymbolRef::SF_Global)) continue; ErrorOr<section_iterator> SectionOrErr = Sym.getSection(); if (!SectionOrErr) continue; Section = *SectionOrErr; if (Section == MainBinary.section_end() || Section->isText()) continue; uint64_t Addr = Sym.getValue(); ErrorOr<StringRef> NameOrErr = Sym.getName(); if (!NameOrErr) continue; StringRef Name = *NameOrErr; if (Name.size() == 0 || Name[0] == '\0') continue; MainBinarySymbolAddresses[Name] = Addr; } }
/// @brief Checks to see if the @p o ObjectFile is a Mach-O file and if it is /// and there is a list of architecture flags specified then check to /// make sure this Mach-O file is one of those architectures or all /// architectures was specificed. If not then an error is generated and /// this routine returns false. Else it returns true. static bool checkMachOAndArchFlags(ObjectFile *o, StringRef file) { if (isa<MachOObjectFile>(o) && !ArchAll && ArchFlags.size() != 0) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(o); bool ArchFound = false; MachO::mach_header H; MachO::mach_header_64 H_64; Triple T; if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); } else { H = MachO->MachOObjectFile::getHeader(); T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); } unsigned i; for (i = 0; i < ArchFlags.size(); ++i) { if (ArchFlags[i] == T.getArchName()) ArchFound = true; break; } if (!ArchFound) { errs() << ToolName << ": file: " << file << " does not contain architecture: " << ArchFlags[i] << ".\n"; return false; } } return true; }
static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { DataRefImpl Symb = I->getRawDataRefImpl(); uint8_t NType = getNType(Obj, Symb); switch (NType & MachO::N_TYPE) { case MachO::N_ABS: return 's'; case MachO::N_INDR: return 'i'; case MachO::N_SECT: { section_iterator Sec = Obj.section_end(); Obj.getSymbolSection(Symb, Sec); DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; Obj.getSectionName(Ref, SectionName); StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); if (SegmentName == "__TEXT" && SectionName == "__text") return 't'; else if (SegmentName == "__DATA" && SectionName == "__data") return 'd'; else if (SegmentName == "__DATA" && SectionName == "__bss") return 'b'; else return 's'; } } return '?'; }
static uint8_t getNType(MachOObjectFile &Obj, DataRefImpl Symb) { if (Obj.is64Bit()) { MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); return STE.n_type; } MachO::nlist STE = Obj.getSymbolTableEntry(Symb); return STE.n_type; }
error_or<uint64_t> image_entry_macho(const MachOObjectFile& obj) { auto it = std::find_if(obj.begin_load_commands(), obj.end_load_commands(), is_main); if (it == obj.end_load_commands()) return failure("LC_MAIN not found, binary version < 10.8"); const MachO::entry_point_command *entry_cmd = reinterpret_cast<const MachO::entry_point_command*>(it->Ptr); return success(entry_cmd->entryoff); }
// getNsectInMachO() is used to implement the Mach-O "-s segname sectname" // option to dump only those symbols from that section in a Mach-O file. // It is called once for each symbol in a Mach-O file from // dumpSymbolNamesFromObject() and returns the section number for that symbol // if it is in a section, else it returns 0. static unsigned getNsectInMachO(MachOObjectFile &Obj, basic_symbol_iterator I) { DataRefImpl Symb = I->getRawDataRefImpl(); if (Obj.is64Bit()) { MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT) return STE.n_sect; return 0; } MachO::nlist STE = Obj.getSymbolTableEntry(Symb); if ((STE.n_type & MachO::N_TYPE) == MachO::N_SECT) return STE.n_sect; return 0; }
std::vector<segment> read(const MachOObjectFile& obj) { typedef MachOObjectFile::LoadCommandInfo command_info; std::vector<command_info> cmds = utils::load_commands(obj); std::vector<segment> segments; for (std::size_t i = 0; i < cmds.size(); ++i) { command_info info = cmds.at(i); if (info.C.cmd == MachO::LoadCommandType::LC_SEGMENT_64) segments.push_back(segment(obj.getSegment64LoadCommand(info))); if (info.C.cmd == MachO::LoadCommandType::LC_SEGMENT) segments.push_back(segment(obj.getSegmentLoadCommand(info))); } return segments; }
std::vector<MachOObjectFile::LoadCommandInfo> load_commands(const MachOObjectFile& obj) { std::size_t cmd_count = 0; if (obj.is64Bit()) cmd_count = obj.getHeader64().ncmds; else cmd_count = obj.getHeader().ncmds; std::vector<MachOObjectFile::LoadCommandInfo> cmds; MachOObjectFile::LoadCommandInfo info = obj.getFirstLoadCommandInfo(); for (std::size_t i = 0; i < cmd_count; ++i) { cmds.push_back(info); info = obj.getNextLoadCommandInfo(info); } return cmds; }
section_iterator RuntimeDyldMachO::getSectionByAddress(const MachOObjectFile &Obj, uint64_t Addr) { section_iterator SI = Obj.section_begin(); section_iterator SE = Obj.section_end(); for (; SI != SE; ++SI) { uint64_t SAddr = SI->getAddress(); uint64_t SSize = SI->getSize(); if ((Addr >= SAddr) && (Addr < SAddr + SSize)) return SI; } return SE; }
/// Load the interesting main binary symbols' addresses into /// MainBinarySymbolAddresses. void MachODebugMapParser::loadMainBinarySymbols( const MachOObjectFile &MainBinary) { MainBinarySymbolAddresses.clear(); for (const auto &Sym : MainBinary.symbols()) { SymbolRef::Type Type; // Skip undefined and STAB entries. if (Sym.getType(Type) || (Type & SymbolRef::ST_Debug) || (Type & SymbolRef::ST_Unknown)) continue; StringRef Name; uint64_t Addr; if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize || Sym.getName(Name) || Name.size() == 0 || Name[0] == '\0') { continue; } // FIXME: dsymutil-classic ompatibility: retain the first // symbol with a given name. We should check why we get duplicated // symbols with different addresses instead. (emacs binary has 2 // Qwindow symbols) uint64_t &AddrInMap = MainBinarySymbolAddresses[Name]; if (!AddrInMap) AddrInMap = Addr; } }
/// Load the interesting main binary symbols' addresses into /// MainBinarySymbolAddresses. void MachODebugMapParser::loadMainBinarySymbols( const MachOObjectFile &MainBinary) { section_iterator Section = MainBinary.section_end(); MainBinarySymbolAddresses.clear(); for (const auto &Sym : MainBinary.symbols()) { Expected<SymbolRef::Type> TypeOrErr = Sym.getType(); if (!TypeOrErr) { // TODO: Actually report errors helpfully. consumeError(TypeOrErr.takeError()); continue; } SymbolRef::Type Type = *TypeOrErr; // Skip undefined and STAB entries. if ((Type == SymbolRef::ST_Debug) || (Type == SymbolRef::ST_Unknown)) continue; // The only symbols of interest are the global variables. These // are the only ones that need to be queried because the address // of common data won't be described in the debug map. All other // addresses should be fetched for the debug map. uint8_t SymType = MainBinary.getSymbolTableEntry(Sym.getRawDataRefImpl()).n_type; if (!(SymType & (MachO::N_EXT | MachO::N_PEXT))) continue; Expected<section_iterator> SectionOrErr = Sym.getSection(); if (!SectionOrErr) { // TODO: Actually report errors helpfully. consumeError(SectionOrErr.takeError()); continue; } Section = *SectionOrErr; if (Section == MainBinary.section_end() || Section->isText()) continue; uint64_t Addr = Sym.getValue(); Expected<StringRef> NameOrErr = Sym.getName(); if (!NameOrErr) { // TODO: Actually report errors helpfully. consumeError(NameOrErr.takeError()); continue; } StringRef Name = *NameOrErr; if (Name.size() == 0 || Name[0] == '\0') continue; MainBinarySymbolAddresses[Name] = Addr; } }
std::unique_ptr<DebugMap> MachODebugMapParser::parseOneBinary(const MachOObjectFile &MainBinary, StringRef BinaryPath) { loadMainBinarySymbols(MainBinary); Result = make_unique<DebugMap>(BinaryHolder::getTriple(MainBinary), BinaryPath); MainBinaryStrings = MainBinary.getStringTableData(); for (const SymbolRef &Symbol : MainBinary.symbols()) { const DataRefImpl &DRI = Symbol.getRawDataRefImpl(); if (MainBinary.is64Bit()) handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI)); else handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI)); } resetParserState(); return std::move(Result); }
void MachODebugMapParser::dumpOneBinaryStab(const MachOObjectFile &MainBinary, StringRef BinaryPath) { loadMainBinarySymbols(MainBinary); MainBinaryStrings = MainBinary.getStringTableData(); raw_ostream &OS(llvm::outs()); dumpSymTabHeader(OS, getArchName(MainBinary)); uint64_t Idx = 0; for (const SymbolRef &Symbol : MainBinary.symbols()) { const DataRefImpl &DRI = Symbol.getRawDataRefImpl(); if (MainBinary.is64Bit()) dumpSymTabEntry(OS, Idx, MainBinary.getSymbol64TableEntry(DRI)); else dumpSymTabEntry(OS, Idx, MainBinary.getSymbolTableEntry(DRI)); Idx++; } OS << "\n\n"; resetParserState(); }
// Populate __pointers section. void RuntimeDyldMachO::populateIndirectSymbolPointersSection( const MachOObjectFile &Obj, const SectionRef &PTSection, unsigned PTSectionID) { assert(!Obj.is64Bit() && "Pointer table section not supported in 64-bit MachO."); MachO::dysymtab_command DySymTabCmd = Obj.getDysymtabLoadCommand(); MachO::section Sec32 = Obj.getSection(PTSection.getRawDataRefImpl()); uint32_t PTSectionSize = Sec32.size; unsigned FirstIndirectSymbol = Sec32.reserved1; const unsigned PTEntrySize = 4; unsigned NumPTEntries = PTSectionSize / PTEntrySize; unsigned PTEntryOffset = 0; assert((PTSectionSize % PTEntrySize) == 0 && "Pointers section does not contain a whole number of stubs?"); DEBUG(dbgs() << "Populating pointer table section " << Sections[PTSectionID].getName() << ", Section ID " << PTSectionID << ", " << NumPTEntries << " entries, " << PTEntrySize << " bytes each:\n"); for (unsigned i = 0; i < NumPTEntries; ++i) { unsigned SymbolIndex = Obj.getIndirectSymbolTableEntry(DySymTabCmd, FirstIndirectSymbol + i); symbol_iterator SI = Obj.getSymbolByIndex(SymbolIndex); ErrorOr<StringRef> IndirectSymbolNameOrErr = SI->getName(); if (std::error_code EC = IndirectSymbolNameOrErr.getError()) report_fatal_error(EC.message()); StringRef IndirectSymbolName = *IndirectSymbolNameOrErr; DEBUG(dbgs() << " " << IndirectSymbolName << ": index " << SymbolIndex << ", PT offset: " << PTEntryOffset << "\n"); RelocationEntry RE(PTSectionID, PTEntryOffset, MachO::GENERIC_RELOC_VANILLA, 0, false, 2); addRelocationForSymbol(RE, IndirectSymbolName); PTEntryOffset += PTEntrySize; } }
MCMachOObjectDisassembler::MCMachOObjectDisassembler( const MachOObjectFile &MOOF, const MCDisassembler &Dis, const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, uint64_t HeaderLoadAddress) : MCObjectDisassembler(MOOF, Dis, MIA), MOOF(MOOF), VMAddrSlide(VMAddrSlide), HeaderLoadAddress(HeaderLoadAddress) { error_code ec; for (section_iterator SI = MOOF.begin_sections(), SE = MOOF.end_sections(); SI != SE; SI.increment(ec)) { if (ec) break; StringRef Name; SI->getName(Name); // FIXME: We should use the S_ section type instead of the name. if (Name == "__mod_init_func") { DEBUG(dbgs() << "Found __mod_init_func section!\n"); SI->getContents(ModInitContents); } else if (Name == "__mod_exit_func") { DEBUG(dbgs() << "Found __mod_exit_func section!\n"); SI->getContents(ModExitContents); } } }
// checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file // and if it is and there is a list of architecture flags is specified then // check to make sure this Mach-O file is one of those architectures or all // architectures was specificed. If not then an error is generated and this // routine returns false. Else it returns true. static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) { MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(O); if (!MachO || ArchAll || ArchFlags.size() == 0) return true; MachO::mach_header H; MachO::mach_header_64 H_64; Triple T; if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); T = MachOObjectFile::getArch(H_64.cputype, H_64.cpusubtype); } else { H = MachO->MachOObjectFile::getHeader(); T = MachOObjectFile::getArch(H.cputype, H.cpusubtype); } if (std::none_of( ArchFlags.begin(), ArchFlags.end(), [&](const std::string &Name) { return Name == T.getArchName(); })) { error("No architecture specified", Filename); return false; } return true; }
MCMachOObjectDisassembler::MCMachOObjectDisassembler( const MachOObjectFile &MOOF, const MCDisassembler &Dis, const MCInstrAnalysis &MIA, uint64_t VMAddrSlide, uint64_t HeaderLoadAddress) : MCObjectDisassembler(MOOF, Dis, MIA), MOOF(MOOF), VMAddrSlide(VMAddrSlide), HeaderLoadAddress(HeaderLoadAddress) { for (const SectionRef &Section : MOOF.sections()) { StringRef Name; Section.getName(Name); // FIXME: We should use the S_ section type instead of the name. if (Name == "__mod_init_func") { DEBUG(dbgs() << "Found __mod_init_func section!\n"); Section.getContents(ModInitContents); } else if (Name == "__mod_exit_func") { DEBUG(dbgs() << "Found __mod_exit_func section!\n"); Section.getContents(ModExitContents); } } }
static uint32_t getCPUType(MachOObjectFile &MachO) { if (MachO.is64Bit()) return MachO.getHeader64().cputype; else return MachO.getHeader().cputype; }
// darwinPrintSymbol() is used to print a symbol from a Mach-O file when the // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For // the darwin format it produces the same output as darwin's nm(1) -m output // and when printing Mach-O symbols in hex it produces the same output as // darwin's nm(1) -x format. static void darwinPrintSymbol(SymbolicFile &Obj, SymbolListT::iterator I, char *SymbolAddrStr, const char *printBlanks, const char *printDashes, const char *printFormat) { MachO::mach_header H; MachO::mach_header_64 H_64; uint32_t Filetype = MachO::MH_OBJECT; uint32_t Flags = 0; uint8_t NType = 0; uint8_t NSect = 0; uint16_t NDesc = 0; uint32_t NStrx = 0; uint64_t NValue = 0; MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); if (Obj.isIR()) { uint32_t SymFlags = I->Sym.getFlags(); if (SymFlags & SymbolRef::SF_Global) NType |= MachO::N_EXT; if (SymFlags & SymbolRef::SF_Hidden) NType |= MachO::N_PEXT; if (SymFlags & SymbolRef::SF_Undefined) NType |= MachO::N_EXT | MachO::N_UNDF; else { // Here we have a symbol definition. So to fake out a section name we // use 1, 2 and 3 for section numbers. See below where they are used to // print out fake section names. NType |= MachO::N_SECT; if(SymFlags & SymbolRef::SF_Const) NSect = 3; else { IRObjectFile *IRobj = dyn_cast<IRObjectFile>(&Obj); char c = getSymbolNMTypeChar(*IRobj, I->Sym); if (c == 't') NSect = 1; else NSect = 2; } } if (SymFlags & SymbolRef::SF_Weak) NDesc |= MachO::N_WEAK_DEF; } else { DataRefImpl SymDRI = I->Sym.getRawDataRefImpl(); if (MachO->is64Bit()) { H_64 = MachO->MachOObjectFile::getHeader64(); Filetype = H_64.filetype; Flags = H_64.flags; MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI); NType = STE_64.n_type; NSect = STE_64.n_sect; NDesc = STE_64.n_desc; NStrx = STE_64.n_strx; NValue = STE_64.n_value; } else { H = MachO->MachOObjectFile::getHeader(); Filetype = H.filetype; Flags = H.flags; MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI); NType = STE.n_type; NSect = STE.n_sect; NDesc = STE.n_desc; NStrx = STE.n_strx; NValue = STE.n_value; } } // If we are printing Mach-O symbols in hex do that and return. if (FormatMachOasHex) { char Str[18] = ""; format(printFormat, NValue).print(Str, sizeof(Str)); outs() << Str << ' '; format("%02x", NType).print(Str, sizeof(Str)); outs() << Str << ' '; format("%02x", NSect).print(Str, sizeof(Str)); outs() << Str << ' '; format("%04x", NDesc).print(Str, sizeof(Str)); outs() << Str << ' '; format("%08x", NStrx).print(Str, sizeof(Str)); outs() << Str << ' '; outs() << I->Name << "\n"; return; } if (PrintAddress) { if ((NType & MachO::N_TYPE) == MachO::N_INDR) strcpy(SymbolAddrStr, printBlanks); if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE) strcpy(SymbolAddrStr, printDashes); outs() << SymbolAddrStr << ' '; } switch (NType & MachO::N_TYPE) { case MachO::N_UNDF: if (NValue != 0) { outs() << "(common) "; if (MachO::GET_COMM_ALIGN(NDesc) != 0) outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; } else { if ((NType & MachO::N_TYPE) == MachO::N_PBUD) outs() << "(prebound "; else outs() << "("; if ((NDesc & MachO::REFERENCE_TYPE) == MachO::REFERENCE_FLAG_UNDEFINED_LAZY) outs() << "undefined [lazy bound]) "; else if ((NDesc & MachO::REFERENCE_TYPE) == MachO::REFERENCE_FLAG_UNDEFINED_LAZY) outs() << "undefined [private lazy bound]) "; else if ((NDesc & MachO::REFERENCE_TYPE) == MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY) outs() << "undefined [private]) "; else outs() << "undefined) "; } break; case MachO::N_ABS: outs() << "(absolute) "; break; case MachO::N_INDR: outs() << "(indirect) "; break; case MachO::N_SECT: { if (Obj.isIR()) { // For llvm bitcode files print out a fake section name using the values // use 1, 2 and 3 for section numbers as set above. if (NSect == 1) outs() << "(LTO,CODE) "; else if (NSect == 2) outs() << "(LTO,DATA) "; else if (NSect == 3) outs() << "(LTO,RODATA) "; else outs() << "(?,?) "; break; } ErrorOr<section_iterator> SecOrErr = MachO->getSymbolSection(I->Sym.getRawDataRefImpl()); if (SecOrErr.getError()) { outs() << "(?,?) "; break; } section_iterator Sec = *SecOrErr; DataRefImpl Ref = Sec->getRawDataRefImpl(); StringRef SectionName; MachO->getSectionName(Ref, SectionName); StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref); outs() << "(" << SegmentName << "," << SectionName << ") "; break; } default: outs() << "(?) "; break; } if (NType & MachO::N_EXT) { if (NDesc & MachO::REFERENCED_DYNAMICALLY) outs() << "[referenced dynamically] "; if (NType & MachO::N_PEXT) { if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) outs() << "weak private external "; else outs() << "private external "; } else { if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF || (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) { if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) == (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) outs() << "weak external automatically hidden "; else outs() << "weak external "; } else outs() << "external "; } } else { if (NType & MachO::N_PEXT) outs() << "non-external (was a private external) "; else outs() << "non-external "; } if (Filetype == MachO::MH_OBJECT && (NDesc & MachO::N_NO_DEAD_STRIP) == MachO::N_NO_DEAD_STRIP) outs() << "[no dead strip] "; if (Filetype == MachO::MH_OBJECT && ((NType & MachO::N_TYPE) != MachO::N_UNDF) && (NDesc & MachO::N_SYMBOL_RESOLVER) == MachO::N_SYMBOL_RESOLVER) outs() << "[symbol resolver] "; if (Filetype == MachO::MH_OBJECT && ((NType & MachO::N_TYPE) != MachO::N_UNDF) && (NDesc & MachO::N_ALT_ENTRY) == MachO::N_ALT_ENTRY) outs() << "[alt entry] "; if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF) outs() << "[Thumb] "; if ((NType & MachO::N_TYPE) == MachO::N_INDR) { outs() << I->Name << " (for "; StringRef IndirectName; if (!MachO || MachO->getIndirectName(I->Sym.getRawDataRefImpl(), IndirectName)) outs() << "?)"; else outs() << IndirectName << ")"; } else outs() << I->Name; if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || (NType & MachO::N_TYPE) == MachO::N_PBUD)) { uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); if (LibraryOrdinal != 0) { if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL) outs() << " (from executable)"; else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL) outs() << " (dynamically looked up)"; else { StringRef LibraryName; if (!MachO || MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; else outs() << " (from " << LibraryName << ")"; } } } outs() << "\n"; }