10b57cec5SDimitry Andric //===-- llvm-nm.cpp - Symbol table dumping utility for llvm ---------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This program is a utility that works like traditional Unix "nm", that is, it 100b57cec5SDimitry Andric // prints out the names of symbols in a bitcode or object file, along with some 110b57cec5SDimitry Andric // information about each symbol. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric // This "nm" supports many of the features of GNU "nm", including its different 140b57cec5SDimitry Andric // output formats. 150b57cec5SDimitry Andric // 160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 170b57cec5SDimitry Andric 180b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h" 190b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 200b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h" 210b57cec5SDimitry Andric #include "llvm/IR/Function.h" 220b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h" 230b57cec5SDimitry Andric #include "llvm/Object/Archive.h" 240b57cec5SDimitry Andric #include "llvm/Object/COFF.h" 250b57cec5SDimitry Andric #include "llvm/Object/COFFImportFile.h" 260b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h" 270b57cec5SDimitry Andric #include "llvm/Object/IRObjectFile.h" 280b57cec5SDimitry Andric #include "llvm/Object/MachO.h" 290b57cec5SDimitry Andric #include "llvm/Object/MachOUniversal.h" 300b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h" 315ffd83dbSDimitry Andric #include "llvm/Object/TapiFile.h" 325ffd83dbSDimitry Andric #include "llvm/Object/TapiUniversal.h" 330b57cec5SDimitry Andric #include "llvm/Object/Wasm.h" 340b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h" 350b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 360b57cec5SDimitry Andric #include "llvm/Support/Format.h" 370b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h" 380b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 390b57cec5SDimitry Andric #include "llvm/Support/Program.h" 400b57cec5SDimitry Andric #include "llvm/Support/Signals.h" 410b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h" 420b57cec5SDimitry Andric #include "llvm/Support/WithColor.h" 430b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 440b57cec5SDimitry Andric #include <vector> 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric using namespace llvm; 470b57cec5SDimitry Andric using namespace object; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric namespace { 500b57cec5SDimitry Andric enum OutputFormatTy { bsd, sysv, posix, darwin }; 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric cl::OptionCategory NMCat("llvm-nm Options"); 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric cl::opt<OutputFormatTy> OutputFormat( 550b57cec5SDimitry Andric "format", cl::desc("Specify output format"), 560b57cec5SDimitry Andric cl::values(clEnumVal(bsd, "BSD format"), clEnumVal(sysv, "System V format"), 570b57cec5SDimitry Andric clEnumVal(posix, "POSIX.2 format"), 580b57cec5SDimitry Andric clEnumVal(darwin, "Darwin -m format")), 590b57cec5SDimitry Andric cl::init(bsd), cl::cat(NMCat)); 600b57cec5SDimitry Andric cl::alias OutputFormat2("f", cl::desc("Alias for --format"), 610b57cec5SDimitry Andric cl::aliasopt(OutputFormat)); 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<input files>"), 640b57cec5SDimitry Andric cl::ZeroOrMore); 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric cl::opt<bool> UndefinedOnly("undefined-only", 670b57cec5SDimitry Andric cl::desc("Show only undefined symbols"), 680b57cec5SDimitry Andric cl::cat(NMCat)); 690b57cec5SDimitry Andric cl::alias UndefinedOnly2("u", cl::desc("Alias for --undefined-only"), 700b57cec5SDimitry Andric cl::aliasopt(UndefinedOnly), cl::Grouping); 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric cl::opt<bool> DynamicSyms("dynamic", 730b57cec5SDimitry Andric cl::desc("Display the dynamic symbols instead " 740b57cec5SDimitry Andric "of normal symbols."), 750b57cec5SDimitry Andric cl::cat(NMCat)); 760b57cec5SDimitry Andric cl::alias DynamicSyms2("D", cl::desc("Alias for --dynamic"), 770b57cec5SDimitry Andric cl::aliasopt(DynamicSyms), cl::Grouping); 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric cl::opt<bool> DefinedOnly("defined-only", cl::desc("Show only defined symbols"), 800b57cec5SDimitry Andric cl::cat(NMCat)); 810b57cec5SDimitry Andric cl::alias DefinedOnly2("U", cl::desc("Alias for --defined-only"), 820b57cec5SDimitry Andric cl::aliasopt(DefinedOnly), cl::Grouping); 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric cl::opt<bool> ExternalOnly("extern-only", 850b57cec5SDimitry Andric cl::desc("Show only external symbols"), 860b57cec5SDimitry Andric cl::ZeroOrMore, cl::cat(NMCat)); 870b57cec5SDimitry Andric cl::alias ExternalOnly2("g", cl::desc("Alias for --extern-only"), 880b57cec5SDimitry Andric cl::aliasopt(ExternalOnly), cl::Grouping, 890b57cec5SDimitry Andric cl::ZeroOrMore); 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric cl::opt<bool> NoWeakSymbols("no-weak", cl::desc("Show only non-weak symbols"), 920b57cec5SDimitry Andric cl::cat(NMCat)); 930b57cec5SDimitry Andric cl::alias NoWeakSymbols2("W", cl::desc("Alias for --no-weak"), 940b57cec5SDimitry Andric cl::aliasopt(NoWeakSymbols), cl::Grouping); 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric cl::opt<bool> BSDFormat("B", cl::desc("Alias for --format=bsd"), cl::Grouping, 970b57cec5SDimitry Andric cl::cat(NMCat)); 980b57cec5SDimitry Andric cl::opt<bool> POSIXFormat("P", cl::desc("Alias for --format=posix"), 990b57cec5SDimitry Andric cl::Grouping, cl::cat(NMCat)); 1000b57cec5SDimitry Andric cl::alias Portability("portability", cl::desc("Alias for --format=posix"), 1010b57cec5SDimitry Andric cl::aliasopt(POSIXFormat), cl::NotHidden); 1020b57cec5SDimitry Andric cl::opt<bool> DarwinFormat("m", cl::desc("Alias for --format=darwin"), 1030b57cec5SDimitry Andric cl::Grouping, cl::cat(NMCat)); 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric static cl::list<std::string> 1060b57cec5SDimitry Andric ArchFlags("arch", cl::desc("architecture(s) from a Mach-O file to dump"), 1070b57cec5SDimitry Andric cl::ZeroOrMore, cl::cat(NMCat)); 1080b57cec5SDimitry Andric bool ArchAll = false; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric cl::opt<bool> PrintFileName( 1110b57cec5SDimitry Andric "print-file-name", 1120b57cec5SDimitry Andric cl::desc("Precede each symbol with the object file it came from"), 1130b57cec5SDimitry Andric cl::cat(NMCat)); 1140b57cec5SDimitry Andric 1150b57cec5SDimitry Andric cl::alias PrintFileNameA("A", cl::desc("Alias for --print-file-name"), 1160b57cec5SDimitry Andric cl::aliasopt(PrintFileName), cl::Grouping); 1170b57cec5SDimitry Andric cl::alias PrintFileNameo("o", cl::desc("Alias for --print-file-name"), 1180b57cec5SDimitry Andric cl::aliasopt(PrintFileName), cl::Grouping); 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric cl::opt<bool> DebugSyms("debug-syms", 1210b57cec5SDimitry Andric cl::desc("Show all symbols, even debugger only"), 1220b57cec5SDimitry Andric cl::cat(NMCat)); 1230b57cec5SDimitry Andric cl::alias DebugSymsa("a", cl::desc("Alias for --debug-syms"), 1240b57cec5SDimitry Andric cl::aliasopt(DebugSyms), cl::Grouping); 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric cl::opt<bool> NumericSort("numeric-sort", cl::desc("Sort symbols by address"), 1270b57cec5SDimitry Andric cl::cat(NMCat)); 1280b57cec5SDimitry Andric cl::alias NumericSortn("n", cl::desc("Alias for --numeric-sort"), 1290b57cec5SDimitry Andric cl::aliasopt(NumericSort), cl::Grouping); 1300b57cec5SDimitry Andric cl::alias NumericSortv("v", cl::desc("Alias for --numeric-sort"), 1310b57cec5SDimitry Andric cl::aliasopt(NumericSort), cl::Grouping); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric cl::opt<bool> NoSort("no-sort", cl::desc("Show symbols in order encountered"), 1340b57cec5SDimitry Andric cl::cat(NMCat)); 1350b57cec5SDimitry Andric cl::alias NoSortp("p", cl::desc("Alias for --no-sort"), cl::aliasopt(NoSort), 1360b57cec5SDimitry Andric cl::Grouping); 1370b57cec5SDimitry Andric 1380b57cec5SDimitry Andric cl::opt<bool> Demangle("demangle", cl::ZeroOrMore, 1390b57cec5SDimitry Andric cl::desc("Demangle C++ symbol names"), cl::cat(NMCat)); 1400b57cec5SDimitry Andric cl::alias DemangleC("C", cl::desc("Alias for --demangle"), 1410b57cec5SDimitry Andric cl::aliasopt(Demangle), cl::Grouping); 1420b57cec5SDimitry Andric cl::opt<bool> NoDemangle("no-demangle", cl::init(false), cl::ZeroOrMore, 1430b57cec5SDimitry Andric cl::desc("Don't demangle symbol names"), 1440b57cec5SDimitry Andric cl::cat(NMCat)); 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric cl::opt<bool> ReverseSort("reverse-sort", cl::desc("Sort in reverse order"), 1470b57cec5SDimitry Andric cl::cat(NMCat)); 1480b57cec5SDimitry Andric cl::alias ReverseSortr("r", cl::desc("Alias for --reverse-sort"), 1490b57cec5SDimitry Andric cl::aliasopt(ReverseSort), cl::Grouping); 1500b57cec5SDimitry Andric 1510b57cec5SDimitry Andric cl::opt<bool> PrintSize("print-size", 1520b57cec5SDimitry Andric cl::desc("Show symbol size as well as address"), 1530b57cec5SDimitry Andric cl::cat(NMCat)); 1540b57cec5SDimitry Andric cl::alias PrintSizeS("S", cl::desc("Alias for --print-size"), 1550b57cec5SDimitry Andric cl::aliasopt(PrintSize), cl::Grouping); 1560b57cec5SDimitry Andric bool MachOPrintSizeWarning = false; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric cl::opt<bool> SizeSort("size-sort", cl::desc("Sort symbols by size"), 1590b57cec5SDimitry Andric cl::cat(NMCat)); 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric cl::opt<bool> WithoutAliases("without-aliases", cl::Hidden, 1620b57cec5SDimitry Andric cl::desc("Exclude aliases from output"), 1630b57cec5SDimitry Andric cl::cat(NMCat)); 1640b57cec5SDimitry Andric 1650b57cec5SDimitry Andric cl::opt<bool> ArchiveMap("print-armap", cl::desc("Print the archive map"), 1660b57cec5SDimitry Andric cl::cat(NMCat)); 1670b57cec5SDimitry Andric cl::alias ArchiveMaps("M", cl::desc("Alias for --print-armap"), 1680b57cec5SDimitry Andric cl::aliasopt(ArchiveMap), cl::Grouping); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric enum Radix { d, o, x }; 1710b57cec5SDimitry Andric cl::opt<Radix> 1720b57cec5SDimitry Andric AddressRadix("radix", cl::desc("Radix (o/d/x) for printing symbol Values"), 1730b57cec5SDimitry Andric cl::values(clEnumVal(d, "decimal"), clEnumVal(o, "octal"), 1740b57cec5SDimitry Andric clEnumVal(x, "hexadecimal")), 1750b57cec5SDimitry Andric cl::init(x), cl::cat(NMCat)); 1760b57cec5SDimitry Andric cl::alias RadixAlias("t", cl::desc("Alias for --radix"), 1770b57cec5SDimitry Andric cl::aliasopt(AddressRadix)); 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric cl::opt<bool> JustSymbolName("just-symbol-name", 1800b57cec5SDimitry Andric cl::desc("Print just the symbol's name"), 1810b57cec5SDimitry Andric cl::cat(NMCat)); 1820b57cec5SDimitry Andric cl::alias JustSymbolNames("j", cl::desc("Alias for --just-symbol-name"), 1830b57cec5SDimitry Andric cl::aliasopt(JustSymbolName), cl::Grouping); 1840b57cec5SDimitry Andric 1855ffd83dbSDimitry Andric cl::opt<bool> 1865ffd83dbSDimitry Andric SpecialSyms("special-syms", 1875ffd83dbSDimitry Andric cl::desc("Do not filter special symbols from the output"), 1885ffd83dbSDimitry Andric cl::cat(NMCat)); 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric cl::list<std::string> SegSect("s", cl::multi_val(2), cl::ZeroOrMore, 1910b57cec5SDimitry Andric cl::value_desc("segment section"), cl::Hidden, 1920b57cec5SDimitry Andric cl::desc("Dump only symbols from this segment " 1930b57cec5SDimitry Andric "and section name, Mach-O only"), 1940b57cec5SDimitry Andric cl::cat(NMCat)); 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric cl::opt<bool> FormatMachOasHex("x", 1970b57cec5SDimitry Andric cl::desc("Print symbol entry in hex, " 1980b57cec5SDimitry Andric "Mach-O only"), 1990b57cec5SDimitry Andric cl::Grouping, cl::cat(NMCat)); 2000b57cec5SDimitry Andric cl::opt<bool> AddDyldInfo("add-dyldinfo", 2010b57cec5SDimitry Andric cl::desc("Add symbols from the dyldinfo not already " 2020b57cec5SDimitry Andric "in the symbol table, Mach-O only"), 2030b57cec5SDimitry Andric cl::cat(NMCat)); 2040b57cec5SDimitry Andric cl::opt<bool> NoDyldInfo("no-dyldinfo", 2050b57cec5SDimitry Andric cl::desc("Don't add any symbols from the dyldinfo, " 2060b57cec5SDimitry Andric "Mach-O only"), 2070b57cec5SDimitry Andric cl::cat(NMCat)); 2080b57cec5SDimitry Andric cl::opt<bool> DyldInfoOnly("dyldinfo-only", 2090b57cec5SDimitry Andric cl::desc("Show only symbols from the dyldinfo, " 2100b57cec5SDimitry Andric "Mach-O only"), 2110b57cec5SDimitry Andric cl::cat(NMCat)); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric cl::opt<bool> NoLLVMBitcode("no-llvm-bc", 2140b57cec5SDimitry Andric cl::desc("Disable LLVM bitcode reader"), 2150b57cec5SDimitry Andric cl::cat(NMCat)); 2160b57cec5SDimitry Andric 2175ffd83dbSDimitry Andric cl::opt<bool> AddInlinedInfo("add-inlinedinfo", 2185ffd83dbSDimitry Andric cl::desc("Add symbols from the inlined libraries, " 2195ffd83dbSDimitry Andric "TBD(Mach-O) only"), 2205ffd83dbSDimitry Andric cl::cat(NMCat)); 2215ffd83dbSDimitry Andric 2220b57cec5SDimitry Andric cl::extrahelp HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); 2230b57cec5SDimitry Andric 2240b57cec5SDimitry Andric bool PrintAddress = true; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric bool MultipleFiles = false; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric bool HadError = false; 2290b57cec5SDimitry Andric 2300b57cec5SDimitry Andric std::string ToolName; 2310b57cec5SDimitry Andric } // anonymous namespace 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric static void error(Twine Message, Twine Path = Twine()) { 2340b57cec5SDimitry Andric HadError = true; 2350b57cec5SDimitry Andric WithColor::error(errs(), ToolName) << Path << ": " << Message << ".\n"; 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric static bool error(std::error_code EC, Twine Path = Twine()) { 2390b57cec5SDimitry Andric if (EC) { 2400b57cec5SDimitry Andric error(EC.message(), Path); 2410b57cec5SDimitry Andric return true; 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric return false; 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric // This version of error() prints the archive name and member name, for example: 2470b57cec5SDimitry Andric // "libx.a(foo.o)" after the ToolName before the error message. It sets 2480b57cec5SDimitry Andric // HadError but returns allowing the code to move on to other archive members. 2490b57cec5SDimitry Andric static void error(llvm::Error E, StringRef FileName, const Archive::Child &C, 2500b57cec5SDimitry Andric StringRef ArchitectureName = StringRef()) { 2510b57cec5SDimitry Andric HadError = true; 2520b57cec5SDimitry Andric WithColor::error(errs(), ToolName) << FileName; 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric Expected<StringRef> NameOrErr = C.getName(); 2550b57cec5SDimitry Andric // TODO: if we have a error getting the name then it would be nice to print 2560b57cec5SDimitry Andric // the index of which archive member this is and or its offset in the 2570b57cec5SDimitry Andric // archive instead of "???" as the name. 2580b57cec5SDimitry Andric if (!NameOrErr) { 2590b57cec5SDimitry Andric consumeError(NameOrErr.takeError()); 2600b57cec5SDimitry Andric errs() << "(" << "???" << ")"; 2610b57cec5SDimitry Andric } else 2620b57cec5SDimitry Andric errs() << "(" << NameOrErr.get() << ")"; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric if (!ArchitectureName.empty()) 2650b57cec5SDimitry Andric errs() << " (for architecture " << ArchitectureName << ") "; 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric std::string Buf; 2680b57cec5SDimitry Andric raw_string_ostream OS(Buf); 2690b57cec5SDimitry Andric logAllUnhandledErrors(std::move(E), OS); 2700b57cec5SDimitry Andric OS.flush(); 2710b57cec5SDimitry Andric errs() << " " << Buf << "\n"; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 2740b57cec5SDimitry Andric // This version of error() prints the file name and which architecture slice it 2750b57cec5SDimitry Andric // is from, for example: "foo.o (for architecture i386)" after the ToolName 2760b57cec5SDimitry Andric // before the error message. It sets HadError but returns allowing the code to 2770b57cec5SDimitry Andric // move on to other architecture slices. 2780b57cec5SDimitry Andric static void error(llvm::Error E, StringRef FileName, 2790b57cec5SDimitry Andric StringRef ArchitectureName = StringRef()) { 2800b57cec5SDimitry Andric HadError = true; 2810b57cec5SDimitry Andric WithColor::error(errs(), ToolName) << FileName; 2820b57cec5SDimitry Andric 2830b57cec5SDimitry Andric if (!ArchitectureName.empty()) 2840b57cec5SDimitry Andric errs() << " (for architecture " << ArchitectureName << ") "; 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric std::string Buf; 2870b57cec5SDimitry Andric raw_string_ostream OS(Buf); 2880b57cec5SDimitry Andric logAllUnhandledErrors(std::move(E), OS); 2890b57cec5SDimitry Andric OS.flush(); 2900b57cec5SDimitry Andric errs() << " " << Buf << "\n"; 2910b57cec5SDimitry Andric } 2920b57cec5SDimitry Andric 2930b57cec5SDimitry Andric namespace { 2940b57cec5SDimitry Andric struct NMSymbol { 2950b57cec5SDimitry Andric uint64_t Address; 2960b57cec5SDimitry Andric uint64_t Size; 2970b57cec5SDimitry Andric char TypeChar; 298*e8d8bef9SDimitry Andric std::string Name; 2990b57cec5SDimitry Andric StringRef SectionName; 3000b57cec5SDimitry Andric StringRef TypeName; 3010b57cec5SDimitry Andric BasicSymbolRef Sym; 3020b57cec5SDimitry Andric // The Sym field above points to the native symbol in the object file, 3030b57cec5SDimitry Andric // for Mach-O when we are creating symbols from the dyld info the above 3040b57cec5SDimitry Andric // pointer is null as there is no native symbol. In these cases the fields 3050b57cec5SDimitry Andric // below are filled in to represent what would have been a Mach-O nlist 3060b57cec5SDimitry Andric // native symbol. 3070b57cec5SDimitry Andric uint32_t SymFlags; 3080b57cec5SDimitry Andric SectionRef Section; 3090b57cec5SDimitry Andric uint8_t NType; 3100b57cec5SDimitry Andric uint8_t NSect; 3110b57cec5SDimitry Andric uint16_t NDesc; 312*e8d8bef9SDimitry Andric std::string IndirectName; 3130b57cec5SDimitry Andric }; 3140b57cec5SDimitry Andric } // anonymous namespace 3150b57cec5SDimitry Andric 3160b57cec5SDimitry Andric static bool compareSymbolAddress(const NMSymbol &A, const NMSymbol &B) { 3170b57cec5SDimitry Andric bool ADefined; 3185ffd83dbSDimitry Andric // Symbol flags have been checked in the caller. 319*e8d8bef9SDimitry Andric if (A.Sym.getRawDataRefImpl().p) { 3205ffd83dbSDimitry Andric uint32_t AFlags = cantFail(A.Sym.getFlags()); 3215ffd83dbSDimitry Andric ADefined = !(AFlags & SymbolRef::SF_Undefined); 322*e8d8bef9SDimitry Andric } else { 3230b57cec5SDimitry Andric ADefined = A.TypeChar != 'U'; 324*e8d8bef9SDimitry Andric } 3250b57cec5SDimitry Andric bool BDefined; 3265ffd83dbSDimitry Andric // Symbol flags have been checked in the caller. 327*e8d8bef9SDimitry Andric if (B.Sym.getRawDataRefImpl().p) { 3285ffd83dbSDimitry Andric uint32_t BFlags = cantFail(B.Sym.getFlags()); 3295ffd83dbSDimitry Andric BDefined = !(BFlags & SymbolRef::SF_Undefined); 330*e8d8bef9SDimitry Andric } else { 3310b57cec5SDimitry Andric BDefined = B.TypeChar != 'U'; 332*e8d8bef9SDimitry Andric } 3330b57cec5SDimitry Andric return std::make_tuple(ADefined, A.Address, A.Name, A.Size) < 3340b57cec5SDimitry Andric std::make_tuple(BDefined, B.Address, B.Name, B.Size); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric 3370b57cec5SDimitry Andric static bool compareSymbolSize(const NMSymbol &A, const NMSymbol &B) { 3380b57cec5SDimitry Andric return std::make_tuple(A.Size, A.Name, A.Address) < 3390b57cec5SDimitry Andric std::make_tuple(B.Size, B.Name, B.Address); 3400b57cec5SDimitry Andric } 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric static bool compareSymbolName(const NMSymbol &A, const NMSymbol &B) { 3430b57cec5SDimitry Andric return std::make_tuple(A.Name, A.Size, A.Address) < 3440b57cec5SDimitry Andric std::make_tuple(B.Name, B.Size, B.Address); 3450b57cec5SDimitry Andric } 3460b57cec5SDimitry Andric 3470b57cec5SDimitry Andric static char isSymbolList64Bit(SymbolicFile &Obj) { 3480b57cec5SDimitry Andric if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj)) 3490b57cec5SDimitry Andric return Triple(IRObj->getTargetTriple()).isArch64Bit(); 3500b57cec5SDimitry Andric if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj)) 3510b57cec5SDimitry Andric return false; 3520b57cec5SDimitry Andric if (isa<WasmObjectFile>(Obj)) 3530b57cec5SDimitry Andric return false; 3545ffd83dbSDimitry Andric if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj)) 3555ffd83dbSDimitry Andric return Tapi->is64Bit(); 3560b57cec5SDimitry Andric if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) 3570b57cec5SDimitry Andric return MachO->is64Bit(); 3580b57cec5SDimitry Andric return cast<ELFObjectFileBase>(Obj).getBytesInAddress() == 8; 3590b57cec5SDimitry Andric } 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric static StringRef CurrentFilename; 3620b57cec5SDimitry Andric static std::vector<NMSymbol> SymbolList; 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I); 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the 3670b57cec5SDimitry Andric // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For 3680b57cec5SDimitry Andric // the darwin format it produces the same output as darwin's nm(1) -m output 3690b57cec5SDimitry Andric // and when printing Mach-O symbols in hex it produces the same output as 3700b57cec5SDimitry Andric // darwin's nm(1) -x format. 3710b57cec5SDimitry Andric static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S, 3720b57cec5SDimitry Andric char *SymbolAddrStr, const char *printBlanks, 3730b57cec5SDimitry Andric const char *printDashes, 3740b57cec5SDimitry Andric const char *printFormat) { 3750b57cec5SDimitry Andric MachO::mach_header H; 3760b57cec5SDimitry Andric MachO::mach_header_64 H_64; 3770b57cec5SDimitry Andric uint32_t Filetype = MachO::MH_OBJECT; 3780b57cec5SDimitry Andric uint32_t Flags = 0; 3790b57cec5SDimitry Andric uint8_t NType = 0; 3800b57cec5SDimitry Andric uint8_t NSect = 0; 3810b57cec5SDimitry Andric uint16_t NDesc = 0; 3820b57cec5SDimitry Andric uint32_t NStrx = 0; 3830b57cec5SDimitry Andric uint64_t NValue = 0; 3840b57cec5SDimitry Andric MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); 3850b57cec5SDimitry Andric if (Obj.isIR()) { 3865ffd83dbSDimitry Andric uint32_t SymFlags = cantFail(S.Sym.getFlags()); 3870b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Global) 3880b57cec5SDimitry Andric NType |= MachO::N_EXT; 3890b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Hidden) 3900b57cec5SDimitry Andric NType |= MachO::N_PEXT; 3910b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Undefined) 3920b57cec5SDimitry Andric NType |= MachO::N_EXT | MachO::N_UNDF; 3930b57cec5SDimitry Andric else { 3940b57cec5SDimitry Andric // Here we have a symbol definition. So to fake out a section name we 3950b57cec5SDimitry Andric // use 1, 2 and 3 for section numbers. See below where they are used to 3960b57cec5SDimitry Andric // print out fake section names. 3970b57cec5SDimitry Andric NType |= MachO::N_SECT; 3980b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Const) 3990b57cec5SDimitry Andric NSect = 3; 4000b57cec5SDimitry Andric else if (SymFlags & SymbolRef::SF_Executable) 4010b57cec5SDimitry Andric NSect = 1; 4020b57cec5SDimitry Andric else 4030b57cec5SDimitry Andric NSect = 2; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Weak) 4060b57cec5SDimitry Andric NDesc |= MachO::N_WEAK_DEF; 4070b57cec5SDimitry Andric } else { 4080b57cec5SDimitry Andric DataRefImpl SymDRI = S.Sym.getRawDataRefImpl(); 4090b57cec5SDimitry Andric if (MachO->is64Bit()) { 4100b57cec5SDimitry Andric H_64 = MachO->MachOObjectFile::getHeader64(); 4110b57cec5SDimitry Andric Filetype = H_64.filetype; 4120b57cec5SDimitry Andric Flags = H_64.flags; 4130b57cec5SDimitry Andric if (SymDRI.p){ 4140b57cec5SDimitry Andric MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI); 4150b57cec5SDimitry Andric NType = STE_64.n_type; 4160b57cec5SDimitry Andric NSect = STE_64.n_sect; 4170b57cec5SDimitry Andric NDesc = STE_64.n_desc; 4180b57cec5SDimitry Andric NStrx = STE_64.n_strx; 4190b57cec5SDimitry Andric NValue = STE_64.n_value; 4200b57cec5SDimitry Andric } else { 4210b57cec5SDimitry Andric NType = S.NType; 4220b57cec5SDimitry Andric NSect = S.NSect; 4230b57cec5SDimitry Andric NDesc = S.NDesc; 4240b57cec5SDimitry Andric NStrx = 0; 4250b57cec5SDimitry Andric NValue = S.Address; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric } else { 4280b57cec5SDimitry Andric H = MachO->MachOObjectFile::getHeader(); 4290b57cec5SDimitry Andric Filetype = H.filetype; 4300b57cec5SDimitry Andric Flags = H.flags; 4310b57cec5SDimitry Andric if (SymDRI.p){ 4320b57cec5SDimitry Andric MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI); 4330b57cec5SDimitry Andric NType = STE.n_type; 4340b57cec5SDimitry Andric NSect = STE.n_sect; 4350b57cec5SDimitry Andric NDesc = STE.n_desc; 4360b57cec5SDimitry Andric NStrx = STE.n_strx; 4370b57cec5SDimitry Andric NValue = STE.n_value; 4380b57cec5SDimitry Andric } else { 4390b57cec5SDimitry Andric NType = S.NType; 4400b57cec5SDimitry Andric NSect = S.NSect; 4410b57cec5SDimitry Andric NDesc = S.NDesc; 4420b57cec5SDimitry Andric NStrx = 0; 4430b57cec5SDimitry Andric NValue = S.Address; 4440b57cec5SDimitry Andric } 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric // If we are printing Mach-O symbols in hex do that and return. 4490b57cec5SDimitry Andric if (FormatMachOasHex) { 4500b57cec5SDimitry Andric outs() << format(printFormat, NValue) << ' ' 4510b57cec5SDimitry Andric << format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' ' 4520b57cec5SDimitry Andric << S.Name; 4530b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_INDR) { 4540b57cec5SDimitry Andric outs() << " (indirect for "; 4550b57cec5SDimitry Andric outs() << format(printFormat, NValue) << ' '; 4560b57cec5SDimitry Andric StringRef IndirectName; 4570b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 4580b57cec5SDimitry Andric if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName)) 4590b57cec5SDimitry Andric outs() << "?)"; 4600b57cec5SDimitry Andric else 4610b57cec5SDimitry Andric outs() << IndirectName << ")"; 4620b57cec5SDimitry Andric } else 4630b57cec5SDimitry Andric outs() << S.IndirectName << ")"; 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric outs() << "\n"; 4660b57cec5SDimitry Andric return; 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric if (PrintAddress) { 4700b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_INDR) 4710b57cec5SDimitry Andric strcpy(SymbolAddrStr, printBlanks); 4720b57cec5SDimitry Andric if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE) 4730b57cec5SDimitry Andric strcpy(SymbolAddrStr, printDashes); 4740b57cec5SDimitry Andric outs() << SymbolAddrStr << ' '; 4750b57cec5SDimitry Andric } 4760b57cec5SDimitry Andric 4770b57cec5SDimitry Andric switch (NType & MachO::N_TYPE) { 4780b57cec5SDimitry Andric case MachO::N_UNDF: 4790b57cec5SDimitry Andric if (NValue != 0) { 4800b57cec5SDimitry Andric outs() << "(common) "; 4810b57cec5SDimitry Andric if (MachO::GET_COMM_ALIGN(NDesc) != 0) 4820b57cec5SDimitry Andric outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; 4830b57cec5SDimitry Andric } else { 4840b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_PBUD) 4850b57cec5SDimitry Andric outs() << "(prebound "; 4860b57cec5SDimitry Andric else 4870b57cec5SDimitry Andric outs() << "("; 4880b57cec5SDimitry Andric if ((NDesc & MachO::REFERENCE_TYPE) == 4890b57cec5SDimitry Andric MachO::REFERENCE_FLAG_UNDEFINED_LAZY) 4900b57cec5SDimitry Andric outs() << "undefined [lazy bound]) "; 4910b57cec5SDimitry Andric else if ((NDesc & MachO::REFERENCE_TYPE) == 4920b57cec5SDimitry Andric MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY) 4930b57cec5SDimitry Andric outs() << "undefined [private lazy bound]) "; 4940b57cec5SDimitry Andric else if ((NDesc & MachO::REFERENCE_TYPE) == 4950b57cec5SDimitry Andric MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY) 4960b57cec5SDimitry Andric outs() << "undefined [private]) "; 4970b57cec5SDimitry Andric else 4980b57cec5SDimitry Andric outs() << "undefined) "; 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric break; 5010b57cec5SDimitry Andric case MachO::N_ABS: 5020b57cec5SDimitry Andric outs() << "(absolute) "; 5030b57cec5SDimitry Andric break; 5040b57cec5SDimitry Andric case MachO::N_INDR: 5050b57cec5SDimitry Andric outs() << "(indirect) "; 5060b57cec5SDimitry Andric break; 5070b57cec5SDimitry Andric case MachO::N_SECT: { 5080b57cec5SDimitry Andric if (Obj.isIR()) { 5090b57cec5SDimitry Andric // For llvm bitcode files print out a fake section name using the values 5100b57cec5SDimitry Andric // use 1, 2 and 3 for section numbers as set above. 5110b57cec5SDimitry Andric if (NSect == 1) 5120b57cec5SDimitry Andric outs() << "(LTO,CODE) "; 5130b57cec5SDimitry Andric else if (NSect == 2) 5140b57cec5SDimitry Andric outs() << "(LTO,DATA) "; 5150b57cec5SDimitry Andric else if (NSect == 3) 5160b57cec5SDimitry Andric outs() << "(LTO,RODATA) "; 5170b57cec5SDimitry Andric else 5180b57cec5SDimitry Andric outs() << "(?,?) "; 5190b57cec5SDimitry Andric break; 5200b57cec5SDimitry Andric } 5210b57cec5SDimitry Andric section_iterator Sec = SectionRef(); 5220b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 5230b57cec5SDimitry Andric Expected<section_iterator> SecOrErr = 5240b57cec5SDimitry Andric MachO->getSymbolSection(S.Sym.getRawDataRefImpl()); 5250b57cec5SDimitry Andric if (!SecOrErr) { 5260b57cec5SDimitry Andric consumeError(SecOrErr.takeError()); 5270b57cec5SDimitry Andric outs() << "(?,?) "; 5280b57cec5SDimitry Andric break; 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric Sec = *SecOrErr; 5310b57cec5SDimitry Andric if (Sec == MachO->section_end()) { 5320b57cec5SDimitry Andric outs() << "(?,?) "; 5330b57cec5SDimitry Andric break; 5340b57cec5SDimitry Andric } 5350b57cec5SDimitry Andric } else { 5360b57cec5SDimitry Andric Sec = S.Section; 5370b57cec5SDimitry Andric } 5380b57cec5SDimitry Andric DataRefImpl Ref = Sec->getRawDataRefImpl(); 5390b57cec5SDimitry Andric StringRef SectionName; 5400b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref)) 5410b57cec5SDimitry Andric SectionName = *NameOrErr; 5420b57cec5SDimitry Andric StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref); 5430b57cec5SDimitry Andric outs() << "(" << SegmentName << "," << SectionName << ") "; 5440b57cec5SDimitry Andric break; 5450b57cec5SDimitry Andric } 5460b57cec5SDimitry Andric default: 5470b57cec5SDimitry Andric outs() << "(?) "; 5480b57cec5SDimitry Andric break; 5490b57cec5SDimitry Andric } 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric if (NType & MachO::N_EXT) { 5520b57cec5SDimitry Andric if (NDesc & MachO::REFERENCED_DYNAMICALLY) 5530b57cec5SDimitry Andric outs() << "[referenced dynamically] "; 5540b57cec5SDimitry Andric if (NType & MachO::N_PEXT) { 5550b57cec5SDimitry Andric if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) 5560b57cec5SDimitry Andric outs() << "weak private external "; 5570b57cec5SDimitry Andric else 5580b57cec5SDimitry Andric outs() << "private external "; 5590b57cec5SDimitry Andric } else { 5600b57cec5SDimitry Andric if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF || 5610b57cec5SDimitry Andric (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) { 5620b57cec5SDimitry Andric if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) == 5630b57cec5SDimitry Andric (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 5640b57cec5SDimitry Andric outs() << "weak external automatically hidden "; 5650b57cec5SDimitry Andric else 5660b57cec5SDimitry Andric outs() << "weak external "; 5670b57cec5SDimitry Andric } else 5680b57cec5SDimitry Andric outs() << "external "; 5690b57cec5SDimitry Andric } 5700b57cec5SDimitry Andric } else { 5710b57cec5SDimitry Andric if (NType & MachO::N_PEXT) 5720b57cec5SDimitry Andric outs() << "non-external (was a private external) "; 5730b57cec5SDimitry Andric else 5740b57cec5SDimitry Andric outs() << "non-external "; 5750b57cec5SDimitry Andric } 5760b57cec5SDimitry Andric 5770b57cec5SDimitry Andric if (Filetype == MachO::MH_OBJECT) { 5780b57cec5SDimitry Andric if (NDesc & MachO::N_NO_DEAD_STRIP) 5790b57cec5SDimitry Andric outs() << "[no dead strip] "; 5800b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) != MachO::N_UNDF && 5810b57cec5SDimitry Andric NDesc & MachO::N_SYMBOL_RESOLVER) 5820b57cec5SDimitry Andric outs() << "[symbol resolver] "; 5830b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY) 5840b57cec5SDimitry Andric outs() << "[alt entry] "; 5850b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC) 5860b57cec5SDimitry Andric outs() << "[cold func] "; 5870b57cec5SDimitry Andric } 5880b57cec5SDimitry Andric 5890b57cec5SDimitry Andric if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF) 5900b57cec5SDimitry Andric outs() << "[Thumb] "; 5910b57cec5SDimitry Andric 5920b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_INDR) { 5930b57cec5SDimitry Andric outs() << S.Name << " (for "; 5940b57cec5SDimitry Andric StringRef IndirectName; 5950b57cec5SDimitry Andric if (MachO) { 5960b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 5970b57cec5SDimitry Andric if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName)) 5980b57cec5SDimitry Andric outs() << "?)"; 5990b57cec5SDimitry Andric else 6000b57cec5SDimitry Andric outs() << IndirectName << ")"; 6010b57cec5SDimitry Andric } else 6020b57cec5SDimitry Andric outs() << S.IndirectName << ")"; 6030b57cec5SDimitry Andric } else 6040b57cec5SDimitry Andric outs() << "?)"; 6050b57cec5SDimitry Andric } else 6060b57cec5SDimitry Andric outs() << S.Name; 6070b57cec5SDimitry Andric 6080b57cec5SDimitry Andric if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && 6090b57cec5SDimitry Andric (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || 6100b57cec5SDimitry Andric (NType & MachO::N_TYPE) == MachO::N_PBUD)) { 6110b57cec5SDimitry Andric uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); 6120b57cec5SDimitry Andric if (LibraryOrdinal != 0) { 6130b57cec5SDimitry Andric if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL) 6140b57cec5SDimitry Andric outs() << " (from executable)"; 6150b57cec5SDimitry Andric else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL) 6160b57cec5SDimitry Andric outs() << " (dynamically looked up)"; 6170b57cec5SDimitry Andric else { 6180b57cec5SDimitry Andric StringRef LibraryName; 6190b57cec5SDimitry Andric if (!MachO || 6200b57cec5SDimitry Andric MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) 6210b57cec5SDimitry Andric outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; 6220b57cec5SDimitry Andric else 6230b57cec5SDimitry Andric outs() << " (from " << LibraryName << ")"; 6240b57cec5SDimitry Andric } 6250b57cec5SDimitry Andric } 6260b57cec5SDimitry Andric } 6270b57cec5SDimitry Andric 6280b57cec5SDimitry Andric outs() << "\n"; 6290b57cec5SDimitry Andric } 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric // Table that maps Darwin's Mach-O stab constants to strings to allow printing. 6320b57cec5SDimitry Andric struct DarwinStabName { 6330b57cec5SDimitry Andric uint8_t NType; 6340b57cec5SDimitry Andric const char *Name; 6350b57cec5SDimitry Andric }; 6360b57cec5SDimitry Andric static const struct DarwinStabName DarwinStabNames[] = { 6370b57cec5SDimitry Andric {MachO::N_GSYM, "GSYM"}, 6380b57cec5SDimitry Andric {MachO::N_FNAME, "FNAME"}, 6390b57cec5SDimitry Andric {MachO::N_FUN, "FUN"}, 6400b57cec5SDimitry Andric {MachO::N_STSYM, "STSYM"}, 6410b57cec5SDimitry Andric {MachO::N_LCSYM, "LCSYM"}, 6420b57cec5SDimitry Andric {MachO::N_BNSYM, "BNSYM"}, 6430b57cec5SDimitry Andric {MachO::N_PC, "PC"}, 6440b57cec5SDimitry Andric {MachO::N_AST, "AST"}, 6450b57cec5SDimitry Andric {MachO::N_OPT, "OPT"}, 6460b57cec5SDimitry Andric {MachO::N_RSYM, "RSYM"}, 6470b57cec5SDimitry Andric {MachO::N_SLINE, "SLINE"}, 6480b57cec5SDimitry Andric {MachO::N_ENSYM, "ENSYM"}, 6490b57cec5SDimitry Andric {MachO::N_SSYM, "SSYM"}, 6500b57cec5SDimitry Andric {MachO::N_SO, "SO"}, 6510b57cec5SDimitry Andric {MachO::N_OSO, "OSO"}, 6520b57cec5SDimitry Andric {MachO::N_LSYM, "LSYM"}, 6530b57cec5SDimitry Andric {MachO::N_BINCL, "BINCL"}, 6540b57cec5SDimitry Andric {MachO::N_SOL, "SOL"}, 6550b57cec5SDimitry Andric {MachO::N_PARAMS, "PARAM"}, 6560b57cec5SDimitry Andric {MachO::N_VERSION, "VERS"}, 6570b57cec5SDimitry Andric {MachO::N_OLEVEL, "OLEV"}, 6580b57cec5SDimitry Andric {MachO::N_PSYM, "PSYM"}, 6590b57cec5SDimitry Andric {MachO::N_EINCL, "EINCL"}, 6600b57cec5SDimitry Andric {MachO::N_ENTRY, "ENTRY"}, 6610b57cec5SDimitry Andric {MachO::N_LBRAC, "LBRAC"}, 6620b57cec5SDimitry Andric {MachO::N_EXCL, "EXCL"}, 6630b57cec5SDimitry Andric {MachO::N_RBRAC, "RBRAC"}, 6640b57cec5SDimitry Andric {MachO::N_BCOMM, "BCOMM"}, 6650b57cec5SDimitry Andric {MachO::N_ECOMM, "ECOMM"}, 6660b57cec5SDimitry Andric {MachO::N_ECOML, "ECOML"}, 6670b57cec5SDimitry Andric {MachO::N_LENG, "LENG"}, 6680b57cec5SDimitry Andric }; 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric static const char *getDarwinStabString(uint8_t NType) { 6710b57cec5SDimitry Andric for (auto I : makeArrayRef(DarwinStabNames)) 6720b57cec5SDimitry Andric if (I.NType == NType) 6730b57cec5SDimitry Andric return I.Name; 6740b57cec5SDimitry Andric return nullptr; 6750b57cec5SDimitry Andric } 6760b57cec5SDimitry Andric 6770b57cec5SDimitry Andric // darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of 6780b57cec5SDimitry Andric // a stab n_type value in a Mach-O file. 6790b57cec5SDimitry Andric static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) { 6800b57cec5SDimitry Andric MachO::nlist_64 STE_64; 6810b57cec5SDimitry Andric MachO::nlist STE; 6820b57cec5SDimitry Andric uint8_t NType; 6830b57cec5SDimitry Andric uint8_t NSect; 6840b57cec5SDimitry Andric uint16_t NDesc; 6850b57cec5SDimitry Andric DataRefImpl SymDRI = S.Sym.getRawDataRefImpl(); 6860b57cec5SDimitry Andric if (MachO->is64Bit()) { 6870b57cec5SDimitry Andric STE_64 = MachO->getSymbol64TableEntry(SymDRI); 6880b57cec5SDimitry Andric NType = STE_64.n_type; 6890b57cec5SDimitry Andric NSect = STE_64.n_sect; 6900b57cec5SDimitry Andric NDesc = STE_64.n_desc; 6910b57cec5SDimitry Andric } else { 6920b57cec5SDimitry Andric STE = MachO->getSymbolTableEntry(SymDRI); 6930b57cec5SDimitry Andric NType = STE.n_type; 6940b57cec5SDimitry Andric NSect = STE.n_sect; 6950b57cec5SDimitry Andric NDesc = STE.n_desc; 6960b57cec5SDimitry Andric } 6970b57cec5SDimitry Andric 6980b57cec5SDimitry Andric outs() << format(" %02x %04x ", NSect, NDesc); 6990b57cec5SDimitry Andric if (const char *stabString = getDarwinStabString(NType)) 7000b57cec5SDimitry Andric outs() << format("%5.5s", stabString); 7010b57cec5SDimitry Andric else 7020b57cec5SDimitry Andric outs() << format(" %02x", NType); 7030b57cec5SDimitry Andric } 7040b57cec5SDimitry Andric 7050b57cec5SDimitry Andric static Optional<std::string> demangle(StringRef Name, bool StripUnderscore) { 7060b57cec5SDimitry Andric if (StripUnderscore && !Name.empty() && Name[0] == '_') 7070b57cec5SDimitry Andric Name = Name.substr(1); 7080b57cec5SDimitry Andric 7090b57cec5SDimitry Andric if (!Name.startswith("_Z")) 7100b57cec5SDimitry Andric return None; 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric int Status; 7130b57cec5SDimitry Andric char *Undecorated = 7140b57cec5SDimitry Andric itaniumDemangle(Name.str().c_str(), nullptr, nullptr, &Status); 7150b57cec5SDimitry Andric if (Status != 0) 7160b57cec5SDimitry Andric return None; 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric std::string S(Undecorated); 7190b57cec5SDimitry Andric free(Undecorated); 7200b57cec5SDimitry Andric return S; 7210b57cec5SDimitry Andric } 7220b57cec5SDimitry Andric 7230b57cec5SDimitry Andric static bool symbolIsDefined(const NMSymbol &Sym) { 7240b57cec5SDimitry Andric return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v'; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7275ffd83dbSDimitry Andric static void writeFileName(raw_ostream &S, StringRef ArchiveName, 7285ffd83dbSDimitry Andric StringRef ArchitectureName) { 7295ffd83dbSDimitry Andric if (!ArchitectureName.empty()) 7305ffd83dbSDimitry Andric S << "(for architecture " << ArchitectureName << "):"; 7315ffd83dbSDimitry Andric if (OutputFormat == posix && !ArchiveName.empty()) 7325ffd83dbSDimitry Andric S << ArchiveName << "[" << CurrentFilename << "]: "; 7335ffd83dbSDimitry Andric else { 7345ffd83dbSDimitry Andric if (!ArchiveName.empty()) 7355ffd83dbSDimitry Andric S << ArchiveName << ":"; 7365ffd83dbSDimitry Andric S << CurrentFilename << ": "; 7375ffd83dbSDimitry Andric } 7385ffd83dbSDimitry Andric } 7395ffd83dbSDimitry Andric 7405ffd83dbSDimitry Andric static bool isSpecialSym(SymbolicFile &Obj, StringRef Name) { 7415ffd83dbSDimitry Andric auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj); 7425ffd83dbSDimitry Andric if (!ELFObj) 7435ffd83dbSDimitry Andric return false; 7445ffd83dbSDimitry Andric uint16_t EMachine = ELFObj->getEMachine(); 7455ffd83dbSDimitry Andric if (EMachine != ELF::EM_ARM && EMachine != ELF::EM_AARCH64) 7465ffd83dbSDimitry Andric return false; 7475ffd83dbSDimitry Andric return !Name.empty() && Name[0] == '$'; 7485ffd83dbSDimitry Andric } 7495ffd83dbSDimitry Andric 7500b57cec5SDimitry Andric static void sortAndPrintSymbolList(SymbolicFile &Obj, bool printName, 7515ffd83dbSDimitry Andric StringRef ArchiveName, 7525ffd83dbSDimitry Andric StringRef ArchitectureName) { 7530b57cec5SDimitry Andric if (!NoSort) { 7548bcb0991SDimitry Andric using Comparator = bool (*)(const NMSymbol &, const NMSymbol &); 7558bcb0991SDimitry Andric Comparator Cmp; 7560b57cec5SDimitry Andric if (NumericSort) 7578bcb0991SDimitry Andric Cmp = &compareSymbolAddress; 7580b57cec5SDimitry Andric else if (SizeSort) 7598bcb0991SDimitry Andric Cmp = &compareSymbolSize; 7600b57cec5SDimitry Andric else 7618bcb0991SDimitry Andric Cmp = &compareSymbolName; 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric if (ReverseSort) 7648bcb0991SDimitry Andric llvm::sort(SymbolList, [=](const NMSymbol &A, const NMSymbol &B) -> bool { 7658bcb0991SDimitry Andric return Cmp(B, A); 7668bcb0991SDimitry Andric }); 7678bcb0991SDimitry Andric else 7680b57cec5SDimitry Andric llvm::sort(SymbolList, Cmp); 7690b57cec5SDimitry Andric } 7700b57cec5SDimitry Andric 7710b57cec5SDimitry Andric if (!PrintFileName) { 7720b57cec5SDimitry Andric if (OutputFormat == posix && MultipleFiles && printName) { 7730b57cec5SDimitry Andric outs() << '\n' << CurrentFilename << ":\n"; 7740b57cec5SDimitry Andric } else if (OutputFormat == bsd && MultipleFiles && printName) { 7750b57cec5SDimitry Andric outs() << "\n" << CurrentFilename << ":\n"; 7760b57cec5SDimitry Andric } else if (OutputFormat == sysv) { 7770b57cec5SDimitry Andric outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"; 7780b57cec5SDimitry Andric if (isSymbolList64Bit(Obj)) 7790b57cec5SDimitry Andric outs() << "Name Value Class Type" 7800b57cec5SDimitry Andric << " Size Line Section\n"; 7810b57cec5SDimitry Andric else 7820b57cec5SDimitry Andric outs() << "Name Value Class Type" 7830b57cec5SDimitry Andric << " Size Line Section\n"; 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric } 7860b57cec5SDimitry Andric 7870b57cec5SDimitry Andric const char *printBlanks, *printDashes, *printFormat; 7880b57cec5SDimitry Andric if (isSymbolList64Bit(Obj)) { 7890b57cec5SDimitry Andric printBlanks = " "; 7900b57cec5SDimitry Andric printDashes = "----------------"; 7910b57cec5SDimitry Andric switch (AddressRadix) { 7920b57cec5SDimitry Andric case Radix::o: 7930b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIo64 : "%016" PRIo64; 7940b57cec5SDimitry Andric break; 7950b57cec5SDimitry Andric case Radix::x: 7960b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIx64 : "%016" PRIx64; 7970b57cec5SDimitry Andric break; 7980b57cec5SDimitry Andric default: 7990b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRId64 : "%016" PRId64; 8000b57cec5SDimitry Andric } 8010b57cec5SDimitry Andric } else { 8020b57cec5SDimitry Andric printBlanks = " "; 8030b57cec5SDimitry Andric printDashes = "--------"; 8040b57cec5SDimitry Andric switch (AddressRadix) { 8050b57cec5SDimitry Andric case Radix::o: 8060b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIo64 : "%08" PRIo64; 8070b57cec5SDimitry Andric break; 8080b57cec5SDimitry Andric case Radix::x: 8090b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIx64 : "%08" PRIx64; 8100b57cec5SDimitry Andric break; 8110b57cec5SDimitry Andric default: 8120b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRId64 : "%08" PRId64; 8130b57cec5SDimitry Andric } 8140b57cec5SDimitry Andric } 8150b57cec5SDimitry Andric 8160b57cec5SDimitry Andric for (const NMSymbol &S : SymbolList) { 8170b57cec5SDimitry Andric uint32_t SymFlags; 818*e8d8bef9SDimitry Andric std::string Name = S.Name; 8190b57cec5SDimitry Andric MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); 8200b57cec5SDimitry Andric if (Demangle) { 8210b57cec5SDimitry Andric if (Optional<std::string> Opt = demangle(S.Name, MachO)) 8220b57cec5SDimitry Andric Name = *Opt; 8230b57cec5SDimitry Andric } 8245ffd83dbSDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 8255ffd83dbSDimitry Andric Expected<uint32_t> SymFlagsOrErr = S.Sym.getFlags(); 8265ffd83dbSDimitry Andric if (!SymFlagsOrErr) { 8275ffd83dbSDimitry Andric // TODO: Test this error. 8285ffd83dbSDimitry Andric error(SymFlagsOrErr.takeError(), Obj.getFileName()); 8295ffd83dbSDimitry Andric return; 8305ffd83dbSDimitry Andric } 8315ffd83dbSDimitry Andric SymFlags = *SymFlagsOrErr; 8325ffd83dbSDimitry Andric } else 8330b57cec5SDimitry Andric SymFlags = S.SymFlags; 8340b57cec5SDimitry Andric 8350b57cec5SDimitry Andric bool Undefined = SymFlags & SymbolRef::SF_Undefined; 8360b57cec5SDimitry Andric bool Global = SymFlags & SymbolRef::SF_Global; 8370b57cec5SDimitry Andric bool Weak = SymFlags & SymbolRef::SF_Weak; 8380b57cec5SDimitry Andric if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) || 8395ffd83dbSDimitry Andric (!Global && ExternalOnly) || (Weak && NoWeakSymbols) || 8405ffd83dbSDimitry Andric (!SpecialSyms && isSpecialSym(Obj, Name))) 8410b57cec5SDimitry Andric continue; 8420b57cec5SDimitry Andric if (PrintFileName) 8435ffd83dbSDimitry Andric writeFileName(outs(), ArchiveName, ArchitectureName); 8440b57cec5SDimitry Andric if ((JustSymbolName || 8450b57cec5SDimitry Andric (UndefinedOnly && MachO && OutputFormat != darwin)) && 8460b57cec5SDimitry Andric OutputFormat != posix) { 8470b57cec5SDimitry Andric outs() << Name << "\n"; 8480b57cec5SDimitry Andric continue; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric char SymbolAddrStr[23], SymbolSizeStr[23]; 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric // If the format is SysV or the symbol isn't defined, then print spaces. 8540b57cec5SDimitry Andric if (OutputFormat == sysv || !symbolIsDefined(S)) { 8550b57cec5SDimitry Andric if (OutputFormat == posix) { 8560b57cec5SDimitry Andric format(printFormat, S.Address) 8570b57cec5SDimitry Andric .print(SymbolAddrStr, sizeof(SymbolAddrStr)); 8580b57cec5SDimitry Andric format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); 8590b57cec5SDimitry Andric } else { 8600b57cec5SDimitry Andric strcpy(SymbolAddrStr, printBlanks); 8610b57cec5SDimitry Andric strcpy(SymbolSizeStr, printBlanks); 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric } 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric if (symbolIsDefined(S)) { 8660b57cec5SDimitry Andric // Otherwise, print the symbol address and size. 8670b57cec5SDimitry Andric if (Obj.isIR()) 8680b57cec5SDimitry Andric strcpy(SymbolAddrStr, printDashes); 8690b57cec5SDimitry Andric else if (MachO && S.TypeChar == 'I') 8700b57cec5SDimitry Andric strcpy(SymbolAddrStr, printBlanks); 8710b57cec5SDimitry Andric else 8720b57cec5SDimitry Andric format(printFormat, S.Address) 8730b57cec5SDimitry Andric .print(SymbolAddrStr, sizeof(SymbolAddrStr)); 8740b57cec5SDimitry Andric format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric // If OutputFormat is darwin or we are printing Mach-O symbols in hex and 8780b57cec5SDimitry Andric // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's 8790b57cec5SDimitry Andric // nm(1) -m output or hex, else if OutputFormat is darwin or we are 8800b57cec5SDimitry Andric // printing Mach-O symbols in hex and not a Mach-O object fall back to 8810b57cec5SDimitry Andric // OutputFormat bsd (see below). 8820b57cec5SDimitry Andric if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) { 8830b57cec5SDimitry Andric darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes, 8840b57cec5SDimitry Andric printFormat); 8850b57cec5SDimitry Andric } else if (OutputFormat == posix) { 8860b57cec5SDimitry Andric outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " " 8870b57cec5SDimitry Andric << (MachO ? "0" : SymbolSizeStr) << "\n"; 8880b57cec5SDimitry Andric } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) { 8890b57cec5SDimitry Andric if (PrintAddress) 8900b57cec5SDimitry Andric outs() << SymbolAddrStr << ' '; 8910b57cec5SDimitry Andric if (PrintSize) 8920b57cec5SDimitry Andric outs() << SymbolSizeStr << ' '; 8930b57cec5SDimitry Andric outs() << S.TypeChar; 8940b57cec5SDimitry Andric if (S.TypeChar == '-' && MachO) 8950b57cec5SDimitry Andric darwinPrintStab(MachO, S); 8960b57cec5SDimitry Andric outs() << " " << Name; 8970b57cec5SDimitry Andric if (S.TypeChar == 'I' && MachO) { 8980b57cec5SDimitry Andric outs() << " (indirect for "; 8990b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 9000b57cec5SDimitry Andric StringRef IndirectName; 9010b57cec5SDimitry Andric if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName)) 9020b57cec5SDimitry Andric outs() << "?)"; 9030b57cec5SDimitry Andric else 9040b57cec5SDimitry Andric outs() << IndirectName << ")"; 9050b57cec5SDimitry Andric } else 9060b57cec5SDimitry Andric outs() << S.IndirectName << ")"; 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric outs() << "\n"; 9090b57cec5SDimitry Andric } else if (OutputFormat == sysv) { 9100b57cec5SDimitry Andric outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| " 9110b57cec5SDimitry Andric << S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|" 9120b57cec5SDimitry Andric << SymbolSizeStr << "| |" << S.SectionName << "\n"; 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric } 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric SymbolList.clear(); 9170b57cec5SDimitry Andric } 9180b57cec5SDimitry Andric 9190b57cec5SDimitry Andric static char getSymbolNMTypeChar(ELFObjectFileBase &Obj, 9200b57cec5SDimitry Andric basic_symbol_iterator I) { 9210b57cec5SDimitry Andric // OK, this is ELF 9220b57cec5SDimitry Andric elf_symbol_iterator SymI(I); 9230b57cec5SDimitry Andric 9240b57cec5SDimitry Andric Expected<elf_section_iterator> SecIOrErr = SymI->getSection(); 9250b57cec5SDimitry Andric if (!SecIOrErr) { 9260b57cec5SDimitry Andric consumeError(SecIOrErr.takeError()); 9270b57cec5SDimitry Andric return '?'; 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric uint8_t Binding = SymI->getBinding(); 9310b57cec5SDimitry Andric if (Binding == ELF::STB_GNU_UNIQUE) 9320b57cec5SDimitry Andric return 'u'; 9330b57cec5SDimitry Andric 9340b57cec5SDimitry Andric assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function"); 9350b57cec5SDimitry Andric if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL) 9360b57cec5SDimitry Andric return '?'; 9370b57cec5SDimitry Andric 9380b57cec5SDimitry Andric elf_section_iterator SecI = *SecIOrErr; 9390b57cec5SDimitry Andric if (SecI != Obj.section_end()) { 9400b57cec5SDimitry Andric uint32_t Type = SecI->getType(); 9410b57cec5SDimitry Andric uint64_t Flags = SecI->getFlags(); 9420b57cec5SDimitry Andric if (Flags & ELF::SHF_EXECINSTR) 9430b57cec5SDimitry Andric return 't'; 9440b57cec5SDimitry Andric if (Type == ELF::SHT_NOBITS) 9450b57cec5SDimitry Andric return 'b'; 9460b57cec5SDimitry Andric if (Flags & ELF::SHF_ALLOC) 9470b57cec5SDimitry Andric return Flags & ELF::SHF_WRITE ? 'd' : 'r'; 9480b57cec5SDimitry Andric 9498bcb0991SDimitry Andric auto NameOrErr = SecI->getName(); 9508bcb0991SDimitry Andric if (!NameOrErr) { 9518bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 9520b57cec5SDimitry Andric return '?'; 9538bcb0991SDimitry Andric } 9548bcb0991SDimitry Andric if ((*NameOrErr).startswith(".debug")) 9550b57cec5SDimitry Andric return 'N'; 9560b57cec5SDimitry Andric if (!(Flags & ELF::SHF_WRITE)) 9570b57cec5SDimitry Andric return 'n'; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric return '?'; 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { 9640b57cec5SDimitry Andric COFFSymbolRef Symb = Obj.getCOFFSymbol(*I); 9650b57cec5SDimitry Andric // OK, this is COFF. 9660b57cec5SDimitry Andric symbol_iterator SymI(I); 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric Expected<StringRef> Name = SymI->getName(); 9690b57cec5SDimitry Andric if (!Name) { 9700b57cec5SDimitry Andric consumeError(Name.takeError()); 9710b57cec5SDimitry Andric return '?'; 9720b57cec5SDimitry Andric } 9730b57cec5SDimitry Andric 9740b57cec5SDimitry Andric char Ret = StringSwitch<char>(*Name) 9750b57cec5SDimitry Andric .StartsWith(".debug", 'N') 9760b57cec5SDimitry Andric .StartsWith(".sxdata", 'N') 9770b57cec5SDimitry Andric .Default('?'); 9780b57cec5SDimitry Andric 9790b57cec5SDimitry Andric if (Ret != '?') 9800b57cec5SDimitry Andric return Ret; 9810b57cec5SDimitry Andric 9820b57cec5SDimitry Andric uint32_t Characteristics = 0; 9830b57cec5SDimitry Andric if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 9840b57cec5SDimitry Andric Expected<section_iterator> SecIOrErr = SymI->getSection(); 9850b57cec5SDimitry Andric if (!SecIOrErr) { 9860b57cec5SDimitry Andric consumeError(SecIOrErr.takeError()); 9870b57cec5SDimitry Andric return '?'; 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric section_iterator SecI = *SecIOrErr; 9900b57cec5SDimitry Andric const coff_section *Section = Obj.getCOFFSection(*SecI); 9910b57cec5SDimitry Andric Characteristics = Section->Characteristics; 9920b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section)) 9930b57cec5SDimitry Andric if (NameOrErr->startswith(".idata")) 9940b57cec5SDimitry Andric return 'i'; 9950b57cec5SDimitry Andric } 9960b57cec5SDimitry Andric 9970b57cec5SDimitry Andric switch (Symb.getSectionNumber()) { 9980b57cec5SDimitry Andric case COFF::IMAGE_SYM_DEBUG: 9990b57cec5SDimitry Andric return 'n'; 10000b57cec5SDimitry Andric default: 10010b57cec5SDimitry Andric // Check section type. 10020b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 10030b57cec5SDimitry Andric return 't'; 10040b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 10050b57cec5SDimitry Andric return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r'; 10060b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 10070b57cec5SDimitry Andric return 'b'; 10080b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 10090b57cec5SDimitry Andric return 'i'; 10100b57cec5SDimitry Andric // Check for section symbol. 10110b57cec5SDimitry Andric if (Symb.isSectionDefinition()) 10120b57cec5SDimitry Andric return 's'; 10130b57cec5SDimitry Andric } 10140b57cec5SDimitry Andric 10150b57cec5SDimitry Andric return '?'; 10160b57cec5SDimitry Andric } 10170b57cec5SDimitry Andric 10180b57cec5SDimitry Andric static char getSymbolNMTypeChar(COFFImportFile &Obj) { 10190b57cec5SDimitry Andric switch (Obj.getCOFFImportHeader()->getType()) { 10200b57cec5SDimitry Andric case COFF::IMPORT_CODE: 10210b57cec5SDimitry Andric return 't'; 10220b57cec5SDimitry Andric case COFF::IMPORT_DATA: 10230b57cec5SDimitry Andric return 'd'; 10240b57cec5SDimitry Andric case COFF::IMPORT_CONST: 10250b57cec5SDimitry Andric return 'r'; 10260b57cec5SDimitry Andric } 10270b57cec5SDimitry Andric return '?'; 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { 10310b57cec5SDimitry Andric DataRefImpl Symb = I->getRawDataRefImpl(); 10320b57cec5SDimitry Andric uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type 10330b57cec5SDimitry Andric : Obj.getSymbolTableEntry(Symb).n_type; 10340b57cec5SDimitry Andric 10350b57cec5SDimitry Andric if (NType & MachO::N_STAB) 10360b57cec5SDimitry Andric return '-'; 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric switch (NType & MachO::N_TYPE) { 10390b57cec5SDimitry Andric case MachO::N_ABS: 10400b57cec5SDimitry Andric return 's'; 10410b57cec5SDimitry Andric case MachO::N_INDR: 10420b57cec5SDimitry Andric return 'i'; 10430b57cec5SDimitry Andric case MachO::N_SECT: { 10440b57cec5SDimitry Andric Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb); 10450b57cec5SDimitry Andric if (!SecOrErr) { 10460b57cec5SDimitry Andric consumeError(SecOrErr.takeError()); 10470b57cec5SDimitry Andric return 's'; 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric section_iterator Sec = *SecOrErr; 10500b57cec5SDimitry Andric if (Sec == Obj.section_end()) 10510b57cec5SDimitry Andric return 's'; 10520b57cec5SDimitry Andric DataRefImpl Ref = Sec->getRawDataRefImpl(); 10530b57cec5SDimitry Andric StringRef SectionName; 10540b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref)) 10550b57cec5SDimitry Andric SectionName = *NameOrErr; 10560b57cec5SDimitry Andric StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); 10570b57cec5SDimitry Andric if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE && 10580b57cec5SDimitry Andric SegmentName == "__TEXT_EXEC" && SectionName == "__text") 10590b57cec5SDimitry Andric return 't'; 10600b57cec5SDimitry Andric if (SegmentName == "__TEXT" && SectionName == "__text") 10610b57cec5SDimitry Andric return 't'; 10620b57cec5SDimitry Andric if (SegmentName == "__DATA" && SectionName == "__data") 10630b57cec5SDimitry Andric return 'd'; 10640b57cec5SDimitry Andric if (SegmentName == "__DATA" && SectionName == "__bss") 10650b57cec5SDimitry Andric return 'b'; 10660b57cec5SDimitry Andric return 's'; 10670b57cec5SDimitry Andric } 10680b57cec5SDimitry Andric } 10690b57cec5SDimitry Andric 10700b57cec5SDimitry Andric return '?'; 10710b57cec5SDimitry Andric } 10720b57cec5SDimitry Andric 10735ffd83dbSDimitry Andric static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) { 10745ffd83dbSDimitry Andric return 's'; 10755ffd83dbSDimitry Andric } 10765ffd83dbSDimitry Andric 10770b57cec5SDimitry Andric static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { 10785ffd83dbSDimitry Andric uint32_t Flags = cantFail(I->getFlags()); 10790b57cec5SDimitry Andric if (Flags & SymbolRef::SF_Executable) 10800b57cec5SDimitry Andric return 't'; 10810b57cec5SDimitry Andric return 'd'; 10820b57cec5SDimitry Andric } 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { 10855ffd83dbSDimitry Andric uint32_t Flags = cantFail(I->getFlags()); 10860b57cec5SDimitry Andric // FIXME: should we print 'b'? At the IR level we cannot be sure if this 10870b57cec5SDimitry Andric // will be in bss or not, but we could approximate. 10880b57cec5SDimitry Andric if (Flags & SymbolRef::SF_Executable) 10890b57cec5SDimitry Andric return 't'; 10900b57cec5SDimitry Andric else if (Triple(Obj.getTargetTriple()).isOSDarwin() && 10910b57cec5SDimitry Andric (Flags & SymbolRef::SF_Const)) 10920b57cec5SDimitry Andric return 's'; 10930b57cec5SDimitry Andric else 10940b57cec5SDimitry Andric return 'd'; 10950b57cec5SDimitry Andric } 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) { 1098*e8d8bef9SDimitry Andric return isa<ELFObjectFileBase>(&Obj) && 1099*e8d8bef9SDimitry Andric elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT; 11000b57cec5SDimitry Andric } 11010b57cec5SDimitry Andric 11020b57cec5SDimitry Andric // For ELF object files, Set TypeName to the symbol typename, to be printed 11030b57cec5SDimitry Andric // in the 'Type' column of the SYSV format output. 11040b57cec5SDimitry Andric static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) { 11050b57cec5SDimitry Andric if (isa<ELFObjectFileBase>(&Obj)) { 11060b57cec5SDimitry Andric elf_symbol_iterator SymI(I); 11070b57cec5SDimitry Andric return SymI->getELFTypeName(); 11080b57cec5SDimitry Andric } 11090b57cec5SDimitry Andric return ""; 11100b57cec5SDimitry Andric } 11110b57cec5SDimitry Andric 11120b57cec5SDimitry Andric // Return Posix nm class type tag (single letter), but also set SecName and 11130b57cec5SDimitry Andric // section and name, to be used in format=sysv output. 11140b57cec5SDimitry Andric static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, 11150b57cec5SDimitry Andric StringRef &SecName) { 11165ffd83dbSDimitry Andric // Symbol Flags have been checked in the caller. 11175ffd83dbSDimitry Andric uint32_t Symflags = cantFail(I->getFlags()); 11188bcb0991SDimitry Andric if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) { 11190b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Absolute) 11200b57cec5SDimitry Andric SecName = "*ABS*"; 11210b57cec5SDimitry Andric else if (Symflags & object::SymbolRef::SF_Common) 11220b57cec5SDimitry Andric SecName = "*COM*"; 11230b57cec5SDimitry Andric else if (Symflags & object::SymbolRef::SF_Undefined) 11240b57cec5SDimitry Andric SecName = "*UND*"; 11250b57cec5SDimitry Andric else { 11260b57cec5SDimitry Andric elf_symbol_iterator SymI(I); 11270b57cec5SDimitry Andric Expected<elf_section_iterator> SecIOrErr = SymI->getSection(); 11280b57cec5SDimitry Andric if (!SecIOrErr) { 11290b57cec5SDimitry Andric consumeError(SecIOrErr.takeError()); 11300b57cec5SDimitry Andric return '?'; 11310b57cec5SDimitry Andric } 11328bcb0991SDimitry Andric 11338bcb0991SDimitry Andric if (*SecIOrErr == ELFObj->section_end()) 11348bcb0991SDimitry Andric return '?'; 11358bcb0991SDimitry Andric 11368bcb0991SDimitry Andric Expected<StringRef> NameOrErr = (*SecIOrErr)->getName(); 11378bcb0991SDimitry Andric if (!NameOrErr) { 11388bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 11398bcb0991SDimitry Andric return '?'; 11408bcb0991SDimitry Andric } 11418bcb0991SDimitry Andric SecName = *NameOrErr; 11420b57cec5SDimitry Andric } 11430b57cec5SDimitry Andric } 11440b57cec5SDimitry Andric 11450b57cec5SDimitry Andric if ((Symflags & object::SymbolRef::SF_Weak) && !isa<MachOObjectFile>(Obj)) { 11460b57cec5SDimitry Andric char Ret = isObject(Obj, I) ? 'v' : 'w'; 11470b57cec5SDimitry Andric return (!(Symflags & object::SymbolRef::SF_Undefined)) ? toupper(Ret) : Ret; 11480b57cec5SDimitry Andric } 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Undefined) 11510b57cec5SDimitry Andric return 'U'; 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Common) 11540b57cec5SDimitry Andric return 'C'; 11550b57cec5SDimitry Andric 11560b57cec5SDimitry Andric char Ret = '?'; 11570b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Absolute) 11580b57cec5SDimitry Andric Ret = 'a'; 11590b57cec5SDimitry Andric else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj)) 11600b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*IR, I); 11610b57cec5SDimitry Andric else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj)) 11620b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*COFF, I); 11630b57cec5SDimitry Andric else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj)) 11640b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*COFFImport); 11650b57cec5SDimitry Andric else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) 11660b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*MachO, I); 11670b57cec5SDimitry Andric else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj)) 11680b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*Wasm, I); 11695ffd83dbSDimitry Andric else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj)) 11705ffd83dbSDimitry Andric Ret = getSymbolNMTypeChar(*Tapi, I); 1171480093f4SDimitry Andric else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) { 1172480093f4SDimitry Andric if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC) 1173480093f4SDimitry Andric return 'i'; 1174480093f4SDimitry Andric Ret = getSymbolNMTypeChar(*ELF, I); 1175480093f4SDimitry Andric if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE) 1176480093f4SDimitry Andric return Ret; 1177480093f4SDimitry Andric } else 1178480093f4SDimitry Andric llvm_unreachable("unknown binary format"); 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric if (!(Symflags & object::SymbolRef::SF_Global)) 11810b57cec5SDimitry Andric return Ret; 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric return toupper(Ret); 11840b57cec5SDimitry Andric } 11850b57cec5SDimitry Andric 11860b57cec5SDimitry Andric // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname" 11870b57cec5SDimitry Andric // option to dump only those symbols from that section in a Mach-O file. 11880b57cec5SDimitry Andric // It is called once for each Mach-O file from dumpSymbolNamesFromObject() 11890b57cec5SDimitry Andric // to get the section number for that named section from the command line 11900b57cec5SDimitry Andric // arguments. It returns the section number for that section in the Mach-O 11910b57cec5SDimitry Andric // file or zero it is not present. 11920b57cec5SDimitry Andric static unsigned getNsectForSegSect(MachOObjectFile *Obj) { 11930b57cec5SDimitry Andric unsigned Nsect = 1; 11940b57cec5SDimitry Andric for (auto &S : Obj->sections()) { 11950b57cec5SDimitry Andric DataRefImpl Ref = S.getRawDataRefImpl(); 11960b57cec5SDimitry Andric StringRef SectionName; 11970b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = Obj->getSectionName(Ref)) 11980b57cec5SDimitry Andric SectionName = *NameOrErr; 11990b57cec5SDimitry Andric StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref); 12000b57cec5SDimitry Andric if (SegmentName == SegSect[0] && SectionName == SegSect[1]) 12010b57cec5SDimitry Andric return Nsect; 12020b57cec5SDimitry Andric Nsect++; 12030b57cec5SDimitry Andric } 12040b57cec5SDimitry Andric return 0; 12050b57cec5SDimitry Andric } 12060b57cec5SDimitry Andric 12070b57cec5SDimitry Andric // getNsectInMachO() is used to implement the Mach-O "-s segname sectname" 12080b57cec5SDimitry Andric // option to dump only those symbols from that section in a Mach-O file. 12090b57cec5SDimitry Andric // It is called once for each symbol in a Mach-O file from 12100b57cec5SDimitry Andric // dumpSymbolNamesFromObject() and returns the section number for that symbol 12110b57cec5SDimitry Andric // if it is in a section, else it returns 0. 12120b57cec5SDimitry Andric static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) { 12130b57cec5SDimitry Andric DataRefImpl Symb = Sym.getRawDataRefImpl(); 12140b57cec5SDimitry Andric if (Obj.is64Bit()) { 12150b57cec5SDimitry Andric MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); 12160b57cec5SDimitry Andric return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; 12170b57cec5SDimitry Andric } 12180b57cec5SDimitry Andric MachO::nlist STE = Obj.getSymbolTableEntry(Symb); 12190b57cec5SDimitry Andric return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; 12200b57cec5SDimitry Andric } 12210b57cec5SDimitry Andric 1222*e8d8bef9SDimitry Andric static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO) { 1223*e8d8bef9SDimitry Andric size_t I = SymbolList.size(); 12240b57cec5SDimitry Andric std::string ExportsNameBuffer; 12250b57cec5SDimitry Andric raw_string_ostream EOS(ExportsNameBuffer); 12260b57cec5SDimitry Andric std::string BindsNameBuffer; 12270b57cec5SDimitry Andric raw_string_ostream BOS(BindsNameBuffer); 12280b57cec5SDimitry Andric std::string LazysNameBuffer; 12290b57cec5SDimitry Andric raw_string_ostream LOS(LazysNameBuffer); 12300b57cec5SDimitry Andric std::string WeaksNameBuffer; 12310b57cec5SDimitry Andric raw_string_ostream WOS(WeaksNameBuffer); 12320b57cec5SDimitry Andric std::string FunctionStartsNameBuffer; 12330b57cec5SDimitry Andric raw_string_ostream FOS(FunctionStartsNameBuffer); 1234*e8d8bef9SDimitry Andric 12350b57cec5SDimitry Andric MachO::mach_header H; 12360b57cec5SDimitry Andric MachO::mach_header_64 H_64; 12370b57cec5SDimitry Andric uint32_t HFlags = 0; 1238*e8d8bef9SDimitry Andric if (MachO.is64Bit()) { 1239*e8d8bef9SDimitry Andric H_64 = MachO.MachOObjectFile::getHeader64(); 12400b57cec5SDimitry Andric HFlags = H_64.flags; 12410b57cec5SDimitry Andric } else { 1242*e8d8bef9SDimitry Andric H = MachO.MachOObjectFile::getHeader(); 12430b57cec5SDimitry Andric HFlags = H.flags; 12440b57cec5SDimitry Andric } 12450b57cec5SDimitry Andric uint64_t BaseSegmentAddress = 0; 1246*e8d8bef9SDimitry Andric for (const auto &Command : MachO.load_commands()) { 12470b57cec5SDimitry Andric if (Command.C.cmd == MachO::LC_SEGMENT) { 1248*e8d8bef9SDimitry Andric MachO::segment_command Seg = MachO.getSegmentLoadCommand(Command); 12490b57cec5SDimitry Andric if (Seg.fileoff == 0 && Seg.filesize != 0) { 12500b57cec5SDimitry Andric BaseSegmentAddress = Seg.vmaddr; 12510b57cec5SDimitry Andric break; 12520b57cec5SDimitry Andric } 12530b57cec5SDimitry Andric } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 1254*e8d8bef9SDimitry Andric MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(Command); 12550b57cec5SDimitry Andric if (Seg.fileoff == 0 && Seg.filesize != 0) { 12560b57cec5SDimitry Andric BaseSegmentAddress = Seg.vmaddr; 12570b57cec5SDimitry Andric break; 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric } 12600b57cec5SDimitry Andric } 12610b57cec5SDimitry Andric if (DyldInfoOnly || AddDyldInfo || 12620b57cec5SDimitry Andric HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 12630b57cec5SDimitry Andric unsigned ExportsAdded = 0; 12640b57cec5SDimitry Andric Error Err = Error::success(); 1265*e8d8bef9SDimitry Andric for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) { 12660b57cec5SDimitry Andric bool found = false; 12670b57cec5SDimitry Andric bool ReExport = false; 12680b57cec5SDimitry Andric if (!DyldInfoOnly) { 12690b57cec5SDimitry Andric for (const NMSymbol &S : SymbolList) 12700b57cec5SDimitry Andric if (S.Address == Entry.address() + BaseSegmentAddress && 12710b57cec5SDimitry Andric S.Name == Entry.name()) { 12720b57cec5SDimitry Andric found = true; 12730b57cec5SDimitry Andric break; 12740b57cec5SDimitry Andric } 12750b57cec5SDimitry Andric } 12760b57cec5SDimitry Andric if (!found) { 12770b57cec5SDimitry Andric NMSymbol S = {}; 12780b57cec5SDimitry Andric S.Address = Entry.address() + BaseSegmentAddress; 12790b57cec5SDimitry Andric S.Size = 0; 12800b57cec5SDimitry Andric S.TypeChar = '\0'; 1281*e8d8bef9SDimitry Andric S.Name = Entry.name().str(); 12820b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 12830b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 12840b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 12850b57cec5SDimitry Andric S.Sym = BasicSymbolRef(); 12860b57cec5SDimitry Andric S.SymFlags = SymbolRef::SF_Global; 12870b57cec5SDimitry Andric S.Section = SectionRef(); 12880b57cec5SDimitry Andric S.NType = 0; 12890b57cec5SDimitry Andric S.NSect = 0; 12900b57cec5SDimitry Andric S.NDesc = 0; 12910b57cec5SDimitry Andric 12920b57cec5SDimitry Andric uint64_t EFlags = Entry.flags(); 12930b57cec5SDimitry Andric bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 12940b57cec5SDimitry Andric MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 1295*e8d8bef9SDimitry Andric bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 12960b57cec5SDimitry Andric ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 12970b57cec5SDimitry Andric bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 12980b57cec5SDimitry Andric if (WeakDef) 12990b57cec5SDimitry Andric S.NDesc |= MachO::N_WEAK_DEF; 13000b57cec5SDimitry Andric if (Abs) { 13010b57cec5SDimitry Andric S.NType = MachO::N_EXT | MachO::N_ABS; 13020b57cec5SDimitry Andric S.TypeChar = 'A'; 13030b57cec5SDimitry Andric } else if (ReExport) { 13040b57cec5SDimitry Andric S.NType = MachO::N_EXT | MachO::N_INDR; 13050b57cec5SDimitry Andric S.TypeChar = 'I'; 13060b57cec5SDimitry Andric } else { 13070b57cec5SDimitry Andric S.NType = MachO::N_EXT | MachO::N_SECT; 13080b57cec5SDimitry Andric if (Resolver) { 13090b57cec5SDimitry Andric S.Address = Entry.other() + BaseSegmentAddress; 1310*e8d8bef9SDimitry Andric if ((S.Address & 1) != 0 && !MachO.is64Bit() && 1311*e8d8bef9SDimitry Andric H.cputype == MachO::CPU_TYPE_ARM) { 13120b57cec5SDimitry Andric S.Address &= ~1LL; 13130b57cec5SDimitry Andric S.NDesc |= MachO::N_ARM_THUMB_DEF; 13140b57cec5SDimitry Andric } 13150b57cec5SDimitry Andric } else { 13160b57cec5SDimitry Andric S.Address = Entry.address() + BaseSegmentAddress; 13170b57cec5SDimitry Andric } 13180b57cec5SDimitry Andric StringRef SegmentName = StringRef(); 13190b57cec5SDimitry Andric StringRef SectionName = StringRef(); 1320*e8d8bef9SDimitry Andric for (const SectionRef &Section : MachO.sections()) { 13210b57cec5SDimitry Andric S.NSect++; 13228bcb0991SDimitry Andric 13238bcb0991SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 13248bcb0991SDimitry Andric SectionName = *NameOrErr; 13258bcb0991SDimitry Andric else 13268bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 13278bcb0991SDimitry Andric 1328*e8d8bef9SDimitry Andric SegmentName = 1329*e8d8bef9SDimitry Andric MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl()); 13300b57cec5SDimitry Andric if (S.Address >= Section.getAddress() && 13310b57cec5SDimitry Andric S.Address < Section.getAddress() + Section.getSize()) { 13320b57cec5SDimitry Andric S.Section = Section; 13330b57cec5SDimitry Andric break; 13340b57cec5SDimitry Andric } else if (Entry.name() == "__mh_execute_header" && 13350b57cec5SDimitry Andric SegmentName == "__TEXT" && SectionName == "__text") { 13360b57cec5SDimitry Andric S.Section = Section; 13370b57cec5SDimitry Andric S.NDesc |= MachO::REFERENCED_DYNAMICALLY; 13380b57cec5SDimitry Andric break; 13390b57cec5SDimitry Andric } 13400b57cec5SDimitry Andric } 13410b57cec5SDimitry Andric if (SegmentName == "__TEXT" && SectionName == "__text") 13420b57cec5SDimitry Andric S.TypeChar = 'T'; 13430b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__data") 13440b57cec5SDimitry Andric S.TypeChar = 'D'; 13450b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__bss") 13460b57cec5SDimitry Andric S.TypeChar = 'B'; 13470b57cec5SDimitry Andric else 13480b57cec5SDimitry Andric S.TypeChar = 'S'; 13490b57cec5SDimitry Andric } 13500b57cec5SDimitry Andric SymbolList.push_back(S); 13510b57cec5SDimitry Andric 13520b57cec5SDimitry Andric EOS << Entry.name(); 13530b57cec5SDimitry Andric EOS << '\0'; 13540b57cec5SDimitry Andric ExportsAdded++; 13550b57cec5SDimitry Andric 13560b57cec5SDimitry Andric // For ReExports there are a two more things to do, first add the 13570b57cec5SDimitry Andric // indirect name and second create the undefined symbol using the 13580b57cec5SDimitry Andric // referened dynamic library. 13590b57cec5SDimitry Andric if (ReExport) { 13600b57cec5SDimitry Andric 13610b57cec5SDimitry Andric // Add the indirect name. 13620b57cec5SDimitry Andric if (Entry.otherName().empty()) 13630b57cec5SDimitry Andric EOS << Entry.name(); 13640b57cec5SDimitry Andric else 13650b57cec5SDimitry Andric EOS << Entry.otherName(); 13660b57cec5SDimitry Andric EOS << '\0'; 13670b57cec5SDimitry Andric 13680b57cec5SDimitry Andric // Now create the undefined symbol using the referened dynamic 13690b57cec5SDimitry Andric // library. 13700b57cec5SDimitry Andric NMSymbol U = {}; 13710b57cec5SDimitry Andric U.Address = 0; 13720b57cec5SDimitry Andric U.Size = 0; 13730b57cec5SDimitry Andric U.TypeChar = 'U'; 13740b57cec5SDimitry Andric if (Entry.otherName().empty()) 1375*e8d8bef9SDimitry Andric U.Name = Entry.name().str(); 13760b57cec5SDimitry Andric else 1377*e8d8bef9SDimitry Andric U.Name = Entry.otherName().str(); 13780b57cec5SDimitry Andric // Again there is no symbol in the nlist symbol table for this so 13790b57cec5SDimitry Andric // we set Sym effectivly to null and the rest of code in here must 13800b57cec5SDimitry Andric // test for it and not do things like Sym.getFlags() for it. 13810b57cec5SDimitry Andric U.Sym = BasicSymbolRef(); 13820b57cec5SDimitry Andric U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 13830b57cec5SDimitry Andric U.Section = SectionRef(); 13840b57cec5SDimitry Andric U.NType = MachO::N_EXT | MachO::N_UNDF; 13850b57cec5SDimitry Andric U.NSect = 0; 13860b57cec5SDimitry Andric U.NDesc = 0; 13870b57cec5SDimitry Andric // The library ordinal for this undefined symbol is in the export 13880b57cec5SDimitry Andric // trie Entry.other(). 13890b57cec5SDimitry Andric MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other()); 13900b57cec5SDimitry Andric SymbolList.push_back(U); 13910b57cec5SDimitry Andric 13920b57cec5SDimitry Andric // Finally add the undefined symbol's name. 13930b57cec5SDimitry Andric if (Entry.otherName().empty()) 13940b57cec5SDimitry Andric EOS << Entry.name(); 13950b57cec5SDimitry Andric else 13960b57cec5SDimitry Andric EOS << Entry.otherName(); 13970b57cec5SDimitry Andric EOS << '\0'; 13980b57cec5SDimitry Andric ExportsAdded++; 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric } 14010b57cec5SDimitry Andric } 14020b57cec5SDimitry Andric if (Err) 1403*e8d8bef9SDimitry Andric error(std::move(Err), MachO.getFileName()); 14040b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 14050b57cec5SDimitry Andric if (ExportsAdded) { 14060b57cec5SDimitry Andric EOS.flush(); 14070b57cec5SDimitry Andric const char *Q = ExportsNameBuffer.c_str(); 14080b57cec5SDimitry Andric for (unsigned K = 0; K < ExportsAdded; K++) { 14090b57cec5SDimitry Andric SymbolList[I].Name = Q; 14100b57cec5SDimitry Andric Q += strlen(Q) + 1; 14110b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 14120b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 14130b57cec5SDimitry Andric Q += strlen(Q) + 1; 14140b57cec5SDimitry Andric } 14150b57cec5SDimitry Andric I++; 14160b57cec5SDimitry Andric } 14170b57cec5SDimitry Andric } 14180b57cec5SDimitry Andric 14190b57cec5SDimitry Andric // Add the undefined symbols from the bind entries. 14200b57cec5SDimitry Andric unsigned BindsAdded = 0; 14210b57cec5SDimitry Andric Error BErr = Error::success(); 14220b57cec5SDimitry Andric StringRef LastSymbolName = StringRef(); 1423*e8d8bef9SDimitry Andric for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(BErr)) { 14240b57cec5SDimitry Andric bool found = false; 14250b57cec5SDimitry Andric if (LastSymbolName == Entry.symbolName()) 14260b57cec5SDimitry Andric found = true; 14270b57cec5SDimitry Andric else if (!DyldInfoOnly) { 14280b57cec5SDimitry Andric for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { 14290b57cec5SDimitry Andric if (SymbolList[J].Name == Entry.symbolName()) 14300b57cec5SDimitry Andric found = true; 14310b57cec5SDimitry Andric } 14320b57cec5SDimitry Andric } 14330b57cec5SDimitry Andric if (!found) { 14340b57cec5SDimitry Andric LastSymbolName = Entry.symbolName(); 14350b57cec5SDimitry Andric NMSymbol B = {}; 14360b57cec5SDimitry Andric B.Address = 0; 14370b57cec5SDimitry Andric B.Size = 0; 14380b57cec5SDimitry Andric B.TypeChar = 'U'; 14390b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 14400b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 14410b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 14420b57cec5SDimitry Andric B.Sym = BasicSymbolRef(); 14430b57cec5SDimitry Andric B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 14440b57cec5SDimitry Andric B.NType = MachO::N_EXT | MachO::N_UNDF; 14450b57cec5SDimitry Andric B.NSect = 0; 14460b57cec5SDimitry Andric B.NDesc = 0; 14470b57cec5SDimitry Andric MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal()); 1448*e8d8bef9SDimitry Andric B.Name = Entry.symbolName().str(); 14490b57cec5SDimitry Andric SymbolList.push_back(B); 14500b57cec5SDimitry Andric BOS << Entry.symbolName(); 14510b57cec5SDimitry Andric BOS << '\0'; 14520b57cec5SDimitry Andric BindsAdded++; 14530b57cec5SDimitry Andric } 14540b57cec5SDimitry Andric } 14550b57cec5SDimitry Andric if (BErr) 1456*e8d8bef9SDimitry Andric error(std::move(BErr), MachO.getFileName()); 14570b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 14580b57cec5SDimitry Andric if (BindsAdded) { 14590b57cec5SDimitry Andric BOS.flush(); 14600b57cec5SDimitry Andric const char *Q = BindsNameBuffer.c_str(); 14610b57cec5SDimitry Andric for (unsigned K = 0; K < BindsAdded; K++) { 14620b57cec5SDimitry Andric SymbolList[I].Name = Q; 14630b57cec5SDimitry Andric Q += strlen(Q) + 1; 14640b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 14650b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 14660b57cec5SDimitry Andric Q += strlen(Q) + 1; 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric I++; 14690b57cec5SDimitry Andric } 14700b57cec5SDimitry Andric } 14710b57cec5SDimitry Andric 14720b57cec5SDimitry Andric // Add the undefined symbols from the lazy bind entries. 14730b57cec5SDimitry Andric unsigned LazysAdded = 0; 14740b57cec5SDimitry Andric Error LErr = Error::success(); 14750b57cec5SDimitry Andric LastSymbolName = StringRef(); 14760b57cec5SDimitry Andric for (const llvm::object::MachOBindEntry &Entry : 1477*e8d8bef9SDimitry Andric MachO.lazyBindTable(LErr)) { 14780b57cec5SDimitry Andric bool found = false; 14790b57cec5SDimitry Andric if (LastSymbolName == Entry.symbolName()) 14800b57cec5SDimitry Andric found = true; 14810b57cec5SDimitry Andric else { 14820b57cec5SDimitry Andric // Here we must check to see it this symbol is already in the 14830b57cec5SDimitry Andric // SymbolList as it might have already have been added above via a 14840b57cec5SDimitry Andric // non-lazy (bind) entry. 14850b57cec5SDimitry Andric for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { 14860b57cec5SDimitry Andric if (SymbolList[J].Name == Entry.symbolName()) 14870b57cec5SDimitry Andric found = true; 14880b57cec5SDimitry Andric } 14890b57cec5SDimitry Andric } 14900b57cec5SDimitry Andric if (!found) { 14910b57cec5SDimitry Andric LastSymbolName = Entry.symbolName(); 14920b57cec5SDimitry Andric NMSymbol L = {}; 1493*e8d8bef9SDimitry Andric L.Name = Entry.symbolName().str(); 14940b57cec5SDimitry Andric L.Address = 0; 14950b57cec5SDimitry Andric L.Size = 0; 14960b57cec5SDimitry Andric L.TypeChar = 'U'; 14970b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 14980b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 14990b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 15000b57cec5SDimitry Andric L.Sym = BasicSymbolRef(); 15010b57cec5SDimitry Andric L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 15020b57cec5SDimitry Andric L.NType = MachO::N_EXT | MachO::N_UNDF; 15030b57cec5SDimitry Andric L.NSect = 0; 15040b57cec5SDimitry Andric // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it 15050b57cec5SDimitry Andric // makes sence since we are creating this from a lazy bind entry. 15060b57cec5SDimitry Andric L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY; 15070b57cec5SDimitry Andric MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal()); 15080b57cec5SDimitry Andric SymbolList.push_back(L); 15090b57cec5SDimitry Andric LOS << Entry.symbolName(); 15100b57cec5SDimitry Andric LOS << '\0'; 15110b57cec5SDimitry Andric LazysAdded++; 15120b57cec5SDimitry Andric } 15130b57cec5SDimitry Andric } 15140b57cec5SDimitry Andric if (LErr) 1515*e8d8bef9SDimitry Andric error(std::move(LErr), MachO.getFileName()); 15160b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 15170b57cec5SDimitry Andric if (LazysAdded) { 15180b57cec5SDimitry Andric LOS.flush(); 15190b57cec5SDimitry Andric const char *Q = LazysNameBuffer.c_str(); 15200b57cec5SDimitry Andric for (unsigned K = 0; K < LazysAdded; K++) { 15210b57cec5SDimitry Andric SymbolList[I].Name = Q; 15220b57cec5SDimitry Andric Q += strlen(Q) + 1; 15230b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 15240b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 15250b57cec5SDimitry Andric Q += strlen(Q) + 1; 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric I++; 15280b57cec5SDimitry Andric } 15290b57cec5SDimitry Andric } 15300b57cec5SDimitry Andric 15310b57cec5SDimitry Andric // Add the undefineds symbol from the weak bind entries which are not 15320b57cec5SDimitry Andric // strong symbols. 15330b57cec5SDimitry Andric unsigned WeaksAdded = 0; 15340b57cec5SDimitry Andric Error WErr = Error::success(); 15350b57cec5SDimitry Andric LastSymbolName = StringRef(); 15360b57cec5SDimitry Andric for (const llvm::object::MachOBindEntry &Entry : 1537*e8d8bef9SDimitry Andric MachO.weakBindTable(WErr)) { 15380b57cec5SDimitry Andric bool found = false; 15390b57cec5SDimitry Andric unsigned J = 0; 15400b57cec5SDimitry Andric if (LastSymbolName == Entry.symbolName() || 15410b57cec5SDimitry Andric Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 15420b57cec5SDimitry Andric found = true; 15430b57cec5SDimitry Andric } else { 15440b57cec5SDimitry Andric for (J = 0; J < SymbolList.size() && !found; ++J) { 15450b57cec5SDimitry Andric if (SymbolList[J].Name == Entry.symbolName()) { 15460b57cec5SDimitry Andric found = true; 15470b57cec5SDimitry Andric break; 15480b57cec5SDimitry Andric } 15490b57cec5SDimitry Andric } 15500b57cec5SDimitry Andric } 15510b57cec5SDimitry Andric if (!found) { 15520b57cec5SDimitry Andric LastSymbolName = Entry.symbolName(); 1553*e8d8bef9SDimitry Andric NMSymbol W = {}; 1554*e8d8bef9SDimitry Andric W.Name = Entry.symbolName().str(); 15550b57cec5SDimitry Andric W.Address = 0; 15560b57cec5SDimitry Andric W.Size = 0; 15570b57cec5SDimitry Andric W.TypeChar = 'U'; 15580b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 15590b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 15600b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 15610b57cec5SDimitry Andric W.Sym = BasicSymbolRef(); 15620b57cec5SDimitry Andric W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 15630b57cec5SDimitry Andric W.NType = MachO::N_EXT | MachO::N_UNDF; 15640b57cec5SDimitry Andric W.NSect = 0; 15650b57cec5SDimitry Andric // Odd that we are using N_WEAK_DEF on an undefined symbol but that is 15660b57cec5SDimitry Andric // what is created in this case by the linker when there are real 15670b57cec5SDimitry Andric // symbols in the nlist structs. 15680b57cec5SDimitry Andric W.NDesc = MachO::N_WEAK_DEF; 15690b57cec5SDimitry Andric SymbolList.push_back(W); 15700b57cec5SDimitry Andric WOS << Entry.symbolName(); 15710b57cec5SDimitry Andric WOS << '\0'; 15720b57cec5SDimitry Andric WeaksAdded++; 15730b57cec5SDimitry Andric } else { 15740b57cec5SDimitry Andric // This is the case the symbol was previously been found and it could 15750b57cec5SDimitry Andric // have been added from a bind or lazy bind symbol. If so and not 15760b57cec5SDimitry Andric // a definition also mark it as weak. 15770b57cec5SDimitry Andric if (SymbolList[J].TypeChar == 'U') 15780b57cec5SDimitry Andric // See comment above about N_WEAK_DEF. 15790b57cec5SDimitry Andric SymbolList[J].NDesc |= MachO::N_WEAK_DEF; 15800b57cec5SDimitry Andric } 15810b57cec5SDimitry Andric } 15820b57cec5SDimitry Andric if (WErr) 1583*e8d8bef9SDimitry Andric error(std::move(WErr), MachO.getFileName()); 15840b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 15850b57cec5SDimitry Andric if (WeaksAdded) { 15860b57cec5SDimitry Andric WOS.flush(); 15870b57cec5SDimitry Andric const char *Q = WeaksNameBuffer.c_str(); 15880b57cec5SDimitry Andric for (unsigned K = 0; K < WeaksAdded; K++) { 15890b57cec5SDimitry Andric SymbolList[I].Name = Q; 15900b57cec5SDimitry Andric Q += strlen(Q) + 1; 15910b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 15920b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 15930b57cec5SDimitry Andric Q += strlen(Q) + 1; 15940b57cec5SDimitry Andric } 15950b57cec5SDimitry Andric I++; 15960b57cec5SDimitry Andric } 15970b57cec5SDimitry Andric } 15980b57cec5SDimitry Andric 15990b57cec5SDimitry Andric // Trying adding symbol from the function starts table and LC_MAIN entry 16000b57cec5SDimitry Andric // point. 16010b57cec5SDimitry Andric SmallVector<uint64_t, 8> FoundFns; 16020b57cec5SDimitry Andric uint64_t lc_main_offset = UINT64_MAX; 1603*e8d8bef9SDimitry Andric for (const auto &Command : MachO.load_commands()) { 16040b57cec5SDimitry Andric if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 16050b57cec5SDimitry Andric // We found a function starts segment, parse the addresses for 16060b57cec5SDimitry Andric // consumption. 16070b57cec5SDimitry Andric MachO::linkedit_data_command LLC = 1608*e8d8bef9SDimitry Andric MachO.getLinkeditDataLoadCommand(Command); 16090b57cec5SDimitry Andric 1610*e8d8bef9SDimitry Andric MachO.ReadULEB128s(LLC.dataoff, FoundFns); 16110b57cec5SDimitry Andric } else if (Command.C.cmd == MachO::LC_MAIN) { 1612*e8d8bef9SDimitry Andric MachO::entry_point_command LCmain = MachO.getEntryPointCommand(Command); 16130b57cec5SDimitry Andric lc_main_offset = LCmain.entryoff; 16140b57cec5SDimitry Andric } 16150b57cec5SDimitry Andric } 16160b57cec5SDimitry Andric // See if these addresses are already in the symbol table. 16170b57cec5SDimitry Andric unsigned FunctionStartsAdded = 0; 16180b57cec5SDimitry Andric for (uint64_t f = 0; f < FoundFns.size(); f++) { 16190b57cec5SDimitry Andric bool found = false; 16200b57cec5SDimitry Andric for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { 16210b57cec5SDimitry Andric if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress) 16220b57cec5SDimitry Andric found = true; 16230b57cec5SDimitry Andric } 16240b57cec5SDimitry Andric // See this address is not already in the symbol table fake up an 16250b57cec5SDimitry Andric // nlist for it. 16260b57cec5SDimitry Andric if (!found) { 16270b57cec5SDimitry Andric NMSymbol F = {}; 16280b57cec5SDimitry Andric F.Name = "<redacted function X>"; 16290b57cec5SDimitry Andric F.Address = FoundFns[f] + BaseSegmentAddress; 16300b57cec5SDimitry Andric F.Size = 0; 16310b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 16320b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 16330b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 16340b57cec5SDimitry Andric F.Sym = BasicSymbolRef(); 16350b57cec5SDimitry Andric F.SymFlags = 0; 16360b57cec5SDimitry Andric F.NType = MachO::N_SECT; 16370b57cec5SDimitry Andric F.NSect = 0; 16380b57cec5SDimitry Andric StringRef SegmentName = StringRef(); 16390b57cec5SDimitry Andric StringRef SectionName = StringRef(); 1640*e8d8bef9SDimitry Andric for (const SectionRef &Section : MachO.sections()) { 16418bcb0991SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 16428bcb0991SDimitry Andric SectionName = *NameOrErr; 16438bcb0991SDimitry Andric else 16448bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 16458bcb0991SDimitry Andric 1646*e8d8bef9SDimitry Andric SegmentName = 1647*e8d8bef9SDimitry Andric MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl()); 16480b57cec5SDimitry Andric F.NSect++; 16490b57cec5SDimitry Andric if (F.Address >= Section.getAddress() && 16500b57cec5SDimitry Andric F.Address < Section.getAddress() + Section.getSize()) { 16510b57cec5SDimitry Andric F.Section = Section; 16520b57cec5SDimitry Andric break; 16530b57cec5SDimitry Andric } 16540b57cec5SDimitry Andric } 16550b57cec5SDimitry Andric if (SegmentName == "__TEXT" && SectionName == "__text") 16560b57cec5SDimitry Andric F.TypeChar = 't'; 16570b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__data") 16580b57cec5SDimitry Andric F.TypeChar = 'd'; 16590b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__bss") 16600b57cec5SDimitry Andric F.TypeChar = 'b'; 16610b57cec5SDimitry Andric else 16620b57cec5SDimitry Andric F.TypeChar = 's'; 16630b57cec5SDimitry Andric F.NDesc = 0; 16640b57cec5SDimitry Andric SymbolList.push_back(F); 16650b57cec5SDimitry Andric if (FoundFns[f] == lc_main_offset) 16660b57cec5SDimitry Andric FOS << "<redacted LC_MAIN>"; 16670b57cec5SDimitry Andric else 16680b57cec5SDimitry Andric FOS << "<redacted function " << f << ">"; 16690b57cec5SDimitry Andric FOS << '\0'; 16700b57cec5SDimitry Andric FunctionStartsAdded++; 16710b57cec5SDimitry Andric } 16720b57cec5SDimitry Andric } 16730b57cec5SDimitry Andric if (FunctionStartsAdded) { 16740b57cec5SDimitry Andric FOS.flush(); 16750b57cec5SDimitry Andric const char *Q = FunctionStartsNameBuffer.c_str(); 16760b57cec5SDimitry Andric for (unsigned K = 0; K < FunctionStartsAdded; K++) { 16770b57cec5SDimitry Andric SymbolList[I].Name = Q; 16780b57cec5SDimitry Andric Q += strlen(Q) + 1; 16790b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 16800b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 16810b57cec5SDimitry Andric Q += strlen(Q) + 1; 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric I++; 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric } 16870b57cec5SDimitry Andric } 16880b57cec5SDimitry Andric 1689*e8d8bef9SDimitry Andric namespace { 1690*e8d8bef9SDimitry Andric struct SymbolVersion { 1691*e8d8bef9SDimitry Andric std::string Name; 1692*e8d8bef9SDimitry Andric bool IsDefault; 1693*e8d8bef9SDimitry Andric }; 1694*e8d8bef9SDimitry Andric } // namespace 1695*e8d8bef9SDimitry Andric 1696*e8d8bef9SDimitry Andric template <class ELFT> 1697*e8d8bef9SDimitry Andric static Expected<std::vector<SymbolVersion>> 1698*e8d8bef9SDimitry Andric readSymbolVersionsELF(const ELFFile<ELFT> &Obj, StringRef FileName, 1699*e8d8bef9SDimitry Andric ELFObjectFileBase::elf_symbol_iterator_range Symbols) { 1700*e8d8bef9SDimitry Andric using Elf_Shdr = typename ELFT::Shdr; 1701*e8d8bef9SDimitry Andric 1702*e8d8bef9SDimitry Andric // We called sections() earlier, so can't fail here. 1703*e8d8bef9SDimitry Andric typename ELFT::ShdrRange SectionsOrErr = cantFail(Obj.sections()); 1704*e8d8bef9SDimitry Andric const Elf_Shdr *SymVerSec = nullptr; 1705*e8d8bef9SDimitry Andric const Elf_Shdr *SymVerNeedSec = nullptr; 1706*e8d8bef9SDimitry Andric const Elf_Shdr *SymVerDefSec = nullptr; 1707*e8d8bef9SDimitry Andric for (const Elf_Shdr &Sec : SectionsOrErr) { 1708*e8d8bef9SDimitry Andric if (Sec.sh_type == ELF::SHT_GNU_versym) 1709*e8d8bef9SDimitry Andric SymVerSec = &Sec; 1710*e8d8bef9SDimitry Andric else if (Sec.sh_type == ELF::SHT_GNU_verdef) 1711*e8d8bef9SDimitry Andric SymVerDefSec = &Sec; 1712*e8d8bef9SDimitry Andric else if (Sec.sh_type == ELF::SHT_GNU_verneed) 1713*e8d8bef9SDimitry Andric SymVerNeedSec = &Sec; 1714*e8d8bef9SDimitry Andric } 1715*e8d8bef9SDimitry Andric 1716*e8d8bef9SDimitry Andric if (!SymVerSec) 1717*e8d8bef9SDimitry Andric return std::vector<SymbolVersion>{}; 1718*e8d8bef9SDimitry Andric 1719*e8d8bef9SDimitry Andric Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr = 1720*e8d8bef9SDimitry Andric Obj.loadVersionMap(SymVerNeedSec, SymVerDefSec); 1721*e8d8bef9SDimitry Andric if (!MapOrErr) 1722*e8d8bef9SDimitry Andric return MapOrErr.takeError(); 1723*e8d8bef9SDimitry Andric 1724*e8d8bef9SDimitry Andric std::vector<SymbolVersion> Ret; 1725*e8d8bef9SDimitry Andric size_t I = 0; 1726*e8d8bef9SDimitry Andric for (auto It = Symbols.begin(), E = Symbols.end(); It != E; ++It) { 1727*e8d8bef9SDimitry Andric ++I; 1728*e8d8bef9SDimitry Andric Expected<const typename ELFT::Versym *> VerEntryOrErr = 1729*e8d8bef9SDimitry Andric Obj.template getEntry<typename ELFT::Versym>(*SymVerSec, I); 1730*e8d8bef9SDimitry Andric if (!VerEntryOrErr) 1731*e8d8bef9SDimitry Andric return createError("unable to read an entry with index " + Twine(I) + 1732*e8d8bef9SDimitry Andric " from " + describe(Obj, *SymVerSec) + ": " + 1733*e8d8bef9SDimitry Andric toString(VerEntryOrErr.takeError())); 1734*e8d8bef9SDimitry Andric 1735*e8d8bef9SDimitry Andric Expected<uint32_t> FlagsOrErr = It->getFlags(); 1736*e8d8bef9SDimitry Andric if (!FlagsOrErr) 1737*e8d8bef9SDimitry Andric return createError("unable to read flags for symbol with index " + 1738*e8d8bef9SDimitry Andric Twine(I) + ": " + toString(FlagsOrErr.takeError())); 1739*e8d8bef9SDimitry Andric 1740*e8d8bef9SDimitry Andric bool IsDefault; 1741*e8d8bef9SDimitry Andric Expected<StringRef> VerOrErr = Obj.getSymbolVersionByIndex( 1742*e8d8bef9SDimitry Andric (*VerEntryOrErr)->vs_index, IsDefault, *MapOrErr, 1743*e8d8bef9SDimitry Andric (*FlagsOrErr) & SymbolRef::SF_Undefined); 1744*e8d8bef9SDimitry Andric if (!VerOrErr) 1745*e8d8bef9SDimitry Andric return createError("unable to get a version for entry " + Twine(I) + 1746*e8d8bef9SDimitry Andric " of " + describe(Obj, *SymVerSec) + ": " + 1747*e8d8bef9SDimitry Andric toString(VerOrErr.takeError())); 1748*e8d8bef9SDimitry Andric 1749*e8d8bef9SDimitry Andric Ret.push_back({(*VerOrErr).str(), IsDefault}); 1750*e8d8bef9SDimitry Andric } 1751*e8d8bef9SDimitry Andric 1752*e8d8bef9SDimitry Andric return Ret; 1753*e8d8bef9SDimitry Andric } 1754*e8d8bef9SDimitry Andric 1755*e8d8bef9SDimitry Andric static Expected<std::vector<SymbolVersion>> 1756*e8d8bef9SDimitry Andric readSymbolVersionsELF(const ELFObjectFileBase &Obj, 1757*e8d8bef9SDimitry Andric ELFObjectFileBase::elf_symbol_iterator_range Symbols) { 1758*e8d8bef9SDimitry Andric if (const auto *ELF = dyn_cast<ELF32LEObjectFile>(&Obj)) 1759*e8d8bef9SDimitry Andric return readSymbolVersionsELF(ELF->getELFFile(), Obj.getFileName(), Symbols); 1760*e8d8bef9SDimitry Andric else if (const auto *ELF = dyn_cast<ELF32BEObjectFile>(&Obj)) 1761*e8d8bef9SDimitry Andric return readSymbolVersionsELF(ELF->getELFFile(), Obj.getFileName(), Symbols); 1762*e8d8bef9SDimitry Andric else if (const auto *ELF = dyn_cast<ELF64LEObjectFile>(&Obj)) 1763*e8d8bef9SDimitry Andric return readSymbolVersionsELF(ELF->getELFFile(), Obj.getFileName(), Symbols); 1764*e8d8bef9SDimitry Andric return readSymbolVersionsELF(cast<ELF64BEObjectFile>(&Obj)->getELFFile(), 1765*e8d8bef9SDimitry Andric Obj.getFileName(), Symbols); 1766*e8d8bef9SDimitry Andric } 1767*e8d8bef9SDimitry Andric 1768*e8d8bef9SDimitry Andric static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, 1769*e8d8bef9SDimitry Andric StringRef ArchiveName = {}, 1770*e8d8bef9SDimitry Andric StringRef ArchitectureName = {}) { 1771*e8d8bef9SDimitry Andric auto Symbols = Obj.symbols(); 1772*e8d8bef9SDimitry Andric std::vector<SymbolVersion> SymbolVersions; 1773*e8d8bef9SDimitry Andric if (DynamicSyms) { 1774*e8d8bef9SDimitry Andric const auto *E = dyn_cast<ELFObjectFileBase>(&Obj); 1775*e8d8bef9SDimitry Andric if (!E) { 1776*e8d8bef9SDimitry Andric error("File format has no dynamic symbol table", Obj.getFileName()); 1777*e8d8bef9SDimitry Andric return; 1778*e8d8bef9SDimitry Andric } 1779*e8d8bef9SDimitry Andric Symbols = E->getDynamicSymbolIterators(); 1780*e8d8bef9SDimitry Andric 1781*e8d8bef9SDimitry Andric if (Expected<std::vector<SymbolVersion>> VersionsOrErr = 1782*e8d8bef9SDimitry Andric readSymbolVersionsELF(*E, Symbols)) 1783*e8d8bef9SDimitry Andric SymbolVersions = std::move(*VersionsOrErr); 1784*e8d8bef9SDimitry Andric else 1785*e8d8bef9SDimitry Andric WithColor::warning(errs(), ToolName) 1786*e8d8bef9SDimitry Andric << "unable to read symbol versions: " 1787*e8d8bef9SDimitry Andric << toString(VersionsOrErr.takeError()) << "\n"; 1788*e8d8bef9SDimitry Andric } 1789*e8d8bef9SDimitry Andric 1790*e8d8bef9SDimitry Andric // If a "-s segname sectname" option was specified and this is a Mach-O 1791*e8d8bef9SDimitry Andric // file get the section number for that section in this object file. 1792*e8d8bef9SDimitry Andric unsigned int Nsect = 0; 1793*e8d8bef9SDimitry Andric MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); 1794*e8d8bef9SDimitry Andric if (!SegSect.empty() && MachO) { 1795*e8d8bef9SDimitry Andric Nsect = getNsectForSegSect(MachO); 1796*e8d8bef9SDimitry Andric // If this section is not in the object file no symbols are printed. 1797*e8d8bef9SDimitry Andric if (Nsect == 0) 1798*e8d8bef9SDimitry Andric return; 1799*e8d8bef9SDimitry Andric } 1800*e8d8bef9SDimitry Andric if (!(MachO && DyldInfoOnly)) { 1801*e8d8bef9SDimitry Andric size_t I = -1; 1802*e8d8bef9SDimitry Andric for (BasicSymbolRef Sym : Symbols) { 1803*e8d8bef9SDimitry Andric ++I; 1804*e8d8bef9SDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 1805*e8d8bef9SDimitry Andric if (!SymFlagsOrErr) { 1806*e8d8bef9SDimitry Andric error(SymFlagsOrErr.takeError(), Obj.getFileName()); 1807*e8d8bef9SDimitry Andric return; 1808*e8d8bef9SDimitry Andric } 1809*e8d8bef9SDimitry Andric if (!DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) 1810*e8d8bef9SDimitry Andric continue; 1811*e8d8bef9SDimitry Andric if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect)) 1812*e8d8bef9SDimitry Andric continue; 1813*e8d8bef9SDimitry Andric // If a "-s segname sectname" option was specified and this is a Mach-O 1814*e8d8bef9SDimitry Andric // file and this section appears in this file, Nsect will be non-zero then 1815*e8d8bef9SDimitry Andric // see if this symbol is a symbol from that section and if not skip it. 1816*e8d8bef9SDimitry Andric if (Nsect && Nsect != getNsectInMachO(*MachO, Sym)) 1817*e8d8bef9SDimitry Andric continue; 1818*e8d8bef9SDimitry Andric NMSymbol S = {}; 1819*e8d8bef9SDimitry Andric S.Size = 0; 1820*e8d8bef9SDimitry Andric S.Address = 0; 1821*e8d8bef9SDimitry Andric if (isa<ELFObjectFileBase>(&Obj)) 1822*e8d8bef9SDimitry Andric S.Size = ELFSymbolRef(Sym).getSize(); 1823*e8d8bef9SDimitry Andric if (PrintAddress && isa<ObjectFile>(Obj)) { 1824*e8d8bef9SDimitry Andric SymbolRef SymRef(Sym); 1825*e8d8bef9SDimitry Andric Expected<uint64_t> AddressOrErr = SymRef.getAddress(); 1826*e8d8bef9SDimitry Andric if (!AddressOrErr) { 1827*e8d8bef9SDimitry Andric consumeError(AddressOrErr.takeError()); 1828*e8d8bef9SDimitry Andric break; 1829*e8d8bef9SDimitry Andric } 1830*e8d8bef9SDimitry Andric S.Address = *AddressOrErr; 1831*e8d8bef9SDimitry Andric } 1832*e8d8bef9SDimitry Andric S.TypeName = getNMTypeName(Obj, Sym); 1833*e8d8bef9SDimitry Andric S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName); 1834*e8d8bef9SDimitry Andric 1835*e8d8bef9SDimitry Andric raw_string_ostream OS(S.Name); 1836*e8d8bef9SDimitry Andric if (Error E = Sym.printName(OS)) { 1837*e8d8bef9SDimitry Andric if (MachO) { 1838*e8d8bef9SDimitry Andric OS << "bad string index"; 1839*e8d8bef9SDimitry Andric consumeError(std::move(E)); 1840*e8d8bef9SDimitry Andric } else 1841*e8d8bef9SDimitry Andric error(std::move(E), Obj.getFileName()); 1842*e8d8bef9SDimitry Andric } 1843*e8d8bef9SDimitry Andric if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty()) 1844*e8d8bef9SDimitry Andric S.Name += 1845*e8d8bef9SDimitry Andric (SymbolVersions[I].IsDefault ? "@@" : "@") + SymbolVersions[I].Name; 1846*e8d8bef9SDimitry Andric 1847*e8d8bef9SDimitry Andric S.Sym = Sym; 1848*e8d8bef9SDimitry Andric SymbolList.push_back(S); 1849*e8d8bef9SDimitry Andric } 1850*e8d8bef9SDimitry Andric } 1851*e8d8bef9SDimitry Andric 1852*e8d8bef9SDimitry Andric // If this is a Mach-O file where the nlist symbol table is out of sync 1853*e8d8bef9SDimitry Andric // with the dyld export trie then look through exports and fake up symbols 1854*e8d8bef9SDimitry Andric // for the ones that are missing (also done with the -add-dyldinfo flag). 1855*e8d8bef9SDimitry Andric // This is needed if strip(1) -T is run on a binary containing swift 1856*e8d8bef9SDimitry Andric // language symbols for example. The option -only-dyldinfo will fake up 1857*e8d8bef9SDimitry Andric // all symbols from the dyld export trie as well as the bind info. 1858*e8d8bef9SDimitry Andric if (MachO && !NoDyldInfo) 1859*e8d8bef9SDimitry Andric dumpSymbolsFromDLInfoMachO(*MachO); 1860*e8d8bef9SDimitry Andric 18610b57cec5SDimitry Andric CurrentFilename = Obj.getFileName(); 18625ffd83dbSDimitry Andric 18635ffd83dbSDimitry Andric if (Symbols.empty() && SymbolList.empty()) { 18645ffd83dbSDimitry Andric writeFileName(errs(), ArchiveName, ArchitectureName); 18655ffd83dbSDimitry Andric errs() << "no symbols\n"; 18665ffd83dbSDimitry Andric } 18675ffd83dbSDimitry Andric 18680b57cec5SDimitry Andric sortAndPrintSymbolList(Obj, printName, ArchiveName, ArchitectureName); 18690b57cec5SDimitry Andric } 18700b57cec5SDimitry Andric 18710b57cec5SDimitry Andric // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file 18720b57cec5SDimitry Andric // and if it is and there is a list of architecture flags is specified then 18730b57cec5SDimitry Andric // check to make sure this Mach-O file is one of those architectures or all 18740b57cec5SDimitry Andric // architectures was specificed. If not then an error is generated and this 18750b57cec5SDimitry Andric // routine returns false. Else it returns true. 18760b57cec5SDimitry Andric static bool checkMachOAndArchFlags(SymbolicFile *O, std::string &Filename) { 18770b57cec5SDimitry Andric auto *MachO = dyn_cast<MachOObjectFile>(O); 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric if (!MachO || ArchAll || ArchFlags.empty()) 18800b57cec5SDimitry Andric return true; 18810b57cec5SDimitry Andric 18820b57cec5SDimitry Andric MachO::mach_header H; 18830b57cec5SDimitry Andric MachO::mach_header_64 H_64; 18840b57cec5SDimitry Andric Triple T; 18850b57cec5SDimitry Andric const char *McpuDefault, *ArchFlag; 18860b57cec5SDimitry Andric if (MachO->is64Bit()) { 18870b57cec5SDimitry Andric H_64 = MachO->MachOObjectFile::getHeader64(); 18880b57cec5SDimitry Andric T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 18890b57cec5SDimitry Andric &McpuDefault, &ArchFlag); 18900b57cec5SDimitry Andric } else { 18910b57cec5SDimitry Andric H = MachO->MachOObjectFile::getHeader(); 18920b57cec5SDimitry Andric T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 18930b57cec5SDimitry Andric &McpuDefault, &ArchFlag); 18940b57cec5SDimitry Andric } 18950b57cec5SDimitry Andric const std::string ArchFlagName(ArchFlag); 1896*e8d8bef9SDimitry Andric if (!llvm::is_contained(ArchFlags, ArchFlagName)) { 18970b57cec5SDimitry Andric error("No architecture specified", Filename); 18980b57cec5SDimitry Andric return false; 18990b57cec5SDimitry Andric } 19000b57cec5SDimitry Andric return true; 19010b57cec5SDimitry Andric } 19020b57cec5SDimitry Andric 19030b57cec5SDimitry Andric static void dumpSymbolNamesFromFile(std::string &Filename) { 19040b57cec5SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 19050b57cec5SDimitry Andric MemoryBuffer::getFileOrSTDIN(Filename); 19060b57cec5SDimitry Andric if (error(BufferOrErr.getError(), Filename)) 19070b57cec5SDimitry Andric return; 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric LLVMContext Context; 19100b57cec5SDimitry Andric LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context; 19110b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> BinaryOrErr = 19120b57cec5SDimitry Andric createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr); 19130b57cec5SDimitry Andric if (!BinaryOrErr) { 19140b57cec5SDimitry Andric error(BinaryOrErr.takeError(), Filename); 19150b57cec5SDimitry Andric return; 19160b57cec5SDimitry Andric } 19170b57cec5SDimitry Andric Binary &Bin = *BinaryOrErr.get(); 19180b57cec5SDimitry Andric 19190b57cec5SDimitry Andric if (Archive *A = dyn_cast<Archive>(&Bin)) { 19200b57cec5SDimitry Andric if (ArchiveMap) { 19210b57cec5SDimitry Andric Archive::symbol_iterator I = A->symbol_begin(); 19220b57cec5SDimitry Andric Archive::symbol_iterator E = A->symbol_end(); 19230b57cec5SDimitry Andric if (I != E) { 19240b57cec5SDimitry Andric outs() << "Archive map\n"; 19250b57cec5SDimitry Andric for (; I != E; ++I) { 19260b57cec5SDimitry Andric Expected<Archive::Child> C = I->getMember(); 19270b57cec5SDimitry Andric if (!C) { 19280b57cec5SDimitry Andric error(C.takeError(), Filename); 19290b57cec5SDimitry Andric break; 19300b57cec5SDimitry Andric } 19310b57cec5SDimitry Andric Expected<StringRef> FileNameOrErr = C->getName(); 19320b57cec5SDimitry Andric if (!FileNameOrErr) { 19330b57cec5SDimitry Andric error(FileNameOrErr.takeError(), Filename); 19340b57cec5SDimitry Andric break; 19350b57cec5SDimitry Andric } 19360b57cec5SDimitry Andric StringRef SymName = I->getName(); 19370b57cec5SDimitry Andric outs() << SymName << " in " << FileNameOrErr.get() << "\n"; 19380b57cec5SDimitry Andric } 19390b57cec5SDimitry Andric outs() << "\n"; 19400b57cec5SDimitry Andric } 19410b57cec5SDimitry Andric } 19420b57cec5SDimitry Andric 19430b57cec5SDimitry Andric { 19440b57cec5SDimitry Andric Error Err = Error::success(); 19450b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 19460b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 19470b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 19480b57cec5SDimitry Andric if (!ChildOrErr) { 19490b57cec5SDimitry Andric if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 19500b57cec5SDimitry Andric error(std::move(E), Filename, C); 19510b57cec5SDimitry Andric continue; 19520b57cec5SDimitry Andric } 19530b57cec5SDimitry Andric if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 19540b57cec5SDimitry Andric if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { 19550b57cec5SDimitry Andric WithColor::warning(errs(), ToolName) 19560b57cec5SDimitry Andric << "sizes with -print-size for Mach-O files are always zero.\n"; 19570b57cec5SDimitry Andric MachOPrintSizeWarning = true; 19580b57cec5SDimitry Andric } 19590b57cec5SDimitry Andric if (!checkMachOAndArchFlags(O, Filename)) 19600b57cec5SDimitry Andric return; 19610b57cec5SDimitry Andric if (!PrintFileName) { 19620b57cec5SDimitry Andric outs() << "\n"; 19630b57cec5SDimitry Andric if (isa<MachOObjectFile>(O)) { 19640b57cec5SDimitry Andric outs() << Filename << "(" << O->getFileName() << ")"; 19650b57cec5SDimitry Andric } else 19660b57cec5SDimitry Andric outs() << O->getFileName(); 19670b57cec5SDimitry Andric outs() << ":\n"; 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric dumpSymbolNamesFromObject(*O, false, Filename); 19700b57cec5SDimitry Andric } 19710b57cec5SDimitry Andric } 19720b57cec5SDimitry Andric if (Err) 19730b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 19740b57cec5SDimitry Andric } 19750b57cec5SDimitry Andric return; 19760b57cec5SDimitry Andric } 19770b57cec5SDimitry Andric if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) { 19780b57cec5SDimitry Andric // If we have a list of architecture flags specified dump only those. 19790b57cec5SDimitry Andric if (!ArchAll && !ArchFlags.empty()) { 19800b57cec5SDimitry Andric // Look for a slice in the universal binary that matches each ArchFlag. 19810b57cec5SDimitry Andric bool ArchFound; 19820b57cec5SDimitry Andric for (unsigned i = 0; i < ArchFlags.size(); ++i) { 19830b57cec5SDimitry Andric ArchFound = false; 19840b57cec5SDimitry Andric for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 19850b57cec5SDimitry Andric E = UB->end_objects(); 19860b57cec5SDimitry Andric I != E; ++I) { 19870b57cec5SDimitry Andric if (ArchFlags[i] == I->getArchFlagName()) { 19880b57cec5SDimitry Andric ArchFound = true; 19890b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = 19900b57cec5SDimitry Andric I->getAsObjectFile(); 19910b57cec5SDimitry Andric std::string ArchiveName; 19920b57cec5SDimitry Andric std::string ArchitectureName; 19930b57cec5SDimitry Andric ArchiveName.clear(); 19940b57cec5SDimitry Andric ArchitectureName.clear(); 19950b57cec5SDimitry Andric if (ObjOrErr) { 19960b57cec5SDimitry Andric ObjectFile &Obj = *ObjOrErr.get(); 19970b57cec5SDimitry Andric if (ArchFlags.size() > 1) { 19980b57cec5SDimitry Andric if (PrintFileName) 19990b57cec5SDimitry Andric ArchitectureName = I->getArchFlagName(); 20000b57cec5SDimitry Andric else 20010b57cec5SDimitry Andric outs() << "\n" << Obj.getFileName() << " (for architecture " 20020b57cec5SDimitry Andric << I->getArchFlagName() << ")" 20030b57cec5SDimitry Andric << ":\n"; 20040b57cec5SDimitry Andric } 20050b57cec5SDimitry Andric dumpSymbolNamesFromObject(Obj, false, ArchiveName, 20060b57cec5SDimitry Andric ArchitectureName); 20070b57cec5SDimitry Andric } else if (auto E = isNotObjectErrorInvalidFileType( 20080b57cec5SDimitry Andric ObjOrErr.takeError())) { 20090b57cec5SDimitry Andric error(std::move(E), Filename, ArchFlags.size() > 1 ? 20100b57cec5SDimitry Andric StringRef(I->getArchFlagName()) : StringRef()); 20110b57cec5SDimitry Andric continue; 20120b57cec5SDimitry Andric } else if (Expected<std::unique_ptr<Archive>> AOrErr = 20130b57cec5SDimitry Andric I->getAsArchive()) { 20140b57cec5SDimitry Andric std::unique_ptr<Archive> &A = *AOrErr; 20150b57cec5SDimitry Andric Error Err = Error::success(); 20160b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 20170b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 20180b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 20190b57cec5SDimitry Andric if (!ChildOrErr) { 20200b57cec5SDimitry Andric if (auto E = isNotObjectErrorInvalidFileType( 20210b57cec5SDimitry Andric ChildOrErr.takeError())) { 20220b57cec5SDimitry Andric error(std::move(E), Filename, C, ArchFlags.size() > 1 ? 20230b57cec5SDimitry Andric StringRef(I->getArchFlagName()) : StringRef()); 20240b57cec5SDimitry Andric } 20250b57cec5SDimitry Andric continue; 20260b57cec5SDimitry Andric } 20270b57cec5SDimitry Andric if (SymbolicFile *O = 20280b57cec5SDimitry Andric dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 20290b57cec5SDimitry Andric if (PrintFileName) { 20305ffd83dbSDimitry Andric ArchiveName = std::string(A->getFileName()); 20310b57cec5SDimitry Andric if (ArchFlags.size() > 1) 20320b57cec5SDimitry Andric ArchitectureName = I->getArchFlagName(); 20330b57cec5SDimitry Andric } else { 20340b57cec5SDimitry Andric outs() << "\n" << A->getFileName(); 20350b57cec5SDimitry Andric outs() << "(" << O->getFileName() << ")"; 20360b57cec5SDimitry Andric if (ArchFlags.size() > 1) { 20370b57cec5SDimitry Andric outs() << " (for architecture " << I->getArchFlagName() 20380b57cec5SDimitry Andric << ")"; 20390b57cec5SDimitry Andric } 20400b57cec5SDimitry Andric outs() << ":\n"; 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric dumpSymbolNamesFromObject(*O, false, ArchiveName, 20430b57cec5SDimitry Andric ArchitectureName); 20440b57cec5SDimitry Andric } 20450b57cec5SDimitry Andric } 20460b57cec5SDimitry Andric if (Err) 20470b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 20480b57cec5SDimitry Andric } else { 20490b57cec5SDimitry Andric consumeError(AOrErr.takeError()); 20500b57cec5SDimitry Andric error(Filename + " for architecture " + 20510b57cec5SDimitry Andric StringRef(I->getArchFlagName()) + 20520b57cec5SDimitry Andric " is not a Mach-O file or an archive file", 20530b57cec5SDimitry Andric "Mach-O universal file"); 20540b57cec5SDimitry Andric } 20550b57cec5SDimitry Andric } 20560b57cec5SDimitry Andric } 20570b57cec5SDimitry Andric if (!ArchFound) { 20580b57cec5SDimitry Andric error(ArchFlags[i], 20590b57cec5SDimitry Andric "file: " + Filename + " does not contain architecture"); 20600b57cec5SDimitry Andric return; 20610b57cec5SDimitry Andric } 20620b57cec5SDimitry Andric } 20630b57cec5SDimitry Andric return; 20640b57cec5SDimitry Andric } 20650b57cec5SDimitry Andric // No architecture flags were specified so if this contains a slice that 20660b57cec5SDimitry Andric // matches the host architecture dump only that. 20670b57cec5SDimitry Andric if (!ArchAll) { 20680b57cec5SDimitry Andric Triple HostTriple = MachOObjectFile::getHostArch(); 20690b57cec5SDimitry Andric StringRef HostArchName = HostTriple.getArchName(); 20700b57cec5SDimitry Andric for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 20710b57cec5SDimitry Andric E = UB->end_objects(); 20720b57cec5SDimitry Andric I != E; ++I) { 20730b57cec5SDimitry Andric if (HostArchName == I->getArchFlagName()) { 20740b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 20750b57cec5SDimitry Andric std::string ArchiveName; 20760b57cec5SDimitry Andric if (ObjOrErr) { 20770b57cec5SDimitry Andric ObjectFile &Obj = *ObjOrErr.get(); 20780b57cec5SDimitry Andric dumpSymbolNamesFromObject(Obj, false); 20790b57cec5SDimitry Andric } else if (auto E = isNotObjectErrorInvalidFileType( 20800b57cec5SDimitry Andric ObjOrErr.takeError())) { 20810b57cec5SDimitry Andric error(std::move(E), Filename); 20820b57cec5SDimitry Andric return; 20830b57cec5SDimitry Andric } else if (Expected<std::unique_ptr<Archive>> AOrErr = 20840b57cec5SDimitry Andric I->getAsArchive()) { 20850b57cec5SDimitry Andric std::unique_ptr<Archive> &A = *AOrErr; 20860b57cec5SDimitry Andric Error Err = Error::success(); 20870b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 20880b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 20890b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 20900b57cec5SDimitry Andric if (!ChildOrErr) { 20910b57cec5SDimitry Andric if (auto E = isNotObjectErrorInvalidFileType( 20920b57cec5SDimitry Andric ChildOrErr.takeError())) 20930b57cec5SDimitry Andric error(std::move(E), Filename, C); 20940b57cec5SDimitry Andric continue; 20950b57cec5SDimitry Andric } 20960b57cec5SDimitry Andric if (SymbolicFile *O = 20970b57cec5SDimitry Andric dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 20980b57cec5SDimitry Andric if (PrintFileName) 20995ffd83dbSDimitry Andric ArchiveName = std::string(A->getFileName()); 21000b57cec5SDimitry Andric else 21010b57cec5SDimitry Andric outs() << "\n" << A->getFileName() << "(" << O->getFileName() 21020b57cec5SDimitry Andric << ")" 21030b57cec5SDimitry Andric << ":\n"; 21040b57cec5SDimitry Andric dumpSymbolNamesFromObject(*O, false, ArchiveName); 21050b57cec5SDimitry Andric } 21060b57cec5SDimitry Andric } 21070b57cec5SDimitry Andric if (Err) 21080b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 21090b57cec5SDimitry Andric } else { 21100b57cec5SDimitry Andric consumeError(AOrErr.takeError()); 21110b57cec5SDimitry Andric error(Filename + " for architecture " + 21120b57cec5SDimitry Andric StringRef(I->getArchFlagName()) + 21130b57cec5SDimitry Andric " is not a Mach-O file or an archive file", 21140b57cec5SDimitry Andric "Mach-O universal file"); 21150b57cec5SDimitry Andric } 21160b57cec5SDimitry Andric return; 21170b57cec5SDimitry Andric } 21180b57cec5SDimitry Andric } 21190b57cec5SDimitry Andric } 21200b57cec5SDimitry Andric // Either all architectures have been specified or none have been specified 21210b57cec5SDimitry Andric // and this does not contain the host architecture so dump all the slices. 21220b57cec5SDimitry Andric bool moreThanOneArch = UB->getNumberOfObjects() > 1; 21230b57cec5SDimitry Andric for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) { 21240b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile(); 21250b57cec5SDimitry Andric std::string ArchiveName; 21260b57cec5SDimitry Andric std::string ArchitectureName; 21270b57cec5SDimitry Andric ArchiveName.clear(); 21280b57cec5SDimitry Andric ArchitectureName.clear(); 21290b57cec5SDimitry Andric if (ObjOrErr) { 21300b57cec5SDimitry Andric ObjectFile &Obj = *ObjOrErr.get(); 21310b57cec5SDimitry Andric if (PrintFileName) { 21320b57cec5SDimitry Andric if (isa<MachOObjectFile>(Obj) && moreThanOneArch) 21330b57cec5SDimitry Andric ArchitectureName = O.getArchFlagName(); 21340b57cec5SDimitry Andric } else { 21350b57cec5SDimitry Andric if (moreThanOneArch) 21360b57cec5SDimitry Andric outs() << "\n"; 21370b57cec5SDimitry Andric outs() << Obj.getFileName(); 21380b57cec5SDimitry Andric if (isa<MachOObjectFile>(Obj) && moreThanOneArch) 21390b57cec5SDimitry Andric outs() << " (for architecture " << O.getArchFlagName() << ")"; 21400b57cec5SDimitry Andric outs() << ":\n"; 21410b57cec5SDimitry Andric } 21420b57cec5SDimitry Andric dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName); 21430b57cec5SDimitry Andric } else if (auto E = isNotObjectErrorInvalidFileType( 21440b57cec5SDimitry Andric ObjOrErr.takeError())) { 21450b57cec5SDimitry Andric error(std::move(E), Filename, moreThanOneArch ? 21460b57cec5SDimitry Andric StringRef(O.getArchFlagName()) : StringRef()); 21470b57cec5SDimitry Andric continue; 21480b57cec5SDimitry Andric } else if (Expected<std::unique_ptr<Archive>> AOrErr = 21490b57cec5SDimitry Andric O.getAsArchive()) { 21500b57cec5SDimitry Andric std::unique_ptr<Archive> &A = *AOrErr; 21510b57cec5SDimitry Andric Error Err = Error::success(); 21520b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 21530b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 21540b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 21550b57cec5SDimitry Andric if (!ChildOrErr) { 21560b57cec5SDimitry Andric if (auto E = isNotObjectErrorInvalidFileType( 21570b57cec5SDimitry Andric ChildOrErr.takeError())) 21580b57cec5SDimitry Andric error(std::move(E), Filename, C, moreThanOneArch ? 21590b57cec5SDimitry Andric StringRef(ArchitectureName) : StringRef()); 21600b57cec5SDimitry Andric continue; 21610b57cec5SDimitry Andric } 21620b57cec5SDimitry Andric if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 21630b57cec5SDimitry Andric if (PrintFileName) { 21645ffd83dbSDimitry Andric ArchiveName = std::string(A->getFileName()); 21650b57cec5SDimitry Andric if (isa<MachOObjectFile>(F) && moreThanOneArch) 21660b57cec5SDimitry Andric ArchitectureName = O.getArchFlagName(); 21670b57cec5SDimitry Andric } else { 21680b57cec5SDimitry Andric outs() << "\n" << A->getFileName(); 21690b57cec5SDimitry Andric if (isa<MachOObjectFile>(F)) { 21700b57cec5SDimitry Andric outs() << "(" << F->getFileName() << ")"; 21710b57cec5SDimitry Andric if (moreThanOneArch) 21720b57cec5SDimitry Andric outs() << " (for architecture " << O.getArchFlagName() 21730b57cec5SDimitry Andric << ")"; 21740b57cec5SDimitry Andric } else 21750b57cec5SDimitry Andric outs() << ":" << F->getFileName(); 21760b57cec5SDimitry Andric outs() << ":\n"; 21770b57cec5SDimitry Andric } 21780b57cec5SDimitry Andric dumpSymbolNamesFromObject(*F, false, ArchiveName, ArchitectureName); 21790b57cec5SDimitry Andric } 21800b57cec5SDimitry Andric } 21810b57cec5SDimitry Andric if (Err) 21820b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 21830b57cec5SDimitry Andric } else { 21840b57cec5SDimitry Andric consumeError(AOrErr.takeError()); 21850b57cec5SDimitry Andric error(Filename + " for architecture " + 21860b57cec5SDimitry Andric StringRef(O.getArchFlagName()) + 21870b57cec5SDimitry Andric " is not a Mach-O file or an archive file", 21880b57cec5SDimitry Andric "Mach-O universal file"); 21890b57cec5SDimitry Andric } 21900b57cec5SDimitry Andric } 21910b57cec5SDimitry Andric return; 21920b57cec5SDimitry Andric } 21935ffd83dbSDimitry Andric 21945ffd83dbSDimitry Andric if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin)) { 21955ffd83dbSDimitry Andric for (const TapiUniversal::ObjectForArch &I : TU->objects()) { 21965ffd83dbSDimitry Andric StringRef ArchName = I.getArchFlagName(); 21975ffd83dbSDimitry Andric const bool ShowArch = 2198*e8d8bef9SDimitry Andric ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName); 21995ffd83dbSDimitry Andric if (!ShowArch) 22005ffd83dbSDimitry Andric continue; 22015ffd83dbSDimitry Andric if (!AddInlinedInfo && !I.isTopLevelLib()) 22025ffd83dbSDimitry Andric continue; 22035ffd83dbSDimitry Andric if (auto ObjOrErr = I.getAsObjectFile()) { 22045ffd83dbSDimitry Andric outs() << "\n" 22055ffd83dbSDimitry Andric << I.getInstallName() << " (for architecture " << ArchName << ")" 22065ffd83dbSDimitry Andric << ":\n"; 22075ffd83dbSDimitry Andric dumpSymbolNamesFromObject(*ObjOrErr.get(), false, {}, ArchName); 22085ffd83dbSDimitry Andric } else if (Error E = 22095ffd83dbSDimitry Andric isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 22105ffd83dbSDimitry Andric error(std::move(E), Filename, ArchName); 22115ffd83dbSDimitry Andric } 22125ffd83dbSDimitry Andric } 22135ffd83dbSDimitry Andric 22145ffd83dbSDimitry Andric return; 22155ffd83dbSDimitry Andric } 22165ffd83dbSDimitry Andric 22170b57cec5SDimitry Andric if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) { 22180b57cec5SDimitry Andric if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { 22190b57cec5SDimitry Andric WithColor::warning(errs(), ToolName) 22200b57cec5SDimitry Andric << "sizes with --print-size for Mach-O files are always zero.\n"; 22210b57cec5SDimitry Andric MachOPrintSizeWarning = true; 22220b57cec5SDimitry Andric } 22230b57cec5SDimitry Andric if (!checkMachOAndArchFlags(O, Filename)) 22240b57cec5SDimitry Andric return; 22250b57cec5SDimitry Andric dumpSymbolNamesFromObject(*O, true); 22260b57cec5SDimitry Andric } 22270b57cec5SDimitry Andric } 22280b57cec5SDimitry Andric 22290b57cec5SDimitry Andric int main(int argc, char **argv) { 22300b57cec5SDimitry Andric InitLLVM X(argc, argv); 22310b57cec5SDimitry Andric cl::HideUnrelatedOptions(NMCat); 22320b57cec5SDimitry Andric cl::ParseCommandLineOptions(argc, argv, "llvm symbol table dumper\n"); 22330b57cec5SDimitry Andric 22340b57cec5SDimitry Andric // llvm-nm only reads binary files. 22350b57cec5SDimitry Andric if (error(sys::ChangeStdinToBinary())) 22360b57cec5SDimitry Andric return 1; 22370b57cec5SDimitry Andric 22380b57cec5SDimitry Andric // These calls are needed so that we can read bitcode correctly. 22390b57cec5SDimitry Andric llvm::InitializeAllTargetInfos(); 22400b57cec5SDimitry Andric llvm::InitializeAllTargetMCs(); 22410b57cec5SDimitry Andric llvm::InitializeAllAsmParsers(); 22420b57cec5SDimitry Andric 22430b57cec5SDimitry Andric ToolName = argv[0]; 22440b57cec5SDimitry Andric if (BSDFormat) 22450b57cec5SDimitry Andric OutputFormat = bsd; 22460b57cec5SDimitry Andric if (POSIXFormat) 22470b57cec5SDimitry Andric OutputFormat = posix; 22480b57cec5SDimitry Andric if (DarwinFormat) 22490b57cec5SDimitry Andric OutputFormat = darwin; 22500b57cec5SDimitry Andric 22510b57cec5SDimitry Andric // The relative order of these is important. If you pass --size-sort it should 22520b57cec5SDimitry Andric // only print out the size. However, if you pass -S --size-sort, it should 22530b57cec5SDimitry Andric // print out both the size and address. 22540b57cec5SDimitry Andric if (SizeSort && !PrintSize) 22550b57cec5SDimitry Andric PrintAddress = false; 22560b57cec5SDimitry Andric if (OutputFormat == sysv || SizeSort) 22570b57cec5SDimitry Andric PrintSize = true; 22580b57cec5SDimitry Andric if (InputFilenames.empty()) 22590b57cec5SDimitry Andric InputFilenames.push_back("a.out"); 22600b57cec5SDimitry Andric if (InputFilenames.size() > 1) 22610b57cec5SDimitry Andric MultipleFiles = true; 22620b57cec5SDimitry Andric 22630b57cec5SDimitry Andric // If both --demangle and --no-demangle are specified then pick the last one. 22640b57cec5SDimitry Andric if (NoDemangle.getPosition() > Demangle.getPosition()) 22650b57cec5SDimitry Andric Demangle = !NoDemangle; 22660b57cec5SDimitry Andric 22670b57cec5SDimitry Andric for (unsigned i = 0; i < ArchFlags.size(); ++i) { 22680b57cec5SDimitry Andric if (ArchFlags[i] == "all") { 22690b57cec5SDimitry Andric ArchAll = true; 22700b57cec5SDimitry Andric } else { 22710b57cec5SDimitry Andric if (!MachOObjectFile::isValidArch(ArchFlags[i])) 22720b57cec5SDimitry Andric error("Unknown architecture named '" + ArchFlags[i] + "'", 22730b57cec5SDimitry Andric "for the --arch option"); 22740b57cec5SDimitry Andric } 22750b57cec5SDimitry Andric } 22760b57cec5SDimitry Andric 22770b57cec5SDimitry Andric if (!SegSect.empty() && SegSect.size() != 2) 22780b57cec5SDimitry Andric error("bad number of arguments (must be two arguments)", 22790b57cec5SDimitry Andric "for the -s option"); 22800b57cec5SDimitry Andric 22810b57cec5SDimitry Andric if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly)) 22820b57cec5SDimitry Andric error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only"); 22830b57cec5SDimitry Andric 22840b57cec5SDimitry Andric llvm::for_each(InputFilenames, dumpSymbolNamesFromFile); 22850b57cec5SDimitry Andric 22860b57cec5SDimitry Andric if (HadError) 22870b57cec5SDimitry Andric return 1; 22880b57cec5SDimitry Andric } 2289