xref: /freebsd/contrib/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
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"
20*5f757f3fSDimitry Andric #include "llvm/BinaryFormat/MachO.h"
2181ad6265SDimitry Andric #include "llvm/BinaryFormat/XCOFF.h"
22*5f757f3fSDimitry Andric #include "llvm/DebugInfo/Symbolize/Symbolize.h"
230b57cec5SDimitry Andric #include "llvm/Demangle/Demangle.h"
240b57cec5SDimitry Andric #include "llvm/IR/Function.h"
250b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
260b57cec5SDimitry Andric #include "llvm/Object/Archive.h"
270b57cec5SDimitry Andric #include "llvm/Object/COFF.h"
280b57cec5SDimitry Andric #include "llvm/Object/COFFImportFile.h"
290b57cec5SDimitry Andric #include "llvm/Object/ELFObjectFile.h"
300b57cec5SDimitry Andric #include "llvm/Object/IRObjectFile.h"
310b57cec5SDimitry Andric #include "llvm/Object/MachO.h"
320b57cec5SDimitry Andric #include "llvm/Object/MachOUniversal.h"
330b57cec5SDimitry Andric #include "llvm/Object/ObjectFile.h"
34*5f757f3fSDimitry Andric #include "llvm/Object/SymbolicFile.h"
355ffd83dbSDimitry Andric #include "llvm/Object/TapiFile.h"
365ffd83dbSDimitry Andric #include "llvm/Object/TapiUniversal.h"
370b57cec5SDimitry Andric #include "llvm/Object/Wasm.h"
3804eeddc0SDimitry Andric #include "llvm/Object/XCOFFObjectFile.h"
39fe6060f1SDimitry Andric #include "llvm/Option/Arg.h"
40fe6060f1SDimitry Andric #include "llvm/Option/ArgList.h"
41fe6060f1SDimitry Andric #include "llvm/Option/Option.h"
420b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
430b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
440b57cec5SDimitry Andric #include "llvm/Support/Format.h"
450b57cec5SDimitry Andric #include "llvm/Support/InitLLVM.h"
4606c3fb27SDimitry Andric #include "llvm/Support/LLVMDriver.h"
470b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
480b57cec5SDimitry Andric #include "llvm/Support/Program.h"
490b57cec5SDimitry Andric #include "llvm/Support/Signals.h"
500b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h"
510b57cec5SDimitry Andric #include "llvm/Support/WithColor.h"
520b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
5306c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
5406c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h"
550b57cec5SDimitry Andric #include <vector>
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric using namespace llvm;
580b57cec5SDimitry Andric using namespace object;
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric namespace {
61fe6060f1SDimitry Andric using namespace llvm::opt; // for HelpHidden in Opts.inc
62fe6060f1SDimitry Andric enum ID {
63fe6060f1SDimitry Andric   OPT_INVALID = 0, // This is not an option ID.
64*5f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
65fe6060f1SDimitry Andric #include "Opts.inc"
66fe6060f1SDimitry Andric #undef OPTION
67fe6060f1SDimitry Andric };
680b57cec5SDimitry Andric 
69bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE)                                                    \
70bdd1243dSDimitry Andric   static constexpr StringLiteral NAME##_init[] = VALUE;                        \
71bdd1243dSDimitry Andric   static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
72bdd1243dSDimitry Andric                                                 std::size(NAME##_init) - 1);
73fe6060f1SDimitry Andric #include "Opts.inc"
74fe6060f1SDimitry Andric #undef PREFIX
750b57cec5SDimitry Andric 
76bdd1243dSDimitry Andric static constexpr opt::OptTable::Info InfoTable[] = {
77*5f757f3fSDimitry Andric #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
78fe6060f1SDimitry Andric #include "Opts.inc"
79fe6060f1SDimitry Andric #undef OPTION
80fe6060f1SDimitry Andric };
810b57cec5SDimitry Andric 
82bdd1243dSDimitry Andric class NmOptTable : public opt::GenericOptTable {
83fe6060f1SDimitry Andric public:
84bdd1243dSDimitry Andric   NmOptTable() : opt::GenericOptTable(InfoTable) {
85bdd1243dSDimitry Andric     setGroupedShortOptions(true);
86bdd1243dSDimitry Andric   }
87fe6060f1SDimitry Andric };
880b57cec5SDimitry Andric 
89fe6060f1SDimitry Andric enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
9081ad6265SDimitry Andric enum class BitModeTy { Bit32, Bit64, Bit32_64, Any };
91fe6060f1SDimitry Andric } // namespace
920b57cec5SDimitry Andric 
93fe6060f1SDimitry Andric static bool ArchiveMap;
9481ad6265SDimitry Andric static BitModeTy BitMode;
95fe6060f1SDimitry Andric static bool DebugSyms;
96fe6060f1SDimitry Andric static bool DefinedOnly;
97fe6060f1SDimitry Andric static bool Demangle;
98fe6060f1SDimitry Andric static bool DynamicSyms;
9981ad6265SDimitry Andric static bool ExportSymbols;
100fe6060f1SDimitry Andric static bool ExternalOnly;
101*5f757f3fSDimitry Andric static bool LineNumbers;
102fe6060f1SDimitry Andric static OutputFormatTy OutputFormat;
103fe6060f1SDimitry Andric static bool NoLLVMBitcode;
104fe6060f1SDimitry Andric static bool NoSort;
105fe6060f1SDimitry Andric static bool NoWeakSymbols;
106fe6060f1SDimitry Andric static bool NumericSort;
107fe6060f1SDimitry Andric static bool PrintFileName;
108fe6060f1SDimitry Andric static bool PrintSize;
109fe6060f1SDimitry Andric static bool Quiet;
110fe6060f1SDimitry Andric static bool ReverseSort;
111fe6060f1SDimitry Andric static bool SpecialSyms;
112fe6060f1SDimitry Andric static bool SizeSort;
113fe6060f1SDimitry Andric static bool UndefinedOnly;
114fe6060f1SDimitry Andric static bool WithoutAliases;
1150b57cec5SDimitry Andric 
11681ad6265SDimitry Andric // XCOFF-specific options.
11781ad6265SDimitry Andric static bool NoRsrc;
11881ad6265SDimitry Andric 
119fe6060f1SDimitry Andric namespace {
1200b57cec5SDimitry Andric enum Radix { d, o, x };
121fe6060f1SDimitry Andric } // namespace
122fe6060f1SDimitry Andric static Radix AddressRadix;
1230b57cec5SDimitry Andric 
124fe6060f1SDimitry Andric // Mach-O specific options.
125fe6060f1SDimitry Andric static bool ArchAll = false;
126fe6060f1SDimitry Andric static std::vector<StringRef> ArchFlags;
127fe6060f1SDimitry Andric static bool AddDyldInfo;
128fe6060f1SDimitry Andric static bool AddInlinedInfo;
129fe6060f1SDimitry Andric static bool DyldInfoOnly;
130fe6060f1SDimitry Andric static bool FormatMachOasHex;
131fe6060f1SDimitry Andric static bool NoDyldInfo;
132fe6060f1SDimitry Andric static std::vector<StringRef> SegSect;
133fe6060f1SDimitry Andric static bool MachOPrintSizeWarning = false;
1340b57cec5SDimitry Andric 
135fe6060f1SDimitry Andric // Miscellaneous states.
136fe6060f1SDimitry Andric static bool PrintAddress = true;
137fe6060f1SDimitry Andric static bool MultipleFiles = false;
138fe6060f1SDimitry Andric static bool HadError = false;
1390b57cec5SDimitry Andric 
140fe6060f1SDimitry Andric static StringRef ToolName;
1410b57cec5SDimitry Andric 
14281ad6265SDimitry Andric static void warn(Error Err, Twine FileName, Twine Context = Twine(),
14381ad6265SDimitry Andric                  Twine Archive = Twine()) {
14404eeddc0SDimitry Andric   assert(Err);
14504eeddc0SDimitry Andric 
14604eeddc0SDimitry Andric   // Flush the standard output so that the warning isn't interleaved with other
14704eeddc0SDimitry Andric   // output if stdout and stderr are writing to the same place.
14804eeddc0SDimitry Andric   outs().flush();
14904eeddc0SDimitry Andric 
15004eeddc0SDimitry Andric   handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
15104eeddc0SDimitry Andric     WithColor::warning(errs(), ToolName)
15281ad6265SDimitry Andric         << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")")
15381ad6265SDimitry Andric         << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message()
15481ad6265SDimitry Andric         << "\n";
15504eeddc0SDimitry Andric   });
15604eeddc0SDimitry Andric }
15704eeddc0SDimitry Andric 
1580b57cec5SDimitry Andric static void error(Twine Message, Twine Path = Twine()) {
1590b57cec5SDimitry Andric   HadError = true;
160fe6060f1SDimitry Andric   WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n";
1610b57cec5SDimitry Andric }
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric static bool error(std::error_code EC, Twine Path = Twine()) {
1640b57cec5SDimitry Andric   if (EC) {
1650b57cec5SDimitry Andric     error(EC.message(), Path);
1660b57cec5SDimitry Andric     return true;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric   return false;
1690b57cec5SDimitry Andric }
1700b57cec5SDimitry Andric 
1710b57cec5SDimitry Andric // This version of error() prints the archive name and member name, for example:
1720b57cec5SDimitry Andric // "libx.a(foo.o)" after the ToolName before the error message.  It sets
1730b57cec5SDimitry Andric // HadError but returns allowing the code to move on to other archive members.
1740b57cec5SDimitry Andric static void error(llvm::Error E, StringRef FileName, const Archive::Child &C,
1750b57cec5SDimitry Andric                   StringRef ArchitectureName = StringRef()) {
1760b57cec5SDimitry Andric   HadError = true;
1770b57cec5SDimitry Andric   WithColor::error(errs(), ToolName) << FileName;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   Expected<StringRef> NameOrErr = C.getName();
1800b57cec5SDimitry Andric   // TODO: if we have a error getting the name then it would be nice to print
1810b57cec5SDimitry Andric   // the index of which archive member this is and or its offset in the
1820b57cec5SDimitry Andric   // archive instead of "???" as the name.
1830b57cec5SDimitry Andric   if (!NameOrErr) {
1840b57cec5SDimitry Andric     consumeError(NameOrErr.takeError());
1850b57cec5SDimitry Andric     errs() << "(" << "???" << ")";
1860b57cec5SDimitry Andric   } else
1870b57cec5SDimitry Andric     errs() << "(" << NameOrErr.get() << ")";
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   if (!ArchitectureName.empty())
1900b57cec5SDimitry Andric     errs() << " (for architecture " << ArchitectureName << ")";
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric   std::string Buf;
1930b57cec5SDimitry Andric   raw_string_ostream OS(Buf);
1940b57cec5SDimitry Andric   logAllUnhandledErrors(std::move(E), OS);
1950b57cec5SDimitry Andric   OS.flush();
196fe6060f1SDimitry Andric   errs() << ": " << Buf << "\n";
1970b57cec5SDimitry Andric }
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric // This version of error() prints the file name and which architecture slice it
2000b57cec5SDimitry Andric // is from, for example: "foo.o (for architecture i386)" after the ToolName
2010b57cec5SDimitry Andric // before the error message.  It sets HadError but returns allowing the code to
2020b57cec5SDimitry Andric // move on to other architecture slices.
2030b57cec5SDimitry Andric static void error(llvm::Error E, StringRef FileName,
2040b57cec5SDimitry Andric                   StringRef ArchitectureName = StringRef()) {
2050b57cec5SDimitry Andric   HadError = true;
2060b57cec5SDimitry Andric   WithColor::error(errs(), ToolName) << FileName;
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   if (!ArchitectureName.empty())
2090b57cec5SDimitry Andric     errs() << " (for architecture " << ArchitectureName << ")";
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   std::string Buf;
2120b57cec5SDimitry Andric   raw_string_ostream OS(Buf);
2130b57cec5SDimitry Andric   logAllUnhandledErrors(std::move(E), OS);
2140b57cec5SDimitry Andric   OS.flush();
215fe6060f1SDimitry Andric   errs() << ": " << Buf << "\n";
2160b57cec5SDimitry Andric }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric namespace {
2190b57cec5SDimitry Andric struct NMSymbol {
2200b57cec5SDimitry Andric   uint64_t Address;
2210b57cec5SDimitry Andric   uint64_t Size;
2220b57cec5SDimitry Andric   char TypeChar;
223e8d8bef9SDimitry Andric   std::string Name;
2240b57cec5SDimitry Andric   StringRef SectionName;
2250b57cec5SDimitry Andric   StringRef TypeName;
2260b57cec5SDimitry Andric   BasicSymbolRef Sym;
22781ad6265SDimitry Andric   StringRef Visibility;
22881ad6265SDimitry Andric 
2290b57cec5SDimitry Andric   // The Sym field above points to the native symbol in the object file,
2300b57cec5SDimitry Andric   // for Mach-O when we are creating symbols from the dyld info the above
2310b57cec5SDimitry Andric   // pointer is null as there is no native symbol.  In these cases the fields
2320b57cec5SDimitry Andric   // below are filled in to represent what would have been a Mach-O nlist
2330b57cec5SDimitry Andric   // native symbol.
2340b57cec5SDimitry Andric   uint32_t SymFlags;
2350b57cec5SDimitry Andric   SectionRef Section;
2360b57cec5SDimitry Andric   uint8_t NType;
2370b57cec5SDimitry Andric   uint8_t NSect;
2380b57cec5SDimitry Andric   uint16_t NDesc;
239e8d8bef9SDimitry Andric   std::string IndirectName;
24081ad6265SDimitry Andric 
24181ad6265SDimitry Andric   bool isDefined() const {
242*5f757f3fSDimitry Andric     if (Sym.getRawDataRefImpl().p)
243*5f757f3fSDimitry Andric       return !(SymFlags & SymbolRef::SF_Undefined);
24481ad6265SDimitry Andric     return TypeChar != 'U';
24581ad6265SDimitry Andric   }
24681ad6265SDimitry Andric 
24781ad6265SDimitry Andric   bool initializeFlags(const SymbolicFile &Obj) {
24881ad6265SDimitry Andric     Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
24981ad6265SDimitry Andric     if (!SymFlagsOrErr) {
25081ad6265SDimitry Andric       // TODO: Test this error.
25181ad6265SDimitry Andric       error(SymFlagsOrErr.takeError(), Obj.getFileName());
25281ad6265SDimitry Andric       return false;
25381ad6265SDimitry Andric     }
25481ad6265SDimitry Andric     SymFlags = *SymFlagsOrErr;
25581ad6265SDimitry Andric     return true;
25681ad6265SDimitry Andric   }
25781ad6265SDimitry Andric 
25881ad6265SDimitry Andric   bool shouldPrint() const {
25981ad6265SDimitry Andric     bool Undefined = SymFlags & SymbolRef::SF_Undefined;
26081ad6265SDimitry Andric     bool Global = SymFlags & SymbolRef::SF_Global;
26181ad6265SDimitry Andric     bool Weak = SymFlags & SymbolRef::SF_Weak;
26281ad6265SDimitry Andric     bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific;
26381ad6265SDimitry Andric     if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) ||
26481ad6265SDimitry Andric         (!Global && ExternalOnly) || (Weak && NoWeakSymbols) ||
26581ad6265SDimitry Andric         (FormatSpecific && !(SpecialSyms || DebugSyms)))
26681ad6265SDimitry Andric       return false;
26781ad6265SDimitry Andric     return true;
26881ad6265SDimitry Andric   }
2690b57cec5SDimitry Andric };
2700b57cec5SDimitry Andric 
27181ad6265SDimitry Andric bool operator<(const NMSymbol &A, const NMSymbol &B) {
27281ad6265SDimitry Andric   if (NumericSort)
27381ad6265SDimitry Andric     return std::make_tuple(A.isDefined(), A.Address, A.Name, A.Size) <
27481ad6265SDimitry Andric            std::make_tuple(B.isDefined(), B.Address, B.Name, B.Size);
27581ad6265SDimitry Andric   if (SizeSort)
2760b57cec5SDimitry Andric     return std::make_tuple(A.Size, A.Name, A.Address) <
2770b57cec5SDimitry Andric            std::make_tuple(B.Size, B.Name, B.Address);
27881ad6265SDimitry Andric   if (ExportSymbols)
27981ad6265SDimitry Andric     return std::make_tuple(A.Name, A.Visibility) <
28081ad6265SDimitry Andric            std::make_tuple(B.Name, B.Visibility);
2810b57cec5SDimitry Andric   return std::make_tuple(A.Name, A.Size, A.Address) <
2820b57cec5SDimitry Andric          std::make_tuple(B.Name, B.Size, B.Address);
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
28581ad6265SDimitry Andric bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; }
28681ad6265SDimitry Andric bool operator==(const NMSymbol &A, const NMSymbol &B) {
28781ad6265SDimitry Andric   return !(A < B) && !(B < A);
28881ad6265SDimitry Andric }
28981ad6265SDimitry Andric } // anonymous namespace
29081ad6265SDimitry Andric 
2910b57cec5SDimitry Andric static StringRef CurrentFilename;
2920b57cec5SDimitry Andric 
2930b57cec5SDimitry Andric static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I);
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the
2960b57cec5SDimitry Andric // the OutputFormat is darwin or we are printing Mach-O symbols in hex.  For
2970b57cec5SDimitry Andric // the darwin format it produces the same output as darwin's nm(1) -m output
2980b57cec5SDimitry Andric // and when printing Mach-O symbols in hex it produces the same output as
2990b57cec5SDimitry Andric // darwin's nm(1) -x format.
3000b57cec5SDimitry Andric static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S,
3010b57cec5SDimitry Andric                               char *SymbolAddrStr, const char *printBlanks,
3020b57cec5SDimitry Andric                               const char *printDashes,
3030b57cec5SDimitry Andric                               const char *printFormat) {
3040b57cec5SDimitry Andric   MachO::mach_header H;
3050b57cec5SDimitry Andric   MachO::mach_header_64 H_64;
3060b57cec5SDimitry Andric   uint32_t Filetype = MachO::MH_OBJECT;
3070b57cec5SDimitry Andric   uint32_t Flags = 0;
3080b57cec5SDimitry Andric   uint8_t NType = 0;
3090b57cec5SDimitry Andric   uint8_t NSect = 0;
3100b57cec5SDimitry Andric   uint16_t NDesc = 0;
3110b57cec5SDimitry Andric   uint32_t NStrx = 0;
3120b57cec5SDimitry Andric   uint64_t NValue = 0;
3130b57cec5SDimitry Andric   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
3140b57cec5SDimitry Andric   if (Obj.isIR()) {
3155ffd83dbSDimitry Andric     uint32_t SymFlags = cantFail(S.Sym.getFlags());
3160b57cec5SDimitry Andric     if (SymFlags & SymbolRef::SF_Global)
3170b57cec5SDimitry Andric       NType |= MachO::N_EXT;
3180b57cec5SDimitry Andric     if (SymFlags & SymbolRef::SF_Hidden)
3190b57cec5SDimitry Andric       NType |= MachO::N_PEXT;
3200b57cec5SDimitry Andric     if (SymFlags & SymbolRef::SF_Undefined)
3210b57cec5SDimitry Andric       NType |= MachO::N_EXT | MachO::N_UNDF;
3220b57cec5SDimitry Andric     else {
3230b57cec5SDimitry Andric       // Here we have a symbol definition.  So to fake out a section name we
3240b57cec5SDimitry Andric       // use 1, 2 and 3 for section numbers.  See below where they are used to
3250b57cec5SDimitry Andric       // print out fake section names.
3260b57cec5SDimitry Andric       NType |= MachO::N_SECT;
3270b57cec5SDimitry Andric       if (SymFlags & SymbolRef::SF_Const)
3280b57cec5SDimitry Andric         NSect = 3;
3290b57cec5SDimitry Andric       else if (SymFlags & SymbolRef::SF_Executable)
3300b57cec5SDimitry Andric         NSect = 1;
3310b57cec5SDimitry Andric       else
3320b57cec5SDimitry Andric         NSect = 2;
3330b57cec5SDimitry Andric     }
3340b57cec5SDimitry Andric     if (SymFlags & SymbolRef::SF_Weak)
3350b57cec5SDimitry Andric       NDesc |= MachO::N_WEAK_DEF;
3360b57cec5SDimitry Andric   } else {
3370b57cec5SDimitry Andric     DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
3380b57cec5SDimitry Andric     if (MachO->is64Bit()) {
3390b57cec5SDimitry Andric       H_64 = MachO->MachOObjectFile::getHeader64();
3400b57cec5SDimitry Andric       Filetype = H_64.filetype;
3410b57cec5SDimitry Andric       Flags = H_64.flags;
3420b57cec5SDimitry Andric       if (SymDRI.p){
3430b57cec5SDimitry Andric         MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI);
3440b57cec5SDimitry Andric         NType = STE_64.n_type;
3450b57cec5SDimitry Andric         NSect = STE_64.n_sect;
3460b57cec5SDimitry Andric         NDesc = STE_64.n_desc;
3470b57cec5SDimitry Andric         NStrx = STE_64.n_strx;
3480b57cec5SDimitry Andric         NValue = STE_64.n_value;
3490b57cec5SDimitry Andric       } else {
3500b57cec5SDimitry Andric         NType = S.NType;
3510b57cec5SDimitry Andric         NSect = S.NSect;
3520b57cec5SDimitry Andric         NDesc = S.NDesc;
3530b57cec5SDimitry Andric         NStrx = 0;
3540b57cec5SDimitry Andric         NValue = S.Address;
3550b57cec5SDimitry Andric       }
3560b57cec5SDimitry Andric     } else {
3570b57cec5SDimitry Andric       H = MachO->MachOObjectFile::getHeader();
3580b57cec5SDimitry Andric       Filetype = H.filetype;
3590b57cec5SDimitry Andric       Flags = H.flags;
3600b57cec5SDimitry Andric       if (SymDRI.p){
3610b57cec5SDimitry Andric         MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI);
3620b57cec5SDimitry Andric         NType = STE.n_type;
3630b57cec5SDimitry Andric         NSect = STE.n_sect;
3640b57cec5SDimitry Andric         NDesc = STE.n_desc;
3650b57cec5SDimitry Andric         NStrx = STE.n_strx;
3660b57cec5SDimitry Andric         NValue = STE.n_value;
3670b57cec5SDimitry Andric       } else {
3680b57cec5SDimitry Andric         NType = S.NType;
3690b57cec5SDimitry Andric         NSect = S.NSect;
3700b57cec5SDimitry Andric         NDesc = S.NDesc;
3710b57cec5SDimitry Andric         NStrx = 0;
3720b57cec5SDimitry Andric         NValue = S.Address;
3730b57cec5SDimitry Andric       }
3740b57cec5SDimitry Andric     }
3750b57cec5SDimitry Andric   }
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric   // If we are printing Mach-O symbols in hex do that and return.
3780b57cec5SDimitry Andric   if (FormatMachOasHex) {
3790b57cec5SDimitry Andric     outs() << format(printFormat, NValue) << ' '
3800b57cec5SDimitry Andric            << format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' '
3810b57cec5SDimitry Andric            << S.Name;
3820b57cec5SDimitry Andric     if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
3830b57cec5SDimitry Andric       outs() << " (indirect for ";
3840b57cec5SDimitry Andric       outs() << format(printFormat, NValue) << ' ';
3850b57cec5SDimitry Andric       StringRef IndirectName;
3860b57cec5SDimitry Andric       if (S.Sym.getRawDataRefImpl().p) {
3870b57cec5SDimitry Andric         if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
3880b57cec5SDimitry Andric           outs() << "?)";
3890b57cec5SDimitry Andric         else
3900b57cec5SDimitry Andric           outs() << IndirectName << ")";
3910b57cec5SDimitry Andric       } else
3920b57cec5SDimitry Andric         outs() << S.IndirectName << ")";
3930b57cec5SDimitry Andric     }
3940b57cec5SDimitry Andric     outs() << "\n";
3950b57cec5SDimitry Andric     return;
3960b57cec5SDimitry Andric   }
3970b57cec5SDimitry Andric 
3980b57cec5SDimitry Andric   if (PrintAddress) {
3990b57cec5SDimitry Andric     if ((NType & MachO::N_TYPE) == MachO::N_INDR)
4000b57cec5SDimitry Andric       strcpy(SymbolAddrStr, printBlanks);
4010b57cec5SDimitry Andric     if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE)
4020b57cec5SDimitry Andric       strcpy(SymbolAddrStr, printDashes);
4030b57cec5SDimitry Andric     outs() << SymbolAddrStr << ' ';
4040b57cec5SDimitry Andric   }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric   switch (NType & MachO::N_TYPE) {
4070b57cec5SDimitry Andric   case MachO::N_UNDF:
4080b57cec5SDimitry Andric     if (NValue != 0) {
4090b57cec5SDimitry Andric       outs() << "(common) ";
4100b57cec5SDimitry Andric       if (MachO::GET_COMM_ALIGN(NDesc) != 0)
4110b57cec5SDimitry Andric         outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") ";
4120b57cec5SDimitry Andric     } else {
4130b57cec5SDimitry Andric       if ((NType & MachO::N_TYPE) == MachO::N_PBUD)
4140b57cec5SDimitry Andric         outs() << "(prebound ";
4150b57cec5SDimitry Andric       else
4160b57cec5SDimitry Andric         outs() << "(";
4170b57cec5SDimitry Andric       if ((NDesc & MachO::REFERENCE_TYPE) ==
4180b57cec5SDimitry Andric           MachO::REFERENCE_FLAG_UNDEFINED_LAZY)
4190b57cec5SDimitry Andric         outs() << "undefined [lazy bound]) ";
4200b57cec5SDimitry Andric       else if ((NDesc & MachO::REFERENCE_TYPE) ==
4210b57cec5SDimitry Andric                MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY)
4220b57cec5SDimitry Andric         outs() << "undefined [private lazy bound]) ";
4230b57cec5SDimitry Andric       else if ((NDesc & MachO::REFERENCE_TYPE) ==
4240b57cec5SDimitry Andric                MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY)
4250b57cec5SDimitry Andric         outs() << "undefined [private]) ";
4260b57cec5SDimitry Andric       else
4270b57cec5SDimitry Andric         outs() << "undefined) ";
4280b57cec5SDimitry Andric     }
4290b57cec5SDimitry Andric     break;
4300b57cec5SDimitry Andric   case MachO::N_ABS:
4310b57cec5SDimitry Andric     outs() << "(absolute) ";
4320b57cec5SDimitry Andric     break;
4330b57cec5SDimitry Andric   case MachO::N_INDR:
4340b57cec5SDimitry Andric     outs() << "(indirect) ";
4350b57cec5SDimitry Andric     break;
4360b57cec5SDimitry Andric   case MachO::N_SECT: {
4370b57cec5SDimitry Andric     if (Obj.isIR()) {
4380b57cec5SDimitry Andric       // For llvm bitcode files print out a fake section name using the values
4390b57cec5SDimitry Andric       // use 1, 2 and 3 for section numbers as set above.
4400b57cec5SDimitry Andric       if (NSect == 1)
4410b57cec5SDimitry Andric         outs() << "(LTO,CODE) ";
4420b57cec5SDimitry Andric       else if (NSect == 2)
4430b57cec5SDimitry Andric         outs() << "(LTO,DATA) ";
4440b57cec5SDimitry Andric       else if (NSect == 3)
4450b57cec5SDimitry Andric         outs() << "(LTO,RODATA) ";
4460b57cec5SDimitry Andric       else
4470b57cec5SDimitry Andric         outs() << "(?,?) ";
4480b57cec5SDimitry Andric       break;
4490b57cec5SDimitry Andric     }
4500b57cec5SDimitry Andric     section_iterator Sec = SectionRef();
4510b57cec5SDimitry Andric     if (S.Sym.getRawDataRefImpl().p) {
4520b57cec5SDimitry Andric       Expected<section_iterator> SecOrErr =
4530b57cec5SDimitry Andric           MachO->getSymbolSection(S.Sym.getRawDataRefImpl());
4540b57cec5SDimitry Andric       if (!SecOrErr) {
4550b57cec5SDimitry Andric         consumeError(SecOrErr.takeError());
4560b57cec5SDimitry Andric         outs() << "(?,?) ";
4570b57cec5SDimitry Andric         break;
4580b57cec5SDimitry Andric       }
4590b57cec5SDimitry Andric       Sec = *SecOrErr;
4600b57cec5SDimitry Andric       if (Sec == MachO->section_end()) {
4610b57cec5SDimitry Andric         outs() << "(?,?) ";
4620b57cec5SDimitry Andric         break;
4630b57cec5SDimitry Andric       }
4640b57cec5SDimitry Andric     } else {
4650b57cec5SDimitry Andric       Sec = S.Section;
4660b57cec5SDimitry Andric     }
4670b57cec5SDimitry Andric     DataRefImpl Ref = Sec->getRawDataRefImpl();
4680b57cec5SDimitry Andric     StringRef SectionName;
4690b57cec5SDimitry Andric     if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref))
4700b57cec5SDimitry Andric       SectionName = *NameOrErr;
4710b57cec5SDimitry Andric     StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref);
4720b57cec5SDimitry Andric     outs() << "(" << SegmentName << "," << SectionName << ") ";
4730b57cec5SDimitry Andric     break;
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric   default:
4760b57cec5SDimitry Andric     outs() << "(?) ";
4770b57cec5SDimitry Andric     break;
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric   if (NType & MachO::N_EXT) {
4810b57cec5SDimitry Andric     if (NDesc & MachO::REFERENCED_DYNAMICALLY)
4820b57cec5SDimitry Andric       outs() << "[referenced dynamically] ";
4830b57cec5SDimitry Andric     if (NType & MachO::N_PEXT) {
4840b57cec5SDimitry Andric       if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF)
4850b57cec5SDimitry Andric         outs() << "weak private external ";
4860b57cec5SDimitry Andric       else
4870b57cec5SDimitry Andric         outs() << "private external ";
4880b57cec5SDimitry Andric     } else {
4890b57cec5SDimitry Andric       if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF ||
4900b57cec5SDimitry Andric           (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) {
4910b57cec5SDimitry Andric         if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) ==
4920b57cec5SDimitry Andric             (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
4930b57cec5SDimitry Andric           outs() << "weak external automatically hidden ";
4940b57cec5SDimitry Andric         else
4950b57cec5SDimitry Andric           outs() << "weak external ";
4960b57cec5SDimitry Andric       } else
4970b57cec5SDimitry Andric         outs() << "external ";
4980b57cec5SDimitry Andric     }
4990b57cec5SDimitry Andric   } else {
5000b57cec5SDimitry Andric     if (NType & MachO::N_PEXT)
5010b57cec5SDimitry Andric       outs() << "non-external (was a private external) ";
5020b57cec5SDimitry Andric     else
5030b57cec5SDimitry Andric       outs() << "non-external ";
5040b57cec5SDimitry Andric   }
5050b57cec5SDimitry Andric 
5060b57cec5SDimitry Andric   if (Filetype == MachO::MH_OBJECT) {
5070b57cec5SDimitry Andric     if (NDesc & MachO::N_NO_DEAD_STRIP)
5080b57cec5SDimitry Andric       outs() << "[no dead strip] ";
5090b57cec5SDimitry Andric     if ((NType & MachO::N_TYPE) != MachO::N_UNDF &&
5100b57cec5SDimitry Andric         NDesc & MachO::N_SYMBOL_RESOLVER)
5110b57cec5SDimitry Andric       outs() << "[symbol resolver] ";
5120b57cec5SDimitry Andric     if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY)
5130b57cec5SDimitry Andric       outs() << "[alt entry] ";
5140b57cec5SDimitry Andric     if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC)
5150b57cec5SDimitry Andric       outs() << "[cold func] ";
5160b57cec5SDimitry Andric   }
5170b57cec5SDimitry Andric 
5180b57cec5SDimitry Andric   if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF)
5190b57cec5SDimitry Andric     outs() << "[Thumb] ";
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
5220b57cec5SDimitry Andric     outs() << S.Name << " (for ";
5230b57cec5SDimitry Andric     StringRef IndirectName;
5240b57cec5SDimitry Andric     if (MachO) {
5250b57cec5SDimitry Andric       if (S.Sym.getRawDataRefImpl().p) {
5260b57cec5SDimitry Andric         if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
5270b57cec5SDimitry Andric           outs() << "?)";
5280b57cec5SDimitry Andric         else
5290b57cec5SDimitry Andric           outs() << IndirectName << ")";
5300b57cec5SDimitry Andric       } else
5310b57cec5SDimitry Andric         outs() << S.IndirectName << ")";
5320b57cec5SDimitry Andric     } else
5330b57cec5SDimitry Andric       outs() << "?)";
5340b57cec5SDimitry Andric   } else
5350b57cec5SDimitry Andric     outs() << S.Name;
5360b57cec5SDimitry Andric 
5370b57cec5SDimitry Andric   if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
5380b57cec5SDimitry Andric       (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) ||
5390b57cec5SDimitry Andric        (NType & MachO::N_TYPE) == MachO::N_PBUD)) {
5400b57cec5SDimitry Andric     uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
5410b57cec5SDimitry Andric     if (LibraryOrdinal != 0) {
5420b57cec5SDimitry Andric       if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL)
5430b57cec5SDimitry Andric         outs() << " (from executable)";
5440b57cec5SDimitry Andric       else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL)
5450b57cec5SDimitry Andric         outs() << " (dynamically looked up)";
5460b57cec5SDimitry Andric       else {
5470b57cec5SDimitry Andric         StringRef LibraryName;
5480b57cec5SDimitry Andric         if (!MachO ||
5490b57cec5SDimitry Andric             MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName))
5500b57cec5SDimitry Andric           outs() << " (from bad library ordinal " << LibraryOrdinal << ")";
5510b57cec5SDimitry Andric         else
5520b57cec5SDimitry Andric           outs() << " (from " << LibraryName << ")";
5530b57cec5SDimitry Andric       }
5540b57cec5SDimitry Andric     }
5550b57cec5SDimitry Andric   }
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric // Table that maps Darwin's Mach-O stab constants to strings to allow printing.
5590b57cec5SDimitry Andric struct DarwinStabName {
5600b57cec5SDimitry Andric   uint8_t NType;
5610b57cec5SDimitry Andric   const char *Name;
5620b57cec5SDimitry Andric };
563349cc55cSDimitry Andric const struct DarwinStabName DarwinStabNames[] = {
564*5f757f3fSDimitry Andric     {MachO::N_GSYM, "GSYM"},    {MachO::N_FNAME, "FNAME"},
565*5f757f3fSDimitry Andric     {MachO::N_FUN, "FUN"},      {MachO::N_STSYM, "STSYM"},
566*5f757f3fSDimitry Andric     {MachO::N_LCSYM, "LCSYM"},  {MachO::N_BNSYM, "BNSYM"},
567*5f757f3fSDimitry Andric     {MachO::N_PC, "PC"},        {MachO::N_AST, "AST"},
568*5f757f3fSDimitry Andric     {MachO::N_OPT, "OPT"},      {MachO::N_RSYM, "RSYM"},
569*5f757f3fSDimitry Andric     {MachO::N_SLINE, "SLINE"},  {MachO::N_ENSYM, "ENSYM"},
570*5f757f3fSDimitry Andric     {MachO::N_SSYM, "SSYM"},    {MachO::N_SO, "SO"},
571*5f757f3fSDimitry Andric     {MachO::N_OSO, "OSO"},      {MachO::N_LIB, "LIB"},
572*5f757f3fSDimitry Andric     {MachO::N_LSYM, "LSYM"},    {MachO::N_BINCL, "BINCL"},
573*5f757f3fSDimitry Andric     {MachO::N_SOL, "SOL"},      {MachO::N_PARAMS, "PARAM"},
574*5f757f3fSDimitry Andric     {MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},
575*5f757f3fSDimitry Andric     {MachO::N_PSYM, "PSYM"},    {MachO::N_EINCL, "EINCL"},
576*5f757f3fSDimitry Andric     {MachO::N_ENTRY, "ENTRY"},  {MachO::N_LBRAC, "LBRAC"},
577*5f757f3fSDimitry Andric     {MachO::N_EXCL, "EXCL"},    {MachO::N_RBRAC, "RBRAC"},
578*5f757f3fSDimitry Andric     {MachO::N_BCOMM, "BCOMM"},  {MachO::N_ECOMM, "ECOMM"},
579*5f757f3fSDimitry Andric     {MachO::N_ECOML, "ECOML"},  {MachO::N_LENG, "LENG"},
5800b57cec5SDimitry Andric };
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric static const char *getDarwinStabString(uint8_t NType) {
583bdd1243dSDimitry Andric   for (auto I : ArrayRef(DarwinStabNames))
5840b57cec5SDimitry Andric     if (I.NType == NType)
5850b57cec5SDimitry Andric       return I.Name;
5860b57cec5SDimitry Andric   return nullptr;
5870b57cec5SDimitry Andric }
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric // darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of
5900b57cec5SDimitry Andric // a stab n_type value in a Mach-O file.
5910b57cec5SDimitry Andric static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) {
5920b57cec5SDimitry Andric   MachO::nlist_64 STE_64;
5930b57cec5SDimitry Andric   MachO::nlist STE;
5940b57cec5SDimitry Andric   uint8_t NType;
5950b57cec5SDimitry Andric   uint8_t NSect;
5960b57cec5SDimitry Andric   uint16_t NDesc;
5970b57cec5SDimitry Andric   DataRefImpl SymDRI = S.Sym.getRawDataRefImpl();
5980b57cec5SDimitry Andric   if (MachO->is64Bit()) {
5990b57cec5SDimitry Andric     STE_64 = MachO->getSymbol64TableEntry(SymDRI);
6000b57cec5SDimitry Andric     NType = STE_64.n_type;
6010b57cec5SDimitry Andric     NSect = STE_64.n_sect;
6020b57cec5SDimitry Andric     NDesc = STE_64.n_desc;
6030b57cec5SDimitry Andric   } else {
6040b57cec5SDimitry Andric     STE = MachO->getSymbolTableEntry(SymDRI);
6050b57cec5SDimitry Andric     NType = STE.n_type;
6060b57cec5SDimitry Andric     NSect = STE.n_sect;
6070b57cec5SDimitry Andric     NDesc = STE.n_desc;
6080b57cec5SDimitry Andric   }
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric   outs() << format(" %02x %04x ", NSect, NDesc);
6110b57cec5SDimitry Andric   if (const char *stabString = getDarwinStabString(NType))
6120b57cec5SDimitry Andric     outs() << format("%5.5s", stabString);
6130b57cec5SDimitry Andric   else
6140b57cec5SDimitry Andric     outs() << format("   %02x", NType);
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric static bool symbolIsDefined(const NMSymbol &Sym) {
6180b57cec5SDimitry Andric   return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
6190b57cec5SDimitry Andric }
6200b57cec5SDimitry Andric 
6215ffd83dbSDimitry Andric static void writeFileName(raw_ostream &S, StringRef ArchiveName,
6225ffd83dbSDimitry Andric                           StringRef ArchitectureName) {
6235ffd83dbSDimitry Andric   if (!ArchitectureName.empty())
6245ffd83dbSDimitry Andric     S << "(for architecture " << ArchitectureName << "):";
6255ffd83dbSDimitry Andric   if (OutputFormat == posix && !ArchiveName.empty())
6265ffd83dbSDimitry Andric     S << ArchiveName << "[" << CurrentFilename << "]: ";
6275ffd83dbSDimitry Andric   else {
6285ffd83dbSDimitry Andric     if (!ArchiveName.empty())
6295ffd83dbSDimitry Andric       S << ArchiveName << ":";
6305ffd83dbSDimitry Andric     S << CurrentFilename << ": ";
6315ffd83dbSDimitry Andric   }
6325ffd83dbSDimitry Andric }
6335ffd83dbSDimitry Andric 
63481ad6265SDimitry Andric static void sortSymbolList(std::vector<NMSymbol> &SymbolList) {
63581ad6265SDimitry Andric   if (NoSort)
63681ad6265SDimitry Andric     return;
6370b57cec5SDimitry Andric 
6380b57cec5SDimitry Andric   if (ReverseSort)
63981ad6265SDimitry Andric     llvm::sort(SymbolList, std::greater<>());
6408bcb0991SDimitry Andric   else
64181ad6265SDimitry Andric     llvm::sort(SymbolList);
6420b57cec5SDimitry Andric }
6430b57cec5SDimitry Andric 
64481ad6265SDimitry Andric static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) {
64581ad6265SDimitry Andric   for (const NMSymbol &Sym : SymbolList) {
64681ad6265SDimitry Andric     outs() << Sym.Name;
64781ad6265SDimitry Andric     if (!Sym.Visibility.empty())
64881ad6265SDimitry Andric       outs() << ' ' << Sym.Visibility;
64981ad6265SDimitry Andric     outs() << '\n';
65081ad6265SDimitry Andric   }
65181ad6265SDimitry Andric }
65281ad6265SDimitry Andric 
653*5f757f3fSDimitry Andric static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer,
654*5f757f3fSDimitry Andric                              const NMSymbol &S) {
655*5f757f3fSDimitry Andric   const auto *Obj = dyn_cast<ObjectFile>(S.Sym.getObject());
656*5f757f3fSDimitry Andric   if (!Obj)
657*5f757f3fSDimitry Andric     return;
658*5f757f3fSDimitry Andric   const SymbolRef Sym(S.Sym);
659*5f757f3fSDimitry Andric   uint64_t SectionIndex = object::SectionedAddress::UndefSection;
660*5f757f3fSDimitry Andric   section_iterator Sec = cantFail(Sym.getSection());
661*5f757f3fSDimitry Andric   if (Sec != Obj->section_end())
662*5f757f3fSDimitry Andric     SectionIndex = Sec->getIndex();
663*5f757f3fSDimitry Andric   object::SectionedAddress Address = {cantFail(Sym.getAddress()), SectionIndex};
664*5f757f3fSDimitry Andric 
665*5f757f3fSDimitry Andric   std::string FileName;
666*5f757f3fSDimitry Andric   uint32_t Line;
667*5f757f3fSDimitry Andric   switch (S.TypeChar) {
668*5f757f3fSDimitry Andric   // For undefined symbols, find the first relocation for that symbol with a
669*5f757f3fSDimitry Andric   // line number.
670*5f757f3fSDimitry Andric   case 'U': {
671*5f757f3fSDimitry Andric     for (const SectionRef RelocsSec : Obj->sections()) {
672*5f757f3fSDimitry Andric       if (RelocsSec.relocations().empty())
673*5f757f3fSDimitry Andric         continue;
674*5f757f3fSDimitry Andric       SectionRef TextSec = *cantFail(RelocsSec.getRelocatedSection());
675*5f757f3fSDimitry Andric       if (!TextSec.isText())
676*5f757f3fSDimitry Andric         continue;
677*5f757f3fSDimitry Andric       for (const RelocationRef R : RelocsSec.relocations()) {
678*5f757f3fSDimitry Andric         if (R.getSymbol() != Sym)
679*5f757f3fSDimitry Andric           continue;
680*5f757f3fSDimitry Andric         Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(
681*5f757f3fSDimitry Andric             *Obj, {TextSec.getAddress() + R.getOffset(), SectionIndex});
682*5f757f3fSDimitry Andric         if (!ResOrErr) {
683*5f757f3fSDimitry Andric           error(ResOrErr.takeError(), Obj->getFileName());
684*5f757f3fSDimitry Andric           return;
685*5f757f3fSDimitry Andric         }
686*5f757f3fSDimitry Andric         if (ResOrErr->FileName == DILineInfo::BadString)
687*5f757f3fSDimitry Andric           return;
688*5f757f3fSDimitry Andric         FileName = std::move(ResOrErr->FileName);
689*5f757f3fSDimitry Andric         Line = ResOrErr->Line;
690*5f757f3fSDimitry Andric         break;
691*5f757f3fSDimitry Andric       }
692*5f757f3fSDimitry Andric       if (!FileName.empty())
693*5f757f3fSDimitry Andric         break;
694*5f757f3fSDimitry Andric     }
695*5f757f3fSDimitry Andric     if (FileName.empty())
696*5f757f3fSDimitry Andric       return;
697*5f757f3fSDimitry Andric     break;
698*5f757f3fSDimitry Andric   }
699*5f757f3fSDimitry Andric   case 't':
700*5f757f3fSDimitry Andric   case 'T': {
701*5f757f3fSDimitry Andric     Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(*Obj, Address);
702*5f757f3fSDimitry Andric     if (!ResOrErr) {
703*5f757f3fSDimitry Andric       error(ResOrErr.takeError(), Obj->getFileName());
704*5f757f3fSDimitry Andric       return;
705*5f757f3fSDimitry Andric     }
706*5f757f3fSDimitry Andric     if (ResOrErr->FileName == DILineInfo::BadString)
707*5f757f3fSDimitry Andric       return;
708*5f757f3fSDimitry Andric     FileName = std::move(ResOrErr->FileName);
709*5f757f3fSDimitry Andric     Line = ResOrErr->Line;
710*5f757f3fSDimitry Andric     break;
711*5f757f3fSDimitry Andric   }
712*5f757f3fSDimitry Andric   default: {
713*5f757f3fSDimitry Andric     Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address);
714*5f757f3fSDimitry Andric     if (!ResOrErr) {
715*5f757f3fSDimitry Andric       error(ResOrErr.takeError(), Obj->getFileName());
716*5f757f3fSDimitry Andric       return;
717*5f757f3fSDimitry Andric     }
718*5f757f3fSDimitry Andric     if (ResOrErr->DeclFile.empty())
719*5f757f3fSDimitry Andric       return;
720*5f757f3fSDimitry Andric     FileName = std::move(ResOrErr->DeclFile);
721*5f757f3fSDimitry Andric     Line = ResOrErr->DeclLine;
722*5f757f3fSDimitry Andric     break;
723*5f757f3fSDimitry Andric   }
724*5f757f3fSDimitry Andric   }
725*5f757f3fSDimitry Andric   outs() << '\t' << FileName << ':' << Line;
726*5f757f3fSDimitry Andric }
727*5f757f3fSDimitry Andric 
72881ad6265SDimitry Andric static void printSymbolList(SymbolicFile &Obj,
72981ad6265SDimitry Andric                             std::vector<NMSymbol> &SymbolList, bool printName,
73081ad6265SDimitry Andric                             StringRef ArchiveName, StringRef ArchitectureName) {
731*5f757f3fSDimitry Andric   std::optional<symbolize::LLVMSymbolizer> Symbolizer;
732*5f757f3fSDimitry Andric   if (LineNumbers)
733*5f757f3fSDimitry Andric     Symbolizer.emplace();
734*5f757f3fSDimitry Andric 
7350b57cec5SDimitry Andric   if (!PrintFileName) {
736fe6060f1SDimitry Andric     if ((OutputFormat == bsd || OutputFormat == posix ||
737fe6060f1SDimitry Andric          OutputFormat == just_symbols) &&
738fe6060f1SDimitry Andric         MultipleFiles && printName) {
7390b57cec5SDimitry Andric       outs() << '\n' << CurrentFilename << ":\n";
7400b57cec5SDimitry Andric     } else if (OutputFormat == sysv) {
7410b57cec5SDimitry Andric       outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n";
74206c3fb27SDimitry Andric       if (Obj.is64Bit())
7430b57cec5SDimitry Andric         outs() << "Name                  Value           Class        Type"
7440b57cec5SDimitry Andric                << "         Size             Line  Section\n";
7450b57cec5SDimitry Andric       else
7460b57cec5SDimitry Andric         outs() << "Name                  Value   Class        Type"
7470b57cec5SDimitry Andric                << "         Size     Line  Section\n";
7480b57cec5SDimitry Andric     }
7490b57cec5SDimitry Andric   }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   const char *printBlanks, *printDashes, *printFormat;
75206c3fb27SDimitry Andric   if (Obj.is64Bit()) {
7530b57cec5SDimitry Andric     printBlanks = "                ";
7540b57cec5SDimitry Andric     printDashes = "----------------";
7550b57cec5SDimitry Andric     switch (AddressRadix) {
7560b57cec5SDimitry Andric     case Radix::o:
7570b57cec5SDimitry Andric       printFormat = OutputFormat == posix ? "%" PRIo64 : "%016" PRIo64;
7580b57cec5SDimitry Andric       break;
7590b57cec5SDimitry Andric     case Radix::x:
7600b57cec5SDimitry Andric       printFormat = OutputFormat == posix ? "%" PRIx64 : "%016" PRIx64;
7610b57cec5SDimitry Andric       break;
7620b57cec5SDimitry Andric     default:
7630b57cec5SDimitry Andric       printFormat = OutputFormat == posix ? "%" PRId64 : "%016" PRId64;
7640b57cec5SDimitry Andric     }
7650b57cec5SDimitry Andric   } else {
7660b57cec5SDimitry Andric     printBlanks = "        ";
7670b57cec5SDimitry Andric     printDashes = "--------";
7680b57cec5SDimitry Andric     switch (AddressRadix) {
7690b57cec5SDimitry Andric     case Radix::o:
7700b57cec5SDimitry Andric       printFormat = OutputFormat == posix ? "%" PRIo64 : "%08" PRIo64;
7710b57cec5SDimitry Andric       break;
7720b57cec5SDimitry Andric     case Radix::x:
7730b57cec5SDimitry Andric       printFormat = OutputFormat == posix ? "%" PRIx64 : "%08" PRIx64;
7740b57cec5SDimitry Andric       break;
7750b57cec5SDimitry Andric     default:
7760b57cec5SDimitry Andric       printFormat = OutputFormat == posix ? "%" PRId64 : "%08" PRId64;
7770b57cec5SDimitry Andric     }
7780b57cec5SDimitry Andric   }
7790b57cec5SDimitry Andric 
7800b57cec5SDimitry Andric   for (const NMSymbol &S : SymbolList) {
78181ad6265SDimitry Andric     if (!S.shouldPrint())
78281ad6265SDimitry Andric       continue;
78381ad6265SDimitry Andric 
784e8d8bef9SDimitry Andric     std::string Name = S.Name;
7850b57cec5SDimitry Andric     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
786*5f757f3fSDimitry Andric     if (Demangle)
787*5f757f3fSDimitry Andric       Name = demangle(Name);
7880b57cec5SDimitry Andric 
7890b57cec5SDimitry Andric     if (PrintFileName)
7905ffd83dbSDimitry Andric       writeFileName(outs(), ArchiveName, ArchitectureName);
791fe6060f1SDimitry Andric     if ((OutputFormat == just_symbols ||
7920b57cec5SDimitry Andric          (UndefinedOnly && MachO && OutputFormat != darwin)) &&
7930b57cec5SDimitry Andric         OutputFormat != posix) {
7940b57cec5SDimitry Andric       outs() << Name << "\n";
7950b57cec5SDimitry Andric       continue;
7960b57cec5SDimitry Andric     }
7970b57cec5SDimitry Andric 
7980b57cec5SDimitry Andric     char SymbolAddrStr[23], SymbolSizeStr[23];
7990b57cec5SDimitry Andric 
8000b57cec5SDimitry Andric     // If the format is SysV or the symbol isn't defined, then print spaces.
8010b57cec5SDimitry Andric     if (OutputFormat == sysv || !symbolIsDefined(S)) {
8020b57cec5SDimitry Andric       if (OutputFormat == posix) {
8030b57cec5SDimitry Andric         format(printFormat, S.Address)
8040b57cec5SDimitry Andric             .print(SymbolAddrStr, sizeof(SymbolAddrStr));
8050b57cec5SDimitry Andric         format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
8060b57cec5SDimitry Andric       } else {
8070b57cec5SDimitry Andric         strcpy(SymbolAddrStr, printBlanks);
8080b57cec5SDimitry Andric         strcpy(SymbolSizeStr, printBlanks);
8090b57cec5SDimitry Andric       }
8100b57cec5SDimitry Andric     }
8110b57cec5SDimitry Andric 
8120b57cec5SDimitry Andric     if (symbolIsDefined(S)) {
8130b57cec5SDimitry Andric       // Otherwise, print the symbol address and size.
8140b57cec5SDimitry Andric       if (Obj.isIR())
8150b57cec5SDimitry Andric         strcpy(SymbolAddrStr, printDashes);
8160b57cec5SDimitry Andric       else if (MachO && S.TypeChar == 'I')
8170b57cec5SDimitry Andric         strcpy(SymbolAddrStr, printBlanks);
8180b57cec5SDimitry Andric       else
8190b57cec5SDimitry Andric         format(printFormat, S.Address)
8200b57cec5SDimitry Andric             .print(SymbolAddrStr, sizeof(SymbolAddrStr));
8210b57cec5SDimitry Andric       format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr));
8220b57cec5SDimitry Andric     }
8230b57cec5SDimitry Andric 
8240b57cec5SDimitry Andric     // If OutputFormat is darwin or we are printing Mach-O symbols in hex and
8250b57cec5SDimitry Andric     // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's
8260b57cec5SDimitry Andric     // nm(1) -m output or hex, else if OutputFormat is darwin or we are
8270b57cec5SDimitry Andric     // printing Mach-O symbols in hex and not a Mach-O object fall back to
8280b57cec5SDimitry Andric     // OutputFormat bsd (see below).
8290b57cec5SDimitry Andric     if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) {
8300b57cec5SDimitry Andric       darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes,
8310b57cec5SDimitry Andric                         printFormat);
8320b57cec5SDimitry Andric     } else if (OutputFormat == posix) {
8330b57cec5SDimitry Andric       outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "
834*5f757f3fSDimitry Andric              << (MachO ? "0" : SymbolSizeStr);
8350b57cec5SDimitry Andric     } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
8360b57cec5SDimitry Andric       if (PrintAddress)
8370b57cec5SDimitry Andric         outs() << SymbolAddrStr << ' ';
8380b57cec5SDimitry Andric       if (PrintSize)
8390b57cec5SDimitry Andric         outs() << SymbolSizeStr << ' ';
8400b57cec5SDimitry Andric       outs() << S.TypeChar;
8410b57cec5SDimitry Andric       if (S.TypeChar == '-' && MachO)
8420b57cec5SDimitry Andric         darwinPrintStab(MachO, S);
8430b57cec5SDimitry Andric       outs() << " " << Name;
8440b57cec5SDimitry Andric       if (S.TypeChar == 'I' && MachO) {
8450b57cec5SDimitry Andric         outs() << " (indirect for ";
8460b57cec5SDimitry Andric         if (S.Sym.getRawDataRefImpl().p) {
8470b57cec5SDimitry Andric           StringRef IndirectName;
8480b57cec5SDimitry Andric           if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName))
8490b57cec5SDimitry Andric             outs() << "?)";
8500b57cec5SDimitry Andric           else
8510b57cec5SDimitry Andric             outs() << IndirectName << ")";
8520b57cec5SDimitry Andric         } else
8530b57cec5SDimitry Andric           outs() << S.IndirectName << ")";
8540b57cec5SDimitry Andric       }
8550b57cec5SDimitry Andric     } else if (OutputFormat == sysv) {
8560b57cec5SDimitry Andric       outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "|   "
8570b57cec5SDimitry Andric              << S.TypeChar << "  |" << right_justify(S.TypeName, 18) << "|"
858*5f757f3fSDimitry Andric              << SymbolSizeStr << "|     |" << S.SectionName;
8590b57cec5SDimitry Andric     }
860*5f757f3fSDimitry Andric     if (LineNumbers)
861*5f757f3fSDimitry Andric       printLineNumbers(*Symbolizer, S);
862*5f757f3fSDimitry Andric     outs() << '\n';
8630b57cec5SDimitry Andric   }
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   SymbolList.clear();
8660b57cec5SDimitry Andric }
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric static char getSymbolNMTypeChar(ELFObjectFileBase &Obj,
8690b57cec5SDimitry Andric                                 basic_symbol_iterator I) {
8700b57cec5SDimitry Andric   // OK, this is ELF
8710b57cec5SDimitry Andric   elf_symbol_iterator SymI(I);
8720b57cec5SDimitry Andric 
8730b57cec5SDimitry Andric   Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
8740b57cec5SDimitry Andric   if (!SecIOrErr) {
8750b57cec5SDimitry Andric     consumeError(SecIOrErr.takeError());
8760b57cec5SDimitry Andric     return '?';
8770b57cec5SDimitry Andric   }
8780b57cec5SDimitry Andric 
8790b57cec5SDimitry Andric   uint8_t Binding = SymI->getBinding();
8800b57cec5SDimitry Andric   if (Binding == ELF::STB_GNU_UNIQUE)
8810b57cec5SDimitry Andric     return 'u';
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function");
8840b57cec5SDimitry Andric   if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL)
8850b57cec5SDimitry Andric     return '?';
8860b57cec5SDimitry Andric 
8870b57cec5SDimitry Andric   elf_section_iterator SecI = *SecIOrErr;
8880b57cec5SDimitry Andric   if (SecI != Obj.section_end()) {
8890b57cec5SDimitry Andric     uint32_t Type = SecI->getType();
8900b57cec5SDimitry Andric     uint64_t Flags = SecI->getFlags();
8910b57cec5SDimitry Andric     if (Flags & ELF::SHF_EXECINSTR)
8920b57cec5SDimitry Andric       return 't';
8930b57cec5SDimitry Andric     if (Type == ELF::SHT_NOBITS)
8940b57cec5SDimitry Andric       return 'b';
8950b57cec5SDimitry Andric     if (Flags & ELF::SHF_ALLOC)
8960b57cec5SDimitry Andric       return Flags & ELF::SHF_WRITE ? 'd' : 'r';
8970b57cec5SDimitry Andric 
8988bcb0991SDimitry Andric     auto NameOrErr = SecI->getName();
8998bcb0991SDimitry Andric     if (!NameOrErr) {
9008bcb0991SDimitry Andric       consumeError(NameOrErr.takeError());
9010b57cec5SDimitry Andric       return '?';
9028bcb0991SDimitry Andric     }
903*5f757f3fSDimitry Andric     if ((*NameOrErr).starts_with(".debug"))
9040b57cec5SDimitry Andric       return 'N';
9050b57cec5SDimitry Andric     if (!(Flags & ELF::SHF_WRITE))
9060b57cec5SDimitry Andric       return 'n';
9070b57cec5SDimitry Andric   }
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   return '?';
9100b57cec5SDimitry Andric }
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) {
9130b57cec5SDimitry Andric   COFFSymbolRef Symb = Obj.getCOFFSymbol(*I);
9140b57cec5SDimitry Andric   // OK, this is COFF.
9150b57cec5SDimitry Andric   symbol_iterator SymI(I);
9160b57cec5SDimitry Andric 
9170b57cec5SDimitry Andric   Expected<StringRef> Name = SymI->getName();
9180b57cec5SDimitry Andric   if (!Name) {
9190b57cec5SDimitry Andric     consumeError(Name.takeError());
9200b57cec5SDimitry Andric     return '?';
9210b57cec5SDimitry Andric   }
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric   char Ret = StringSwitch<char>(*Name)
9240b57cec5SDimitry Andric                  .StartsWith(".debug", 'N')
9250b57cec5SDimitry Andric                  .StartsWith(".sxdata", 'N')
9260b57cec5SDimitry Andric                  .Default('?');
9270b57cec5SDimitry Andric 
9280b57cec5SDimitry Andric   if (Ret != '?')
9290b57cec5SDimitry Andric     return Ret;
9300b57cec5SDimitry Andric 
9310b57cec5SDimitry Andric   uint32_t Characteristics = 0;
9320b57cec5SDimitry Andric   if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) {
9330b57cec5SDimitry Andric     Expected<section_iterator> SecIOrErr = SymI->getSection();
9340b57cec5SDimitry Andric     if (!SecIOrErr) {
9350b57cec5SDimitry Andric       consumeError(SecIOrErr.takeError());
9360b57cec5SDimitry Andric       return '?';
9370b57cec5SDimitry Andric     }
9380b57cec5SDimitry Andric     section_iterator SecI = *SecIOrErr;
9390b57cec5SDimitry Andric     const coff_section *Section = Obj.getCOFFSection(*SecI);
9400b57cec5SDimitry Andric     Characteristics = Section->Characteristics;
9410b57cec5SDimitry Andric     if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section))
942*5f757f3fSDimitry Andric       if (NameOrErr->starts_with(".idata"))
9430b57cec5SDimitry Andric         return 'i';
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric 
9460b57cec5SDimitry Andric   switch (Symb.getSectionNumber()) {
9470b57cec5SDimitry Andric   case COFF::IMAGE_SYM_DEBUG:
9480b57cec5SDimitry Andric     return 'n';
9490b57cec5SDimitry Andric   default:
9500b57cec5SDimitry Andric     // Check section type.
9510b57cec5SDimitry Andric     if (Characteristics & COFF::IMAGE_SCN_CNT_CODE)
9520b57cec5SDimitry Andric       return 't';
9530b57cec5SDimitry Andric     if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
9540b57cec5SDimitry Andric       return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r';
9550b57cec5SDimitry Andric     if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
9560b57cec5SDimitry Andric       return 'b';
9570b57cec5SDimitry Andric     if (Characteristics & COFF::IMAGE_SCN_LNK_INFO)
9580b57cec5SDimitry Andric       return 'i';
9590b57cec5SDimitry Andric     // Check for section symbol.
9600b57cec5SDimitry Andric     if (Symb.isSectionDefinition())
9610b57cec5SDimitry Andric       return 's';
9620b57cec5SDimitry Andric   }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   return '?';
9650b57cec5SDimitry Andric }
9660b57cec5SDimitry Andric 
96704eeddc0SDimitry Andric static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) {
96804eeddc0SDimitry Andric   Expected<uint32_t> TypeOrErr = I->getType();
96904eeddc0SDimitry Andric   if (!TypeOrErr) {
97004eeddc0SDimitry Andric     warn(TypeOrErr.takeError(), Obj.getFileName(),
97104eeddc0SDimitry Andric          "for symbol with index " +
97204eeddc0SDimitry Andric              Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p)));
97304eeddc0SDimitry Andric     return '?';
97404eeddc0SDimitry Andric   }
97504eeddc0SDimitry Andric 
97604eeddc0SDimitry Andric   uint32_t SymType = *TypeOrErr;
97704eeddc0SDimitry Andric 
97804eeddc0SDimitry Andric   if (SymType == SymbolRef::ST_File)
97904eeddc0SDimitry Andric     return 'f';
98004eeddc0SDimitry Andric 
98104eeddc0SDimitry Andric   // If the I->getSection() call would return an error, the earlier I->getType()
98204eeddc0SDimitry Andric   // call will already have returned the same error first.
98304eeddc0SDimitry Andric   section_iterator SecIter = cantFail(I->getSection());
98404eeddc0SDimitry Andric 
98504eeddc0SDimitry Andric   if (SecIter == Obj.section_end())
98604eeddc0SDimitry Andric     return '?';
98704eeddc0SDimitry Andric 
98804eeddc0SDimitry Andric   if (Obj.isDebugSection(SecIter->getRawDataRefImpl()))
98904eeddc0SDimitry Andric     return 'N';
99004eeddc0SDimitry Andric 
99104eeddc0SDimitry Andric   if (SecIter->isText())
99204eeddc0SDimitry Andric     return 't';
99304eeddc0SDimitry Andric 
99404eeddc0SDimitry Andric   if (SecIter->isData())
99504eeddc0SDimitry Andric     return 'd';
99604eeddc0SDimitry Andric 
99704eeddc0SDimitry Andric   if (SecIter->isBSS())
99804eeddc0SDimitry Andric     return 'b';
99904eeddc0SDimitry Andric 
100004eeddc0SDimitry Andric   return '?';
100104eeddc0SDimitry Andric }
100204eeddc0SDimitry Andric 
10030b57cec5SDimitry Andric static char getSymbolNMTypeChar(COFFImportFile &Obj) {
10040b57cec5SDimitry Andric   switch (Obj.getCOFFImportHeader()->getType()) {
10050b57cec5SDimitry Andric   case COFF::IMPORT_CODE:
10060b57cec5SDimitry Andric     return 't';
10070b57cec5SDimitry Andric   case COFF::IMPORT_DATA:
10080b57cec5SDimitry Andric     return 'd';
10090b57cec5SDimitry Andric   case COFF::IMPORT_CONST:
10100b57cec5SDimitry Andric     return 'r';
10110b57cec5SDimitry Andric   }
10120b57cec5SDimitry Andric   return '?';
10130b57cec5SDimitry Andric }
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) {
10160b57cec5SDimitry Andric   DataRefImpl Symb = I->getRawDataRefImpl();
10170b57cec5SDimitry Andric   uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type
10180b57cec5SDimitry Andric                                 : Obj.getSymbolTableEntry(Symb).n_type;
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   if (NType & MachO::N_STAB)
10210b57cec5SDimitry Andric     return '-';
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   switch (NType & MachO::N_TYPE) {
10240b57cec5SDimitry Andric   case MachO::N_ABS:
10250b57cec5SDimitry Andric     return 's';
10260b57cec5SDimitry Andric   case MachO::N_INDR:
10270b57cec5SDimitry Andric     return 'i';
10280b57cec5SDimitry Andric   case MachO::N_SECT: {
10290b57cec5SDimitry Andric     Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb);
10300b57cec5SDimitry Andric     if (!SecOrErr) {
10310b57cec5SDimitry Andric       consumeError(SecOrErr.takeError());
10320b57cec5SDimitry Andric       return 's';
10330b57cec5SDimitry Andric     }
10340b57cec5SDimitry Andric     section_iterator Sec = *SecOrErr;
10350b57cec5SDimitry Andric     if (Sec == Obj.section_end())
10360b57cec5SDimitry Andric       return 's';
10370b57cec5SDimitry Andric     DataRefImpl Ref = Sec->getRawDataRefImpl();
10380b57cec5SDimitry Andric     StringRef SectionName;
10390b57cec5SDimitry Andric     if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref))
10400b57cec5SDimitry Andric       SectionName = *NameOrErr;
10410b57cec5SDimitry Andric     StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref);
10420b57cec5SDimitry Andric     if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE &&
10430b57cec5SDimitry Andric         SegmentName == "__TEXT_EXEC" && SectionName == "__text")
10440b57cec5SDimitry Andric       return 't';
10450b57cec5SDimitry Andric     if (SegmentName == "__TEXT" && SectionName == "__text")
10460b57cec5SDimitry Andric       return 't';
10470b57cec5SDimitry Andric     if (SegmentName == "__DATA" && SectionName == "__data")
10480b57cec5SDimitry Andric       return 'd';
10490b57cec5SDimitry Andric     if (SegmentName == "__DATA" && SectionName == "__bss")
10500b57cec5SDimitry Andric       return 'b';
10510b57cec5SDimitry Andric     return 's';
10520b57cec5SDimitry Andric   }
10530b57cec5SDimitry Andric   }
10540b57cec5SDimitry Andric 
10550b57cec5SDimitry Andric   return '?';
10560b57cec5SDimitry Andric }
10570b57cec5SDimitry Andric 
10585ffd83dbSDimitry Andric static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
105906c3fb27SDimitry Andric   auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));
106006c3fb27SDimitry Andric   switch (Type) {
106106c3fb27SDimitry Andric   case SymbolRef::ST_Function:
106206c3fb27SDimitry Andric     return 't';
1063*5f757f3fSDimitry Andric   case SymbolRef::ST_Data:
1064*5f757f3fSDimitry Andric     if (Obj.hasSegmentInfo())
1065*5f757f3fSDimitry Andric       return 'd';
1066*5f757f3fSDimitry Andric     [[fallthrough]];
106706c3fb27SDimitry Andric   default:
10685ffd83dbSDimitry Andric     return 's';
10695ffd83dbSDimitry Andric   }
107006c3fb27SDimitry Andric }
10715ffd83dbSDimitry Andric 
10720b57cec5SDimitry Andric static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) {
10735ffd83dbSDimitry Andric   uint32_t Flags = cantFail(I->getFlags());
10740b57cec5SDimitry Andric   if (Flags & SymbolRef::SF_Executable)
10750b57cec5SDimitry Andric     return 't';
10760b57cec5SDimitry Andric   return 'd';
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric 
10790b57cec5SDimitry Andric static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) {
10805ffd83dbSDimitry Andric   uint32_t Flags = cantFail(I->getFlags());
10810b57cec5SDimitry Andric   // FIXME: should we print 'b'? At the IR level we cannot be sure if this
10820b57cec5SDimitry Andric   // will be in bss or not, but we could approximate.
10830b57cec5SDimitry Andric   if (Flags & SymbolRef::SF_Executable)
10840b57cec5SDimitry Andric     return 't';
10850b57cec5SDimitry Andric   else if (Triple(Obj.getTargetTriple()).isOSDarwin() &&
10860b57cec5SDimitry Andric            (Flags & SymbolRef::SF_Const))
10870b57cec5SDimitry Andric     return 's';
10880b57cec5SDimitry Andric   else
10890b57cec5SDimitry Andric     return 'd';
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) {
1093e8d8bef9SDimitry Andric   return isa<ELFObjectFileBase>(&Obj) &&
1094e8d8bef9SDimitry Andric          elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT;
10950b57cec5SDimitry Andric }
10960b57cec5SDimitry Andric 
10970b57cec5SDimitry Andric // For ELF object files, Set TypeName to the symbol typename, to be printed
10980b57cec5SDimitry Andric // in the 'Type' column of the SYSV format output.
10990b57cec5SDimitry Andric static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) {
11000b57cec5SDimitry Andric   if (isa<ELFObjectFileBase>(&Obj)) {
11010b57cec5SDimitry Andric     elf_symbol_iterator SymI(I);
11020b57cec5SDimitry Andric     return SymI->getELFTypeName();
11030b57cec5SDimitry Andric   }
11040b57cec5SDimitry Andric   return "";
11050b57cec5SDimitry Andric }
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric // Return Posix nm class type tag (single letter), but also set SecName and
11080b57cec5SDimitry Andric // section and name, to be used in format=sysv output.
11090b57cec5SDimitry Andric static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I,
11100b57cec5SDimitry Andric                                    StringRef &SecName) {
11115ffd83dbSDimitry Andric   // Symbol Flags have been checked in the caller.
11125ffd83dbSDimitry Andric   uint32_t Symflags = cantFail(I->getFlags());
11138bcb0991SDimitry Andric   if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) {
11140b57cec5SDimitry Andric     if (Symflags & object::SymbolRef::SF_Absolute)
11150b57cec5SDimitry Andric       SecName = "*ABS*";
11160b57cec5SDimitry Andric     else if (Symflags & object::SymbolRef::SF_Common)
11170b57cec5SDimitry Andric       SecName = "*COM*";
11180b57cec5SDimitry Andric     else if (Symflags & object::SymbolRef::SF_Undefined)
11190b57cec5SDimitry Andric       SecName = "*UND*";
11200b57cec5SDimitry Andric     else {
11210b57cec5SDimitry Andric       elf_symbol_iterator SymI(I);
11220b57cec5SDimitry Andric       Expected<elf_section_iterator> SecIOrErr = SymI->getSection();
11230b57cec5SDimitry Andric       if (!SecIOrErr) {
11240b57cec5SDimitry Andric         consumeError(SecIOrErr.takeError());
11250b57cec5SDimitry Andric         return '?';
11260b57cec5SDimitry Andric       }
11278bcb0991SDimitry Andric 
11288bcb0991SDimitry Andric       if (*SecIOrErr == ELFObj->section_end())
11298bcb0991SDimitry Andric         return '?';
11308bcb0991SDimitry Andric 
11318bcb0991SDimitry Andric       Expected<StringRef> NameOrErr = (*SecIOrErr)->getName();
11328bcb0991SDimitry Andric       if (!NameOrErr) {
11338bcb0991SDimitry Andric         consumeError(NameOrErr.takeError());
11348bcb0991SDimitry Andric         return '?';
11358bcb0991SDimitry Andric       }
11368bcb0991SDimitry Andric       SecName = *NameOrErr;
11370b57cec5SDimitry Andric     }
11380b57cec5SDimitry Andric   }
11390b57cec5SDimitry Andric 
1140fe6060f1SDimitry Andric   if (Symflags & object::SymbolRef::SF_Undefined) {
1141fe6060f1SDimitry Andric     if (isa<MachOObjectFile>(Obj) || !(Symflags & object::SymbolRef::SF_Weak))
11420b57cec5SDimitry Andric       return 'U';
1143fe6060f1SDimitry Andric     return isObject(Obj, I) ? 'v' : 'w';
1144fe6060f1SDimitry Andric   }
1145fe6060f1SDimitry Andric   if (isa<ELFObjectFileBase>(&Obj))
1146fe6060f1SDimitry Andric     if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC)
1147fe6060f1SDimitry Andric       return 'i';
1148fe6060f1SDimitry Andric   if (!isa<MachOObjectFile>(Obj) && (Symflags & object::SymbolRef::SF_Weak))
1149fe6060f1SDimitry Andric     return isObject(Obj, I) ? 'V' : 'W';
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric   if (Symflags & object::SymbolRef::SF_Common)
11520b57cec5SDimitry Andric     return 'C';
11530b57cec5SDimitry Andric 
11540b57cec5SDimitry Andric   char Ret = '?';
11550b57cec5SDimitry Andric   if (Symflags & object::SymbolRef::SF_Absolute)
11560b57cec5SDimitry Andric     Ret = 'a';
11570b57cec5SDimitry Andric   else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj))
11580b57cec5SDimitry Andric     Ret = getSymbolNMTypeChar(*IR, I);
11590b57cec5SDimitry Andric   else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj))
11600b57cec5SDimitry Andric     Ret = getSymbolNMTypeChar(*COFF, I);
116104eeddc0SDimitry Andric   else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(&Obj))
116204eeddc0SDimitry Andric     Ret = getSymbolNMTypeChar(*XCOFF, 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     Ret = getSymbolNMTypeChar(*ELF, I);
1173480093f4SDimitry Andric     if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE)
1174480093f4SDimitry Andric       return Ret;
1175480093f4SDimitry Andric   } else
1176480093f4SDimitry Andric     llvm_unreachable("unknown binary format");
11770b57cec5SDimitry Andric 
11780b57cec5SDimitry Andric   if (!(Symflags & object::SymbolRef::SF_Global))
11790b57cec5SDimitry Andric     return Ret;
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric   return toupper(Ret);
11820b57cec5SDimitry Andric }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname"
11850b57cec5SDimitry Andric // option to dump only those symbols from that section in a Mach-O file.
118681ad6265SDimitry Andric // It is called once for each Mach-O file from getSymbolNamesFromObject()
11870b57cec5SDimitry Andric // to get the section number for that named section from the command line
11880b57cec5SDimitry Andric // arguments. It returns the section number for that section in the Mach-O
11890b57cec5SDimitry Andric // file or zero it is not present.
11900b57cec5SDimitry Andric static unsigned getNsectForSegSect(MachOObjectFile *Obj) {
11910b57cec5SDimitry Andric   unsigned Nsect = 1;
11920b57cec5SDimitry Andric   for (auto &S : Obj->sections()) {
11930b57cec5SDimitry Andric     DataRefImpl Ref = S.getRawDataRefImpl();
11940b57cec5SDimitry Andric     StringRef SectionName;
11950b57cec5SDimitry Andric     if (Expected<StringRef> NameOrErr = Obj->getSectionName(Ref))
11960b57cec5SDimitry Andric       SectionName = *NameOrErr;
11970b57cec5SDimitry Andric     StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref);
11980b57cec5SDimitry Andric     if (SegmentName == SegSect[0] && SectionName == SegSect[1])
11990b57cec5SDimitry Andric       return Nsect;
12000b57cec5SDimitry Andric     Nsect++;
12010b57cec5SDimitry Andric   }
12020b57cec5SDimitry Andric   return 0;
12030b57cec5SDimitry Andric }
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric // getNsectInMachO() is used to implement the Mach-O "-s segname sectname"
12060b57cec5SDimitry Andric // option to dump only those symbols from that section in a Mach-O file.
12070b57cec5SDimitry Andric // It is called once for each symbol in a Mach-O file from
120881ad6265SDimitry Andric // getSymbolNamesFromObject() and returns the section number for that symbol
12090b57cec5SDimitry Andric // if it is in a section, else it returns 0.
12100b57cec5SDimitry Andric static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) {
12110b57cec5SDimitry Andric   DataRefImpl Symb = Sym.getRawDataRefImpl();
12120b57cec5SDimitry Andric   if (Obj.is64Bit()) {
12130b57cec5SDimitry Andric     MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb);
12140b57cec5SDimitry Andric     return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
12150b57cec5SDimitry Andric   }
12160b57cec5SDimitry Andric   MachO::nlist STE = Obj.getSymbolTableEntry(Symb);
12170b57cec5SDimitry Andric   return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0;
12180b57cec5SDimitry Andric }
12190b57cec5SDimitry Andric 
122081ad6265SDimitry Andric static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO,
122181ad6265SDimitry Andric                                        std::vector<NMSymbol> &SymbolList) {
1222e8d8bef9SDimitry Andric   size_t I = SymbolList.size();
12230b57cec5SDimitry Andric   std::string ExportsNameBuffer;
12240b57cec5SDimitry Andric   raw_string_ostream EOS(ExportsNameBuffer);
12250b57cec5SDimitry Andric   std::string BindsNameBuffer;
12260b57cec5SDimitry Andric   raw_string_ostream BOS(BindsNameBuffer);
12270b57cec5SDimitry Andric   std::string LazysNameBuffer;
12280b57cec5SDimitry Andric   raw_string_ostream LOS(LazysNameBuffer);
12290b57cec5SDimitry Andric   std::string WeaksNameBuffer;
12300b57cec5SDimitry Andric   raw_string_ostream WOS(WeaksNameBuffer);
12310b57cec5SDimitry Andric   std::string FunctionStartsNameBuffer;
12320b57cec5SDimitry Andric   raw_string_ostream FOS(FunctionStartsNameBuffer);
1233e8d8bef9SDimitry Andric 
12340b57cec5SDimitry Andric   MachO::mach_header H;
12350b57cec5SDimitry Andric   MachO::mach_header_64 H_64;
12360b57cec5SDimitry Andric   uint32_t HFlags = 0;
1237e8d8bef9SDimitry Andric   if (MachO.is64Bit()) {
1238e8d8bef9SDimitry Andric     H_64 = MachO.MachOObjectFile::getHeader64();
12390b57cec5SDimitry Andric     HFlags = H_64.flags;
12400b57cec5SDimitry Andric   } else {
1241e8d8bef9SDimitry Andric     H = MachO.MachOObjectFile::getHeader();
12420b57cec5SDimitry Andric     HFlags = H.flags;
12430b57cec5SDimitry Andric   }
12440b57cec5SDimitry Andric   uint64_t BaseSegmentAddress = 0;
1245e8d8bef9SDimitry Andric   for (const auto &Command : MachO.load_commands()) {
12460b57cec5SDimitry Andric     if (Command.C.cmd == MachO::LC_SEGMENT) {
1247e8d8bef9SDimitry Andric       MachO::segment_command Seg = MachO.getSegmentLoadCommand(Command);
12480b57cec5SDimitry Andric       if (Seg.fileoff == 0 && Seg.filesize != 0) {
12490b57cec5SDimitry Andric         BaseSegmentAddress = Seg.vmaddr;
12500b57cec5SDimitry Andric         break;
12510b57cec5SDimitry Andric       }
12520b57cec5SDimitry Andric     } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
1253e8d8bef9SDimitry Andric       MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(Command);
12540b57cec5SDimitry Andric       if (Seg.fileoff == 0 && Seg.filesize != 0) {
12550b57cec5SDimitry Andric         BaseSegmentAddress = Seg.vmaddr;
12560b57cec5SDimitry Andric         break;
12570b57cec5SDimitry Andric       }
12580b57cec5SDimitry Andric     }
12590b57cec5SDimitry Andric   }
12600b57cec5SDimitry Andric   if (DyldInfoOnly || AddDyldInfo ||
12610b57cec5SDimitry Andric       HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) {
12620b57cec5SDimitry Andric     unsigned ExportsAdded = 0;
12630b57cec5SDimitry Andric     Error Err = Error::success();
1264e8d8bef9SDimitry Andric     for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) {
12650b57cec5SDimitry Andric       bool found = false;
12660b57cec5SDimitry Andric       bool ReExport = false;
12670b57cec5SDimitry Andric       if (!DyldInfoOnly) {
12680b57cec5SDimitry Andric         for (const NMSymbol &S : SymbolList)
12690b57cec5SDimitry Andric           if (S.Address == Entry.address() + BaseSegmentAddress &&
12700b57cec5SDimitry Andric               S.Name == Entry.name()) {
12710b57cec5SDimitry Andric             found = true;
12720b57cec5SDimitry Andric             break;
12730b57cec5SDimitry Andric           }
12740b57cec5SDimitry Andric       }
12750b57cec5SDimitry Andric       if (!found) {
12760b57cec5SDimitry Andric         NMSymbol S = {};
12770b57cec5SDimitry Andric         S.Address = Entry.address() + BaseSegmentAddress;
12780b57cec5SDimitry Andric         S.Size = 0;
12790b57cec5SDimitry Andric         S.TypeChar = '\0';
1280e8d8bef9SDimitry Andric         S.Name = Entry.name().str();
12810b57cec5SDimitry Andric         // There is no symbol in the nlist symbol table for this so we set
12820b57cec5SDimitry Andric         // Sym effectivly to null and the rest of code in here must test for
12830b57cec5SDimitry Andric         // it and not do things like Sym.getFlags() for it.
12840b57cec5SDimitry Andric         S.Sym = BasicSymbolRef();
12850b57cec5SDimitry Andric         S.SymFlags = SymbolRef::SF_Global;
12860b57cec5SDimitry Andric         S.Section = SectionRef();
12870b57cec5SDimitry Andric         S.NType = 0;
12880b57cec5SDimitry Andric         S.NSect = 0;
12890b57cec5SDimitry Andric         S.NDesc = 0;
12900b57cec5SDimitry Andric 
12910b57cec5SDimitry Andric         uint64_t EFlags = Entry.flags();
12920b57cec5SDimitry Andric         bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) ==
12930b57cec5SDimitry Andric                     MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE);
1294e8d8bef9SDimitry Andric         bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER);
12950b57cec5SDimitry Andric         ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT);
12960b57cec5SDimitry Andric         bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION);
12970b57cec5SDimitry Andric         if (WeakDef)
12980b57cec5SDimitry Andric           S.NDesc |= MachO::N_WEAK_DEF;
12990b57cec5SDimitry Andric         if (Abs) {
13000b57cec5SDimitry Andric           S.NType = MachO::N_EXT | MachO::N_ABS;
13010b57cec5SDimitry Andric           S.TypeChar = 'A';
13020b57cec5SDimitry Andric         } else if (ReExport) {
13030b57cec5SDimitry Andric           S.NType = MachO::N_EXT | MachO::N_INDR;
13040b57cec5SDimitry Andric           S.TypeChar = 'I';
13050b57cec5SDimitry Andric         } else {
13060b57cec5SDimitry Andric           S.NType = MachO::N_EXT | MachO::N_SECT;
13070b57cec5SDimitry Andric           if (Resolver) {
13080b57cec5SDimitry Andric             S.Address = Entry.other() + BaseSegmentAddress;
1309e8d8bef9SDimitry Andric             if ((S.Address & 1) != 0 && !MachO.is64Bit() &&
1310e8d8bef9SDimitry Andric                 H.cputype == MachO::CPU_TYPE_ARM) {
13110b57cec5SDimitry Andric               S.Address &= ~1LL;
13120b57cec5SDimitry Andric               S.NDesc |= MachO::N_ARM_THUMB_DEF;
13130b57cec5SDimitry Andric             }
13140b57cec5SDimitry Andric           } else {
13150b57cec5SDimitry Andric             S.Address = Entry.address() + BaseSegmentAddress;
13160b57cec5SDimitry Andric           }
13170b57cec5SDimitry Andric           StringRef SegmentName = StringRef();
13180b57cec5SDimitry Andric           StringRef SectionName = StringRef();
1319e8d8bef9SDimitry Andric           for (const SectionRef &Section : MachO.sections()) {
13200b57cec5SDimitry Andric             S.NSect++;
13218bcb0991SDimitry Andric 
13228bcb0991SDimitry Andric             if (Expected<StringRef> NameOrErr = Section.getName())
13238bcb0991SDimitry Andric               SectionName = *NameOrErr;
13248bcb0991SDimitry Andric             else
13258bcb0991SDimitry Andric               consumeError(NameOrErr.takeError());
13268bcb0991SDimitry Andric 
1327e8d8bef9SDimitry Andric             SegmentName =
1328e8d8bef9SDimitry Andric                 MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());
13290b57cec5SDimitry Andric             if (S.Address >= Section.getAddress() &&
13300b57cec5SDimitry Andric                 S.Address < Section.getAddress() + Section.getSize()) {
13310b57cec5SDimitry Andric               S.Section = Section;
13320b57cec5SDimitry Andric               break;
13330b57cec5SDimitry Andric             } else if (Entry.name() == "__mh_execute_header" &&
13340b57cec5SDimitry Andric                        SegmentName == "__TEXT" && SectionName == "__text") {
13350b57cec5SDimitry Andric               S.Section = Section;
13360b57cec5SDimitry Andric               S.NDesc |= MachO::REFERENCED_DYNAMICALLY;
13370b57cec5SDimitry Andric               break;
13380b57cec5SDimitry Andric             }
13390b57cec5SDimitry Andric           }
13400b57cec5SDimitry Andric           if (SegmentName == "__TEXT" && SectionName == "__text")
13410b57cec5SDimitry Andric             S.TypeChar = 'T';
13420b57cec5SDimitry Andric           else if (SegmentName == "__DATA" && SectionName == "__data")
13430b57cec5SDimitry Andric             S.TypeChar = 'D';
13440b57cec5SDimitry Andric           else if (SegmentName == "__DATA" && SectionName == "__bss")
13450b57cec5SDimitry Andric             S.TypeChar = 'B';
13460b57cec5SDimitry Andric           else
13470b57cec5SDimitry Andric             S.TypeChar = 'S';
13480b57cec5SDimitry Andric         }
13490b57cec5SDimitry Andric         SymbolList.push_back(S);
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric         EOS << Entry.name();
13520b57cec5SDimitry Andric         EOS << '\0';
13530b57cec5SDimitry Andric         ExportsAdded++;
13540b57cec5SDimitry Andric 
13550b57cec5SDimitry Andric         // For ReExports there are a two more things to do, first add the
13560b57cec5SDimitry Andric         // indirect name and second create the undefined symbol using the
13570b57cec5SDimitry Andric         // referened dynamic library.
13580b57cec5SDimitry Andric         if (ReExport) {
13590b57cec5SDimitry Andric 
13600b57cec5SDimitry Andric           // Add the indirect name.
13610b57cec5SDimitry Andric           if (Entry.otherName().empty())
13620b57cec5SDimitry Andric             EOS << Entry.name();
13630b57cec5SDimitry Andric           else
13640b57cec5SDimitry Andric             EOS << Entry.otherName();
13650b57cec5SDimitry Andric           EOS << '\0';
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric           // Now create the undefined symbol using the referened dynamic
13680b57cec5SDimitry Andric           // library.
13690b57cec5SDimitry Andric           NMSymbol U = {};
13700b57cec5SDimitry Andric           U.Address = 0;
13710b57cec5SDimitry Andric           U.Size = 0;
13720b57cec5SDimitry Andric           U.TypeChar = 'U';
13730b57cec5SDimitry Andric           if (Entry.otherName().empty())
1374e8d8bef9SDimitry Andric             U.Name = Entry.name().str();
13750b57cec5SDimitry Andric           else
1376e8d8bef9SDimitry Andric             U.Name = Entry.otherName().str();
13770b57cec5SDimitry Andric           // Again there is no symbol in the nlist symbol table for this so
13780b57cec5SDimitry Andric           // we set Sym effectivly to null and the rest of code in here must
13790b57cec5SDimitry Andric           // test for it and not do things like Sym.getFlags() for it.
13800b57cec5SDimitry Andric           U.Sym = BasicSymbolRef();
13810b57cec5SDimitry Andric           U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
13820b57cec5SDimitry Andric           U.Section = SectionRef();
13830b57cec5SDimitry Andric           U.NType = MachO::N_EXT | MachO::N_UNDF;
13840b57cec5SDimitry Andric           U.NSect = 0;
13850b57cec5SDimitry Andric           U.NDesc = 0;
13860b57cec5SDimitry Andric           // The library ordinal for this undefined symbol is in the export
13870b57cec5SDimitry Andric           // trie Entry.other().
13880b57cec5SDimitry Andric           MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other());
13890b57cec5SDimitry Andric           SymbolList.push_back(U);
13900b57cec5SDimitry Andric 
13910b57cec5SDimitry Andric           // Finally add the undefined symbol's name.
13920b57cec5SDimitry Andric           if (Entry.otherName().empty())
13930b57cec5SDimitry Andric             EOS << Entry.name();
13940b57cec5SDimitry Andric           else
13950b57cec5SDimitry Andric             EOS << Entry.otherName();
13960b57cec5SDimitry Andric           EOS << '\0';
13970b57cec5SDimitry Andric           ExportsAdded++;
13980b57cec5SDimitry Andric         }
13990b57cec5SDimitry Andric       }
14000b57cec5SDimitry Andric     }
14010b57cec5SDimitry Andric     if (Err)
1402e8d8bef9SDimitry Andric       error(std::move(Err), MachO.getFileName());
14030b57cec5SDimitry Andric     // Set the symbol names and indirect names for the added symbols.
14040b57cec5SDimitry Andric     if (ExportsAdded) {
14050b57cec5SDimitry Andric       EOS.flush();
14060b57cec5SDimitry Andric       const char *Q = ExportsNameBuffer.c_str();
14070b57cec5SDimitry Andric       for (unsigned K = 0; K < ExportsAdded; K++) {
14080b57cec5SDimitry Andric         SymbolList[I].Name = Q;
14090b57cec5SDimitry Andric         Q += strlen(Q) + 1;
14100b57cec5SDimitry Andric         if (SymbolList[I].TypeChar == 'I') {
14110b57cec5SDimitry Andric           SymbolList[I].IndirectName = Q;
14120b57cec5SDimitry Andric           Q += strlen(Q) + 1;
14130b57cec5SDimitry Andric         }
14140b57cec5SDimitry Andric         I++;
14150b57cec5SDimitry Andric       }
14160b57cec5SDimitry Andric     }
14170b57cec5SDimitry Andric 
14180b57cec5SDimitry Andric     // Add the undefined symbols from the bind entries.
14190b57cec5SDimitry Andric     unsigned BindsAdded = 0;
14200b57cec5SDimitry Andric     Error BErr = Error::success();
14210b57cec5SDimitry Andric     StringRef LastSymbolName = StringRef();
1422e8d8bef9SDimitry Andric     for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(BErr)) {
14230b57cec5SDimitry Andric       bool found = false;
14240b57cec5SDimitry Andric       if (LastSymbolName == Entry.symbolName())
14250b57cec5SDimitry Andric         found = true;
14260b57cec5SDimitry Andric       else if (!DyldInfoOnly) {
14270b57cec5SDimitry Andric         for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
14280b57cec5SDimitry Andric           if (SymbolList[J].Name == Entry.symbolName())
14290b57cec5SDimitry Andric             found = true;
14300b57cec5SDimitry Andric         }
14310b57cec5SDimitry Andric       }
14320b57cec5SDimitry Andric       if (!found) {
14330b57cec5SDimitry Andric         LastSymbolName = Entry.symbolName();
14340b57cec5SDimitry Andric         NMSymbol B = {};
14350b57cec5SDimitry Andric         B.Address = 0;
14360b57cec5SDimitry Andric         B.Size = 0;
14370b57cec5SDimitry Andric         B.TypeChar = 'U';
14380b57cec5SDimitry Andric         // There is no symbol in the nlist symbol table for this so we set
14390b57cec5SDimitry Andric         // Sym effectivly to null and the rest of code in here must test for
14400b57cec5SDimitry Andric         // it and not do things like Sym.getFlags() for it.
14410b57cec5SDimitry Andric         B.Sym = BasicSymbolRef();
14420b57cec5SDimitry Andric         B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
14430b57cec5SDimitry Andric         B.NType = MachO::N_EXT | MachO::N_UNDF;
14440b57cec5SDimitry Andric         B.NSect = 0;
14450b57cec5SDimitry Andric         B.NDesc = 0;
14460b57cec5SDimitry Andric         MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal());
1447e8d8bef9SDimitry Andric         B.Name = Entry.symbolName().str();
14480b57cec5SDimitry Andric         SymbolList.push_back(B);
14490b57cec5SDimitry Andric         BOS << Entry.symbolName();
14500b57cec5SDimitry Andric         BOS << '\0';
14510b57cec5SDimitry Andric         BindsAdded++;
14520b57cec5SDimitry Andric       }
14530b57cec5SDimitry Andric     }
14540b57cec5SDimitry Andric     if (BErr)
1455e8d8bef9SDimitry Andric       error(std::move(BErr), MachO.getFileName());
14560b57cec5SDimitry Andric     // Set the symbol names and indirect names for the added symbols.
14570b57cec5SDimitry Andric     if (BindsAdded) {
14580b57cec5SDimitry Andric       BOS.flush();
14590b57cec5SDimitry Andric       const char *Q = BindsNameBuffer.c_str();
14600b57cec5SDimitry Andric       for (unsigned K = 0; K < BindsAdded; K++) {
14610b57cec5SDimitry Andric         SymbolList[I].Name = Q;
14620b57cec5SDimitry Andric         Q += strlen(Q) + 1;
14630b57cec5SDimitry Andric         if (SymbolList[I].TypeChar == 'I') {
14640b57cec5SDimitry Andric           SymbolList[I].IndirectName = Q;
14650b57cec5SDimitry Andric           Q += strlen(Q) + 1;
14660b57cec5SDimitry Andric         }
14670b57cec5SDimitry Andric         I++;
14680b57cec5SDimitry Andric       }
14690b57cec5SDimitry Andric     }
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric     // Add the undefined symbols from the lazy bind entries.
14720b57cec5SDimitry Andric     unsigned LazysAdded = 0;
14730b57cec5SDimitry Andric     Error LErr = Error::success();
14740b57cec5SDimitry Andric     LastSymbolName = StringRef();
14750b57cec5SDimitry Andric     for (const llvm::object::MachOBindEntry &Entry :
1476e8d8bef9SDimitry Andric          MachO.lazyBindTable(LErr)) {
14770b57cec5SDimitry Andric       bool found = false;
14780b57cec5SDimitry Andric       if (LastSymbolName == Entry.symbolName())
14790b57cec5SDimitry Andric         found = true;
14800b57cec5SDimitry Andric       else {
14810b57cec5SDimitry Andric         // Here we must check to see it this symbol is already in the
14820b57cec5SDimitry Andric         // SymbolList as it might have already have been added above via a
14830b57cec5SDimitry Andric         // non-lazy (bind) entry.
14840b57cec5SDimitry Andric         for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
14850b57cec5SDimitry Andric           if (SymbolList[J].Name == Entry.symbolName())
14860b57cec5SDimitry Andric             found = true;
14870b57cec5SDimitry Andric         }
14880b57cec5SDimitry Andric       }
14890b57cec5SDimitry Andric       if (!found) {
14900b57cec5SDimitry Andric         LastSymbolName = Entry.symbolName();
14910b57cec5SDimitry Andric         NMSymbol L = {};
1492e8d8bef9SDimitry Andric         L.Name = Entry.symbolName().str();
14930b57cec5SDimitry Andric         L.Address = 0;
14940b57cec5SDimitry Andric         L.Size = 0;
14950b57cec5SDimitry Andric         L.TypeChar = 'U';
14960b57cec5SDimitry Andric         // There is no symbol in the nlist symbol table for this so we set
14970b57cec5SDimitry Andric         // Sym effectivly to null and the rest of code in here must test for
14980b57cec5SDimitry Andric         // it and not do things like Sym.getFlags() for it.
14990b57cec5SDimitry Andric         L.Sym = BasicSymbolRef();
15000b57cec5SDimitry Andric         L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
15010b57cec5SDimitry Andric         L.NType = MachO::N_EXT | MachO::N_UNDF;
15020b57cec5SDimitry Andric         L.NSect = 0;
15030b57cec5SDimitry Andric         // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it
15040b57cec5SDimitry Andric         // makes sence since we are creating this from a lazy bind entry.
15050b57cec5SDimitry Andric         L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY;
15060b57cec5SDimitry Andric         MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal());
15070b57cec5SDimitry Andric         SymbolList.push_back(L);
15080b57cec5SDimitry Andric         LOS << Entry.symbolName();
15090b57cec5SDimitry Andric         LOS << '\0';
15100b57cec5SDimitry Andric         LazysAdded++;
15110b57cec5SDimitry Andric       }
15120b57cec5SDimitry Andric     }
15130b57cec5SDimitry Andric     if (LErr)
1514e8d8bef9SDimitry Andric       error(std::move(LErr), MachO.getFileName());
15150b57cec5SDimitry Andric     // Set the symbol names and indirect names for the added symbols.
15160b57cec5SDimitry Andric     if (LazysAdded) {
15170b57cec5SDimitry Andric       LOS.flush();
15180b57cec5SDimitry Andric       const char *Q = LazysNameBuffer.c_str();
15190b57cec5SDimitry Andric       for (unsigned K = 0; K < LazysAdded; K++) {
15200b57cec5SDimitry Andric         SymbolList[I].Name = Q;
15210b57cec5SDimitry Andric         Q += strlen(Q) + 1;
15220b57cec5SDimitry Andric         if (SymbolList[I].TypeChar == 'I') {
15230b57cec5SDimitry Andric           SymbolList[I].IndirectName = Q;
15240b57cec5SDimitry Andric           Q += strlen(Q) + 1;
15250b57cec5SDimitry Andric         }
15260b57cec5SDimitry Andric         I++;
15270b57cec5SDimitry Andric       }
15280b57cec5SDimitry Andric     }
15290b57cec5SDimitry Andric 
15300b57cec5SDimitry Andric     // Add the undefineds symbol from the weak bind entries which are not
15310b57cec5SDimitry Andric     // strong symbols.
15320b57cec5SDimitry Andric     unsigned WeaksAdded = 0;
15330b57cec5SDimitry Andric     Error WErr = Error::success();
15340b57cec5SDimitry Andric     LastSymbolName = StringRef();
15350b57cec5SDimitry Andric     for (const llvm::object::MachOBindEntry &Entry :
1536e8d8bef9SDimitry Andric          MachO.weakBindTable(WErr)) {
15370b57cec5SDimitry Andric       bool found = false;
15380b57cec5SDimitry Andric       unsigned J = 0;
15390b57cec5SDimitry Andric       if (LastSymbolName == Entry.symbolName() ||
15400b57cec5SDimitry Andric           Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) {
15410b57cec5SDimitry Andric         found = true;
15420b57cec5SDimitry Andric       } else {
15430b57cec5SDimitry Andric         for (J = 0; J < SymbolList.size() && !found; ++J) {
15440b57cec5SDimitry Andric           if (SymbolList[J].Name == Entry.symbolName()) {
15450b57cec5SDimitry Andric             found = true;
15460b57cec5SDimitry Andric             break;
15470b57cec5SDimitry Andric           }
15480b57cec5SDimitry Andric         }
15490b57cec5SDimitry Andric       }
15500b57cec5SDimitry Andric       if (!found) {
15510b57cec5SDimitry Andric         LastSymbolName = Entry.symbolName();
1552e8d8bef9SDimitry Andric         NMSymbol W = {};
1553e8d8bef9SDimitry Andric         W.Name = Entry.symbolName().str();
15540b57cec5SDimitry Andric         W.Address = 0;
15550b57cec5SDimitry Andric         W.Size = 0;
15560b57cec5SDimitry Andric         W.TypeChar = 'U';
15570b57cec5SDimitry Andric         // There is no symbol in the nlist symbol table for this so we set
15580b57cec5SDimitry Andric         // Sym effectivly to null and the rest of code in here must test for
15590b57cec5SDimitry Andric         // it and not do things like Sym.getFlags() for it.
15600b57cec5SDimitry Andric         W.Sym = BasicSymbolRef();
15610b57cec5SDimitry Andric         W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined;
15620b57cec5SDimitry Andric         W.NType = MachO::N_EXT | MachO::N_UNDF;
15630b57cec5SDimitry Andric         W.NSect = 0;
15640b57cec5SDimitry Andric         // Odd that we are using N_WEAK_DEF on an undefined symbol but that is
15650b57cec5SDimitry Andric         // what is created in this case by the linker when there are real
15660b57cec5SDimitry Andric         // symbols in the nlist structs.
15670b57cec5SDimitry Andric         W.NDesc = MachO::N_WEAK_DEF;
15680b57cec5SDimitry Andric         SymbolList.push_back(W);
15690b57cec5SDimitry Andric         WOS << Entry.symbolName();
15700b57cec5SDimitry Andric         WOS << '\0';
15710b57cec5SDimitry Andric         WeaksAdded++;
15720b57cec5SDimitry Andric       } else {
15730b57cec5SDimitry Andric         // This is the case the symbol was previously been found and it could
15740b57cec5SDimitry Andric         // have been added from a bind or lazy bind symbol.  If so and not
15750b57cec5SDimitry Andric         // a definition also mark it as weak.
15760b57cec5SDimitry Andric         if (SymbolList[J].TypeChar == 'U')
15770b57cec5SDimitry Andric           // See comment above about N_WEAK_DEF.
15780b57cec5SDimitry Andric           SymbolList[J].NDesc |= MachO::N_WEAK_DEF;
15790b57cec5SDimitry Andric       }
15800b57cec5SDimitry Andric     }
15810b57cec5SDimitry Andric     if (WErr)
1582e8d8bef9SDimitry Andric       error(std::move(WErr), MachO.getFileName());
15830b57cec5SDimitry Andric     // Set the symbol names and indirect names for the added symbols.
15840b57cec5SDimitry Andric     if (WeaksAdded) {
15850b57cec5SDimitry Andric       WOS.flush();
15860b57cec5SDimitry Andric       const char *Q = WeaksNameBuffer.c_str();
15870b57cec5SDimitry Andric       for (unsigned K = 0; K < WeaksAdded; K++) {
15880b57cec5SDimitry Andric         SymbolList[I].Name = Q;
15890b57cec5SDimitry Andric         Q += strlen(Q) + 1;
15900b57cec5SDimitry Andric         if (SymbolList[I].TypeChar == 'I') {
15910b57cec5SDimitry Andric           SymbolList[I].IndirectName = Q;
15920b57cec5SDimitry Andric           Q += strlen(Q) + 1;
15930b57cec5SDimitry Andric         }
15940b57cec5SDimitry Andric         I++;
15950b57cec5SDimitry Andric       }
15960b57cec5SDimitry Andric     }
15970b57cec5SDimitry Andric 
15980b57cec5SDimitry Andric     // Trying adding symbol from the function starts table and LC_MAIN entry
15990b57cec5SDimitry Andric     // point.
16000b57cec5SDimitry Andric     SmallVector<uint64_t, 8> FoundFns;
16010b57cec5SDimitry Andric     uint64_t lc_main_offset = UINT64_MAX;
1602e8d8bef9SDimitry Andric     for (const auto &Command : MachO.load_commands()) {
16030b57cec5SDimitry Andric       if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) {
16040b57cec5SDimitry Andric         // We found a function starts segment, parse the addresses for
16050b57cec5SDimitry Andric         // consumption.
16060b57cec5SDimitry Andric         MachO::linkedit_data_command LLC =
1607e8d8bef9SDimitry Andric             MachO.getLinkeditDataLoadCommand(Command);
16080b57cec5SDimitry Andric 
1609e8d8bef9SDimitry Andric         MachO.ReadULEB128s(LLC.dataoff, FoundFns);
16100b57cec5SDimitry Andric       } else if (Command.C.cmd == MachO::LC_MAIN) {
1611e8d8bef9SDimitry Andric         MachO::entry_point_command LCmain = MachO.getEntryPointCommand(Command);
16120b57cec5SDimitry Andric         lc_main_offset = LCmain.entryoff;
16130b57cec5SDimitry Andric       }
16140b57cec5SDimitry Andric     }
16150b57cec5SDimitry Andric     // See if these addresses are already in the symbol table.
16160b57cec5SDimitry Andric     unsigned FunctionStartsAdded = 0;
16170b57cec5SDimitry Andric     for (uint64_t f = 0; f < FoundFns.size(); f++) {
16180b57cec5SDimitry Andric       bool found = false;
16190b57cec5SDimitry Andric       for (unsigned J = 0; J < SymbolList.size() && !found; ++J) {
16200b57cec5SDimitry Andric         if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress)
16210b57cec5SDimitry Andric           found = true;
16220b57cec5SDimitry Andric       }
16230b57cec5SDimitry Andric       // See this address is not already in the symbol table fake up an
16240b57cec5SDimitry Andric       // nlist for it.
16250b57cec5SDimitry Andric       if (!found) {
16260b57cec5SDimitry Andric         NMSymbol F = {};
16270b57cec5SDimitry Andric         F.Name = "<redacted function X>";
16280b57cec5SDimitry Andric         F.Address = FoundFns[f] + BaseSegmentAddress;
16290b57cec5SDimitry Andric         F.Size = 0;
16300b57cec5SDimitry Andric         // There is no symbol in the nlist symbol table for this so we set
16310b57cec5SDimitry Andric         // Sym effectivly to null and the rest of code in here must test for
16320b57cec5SDimitry Andric         // it and not do things like Sym.getFlags() for it.
16330b57cec5SDimitry Andric         F.Sym = BasicSymbolRef();
16340b57cec5SDimitry Andric         F.SymFlags = 0;
16350b57cec5SDimitry Andric         F.NType = MachO::N_SECT;
16360b57cec5SDimitry Andric         F.NSect = 0;
16370b57cec5SDimitry Andric         StringRef SegmentName = StringRef();
16380b57cec5SDimitry Andric         StringRef SectionName = StringRef();
1639e8d8bef9SDimitry Andric         for (const SectionRef &Section : MachO.sections()) {
16408bcb0991SDimitry Andric           if (Expected<StringRef> NameOrErr = Section.getName())
16418bcb0991SDimitry Andric             SectionName = *NameOrErr;
16428bcb0991SDimitry Andric           else
16438bcb0991SDimitry Andric             consumeError(NameOrErr.takeError());
16448bcb0991SDimitry Andric 
1645e8d8bef9SDimitry Andric           SegmentName =
1646e8d8bef9SDimitry Andric               MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl());
16470b57cec5SDimitry Andric           F.NSect++;
16480b57cec5SDimitry Andric           if (F.Address >= Section.getAddress() &&
16490b57cec5SDimitry Andric               F.Address < Section.getAddress() + Section.getSize()) {
16500b57cec5SDimitry Andric             F.Section = Section;
16510b57cec5SDimitry Andric             break;
16520b57cec5SDimitry Andric           }
16530b57cec5SDimitry Andric         }
16540b57cec5SDimitry Andric         if (SegmentName == "__TEXT" && SectionName == "__text")
16550b57cec5SDimitry Andric           F.TypeChar = 't';
16560b57cec5SDimitry Andric         else if (SegmentName == "__DATA" && SectionName == "__data")
16570b57cec5SDimitry Andric           F.TypeChar = 'd';
16580b57cec5SDimitry Andric         else if (SegmentName == "__DATA" && SectionName == "__bss")
16590b57cec5SDimitry Andric           F.TypeChar = 'b';
16600b57cec5SDimitry Andric         else
16610b57cec5SDimitry Andric           F.TypeChar = 's';
16620b57cec5SDimitry Andric         F.NDesc = 0;
16630b57cec5SDimitry Andric         SymbolList.push_back(F);
16640b57cec5SDimitry Andric         if (FoundFns[f] == lc_main_offset)
16650b57cec5SDimitry Andric           FOS << "<redacted LC_MAIN>";
16660b57cec5SDimitry Andric         else
16670b57cec5SDimitry Andric           FOS << "<redacted function " << f << ">";
16680b57cec5SDimitry Andric         FOS << '\0';
16690b57cec5SDimitry Andric         FunctionStartsAdded++;
16700b57cec5SDimitry Andric       }
16710b57cec5SDimitry Andric     }
16720b57cec5SDimitry Andric     if (FunctionStartsAdded) {
16730b57cec5SDimitry Andric       FOS.flush();
16740b57cec5SDimitry Andric       const char *Q = FunctionStartsNameBuffer.c_str();
16750b57cec5SDimitry Andric       for (unsigned K = 0; K < FunctionStartsAdded; K++) {
16760b57cec5SDimitry Andric         SymbolList[I].Name = Q;
16770b57cec5SDimitry Andric         Q += strlen(Q) + 1;
16780b57cec5SDimitry Andric         if (SymbolList[I].TypeChar == 'I') {
16790b57cec5SDimitry Andric           SymbolList[I].IndirectName = Q;
16800b57cec5SDimitry Andric           Q += strlen(Q) + 1;
16810b57cec5SDimitry Andric         }
16820b57cec5SDimitry Andric         I++;
16830b57cec5SDimitry Andric       }
16840b57cec5SDimitry Andric     }
16850b57cec5SDimitry Andric   }
16860b57cec5SDimitry Andric }
16870b57cec5SDimitry Andric 
168881ad6265SDimitry Andric static bool shouldDump(SymbolicFile &Obj) {
168981ad6265SDimitry Andric   // The -X option is currently only implemented for XCOFF, ELF, and IR object
169081ad6265SDimitry Andric   // files. The option isn't fundamentally impossible with other formats, just
169181ad6265SDimitry Andric   // isn't implemented.
169281ad6265SDimitry Andric   if (!isa<XCOFFObjectFile>(Obj) && !isa<ELFObjectFileBase>(Obj) &&
169381ad6265SDimitry Andric       !isa<IRObjectFile>(Obj))
169481ad6265SDimitry Andric     return true;
169581ad6265SDimitry Andric 
169606c3fb27SDimitry Andric   return Obj.is64Bit() ? BitMode != BitModeTy::Bit32
169781ad6265SDimitry Andric                        : BitMode != BitModeTy::Bit64;
169881ad6265SDimitry Andric }
169981ad6265SDimitry Andric 
170081ad6265SDimitry Andric static void getXCOFFExports(XCOFFObjectFile *XCOFFObj,
170181ad6265SDimitry Andric                             std::vector<NMSymbol> &SymbolList,
170281ad6265SDimitry Andric                             StringRef ArchiveName) {
170381ad6265SDimitry Andric   // Skip Shared object file.
170481ad6265SDimitry Andric   if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ)
170581ad6265SDimitry Andric     return;
170681ad6265SDimitry Andric 
170781ad6265SDimitry Andric   for (SymbolRef Sym : XCOFFObj->symbols()) {
170881ad6265SDimitry Andric     // There is no visibility in old 32 bit XCOFF object file interpret.
170981ad6265SDimitry Andric     bool HasVisibilityAttr =
171081ad6265SDimitry Andric         XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() &&
171181ad6265SDimitry Andric                                 (XCOFFObj->auxiliaryHeader32()->getVersion() ==
171281ad6265SDimitry Andric                                  XCOFF::NEW_XCOFF_INTERPRET));
171381ad6265SDimitry Andric 
171481ad6265SDimitry Andric     if (HasVisibilityAttr) {
171581ad6265SDimitry Andric       XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());
171681ad6265SDimitry Andric       uint16_t SymType = XCOFFSym.getSymbolType();
171781ad6265SDimitry Andric       if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL)
171881ad6265SDimitry Andric         continue;
171981ad6265SDimitry Andric       if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN)
172081ad6265SDimitry Andric         continue;
172181ad6265SDimitry Andric     }
172281ad6265SDimitry Andric 
172381ad6265SDimitry Andric     Expected<section_iterator> SymSecOrErr = Sym.getSection();
172481ad6265SDimitry Andric     if (!SymSecOrErr) {
172581ad6265SDimitry Andric       warn(SymSecOrErr.takeError(), XCOFFObj->getFileName(),
172681ad6265SDimitry Andric            "for symbol with index " +
172781ad6265SDimitry Andric                Twine(XCOFFObj->getSymbolIndex(Sym.getRawDataRefImpl().p)),
172881ad6265SDimitry Andric            ArchiveName);
172981ad6265SDimitry Andric       continue;
173081ad6265SDimitry Andric     }
173181ad6265SDimitry Andric     section_iterator SecIter = *SymSecOrErr;
173281ad6265SDimitry Andric     // If the symbol is not in a text or data section, it is not exported.
173381ad6265SDimitry Andric     if (SecIter == XCOFFObj->section_end())
173481ad6265SDimitry Andric       continue;
173581ad6265SDimitry Andric     if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS()))
173681ad6265SDimitry Andric       continue;
173781ad6265SDimitry Andric 
173881ad6265SDimitry Andric     StringRef SymName = cantFail(Sym.getName());
173981ad6265SDimitry Andric     if (SymName.empty())
174081ad6265SDimitry Andric       continue;
1741*5f757f3fSDimitry Andric     if (SymName.starts_with("__sinit") || SymName.starts_with("__sterm") ||
174281ad6265SDimitry Andric         SymName.front() == '.' || SymName.front() == '(')
174381ad6265SDimitry Andric       continue;
174481ad6265SDimitry Andric 
174581ad6265SDimitry Andric     // Check the SymName regex matching with "^__[0-9]+__".
1746*5f757f3fSDimitry Andric     if (SymName.size() > 4 && SymName.starts_with("__") &&
1747*5f757f3fSDimitry Andric         SymName.ends_with("__")) {
174881ad6265SDimitry Andric       if (std::all_of(SymName.begin() + 2, SymName.end() - 2, isDigit))
174981ad6265SDimitry Andric         continue;
175081ad6265SDimitry Andric     }
175181ad6265SDimitry Andric 
175281ad6265SDimitry Andric     if (SymName == "__rsrc" && NoRsrc)
175381ad6265SDimitry Andric       continue;
175481ad6265SDimitry Andric 
1755*5f757f3fSDimitry Andric     if (SymName.starts_with("__tf1"))
175681ad6265SDimitry Andric       SymName = SymName.substr(6);
1757*5f757f3fSDimitry Andric     else if (SymName.starts_with("__tf9"))
175881ad6265SDimitry Andric       SymName = SymName.substr(14);
175981ad6265SDimitry Andric 
176081ad6265SDimitry Andric     NMSymbol S = {};
176181ad6265SDimitry Andric     S.Name = SymName.str();
176281ad6265SDimitry Andric     S.Sym = Sym;
176381ad6265SDimitry Andric 
176481ad6265SDimitry Andric     if (HasVisibilityAttr) {
176581ad6265SDimitry Andric       XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl());
176681ad6265SDimitry Andric       uint16_t SymType = XCOFFSym.getSymbolType();
176781ad6265SDimitry Andric       if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED)
176881ad6265SDimitry Andric         S.Visibility = "protected";
176981ad6265SDimitry Andric       else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED)
177081ad6265SDimitry Andric         S.Visibility = "export";
177181ad6265SDimitry Andric     }
177281ad6265SDimitry Andric     if (S.initializeFlags(*XCOFFObj))
177381ad6265SDimitry Andric       SymbolList.push_back(S);
177481ad6265SDimitry Andric   }
177581ad6265SDimitry Andric }
177681ad6265SDimitry Andric 
177781ad6265SDimitry Andric static Expected<SymbolicFile::basic_symbol_iterator_range>
177881ad6265SDimitry Andric getDynamicSyms(SymbolicFile &Obj) {
177981ad6265SDimitry Andric   const auto *E = dyn_cast<ELFObjectFileBase>(&Obj);
178081ad6265SDimitry Andric   if (!E)
178181ad6265SDimitry Andric     return createError("File format has no dynamic symbol table");
178281ad6265SDimitry Andric   return E->getDynamicSymbolIterators();
178381ad6265SDimitry Andric }
178481ad6265SDimitry Andric 
178581ad6265SDimitry Andric // Returns false if there is error found or true otherwise.
178681ad6265SDimitry Andric static bool getSymbolNamesFromObject(SymbolicFile &Obj,
178781ad6265SDimitry Andric                                      std::vector<NMSymbol> &SymbolList) {
1788e8d8bef9SDimitry Andric   auto Symbols = Obj.symbols();
1789349cc55cSDimitry Andric   std::vector<VersionEntry> SymbolVersions;
1790e8d8bef9SDimitry Andric 
179181ad6265SDimitry Andric   if (DynamicSyms) {
179281ad6265SDimitry Andric     Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr =
179381ad6265SDimitry Andric         getDynamicSyms(Obj);
179481ad6265SDimitry Andric     if (!SymbolsOrErr) {
179581ad6265SDimitry Andric       error(SymbolsOrErr.takeError(), Obj.getFileName());
179681ad6265SDimitry Andric       return false;
179781ad6265SDimitry Andric     }
179881ad6265SDimitry Andric     Symbols = *SymbolsOrErr;
179981ad6265SDimitry Andric     if (const auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) {
1800349cc55cSDimitry Andric       if (Expected<std::vector<VersionEntry>> VersionsOrErr =
1801349cc55cSDimitry Andric               E->readDynsymVersions())
1802e8d8bef9SDimitry Andric         SymbolVersions = std::move(*VersionsOrErr);
1803e8d8bef9SDimitry Andric       else
1804e8d8bef9SDimitry Andric         WithColor::warning(errs(), ToolName)
1805e8d8bef9SDimitry Andric             << "unable to read symbol versions: "
1806e8d8bef9SDimitry Andric             << toString(VersionsOrErr.takeError()) << "\n";
1807e8d8bef9SDimitry Andric     }
180881ad6265SDimitry Andric   }
1809e8d8bef9SDimitry Andric   // If a "-s segname sectname" option was specified and this is a Mach-O
1810e8d8bef9SDimitry Andric   // file get the section number for that section in this object file.
1811e8d8bef9SDimitry Andric   unsigned int Nsect = 0;
1812e8d8bef9SDimitry Andric   MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
1813e8d8bef9SDimitry Andric   if (!SegSect.empty() && MachO) {
1814e8d8bef9SDimitry Andric     Nsect = getNsectForSegSect(MachO);
1815e8d8bef9SDimitry Andric     // If this section is not in the object file no symbols are printed.
1816e8d8bef9SDimitry Andric     if (Nsect == 0)
181781ad6265SDimitry Andric       return false;
1818e8d8bef9SDimitry Andric   }
181981ad6265SDimitry Andric 
1820e8d8bef9SDimitry Andric   if (!(MachO && DyldInfoOnly)) {
1821e8d8bef9SDimitry Andric     size_t I = -1;
1822e8d8bef9SDimitry Andric     for (BasicSymbolRef Sym : Symbols) {
1823e8d8bef9SDimitry Andric       ++I;
1824e8d8bef9SDimitry Andric       Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
1825e8d8bef9SDimitry Andric       if (!SymFlagsOrErr) {
1826e8d8bef9SDimitry Andric         error(SymFlagsOrErr.takeError(), Obj.getFileName());
182781ad6265SDimitry Andric         return false;
1828e8d8bef9SDimitry Andric       }
1829fe6060f1SDimitry Andric 
1830fe6060f1SDimitry Andric       // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they
1831fe6060f1SDimitry Andric       // are used to repesent mapping symbols and needed to honor the
1832fe6060f1SDimitry Andric       // --special-syms option.
1833fe6060f1SDimitry Andric       auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
1834*5f757f3fSDimitry Andric       bool HasMappingSymbol =
1835*5f757f3fSDimitry Andric           ELFObj && llvm::is_contained({ELF::EM_ARM, ELF::EM_AARCH64,
1836*5f757f3fSDimitry Andric                                         ELF::EM_CSKY, ELF::EM_RISCV},
1837*5f757f3fSDimitry Andric                                        ELFObj->getEMachine());
1838*5f757f3fSDimitry Andric       if (!HasMappingSymbol && !DebugSyms &&
1839*5f757f3fSDimitry Andric           (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
1840e8d8bef9SDimitry Andric         continue;
1841e8d8bef9SDimitry Andric       if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
1842e8d8bef9SDimitry Andric         continue;
1843e8d8bef9SDimitry Andric       // If a "-s segname sectname" option was specified and this is a Mach-O
1844e8d8bef9SDimitry Andric       // file and this section appears in this file, Nsect will be non-zero then
1845e8d8bef9SDimitry Andric       // see if this symbol is a symbol from that section and if not skip it.
1846e8d8bef9SDimitry Andric       if (Nsect && Nsect != getNsectInMachO(*MachO, Sym))
1847e8d8bef9SDimitry Andric         continue;
1848e8d8bef9SDimitry Andric       NMSymbol S = {};
1849e8d8bef9SDimitry Andric       S.Size = 0;
1850e8d8bef9SDimitry Andric       S.Address = 0;
1851e8d8bef9SDimitry Andric       if (isa<ELFObjectFileBase>(&Obj))
1852e8d8bef9SDimitry Andric         S.Size = ELFSymbolRef(Sym).getSize();
185304eeddc0SDimitry Andric 
185404eeddc0SDimitry Andric       if (const XCOFFObjectFile *XCOFFObj =
185504eeddc0SDimitry Andric               dyn_cast<const XCOFFObjectFile>(&Obj))
185604eeddc0SDimitry Andric         S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl());
185704eeddc0SDimitry Andric 
1858*5f757f3fSDimitry Andric       if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj)) {
1859*5f757f3fSDimitry Andric         const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym);
1860*5f757f3fSDimitry Andric         if (WasmSym.isTypeData() && !WasmSym.isUndefined())
1861*5f757f3fSDimitry Andric           S.Size = WasmSym.Info.DataRef.Size;
1862*5f757f3fSDimitry Andric       }
1863*5f757f3fSDimitry Andric 
1864e8d8bef9SDimitry Andric       if (PrintAddress && isa<ObjectFile>(Obj)) {
1865e8d8bef9SDimitry Andric         SymbolRef SymRef(Sym);
1866e8d8bef9SDimitry Andric         Expected<uint64_t> AddressOrErr = SymRef.getAddress();
1867e8d8bef9SDimitry Andric         if (!AddressOrErr) {
1868e8d8bef9SDimitry Andric           consumeError(AddressOrErr.takeError());
1869e8d8bef9SDimitry Andric           break;
1870e8d8bef9SDimitry Andric         }
1871e8d8bef9SDimitry Andric         S.Address = *AddressOrErr;
1872e8d8bef9SDimitry Andric       }
1873e8d8bef9SDimitry Andric       S.TypeName = getNMTypeName(Obj, Sym);
1874e8d8bef9SDimitry Andric       S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName);
1875e8d8bef9SDimitry Andric 
1876e8d8bef9SDimitry Andric       raw_string_ostream OS(S.Name);
1877e8d8bef9SDimitry Andric       if (Error E = Sym.printName(OS)) {
1878e8d8bef9SDimitry Andric         if (MachO) {
1879e8d8bef9SDimitry Andric           OS << "bad string index";
1880e8d8bef9SDimitry Andric           consumeError(std::move(E));
1881e8d8bef9SDimitry Andric         } else
1882e8d8bef9SDimitry Andric           error(std::move(E), Obj.getFileName());
1883e8d8bef9SDimitry Andric       }
1884e8d8bef9SDimitry Andric       if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty())
1885e8d8bef9SDimitry Andric         S.Name +=
1886349cc55cSDimitry Andric             (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name;
1887e8d8bef9SDimitry Andric 
1888e8d8bef9SDimitry Andric       S.Sym = Sym;
188981ad6265SDimitry Andric       if (S.initializeFlags(Obj))
1890e8d8bef9SDimitry Andric         SymbolList.push_back(S);
1891e8d8bef9SDimitry Andric     }
1892e8d8bef9SDimitry Andric   }
1893e8d8bef9SDimitry Andric 
1894e8d8bef9SDimitry Andric   // If this is a Mach-O file where the nlist symbol table is out of sync
1895e8d8bef9SDimitry Andric   // with the dyld export trie then look through exports and fake up symbols
1896e8d8bef9SDimitry Andric   // for the ones that are missing (also done with the -add-dyldinfo flag).
1897e8d8bef9SDimitry Andric   // This is needed if strip(1) -T is run on a binary containing swift
1898e8d8bef9SDimitry Andric   // language symbols for example.  The option -only-dyldinfo will fake up
1899e8d8bef9SDimitry Andric   // all symbols from the dyld export trie as well as the bind info.
1900e8d8bef9SDimitry Andric   if (MachO && !NoDyldInfo)
190181ad6265SDimitry Andric     dumpSymbolsFromDLInfoMachO(*MachO, SymbolList);
1902e8d8bef9SDimitry Andric 
190381ad6265SDimitry Andric   return true;
190481ad6265SDimitry Andric }
190581ad6265SDimitry Andric 
190681ad6265SDimitry Andric static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName,
190781ad6265SDimitry Andric                              StringRef ArchitectureName,
190881ad6265SDimitry Andric                              StringRef ObjectFileName) {
190981ad6265SDimitry Andric   outs() << "\n";
191081ad6265SDimitry Andric   if (ArchiveName.empty() || !PrintArchiveName)
191181ad6265SDimitry Andric     outs() << ObjectFileName;
191281ad6265SDimitry Andric   else
191381ad6265SDimitry Andric     outs() << ArchiveName << "(" << ObjectFileName << ")";
191481ad6265SDimitry Andric   if (!ArchitectureName.empty())
191581ad6265SDimitry Andric     outs() << " (for architecture " << ArchitectureName << ")";
191681ad6265SDimitry Andric   outs() << ":\n";
191781ad6265SDimitry Andric }
191881ad6265SDimitry Andric 
191981ad6265SDimitry Andric static Expected<bool> hasSymbols(SymbolicFile &Obj) {
192081ad6265SDimitry Andric   if (DynamicSyms) {
192181ad6265SDimitry Andric     Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr =
192281ad6265SDimitry Andric         getDynamicSyms(Obj);
192381ad6265SDimitry Andric     if (!DynamicSymsOrErr)
192481ad6265SDimitry Andric       return DynamicSymsOrErr.takeError();
192581ad6265SDimitry Andric     return !DynamicSymsOrErr->empty();
192681ad6265SDimitry Andric   }
192781ad6265SDimitry Andric   return !Obj.symbols().empty();
192881ad6265SDimitry Andric }
192981ad6265SDimitry Andric 
1930*5f757f3fSDimitry Andric static void printSymbolNamesFromObject(
1931*5f757f3fSDimitry Andric     SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
1932*5f757f3fSDimitry Andric     bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
1933*5f757f3fSDimitry Andric     StringRef ArchitectureName = {}, StringRef ObjectName = {},
1934*5f757f3fSDimitry Andric     bool PrintArchiveName = true) {
1935*5f757f3fSDimitry Andric 
1936*5f757f3fSDimitry Andric   if (PrintObjectLabel && !ExportSymbols)
1937*5f757f3fSDimitry Andric     printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
1938*5f757f3fSDimitry Andric                      ObjectName.empty() ? Obj.getFileName() : ObjectName);
1939*5f757f3fSDimitry Andric 
1940*5f757f3fSDimitry Andric   if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
1941*5f757f3fSDimitry Andric     return;
1942*5f757f3fSDimitry Andric 
1943*5f757f3fSDimitry Andric   // If there is an error in hasSymbols(), the error should be encountered in
1944*5f757f3fSDimitry Andric   // function getSymbolNamesFromObject first.
1945*5f757f3fSDimitry Andric   if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
1946*5f757f3fSDimitry Andric     writeFileName(errs(), ArchiveName, ArchitectureName);
1947*5f757f3fSDimitry Andric     errs() << "no symbols\n";
1948*5f757f3fSDimitry Andric   }
1949*5f757f3fSDimitry Andric 
1950*5f757f3fSDimitry Andric   sortSymbolList(SymbolList);
1951*5f757f3fSDimitry Andric   printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,
1952*5f757f3fSDimitry Andric                   ArchitectureName);
1953*5f757f3fSDimitry Andric }
1954*5f757f3fSDimitry Andric 
1955*5f757f3fSDimitry Andric static void dumpSymbolsNameFromMachOFilesetEntry(
1956*5f757f3fSDimitry Andric     MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList,
1957*5f757f3fSDimitry Andric     bool PrintSymbolObject, bool PrintObjectLabel) {
1958*5f757f3fSDimitry Andric   auto Buf = Obj->getMemoryBufferRef();
1959*5f757f3fSDimitry Andric   const auto *End = Obj->load_commands().end();
1960*5f757f3fSDimitry Andric   for (const auto *It = Obj->load_commands().begin(); It != End; ++It) {
1961*5f757f3fSDimitry Andric     const auto &Command = *It;
1962*5f757f3fSDimitry Andric     if (Command.C.cmd != MachO::LC_FILESET_ENTRY)
1963*5f757f3fSDimitry Andric       continue;
1964*5f757f3fSDimitry Andric 
1965*5f757f3fSDimitry Andric     MachO::fileset_entry_command Entry =
1966*5f757f3fSDimitry Andric         Obj->getFilesetEntryLoadCommand(Command);
1967*5f757f3fSDimitry Andric     auto MaybeMachO =
1968*5f757f3fSDimitry Andric         MachOObjectFile::createMachOObjectFile(Buf, 0, 0, Entry.fileoff);
1969*5f757f3fSDimitry Andric 
1970*5f757f3fSDimitry Andric     if (Error Err = MaybeMachO.takeError())
1971*5f757f3fSDimitry Andric       report_fatal_error(std::move(Err));
1972*5f757f3fSDimitry Andric 
1973*5f757f3fSDimitry Andric     const char *EntryName = Command.Ptr + Entry.entry_id.offset;
1974*5f757f3fSDimitry Andric     if (EntryName)
1975*5f757f3fSDimitry Andric       outs() << "Symbols for " << EntryName << ": \n";
1976*5f757f3fSDimitry Andric 
1977*5f757f3fSDimitry Andric     std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());
1978*5f757f3fSDimitry Andric     printSymbolNamesFromObject(*EntryMachO, SymbolList, PrintSymbolObject,
1979*5f757f3fSDimitry Andric                                PrintObjectLabel);
1980*5f757f3fSDimitry Andric 
1981*5f757f3fSDimitry Andric     if (std::next(It) != End)
1982*5f757f3fSDimitry Andric       outs() << "\n";
1983*5f757f3fSDimitry Andric   }
1984*5f757f3fSDimitry Andric }
1985*5f757f3fSDimitry Andric 
198681ad6265SDimitry Andric static void dumpSymbolNamesFromObject(
198781ad6265SDimitry Andric     SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
198881ad6265SDimitry Andric     bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
198981ad6265SDimitry Andric     StringRef ArchitectureName = {}, StringRef ObjectName = {},
199081ad6265SDimitry Andric     bool PrintArchiveName = true) {
199181ad6265SDimitry Andric   if (!shouldDump(Obj))
199281ad6265SDimitry Andric     return;
199381ad6265SDimitry Andric 
199481ad6265SDimitry Andric   if (ExportSymbols && Obj.isXCOFF()) {
199581ad6265SDimitry Andric     XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj);
199681ad6265SDimitry Andric     getXCOFFExports(XCOFFObj, SymbolList, ArchiveName);
199781ad6265SDimitry Andric     return;
199881ad6265SDimitry Andric   }
199981ad6265SDimitry Andric 
20000b57cec5SDimitry Andric   CurrentFilename = Obj.getFileName();
20015ffd83dbSDimitry Andric 
2002*5f757f3fSDimitry Andric   // Are we handling a MachO of type MH_FILESET?
2003*5f757f3fSDimitry Andric   if (Obj.isMachO() && Obj.is64Bit() &&
2004*5f757f3fSDimitry Andric       cast<MachOObjectFile>(&Obj)->getHeader64().filetype ==
2005*5f757f3fSDimitry Andric           MachO::MH_FILESET) {
2006*5f757f3fSDimitry Andric     dumpSymbolsNameFromMachOFilesetEntry(cast<MachOObjectFile>(&Obj),
2007*5f757f3fSDimitry Andric                                          SymbolList, PrintSymbolObject,
2008*5f757f3fSDimitry Andric                                          PrintObjectLabel);
2009*5f757f3fSDimitry Andric     return;
20105ffd83dbSDimitry Andric   }
20115ffd83dbSDimitry Andric 
2012*5f757f3fSDimitry Andric   printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,
2013*5f757f3fSDimitry Andric                              PrintObjectLabel, ArchiveName, ArchitectureName,
2014*5f757f3fSDimitry Andric                              ObjectName, PrintArchiveName);
20150b57cec5SDimitry Andric }
20160b57cec5SDimitry Andric 
20170b57cec5SDimitry Andric // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
20180b57cec5SDimitry Andric // and if it is and there is a list of architecture flags is specified then
20190b57cec5SDimitry Andric // check to make sure this Mach-O file is one of those architectures or all
20200b57cec5SDimitry Andric // architectures was specificed.  If not then an error is generated and this
20210b57cec5SDimitry Andric // routine returns false.  Else it returns true.
202281ad6265SDimitry Andric static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) {
20230b57cec5SDimitry Andric   auto *MachO = dyn_cast<MachOObjectFile>(O);
20240b57cec5SDimitry Andric 
20250b57cec5SDimitry Andric   if (!MachO || ArchAll || ArchFlags.empty())
20260b57cec5SDimitry Andric     return true;
20270b57cec5SDimitry Andric 
20280b57cec5SDimitry Andric   MachO::mach_header H;
20290b57cec5SDimitry Andric   MachO::mach_header_64 H_64;
20300b57cec5SDimitry Andric   Triple T;
20310b57cec5SDimitry Andric   const char *McpuDefault, *ArchFlag;
20320b57cec5SDimitry Andric   if (MachO->is64Bit()) {
20330b57cec5SDimitry Andric     H_64 = MachO->MachOObjectFile::getHeader64();
20340b57cec5SDimitry Andric     T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype,
20350b57cec5SDimitry Andric                                        &McpuDefault, &ArchFlag);
20360b57cec5SDimitry Andric   } else {
20370b57cec5SDimitry Andric     H = MachO->MachOObjectFile::getHeader();
20380b57cec5SDimitry Andric     T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype,
20390b57cec5SDimitry Andric                                        &McpuDefault, &ArchFlag);
20400b57cec5SDimitry Andric   }
20410b57cec5SDimitry Andric   const std::string ArchFlagName(ArchFlag);
2042e8d8bef9SDimitry Andric   if (!llvm::is_contained(ArchFlags, ArchFlagName)) {
20430b57cec5SDimitry Andric     error("No architecture specified", Filename);
20440b57cec5SDimitry Andric     return false;
20450b57cec5SDimitry Andric   }
20460b57cec5SDimitry Andric   return true;
20470b57cec5SDimitry Andric }
20480b57cec5SDimitry Andric 
204906c3fb27SDimitry Andric static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map,
205006c3fb27SDimitry Andric                             StringRef Filename) {
205106c3fb27SDimitry Andric   for (auto I : map) {
205206c3fb27SDimitry Andric     Expected<Archive::Child> C = I.getMember();
20530b57cec5SDimitry Andric     if (!C) {
20540b57cec5SDimitry Andric       error(C.takeError(), Filename);
20550b57cec5SDimitry Andric       break;
20560b57cec5SDimitry Andric     }
20570b57cec5SDimitry Andric     Expected<StringRef> FileNameOrErr = C->getName();
20580b57cec5SDimitry Andric     if (!FileNameOrErr) {
20590b57cec5SDimitry Andric       error(FileNameOrErr.takeError(), Filename);
20600b57cec5SDimitry Andric       break;
20610b57cec5SDimitry Andric     }
206206c3fb27SDimitry Andric     StringRef SymName = I.getName();
20630b57cec5SDimitry Andric     outs() << SymName << " in " << FileNameOrErr.get() << "\n";
20640b57cec5SDimitry Andric   }
206506c3fb27SDimitry Andric 
20660b57cec5SDimitry Andric   outs() << "\n";
20670b57cec5SDimitry Andric }
206806c3fb27SDimitry Andric 
206906c3fb27SDimitry Andric static void dumpArchiveMap(Archive *A, StringRef Filename) {
207006c3fb27SDimitry Andric   auto Map = A->symbols();
207106c3fb27SDimitry Andric   if (!Map.empty()) {
207206c3fb27SDimitry Andric     outs() << "Archive map\n";
207306c3fb27SDimitry Andric     printArchiveMap(Map, Filename);
207406c3fb27SDimitry Andric   }
207506c3fb27SDimitry Andric 
207606c3fb27SDimitry Andric   auto ECMap = A->ec_symbols();
207706c3fb27SDimitry Andric   if (!ECMap) {
207806c3fb27SDimitry Andric     warn(ECMap.takeError(), Filename);
207906c3fb27SDimitry Andric   } else if (!ECMap->empty()) {
208006c3fb27SDimitry Andric     outs() << "Archive EC map\n";
208106c3fb27SDimitry Andric     printArchiveMap(*ECMap, Filename);
208206c3fb27SDimitry Andric   }
20830b57cec5SDimitry Andric }
20840b57cec5SDimitry Andric 
208581ad6265SDimitry Andric static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList,
208681ad6265SDimitry Andric                         StringRef Filename, LLVMContext *ContextPtr) {
208781ad6265SDimitry Andric   if (ArchiveMap)
208881ad6265SDimitry Andric     dumpArchiveMap(A, Filename);
208981ad6265SDimitry Andric 
20900b57cec5SDimitry Andric   Error Err = Error::success();
20910b57cec5SDimitry Andric   for (auto &C : A->children(Err)) {
209281ad6265SDimitry Andric     Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(ContextPtr);
20930b57cec5SDimitry Andric     if (!ChildOrErr) {
20940b57cec5SDimitry Andric       if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
20950b57cec5SDimitry Andric         error(std::move(E), Filename, C);
20960b57cec5SDimitry Andric       continue;
20970b57cec5SDimitry Andric     }
20980b57cec5SDimitry Andric     if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
20990b57cec5SDimitry Andric       if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
21000b57cec5SDimitry Andric         WithColor::warning(errs(), ToolName)
21010b57cec5SDimitry Andric             << "sizes with -print-size for Mach-O files are always zero.\n";
21020b57cec5SDimitry Andric         MachOPrintSizeWarning = true;
21030b57cec5SDimitry Andric       }
21040b57cec5SDimitry Andric       if (!checkMachOAndArchFlags(O, Filename))
21050b57cec5SDimitry Andric         return;
210681ad6265SDimitry Andric       dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false,
210781ad6265SDimitry Andric                                 !PrintFileName, Filename,
210881ad6265SDimitry Andric                                 /*ArchitectureName=*/{}, O->getFileName(),
210981ad6265SDimitry Andric                                 /*PrintArchiveName=*/false);
21100b57cec5SDimitry Andric     }
21110b57cec5SDimitry Andric   }
21120b57cec5SDimitry Andric   if (Err)
21130b57cec5SDimitry Andric     error(std::move(Err), A->getFileName());
21140b57cec5SDimitry Andric }
211581ad6265SDimitry Andric 
211681ad6265SDimitry Andric static void dumpMachOUniversalBinaryMatchArchFlags(
211781ad6265SDimitry Andric     MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList,
211881ad6265SDimitry Andric     StringRef Filename, LLVMContext *ContextPtr) {
21190b57cec5SDimitry Andric   // Look for a slice in the universal binary that matches each ArchFlag.
21200b57cec5SDimitry Andric   bool ArchFound;
21210b57cec5SDimitry Andric   for (unsigned i = 0; i < ArchFlags.size(); ++i) {
21220b57cec5SDimitry Andric     ArchFound = false;
21230b57cec5SDimitry Andric     for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
21240b57cec5SDimitry Andric                                                E = UB->end_objects();
21250b57cec5SDimitry Andric          I != E; ++I) {
21260b57cec5SDimitry Andric       if (ArchFlags[i] == I->getArchFlagName()) {
21270b57cec5SDimitry Andric         ArchFound = true;
212881ad6265SDimitry Andric         Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
21290b57cec5SDimitry Andric         std::string ArchiveName;
21300b57cec5SDimitry Andric         std::string ArchitectureName;
21310b57cec5SDimitry Andric         ArchiveName.clear();
21320b57cec5SDimitry Andric         ArchitectureName.clear();
21330b57cec5SDimitry Andric         if (ObjOrErr) {
21340b57cec5SDimitry Andric           ObjectFile &Obj = *ObjOrErr.get();
213581ad6265SDimitry Andric           if (ArchFlags.size() > 1)
21360b57cec5SDimitry Andric             ArchitectureName = I->getArchFlagName();
213781ad6265SDimitry Andric           dumpSymbolNamesFromObject(Obj, SymbolList,
213881ad6265SDimitry Andric                                     /*PrintSymbolObject=*/false,
213981ad6265SDimitry Andric                                     (ArchFlags.size() > 1) && !PrintFileName,
214081ad6265SDimitry Andric                                     ArchiveName, ArchitectureName);
214181ad6265SDimitry Andric         } else if (auto E =
214281ad6265SDimitry Andric                        isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
214381ad6265SDimitry Andric           error(std::move(E), Filename,
214481ad6265SDimitry Andric                 ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
214581ad6265SDimitry Andric                                      : StringRef());
21460b57cec5SDimitry Andric           continue;
21470b57cec5SDimitry Andric         } else if (Expected<std::unique_ptr<Archive>> AOrErr =
21480b57cec5SDimitry Andric                        I->getAsArchive()) {
21490b57cec5SDimitry Andric           std::unique_ptr<Archive> &A = *AOrErr;
21500b57cec5SDimitry Andric           Error Err = Error::success();
21510b57cec5SDimitry Andric           for (auto &C : A->children(Err)) {
21520b57cec5SDimitry Andric             Expected<std::unique_ptr<Binary>> ChildOrErr =
21530b57cec5SDimitry Andric                 C.getAsBinary(ContextPtr);
21540b57cec5SDimitry Andric             if (!ChildOrErr) {
215581ad6265SDimitry Andric               if (auto E =
215681ad6265SDimitry Andric                       isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) {
215781ad6265SDimitry Andric                 error(std::move(E), Filename, C,
215881ad6265SDimitry Andric                       ArchFlags.size() > 1 ? StringRef(I->getArchFlagName())
215981ad6265SDimitry Andric                                            : StringRef());
21600b57cec5SDimitry Andric               }
21610b57cec5SDimitry Andric               continue;
21620b57cec5SDimitry Andric             }
216381ad6265SDimitry Andric             if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
21645ffd83dbSDimitry Andric               ArchiveName = std::string(A->getFileName());
21650b57cec5SDimitry Andric               if (ArchFlags.size() > 1)
21660b57cec5SDimitry Andric                 ArchitectureName = I->getArchFlagName();
216781ad6265SDimitry Andric               dumpSymbolNamesFromObject(
216881ad6265SDimitry Andric                   *O, SymbolList, /*PrintSymbolObject=*/false, !PrintFileName,
216981ad6265SDimitry Andric                   ArchiveName, ArchitectureName);
21700b57cec5SDimitry Andric             }
21710b57cec5SDimitry Andric           }
21720b57cec5SDimitry Andric           if (Err)
21730b57cec5SDimitry Andric             error(std::move(Err), A->getFileName());
21740b57cec5SDimitry Andric         } else {
21750b57cec5SDimitry Andric           consumeError(AOrErr.takeError());
21760b57cec5SDimitry Andric           error(Filename + " for architecture " +
21770b57cec5SDimitry Andric                     StringRef(I->getArchFlagName()) +
21780b57cec5SDimitry Andric                     " is not a Mach-O file or an archive file",
21790b57cec5SDimitry Andric                 "Mach-O universal file");
21800b57cec5SDimitry Andric         }
21810b57cec5SDimitry Andric       }
21820b57cec5SDimitry Andric     }
21830b57cec5SDimitry Andric     if (!ArchFound) {
21840b57cec5SDimitry Andric       error(ArchFlags[i],
21850b57cec5SDimitry Andric             "file: " + Filename + " does not contain architecture");
21860b57cec5SDimitry Andric       return;
21870b57cec5SDimitry Andric     }
21880b57cec5SDimitry Andric   }
21890b57cec5SDimitry Andric }
219081ad6265SDimitry Andric 
219181ad6265SDimitry Andric // Returns true If the binary contains a slice that matches the host
219281ad6265SDimitry Andric // architecture, or false otherwise.
219381ad6265SDimitry Andric static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB,
219481ad6265SDimitry Andric                                               std::vector<NMSymbol> &SymbolList,
219581ad6265SDimitry Andric                                               StringRef Filename,
219681ad6265SDimitry Andric                                               LLVMContext *ContextPtr) {
21970b57cec5SDimitry Andric   Triple HostTriple = MachOObjectFile::getHostArch();
21980b57cec5SDimitry Andric   StringRef HostArchName = HostTriple.getArchName();
21990b57cec5SDimitry Andric   for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
22000b57cec5SDimitry Andric                                              E = UB->end_objects();
22010b57cec5SDimitry Andric        I != E; ++I) {
22020b57cec5SDimitry Andric     if (HostArchName == I->getArchFlagName()) {
22030b57cec5SDimitry Andric       Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
22040b57cec5SDimitry Andric       std::string ArchiveName;
22050b57cec5SDimitry Andric       if (ObjOrErr) {
22060b57cec5SDimitry Andric         ObjectFile &Obj = *ObjOrErr.get();
220781ad6265SDimitry Andric         dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
220881ad6265SDimitry Andric                                   /*PrintObjectLabel=*/false);
220981ad6265SDimitry Andric       } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
22100b57cec5SDimitry Andric         error(std::move(E), Filename);
221181ad6265SDimitry Andric       else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
22120b57cec5SDimitry Andric         std::unique_ptr<Archive> &A = *AOrErr;
22130b57cec5SDimitry Andric         Error Err = Error::success();
22140b57cec5SDimitry Andric         for (auto &C : A->children(Err)) {
22150b57cec5SDimitry Andric           Expected<std::unique_ptr<Binary>> ChildOrErr =
22160b57cec5SDimitry Andric               C.getAsBinary(ContextPtr);
22170b57cec5SDimitry Andric           if (!ChildOrErr) {
221881ad6265SDimitry Andric             if (auto E =
221981ad6265SDimitry Andric                     isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
22200b57cec5SDimitry Andric               error(std::move(E), Filename, C);
22210b57cec5SDimitry Andric             continue;
22220b57cec5SDimitry Andric           }
222381ad6265SDimitry Andric           if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
22245ffd83dbSDimitry Andric             ArchiveName = std::string(A->getFileName());
222581ad6265SDimitry Andric             dumpSymbolNamesFromObject(*O, SymbolList,
222681ad6265SDimitry Andric                                       /*PrintSymbolObject=*/false,
222781ad6265SDimitry Andric                                       !PrintFileName, ArchiveName);
22280b57cec5SDimitry Andric           }
22290b57cec5SDimitry Andric         }
22300b57cec5SDimitry Andric         if (Err)
22310b57cec5SDimitry Andric           error(std::move(Err), A->getFileName());
22320b57cec5SDimitry Andric       } else {
22330b57cec5SDimitry Andric         consumeError(AOrErr.takeError());
22340b57cec5SDimitry Andric         error(Filename + " for architecture " +
22350b57cec5SDimitry Andric                   StringRef(I->getArchFlagName()) +
22360b57cec5SDimitry Andric                   " is not a Mach-O file or an archive file",
22370b57cec5SDimitry Andric               "Mach-O universal file");
22380b57cec5SDimitry Andric       }
223981ad6265SDimitry Andric       return true;
22400b57cec5SDimitry Andric     }
22410b57cec5SDimitry Andric   }
224281ad6265SDimitry Andric   return false;
22430b57cec5SDimitry Andric }
224481ad6265SDimitry Andric 
224581ad6265SDimitry Andric static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB,
224681ad6265SDimitry Andric                                             std::vector<NMSymbol> &SymbolList,
224781ad6265SDimitry Andric                                             StringRef Filename,
224881ad6265SDimitry Andric                                             LLVMContext *ContextPtr) {
22490b57cec5SDimitry Andric   bool moreThanOneArch = UB->getNumberOfObjects() > 1;
22500b57cec5SDimitry Andric   for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) {
22510b57cec5SDimitry Andric     Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile();
22520b57cec5SDimitry Andric     std::string ArchiveName;
22530b57cec5SDimitry Andric     std::string ArchitectureName;
22540b57cec5SDimitry Andric     ArchiveName.clear();
22550b57cec5SDimitry Andric     ArchitectureName.clear();
22560b57cec5SDimitry Andric     if (ObjOrErr) {
22570b57cec5SDimitry Andric       ObjectFile &Obj = *ObjOrErr.get();
22580b57cec5SDimitry Andric       if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
22590b57cec5SDimitry Andric         ArchitectureName = O.getArchFlagName();
226081ad6265SDimitry Andric       dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false,
226181ad6265SDimitry Andric                                 !PrintFileName, ArchiveName, ArchitectureName);
226281ad6265SDimitry Andric     } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
226381ad6265SDimitry Andric       error(std::move(E), Filename,
226481ad6265SDimitry Andric             moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef());
22650b57cec5SDimitry Andric       continue;
226681ad6265SDimitry Andric     } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) {
22670b57cec5SDimitry Andric       std::unique_ptr<Archive> &A = *AOrErr;
22680b57cec5SDimitry Andric       Error Err = Error::success();
22690b57cec5SDimitry Andric       for (auto &C : A->children(Err)) {
22700b57cec5SDimitry Andric         Expected<std::unique_ptr<Binary>> ChildOrErr =
22710b57cec5SDimitry Andric             C.getAsBinary(ContextPtr);
22720b57cec5SDimitry Andric         if (!ChildOrErr) {
227381ad6265SDimitry Andric           if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
227481ad6265SDimitry Andric             error(std::move(E), Filename, C,
227581ad6265SDimitry Andric                   moreThanOneArch ? StringRef(ArchitectureName) : StringRef());
22760b57cec5SDimitry Andric           continue;
22770b57cec5SDimitry Andric         }
22780b57cec5SDimitry Andric         if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
22795ffd83dbSDimitry Andric           ArchiveName = std::string(A->getFileName());
22800b57cec5SDimitry Andric           if (isa<MachOObjectFile>(F) && moreThanOneArch)
22810b57cec5SDimitry Andric             ArchitectureName = O.getArchFlagName();
228281ad6265SDimitry Andric           dumpSymbolNamesFromObject(*F, SymbolList, /*PrintSymbolObject=*/false,
228381ad6265SDimitry Andric                                     !PrintFileName, ArchiveName,
228481ad6265SDimitry Andric                                     ArchitectureName);
22850b57cec5SDimitry Andric         }
22860b57cec5SDimitry Andric       }
22870b57cec5SDimitry Andric       if (Err)
22880b57cec5SDimitry Andric         error(std::move(Err), A->getFileName());
22890b57cec5SDimitry Andric     } else {
22900b57cec5SDimitry Andric       consumeError(AOrErr.takeError());
229181ad6265SDimitry Andric       error(Filename + " for architecture " + StringRef(O.getArchFlagName()) +
22920b57cec5SDimitry Andric                 " is not a Mach-O file or an archive file",
22930b57cec5SDimitry Andric             "Mach-O universal file");
22940b57cec5SDimitry Andric     }
22950b57cec5SDimitry Andric   }
229681ad6265SDimitry Andric }
229781ad6265SDimitry Andric 
229881ad6265SDimitry Andric static void dumpMachOUniversalBinary(MachOUniversalBinary *UB,
229981ad6265SDimitry Andric                                      std::vector<NMSymbol> &SymbolList,
230081ad6265SDimitry Andric                                      StringRef Filename,
230181ad6265SDimitry Andric                                      LLVMContext *ContextPtr) {
230281ad6265SDimitry Andric   // If we have a list of architecture flags specified dump only those.
230381ad6265SDimitry Andric   if (!ArchAll && !ArchFlags.empty()) {
230481ad6265SDimitry Andric     dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename,
230581ad6265SDimitry Andric                                            ContextPtr);
23060b57cec5SDimitry Andric     return;
23070b57cec5SDimitry Andric   }
23085ffd83dbSDimitry Andric 
230981ad6265SDimitry Andric   // No architecture flags were specified so if this contains a slice that
231081ad6265SDimitry Andric   // matches the host architecture dump only that.
231181ad6265SDimitry Andric   if (!ArchAll &&
231281ad6265SDimitry Andric       dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr))
231381ad6265SDimitry Andric     return;
231481ad6265SDimitry Andric 
231581ad6265SDimitry Andric   // Either all architectures have been specified or none have been specified
231681ad6265SDimitry Andric   // and this does not contain the host architecture so dump all the slices.
231781ad6265SDimitry Andric   dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr);
231881ad6265SDimitry Andric }
231981ad6265SDimitry Andric 
232081ad6265SDimitry Andric static void dumpTapiUniversal(TapiUniversal *TU,
232181ad6265SDimitry Andric                               std::vector<NMSymbol> &SymbolList,
232281ad6265SDimitry Andric                               StringRef Filename) {
23235ffd83dbSDimitry Andric   for (const TapiUniversal::ObjectForArch &I : TU->objects()) {
23245ffd83dbSDimitry Andric     StringRef ArchName = I.getArchFlagName();
23255ffd83dbSDimitry Andric     const bool ShowArch =
2326e8d8bef9SDimitry Andric         ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName);
23275ffd83dbSDimitry Andric     if (!ShowArch)
23285ffd83dbSDimitry Andric       continue;
23295ffd83dbSDimitry Andric     if (!AddInlinedInfo && !I.isTopLevelLib())
23305ffd83dbSDimitry Andric       continue;
233181ad6265SDimitry Andric     if (auto ObjOrErr = I.getAsObjectFile())
233281ad6265SDimitry Andric       dumpSymbolNamesFromObject(
233381ad6265SDimitry Andric           *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false,
233481ad6265SDimitry Andric           /*PrintObjectLabel=*/true,
233581ad6265SDimitry Andric           /*ArchiveName=*/{}, ArchName, I.getInstallName());
233681ad6265SDimitry Andric     else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
23375ffd83dbSDimitry Andric       error(std::move(E), Filename, ArchName);
23385ffd83dbSDimitry Andric     }
23395ffd83dbSDimitry Andric   }
23405ffd83dbSDimitry Andric }
23415ffd83dbSDimitry Andric 
234281ad6265SDimitry Andric static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList,
234381ad6265SDimitry Andric                              StringRef Filename) {
23440b57cec5SDimitry Andric   if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) {
23450b57cec5SDimitry Andric     WithColor::warning(errs(), ToolName)
23460b57cec5SDimitry Andric         << "sizes with --print-size for Mach-O files are always zero.\n";
23470b57cec5SDimitry Andric     MachOPrintSizeWarning = true;
23480b57cec5SDimitry Andric   }
23490b57cec5SDimitry Andric   if (!checkMachOAndArchFlags(O, Filename))
23500b57cec5SDimitry Andric     return;
235181ad6265SDimitry Andric   dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true,
235281ad6265SDimitry Andric                             /*PrintObjectLabel=*/false);
23530b57cec5SDimitry Andric }
235481ad6265SDimitry Andric 
235581ad6265SDimitry Andric static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) {
235681ad6265SDimitry Andric   std::vector<NMSymbol> SymbolList;
235781ad6265SDimitry Andric   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
235881ad6265SDimitry Andric       MemoryBuffer::getFileOrSTDIN(Filename);
235981ad6265SDimitry Andric   if (error(BufferOrErr.getError(), Filename))
236081ad6265SDimitry Andric     return SymbolList;
236181ad6265SDimitry Andric 
2362*5f757f3fSDimitry Andric   // Ignore AIX linker import files (these files start with "#!"), when
2363*5f757f3fSDimitry Andric   // exporting symbols.
2364*5f757f3fSDimitry Andric   const char *BuffStart = (*BufferOrErr)->getBufferStart();
2365*5f757f3fSDimitry Andric   size_t BufferSize = (*BufferOrErr)->getBufferSize();
2366*5f757f3fSDimitry Andric   if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' &&
2367*5f757f3fSDimitry Andric       BuffStart[1] == '!')
2368*5f757f3fSDimitry Andric     return SymbolList;
2369*5f757f3fSDimitry Andric 
237081ad6265SDimitry Andric   LLVMContext Context;
237181ad6265SDimitry Andric   LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
237281ad6265SDimitry Andric   Expected<std::unique_ptr<Binary>> BinaryOrErr =
237381ad6265SDimitry Andric       createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr);
237481ad6265SDimitry Andric   if (!BinaryOrErr) {
237581ad6265SDimitry Andric     error(BinaryOrErr.takeError(), Filename);
237681ad6265SDimitry Andric     return SymbolList;
237781ad6265SDimitry Andric   }
237881ad6265SDimitry Andric   Binary &Bin = *BinaryOrErr.get();
237981ad6265SDimitry Andric   if (Archive *A = dyn_cast<Archive>(&Bin))
238081ad6265SDimitry Andric     dumpArchive(A, SymbolList, Filename, ContextPtr);
238181ad6265SDimitry Andric   else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin))
238281ad6265SDimitry Andric     dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr);
238381ad6265SDimitry Andric   else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin))
238481ad6265SDimitry Andric     dumpTapiUniversal(TU, SymbolList, Filename);
238581ad6265SDimitry Andric   else if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin))
238681ad6265SDimitry Andric     dumpSymbolicFile(O, SymbolList, Filename);
238781ad6265SDimitry Andric   return SymbolList;
238881ad6265SDimitry Andric }
238981ad6265SDimitry Andric 
239081ad6265SDimitry Andric static void
239181ad6265SDimitry Andric exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) {
239281ad6265SDimitry Andric   std::vector<NMSymbol> SymbolList;
239381ad6265SDimitry Andric   for (const auto &FileName : InputFilenames) {
239481ad6265SDimitry Andric     std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(FileName);
239581ad6265SDimitry Andric     SymbolList.insert(SymbolList.end(), FileSymList.begin(), FileSymList.end());
239681ad6265SDimitry Andric   }
239781ad6265SDimitry Andric 
239881ad6265SDimitry Andric   // Delete symbols which should not be printed from SymolList.
2399bdd1243dSDimitry Andric   llvm::erase_if(SymbolList,
2400bdd1243dSDimitry Andric                  [](const NMSymbol &s) { return !s.shouldPrint(); });
240181ad6265SDimitry Andric   sortSymbolList(SymbolList);
240281ad6265SDimitry Andric   SymbolList.erase(std::unique(SymbolList.begin(), SymbolList.end()),
240381ad6265SDimitry Andric                    SymbolList.end());
240481ad6265SDimitry Andric   printExportSymbolList(SymbolList);
24050b57cec5SDimitry Andric }
24060b57cec5SDimitry Andric 
240706c3fb27SDimitry Andric int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
24080b57cec5SDimitry Andric   InitLLVM X(argc, argv);
2409fe6060f1SDimitry Andric   BumpPtrAllocator A;
2410fe6060f1SDimitry Andric   StringSaver Saver(A);
2411fe6060f1SDimitry Andric   NmOptTable Tbl;
2412fe6060f1SDimitry Andric   ToolName = argv[0];
2413fe6060f1SDimitry Andric   opt::InputArgList Args =
2414fe6060f1SDimitry Andric       Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
2415fe6060f1SDimitry Andric         error(Msg);
2416fe6060f1SDimitry Andric         exit(1);
2417fe6060f1SDimitry Andric       });
2418fe6060f1SDimitry Andric   if (Args.hasArg(OPT_help)) {
2419fe6060f1SDimitry Andric     Tbl.printHelp(
2420fe6060f1SDimitry Andric         outs(),
2421fe6060f1SDimitry Andric         (Twine(ToolName) + " [options] <input object files>").str().c_str(),
2422fe6060f1SDimitry Andric         "LLVM symbol table dumper");
2423fe6060f1SDimitry Andric     // TODO Replace this with OptTable API once it adds extrahelp support.
2424fe6060f1SDimitry Andric     outs() << "\nPass @FILE as argument to read options from FILE.\n";
2425fe6060f1SDimitry Andric     return 0;
2426fe6060f1SDimitry Andric   }
2427fe6060f1SDimitry Andric   if (Args.hasArg(OPT_version)) {
2428fe6060f1SDimitry Andric     // This needs to contain the word "GNU", libtool looks for that string.
2429fe6060f1SDimitry Andric     outs() << "llvm-nm, compatible with GNU nm" << '\n';
2430fe6060f1SDimitry Andric     cl::PrintVersionMessage();
2431fe6060f1SDimitry Andric     return 0;
2432fe6060f1SDimitry Andric   }
2433fe6060f1SDimitry Andric 
2434fe6060f1SDimitry Andric   DebugSyms = Args.hasArg(OPT_debug_syms);
2435fe6060f1SDimitry Andric   DefinedOnly = Args.hasArg(OPT_defined_only);
2436fe6060f1SDimitry Andric   Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
2437fe6060f1SDimitry Andric   DynamicSyms = Args.hasArg(OPT_dynamic);
2438fe6060f1SDimitry Andric   ExternalOnly = Args.hasArg(OPT_extern_only);
2439fe6060f1SDimitry Andric   StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd");
2440fe6060f1SDimitry Andric   if (V == "bsd")
2441fe6060f1SDimitry Andric     OutputFormat = bsd;
2442fe6060f1SDimitry Andric   else if (V == "posix")
2443fe6060f1SDimitry Andric     OutputFormat = posix;
2444fe6060f1SDimitry Andric   else if (V == "sysv")
2445fe6060f1SDimitry Andric     OutputFormat = sysv;
2446fe6060f1SDimitry Andric   else if (V == "darwin")
2447fe6060f1SDimitry Andric     OutputFormat = darwin;
2448fe6060f1SDimitry Andric   else if (V == "just-symbols")
2449fe6060f1SDimitry Andric     OutputFormat = just_symbols;
2450fe6060f1SDimitry Andric   else
2451fe6060f1SDimitry Andric     error("--format value should be one of: bsd, posix, sysv, darwin, "
2452fe6060f1SDimitry Andric           "just-symbols");
2453*5f757f3fSDimitry Andric   LineNumbers = Args.hasArg(OPT_line_numbers);
2454fe6060f1SDimitry Andric   NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
2455fe6060f1SDimitry Andric   NoSort = Args.hasArg(OPT_no_sort);
2456fe6060f1SDimitry Andric   NoWeakSymbols = Args.hasArg(OPT_no_weak);
2457fe6060f1SDimitry Andric   NumericSort = Args.hasArg(OPT_numeric_sort);
2458fe6060f1SDimitry Andric   ArchiveMap = Args.hasArg(OPT_print_armap);
2459fe6060f1SDimitry Andric   PrintFileName = Args.hasArg(OPT_print_file_name);
2460fe6060f1SDimitry Andric   PrintSize = Args.hasArg(OPT_print_size);
2461fe6060f1SDimitry Andric   ReverseSort = Args.hasArg(OPT_reverse_sort);
246281ad6265SDimitry Andric   ExportSymbols = Args.hasArg(OPT_export_symbols);
246381ad6265SDimitry Andric   if (ExportSymbols) {
246481ad6265SDimitry Andric     ExternalOnly = true;
246581ad6265SDimitry Andric     DefinedOnly = true;
246681ad6265SDimitry Andric   }
246781ad6265SDimitry Andric 
2468fe6060f1SDimitry Andric   Quiet = Args.hasArg(OPT_quiet);
2469fe6060f1SDimitry Andric   V = Args.getLastArgValue(OPT_radix_EQ, "x");
2470fe6060f1SDimitry Andric   if (V == "o")
2471fe6060f1SDimitry Andric     AddressRadix = Radix::o;
2472fe6060f1SDimitry Andric   else if (V == "d")
2473fe6060f1SDimitry Andric     AddressRadix = Radix::d;
2474fe6060f1SDimitry Andric   else if (V == "x")
2475fe6060f1SDimitry Andric     AddressRadix = Radix::x;
2476fe6060f1SDimitry Andric   else
2477fe6060f1SDimitry Andric     error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' "
2478fe6060f1SDimitry Andric           "(hexadecimal)");
2479fe6060f1SDimitry Andric   SizeSort = Args.hasArg(OPT_size_sort);
2480fe6060f1SDimitry Andric   SpecialSyms = Args.hasArg(OPT_special_syms);
2481fe6060f1SDimitry Andric   UndefinedOnly = Args.hasArg(OPT_undefined_only);
2482fe6060f1SDimitry Andric   WithoutAliases = Args.hasArg(OPT_without_aliases);
2483fe6060f1SDimitry Andric 
2484bdd1243dSDimitry Andric   // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if
2485bdd1243dSDimitry Andric   // specified.
2486bdd1243dSDimitry Andric   Triple HostTriple(sys::getProcessTriple());
2487bdd1243dSDimitry Andric   if (HostTriple.isOSAIX()) {
2488bdd1243dSDimitry Andric     BitMode = StringSwitch<BitModeTy>(getenv("OBJECT_MODE"))
2489bdd1243dSDimitry Andric                   .Case("32", BitModeTy::Bit32)
2490bdd1243dSDimitry Andric                   .Case("64", BitModeTy::Bit64)
2491bdd1243dSDimitry Andric                   .Case("32_64", BitModeTy::Bit32_64)
2492bdd1243dSDimitry Andric                   .Case("any", BitModeTy::Any)
2493bdd1243dSDimitry Andric                   .Default(BitModeTy::Bit32);
2494bdd1243dSDimitry Andric   } else
2495bdd1243dSDimitry Andric     BitMode = BitModeTy::Any;
2496bdd1243dSDimitry Andric 
2497bdd1243dSDimitry Andric   if (Arg *A = Args.getLastArg(OPT_X)) {
2498bdd1243dSDimitry Andric     StringRef Mode = A->getValue();
249981ad6265SDimitry Andric     if (Mode == "32")
250081ad6265SDimitry Andric       BitMode = BitModeTy::Bit32;
250181ad6265SDimitry Andric     else if (Mode == "64")
250281ad6265SDimitry Andric       BitMode = BitModeTy::Bit64;
250381ad6265SDimitry Andric     else if (Mode == "32_64")
250481ad6265SDimitry Andric       BitMode = BitModeTy::Bit32_64;
250581ad6265SDimitry Andric     else if (Mode == "any")
250681ad6265SDimitry Andric       BitMode = BitModeTy::Any;
250781ad6265SDimitry Andric     else
250881ad6265SDimitry Andric       error("-X value should be one of: 32, 64, 32_64, (default) any");
2509bdd1243dSDimitry Andric   }
251081ad6265SDimitry Andric 
2511fe6060f1SDimitry Andric   // Mach-O specific options.
2512fe6060f1SDimitry Andric   FormatMachOasHex = Args.hasArg(OPT_x);
2513fe6060f1SDimitry Andric   AddDyldInfo = Args.hasArg(OPT_add_dyldinfo);
2514fe6060f1SDimitry Andric   AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo);
2515fe6060f1SDimitry Andric   DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only);
2516fe6060f1SDimitry Andric   NoDyldInfo = Args.hasArg(OPT_no_dyldinfo);
25170b57cec5SDimitry Andric 
251881ad6265SDimitry Andric   // XCOFF specific options.
251981ad6265SDimitry Andric   NoRsrc = Args.hasArg(OPT_no_rsrc);
252081ad6265SDimitry Andric 
25210b57cec5SDimitry Andric   // llvm-nm only reads binary files.
25220b57cec5SDimitry Andric   if (error(sys::ChangeStdinToBinary()))
25230b57cec5SDimitry Andric     return 1;
25240b57cec5SDimitry Andric 
25250b57cec5SDimitry Andric   // These calls are needed so that we can read bitcode correctly.
25260b57cec5SDimitry Andric   llvm::InitializeAllTargetInfos();
25270b57cec5SDimitry Andric   llvm::InitializeAllTargetMCs();
25280b57cec5SDimitry Andric   llvm::InitializeAllAsmParsers();
25290b57cec5SDimitry Andric 
25300b57cec5SDimitry Andric   // The relative order of these is important. If you pass --size-sort it should
25310b57cec5SDimitry Andric   // only print out the size. However, if you pass -S --size-sort, it should
25320b57cec5SDimitry Andric   // print out both the size and address.
25330b57cec5SDimitry Andric   if (SizeSort && !PrintSize)
25340b57cec5SDimitry Andric     PrintAddress = false;
25350b57cec5SDimitry Andric   if (OutputFormat == sysv || SizeSort)
25360b57cec5SDimitry Andric     PrintSize = true;
25370b57cec5SDimitry Andric 
2538fe6060f1SDimitry Andric   for (const auto *A : Args.filtered(OPT_arch_EQ)) {
2539fe6060f1SDimitry Andric     SmallVector<StringRef, 2> Values;
2540fe6060f1SDimitry Andric     llvm::SplitString(A->getValue(), Values, ",");
2541fe6060f1SDimitry Andric     for (StringRef V : Values) {
2542fe6060f1SDimitry Andric       if (V == "all")
25430b57cec5SDimitry Andric         ArchAll = true;
2544fe6060f1SDimitry Andric       else if (MachOObjectFile::isValidArch(V))
2545fe6060f1SDimitry Andric         ArchFlags.push_back(V);
2546fe6060f1SDimitry Andric       else
2547fe6060f1SDimitry Andric         error("Unknown architecture named '" + V + "'",
25480b57cec5SDimitry Andric               "for the --arch option");
25490b57cec5SDimitry Andric     }
25500b57cec5SDimitry Andric   }
25510b57cec5SDimitry Andric 
2552fe6060f1SDimitry Andric   // Mach-O takes -s to accept two arguments. We emulate this by iterating over
2553fe6060f1SDimitry Andric   // both OPT_s and OPT_INPUT.
2554fe6060f1SDimitry Andric   std::vector<std::string> InputFilenames;
2555fe6060f1SDimitry Andric   int SegSectArgs = 0;
2556fe6060f1SDimitry Andric   for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) {
2557fe6060f1SDimitry Andric     if (SegSectArgs > 0) {
2558fe6060f1SDimitry Andric       --SegSectArgs;
2559fe6060f1SDimitry Andric       SegSect.push_back(A->getValue());
2560fe6060f1SDimitry Andric     } else if (A->getOption().matches(OPT_s)) {
2561fe6060f1SDimitry Andric       SegSectArgs = 2;
2562fe6060f1SDimitry Andric     } else {
2563fe6060f1SDimitry Andric       InputFilenames.push_back(A->getValue());
2564fe6060f1SDimitry Andric     }
2565fe6060f1SDimitry Andric   }
25660b57cec5SDimitry Andric   if (!SegSect.empty() && SegSect.size() != 2)
25670b57cec5SDimitry Andric     error("bad number of arguments (must be two arguments)",
25680b57cec5SDimitry Andric           "for the -s option");
25690b57cec5SDimitry Andric 
2570fe6060f1SDimitry Andric   if (InputFilenames.empty())
2571fe6060f1SDimitry Andric     InputFilenames.push_back("a.out");
2572fe6060f1SDimitry Andric   if (InputFilenames.size() > 1)
2573fe6060f1SDimitry Andric     MultipleFiles = true;
2574fe6060f1SDimitry Andric 
25750b57cec5SDimitry Andric   if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly))
25760b57cec5SDimitry Andric     error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only");
25770b57cec5SDimitry Andric 
257881ad6265SDimitry Andric   if (ExportSymbols)
257981ad6265SDimitry Andric     exportSymbolNamesFromFiles(InputFilenames);
258081ad6265SDimitry Andric   else
25810b57cec5SDimitry Andric     llvm::for_each(InputFilenames, dumpSymbolNamesFromFile);
25820b57cec5SDimitry Andric 
25830b57cec5SDimitry Andric   if (HadError)
25840b57cec5SDimitry Andric     return 1;
2585bdd1243dSDimitry Andric   return 0;
25860b57cec5SDimitry Andric }
2587