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" 205f757f3fSDimitry Andric #include "llvm/BinaryFormat/MachO.h" 2181ad6265SDimitry Andric #include "llvm/BinaryFormat/XCOFF.h" 225f757f3fSDimitry 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" 345f757f3fSDimitry 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" 4506c3fb27SDimitry Andric #include "llvm/Support/LLVMDriver.h" 460b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 470b57cec5SDimitry Andric #include "llvm/Support/Program.h" 480b57cec5SDimitry Andric #include "llvm/Support/Signals.h" 490b57cec5SDimitry Andric #include "llvm/Support/TargetSelect.h" 500b57cec5SDimitry Andric #include "llvm/Support/WithColor.h" 510b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 5206c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h" 5306c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 540b57cec5SDimitry Andric #include <vector> 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric using namespace llvm; 570b57cec5SDimitry Andric using namespace object; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric namespace { 60fe6060f1SDimitry Andric using namespace llvm::opt; // for HelpHidden in Opts.inc 61fe6060f1SDimitry Andric enum ID { 62fe6060f1SDimitry Andric OPT_INVALID = 0, // This is not an option ID. 635f757f3fSDimitry Andric #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__), 64fe6060f1SDimitry Andric #include "Opts.inc" 65fe6060f1SDimitry Andric #undef OPTION 66fe6060f1SDimitry Andric }; 670b57cec5SDimitry Andric 68bdd1243dSDimitry Andric #define PREFIX(NAME, VALUE) \ 69bdd1243dSDimitry Andric static constexpr StringLiteral NAME##_init[] = VALUE; \ 70bdd1243dSDimitry Andric static constexpr ArrayRef<StringLiteral> NAME(NAME##_init, \ 71bdd1243dSDimitry Andric std::size(NAME##_init) - 1); 72fe6060f1SDimitry Andric #include "Opts.inc" 73fe6060f1SDimitry Andric #undef PREFIX 740b57cec5SDimitry Andric 75bdd1243dSDimitry Andric static constexpr opt::OptTable::Info InfoTable[] = { 765f757f3fSDimitry Andric #define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__), 77fe6060f1SDimitry Andric #include "Opts.inc" 78fe6060f1SDimitry Andric #undef OPTION 79fe6060f1SDimitry Andric }; 800b57cec5SDimitry Andric 81bdd1243dSDimitry Andric class NmOptTable : public opt::GenericOptTable { 82fe6060f1SDimitry Andric public: 83bdd1243dSDimitry Andric NmOptTable() : opt::GenericOptTable(InfoTable) { 84bdd1243dSDimitry Andric setGroupedShortOptions(true); 85bdd1243dSDimitry Andric } 86fe6060f1SDimitry Andric }; 870b57cec5SDimitry Andric 88fe6060f1SDimitry Andric enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols }; 8981ad6265SDimitry Andric enum class BitModeTy { Bit32, Bit64, Bit32_64, Any }; 90fe6060f1SDimitry Andric } // namespace 910b57cec5SDimitry Andric 92fe6060f1SDimitry Andric static bool ArchiveMap; 9381ad6265SDimitry Andric static BitModeTy BitMode; 94fe6060f1SDimitry Andric static bool DebugSyms; 95fe6060f1SDimitry Andric static bool DefinedOnly; 96fe6060f1SDimitry Andric static bool Demangle; 97fe6060f1SDimitry Andric static bool DynamicSyms; 9881ad6265SDimitry Andric static bool ExportSymbols; 99fe6060f1SDimitry Andric static bool ExternalOnly; 1005f757f3fSDimitry Andric static bool LineNumbers; 101fe6060f1SDimitry Andric static OutputFormatTy OutputFormat; 102fe6060f1SDimitry Andric static bool NoLLVMBitcode; 103fe6060f1SDimitry Andric static bool NoSort; 104fe6060f1SDimitry Andric static bool NoWeakSymbols; 105fe6060f1SDimitry Andric static bool NumericSort; 106fe6060f1SDimitry Andric static bool PrintFileName; 107fe6060f1SDimitry Andric static bool PrintSize; 108fe6060f1SDimitry Andric static bool Quiet; 109fe6060f1SDimitry Andric static bool ReverseSort; 110fe6060f1SDimitry Andric static bool SpecialSyms; 111fe6060f1SDimitry Andric static bool SizeSort; 112fe6060f1SDimitry Andric static bool UndefinedOnly; 113fe6060f1SDimitry Andric static bool WithoutAliases; 1140b57cec5SDimitry Andric 11581ad6265SDimitry Andric // XCOFF-specific options. 11681ad6265SDimitry Andric static bool NoRsrc; 11781ad6265SDimitry Andric 118fe6060f1SDimitry Andric namespace { 1190b57cec5SDimitry Andric enum Radix { d, o, x }; 120fe6060f1SDimitry Andric } // namespace 121fe6060f1SDimitry Andric static Radix AddressRadix; 1220b57cec5SDimitry Andric 123fe6060f1SDimitry Andric // Mach-O specific options. 124fe6060f1SDimitry Andric static bool ArchAll = false; 125fe6060f1SDimitry Andric static std::vector<StringRef> ArchFlags; 126fe6060f1SDimitry Andric static bool AddDyldInfo; 127fe6060f1SDimitry Andric static bool AddInlinedInfo; 128fe6060f1SDimitry Andric static bool DyldInfoOnly; 129fe6060f1SDimitry Andric static bool FormatMachOasHex; 130fe6060f1SDimitry Andric static bool NoDyldInfo; 131fe6060f1SDimitry Andric static std::vector<StringRef> SegSect; 132fe6060f1SDimitry Andric static bool MachOPrintSizeWarning = false; 1330b57cec5SDimitry Andric 134fe6060f1SDimitry Andric // Miscellaneous states. 135fe6060f1SDimitry Andric static bool PrintAddress = true; 136fe6060f1SDimitry Andric static bool MultipleFiles = false; 137fe6060f1SDimitry Andric static bool HadError = false; 1380b57cec5SDimitry Andric 139fe6060f1SDimitry Andric static StringRef ToolName; 1400b57cec5SDimitry Andric 14181ad6265SDimitry Andric static void warn(Error Err, Twine FileName, Twine Context = Twine(), 14281ad6265SDimitry Andric Twine Archive = Twine()) { 14304eeddc0SDimitry Andric assert(Err); 14404eeddc0SDimitry Andric 14504eeddc0SDimitry Andric // Flush the standard output so that the warning isn't interleaved with other 14604eeddc0SDimitry Andric // output if stdout and stderr are writing to the same place. 14704eeddc0SDimitry Andric outs().flush(); 14804eeddc0SDimitry Andric 14904eeddc0SDimitry Andric handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) { 15004eeddc0SDimitry Andric WithColor::warning(errs(), ToolName) 15181ad6265SDimitry Andric << (Archive.str().empty() ? FileName : Archive + "(" + FileName + ")") 15281ad6265SDimitry Andric << ": " << (Context.str().empty() ? "" : Context + ": ") << EI.message() 15381ad6265SDimitry Andric << "\n"; 15404eeddc0SDimitry Andric }); 15504eeddc0SDimitry Andric } 15604eeddc0SDimitry Andric 1570b57cec5SDimitry Andric static void error(Twine Message, Twine Path = Twine()) { 1580b57cec5SDimitry Andric HadError = true; 159fe6060f1SDimitry Andric WithColor::error(errs(), ToolName) << Path << ": " << Message << "\n"; 1600b57cec5SDimitry Andric } 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric static bool error(std::error_code EC, Twine Path = Twine()) { 1630b57cec5SDimitry Andric if (EC) { 1640b57cec5SDimitry Andric error(EC.message(), Path); 1650b57cec5SDimitry Andric return true; 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric return false; 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // This version of error() prints the archive name and member name, for example: 1710b57cec5SDimitry Andric // "libx.a(foo.o)" after the ToolName before the error message. It sets 1720b57cec5SDimitry Andric // HadError but returns allowing the code to move on to other archive members. 1730b57cec5SDimitry Andric static void error(llvm::Error E, StringRef FileName, const Archive::Child &C, 1740b57cec5SDimitry Andric StringRef ArchitectureName = StringRef()) { 1750b57cec5SDimitry Andric HadError = true; 1760b57cec5SDimitry Andric WithColor::error(errs(), ToolName) << FileName; 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric Expected<StringRef> NameOrErr = C.getName(); 1790b57cec5SDimitry Andric // TODO: if we have a error getting the name then it would be nice to print 1800b57cec5SDimitry Andric // the index of which archive member this is and or its offset in the 1810b57cec5SDimitry Andric // archive instead of "???" as the name. 1820b57cec5SDimitry Andric if (!NameOrErr) { 1830b57cec5SDimitry Andric consumeError(NameOrErr.takeError()); 1840b57cec5SDimitry Andric errs() << "(" << "???" << ")"; 1850b57cec5SDimitry Andric } else 1860b57cec5SDimitry Andric errs() << "(" << NameOrErr.get() << ")"; 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric if (!ArchitectureName.empty()) 1890b57cec5SDimitry Andric errs() << " (for architecture " << ArchitectureName << ")"; 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric std::string Buf; 1920b57cec5SDimitry Andric raw_string_ostream OS(Buf); 1930b57cec5SDimitry Andric logAllUnhandledErrors(std::move(E), OS); 1940b57cec5SDimitry Andric OS.flush(); 195fe6060f1SDimitry Andric errs() << ": " << Buf << "\n"; 1960b57cec5SDimitry Andric } 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric // This version of error() prints the file name and which architecture slice it 1990b57cec5SDimitry Andric // is from, for example: "foo.o (for architecture i386)" after the ToolName 2000b57cec5SDimitry Andric // before the error message. It sets HadError but returns allowing the code to 2010b57cec5SDimitry Andric // move on to other architecture slices. 2020b57cec5SDimitry Andric static void error(llvm::Error E, StringRef FileName, 2030b57cec5SDimitry Andric StringRef ArchitectureName = StringRef()) { 2040b57cec5SDimitry Andric HadError = true; 2050b57cec5SDimitry Andric WithColor::error(errs(), ToolName) << FileName; 2060b57cec5SDimitry Andric 2070b57cec5SDimitry Andric if (!ArchitectureName.empty()) 2080b57cec5SDimitry Andric errs() << " (for architecture " << ArchitectureName << ")"; 2090b57cec5SDimitry Andric 2100b57cec5SDimitry Andric std::string Buf; 2110b57cec5SDimitry Andric raw_string_ostream OS(Buf); 2120b57cec5SDimitry Andric logAllUnhandledErrors(std::move(E), OS); 2130b57cec5SDimitry Andric OS.flush(); 214fe6060f1SDimitry Andric errs() << ": " << Buf << "\n"; 2150b57cec5SDimitry Andric } 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric namespace { 2180b57cec5SDimitry Andric struct NMSymbol { 2190b57cec5SDimitry Andric uint64_t Address; 2200b57cec5SDimitry Andric uint64_t Size; 2210b57cec5SDimitry Andric char TypeChar; 222e8d8bef9SDimitry Andric std::string Name; 2230b57cec5SDimitry Andric StringRef SectionName; 2240b57cec5SDimitry Andric StringRef TypeName; 2250b57cec5SDimitry Andric BasicSymbolRef Sym; 22681ad6265SDimitry Andric StringRef Visibility; 22781ad6265SDimitry Andric 2280b57cec5SDimitry Andric // The Sym field above points to the native symbol in the object file, 2290b57cec5SDimitry Andric // for Mach-O when we are creating symbols from the dyld info the above 2300b57cec5SDimitry Andric // pointer is null as there is no native symbol. In these cases the fields 2310b57cec5SDimitry Andric // below are filled in to represent what would have been a Mach-O nlist 2320b57cec5SDimitry Andric // native symbol. 2330b57cec5SDimitry Andric uint32_t SymFlags; 2340b57cec5SDimitry Andric SectionRef Section; 2350b57cec5SDimitry Andric uint8_t NType; 2360b57cec5SDimitry Andric uint8_t NSect; 2370b57cec5SDimitry Andric uint16_t NDesc; 238e8d8bef9SDimitry Andric std::string IndirectName; 23981ad6265SDimitry Andric 24081ad6265SDimitry Andric bool isDefined() const { 2415f757f3fSDimitry Andric if (Sym.getRawDataRefImpl().p) 2425f757f3fSDimitry Andric return !(SymFlags & SymbolRef::SF_Undefined); 24381ad6265SDimitry Andric return TypeChar != 'U'; 24481ad6265SDimitry Andric } 24581ad6265SDimitry Andric 24681ad6265SDimitry Andric bool initializeFlags(const SymbolicFile &Obj) { 24781ad6265SDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 24881ad6265SDimitry Andric if (!SymFlagsOrErr) { 24981ad6265SDimitry Andric // TODO: Test this error. 25081ad6265SDimitry Andric error(SymFlagsOrErr.takeError(), Obj.getFileName()); 25181ad6265SDimitry Andric return false; 25281ad6265SDimitry Andric } 25381ad6265SDimitry Andric SymFlags = *SymFlagsOrErr; 25481ad6265SDimitry Andric return true; 25581ad6265SDimitry Andric } 25681ad6265SDimitry Andric 25781ad6265SDimitry Andric bool shouldPrint() const { 25881ad6265SDimitry Andric bool Undefined = SymFlags & SymbolRef::SF_Undefined; 25981ad6265SDimitry Andric bool Global = SymFlags & SymbolRef::SF_Global; 26081ad6265SDimitry Andric bool Weak = SymFlags & SymbolRef::SF_Weak; 26181ad6265SDimitry Andric bool FormatSpecific = SymFlags & SymbolRef::SF_FormatSpecific; 26281ad6265SDimitry Andric if ((!Undefined && UndefinedOnly) || (Undefined && DefinedOnly) || 26381ad6265SDimitry Andric (!Global && ExternalOnly) || (Weak && NoWeakSymbols) || 26481ad6265SDimitry Andric (FormatSpecific && !(SpecialSyms || DebugSyms))) 26581ad6265SDimitry Andric return false; 26681ad6265SDimitry Andric return true; 26781ad6265SDimitry Andric } 2680b57cec5SDimitry Andric }; 2690b57cec5SDimitry Andric 27081ad6265SDimitry Andric bool operator<(const NMSymbol &A, const NMSymbol &B) { 27181ad6265SDimitry Andric if (NumericSort) 27281ad6265SDimitry Andric return std::make_tuple(A.isDefined(), A.Address, A.Name, A.Size) < 27381ad6265SDimitry Andric std::make_tuple(B.isDefined(), B.Address, B.Name, B.Size); 27481ad6265SDimitry Andric if (SizeSort) 2750b57cec5SDimitry Andric return std::make_tuple(A.Size, A.Name, A.Address) < 2760b57cec5SDimitry Andric std::make_tuple(B.Size, B.Name, B.Address); 27781ad6265SDimitry Andric if (ExportSymbols) 27881ad6265SDimitry Andric return std::make_tuple(A.Name, A.Visibility) < 27981ad6265SDimitry Andric std::make_tuple(B.Name, B.Visibility); 2800b57cec5SDimitry Andric return std::make_tuple(A.Name, A.Size, A.Address) < 2810b57cec5SDimitry Andric std::make_tuple(B.Name, B.Size, B.Address); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 28481ad6265SDimitry Andric bool operator>(const NMSymbol &A, const NMSymbol &B) { return B < A; } 28581ad6265SDimitry Andric bool operator==(const NMSymbol &A, const NMSymbol &B) { 28681ad6265SDimitry Andric return !(A < B) && !(B < A); 28781ad6265SDimitry Andric } 28881ad6265SDimitry Andric } // anonymous namespace 28981ad6265SDimitry Andric 2900b57cec5SDimitry Andric static StringRef CurrentFilename; 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric // darwinPrintSymbol() is used to print a symbol from a Mach-O file when the 2950b57cec5SDimitry Andric // the OutputFormat is darwin or we are printing Mach-O symbols in hex. For 2960b57cec5SDimitry Andric // the darwin format it produces the same output as darwin's nm(1) -m output 2970b57cec5SDimitry Andric // and when printing Mach-O symbols in hex it produces the same output as 2980b57cec5SDimitry Andric // darwin's nm(1) -x format. 2990b57cec5SDimitry Andric static void darwinPrintSymbol(SymbolicFile &Obj, const NMSymbol &S, 3000b57cec5SDimitry Andric char *SymbolAddrStr, const char *printBlanks, 3010b57cec5SDimitry Andric const char *printDashes, 3020b57cec5SDimitry Andric const char *printFormat) { 3030b57cec5SDimitry Andric MachO::mach_header H; 3040b57cec5SDimitry Andric MachO::mach_header_64 H_64; 3050b57cec5SDimitry Andric uint32_t Filetype = MachO::MH_OBJECT; 3060b57cec5SDimitry Andric uint32_t Flags = 0; 3070b57cec5SDimitry Andric uint8_t NType = 0; 3080b57cec5SDimitry Andric uint8_t NSect = 0; 3090b57cec5SDimitry Andric uint16_t NDesc = 0; 3100b57cec5SDimitry Andric uint32_t NStrx = 0; 3110b57cec5SDimitry Andric uint64_t NValue = 0; 3120b57cec5SDimitry Andric MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); 3130b57cec5SDimitry Andric if (Obj.isIR()) { 3145ffd83dbSDimitry Andric uint32_t SymFlags = cantFail(S.Sym.getFlags()); 3150b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Global) 3160b57cec5SDimitry Andric NType |= MachO::N_EXT; 3170b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Hidden) 3180b57cec5SDimitry Andric NType |= MachO::N_PEXT; 3190b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Undefined) 3200b57cec5SDimitry Andric NType |= MachO::N_EXT | MachO::N_UNDF; 3210b57cec5SDimitry Andric else { 3220b57cec5SDimitry Andric // Here we have a symbol definition. So to fake out a section name we 3230b57cec5SDimitry Andric // use 1, 2 and 3 for section numbers. See below where they are used to 3240b57cec5SDimitry Andric // print out fake section names. 3250b57cec5SDimitry Andric NType |= MachO::N_SECT; 3260b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Const) 3270b57cec5SDimitry Andric NSect = 3; 3280b57cec5SDimitry Andric else if (SymFlags & SymbolRef::SF_Executable) 3290b57cec5SDimitry Andric NSect = 1; 3300b57cec5SDimitry Andric else 3310b57cec5SDimitry Andric NSect = 2; 3320b57cec5SDimitry Andric } 3330b57cec5SDimitry Andric if (SymFlags & SymbolRef::SF_Weak) 3340b57cec5SDimitry Andric NDesc |= MachO::N_WEAK_DEF; 3350b57cec5SDimitry Andric } else { 3360b57cec5SDimitry Andric DataRefImpl SymDRI = S.Sym.getRawDataRefImpl(); 3370b57cec5SDimitry Andric if (MachO->is64Bit()) { 3380b57cec5SDimitry Andric H_64 = MachO->MachOObjectFile::getHeader64(); 3390b57cec5SDimitry Andric Filetype = H_64.filetype; 3400b57cec5SDimitry Andric Flags = H_64.flags; 3410b57cec5SDimitry Andric if (SymDRI.p){ 3420b57cec5SDimitry Andric MachO::nlist_64 STE_64 = MachO->getSymbol64TableEntry(SymDRI); 3430b57cec5SDimitry Andric NType = STE_64.n_type; 3440b57cec5SDimitry Andric NSect = STE_64.n_sect; 3450b57cec5SDimitry Andric NDesc = STE_64.n_desc; 3460b57cec5SDimitry Andric NStrx = STE_64.n_strx; 3470b57cec5SDimitry Andric NValue = STE_64.n_value; 3480b57cec5SDimitry Andric } else { 3490b57cec5SDimitry Andric NType = S.NType; 3500b57cec5SDimitry Andric NSect = S.NSect; 3510b57cec5SDimitry Andric NDesc = S.NDesc; 3520b57cec5SDimitry Andric NStrx = 0; 3530b57cec5SDimitry Andric NValue = S.Address; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric } else { 3560b57cec5SDimitry Andric H = MachO->MachOObjectFile::getHeader(); 3570b57cec5SDimitry Andric Filetype = H.filetype; 3580b57cec5SDimitry Andric Flags = H.flags; 3590b57cec5SDimitry Andric if (SymDRI.p){ 3600b57cec5SDimitry Andric MachO::nlist STE = MachO->getSymbolTableEntry(SymDRI); 3610b57cec5SDimitry Andric NType = STE.n_type; 3620b57cec5SDimitry Andric NSect = STE.n_sect; 3630b57cec5SDimitry Andric NDesc = STE.n_desc; 3640b57cec5SDimitry Andric NStrx = STE.n_strx; 3650b57cec5SDimitry Andric NValue = STE.n_value; 3660b57cec5SDimitry Andric } else { 3670b57cec5SDimitry Andric NType = S.NType; 3680b57cec5SDimitry Andric NSect = S.NSect; 3690b57cec5SDimitry Andric NDesc = S.NDesc; 3700b57cec5SDimitry Andric NStrx = 0; 3710b57cec5SDimitry Andric NValue = S.Address; 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric } 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric // If we are printing Mach-O symbols in hex do that and return. 3770b57cec5SDimitry Andric if (FormatMachOasHex) { 3780b57cec5SDimitry Andric outs() << format(printFormat, NValue) << ' ' 3790b57cec5SDimitry Andric << format("%02x %02x %04x %08x", NType, NSect, NDesc, NStrx) << ' ' 3800b57cec5SDimitry Andric << S.Name; 3810b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_INDR) { 3820b57cec5SDimitry Andric outs() << " (indirect for "; 3830b57cec5SDimitry Andric outs() << format(printFormat, NValue) << ' '; 3840b57cec5SDimitry Andric StringRef IndirectName; 3850b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 3860b57cec5SDimitry Andric if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName)) 3870b57cec5SDimitry Andric outs() << "?)"; 3880b57cec5SDimitry Andric else 3890b57cec5SDimitry Andric outs() << IndirectName << ")"; 3900b57cec5SDimitry Andric } else 3910b57cec5SDimitry Andric outs() << S.IndirectName << ")"; 3920b57cec5SDimitry Andric } 3930b57cec5SDimitry Andric outs() << "\n"; 3940b57cec5SDimitry Andric return; 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric if (PrintAddress) { 3980b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_INDR) 3990b57cec5SDimitry Andric strcpy(SymbolAddrStr, printBlanks); 4000b57cec5SDimitry Andric if (Obj.isIR() && (NType & MachO::N_TYPE) == MachO::N_TYPE) 4010b57cec5SDimitry Andric strcpy(SymbolAddrStr, printDashes); 4020b57cec5SDimitry Andric outs() << SymbolAddrStr << ' '; 4030b57cec5SDimitry Andric } 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric switch (NType & MachO::N_TYPE) { 4060b57cec5SDimitry Andric case MachO::N_UNDF: 4070b57cec5SDimitry Andric if (NValue != 0) { 4080b57cec5SDimitry Andric outs() << "(common) "; 4090b57cec5SDimitry Andric if (MachO::GET_COMM_ALIGN(NDesc) != 0) 4100b57cec5SDimitry Andric outs() << "(alignment 2^" << (int)MachO::GET_COMM_ALIGN(NDesc) << ") "; 4110b57cec5SDimitry Andric } else { 4120b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_PBUD) 4130b57cec5SDimitry Andric outs() << "(prebound "; 4140b57cec5SDimitry Andric else 4150b57cec5SDimitry Andric outs() << "("; 4160b57cec5SDimitry Andric if ((NDesc & MachO::REFERENCE_TYPE) == 4170b57cec5SDimitry Andric MachO::REFERENCE_FLAG_UNDEFINED_LAZY) 4180b57cec5SDimitry Andric outs() << "undefined [lazy bound]) "; 4190b57cec5SDimitry Andric else if ((NDesc & MachO::REFERENCE_TYPE) == 4200b57cec5SDimitry Andric MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY) 4210b57cec5SDimitry Andric outs() << "undefined [private lazy bound]) "; 4220b57cec5SDimitry Andric else if ((NDesc & MachO::REFERENCE_TYPE) == 4230b57cec5SDimitry Andric MachO::REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY) 4240b57cec5SDimitry Andric outs() << "undefined [private]) "; 4250b57cec5SDimitry Andric else 4260b57cec5SDimitry Andric outs() << "undefined) "; 4270b57cec5SDimitry Andric } 4280b57cec5SDimitry Andric break; 4290b57cec5SDimitry Andric case MachO::N_ABS: 4300b57cec5SDimitry Andric outs() << "(absolute) "; 4310b57cec5SDimitry Andric break; 4320b57cec5SDimitry Andric case MachO::N_INDR: 4330b57cec5SDimitry Andric outs() << "(indirect) "; 4340b57cec5SDimitry Andric break; 4350b57cec5SDimitry Andric case MachO::N_SECT: { 4360b57cec5SDimitry Andric if (Obj.isIR()) { 4370b57cec5SDimitry Andric // For llvm bitcode files print out a fake section name using the values 4380b57cec5SDimitry Andric // use 1, 2 and 3 for section numbers as set above. 4390b57cec5SDimitry Andric if (NSect == 1) 4400b57cec5SDimitry Andric outs() << "(LTO,CODE) "; 4410b57cec5SDimitry Andric else if (NSect == 2) 4420b57cec5SDimitry Andric outs() << "(LTO,DATA) "; 4430b57cec5SDimitry Andric else if (NSect == 3) 4440b57cec5SDimitry Andric outs() << "(LTO,RODATA) "; 4450b57cec5SDimitry Andric else 4460b57cec5SDimitry Andric outs() << "(?,?) "; 4470b57cec5SDimitry Andric break; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric section_iterator Sec = SectionRef(); 4500b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 4510b57cec5SDimitry Andric Expected<section_iterator> SecOrErr = 4520b57cec5SDimitry Andric MachO->getSymbolSection(S.Sym.getRawDataRefImpl()); 4530b57cec5SDimitry Andric if (!SecOrErr) { 4540b57cec5SDimitry Andric consumeError(SecOrErr.takeError()); 4550b57cec5SDimitry Andric outs() << "(?,?) "; 4560b57cec5SDimitry Andric break; 4570b57cec5SDimitry Andric } 4580b57cec5SDimitry Andric Sec = *SecOrErr; 4590b57cec5SDimitry Andric if (Sec == MachO->section_end()) { 4600b57cec5SDimitry Andric outs() << "(?,?) "; 4610b57cec5SDimitry Andric break; 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric } else { 4640b57cec5SDimitry Andric Sec = S.Section; 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric DataRefImpl Ref = Sec->getRawDataRefImpl(); 4670b57cec5SDimitry Andric StringRef SectionName; 4680b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = MachO->getSectionName(Ref)) 4690b57cec5SDimitry Andric SectionName = *NameOrErr; 4700b57cec5SDimitry Andric StringRef SegmentName = MachO->getSectionFinalSegmentName(Ref); 4710b57cec5SDimitry Andric outs() << "(" << SegmentName << "," << SectionName << ") "; 4720b57cec5SDimitry Andric break; 4730b57cec5SDimitry Andric } 4740b57cec5SDimitry Andric default: 4750b57cec5SDimitry Andric outs() << "(?) "; 4760b57cec5SDimitry Andric break; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric if (NType & MachO::N_EXT) { 4800b57cec5SDimitry Andric if (NDesc & MachO::REFERENCED_DYNAMICALLY) 4810b57cec5SDimitry Andric outs() << "[referenced dynamically] "; 4820b57cec5SDimitry Andric if (NType & MachO::N_PEXT) { 4830b57cec5SDimitry Andric if ((NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) 4840b57cec5SDimitry Andric outs() << "weak private external "; 4850b57cec5SDimitry Andric else 4860b57cec5SDimitry Andric outs() << "private external "; 4870b57cec5SDimitry Andric } else { 4880b57cec5SDimitry Andric if ((NDesc & MachO::N_WEAK_REF) == MachO::N_WEAK_REF || 4890b57cec5SDimitry Andric (NDesc & MachO::N_WEAK_DEF) == MachO::N_WEAK_DEF) { 4900b57cec5SDimitry Andric if ((NDesc & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) == 4910b57cec5SDimitry Andric (MachO::N_WEAK_REF | MachO::N_WEAK_DEF)) 4920b57cec5SDimitry Andric outs() << "weak external automatically hidden "; 4930b57cec5SDimitry Andric else 4940b57cec5SDimitry Andric outs() << "weak external "; 4950b57cec5SDimitry Andric } else 4960b57cec5SDimitry Andric outs() << "external "; 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric } else { 4990b57cec5SDimitry Andric if (NType & MachO::N_PEXT) 5000b57cec5SDimitry Andric outs() << "non-external (was a private external) "; 5010b57cec5SDimitry Andric else 5020b57cec5SDimitry Andric outs() << "non-external "; 5030b57cec5SDimitry Andric } 5040b57cec5SDimitry Andric 5050b57cec5SDimitry Andric if (Filetype == MachO::MH_OBJECT) { 5060b57cec5SDimitry Andric if (NDesc & MachO::N_NO_DEAD_STRIP) 5070b57cec5SDimitry Andric outs() << "[no dead strip] "; 5080b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) != MachO::N_UNDF && 5090b57cec5SDimitry Andric NDesc & MachO::N_SYMBOL_RESOLVER) 5100b57cec5SDimitry Andric outs() << "[symbol resolver] "; 5110b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_ALT_ENTRY) 5120b57cec5SDimitry Andric outs() << "[alt entry] "; 5130b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) != MachO::N_UNDF && NDesc & MachO::N_COLD_FUNC) 5140b57cec5SDimitry Andric outs() << "[cold func] "; 5150b57cec5SDimitry Andric } 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric if ((NDesc & MachO::N_ARM_THUMB_DEF) == MachO::N_ARM_THUMB_DEF) 5180b57cec5SDimitry Andric outs() << "[Thumb] "; 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric if ((NType & MachO::N_TYPE) == MachO::N_INDR) { 5210b57cec5SDimitry Andric outs() << S.Name << " (for "; 5220b57cec5SDimitry Andric StringRef IndirectName; 5230b57cec5SDimitry Andric if (MachO) { 5240b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 5250b57cec5SDimitry Andric if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName)) 5260b57cec5SDimitry Andric outs() << "?)"; 5270b57cec5SDimitry Andric else 5280b57cec5SDimitry Andric outs() << IndirectName << ")"; 5290b57cec5SDimitry Andric } else 5300b57cec5SDimitry Andric outs() << S.IndirectName << ")"; 5310b57cec5SDimitry Andric } else 5320b57cec5SDimitry Andric outs() << "?)"; 5330b57cec5SDimitry Andric } else 5340b57cec5SDimitry Andric outs() << S.Name; 5350b57cec5SDimitry Andric 5360b57cec5SDimitry Andric if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL && 5370b57cec5SDimitry Andric (((NType & MachO::N_TYPE) == MachO::N_UNDF && NValue == 0) || 5380b57cec5SDimitry Andric (NType & MachO::N_TYPE) == MachO::N_PBUD)) { 5390b57cec5SDimitry Andric uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc); 5400b57cec5SDimitry Andric if (LibraryOrdinal != 0) { 5410b57cec5SDimitry Andric if (LibraryOrdinal == MachO::EXECUTABLE_ORDINAL) 5420b57cec5SDimitry Andric outs() << " (from executable)"; 5430b57cec5SDimitry Andric else if (LibraryOrdinal == MachO::DYNAMIC_LOOKUP_ORDINAL) 5440b57cec5SDimitry Andric outs() << " (dynamically looked up)"; 5450b57cec5SDimitry Andric else { 5460b57cec5SDimitry Andric StringRef LibraryName; 5470b57cec5SDimitry Andric if (!MachO || 5480b57cec5SDimitry Andric MachO->getLibraryShortNameByIndex(LibraryOrdinal - 1, LibraryName)) 5490b57cec5SDimitry Andric outs() << " (from bad library ordinal " << LibraryOrdinal << ")"; 5500b57cec5SDimitry Andric else 5510b57cec5SDimitry Andric outs() << " (from " << LibraryName << ")"; 5520b57cec5SDimitry Andric } 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric } 5550b57cec5SDimitry Andric } 5560b57cec5SDimitry Andric 5570b57cec5SDimitry Andric // Table that maps Darwin's Mach-O stab constants to strings to allow printing. 5580b57cec5SDimitry Andric struct DarwinStabName { 5590b57cec5SDimitry Andric uint8_t NType; 5600b57cec5SDimitry Andric const char *Name; 5610b57cec5SDimitry Andric }; 562349cc55cSDimitry Andric const struct DarwinStabName DarwinStabNames[] = { 5635f757f3fSDimitry Andric {MachO::N_GSYM, "GSYM"}, {MachO::N_FNAME, "FNAME"}, 5645f757f3fSDimitry Andric {MachO::N_FUN, "FUN"}, {MachO::N_STSYM, "STSYM"}, 5655f757f3fSDimitry Andric {MachO::N_LCSYM, "LCSYM"}, {MachO::N_BNSYM, "BNSYM"}, 5665f757f3fSDimitry Andric {MachO::N_PC, "PC"}, {MachO::N_AST, "AST"}, 5675f757f3fSDimitry Andric {MachO::N_OPT, "OPT"}, {MachO::N_RSYM, "RSYM"}, 5685f757f3fSDimitry Andric {MachO::N_SLINE, "SLINE"}, {MachO::N_ENSYM, "ENSYM"}, 5695f757f3fSDimitry Andric {MachO::N_SSYM, "SSYM"}, {MachO::N_SO, "SO"}, 5705f757f3fSDimitry Andric {MachO::N_OSO, "OSO"}, {MachO::N_LIB, "LIB"}, 5715f757f3fSDimitry Andric {MachO::N_LSYM, "LSYM"}, {MachO::N_BINCL, "BINCL"}, 5725f757f3fSDimitry Andric {MachO::N_SOL, "SOL"}, {MachO::N_PARAMS, "PARAM"}, 5735f757f3fSDimitry Andric {MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"}, 5745f757f3fSDimitry Andric {MachO::N_PSYM, "PSYM"}, {MachO::N_EINCL, "EINCL"}, 5755f757f3fSDimitry Andric {MachO::N_ENTRY, "ENTRY"}, {MachO::N_LBRAC, "LBRAC"}, 5765f757f3fSDimitry Andric {MachO::N_EXCL, "EXCL"}, {MachO::N_RBRAC, "RBRAC"}, 5775f757f3fSDimitry Andric {MachO::N_BCOMM, "BCOMM"}, {MachO::N_ECOMM, "ECOMM"}, 5785f757f3fSDimitry Andric {MachO::N_ECOML, "ECOML"}, {MachO::N_LENG, "LENG"}, 5790b57cec5SDimitry Andric }; 5800b57cec5SDimitry Andric 5810b57cec5SDimitry Andric static const char *getDarwinStabString(uint8_t NType) { 582bdd1243dSDimitry Andric for (auto I : ArrayRef(DarwinStabNames)) 5830b57cec5SDimitry Andric if (I.NType == NType) 5840b57cec5SDimitry Andric return I.Name; 5850b57cec5SDimitry Andric return nullptr; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric // darwinPrintStab() prints the n_sect, n_desc along with a symbolic name of 5890b57cec5SDimitry Andric // a stab n_type value in a Mach-O file. 5900b57cec5SDimitry Andric static void darwinPrintStab(MachOObjectFile *MachO, const NMSymbol &S) { 5910b57cec5SDimitry Andric MachO::nlist_64 STE_64; 5920b57cec5SDimitry Andric MachO::nlist STE; 5930b57cec5SDimitry Andric uint8_t NType; 5940b57cec5SDimitry Andric uint8_t NSect; 5950b57cec5SDimitry Andric uint16_t NDesc; 5960b57cec5SDimitry Andric DataRefImpl SymDRI = S.Sym.getRawDataRefImpl(); 5970b57cec5SDimitry Andric if (MachO->is64Bit()) { 5980b57cec5SDimitry Andric STE_64 = MachO->getSymbol64TableEntry(SymDRI); 5990b57cec5SDimitry Andric NType = STE_64.n_type; 6000b57cec5SDimitry Andric NSect = STE_64.n_sect; 6010b57cec5SDimitry Andric NDesc = STE_64.n_desc; 6020b57cec5SDimitry Andric } else { 6030b57cec5SDimitry Andric STE = MachO->getSymbolTableEntry(SymDRI); 6040b57cec5SDimitry Andric NType = STE.n_type; 6050b57cec5SDimitry Andric NSect = STE.n_sect; 6060b57cec5SDimitry Andric NDesc = STE.n_desc; 6070b57cec5SDimitry Andric } 6080b57cec5SDimitry Andric 6090b57cec5SDimitry Andric outs() << format(" %02x %04x ", NSect, NDesc); 6100b57cec5SDimitry Andric if (const char *stabString = getDarwinStabString(NType)) 6110b57cec5SDimitry Andric outs() << format("%5.5s", stabString); 6120b57cec5SDimitry Andric else 6130b57cec5SDimitry Andric outs() << format(" %02x", NType); 6140b57cec5SDimitry Andric } 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric static bool symbolIsDefined(const NMSymbol &Sym) { 6170b57cec5SDimitry Andric return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v'; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6205ffd83dbSDimitry Andric static void writeFileName(raw_ostream &S, StringRef ArchiveName, 6215ffd83dbSDimitry Andric StringRef ArchitectureName) { 6225ffd83dbSDimitry Andric if (!ArchitectureName.empty()) 6235ffd83dbSDimitry Andric S << "(for architecture " << ArchitectureName << "):"; 6245ffd83dbSDimitry Andric if (OutputFormat == posix && !ArchiveName.empty()) 6255ffd83dbSDimitry Andric S << ArchiveName << "[" << CurrentFilename << "]: "; 6265ffd83dbSDimitry Andric else { 6275ffd83dbSDimitry Andric if (!ArchiveName.empty()) 6285ffd83dbSDimitry Andric S << ArchiveName << ":"; 6295ffd83dbSDimitry Andric S << CurrentFilename << ": "; 6305ffd83dbSDimitry Andric } 6315ffd83dbSDimitry Andric } 6325ffd83dbSDimitry Andric 63381ad6265SDimitry Andric static void sortSymbolList(std::vector<NMSymbol> &SymbolList) { 63481ad6265SDimitry Andric if (NoSort) 63581ad6265SDimitry Andric return; 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric if (ReverseSort) 63881ad6265SDimitry Andric llvm::sort(SymbolList, std::greater<>()); 6398bcb0991SDimitry Andric else 64081ad6265SDimitry Andric llvm::sort(SymbolList); 6410b57cec5SDimitry Andric } 6420b57cec5SDimitry Andric 64381ad6265SDimitry Andric static void printExportSymbolList(const std::vector<NMSymbol> &SymbolList) { 64481ad6265SDimitry Andric for (const NMSymbol &Sym : SymbolList) { 64581ad6265SDimitry Andric outs() << Sym.Name; 64681ad6265SDimitry Andric if (!Sym.Visibility.empty()) 64781ad6265SDimitry Andric outs() << ' ' << Sym.Visibility; 64881ad6265SDimitry Andric outs() << '\n'; 64981ad6265SDimitry Andric } 65081ad6265SDimitry Andric } 65181ad6265SDimitry Andric 6525f757f3fSDimitry Andric static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer, 6535f757f3fSDimitry Andric const NMSymbol &S) { 6545f757f3fSDimitry Andric const auto *Obj = dyn_cast<ObjectFile>(S.Sym.getObject()); 6555f757f3fSDimitry Andric if (!Obj) 6565f757f3fSDimitry Andric return; 6575f757f3fSDimitry Andric const SymbolRef Sym(S.Sym); 6585f757f3fSDimitry Andric uint64_t SectionIndex = object::SectionedAddress::UndefSection; 6595f757f3fSDimitry Andric section_iterator Sec = cantFail(Sym.getSection()); 6605f757f3fSDimitry Andric if (Sec != Obj->section_end()) 6615f757f3fSDimitry Andric SectionIndex = Sec->getIndex(); 6625f757f3fSDimitry Andric object::SectionedAddress Address = {cantFail(Sym.getAddress()), SectionIndex}; 6635f757f3fSDimitry Andric 6645f757f3fSDimitry Andric std::string FileName; 6655f757f3fSDimitry Andric uint32_t Line; 6665f757f3fSDimitry Andric switch (S.TypeChar) { 6675f757f3fSDimitry Andric // For undefined symbols, find the first relocation for that symbol with a 6685f757f3fSDimitry Andric // line number. 6695f757f3fSDimitry Andric case 'U': { 6705f757f3fSDimitry Andric for (const SectionRef RelocsSec : Obj->sections()) { 6715f757f3fSDimitry Andric if (RelocsSec.relocations().empty()) 6725f757f3fSDimitry Andric continue; 6735f757f3fSDimitry Andric SectionRef TextSec = *cantFail(RelocsSec.getRelocatedSection()); 6745f757f3fSDimitry Andric if (!TextSec.isText()) 6755f757f3fSDimitry Andric continue; 6765f757f3fSDimitry Andric for (const RelocationRef R : RelocsSec.relocations()) { 6775f757f3fSDimitry Andric if (R.getSymbol() != Sym) 6785f757f3fSDimitry Andric continue; 6795f757f3fSDimitry Andric Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode( 6805f757f3fSDimitry Andric *Obj, {TextSec.getAddress() + R.getOffset(), SectionIndex}); 6815f757f3fSDimitry Andric if (!ResOrErr) { 6825f757f3fSDimitry Andric error(ResOrErr.takeError(), Obj->getFileName()); 6835f757f3fSDimitry Andric return; 6845f757f3fSDimitry Andric } 6855f757f3fSDimitry Andric if (ResOrErr->FileName == DILineInfo::BadString) 6865f757f3fSDimitry Andric return; 6875f757f3fSDimitry Andric FileName = std::move(ResOrErr->FileName); 6885f757f3fSDimitry Andric Line = ResOrErr->Line; 6895f757f3fSDimitry Andric break; 6905f757f3fSDimitry Andric } 6915f757f3fSDimitry Andric if (!FileName.empty()) 6925f757f3fSDimitry Andric break; 6935f757f3fSDimitry Andric } 6945f757f3fSDimitry Andric if (FileName.empty()) 6955f757f3fSDimitry Andric return; 6965f757f3fSDimitry Andric break; 6975f757f3fSDimitry Andric } 6985f757f3fSDimitry Andric case 't': 6995f757f3fSDimitry Andric case 'T': { 7005f757f3fSDimitry Andric Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(*Obj, Address); 7015f757f3fSDimitry Andric if (!ResOrErr) { 7025f757f3fSDimitry Andric error(ResOrErr.takeError(), Obj->getFileName()); 7035f757f3fSDimitry Andric return; 7045f757f3fSDimitry Andric } 7055f757f3fSDimitry Andric if (ResOrErr->FileName == DILineInfo::BadString) 7065f757f3fSDimitry Andric return; 7075f757f3fSDimitry Andric FileName = std::move(ResOrErr->FileName); 7085f757f3fSDimitry Andric Line = ResOrErr->Line; 7095f757f3fSDimitry Andric break; 7105f757f3fSDimitry Andric } 7115f757f3fSDimitry Andric default: { 7125f757f3fSDimitry Andric Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address); 7135f757f3fSDimitry Andric if (!ResOrErr) { 7145f757f3fSDimitry Andric error(ResOrErr.takeError(), Obj->getFileName()); 7155f757f3fSDimitry Andric return; 7165f757f3fSDimitry Andric } 7175f757f3fSDimitry Andric if (ResOrErr->DeclFile.empty()) 7185f757f3fSDimitry Andric return; 7195f757f3fSDimitry Andric FileName = std::move(ResOrErr->DeclFile); 7205f757f3fSDimitry Andric Line = ResOrErr->DeclLine; 7215f757f3fSDimitry Andric break; 7225f757f3fSDimitry Andric } 7235f757f3fSDimitry Andric } 7245f757f3fSDimitry Andric outs() << '\t' << FileName << ':' << Line; 7255f757f3fSDimitry Andric } 7265f757f3fSDimitry Andric 72781ad6265SDimitry Andric static void printSymbolList(SymbolicFile &Obj, 72881ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList, bool printName, 72981ad6265SDimitry Andric StringRef ArchiveName, StringRef ArchitectureName) { 7305f757f3fSDimitry Andric std::optional<symbolize::LLVMSymbolizer> Symbolizer; 7315f757f3fSDimitry Andric if (LineNumbers) 7325f757f3fSDimitry Andric Symbolizer.emplace(); 7335f757f3fSDimitry Andric 7340b57cec5SDimitry Andric if (!PrintFileName) { 735fe6060f1SDimitry Andric if ((OutputFormat == bsd || OutputFormat == posix || 736fe6060f1SDimitry Andric OutputFormat == just_symbols) && 737fe6060f1SDimitry Andric MultipleFiles && printName) { 7380b57cec5SDimitry Andric outs() << '\n' << CurrentFilename << ":\n"; 7390b57cec5SDimitry Andric } else if (OutputFormat == sysv) { 7400b57cec5SDimitry Andric outs() << "\n\nSymbols from " << CurrentFilename << ":\n\n"; 74106c3fb27SDimitry Andric if (Obj.is64Bit()) 7420b57cec5SDimitry Andric outs() << "Name Value Class Type" 7430b57cec5SDimitry Andric << " Size Line Section\n"; 7440b57cec5SDimitry Andric else 7450b57cec5SDimitry Andric outs() << "Name Value Class Type" 7460b57cec5SDimitry Andric << " Size Line Section\n"; 7470b57cec5SDimitry Andric } 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric const char *printBlanks, *printDashes, *printFormat; 75106c3fb27SDimitry Andric if (Obj.is64Bit()) { 7520b57cec5SDimitry Andric printBlanks = " "; 7530b57cec5SDimitry Andric printDashes = "----------------"; 7540b57cec5SDimitry Andric switch (AddressRadix) { 7550b57cec5SDimitry Andric case Radix::o: 7560b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIo64 : "%016" PRIo64; 7570b57cec5SDimitry Andric break; 7580b57cec5SDimitry Andric case Radix::x: 7590b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIx64 : "%016" PRIx64; 7600b57cec5SDimitry Andric break; 7610b57cec5SDimitry Andric default: 7620b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRId64 : "%016" PRId64; 7630b57cec5SDimitry Andric } 7640b57cec5SDimitry Andric } else { 7650b57cec5SDimitry Andric printBlanks = " "; 7660b57cec5SDimitry Andric printDashes = "--------"; 7670b57cec5SDimitry Andric switch (AddressRadix) { 7680b57cec5SDimitry Andric case Radix::o: 7690b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIo64 : "%08" PRIo64; 7700b57cec5SDimitry Andric break; 7710b57cec5SDimitry Andric case Radix::x: 7720b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRIx64 : "%08" PRIx64; 7730b57cec5SDimitry Andric break; 7740b57cec5SDimitry Andric default: 7750b57cec5SDimitry Andric printFormat = OutputFormat == posix ? "%" PRId64 : "%08" PRId64; 7760b57cec5SDimitry Andric } 7770b57cec5SDimitry Andric } 7780b57cec5SDimitry Andric 7790b57cec5SDimitry Andric for (const NMSymbol &S : SymbolList) { 78081ad6265SDimitry Andric if (!S.shouldPrint()) 78181ad6265SDimitry Andric continue; 78281ad6265SDimitry Andric 783e8d8bef9SDimitry Andric std::string Name = S.Name; 7840b57cec5SDimitry Andric MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); 7855f757f3fSDimitry Andric if (Demangle) 7865f757f3fSDimitry Andric Name = demangle(Name); 7870b57cec5SDimitry Andric 7880b57cec5SDimitry Andric if (PrintFileName) 7895ffd83dbSDimitry Andric writeFileName(outs(), ArchiveName, ArchitectureName); 790fe6060f1SDimitry Andric if ((OutputFormat == just_symbols || 7910b57cec5SDimitry Andric (UndefinedOnly && MachO && OutputFormat != darwin)) && 7920b57cec5SDimitry Andric OutputFormat != posix) { 7930b57cec5SDimitry Andric outs() << Name << "\n"; 7940b57cec5SDimitry Andric continue; 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric char SymbolAddrStr[23], SymbolSizeStr[23]; 7980b57cec5SDimitry Andric 7990b57cec5SDimitry Andric // If the format is SysV or the symbol isn't defined, then print spaces. 8000b57cec5SDimitry Andric if (OutputFormat == sysv || !symbolIsDefined(S)) { 8010b57cec5SDimitry Andric if (OutputFormat == posix) { 8020b57cec5SDimitry Andric format(printFormat, S.Address) 8030b57cec5SDimitry Andric .print(SymbolAddrStr, sizeof(SymbolAddrStr)); 8040b57cec5SDimitry Andric format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); 8050b57cec5SDimitry Andric } else { 8060b57cec5SDimitry Andric strcpy(SymbolAddrStr, printBlanks); 8070b57cec5SDimitry Andric strcpy(SymbolSizeStr, printBlanks); 8080b57cec5SDimitry Andric } 8090b57cec5SDimitry Andric } 8100b57cec5SDimitry Andric 8110b57cec5SDimitry Andric if (symbolIsDefined(S)) { 8120b57cec5SDimitry Andric // Otherwise, print the symbol address and size. 8130b57cec5SDimitry Andric if (Obj.isIR()) 8140b57cec5SDimitry Andric strcpy(SymbolAddrStr, printDashes); 8150b57cec5SDimitry Andric else if (MachO && S.TypeChar == 'I') 8160b57cec5SDimitry Andric strcpy(SymbolAddrStr, printBlanks); 8170b57cec5SDimitry Andric else 8180b57cec5SDimitry Andric format(printFormat, S.Address) 8190b57cec5SDimitry Andric .print(SymbolAddrStr, sizeof(SymbolAddrStr)); 8200b57cec5SDimitry Andric format(printFormat, S.Size).print(SymbolSizeStr, sizeof(SymbolSizeStr)); 8210b57cec5SDimitry Andric } 8220b57cec5SDimitry Andric 8230b57cec5SDimitry Andric // If OutputFormat is darwin or we are printing Mach-O symbols in hex and 8240b57cec5SDimitry Andric // we have a MachOObjectFile, call darwinPrintSymbol to print as darwin's 8250b57cec5SDimitry Andric // nm(1) -m output or hex, else if OutputFormat is darwin or we are 8260b57cec5SDimitry Andric // printing Mach-O symbols in hex and not a Mach-O object fall back to 8270b57cec5SDimitry Andric // OutputFormat bsd (see below). 8280b57cec5SDimitry Andric if ((OutputFormat == darwin || FormatMachOasHex) && (MachO || Obj.isIR())) { 8290b57cec5SDimitry Andric darwinPrintSymbol(Obj, S, SymbolAddrStr, printBlanks, printDashes, 8300b57cec5SDimitry Andric printFormat); 8310b57cec5SDimitry Andric } else if (OutputFormat == posix) { 8320b57cec5SDimitry Andric outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " " 8335f757f3fSDimitry Andric << (MachO ? "0" : SymbolSizeStr); 8340b57cec5SDimitry Andric } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) { 8350b57cec5SDimitry Andric if (PrintAddress) 8360b57cec5SDimitry Andric outs() << SymbolAddrStr << ' '; 8370b57cec5SDimitry Andric if (PrintSize) 8380b57cec5SDimitry Andric outs() << SymbolSizeStr << ' '; 8390b57cec5SDimitry Andric outs() << S.TypeChar; 8400b57cec5SDimitry Andric if (S.TypeChar == '-' && MachO) 8410b57cec5SDimitry Andric darwinPrintStab(MachO, S); 8420b57cec5SDimitry Andric outs() << " " << Name; 8430b57cec5SDimitry Andric if (S.TypeChar == 'I' && MachO) { 8440b57cec5SDimitry Andric outs() << " (indirect for "; 8450b57cec5SDimitry Andric if (S.Sym.getRawDataRefImpl().p) { 8460b57cec5SDimitry Andric StringRef IndirectName; 8470b57cec5SDimitry Andric if (MachO->getIndirectName(S.Sym.getRawDataRefImpl(), IndirectName)) 8480b57cec5SDimitry Andric outs() << "?)"; 8490b57cec5SDimitry Andric else 8500b57cec5SDimitry Andric outs() << IndirectName << ")"; 8510b57cec5SDimitry Andric } else 8520b57cec5SDimitry Andric outs() << S.IndirectName << ")"; 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric } else if (OutputFormat == sysv) { 8550b57cec5SDimitry Andric outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "| " 8560b57cec5SDimitry Andric << S.TypeChar << " |" << right_justify(S.TypeName, 18) << "|" 8575f757f3fSDimitry Andric << SymbolSizeStr << "| |" << S.SectionName; 8580b57cec5SDimitry Andric } 8595f757f3fSDimitry Andric if (LineNumbers) 8605f757f3fSDimitry Andric printLineNumbers(*Symbolizer, S); 8615f757f3fSDimitry Andric outs() << '\n'; 8620b57cec5SDimitry Andric } 8630b57cec5SDimitry Andric 8640b57cec5SDimitry Andric SymbolList.clear(); 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric static char getSymbolNMTypeChar(ELFObjectFileBase &Obj, 8680b57cec5SDimitry Andric basic_symbol_iterator I) { 8690b57cec5SDimitry Andric // OK, this is ELF 8700b57cec5SDimitry Andric elf_symbol_iterator SymI(I); 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric Expected<elf_section_iterator> SecIOrErr = SymI->getSection(); 8730b57cec5SDimitry Andric if (!SecIOrErr) { 8740b57cec5SDimitry Andric consumeError(SecIOrErr.takeError()); 8750b57cec5SDimitry Andric return '?'; 8760b57cec5SDimitry Andric } 8770b57cec5SDimitry Andric 8780b57cec5SDimitry Andric uint8_t Binding = SymI->getBinding(); 8790b57cec5SDimitry Andric if (Binding == ELF::STB_GNU_UNIQUE) 8800b57cec5SDimitry Andric return 'u'; 8810b57cec5SDimitry Andric 8820b57cec5SDimitry Andric assert(Binding != ELF::STB_WEAK && "STB_WEAK not tested in calling function"); 8830b57cec5SDimitry Andric if (Binding != ELF::STB_GLOBAL && Binding != ELF::STB_LOCAL) 8840b57cec5SDimitry Andric return '?'; 8850b57cec5SDimitry Andric 8860b57cec5SDimitry Andric elf_section_iterator SecI = *SecIOrErr; 8870b57cec5SDimitry Andric if (SecI != Obj.section_end()) { 8880b57cec5SDimitry Andric uint32_t Type = SecI->getType(); 8890b57cec5SDimitry Andric uint64_t Flags = SecI->getFlags(); 8900b57cec5SDimitry Andric if (Flags & ELF::SHF_EXECINSTR) 8910b57cec5SDimitry Andric return 't'; 8920b57cec5SDimitry Andric if (Type == ELF::SHT_NOBITS) 8930b57cec5SDimitry Andric return 'b'; 8940b57cec5SDimitry Andric if (Flags & ELF::SHF_ALLOC) 8950b57cec5SDimitry Andric return Flags & ELF::SHF_WRITE ? 'd' : 'r'; 8960b57cec5SDimitry Andric 8978bcb0991SDimitry Andric auto NameOrErr = SecI->getName(); 8988bcb0991SDimitry Andric if (!NameOrErr) { 8998bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 9000b57cec5SDimitry Andric return '?'; 9018bcb0991SDimitry Andric } 9025f757f3fSDimitry Andric if ((*NameOrErr).starts_with(".debug")) 9030b57cec5SDimitry Andric return 'N'; 9040b57cec5SDimitry Andric if (!(Flags & ELF::SHF_WRITE)) 9050b57cec5SDimitry Andric return 'n'; 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric return '?'; 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric static char getSymbolNMTypeChar(COFFObjectFile &Obj, symbol_iterator I) { 9120b57cec5SDimitry Andric COFFSymbolRef Symb = Obj.getCOFFSymbol(*I); 9130b57cec5SDimitry Andric // OK, this is COFF. 9140b57cec5SDimitry Andric symbol_iterator SymI(I); 9150b57cec5SDimitry Andric 9160b57cec5SDimitry Andric Expected<StringRef> Name = SymI->getName(); 9170b57cec5SDimitry Andric if (!Name) { 9180b57cec5SDimitry Andric consumeError(Name.takeError()); 9190b57cec5SDimitry Andric return '?'; 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric char Ret = StringSwitch<char>(*Name) 9230b57cec5SDimitry Andric .StartsWith(".debug", 'N') 9240b57cec5SDimitry Andric .StartsWith(".sxdata", 'N') 9250b57cec5SDimitry Andric .Default('?'); 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric if (Ret != '?') 9280b57cec5SDimitry Andric return Ret; 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric uint32_t Characteristics = 0; 9310b57cec5SDimitry Andric if (!COFF::isReservedSectionNumber(Symb.getSectionNumber())) { 9320b57cec5SDimitry Andric Expected<section_iterator> SecIOrErr = SymI->getSection(); 9330b57cec5SDimitry Andric if (!SecIOrErr) { 9340b57cec5SDimitry Andric consumeError(SecIOrErr.takeError()); 9350b57cec5SDimitry Andric return '?'; 9360b57cec5SDimitry Andric } 9370b57cec5SDimitry Andric section_iterator SecI = *SecIOrErr; 9380b57cec5SDimitry Andric const coff_section *Section = Obj.getCOFFSection(*SecI); 9390b57cec5SDimitry Andric Characteristics = Section->Characteristics; 9400b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section)) 9415f757f3fSDimitry Andric if (NameOrErr->starts_with(".idata")) 9420b57cec5SDimitry Andric return 'i'; 9430b57cec5SDimitry Andric } 9440b57cec5SDimitry Andric 9450b57cec5SDimitry Andric switch (Symb.getSectionNumber()) { 9460b57cec5SDimitry Andric case COFF::IMAGE_SYM_DEBUG: 9470b57cec5SDimitry Andric return 'n'; 9480b57cec5SDimitry Andric default: 9490b57cec5SDimitry Andric // Check section type. 9500b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_CNT_CODE) 9510b57cec5SDimitry Andric return 't'; 9520b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_CNT_INITIALIZED_DATA) 9530b57cec5SDimitry Andric return Characteristics & COFF::IMAGE_SCN_MEM_WRITE ? 'd' : 'r'; 9540b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) 9550b57cec5SDimitry Andric return 'b'; 9560b57cec5SDimitry Andric if (Characteristics & COFF::IMAGE_SCN_LNK_INFO) 9570b57cec5SDimitry Andric return 'i'; 9580b57cec5SDimitry Andric // Check for section symbol. 9590b57cec5SDimitry Andric if (Symb.isSectionDefinition()) 9600b57cec5SDimitry Andric return 's'; 9610b57cec5SDimitry Andric } 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric return '?'; 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 96604eeddc0SDimitry Andric static char getSymbolNMTypeChar(XCOFFObjectFile &Obj, symbol_iterator I) { 96704eeddc0SDimitry Andric Expected<uint32_t> TypeOrErr = I->getType(); 96804eeddc0SDimitry Andric if (!TypeOrErr) { 96904eeddc0SDimitry Andric warn(TypeOrErr.takeError(), Obj.getFileName(), 97004eeddc0SDimitry Andric "for symbol with index " + 97104eeddc0SDimitry Andric Twine(Obj.getSymbolIndex(I->getRawDataRefImpl().p))); 97204eeddc0SDimitry Andric return '?'; 97304eeddc0SDimitry Andric } 97404eeddc0SDimitry Andric 97504eeddc0SDimitry Andric uint32_t SymType = *TypeOrErr; 97604eeddc0SDimitry Andric 97704eeddc0SDimitry Andric if (SymType == SymbolRef::ST_File) 97804eeddc0SDimitry Andric return 'f'; 97904eeddc0SDimitry Andric 98004eeddc0SDimitry Andric // If the I->getSection() call would return an error, the earlier I->getType() 98104eeddc0SDimitry Andric // call will already have returned the same error first. 98204eeddc0SDimitry Andric section_iterator SecIter = cantFail(I->getSection()); 98304eeddc0SDimitry Andric 98404eeddc0SDimitry Andric if (SecIter == Obj.section_end()) 98504eeddc0SDimitry Andric return '?'; 98604eeddc0SDimitry Andric 98704eeddc0SDimitry Andric if (Obj.isDebugSection(SecIter->getRawDataRefImpl())) 98804eeddc0SDimitry Andric return 'N'; 98904eeddc0SDimitry Andric 99004eeddc0SDimitry Andric if (SecIter->isText()) 99104eeddc0SDimitry Andric return 't'; 99204eeddc0SDimitry Andric 99304eeddc0SDimitry Andric if (SecIter->isData()) 99404eeddc0SDimitry Andric return 'd'; 99504eeddc0SDimitry Andric 99604eeddc0SDimitry Andric if (SecIter->isBSS()) 99704eeddc0SDimitry Andric return 'b'; 99804eeddc0SDimitry Andric 99904eeddc0SDimitry Andric return '?'; 100004eeddc0SDimitry Andric } 100104eeddc0SDimitry Andric 10020b57cec5SDimitry Andric static char getSymbolNMTypeChar(COFFImportFile &Obj) { 10030b57cec5SDimitry Andric switch (Obj.getCOFFImportHeader()->getType()) { 10040b57cec5SDimitry Andric case COFF::IMPORT_CODE: 10050b57cec5SDimitry Andric return 't'; 10060b57cec5SDimitry Andric case COFF::IMPORT_DATA: 10070b57cec5SDimitry Andric return 'd'; 10080b57cec5SDimitry Andric case COFF::IMPORT_CONST: 10090b57cec5SDimitry Andric return 'r'; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric return '?'; 10120b57cec5SDimitry Andric } 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric static char getSymbolNMTypeChar(MachOObjectFile &Obj, basic_symbol_iterator I) { 10150b57cec5SDimitry Andric DataRefImpl Symb = I->getRawDataRefImpl(); 10160b57cec5SDimitry Andric uint8_t NType = Obj.is64Bit() ? Obj.getSymbol64TableEntry(Symb).n_type 10170b57cec5SDimitry Andric : Obj.getSymbolTableEntry(Symb).n_type; 10180b57cec5SDimitry Andric 10190b57cec5SDimitry Andric if (NType & MachO::N_STAB) 10200b57cec5SDimitry Andric return '-'; 10210b57cec5SDimitry Andric 10220b57cec5SDimitry Andric switch (NType & MachO::N_TYPE) { 10230b57cec5SDimitry Andric case MachO::N_ABS: 10240b57cec5SDimitry Andric return 's'; 10250b57cec5SDimitry Andric case MachO::N_INDR: 10260b57cec5SDimitry Andric return 'i'; 10270b57cec5SDimitry Andric case MachO::N_SECT: { 10280b57cec5SDimitry Andric Expected<section_iterator> SecOrErr = Obj.getSymbolSection(Symb); 10290b57cec5SDimitry Andric if (!SecOrErr) { 10300b57cec5SDimitry Andric consumeError(SecOrErr.takeError()); 10310b57cec5SDimitry Andric return 's'; 10320b57cec5SDimitry Andric } 10330b57cec5SDimitry Andric section_iterator Sec = *SecOrErr; 10340b57cec5SDimitry Andric if (Sec == Obj.section_end()) 10350b57cec5SDimitry Andric return 's'; 10360b57cec5SDimitry Andric DataRefImpl Ref = Sec->getRawDataRefImpl(); 10370b57cec5SDimitry Andric StringRef SectionName; 10380b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = Obj.getSectionName(Ref)) 10390b57cec5SDimitry Andric SectionName = *NameOrErr; 10400b57cec5SDimitry Andric StringRef SegmentName = Obj.getSectionFinalSegmentName(Ref); 10410b57cec5SDimitry Andric if (Obj.is64Bit() && Obj.getHeader64().filetype == MachO::MH_KEXT_BUNDLE && 10420b57cec5SDimitry Andric SegmentName == "__TEXT_EXEC" && SectionName == "__text") 10430b57cec5SDimitry Andric return 't'; 10440b57cec5SDimitry Andric if (SegmentName == "__TEXT" && SectionName == "__text") 10450b57cec5SDimitry Andric return 't'; 10460b57cec5SDimitry Andric if (SegmentName == "__DATA" && SectionName == "__data") 10470b57cec5SDimitry Andric return 'd'; 10480b57cec5SDimitry Andric if (SegmentName == "__DATA" && SectionName == "__bss") 10490b57cec5SDimitry Andric return 'b'; 10500b57cec5SDimitry Andric return 's'; 10510b57cec5SDimitry Andric } 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric return '?'; 10550b57cec5SDimitry Andric } 10560b57cec5SDimitry Andric 10575ffd83dbSDimitry Andric static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) { 105806c3fb27SDimitry Andric auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl())); 105906c3fb27SDimitry Andric switch (Type) { 106006c3fb27SDimitry Andric case SymbolRef::ST_Function: 106106c3fb27SDimitry Andric return 't'; 10625f757f3fSDimitry Andric case SymbolRef::ST_Data: 10635f757f3fSDimitry Andric if (Obj.hasSegmentInfo()) 10645f757f3fSDimitry Andric return 'd'; 10655f757f3fSDimitry Andric [[fallthrough]]; 106606c3fb27SDimitry Andric default: 10675ffd83dbSDimitry Andric return 's'; 10685ffd83dbSDimitry Andric } 106906c3fb27SDimitry Andric } 10705ffd83dbSDimitry Andric 10710b57cec5SDimitry Andric static char getSymbolNMTypeChar(WasmObjectFile &Obj, basic_symbol_iterator I) { 10725ffd83dbSDimitry Andric uint32_t Flags = cantFail(I->getFlags()); 10730b57cec5SDimitry Andric if (Flags & SymbolRef::SF_Executable) 10740b57cec5SDimitry Andric return 't'; 10750b57cec5SDimitry Andric return 'd'; 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric static char getSymbolNMTypeChar(IRObjectFile &Obj, basic_symbol_iterator I) { 10795ffd83dbSDimitry Andric uint32_t Flags = cantFail(I->getFlags()); 10800b57cec5SDimitry Andric // FIXME: should we print 'b'? At the IR level we cannot be sure if this 10810b57cec5SDimitry Andric // will be in bss or not, but we could approximate. 10820b57cec5SDimitry Andric if (Flags & SymbolRef::SF_Executable) 10830b57cec5SDimitry Andric return 't'; 10840b57cec5SDimitry Andric else if (Triple(Obj.getTargetTriple()).isOSDarwin() && 10850b57cec5SDimitry Andric (Flags & SymbolRef::SF_Const)) 10860b57cec5SDimitry Andric return 's'; 10870b57cec5SDimitry Andric else 10880b57cec5SDimitry Andric return 'd'; 10890b57cec5SDimitry Andric } 10900b57cec5SDimitry Andric 10910b57cec5SDimitry Andric static bool isObject(SymbolicFile &Obj, basic_symbol_iterator I) { 1092e8d8bef9SDimitry Andric return isa<ELFObjectFileBase>(&Obj) && 1093e8d8bef9SDimitry Andric elf_symbol_iterator(I)->getELFType() == ELF::STT_OBJECT; 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric // For ELF object files, Set TypeName to the symbol typename, to be printed 10970b57cec5SDimitry Andric // in the 'Type' column of the SYSV format output. 10980b57cec5SDimitry Andric static StringRef getNMTypeName(SymbolicFile &Obj, basic_symbol_iterator I) { 10990b57cec5SDimitry Andric if (isa<ELFObjectFileBase>(&Obj)) { 11000b57cec5SDimitry Andric elf_symbol_iterator SymI(I); 11010b57cec5SDimitry Andric return SymI->getELFTypeName(); 11020b57cec5SDimitry Andric } 11030b57cec5SDimitry Andric return ""; 11040b57cec5SDimitry Andric } 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric // Return Posix nm class type tag (single letter), but also set SecName and 11070b57cec5SDimitry Andric // section and name, to be used in format=sysv output. 11080b57cec5SDimitry Andric static char getNMSectionTagAndName(SymbolicFile &Obj, basic_symbol_iterator I, 11090b57cec5SDimitry Andric StringRef &SecName) { 11105ffd83dbSDimitry Andric // Symbol Flags have been checked in the caller. 11115ffd83dbSDimitry Andric uint32_t Symflags = cantFail(I->getFlags()); 11128bcb0991SDimitry Andric if (ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj)) { 11130b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Absolute) 11140b57cec5SDimitry Andric SecName = "*ABS*"; 11150b57cec5SDimitry Andric else if (Symflags & object::SymbolRef::SF_Common) 11160b57cec5SDimitry Andric SecName = "*COM*"; 11170b57cec5SDimitry Andric else if (Symflags & object::SymbolRef::SF_Undefined) 11180b57cec5SDimitry Andric SecName = "*UND*"; 11190b57cec5SDimitry Andric else { 11200b57cec5SDimitry Andric elf_symbol_iterator SymI(I); 11210b57cec5SDimitry Andric Expected<elf_section_iterator> SecIOrErr = SymI->getSection(); 11220b57cec5SDimitry Andric if (!SecIOrErr) { 11230b57cec5SDimitry Andric consumeError(SecIOrErr.takeError()); 11240b57cec5SDimitry Andric return '?'; 11250b57cec5SDimitry Andric } 11268bcb0991SDimitry Andric 11278bcb0991SDimitry Andric if (*SecIOrErr == ELFObj->section_end()) 11288bcb0991SDimitry Andric return '?'; 11298bcb0991SDimitry Andric 11308bcb0991SDimitry Andric Expected<StringRef> NameOrErr = (*SecIOrErr)->getName(); 11318bcb0991SDimitry Andric if (!NameOrErr) { 11328bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 11338bcb0991SDimitry Andric return '?'; 11348bcb0991SDimitry Andric } 11358bcb0991SDimitry Andric SecName = *NameOrErr; 11360b57cec5SDimitry Andric } 11370b57cec5SDimitry Andric } 11380b57cec5SDimitry Andric 1139fe6060f1SDimitry Andric if (Symflags & object::SymbolRef::SF_Undefined) { 1140fe6060f1SDimitry Andric if (isa<MachOObjectFile>(Obj) || !(Symflags & object::SymbolRef::SF_Weak)) 11410b57cec5SDimitry Andric return 'U'; 1142fe6060f1SDimitry Andric return isObject(Obj, I) ? 'v' : 'w'; 1143fe6060f1SDimitry Andric } 1144fe6060f1SDimitry Andric if (isa<ELFObjectFileBase>(&Obj)) 1145fe6060f1SDimitry Andric if (ELFSymbolRef(*I).getELFType() == ELF::STT_GNU_IFUNC) 1146fe6060f1SDimitry Andric return 'i'; 1147fe6060f1SDimitry Andric if (!isa<MachOObjectFile>(Obj) && (Symflags & object::SymbolRef::SF_Weak)) 1148fe6060f1SDimitry Andric return isObject(Obj, I) ? 'V' : 'W'; 11490b57cec5SDimitry Andric 11500b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Common) 11510b57cec5SDimitry Andric return 'C'; 11520b57cec5SDimitry Andric 11530b57cec5SDimitry Andric char Ret = '?'; 11540b57cec5SDimitry Andric if (Symflags & object::SymbolRef::SF_Absolute) 11550b57cec5SDimitry Andric Ret = 'a'; 11560b57cec5SDimitry Andric else if (IRObjectFile *IR = dyn_cast<IRObjectFile>(&Obj)) 11570b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*IR, I); 11580b57cec5SDimitry Andric else if (COFFObjectFile *COFF = dyn_cast<COFFObjectFile>(&Obj)) 11590b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*COFF, I); 116004eeddc0SDimitry Andric else if (XCOFFObjectFile *XCOFF = dyn_cast<XCOFFObjectFile>(&Obj)) 116104eeddc0SDimitry Andric Ret = getSymbolNMTypeChar(*XCOFF, I); 11620b57cec5SDimitry Andric else if (COFFImportFile *COFFImport = dyn_cast<COFFImportFile>(&Obj)) 11630b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*COFFImport); 11640b57cec5SDimitry Andric else if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) 11650b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*MachO, I); 11660b57cec5SDimitry Andric else if (WasmObjectFile *Wasm = dyn_cast<WasmObjectFile>(&Obj)) 11670b57cec5SDimitry Andric Ret = getSymbolNMTypeChar(*Wasm, I); 11685ffd83dbSDimitry Andric else if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj)) 11695ffd83dbSDimitry Andric Ret = getSymbolNMTypeChar(*Tapi, I); 1170480093f4SDimitry Andric else if (ELFObjectFileBase *ELF = dyn_cast<ELFObjectFileBase>(&Obj)) { 1171480093f4SDimitry Andric Ret = getSymbolNMTypeChar(*ELF, I); 1172480093f4SDimitry Andric if (ELFSymbolRef(*I).getBinding() == ELF::STB_GNU_UNIQUE) 1173480093f4SDimitry Andric return Ret; 1174480093f4SDimitry Andric } else 1175480093f4SDimitry Andric llvm_unreachable("unknown binary format"); 11760b57cec5SDimitry Andric 11770b57cec5SDimitry Andric if (!(Symflags & object::SymbolRef::SF_Global)) 11780b57cec5SDimitry Andric return Ret; 11790b57cec5SDimitry Andric 11800b57cec5SDimitry Andric return toupper(Ret); 11810b57cec5SDimitry Andric } 11820b57cec5SDimitry Andric 11830b57cec5SDimitry Andric // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname" 11840b57cec5SDimitry Andric // option to dump only those symbols from that section in a Mach-O file. 118581ad6265SDimitry Andric // It is called once for each Mach-O file from getSymbolNamesFromObject() 11860b57cec5SDimitry Andric // to get the section number for that named section from the command line 11870b57cec5SDimitry Andric // arguments. It returns the section number for that section in the Mach-O 11880b57cec5SDimitry Andric // file or zero it is not present. 11890b57cec5SDimitry Andric static unsigned getNsectForSegSect(MachOObjectFile *Obj) { 11900b57cec5SDimitry Andric unsigned Nsect = 1; 11910b57cec5SDimitry Andric for (auto &S : Obj->sections()) { 11920b57cec5SDimitry Andric DataRefImpl Ref = S.getRawDataRefImpl(); 11930b57cec5SDimitry Andric StringRef SectionName; 11940b57cec5SDimitry Andric if (Expected<StringRef> NameOrErr = Obj->getSectionName(Ref)) 11950b57cec5SDimitry Andric SectionName = *NameOrErr; 11960b57cec5SDimitry Andric StringRef SegmentName = Obj->getSectionFinalSegmentName(Ref); 11970b57cec5SDimitry Andric if (SegmentName == SegSect[0] && SectionName == SegSect[1]) 11980b57cec5SDimitry Andric return Nsect; 11990b57cec5SDimitry Andric Nsect++; 12000b57cec5SDimitry Andric } 12010b57cec5SDimitry Andric return 0; 12020b57cec5SDimitry Andric } 12030b57cec5SDimitry Andric 12040b57cec5SDimitry Andric // getNsectInMachO() is used to implement the Mach-O "-s segname sectname" 12050b57cec5SDimitry Andric // option to dump only those symbols from that section in a Mach-O file. 12060b57cec5SDimitry Andric // It is called once for each symbol in a Mach-O file from 120781ad6265SDimitry Andric // getSymbolNamesFromObject() and returns the section number for that symbol 12080b57cec5SDimitry Andric // if it is in a section, else it returns 0. 12090b57cec5SDimitry Andric static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) { 12100b57cec5SDimitry Andric DataRefImpl Symb = Sym.getRawDataRefImpl(); 12110b57cec5SDimitry Andric if (Obj.is64Bit()) { 12120b57cec5SDimitry Andric MachO::nlist_64 STE = Obj.getSymbol64TableEntry(Symb); 12130b57cec5SDimitry Andric return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric MachO::nlist STE = Obj.getSymbolTableEntry(Symb); 12160b57cec5SDimitry Andric return (STE.n_type & MachO::N_TYPE) == MachO::N_SECT ? STE.n_sect : 0; 12170b57cec5SDimitry Andric } 12180b57cec5SDimitry Andric 121981ad6265SDimitry Andric static void dumpSymbolsFromDLInfoMachO(MachOObjectFile &MachO, 122081ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList) { 1221e8d8bef9SDimitry Andric size_t I = SymbolList.size(); 12220b57cec5SDimitry Andric std::string ExportsNameBuffer; 12230b57cec5SDimitry Andric raw_string_ostream EOS(ExportsNameBuffer); 12240b57cec5SDimitry Andric std::string BindsNameBuffer; 12250b57cec5SDimitry Andric raw_string_ostream BOS(BindsNameBuffer); 12260b57cec5SDimitry Andric std::string LazysNameBuffer; 12270b57cec5SDimitry Andric raw_string_ostream LOS(LazysNameBuffer); 12280b57cec5SDimitry Andric std::string WeaksNameBuffer; 12290b57cec5SDimitry Andric raw_string_ostream WOS(WeaksNameBuffer); 12300b57cec5SDimitry Andric std::string FunctionStartsNameBuffer; 12310b57cec5SDimitry Andric raw_string_ostream FOS(FunctionStartsNameBuffer); 1232e8d8bef9SDimitry Andric 12330b57cec5SDimitry Andric MachO::mach_header H; 12340b57cec5SDimitry Andric MachO::mach_header_64 H_64; 12350b57cec5SDimitry Andric uint32_t HFlags = 0; 1236e8d8bef9SDimitry Andric if (MachO.is64Bit()) { 1237e8d8bef9SDimitry Andric H_64 = MachO.MachOObjectFile::getHeader64(); 12380b57cec5SDimitry Andric HFlags = H_64.flags; 12390b57cec5SDimitry Andric } else { 1240e8d8bef9SDimitry Andric H = MachO.MachOObjectFile::getHeader(); 12410b57cec5SDimitry Andric HFlags = H.flags; 12420b57cec5SDimitry Andric } 12430b57cec5SDimitry Andric uint64_t BaseSegmentAddress = 0; 1244e8d8bef9SDimitry Andric for (const auto &Command : MachO.load_commands()) { 12450b57cec5SDimitry Andric if (Command.C.cmd == MachO::LC_SEGMENT) { 1246e8d8bef9SDimitry Andric MachO::segment_command Seg = MachO.getSegmentLoadCommand(Command); 12470b57cec5SDimitry Andric if (Seg.fileoff == 0 && Seg.filesize != 0) { 12480b57cec5SDimitry Andric BaseSegmentAddress = Seg.vmaddr; 12490b57cec5SDimitry Andric break; 12500b57cec5SDimitry Andric } 12510b57cec5SDimitry Andric } else if (Command.C.cmd == MachO::LC_SEGMENT_64) { 1252e8d8bef9SDimitry Andric MachO::segment_command_64 Seg = MachO.getSegment64LoadCommand(Command); 12530b57cec5SDimitry Andric if (Seg.fileoff == 0 && Seg.filesize != 0) { 12540b57cec5SDimitry Andric BaseSegmentAddress = Seg.vmaddr; 12550b57cec5SDimitry Andric break; 12560b57cec5SDimitry Andric } 12570b57cec5SDimitry Andric } 12580b57cec5SDimitry Andric } 12590b57cec5SDimitry Andric if (DyldInfoOnly || AddDyldInfo || 12600b57cec5SDimitry Andric HFlags & MachO::MH_NLIST_OUTOFSYNC_WITH_DYLDINFO) { 12610b57cec5SDimitry Andric unsigned ExportsAdded = 0; 12620b57cec5SDimitry Andric Error Err = Error::success(); 1263e8d8bef9SDimitry Andric for (const llvm::object::ExportEntry &Entry : MachO.exports(Err)) { 12640b57cec5SDimitry Andric bool found = false; 12650b57cec5SDimitry Andric bool ReExport = false; 12660b57cec5SDimitry Andric if (!DyldInfoOnly) { 12670b57cec5SDimitry Andric for (const NMSymbol &S : SymbolList) 12680b57cec5SDimitry Andric if (S.Address == Entry.address() + BaseSegmentAddress && 12690b57cec5SDimitry Andric S.Name == Entry.name()) { 12700b57cec5SDimitry Andric found = true; 12710b57cec5SDimitry Andric break; 12720b57cec5SDimitry Andric } 12730b57cec5SDimitry Andric } 12740b57cec5SDimitry Andric if (!found) { 12750b57cec5SDimitry Andric NMSymbol S = {}; 12760b57cec5SDimitry Andric S.Address = Entry.address() + BaseSegmentAddress; 12770b57cec5SDimitry Andric S.Size = 0; 12780b57cec5SDimitry Andric S.TypeChar = '\0'; 1279e8d8bef9SDimitry Andric S.Name = Entry.name().str(); 12800b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 12810b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 12820b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 12830b57cec5SDimitry Andric S.Sym = BasicSymbolRef(); 12840b57cec5SDimitry Andric S.SymFlags = SymbolRef::SF_Global; 12850b57cec5SDimitry Andric S.Section = SectionRef(); 12860b57cec5SDimitry Andric S.NType = 0; 12870b57cec5SDimitry Andric S.NSect = 0; 12880b57cec5SDimitry Andric S.NDesc = 0; 12890b57cec5SDimitry Andric 12900b57cec5SDimitry Andric uint64_t EFlags = Entry.flags(); 12910b57cec5SDimitry Andric bool Abs = ((EFlags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK) == 12920b57cec5SDimitry Andric MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE); 1293e8d8bef9SDimitry Andric bool Resolver = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER); 12940b57cec5SDimitry Andric ReExport = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT); 12950b57cec5SDimitry Andric bool WeakDef = (EFlags & MachO::EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION); 12960b57cec5SDimitry Andric if (WeakDef) 12970b57cec5SDimitry Andric S.NDesc |= MachO::N_WEAK_DEF; 12980b57cec5SDimitry Andric if (Abs) { 12990b57cec5SDimitry Andric S.NType = MachO::N_EXT | MachO::N_ABS; 13000b57cec5SDimitry Andric S.TypeChar = 'A'; 13010b57cec5SDimitry Andric } else if (ReExport) { 13020b57cec5SDimitry Andric S.NType = MachO::N_EXT | MachO::N_INDR; 13030b57cec5SDimitry Andric S.TypeChar = 'I'; 13040b57cec5SDimitry Andric } else { 13050b57cec5SDimitry Andric S.NType = MachO::N_EXT | MachO::N_SECT; 13060b57cec5SDimitry Andric if (Resolver) { 13070b57cec5SDimitry Andric S.Address = Entry.other() + BaseSegmentAddress; 1308e8d8bef9SDimitry Andric if ((S.Address & 1) != 0 && !MachO.is64Bit() && 1309e8d8bef9SDimitry Andric H.cputype == MachO::CPU_TYPE_ARM) { 13100b57cec5SDimitry Andric S.Address &= ~1LL; 13110b57cec5SDimitry Andric S.NDesc |= MachO::N_ARM_THUMB_DEF; 13120b57cec5SDimitry Andric } 13130b57cec5SDimitry Andric } else { 13140b57cec5SDimitry Andric S.Address = Entry.address() + BaseSegmentAddress; 13150b57cec5SDimitry Andric } 13160b57cec5SDimitry Andric StringRef SegmentName = StringRef(); 13170b57cec5SDimitry Andric StringRef SectionName = StringRef(); 1318e8d8bef9SDimitry Andric for (const SectionRef &Section : MachO.sections()) { 13190b57cec5SDimitry Andric S.NSect++; 13208bcb0991SDimitry Andric 13218bcb0991SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 13228bcb0991SDimitry Andric SectionName = *NameOrErr; 13238bcb0991SDimitry Andric else 13248bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 13258bcb0991SDimitry Andric 1326e8d8bef9SDimitry Andric SegmentName = 1327e8d8bef9SDimitry Andric MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl()); 13280b57cec5SDimitry Andric if (S.Address >= Section.getAddress() && 13290b57cec5SDimitry Andric S.Address < Section.getAddress() + Section.getSize()) { 13300b57cec5SDimitry Andric S.Section = Section; 13310b57cec5SDimitry Andric break; 13320b57cec5SDimitry Andric } else if (Entry.name() == "__mh_execute_header" && 13330b57cec5SDimitry Andric SegmentName == "__TEXT" && SectionName == "__text") { 13340b57cec5SDimitry Andric S.Section = Section; 13350b57cec5SDimitry Andric S.NDesc |= MachO::REFERENCED_DYNAMICALLY; 13360b57cec5SDimitry Andric break; 13370b57cec5SDimitry Andric } 13380b57cec5SDimitry Andric } 13390b57cec5SDimitry Andric if (SegmentName == "__TEXT" && SectionName == "__text") 13400b57cec5SDimitry Andric S.TypeChar = 'T'; 13410b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__data") 13420b57cec5SDimitry Andric S.TypeChar = 'D'; 13430b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__bss") 13440b57cec5SDimitry Andric S.TypeChar = 'B'; 13450b57cec5SDimitry Andric else 13460b57cec5SDimitry Andric S.TypeChar = 'S'; 13470b57cec5SDimitry Andric } 13480b57cec5SDimitry Andric SymbolList.push_back(S); 13490b57cec5SDimitry Andric 13500b57cec5SDimitry Andric EOS << Entry.name(); 13510b57cec5SDimitry Andric EOS << '\0'; 13520b57cec5SDimitry Andric ExportsAdded++; 13530b57cec5SDimitry Andric 13540b57cec5SDimitry Andric // For ReExports there are a two more things to do, first add the 13550b57cec5SDimitry Andric // indirect name and second create the undefined symbol using the 13560b57cec5SDimitry Andric // referened dynamic library. 13570b57cec5SDimitry Andric if (ReExport) { 13580b57cec5SDimitry Andric 13590b57cec5SDimitry Andric // Add the indirect name. 13600b57cec5SDimitry Andric if (Entry.otherName().empty()) 13610b57cec5SDimitry Andric EOS << Entry.name(); 13620b57cec5SDimitry Andric else 13630b57cec5SDimitry Andric EOS << Entry.otherName(); 13640b57cec5SDimitry Andric EOS << '\0'; 13650b57cec5SDimitry Andric 13660b57cec5SDimitry Andric // Now create the undefined symbol using the referened dynamic 13670b57cec5SDimitry Andric // library. 13680b57cec5SDimitry Andric NMSymbol U = {}; 13690b57cec5SDimitry Andric U.Address = 0; 13700b57cec5SDimitry Andric U.Size = 0; 13710b57cec5SDimitry Andric U.TypeChar = 'U'; 13720b57cec5SDimitry Andric if (Entry.otherName().empty()) 1373e8d8bef9SDimitry Andric U.Name = Entry.name().str(); 13740b57cec5SDimitry Andric else 1375e8d8bef9SDimitry Andric U.Name = Entry.otherName().str(); 13760b57cec5SDimitry Andric // Again there is no symbol in the nlist symbol table for this so 13770b57cec5SDimitry Andric // we set Sym effectivly to null and the rest of code in here must 13780b57cec5SDimitry Andric // test for it and not do things like Sym.getFlags() for it. 13790b57cec5SDimitry Andric U.Sym = BasicSymbolRef(); 13800b57cec5SDimitry Andric U.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 13810b57cec5SDimitry Andric U.Section = SectionRef(); 13820b57cec5SDimitry Andric U.NType = MachO::N_EXT | MachO::N_UNDF; 13830b57cec5SDimitry Andric U.NSect = 0; 13840b57cec5SDimitry Andric U.NDesc = 0; 13850b57cec5SDimitry Andric // The library ordinal for this undefined symbol is in the export 13860b57cec5SDimitry Andric // trie Entry.other(). 13870b57cec5SDimitry Andric MachO::SET_LIBRARY_ORDINAL(U.NDesc, Entry.other()); 13880b57cec5SDimitry Andric SymbolList.push_back(U); 13890b57cec5SDimitry Andric 13900b57cec5SDimitry Andric // Finally add the undefined symbol's name. 13910b57cec5SDimitry Andric if (Entry.otherName().empty()) 13920b57cec5SDimitry Andric EOS << Entry.name(); 13930b57cec5SDimitry Andric else 13940b57cec5SDimitry Andric EOS << Entry.otherName(); 13950b57cec5SDimitry Andric EOS << '\0'; 13960b57cec5SDimitry Andric ExportsAdded++; 13970b57cec5SDimitry Andric } 13980b57cec5SDimitry Andric } 13990b57cec5SDimitry Andric } 14000b57cec5SDimitry Andric if (Err) 1401e8d8bef9SDimitry Andric error(std::move(Err), MachO.getFileName()); 14020b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 14030b57cec5SDimitry Andric if (ExportsAdded) { 14040b57cec5SDimitry Andric EOS.flush(); 14050b57cec5SDimitry Andric const char *Q = ExportsNameBuffer.c_str(); 14060b57cec5SDimitry Andric for (unsigned K = 0; K < ExportsAdded; K++) { 14070b57cec5SDimitry Andric SymbolList[I].Name = Q; 14080b57cec5SDimitry Andric Q += strlen(Q) + 1; 14090b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 14100b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 14110b57cec5SDimitry Andric Q += strlen(Q) + 1; 14120b57cec5SDimitry Andric } 14130b57cec5SDimitry Andric I++; 14140b57cec5SDimitry Andric } 14150b57cec5SDimitry Andric } 14160b57cec5SDimitry Andric 14170b57cec5SDimitry Andric // Add the undefined symbols from the bind entries. 14180b57cec5SDimitry Andric unsigned BindsAdded = 0; 14190b57cec5SDimitry Andric Error BErr = Error::success(); 14200b57cec5SDimitry Andric StringRef LastSymbolName = StringRef(); 1421e8d8bef9SDimitry Andric for (const llvm::object::MachOBindEntry &Entry : MachO.bindTable(BErr)) { 14220b57cec5SDimitry Andric bool found = false; 14230b57cec5SDimitry Andric if (LastSymbolName == Entry.symbolName()) 14240b57cec5SDimitry Andric found = true; 14250b57cec5SDimitry Andric else if (!DyldInfoOnly) { 14260b57cec5SDimitry Andric for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { 14270b57cec5SDimitry Andric if (SymbolList[J].Name == Entry.symbolName()) 14280b57cec5SDimitry Andric found = true; 14290b57cec5SDimitry Andric } 14300b57cec5SDimitry Andric } 14310b57cec5SDimitry Andric if (!found) { 14320b57cec5SDimitry Andric LastSymbolName = Entry.symbolName(); 14330b57cec5SDimitry Andric NMSymbol B = {}; 14340b57cec5SDimitry Andric B.Address = 0; 14350b57cec5SDimitry Andric B.Size = 0; 14360b57cec5SDimitry Andric B.TypeChar = 'U'; 14370b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 14380b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 14390b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 14400b57cec5SDimitry Andric B.Sym = BasicSymbolRef(); 14410b57cec5SDimitry Andric B.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 14420b57cec5SDimitry Andric B.NType = MachO::N_EXT | MachO::N_UNDF; 14430b57cec5SDimitry Andric B.NSect = 0; 14440b57cec5SDimitry Andric B.NDesc = 0; 14450b57cec5SDimitry Andric MachO::SET_LIBRARY_ORDINAL(B.NDesc, Entry.ordinal()); 1446e8d8bef9SDimitry Andric B.Name = Entry.symbolName().str(); 14470b57cec5SDimitry Andric SymbolList.push_back(B); 14480b57cec5SDimitry Andric BOS << Entry.symbolName(); 14490b57cec5SDimitry Andric BOS << '\0'; 14500b57cec5SDimitry Andric BindsAdded++; 14510b57cec5SDimitry Andric } 14520b57cec5SDimitry Andric } 14530b57cec5SDimitry Andric if (BErr) 1454e8d8bef9SDimitry Andric error(std::move(BErr), MachO.getFileName()); 14550b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 14560b57cec5SDimitry Andric if (BindsAdded) { 14570b57cec5SDimitry Andric BOS.flush(); 14580b57cec5SDimitry Andric const char *Q = BindsNameBuffer.c_str(); 14590b57cec5SDimitry Andric for (unsigned K = 0; K < BindsAdded; K++) { 14600b57cec5SDimitry Andric SymbolList[I].Name = Q; 14610b57cec5SDimitry Andric Q += strlen(Q) + 1; 14620b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 14630b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 14640b57cec5SDimitry Andric Q += strlen(Q) + 1; 14650b57cec5SDimitry Andric } 14660b57cec5SDimitry Andric I++; 14670b57cec5SDimitry Andric } 14680b57cec5SDimitry Andric } 14690b57cec5SDimitry Andric 14700b57cec5SDimitry Andric // Add the undefined symbols from the lazy bind entries. 14710b57cec5SDimitry Andric unsigned LazysAdded = 0; 14720b57cec5SDimitry Andric Error LErr = Error::success(); 14730b57cec5SDimitry Andric LastSymbolName = StringRef(); 14740b57cec5SDimitry Andric for (const llvm::object::MachOBindEntry &Entry : 1475e8d8bef9SDimitry Andric MachO.lazyBindTable(LErr)) { 14760b57cec5SDimitry Andric bool found = false; 14770b57cec5SDimitry Andric if (LastSymbolName == Entry.symbolName()) 14780b57cec5SDimitry Andric found = true; 14790b57cec5SDimitry Andric else { 14800b57cec5SDimitry Andric // Here we must check to see it this symbol is already in the 14810b57cec5SDimitry Andric // SymbolList as it might have already have been added above via a 14820b57cec5SDimitry Andric // non-lazy (bind) entry. 14830b57cec5SDimitry Andric for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { 14840b57cec5SDimitry Andric if (SymbolList[J].Name == Entry.symbolName()) 14850b57cec5SDimitry Andric found = true; 14860b57cec5SDimitry Andric } 14870b57cec5SDimitry Andric } 14880b57cec5SDimitry Andric if (!found) { 14890b57cec5SDimitry Andric LastSymbolName = Entry.symbolName(); 14900b57cec5SDimitry Andric NMSymbol L = {}; 1491e8d8bef9SDimitry Andric L.Name = Entry.symbolName().str(); 14920b57cec5SDimitry Andric L.Address = 0; 14930b57cec5SDimitry Andric L.Size = 0; 14940b57cec5SDimitry Andric L.TypeChar = 'U'; 14950b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 14960b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 14970b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 14980b57cec5SDimitry Andric L.Sym = BasicSymbolRef(); 14990b57cec5SDimitry Andric L.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 15000b57cec5SDimitry Andric L.NType = MachO::N_EXT | MachO::N_UNDF; 15010b57cec5SDimitry Andric L.NSect = 0; 15020b57cec5SDimitry Andric // The REFERENCE_FLAG_UNDEFINED_LAZY is no longer used but here it 15030b57cec5SDimitry Andric // makes sence since we are creating this from a lazy bind entry. 15040b57cec5SDimitry Andric L.NDesc = MachO::REFERENCE_FLAG_UNDEFINED_LAZY; 15050b57cec5SDimitry Andric MachO::SET_LIBRARY_ORDINAL(L.NDesc, Entry.ordinal()); 15060b57cec5SDimitry Andric SymbolList.push_back(L); 15070b57cec5SDimitry Andric LOS << Entry.symbolName(); 15080b57cec5SDimitry Andric LOS << '\0'; 15090b57cec5SDimitry Andric LazysAdded++; 15100b57cec5SDimitry Andric } 15110b57cec5SDimitry Andric } 15120b57cec5SDimitry Andric if (LErr) 1513e8d8bef9SDimitry Andric error(std::move(LErr), MachO.getFileName()); 15140b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 15150b57cec5SDimitry Andric if (LazysAdded) { 15160b57cec5SDimitry Andric LOS.flush(); 15170b57cec5SDimitry Andric const char *Q = LazysNameBuffer.c_str(); 15180b57cec5SDimitry Andric for (unsigned K = 0; K < LazysAdded; K++) { 15190b57cec5SDimitry Andric SymbolList[I].Name = Q; 15200b57cec5SDimitry Andric Q += strlen(Q) + 1; 15210b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 15220b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 15230b57cec5SDimitry Andric Q += strlen(Q) + 1; 15240b57cec5SDimitry Andric } 15250b57cec5SDimitry Andric I++; 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric // Add the undefineds symbol from the weak bind entries which are not 15300b57cec5SDimitry Andric // strong symbols. 15310b57cec5SDimitry Andric unsigned WeaksAdded = 0; 15320b57cec5SDimitry Andric Error WErr = Error::success(); 15330b57cec5SDimitry Andric LastSymbolName = StringRef(); 15340b57cec5SDimitry Andric for (const llvm::object::MachOBindEntry &Entry : 1535e8d8bef9SDimitry Andric MachO.weakBindTable(WErr)) { 15360b57cec5SDimitry Andric bool found = false; 15370b57cec5SDimitry Andric unsigned J = 0; 15380b57cec5SDimitry Andric if (LastSymbolName == Entry.symbolName() || 15390b57cec5SDimitry Andric Entry.flags() & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION) { 15400b57cec5SDimitry Andric found = true; 15410b57cec5SDimitry Andric } else { 15420b57cec5SDimitry Andric for (J = 0; J < SymbolList.size() && !found; ++J) { 15430b57cec5SDimitry Andric if (SymbolList[J].Name == Entry.symbolName()) { 15440b57cec5SDimitry Andric found = true; 15450b57cec5SDimitry Andric break; 15460b57cec5SDimitry Andric } 15470b57cec5SDimitry Andric } 15480b57cec5SDimitry Andric } 15490b57cec5SDimitry Andric if (!found) { 15500b57cec5SDimitry Andric LastSymbolName = Entry.symbolName(); 1551e8d8bef9SDimitry Andric NMSymbol W = {}; 1552e8d8bef9SDimitry Andric W.Name = Entry.symbolName().str(); 15530b57cec5SDimitry Andric W.Address = 0; 15540b57cec5SDimitry Andric W.Size = 0; 15550b57cec5SDimitry Andric W.TypeChar = 'U'; 15560b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 15570b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 15580b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 15590b57cec5SDimitry Andric W.Sym = BasicSymbolRef(); 15600b57cec5SDimitry Andric W.SymFlags = SymbolRef::SF_Global | SymbolRef::SF_Undefined; 15610b57cec5SDimitry Andric W.NType = MachO::N_EXT | MachO::N_UNDF; 15620b57cec5SDimitry Andric W.NSect = 0; 15630b57cec5SDimitry Andric // Odd that we are using N_WEAK_DEF on an undefined symbol but that is 15640b57cec5SDimitry Andric // what is created in this case by the linker when there are real 15650b57cec5SDimitry Andric // symbols in the nlist structs. 15660b57cec5SDimitry Andric W.NDesc = MachO::N_WEAK_DEF; 15670b57cec5SDimitry Andric SymbolList.push_back(W); 15680b57cec5SDimitry Andric WOS << Entry.symbolName(); 15690b57cec5SDimitry Andric WOS << '\0'; 15700b57cec5SDimitry Andric WeaksAdded++; 15710b57cec5SDimitry Andric } else { 15720b57cec5SDimitry Andric // This is the case the symbol was previously been found and it could 15730b57cec5SDimitry Andric // have been added from a bind or lazy bind symbol. If so and not 15740b57cec5SDimitry Andric // a definition also mark it as weak. 15750b57cec5SDimitry Andric if (SymbolList[J].TypeChar == 'U') 15760b57cec5SDimitry Andric // See comment above about N_WEAK_DEF. 15770b57cec5SDimitry Andric SymbolList[J].NDesc |= MachO::N_WEAK_DEF; 15780b57cec5SDimitry Andric } 15790b57cec5SDimitry Andric } 15800b57cec5SDimitry Andric if (WErr) 1581e8d8bef9SDimitry Andric error(std::move(WErr), MachO.getFileName()); 15820b57cec5SDimitry Andric // Set the symbol names and indirect names for the added symbols. 15830b57cec5SDimitry Andric if (WeaksAdded) { 15840b57cec5SDimitry Andric WOS.flush(); 15850b57cec5SDimitry Andric const char *Q = WeaksNameBuffer.c_str(); 15860b57cec5SDimitry Andric for (unsigned K = 0; K < WeaksAdded; K++) { 15870b57cec5SDimitry Andric SymbolList[I].Name = Q; 15880b57cec5SDimitry Andric Q += strlen(Q) + 1; 15890b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 15900b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 15910b57cec5SDimitry Andric Q += strlen(Q) + 1; 15920b57cec5SDimitry Andric } 15930b57cec5SDimitry Andric I++; 15940b57cec5SDimitry Andric } 15950b57cec5SDimitry Andric } 15960b57cec5SDimitry Andric 15970b57cec5SDimitry Andric // Trying adding symbol from the function starts table and LC_MAIN entry 15980b57cec5SDimitry Andric // point. 15990b57cec5SDimitry Andric SmallVector<uint64_t, 8> FoundFns; 16000b57cec5SDimitry Andric uint64_t lc_main_offset = UINT64_MAX; 1601e8d8bef9SDimitry Andric for (const auto &Command : MachO.load_commands()) { 16020b57cec5SDimitry Andric if (Command.C.cmd == MachO::LC_FUNCTION_STARTS) { 16030b57cec5SDimitry Andric // We found a function starts segment, parse the addresses for 16040b57cec5SDimitry Andric // consumption. 16050b57cec5SDimitry Andric MachO::linkedit_data_command LLC = 1606e8d8bef9SDimitry Andric MachO.getLinkeditDataLoadCommand(Command); 16070b57cec5SDimitry Andric 1608e8d8bef9SDimitry Andric MachO.ReadULEB128s(LLC.dataoff, FoundFns); 16090b57cec5SDimitry Andric } else if (Command.C.cmd == MachO::LC_MAIN) { 1610e8d8bef9SDimitry Andric MachO::entry_point_command LCmain = MachO.getEntryPointCommand(Command); 16110b57cec5SDimitry Andric lc_main_offset = LCmain.entryoff; 16120b57cec5SDimitry Andric } 16130b57cec5SDimitry Andric } 16140b57cec5SDimitry Andric // See if these addresses are already in the symbol table. 16150b57cec5SDimitry Andric unsigned FunctionStartsAdded = 0; 16160b57cec5SDimitry Andric for (uint64_t f = 0; f < FoundFns.size(); f++) { 16170b57cec5SDimitry Andric bool found = false; 16180b57cec5SDimitry Andric for (unsigned J = 0; J < SymbolList.size() && !found; ++J) { 16190b57cec5SDimitry Andric if (SymbolList[J].Address == FoundFns[f] + BaseSegmentAddress) 16200b57cec5SDimitry Andric found = true; 16210b57cec5SDimitry Andric } 16220b57cec5SDimitry Andric // See this address is not already in the symbol table fake up an 16230b57cec5SDimitry Andric // nlist for it. 16240b57cec5SDimitry Andric if (!found) { 16250b57cec5SDimitry Andric NMSymbol F = {}; 16260b57cec5SDimitry Andric F.Name = "<redacted function X>"; 16270b57cec5SDimitry Andric F.Address = FoundFns[f] + BaseSegmentAddress; 16280b57cec5SDimitry Andric F.Size = 0; 16290b57cec5SDimitry Andric // There is no symbol in the nlist symbol table for this so we set 16300b57cec5SDimitry Andric // Sym effectivly to null and the rest of code in here must test for 16310b57cec5SDimitry Andric // it and not do things like Sym.getFlags() for it. 16320b57cec5SDimitry Andric F.Sym = BasicSymbolRef(); 16330b57cec5SDimitry Andric F.SymFlags = 0; 16340b57cec5SDimitry Andric F.NType = MachO::N_SECT; 16350b57cec5SDimitry Andric F.NSect = 0; 16360b57cec5SDimitry Andric StringRef SegmentName = StringRef(); 16370b57cec5SDimitry Andric StringRef SectionName = StringRef(); 1638e8d8bef9SDimitry Andric for (const SectionRef &Section : MachO.sections()) { 16398bcb0991SDimitry Andric if (Expected<StringRef> NameOrErr = Section.getName()) 16408bcb0991SDimitry Andric SectionName = *NameOrErr; 16418bcb0991SDimitry Andric else 16428bcb0991SDimitry Andric consumeError(NameOrErr.takeError()); 16438bcb0991SDimitry Andric 1644e8d8bef9SDimitry Andric SegmentName = 1645e8d8bef9SDimitry Andric MachO.getSectionFinalSegmentName(Section.getRawDataRefImpl()); 16460b57cec5SDimitry Andric F.NSect++; 16470b57cec5SDimitry Andric if (F.Address >= Section.getAddress() && 16480b57cec5SDimitry Andric F.Address < Section.getAddress() + Section.getSize()) { 16490b57cec5SDimitry Andric F.Section = Section; 16500b57cec5SDimitry Andric break; 16510b57cec5SDimitry Andric } 16520b57cec5SDimitry Andric } 16530b57cec5SDimitry Andric if (SegmentName == "__TEXT" && SectionName == "__text") 16540b57cec5SDimitry Andric F.TypeChar = 't'; 16550b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__data") 16560b57cec5SDimitry Andric F.TypeChar = 'd'; 16570b57cec5SDimitry Andric else if (SegmentName == "__DATA" && SectionName == "__bss") 16580b57cec5SDimitry Andric F.TypeChar = 'b'; 16590b57cec5SDimitry Andric else 16600b57cec5SDimitry Andric F.TypeChar = 's'; 16610b57cec5SDimitry Andric F.NDesc = 0; 16620b57cec5SDimitry Andric SymbolList.push_back(F); 16630b57cec5SDimitry Andric if (FoundFns[f] == lc_main_offset) 16640b57cec5SDimitry Andric FOS << "<redacted LC_MAIN>"; 16650b57cec5SDimitry Andric else 16660b57cec5SDimitry Andric FOS << "<redacted function " << f << ">"; 16670b57cec5SDimitry Andric FOS << '\0'; 16680b57cec5SDimitry Andric FunctionStartsAdded++; 16690b57cec5SDimitry Andric } 16700b57cec5SDimitry Andric } 16710b57cec5SDimitry Andric if (FunctionStartsAdded) { 16720b57cec5SDimitry Andric FOS.flush(); 16730b57cec5SDimitry Andric const char *Q = FunctionStartsNameBuffer.c_str(); 16740b57cec5SDimitry Andric for (unsigned K = 0; K < FunctionStartsAdded; K++) { 16750b57cec5SDimitry Andric SymbolList[I].Name = Q; 16760b57cec5SDimitry Andric Q += strlen(Q) + 1; 16770b57cec5SDimitry Andric if (SymbolList[I].TypeChar == 'I') { 16780b57cec5SDimitry Andric SymbolList[I].IndirectName = Q; 16790b57cec5SDimitry Andric Q += strlen(Q) + 1; 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric I++; 16820b57cec5SDimitry Andric } 16830b57cec5SDimitry Andric } 16840b57cec5SDimitry Andric } 16850b57cec5SDimitry Andric } 16860b57cec5SDimitry Andric 168781ad6265SDimitry Andric static bool shouldDump(SymbolicFile &Obj) { 168881ad6265SDimitry Andric // The -X option is currently only implemented for XCOFF, ELF, and IR object 168981ad6265SDimitry Andric // files. The option isn't fundamentally impossible with other formats, just 169081ad6265SDimitry Andric // isn't implemented. 169181ad6265SDimitry Andric if (!isa<XCOFFObjectFile>(Obj) && !isa<ELFObjectFileBase>(Obj) && 169281ad6265SDimitry Andric !isa<IRObjectFile>(Obj)) 169381ad6265SDimitry Andric return true; 169481ad6265SDimitry Andric 169506c3fb27SDimitry Andric return Obj.is64Bit() ? BitMode != BitModeTy::Bit32 169681ad6265SDimitry Andric : BitMode != BitModeTy::Bit64; 169781ad6265SDimitry Andric } 169881ad6265SDimitry Andric 169981ad6265SDimitry Andric static void getXCOFFExports(XCOFFObjectFile *XCOFFObj, 170081ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList, 170181ad6265SDimitry Andric StringRef ArchiveName) { 170281ad6265SDimitry Andric // Skip Shared object file. 170381ad6265SDimitry Andric if (XCOFFObj->getFlags() & XCOFF::F_SHROBJ) 170481ad6265SDimitry Andric return; 170581ad6265SDimitry Andric 170681ad6265SDimitry Andric for (SymbolRef Sym : XCOFFObj->symbols()) { 170781ad6265SDimitry Andric // There is no visibility in old 32 bit XCOFF object file interpret. 170881ad6265SDimitry Andric bool HasVisibilityAttr = 170981ad6265SDimitry Andric XCOFFObj->is64Bit() || (XCOFFObj->auxiliaryHeader32() && 171081ad6265SDimitry Andric (XCOFFObj->auxiliaryHeader32()->getVersion() == 171181ad6265SDimitry Andric XCOFF::NEW_XCOFF_INTERPRET)); 171281ad6265SDimitry Andric 171381ad6265SDimitry Andric if (HasVisibilityAttr) { 171481ad6265SDimitry Andric XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl()); 171581ad6265SDimitry Andric uint16_t SymType = XCOFFSym.getSymbolType(); 171681ad6265SDimitry Andric if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_INTERNAL) 171781ad6265SDimitry Andric continue; 171881ad6265SDimitry Andric if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_HIDDEN) 171981ad6265SDimitry Andric continue; 172081ad6265SDimitry Andric } 172181ad6265SDimitry Andric 172281ad6265SDimitry Andric Expected<section_iterator> SymSecOrErr = Sym.getSection(); 172381ad6265SDimitry Andric if (!SymSecOrErr) { 172481ad6265SDimitry Andric warn(SymSecOrErr.takeError(), XCOFFObj->getFileName(), 172581ad6265SDimitry Andric "for symbol with index " + 172681ad6265SDimitry Andric Twine(XCOFFObj->getSymbolIndex(Sym.getRawDataRefImpl().p)), 172781ad6265SDimitry Andric ArchiveName); 172881ad6265SDimitry Andric continue; 172981ad6265SDimitry Andric } 173081ad6265SDimitry Andric section_iterator SecIter = *SymSecOrErr; 173181ad6265SDimitry Andric // If the symbol is not in a text or data section, it is not exported. 173281ad6265SDimitry Andric if (SecIter == XCOFFObj->section_end()) 173381ad6265SDimitry Andric continue; 173481ad6265SDimitry Andric if (!(SecIter->isText() || SecIter->isData() || SecIter->isBSS())) 173581ad6265SDimitry Andric continue; 173681ad6265SDimitry Andric 173781ad6265SDimitry Andric StringRef SymName = cantFail(Sym.getName()); 173881ad6265SDimitry Andric if (SymName.empty()) 173981ad6265SDimitry Andric continue; 17405f757f3fSDimitry Andric if (SymName.starts_with("__sinit") || SymName.starts_with("__sterm") || 174181ad6265SDimitry Andric SymName.front() == '.' || SymName.front() == '(') 174281ad6265SDimitry Andric continue; 174381ad6265SDimitry Andric 174481ad6265SDimitry Andric // Check the SymName regex matching with "^__[0-9]+__". 17455f757f3fSDimitry Andric if (SymName.size() > 4 && SymName.starts_with("__") && 17465f757f3fSDimitry Andric SymName.ends_with("__")) { 174781ad6265SDimitry Andric if (std::all_of(SymName.begin() + 2, SymName.end() - 2, isDigit)) 174881ad6265SDimitry Andric continue; 174981ad6265SDimitry Andric } 175081ad6265SDimitry Andric 175181ad6265SDimitry Andric if (SymName == "__rsrc" && NoRsrc) 175281ad6265SDimitry Andric continue; 175381ad6265SDimitry Andric 17545f757f3fSDimitry Andric if (SymName.starts_with("__tf1")) 175581ad6265SDimitry Andric SymName = SymName.substr(6); 17565f757f3fSDimitry Andric else if (SymName.starts_with("__tf9")) 175781ad6265SDimitry Andric SymName = SymName.substr(14); 175881ad6265SDimitry Andric 175981ad6265SDimitry Andric NMSymbol S = {}; 176081ad6265SDimitry Andric S.Name = SymName.str(); 176181ad6265SDimitry Andric S.Sym = Sym; 176281ad6265SDimitry Andric 176381ad6265SDimitry Andric if (HasVisibilityAttr) { 176481ad6265SDimitry Andric XCOFFSymbolRef XCOFFSym = XCOFFObj->toSymbolRef(Sym.getRawDataRefImpl()); 176581ad6265SDimitry Andric uint16_t SymType = XCOFFSym.getSymbolType(); 176681ad6265SDimitry Andric if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_PROTECTED) 176781ad6265SDimitry Andric S.Visibility = "protected"; 176881ad6265SDimitry Andric else if ((SymType & XCOFF::VISIBILITY_MASK) == XCOFF::SYM_V_EXPORTED) 176981ad6265SDimitry Andric S.Visibility = "export"; 177081ad6265SDimitry Andric } 177181ad6265SDimitry Andric if (S.initializeFlags(*XCOFFObj)) 177281ad6265SDimitry Andric SymbolList.push_back(S); 177381ad6265SDimitry Andric } 177481ad6265SDimitry Andric } 177581ad6265SDimitry Andric 177681ad6265SDimitry Andric static Expected<SymbolicFile::basic_symbol_iterator_range> 177781ad6265SDimitry Andric getDynamicSyms(SymbolicFile &Obj) { 177881ad6265SDimitry Andric const auto *E = dyn_cast<ELFObjectFileBase>(&Obj); 177981ad6265SDimitry Andric if (!E) 178081ad6265SDimitry Andric return createError("File format has no dynamic symbol table"); 178181ad6265SDimitry Andric return E->getDynamicSymbolIterators(); 178281ad6265SDimitry Andric } 178381ad6265SDimitry Andric 178481ad6265SDimitry Andric // Returns false if there is error found or true otherwise. 178581ad6265SDimitry Andric static bool getSymbolNamesFromObject(SymbolicFile &Obj, 178681ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList) { 1787e8d8bef9SDimitry Andric auto Symbols = Obj.symbols(); 1788349cc55cSDimitry Andric std::vector<VersionEntry> SymbolVersions; 1789e8d8bef9SDimitry Andric 179081ad6265SDimitry Andric if (DynamicSyms) { 179181ad6265SDimitry Andric Expected<SymbolicFile::basic_symbol_iterator_range> SymbolsOrErr = 179281ad6265SDimitry Andric getDynamicSyms(Obj); 179381ad6265SDimitry Andric if (!SymbolsOrErr) { 179481ad6265SDimitry Andric error(SymbolsOrErr.takeError(), Obj.getFileName()); 179581ad6265SDimitry Andric return false; 179681ad6265SDimitry Andric } 179781ad6265SDimitry Andric Symbols = *SymbolsOrErr; 179881ad6265SDimitry Andric if (const auto *E = dyn_cast<ELFObjectFileBase>(&Obj)) { 1799349cc55cSDimitry Andric if (Expected<std::vector<VersionEntry>> VersionsOrErr = 1800349cc55cSDimitry Andric E->readDynsymVersions()) 1801e8d8bef9SDimitry Andric SymbolVersions = std::move(*VersionsOrErr); 1802e8d8bef9SDimitry Andric else 1803e8d8bef9SDimitry Andric WithColor::warning(errs(), ToolName) 1804e8d8bef9SDimitry Andric << "unable to read symbol versions: " 1805e8d8bef9SDimitry Andric << toString(VersionsOrErr.takeError()) << "\n"; 1806e8d8bef9SDimitry Andric } 180781ad6265SDimitry Andric } 1808e8d8bef9SDimitry Andric // If a "-s segname sectname" option was specified and this is a Mach-O 1809e8d8bef9SDimitry Andric // file get the section number for that section in this object file. 1810e8d8bef9SDimitry Andric unsigned int Nsect = 0; 1811e8d8bef9SDimitry Andric MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj); 1812e8d8bef9SDimitry Andric if (!SegSect.empty() && MachO) { 1813e8d8bef9SDimitry Andric Nsect = getNsectForSegSect(MachO); 1814e8d8bef9SDimitry Andric // If this section is not in the object file no symbols are printed. 1815e8d8bef9SDimitry Andric if (Nsect == 0) 181681ad6265SDimitry Andric return false; 1817e8d8bef9SDimitry Andric } 181881ad6265SDimitry Andric 1819e8d8bef9SDimitry Andric if (!(MachO && DyldInfoOnly)) { 1820e8d8bef9SDimitry Andric size_t I = -1; 1821e8d8bef9SDimitry Andric for (BasicSymbolRef Sym : Symbols) { 1822e8d8bef9SDimitry Andric ++I; 1823e8d8bef9SDimitry Andric Expected<uint32_t> SymFlagsOrErr = Sym.getFlags(); 1824e8d8bef9SDimitry Andric if (!SymFlagsOrErr) { 1825e8d8bef9SDimitry Andric error(SymFlagsOrErr.takeError(), Obj.getFileName()); 182681ad6265SDimitry Andric return false; 1827e8d8bef9SDimitry Andric } 1828fe6060f1SDimitry Andric 1829fe6060f1SDimitry Andric // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they 1830fe6060f1SDimitry Andric // are used to repesent mapping symbols and needed to honor the 1831fe6060f1SDimitry Andric // --special-syms option. 1832fe6060f1SDimitry Andric auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj); 18335f757f3fSDimitry Andric bool HasMappingSymbol = 18345f757f3fSDimitry Andric ELFObj && llvm::is_contained({ELF::EM_ARM, ELF::EM_AARCH64, 18355f757f3fSDimitry Andric ELF::EM_CSKY, ELF::EM_RISCV}, 18365f757f3fSDimitry Andric ELFObj->getEMachine()); 18375f757f3fSDimitry Andric if (!HasMappingSymbol && !DebugSyms && 18385f757f3fSDimitry Andric (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific)) 1839e8d8bef9SDimitry Andric continue; 1840e8d8bef9SDimitry Andric if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect)) 1841e8d8bef9SDimitry Andric continue; 1842e8d8bef9SDimitry Andric // If a "-s segname sectname" option was specified and this is a Mach-O 1843e8d8bef9SDimitry Andric // file and this section appears in this file, Nsect will be non-zero then 1844e8d8bef9SDimitry Andric // see if this symbol is a symbol from that section and if not skip it. 1845e8d8bef9SDimitry Andric if (Nsect && Nsect != getNsectInMachO(*MachO, Sym)) 1846e8d8bef9SDimitry Andric continue; 1847e8d8bef9SDimitry Andric NMSymbol S = {}; 1848e8d8bef9SDimitry Andric S.Size = 0; 1849e8d8bef9SDimitry Andric S.Address = 0; 1850e8d8bef9SDimitry Andric if (isa<ELFObjectFileBase>(&Obj)) 1851e8d8bef9SDimitry Andric S.Size = ELFSymbolRef(Sym).getSize(); 185204eeddc0SDimitry Andric 185304eeddc0SDimitry Andric if (const XCOFFObjectFile *XCOFFObj = 185404eeddc0SDimitry Andric dyn_cast<const XCOFFObjectFile>(&Obj)) 185504eeddc0SDimitry Andric S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl()); 185604eeddc0SDimitry Andric 1857*0fca6ea1SDimitry Andric if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj)) 1858*0fca6ea1SDimitry Andric S.Size = WasmObj->getSymbolSize(Sym); 18595f757f3fSDimitry Andric 1860e8d8bef9SDimitry Andric if (PrintAddress && isa<ObjectFile>(Obj)) { 1861e8d8bef9SDimitry Andric SymbolRef SymRef(Sym); 1862e8d8bef9SDimitry Andric Expected<uint64_t> AddressOrErr = SymRef.getAddress(); 1863e8d8bef9SDimitry Andric if (!AddressOrErr) { 1864e8d8bef9SDimitry Andric consumeError(AddressOrErr.takeError()); 1865e8d8bef9SDimitry Andric break; 1866e8d8bef9SDimitry Andric } 1867e8d8bef9SDimitry Andric S.Address = *AddressOrErr; 1868e8d8bef9SDimitry Andric } 1869e8d8bef9SDimitry Andric S.TypeName = getNMTypeName(Obj, Sym); 1870e8d8bef9SDimitry Andric S.TypeChar = getNMSectionTagAndName(Obj, Sym, S.SectionName); 1871e8d8bef9SDimitry Andric 1872e8d8bef9SDimitry Andric raw_string_ostream OS(S.Name); 1873e8d8bef9SDimitry Andric if (Error E = Sym.printName(OS)) { 1874e8d8bef9SDimitry Andric if (MachO) { 1875e8d8bef9SDimitry Andric OS << "bad string index"; 1876e8d8bef9SDimitry Andric consumeError(std::move(E)); 1877e8d8bef9SDimitry Andric } else 1878e8d8bef9SDimitry Andric error(std::move(E), Obj.getFileName()); 1879e8d8bef9SDimitry Andric } 1880e8d8bef9SDimitry Andric if (!SymbolVersions.empty() && !SymbolVersions[I].Name.empty()) 1881e8d8bef9SDimitry Andric S.Name += 1882349cc55cSDimitry Andric (SymbolVersions[I].IsVerDef ? "@@" : "@") + SymbolVersions[I].Name; 1883e8d8bef9SDimitry Andric 1884e8d8bef9SDimitry Andric S.Sym = Sym; 188581ad6265SDimitry Andric if (S.initializeFlags(Obj)) 1886e8d8bef9SDimitry Andric SymbolList.push_back(S); 1887e8d8bef9SDimitry Andric } 1888e8d8bef9SDimitry Andric } 1889e8d8bef9SDimitry Andric 1890e8d8bef9SDimitry Andric // If this is a Mach-O file where the nlist symbol table is out of sync 1891e8d8bef9SDimitry Andric // with the dyld export trie then look through exports and fake up symbols 1892e8d8bef9SDimitry Andric // for the ones that are missing (also done with the -add-dyldinfo flag). 1893e8d8bef9SDimitry Andric // This is needed if strip(1) -T is run on a binary containing swift 1894e8d8bef9SDimitry Andric // language symbols for example. The option -only-dyldinfo will fake up 1895e8d8bef9SDimitry Andric // all symbols from the dyld export trie as well as the bind info. 1896e8d8bef9SDimitry Andric if (MachO && !NoDyldInfo) 189781ad6265SDimitry Andric dumpSymbolsFromDLInfoMachO(*MachO, SymbolList); 1898e8d8bef9SDimitry Andric 189981ad6265SDimitry Andric return true; 190081ad6265SDimitry Andric } 190181ad6265SDimitry Andric 190281ad6265SDimitry Andric static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName, 190381ad6265SDimitry Andric StringRef ArchitectureName, 190481ad6265SDimitry Andric StringRef ObjectFileName) { 190581ad6265SDimitry Andric outs() << "\n"; 190681ad6265SDimitry Andric if (ArchiveName.empty() || !PrintArchiveName) 190781ad6265SDimitry Andric outs() << ObjectFileName; 190881ad6265SDimitry Andric else 190981ad6265SDimitry Andric outs() << ArchiveName << "(" << ObjectFileName << ")"; 191081ad6265SDimitry Andric if (!ArchitectureName.empty()) 191181ad6265SDimitry Andric outs() << " (for architecture " << ArchitectureName << ")"; 191281ad6265SDimitry Andric outs() << ":\n"; 191381ad6265SDimitry Andric } 191481ad6265SDimitry Andric 191581ad6265SDimitry Andric static Expected<bool> hasSymbols(SymbolicFile &Obj) { 191681ad6265SDimitry Andric if (DynamicSyms) { 191781ad6265SDimitry Andric Expected<SymbolicFile::basic_symbol_iterator_range> DynamicSymsOrErr = 191881ad6265SDimitry Andric getDynamicSyms(Obj); 191981ad6265SDimitry Andric if (!DynamicSymsOrErr) 192081ad6265SDimitry Andric return DynamicSymsOrErr.takeError(); 192181ad6265SDimitry Andric return !DynamicSymsOrErr->empty(); 192281ad6265SDimitry Andric } 192381ad6265SDimitry Andric return !Obj.symbols().empty(); 192481ad6265SDimitry Andric } 192581ad6265SDimitry Andric 19265f757f3fSDimitry Andric static void printSymbolNamesFromObject( 19275f757f3fSDimitry Andric SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList, 19285f757f3fSDimitry Andric bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {}, 19295f757f3fSDimitry Andric StringRef ArchitectureName = {}, StringRef ObjectName = {}, 19305f757f3fSDimitry Andric bool PrintArchiveName = true) { 19315f757f3fSDimitry Andric 19325f757f3fSDimitry Andric if (PrintObjectLabel && !ExportSymbols) 19335f757f3fSDimitry Andric printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName, 19345f757f3fSDimitry Andric ObjectName.empty() ? Obj.getFileName() : ObjectName); 19355f757f3fSDimitry Andric 19365f757f3fSDimitry Andric if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols) 19375f757f3fSDimitry Andric return; 19385f757f3fSDimitry Andric 19395f757f3fSDimitry Andric // If there is an error in hasSymbols(), the error should be encountered in 19405f757f3fSDimitry Andric // function getSymbolNamesFromObject first. 19415f757f3fSDimitry Andric if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) { 19425f757f3fSDimitry Andric writeFileName(errs(), ArchiveName, ArchitectureName); 19435f757f3fSDimitry Andric errs() << "no symbols\n"; 19445f757f3fSDimitry Andric } 19455f757f3fSDimitry Andric 19465f757f3fSDimitry Andric sortSymbolList(SymbolList); 19475f757f3fSDimitry Andric printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName, 19485f757f3fSDimitry Andric ArchitectureName); 19495f757f3fSDimitry Andric } 19505f757f3fSDimitry Andric 19515f757f3fSDimitry Andric static void dumpSymbolsNameFromMachOFilesetEntry( 19525f757f3fSDimitry Andric MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList, 19535f757f3fSDimitry Andric bool PrintSymbolObject, bool PrintObjectLabel) { 19545f757f3fSDimitry Andric auto Buf = Obj->getMemoryBufferRef(); 19555f757f3fSDimitry Andric const auto *End = Obj->load_commands().end(); 19565f757f3fSDimitry Andric for (const auto *It = Obj->load_commands().begin(); It != End; ++It) { 19575f757f3fSDimitry Andric const auto &Command = *It; 19585f757f3fSDimitry Andric if (Command.C.cmd != MachO::LC_FILESET_ENTRY) 19595f757f3fSDimitry Andric continue; 19605f757f3fSDimitry Andric 19615f757f3fSDimitry Andric MachO::fileset_entry_command Entry = 19625f757f3fSDimitry Andric Obj->getFilesetEntryLoadCommand(Command); 19635f757f3fSDimitry Andric auto MaybeMachO = 19645f757f3fSDimitry Andric MachOObjectFile::createMachOObjectFile(Buf, 0, 0, Entry.fileoff); 19655f757f3fSDimitry Andric 19665f757f3fSDimitry Andric if (Error Err = MaybeMachO.takeError()) 19675f757f3fSDimitry Andric report_fatal_error(std::move(Err)); 19685f757f3fSDimitry Andric 19695f757f3fSDimitry Andric const char *EntryName = Command.Ptr + Entry.entry_id.offset; 19705f757f3fSDimitry Andric if (EntryName) 19715f757f3fSDimitry Andric outs() << "Symbols for " << EntryName << ": \n"; 19725f757f3fSDimitry Andric 19735f757f3fSDimitry Andric std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get()); 19745f757f3fSDimitry Andric printSymbolNamesFromObject(*EntryMachO, SymbolList, PrintSymbolObject, 19755f757f3fSDimitry Andric PrintObjectLabel); 19765f757f3fSDimitry Andric 19775f757f3fSDimitry Andric if (std::next(It) != End) 19785f757f3fSDimitry Andric outs() << "\n"; 19795f757f3fSDimitry Andric } 19805f757f3fSDimitry Andric } 19815f757f3fSDimitry Andric 198281ad6265SDimitry Andric static void dumpSymbolNamesFromObject( 198381ad6265SDimitry Andric SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList, 198481ad6265SDimitry Andric bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {}, 198581ad6265SDimitry Andric StringRef ArchitectureName = {}, StringRef ObjectName = {}, 198681ad6265SDimitry Andric bool PrintArchiveName = true) { 198781ad6265SDimitry Andric if (!shouldDump(Obj)) 198881ad6265SDimitry Andric return; 198981ad6265SDimitry Andric 199081ad6265SDimitry Andric if (ExportSymbols && Obj.isXCOFF()) { 199181ad6265SDimitry Andric XCOFFObjectFile *XCOFFObj = cast<XCOFFObjectFile>(&Obj); 199281ad6265SDimitry Andric getXCOFFExports(XCOFFObj, SymbolList, ArchiveName); 199381ad6265SDimitry Andric return; 199481ad6265SDimitry Andric } 199581ad6265SDimitry Andric 19960b57cec5SDimitry Andric CurrentFilename = Obj.getFileName(); 19975ffd83dbSDimitry Andric 19985f757f3fSDimitry Andric // Are we handling a MachO of type MH_FILESET? 19995f757f3fSDimitry Andric if (Obj.isMachO() && Obj.is64Bit() && 20005f757f3fSDimitry Andric cast<MachOObjectFile>(&Obj)->getHeader64().filetype == 20015f757f3fSDimitry Andric MachO::MH_FILESET) { 20025f757f3fSDimitry Andric dumpSymbolsNameFromMachOFilesetEntry(cast<MachOObjectFile>(&Obj), 20035f757f3fSDimitry Andric SymbolList, PrintSymbolObject, 20045f757f3fSDimitry Andric PrintObjectLabel); 20055f757f3fSDimitry Andric return; 20065ffd83dbSDimitry Andric } 20075ffd83dbSDimitry Andric 20085f757f3fSDimitry Andric printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject, 20095f757f3fSDimitry Andric PrintObjectLabel, ArchiveName, ArchitectureName, 20105f757f3fSDimitry Andric ObjectName, PrintArchiveName); 20110b57cec5SDimitry Andric } 20120b57cec5SDimitry Andric 20130b57cec5SDimitry Andric // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file 20140b57cec5SDimitry Andric // and if it is and there is a list of architecture flags is specified then 20150b57cec5SDimitry Andric // check to make sure this Mach-O file is one of those architectures or all 20160b57cec5SDimitry Andric // architectures was specificed. If not then an error is generated and this 20170b57cec5SDimitry Andric // routine returns false. Else it returns true. 201881ad6265SDimitry Andric static bool checkMachOAndArchFlags(SymbolicFile *O, StringRef Filename) { 20190b57cec5SDimitry Andric auto *MachO = dyn_cast<MachOObjectFile>(O); 20200b57cec5SDimitry Andric 20210b57cec5SDimitry Andric if (!MachO || ArchAll || ArchFlags.empty()) 20220b57cec5SDimitry Andric return true; 20230b57cec5SDimitry Andric 20240b57cec5SDimitry Andric MachO::mach_header H; 20250b57cec5SDimitry Andric MachO::mach_header_64 H_64; 20260b57cec5SDimitry Andric Triple T; 20270b57cec5SDimitry Andric const char *McpuDefault, *ArchFlag; 20280b57cec5SDimitry Andric if (MachO->is64Bit()) { 20290b57cec5SDimitry Andric H_64 = MachO->MachOObjectFile::getHeader64(); 20300b57cec5SDimitry Andric T = MachOObjectFile::getArchTriple(H_64.cputype, H_64.cpusubtype, 20310b57cec5SDimitry Andric &McpuDefault, &ArchFlag); 20320b57cec5SDimitry Andric } else { 20330b57cec5SDimitry Andric H = MachO->MachOObjectFile::getHeader(); 20340b57cec5SDimitry Andric T = MachOObjectFile::getArchTriple(H.cputype, H.cpusubtype, 20350b57cec5SDimitry Andric &McpuDefault, &ArchFlag); 20360b57cec5SDimitry Andric } 20370b57cec5SDimitry Andric const std::string ArchFlagName(ArchFlag); 2038e8d8bef9SDimitry Andric if (!llvm::is_contained(ArchFlags, ArchFlagName)) { 20390b57cec5SDimitry Andric error("No architecture specified", Filename); 20400b57cec5SDimitry Andric return false; 20410b57cec5SDimitry Andric } 20420b57cec5SDimitry Andric return true; 20430b57cec5SDimitry Andric } 20440b57cec5SDimitry Andric 204506c3fb27SDimitry Andric static void printArchiveMap(iterator_range<Archive::symbol_iterator> &map, 204606c3fb27SDimitry Andric StringRef Filename) { 204706c3fb27SDimitry Andric for (auto I : map) { 204806c3fb27SDimitry Andric Expected<Archive::Child> C = I.getMember(); 20490b57cec5SDimitry Andric if (!C) { 20500b57cec5SDimitry Andric error(C.takeError(), Filename); 20510b57cec5SDimitry Andric break; 20520b57cec5SDimitry Andric } 20530b57cec5SDimitry Andric Expected<StringRef> FileNameOrErr = C->getName(); 20540b57cec5SDimitry Andric if (!FileNameOrErr) { 20550b57cec5SDimitry Andric error(FileNameOrErr.takeError(), Filename); 20560b57cec5SDimitry Andric break; 20570b57cec5SDimitry Andric } 205806c3fb27SDimitry Andric StringRef SymName = I.getName(); 20590b57cec5SDimitry Andric outs() << SymName << " in " << FileNameOrErr.get() << "\n"; 20600b57cec5SDimitry Andric } 206106c3fb27SDimitry Andric 20620b57cec5SDimitry Andric outs() << "\n"; 20630b57cec5SDimitry Andric } 206406c3fb27SDimitry Andric 206506c3fb27SDimitry Andric static void dumpArchiveMap(Archive *A, StringRef Filename) { 206606c3fb27SDimitry Andric auto Map = A->symbols(); 206706c3fb27SDimitry Andric if (!Map.empty()) { 206806c3fb27SDimitry Andric outs() << "Archive map\n"; 206906c3fb27SDimitry Andric printArchiveMap(Map, Filename); 207006c3fb27SDimitry Andric } 207106c3fb27SDimitry Andric 207206c3fb27SDimitry Andric auto ECMap = A->ec_symbols(); 207306c3fb27SDimitry Andric if (!ECMap) { 207406c3fb27SDimitry Andric warn(ECMap.takeError(), Filename); 207506c3fb27SDimitry Andric } else if (!ECMap->empty()) { 207606c3fb27SDimitry Andric outs() << "Archive EC map\n"; 207706c3fb27SDimitry Andric printArchiveMap(*ECMap, Filename); 207806c3fb27SDimitry Andric } 20790b57cec5SDimitry Andric } 20800b57cec5SDimitry Andric 208181ad6265SDimitry Andric static void dumpArchive(Archive *A, std::vector<NMSymbol> &SymbolList, 208281ad6265SDimitry Andric StringRef Filename, LLVMContext *ContextPtr) { 208381ad6265SDimitry Andric if (ArchiveMap) 208481ad6265SDimitry Andric dumpArchiveMap(A, Filename); 208581ad6265SDimitry Andric 20860b57cec5SDimitry Andric Error Err = Error::success(); 20870b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 208881ad6265SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(ContextPtr); 20890b57cec5SDimitry Andric if (!ChildOrErr) { 20900b57cec5SDimitry Andric if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 20910b57cec5SDimitry Andric error(std::move(E), Filename, C); 20920b57cec5SDimitry Andric continue; 20930b57cec5SDimitry Andric } 20940b57cec5SDimitry Andric if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 20950b57cec5SDimitry Andric if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { 20960b57cec5SDimitry Andric WithColor::warning(errs(), ToolName) 20970b57cec5SDimitry Andric << "sizes with -print-size for Mach-O files are always zero.\n"; 20980b57cec5SDimitry Andric MachOPrintSizeWarning = true; 20990b57cec5SDimitry Andric } 21000b57cec5SDimitry Andric if (!checkMachOAndArchFlags(O, Filename)) 21010b57cec5SDimitry Andric return; 210281ad6265SDimitry Andric dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/false, 210381ad6265SDimitry Andric !PrintFileName, Filename, 210481ad6265SDimitry Andric /*ArchitectureName=*/{}, O->getFileName(), 210581ad6265SDimitry Andric /*PrintArchiveName=*/false); 21060b57cec5SDimitry Andric } 21070b57cec5SDimitry Andric } 21080b57cec5SDimitry Andric if (Err) 21090b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 21100b57cec5SDimitry Andric } 211181ad6265SDimitry Andric 211281ad6265SDimitry Andric static void dumpMachOUniversalBinaryMatchArchFlags( 211381ad6265SDimitry Andric MachOUniversalBinary *UB, std::vector<NMSymbol> &SymbolList, 211481ad6265SDimitry Andric StringRef Filename, LLVMContext *ContextPtr) { 21150b57cec5SDimitry Andric // Look for a slice in the universal binary that matches each ArchFlag. 21160b57cec5SDimitry Andric bool ArchFound; 21170b57cec5SDimitry Andric for (unsigned i = 0; i < ArchFlags.size(); ++i) { 21180b57cec5SDimitry Andric ArchFound = false; 21190b57cec5SDimitry Andric for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 21200b57cec5SDimitry Andric E = UB->end_objects(); 21210b57cec5SDimitry Andric I != E; ++I) { 21220b57cec5SDimitry Andric if (ArchFlags[i] == I->getArchFlagName()) { 21230b57cec5SDimitry Andric ArchFound = true; 212481ad6265SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 21250b57cec5SDimitry Andric std::string ArchiveName; 21260b57cec5SDimitry Andric std::string ArchitectureName; 21270b57cec5SDimitry Andric ArchiveName.clear(); 21280b57cec5SDimitry Andric ArchitectureName.clear(); 21290b57cec5SDimitry Andric if (ObjOrErr) { 21300b57cec5SDimitry Andric ObjectFile &Obj = *ObjOrErr.get(); 213181ad6265SDimitry Andric if (ArchFlags.size() > 1) 21320b57cec5SDimitry Andric ArchitectureName = I->getArchFlagName(); 213381ad6265SDimitry Andric dumpSymbolNamesFromObject(Obj, SymbolList, 213481ad6265SDimitry Andric /*PrintSymbolObject=*/false, 213581ad6265SDimitry Andric (ArchFlags.size() > 1) && !PrintFileName, 213681ad6265SDimitry Andric ArchiveName, ArchitectureName); 213781ad6265SDimitry Andric } else if (auto E = 213881ad6265SDimitry Andric isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 213981ad6265SDimitry Andric error(std::move(E), Filename, 214081ad6265SDimitry Andric ArchFlags.size() > 1 ? StringRef(I->getArchFlagName()) 214181ad6265SDimitry Andric : StringRef()); 21420b57cec5SDimitry Andric continue; 21430b57cec5SDimitry Andric } else if (Expected<std::unique_ptr<Archive>> AOrErr = 21440b57cec5SDimitry Andric I->getAsArchive()) { 21450b57cec5SDimitry Andric std::unique_ptr<Archive> &A = *AOrErr; 21460b57cec5SDimitry Andric Error Err = Error::success(); 21470b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 21480b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 21490b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 21500b57cec5SDimitry Andric if (!ChildOrErr) { 215181ad6265SDimitry Andric if (auto E = 215281ad6265SDimitry Andric isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) { 215381ad6265SDimitry Andric error(std::move(E), Filename, C, 215481ad6265SDimitry Andric ArchFlags.size() > 1 ? StringRef(I->getArchFlagName()) 215581ad6265SDimitry Andric : StringRef()); 21560b57cec5SDimitry Andric } 21570b57cec5SDimitry Andric continue; 21580b57cec5SDimitry Andric } 215981ad6265SDimitry Andric if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 21605ffd83dbSDimitry Andric ArchiveName = std::string(A->getFileName()); 21610b57cec5SDimitry Andric if (ArchFlags.size() > 1) 21620b57cec5SDimitry Andric ArchitectureName = I->getArchFlagName(); 216381ad6265SDimitry Andric dumpSymbolNamesFromObject( 216481ad6265SDimitry Andric *O, SymbolList, /*PrintSymbolObject=*/false, !PrintFileName, 216581ad6265SDimitry Andric ArchiveName, ArchitectureName); 21660b57cec5SDimitry Andric } 21670b57cec5SDimitry Andric } 21680b57cec5SDimitry Andric if (Err) 21690b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 21700b57cec5SDimitry Andric } else { 21710b57cec5SDimitry Andric consumeError(AOrErr.takeError()); 21720b57cec5SDimitry Andric error(Filename + " for architecture " + 21730b57cec5SDimitry Andric StringRef(I->getArchFlagName()) + 21740b57cec5SDimitry Andric " is not a Mach-O file or an archive file", 21750b57cec5SDimitry Andric "Mach-O universal file"); 21760b57cec5SDimitry Andric } 21770b57cec5SDimitry Andric } 21780b57cec5SDimitry Andric } 21790b57cec5SDimitry Andric if (!ArchFound) { 21800b57cec5SDimitry Andric error(ArchFlags[i], 21810b57cec5SDimitry Andric "file: " + Filename + " does not contain architecture"); 21820b57cec5SDimitry Andric return; 21830b57cec5SDimitry Andric } 21840b57cec5SDimitry Andric } 21850b57cec5SDimitry Andric } 218681ad6265SDimitry Andric 218781ad6265SDimitry Andric // Returns true If the binary contains a slice that matches the host 218881ad6265SDimitry Andric // architecture, or false otherwise. 218981ad6265SDimitry Andric static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB, 219081ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList, 219181ad6265SDimitry Andric StringRef Filename, 219281ad6265SDimitry Andric LLVMContext *ContextPtr) { 21930b57cec5SDimitry Andric Triple HostTriple = MachOObjectFile::getHostArch(); 21940b57cec5SDimitry Andric StringRef HostArchName = HostTriple.getArchName(); 21950b57cec5SDimitry Andric for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), 21960b57cec5SDimitry Andric E = UB->end_objects(); 21970b57cec5SDimitry Andric I != E; ++I) { 21980b57cec5SDimitry Andric if (HostArchName == I->getArchFlagName()) { 21990b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile(); 22000b57cec5SDimitry Andric std::string ArchiveName; 22010b57cec5SDimitry Andric if (ObjOrErr) { 22020b57cec5SDimitry Andric ObjectFile &Obj = *ObjOrErr.get(); 220381ad6265SDimitry Andric dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false, 220481ad6265SDimitry Andric /*PrintObjectLabel=*/false); 220581ad6265SDimitry Andric } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) 22060b57cec5SDimitry Andric error(std::move(E), Filename); 220781ad6265SDimitry Andric else if (Expected<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) { 22080b57cec5SDimitry Andric std::unique_ptr<Archive> &A = *AOrErr; 22090b57cec5SDimitry Andric Error Err = Error::success(); 22100b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 22110b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 22120b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 22130b57cec5SDimitry Andric if (!ChildOrErr) { 221481ad6265SDimitry Andric if (auto E = 221581ad6265SDimitry Andric isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 22160b57cec5SDimitry Andric error(std::move(E), Filename, C); 22170b57cec5SDimitry Andric continue; 22180b57cec5SDimitry Andric } 221981ad6265SDimitry Andric if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 22205ffd83dbSDimitry Andric ArchiveName = std::string(A->getFileName()); 222181ad6265SDimitry Andric dumpSymbolNamesFromObject(*O, SymbolList, 222281ad6265SDimitry Andric /*PrintSymbolObject=*/false, 222381ad6265SDimitry Andric !PrintFileName, ArchiveName); 22240b57cec5SDimitry Andric } 22250b57cec5SDimitry Andric } 22260b57cec5SDimitry Andric if (Err) 22270b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 22280b57cec5SDimitry Andric } else { 22290b57cec5SDimitry Andric consumeError(AOrErr.takeError()); 22300b57cec5SDimitry Andric error(Filename + " for architecture " + 22310b57cec5SDimitry Andric StringRef(I->getArchFlagName()) + 22320b57cec5SDimitry Andric " is not a Mach-O file or an archive file", 22330b57cec5SDimitry Andric "Mach-O universal file"); 22340b57cec5SDimitry Andric } 223581ad6265SDimitry Andric return true; 22360b57cec5SDimitry Andric } 22370b57cec5SDimitry Andric } 223881ad6265SDimitry Andric return false; 22390b57cec5SDimitry Andric } 224081ad6265SDimitry Andric 224181ad6265SDimitry Andric static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB, 224281ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList, 224381ad6265SDimitry Andric StringRef Filename, 224481ad6265SDimitry Andric LLVMContext *ContextPtr) { 22450b57cec5SDimitry Andric bool moreThanOneArch = UB->getNumberOfObjects() > 1; 22460b57cec5SDimitry Andric for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) { 22470b57cec5SDimitry Andric Expected<std::unique_ptr<ObjectFile>> ObjOrErr = O.getAsObjectFile(); 22480b57cec5SDimitry Andric std::string ArchiveName; 22490b57cec5SDimitry Andric std::string ArchitectureName; 22500b57cec5SDimitry Andric ArchiveName.clear(); 22510b57cec5SDimitry Andric ArchitectureName.clear(); 22520b57cec5SDimitry Andric if (ObjOrErr) { 22530b57cec5SDimitry Andric ObjectFile &Obj = *ObjOrErr.get(); 22540b57cec5SDimitry Andric if (isa<MachOObjectFile>(Obj) && moreThanOneArch) 22550b57cec5SDimitry Andric ArchitectureName = O.getArchFlagName(); 225681ad6265SDimitry Andric dumpSymbolNamesFromObject(Obj, SymbolList, /*PrintSymbolObject=*/false, 225781ad6265SDimitry Andric !PrintFileName, ArchiveName, ArchitectureName); 225881ad6265SDimitry Andric } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 225981ad6265SDimitry Andric error(std::move(E), Filename, 226081ad6265SDimitry Andric moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef()); 22610b57cec5SDimitry Andric continue; 226281ad6265SDimitry Andric } else if (Expected<std::unique_ptr<Archive>> AOrErr = O.getAsArchive()) { 22630b57cec5SDimitry Andric std::unique_ptr<Archive> &A = *AOrErr; 22640b57cec5SDimitry Andric Error Err = Error::success(); 22650b57cec5SDimitry Andric for (auto &C : A->children(Err)) { 22660b57cec5SDimitry Andric Expected<std::unique_ptr<Binary>> ChildOrErr = 22670b57cec5SDimitry Andric C.getAsBinary(ContextPtr); 22680b57cec5SDimitry Andric if (!ChildOrErr) { 226981ad6265SDimitry Andric if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) 227081ad6265SDimitry Andric error(std::move(E), Filename, C, 227181ad6265SDimitry Andric moreThanOneArch ? StringRef(ArchitectureName) : StringRef()); 22720b57cec5SDimitry Andric continue; 22730b57cec5SDimitry Andric } 22740b57cec5SDimitry Andric if (SymbolicFile *F = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) { 22755ffd83dbSDimitry Andric ArchiveName = std::string(A->getFileName()); 22760b57cec5SDimitry Andric if (isa<MachOObjectFile>(F) && moreThanOneArch) 22770b57cec5SDimitry Andric ArchitectureName = O.getArchFlagName(); 227881ad6265SDimitry Andric dumpSymbolNamesFromObject(*F, SymbolList, /*PrintSymbolObject=*/false, 227981ad6265SDimitry Andric !PrintFileName, ArchiveName, 228081ad6265SDimitry Andric ArchitectureName); 22810b57cec5SDimitry Andric } 22820b57cec5SDimitry Andric } 22830b57cec5SDimitry Andric if (Err) 22840b57cec5SDimitry Andric error(std::move(Err), A->getFileName()); 22850b57cec5SDimitry Andric } else { 22860b57cec5SDimitry Andric consumeError(AOrErr.takeError()); 228781ad6265SDimitry Andric error(Filename + " for architecture " + StringRef(O.getArchFlagName()) + 22880b57cec5SDimitry Andric " is not a Mach-O file or an archive file", 22890b57cec5SDimitry Andric "Mach-O universal file"); 22900b57cec5SDimitry Andric } 22910b57cec5SDimitry Andric } 229281ad6265SDimitry Andric } 229381ad6265SDimitry Andric 229481ad6265SDimitry Andric static void dumpMachOUniversalBinary(MachOUniversalBinary *UB, 229581ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList, 229681ad6265SDimitry Andric StringRef Filename, 229781ad6265SDimitry Andric LLVMContext *ContextPtr) { 229881ad6265SDimitry Andric // If we have a list of architecture flags specified dump only those. 229981ad6265SDimitry Andric if (!ArchAll && !ArchFlags.empty()) { 230081ad6265SDimitry Andric dumpMachOUniversalBinaryMatchArchFlags(UB, SymbolList, Filename, 230181ad6265SDimitry Andric ContextPtr); 23020b57cec5SDimitry Andric return; 23030b57cec5SDimitry Andric } 23045ffd83dbSDimitry Andric 230581ad6265SDimitry Andric // No architecture flags were specified so if this contains a slice that 230681ad6265SDimitry Andric // matches the host architecture dump only that. 230781ad6265SDimitry Andric if (!ArchAll && 230881ad6265SDimitry Andric dumpMachOUniversalBinaryMatchHost(UB, SymbolList, Filename, ContextPtr)) 230981ad6265SDimitry Andric return; 231081ad6265SDimitry Andric 231181ad6265SDimitry Andric // Either all architectures have been specified or none have been specified 231281ad6265SDimitry Andric // and this does not contain the host architecture so dump all the slices. 231381ad6265SDimitry Andric dumpMachOUniversalBinaryArchAll(UB, SymbolList, Filename, ContextPtr); 231481ad6265SDimitry Andric } 231581ad6265SDimitry Andric 231681ad6265SDimitry Andric static void dumpTapiUniversal(TapiUniversal *TU, 231781ad6265SDimitry Andric std::vector<NMSymbol> &SymbolList, 231881ad6265SDimitry Andric StringRef Filename) { 23195ffd83dbSDimitry Andric for (const TapiUniversal::ObjectForArch &I : TU->objects()) { 23205ffd83dbSDimitry Andric StringRef ArchName = I.getArchFlagName(); 23215ffd83dbSDimitry Andric const bool ShowArch = 2322e8d8bef9SDimitry Andric ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName); 23235ffd83dbSDimitry Andric if (!ShowArch) 23245ffd83dbSDimitry Andric continue; 23255ffd83dbSDimitry Andric if (!AddInlinedInfo && !I.isTopLevelLib()) 23265ffd83dbSDimitry Andric continue; 232781ad6265SDimitry Andric if (auto ObjOrErr = I.getAsObjectFile()) 232881ad6265SDimitry Andric dumpSymbolNamesFromObject( 232981ad6265SDimitry Andric *ObjOrErr.get(), SymbolList, /*PrintSymbolObject=*/false, 233081ad6265SDimitry Andric /*PrintObjectLabel=*/true, 233181ad6265SDimitry Andric /*ArchiveName=*/{}, ArchName, I.getInstallName()); 233281ad6265SDimitry Andric else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { 23335ffd83dbSDimitry Andric error(std::move(E), Filename, ArchName); 23345ffd83dbSDimitry Andric } 23355ffd83dbSDimitry Andric } 23365ffd83dbSDimitry Andric } 23375ffd83dbSDimitry Andric 233881ad6265SDimitry Andric static void dumpSymbolicFile(SymbolicFile *O, std::vector<NMSymbol> &SymbolList, 233981ad6265SDimitry Andric StringRef Filename) { 23400b57cec5SDimitry Andric if (!MachOPrintSizeWarning && PrintSize && isa<MachOObjectFile>(O)) { 23410b57cec5SDimitry Andric WithColor::warning(errs(), ToolName) 23420b57cec5SDimitry Andric << "sizes with --print-size for Mach-O files are always zero.\n"; 23430b57cec5SDimitry Andric MachOPrintSizeWarning = true; 23440b57cec5SDimitry Andric } 23450b57cec5SDimitry Andric if (!checkMachOAndArchFlags(O, Filename)) 23460b57cec5SDimitry Andric return; 234781ad6265SDimitry Andric dumpSymbolNamesFromObject(*O, SymbolList, /*PrintSymbolObject=*/true, 234881ad6265SDimitry Andric /*PrintObjectLabel=*/false); 23490b57cec5SDimitry Andric } 235081ad6265SDimitry Andric 235181ad6265SDimitry Andric static std::vector<NMSymbol> dumpSymbolNamesFromFile(StringRef Filename) { 235281ad6265SDimitry Andric std::vector<NMSymbol> SymbolList; 235381ad6265SDimitry Andric ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 235481ad6265SDimitry Andric MemoryBuffer::getFileOrSTDIN(Filename); 235581ad6265SDimitry Andric if (error(BufferOrErr.getError(), Filename)) 235681ad6265SDimitry Andric return SymbolList; 235781ad6265SDimitry Andric 23585f757f3fSDimitry Andric // Ignore AIX linker import files (these files start with "#!"), when 23595f757f3fSDimitry Andric // exporting symbols. 23605f757f3fSDimitry Andric const char *BuffStart = (*BufferOrErr)->getBufferStart(); 23615f757f3fSDimitry Andric size_t BufferSize = (*BufferOrErr)->getBufferSize(); 23625f757f3fSDimitry Andric if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' && 23635f757f3fSDimitry Andric BuffStart[1] == '!') 23645f757f3fSDimitry Andric return SymbolList; 23655f757f3fSDimitry Andric 236681ad6265SDimitry Andric LLVMContext Context; 236781ad6265SDimitry Andric LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context; 236881ad6265SDimitry Andric Expected<std::unique_ptr<Binary>> BinaryOrErr = 236981ad6265SDimitry Andric createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr); 237081ad6265SDimitry Andric if (!BinaryOrErr) { 237181ad6265SDimitry Andric error(BinaryOrErr.takeError(), Filename); 237281ad6265SDimitry Andric return SymbolList; 237381ad6265SDimitry Andric } 237481ad6265SDimitry Andric Binary &Bin = *BinaryOrErr.get(); 237581ad6265SDimitry Andric if (Archive *A = dyn_cast<Archive>(&Bin)) 237681ad6265SDimitry Andric dumpArchive(A, SymbolList, Filename, ContextPtr); 237781ad6265SDimitry Andric else if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) 237881ad6265SDimitry Andric dumpMachOUniversalBinary(UB, SymbolList, Filename, ContextPtr); 237981ad6265SDimitry Andric else if (TapiUniversal *TU = dyn_cast<TapiUniversal>(&Bin)) 238081ad6265SDimitry Andric dumpTapiUniversal(TU, SymbolList, Filename); 238181ad6265SDimitry Andric else if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) 238281ad6265SDimitry Andric dumpSymbolicFile(O, SymbolList, Filename); 238381ad6265SDimitry Andric return SymbolList; 238481ad6265SDimitry Andric } 238581ad6265SDimitry Andric 238681ad6265SDimitry Andric static void 238781ad6265SDimitry Andric exportSymbolNamesFromFiles(const std::vector<std::string> &InputFilenames) { 238881ad6265SDimitry Andric std::vector<NMSymbol> SymbolList; 238981ad6265SDimitry Andric for (const auto &FileName : InputFilenames) { 239081ad6265SDimitry Andric std::vector<NMSymbol> FileSymList = dumpSymbolNamesFromFile(FileName); 239181ad6265SDimitry Andric SymbolList.insert(SymbolList.end(), FileSymList.begin(), FileSymList.end()); 239281ad6265SDimitry Andric } 239381ad6265SDimitry Andric 239481ad6265SDimitry Andric // Delete symbols which should not be printed from SymolList. 2395bdd1243dSDimitry Andric llvm::erase_if(SymbolList, 2396bdd1243dSDimitry Andric [](const NMSymbol &s) { return !s.shouldPrint(); }); 239781ad6265SDimitry Andric sortSymbolList(SymbolList); 2398*0fca6ea1SDimitry Andric SymbolList.erase(llvm::unique(SymbolList), SymbolList.end()); 239981ad6265SDimitry Andric printExportSymbolList(SymbolList); 24000b57cec5SDimitry Andric } 24010b57cec5SDimitry Andric 240206c3fb27SDimitry Andric int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) { 2403fe6060f1SDimitry Andric BumpPtrAllocator A; 2404fe6060f1SDimitry Andric StringSaver Saver(A); 2405fe6060f1SDimitry Andric NmOptTable Tbl; 2406fe6060f1SDimitry Andric ToolName = argv[0]; 2407fe6060f1SDimitry Andric opt::InputArgList Args = 2408fe6060f1SDimitry Andric Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { 2409fe6060f1SDimitry Andric error(Msg); 2410fe6060f1SDimitry Andric exit(1); 2411fe6060f1SDimitry Andric }); 2412fe6060f1SDimitry Andric if (Args.hasArg(OPT_help)) { 2413fe6060f1SDimitry Andric Tbl.printHelp( 2414fe6060f1SDimitry Andric outs(), 2415fe6060f1SDimitry Andric (Twine(ToolName) + " [options] <input object files>").str().c_str(), 2416fe6060f1SDimitry Andric "LLVM symbol table dumper"); 2417fe6060f1SDimitry Andric // TODO Replace this with OptTable API once it adds extrahelp support. 2418fe6060f1SDimitry Andric outs() << "\nPass @FILE as argument to read options from FILE.\n"; 2419fe6060f1SDimitry Andric return 0; 2420fe6060f1SDimitry Andric } 2421fe6060f1SDimitry Andric if (Args.hasArg(OPT_version)) { 2422fe6060f1SDimitry Andric // This needs to contain the word "GNU", libtool looks for that string. 2423fe6060f1SDimitry Andric outs() << "llvm-nm, compatible with GNU nm" << '\n'; 2424fe6060f1SDimitry Andric cl::PrintVersionMessage(); 2425fe6060f1SDimitry Andric return 0; 2426fe6060f1SDimitry Andric } 2427fe6060f1SDimitry Andric 2428fe6060f1SDimitry Andric DebugSyms = Args.hasArg(OPT_debug_syms); 2429fe6060f1SDimitry Andric DefinedOnly = Args.hasArg(OPT_defined_only); 2430fe6060f1SDimitry Andric Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false); 2431fe6060f1SDimitry Andric DynamicSyms = Args.hasArg(OPT_dynamic); 2432fe6060f1SDimitry Andric ExternalOnly = Args.hasArg(OPT_extern_only); 2433fe6060f1SDimitry Andric StringRef V = Args.getLastArgValue(OPT_format_EQ, "bsd"); 2434fe6060f1SDimitry Andric if (V == "bsd") 2435fe6060f1SDimitry Andric OutputFormat = bsd; 2436fe6060f1SDimitry Andric else if (V == "posix") 2437fe6060f1SDimitry Andric OutputFormat = posix; 2438fe6060f1SDimitry Andric else if (V == "sysv") 2439fe6060f1SDimitry Andric OutputFormat = sysv; 2440fe6060f1SDimitry Andric else if (V == "darwin") 2441fe6060f1SDimitry Andric OutputFormat = darwin; 2442fe6060f1SDimitry Andric else if (V == "just-symbols") 2443fe6060f1SDimitry Andric OutputFormat = just_symbols; 2444fe6060f1SDimitry Andric else 2445fe6060f1SDimitry Andric error("--format value should be one of: bsd, posix, sysv, darwin, " 2446fe6060f1SDimitry Andric "just-symbols"); 24475f757f3fSDimitry Andric LineNumbers = Args.hasArg(OPT_line_numbers); 2448fe6060f1SDimitry Andric NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc); 2449fe6060f1SDimitry Andric NoSort = Args.hasArg(OPT_no_sort); 2450fe6060f1SDimitry Andric NoWeakSymbols = Args.hasArg(OPT_no_weak); 2451fe6060f1SDimitry Andric NumericSort = Args.hasArg(OPT_numeric_sort); 2452fe6060f1SDimitry Andric ArchiveMap = Args.hasArg(OPT_print_armap); 2453fe6060f1SDimitry Andric PrintFileName = Args.hasArg(OPT_print_file_name); 2454fe6060f1SDimitry Andric PrintSize = Args.hasArg(OPT_print_size); 2455fe6060f1SDimitry Andric ReverseSort = Args.hasArg(OPT_reverse_sort); 245681ad6265SDimitry Andric ExportSymbols = Args.hasArg(OPT_export_symbols); 245781ad6265SDimitry Andric if (ExportSymbols) { 245881ad6265SDimitry Andric ExternalOnly = true; 245981ad6265SDimitry Andric DefinedOnly = true; 246081ad6265SDimitry Andric } 246181ad6265SDimitry Andric 2462fe6060f1SDimitry Andric Quiet = Args.hasArg(OPT_quiet); 2463fe6060f1SDimitry Andric V = Args.getLastArgValue(OPT_radix_EQ, "x"); 2464fe6060f1SDimitry Andric if (V == "o") 2465fe6060f1SDimitry Andric AddressRadix = Radix::o; 2466fe6060f1SDimitry Andric else if (V == "d") 2467fe6060f1SDimitry Andric AddressRadix = Radix::d; 2468fe6060f1SDimitry Andric else if (V == "x") 2469fe6060f1SDimitry Andric AddressRadix = Radix::x; 2470fe6060f1SDimitry Andric else 2471fe6060f1SDimitry Andric error("--radix value should be one of: 'o' (octal), 'd' (decimal), 'x' " 2472fe6060f1SDimitry Andric "(hexadecimal)"); 2473fe6060f1SDimitry Andric SizeSort = Args.hasArg(OPT_size_sort); 2474fe6060f1SDimitry Andric SpecialSyms = Args.hasArg(OPT_special_syms); 2475fe6060f1SDimitry Andric UndefinedOnly = Args.hasArg(OPT_undefined_only); 2476fe6060f1SDimitry Andric WithoutAliases = Args.hasArg(OPT_without_aliases); 2477fe6060f1SDimitry Andric 2478bdd1243dSDimitry Andric // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if 2479bdd1243dSDimitry Andric // specified. 2480bdd1243dSDimitry Andric Triple HostTriple(sys::getProcessTriple()); 2481bdd1243dSDimitry Andric if (HostTriple.isOSAIX()) { 2482bdd1243dSDimitry Andric BitMode = StringSwitch<BitModeTy>(getenv("OBJECT_MODE")) 2483bdd1243dSDimitry Andric .Case("32", BitModeTy::Bit32) 2484bdd1243dSDimitry Andric .Case("64", BitModeTy::Bit64) 2485bdd1243dSDimitry Andric .Case("32_64", BitModeTy::Bit32_64) 2486bdd1243dSDimitry Andric .Case("any", BitModeTy::Any) 2487bdd1243dSDimitry Andric .Default(BitModeTy::Bit32); 2488bdd1243dSDimitry Andric } else 2489bdd1243dSDimitry Andric BitMode = BitModeTy::Any; 2490bdd1243dSDimitry Andric 2491bdd1243dSDimitry Andric if (Arg *A = Args.getLastArg(OPT_X)) { 2492bdd1243dSDimitry Andric StringRef Mode = A->getValue(); 249381ad6265SDimitry Andric if (Mode == "32") 249481ad6265SDimitry Andric BitMode = BitModeTy::Bit32; 249581ad6265SDimitry Andric else if (Mode == "64") 249681ad6265SDimitry Andric BitMode = BitModeTy::Bit64; 249781ad6265SDimitry Andric else if (Mode == "32_64") 249881ad6265SDimitry Andric BitMode = BitModeTy::Bit32_64; 249981ad6265SDimitry Andric else if (Mode == "any") 250081ad6265SDimitry Andric BitMode = BitModeTy::Any; 250181ad6265SDimitry Andric else 250281ad6265SDimitry Andric error("-X value should be one of: 32, 64, 32_64, (default) any"); 2503bdd1243dSDimitry Andric } 250481ad6265SDimitry Andric 2505fe6060f1SDimitry Andric // Mach-O specific options. 2506fe6060f1SDimitry Andric FormatMachOasHex = Args.hasArg(OPT_x); 2507fe6060f1SDimitry Andric AddDyldInfo = Args.hasArg(OPT_add_dyldinfo); 2508fe6060f1SDimitry Andric AddInlinedInfo = Args.hasArg(OPT_add_inlinedinfo); 2509fe6060f1SDimitry Andric DyldInfoOnly = Args.hasArg(OPT_dyldinfo_only); 2510fe6060f1SDimitry Andric NoDyldInfo = Args.hasArg(OPT_no_dyldinfo); 25110b57cec5SDimitry Andric 251281ad6265SDimitry Andric // XCOFF specific options. 251381ad6265SDimitry Andric NoRsrc = Args.hasArg(OPT_no_rsrc); 251481ad6265SDimitry Andric 25150b57cec5SDimitry Andric // llvm-nm only reads binary files. 25160b57cec5SDimitry Andric if (error(sys::ChangeStdinToBinary())) 25170b57cec5SDimitry Andric return 1; 25180b57cec5SDimitry Andric 25190b57cec5SDimitry Andric // These calls are needed so that we can read bitcode correctly. 25200b57cec5SDimitry Andric llvm::InitializeAllTargetInfos(); 25210b57cec5SDimitry Andric llvm::InitializeAllTargetMCs(); 25220b57cec5SDimitry Andric llvm::InitializeAllAsmParsers(); 25230b57cec5SDimitry Andric 25240b57cec5SDimitry Andric // The relative order of these is important. If you pass --size-sort it should 25250b57cec5SDimitry Andric // only print out the size. However, if you pass -S --size-sort, it should 25260b57cec5SDimitry Andric // print out both the size and address. 25270b57cec5SDimitry Andric if (SizeSort && !PrintSize) 25280b57cec5SDimitry Andric PrintAddress = false; 25290b57cec5SDimitry Andric if (OutputFormat == sysv || SizeSort) 25300b57cec5SDimitry Andric PrintSize = true; 25310b57cec5SDimitry Andric 2532fe6060f1SDimitry Andric for (const auto *A : Args.filtered(OPT_arch_EQ)) { 2533fe6060f1SDimitry Andric SmallVector<StringRef, 2> Values; 2534fe6060f1SDimitry Andric llvm::SplitString(A->getValue(), Values, ","); 2535fe6060f1SDimitry Andric for (StringRef V : Values) { 2536fe6060f1SDimitry Andric if (V == "all") 25370b57cec5SDimitry Andric ArchAll = true; 2538fe6060f1SDimitry Andric else if (MachOObjectFile::isValidArch(V)) 2539fe6060f1SDimitry Andric ArchFlags.push_back(V); 2540fe6060f1SDimitry Andric else 2541fe6060f1SDimitry Andric error("Unknown architecture named '" + V + "'", 25420b57cec5SDimitry Andric "for the --arch option"); 25430b57cec5SDimitry Andric } 25440b57cec5SDimitry Andric } 25450b57cec5SDimitry Andric 2546fe6060f1SDimitry Andric // Mach-O takes -s to accept two arguments. We emulate this by iterating over 2547fe6060f1SDimitry Andric // both OPT_s and OPT_INPUT. 2548fe6060f1SDimitry Andric std::vector<std::string> InputFilenames; 2549fe6060f1SDimitry Andric int SegSectArgs = 0; 2550fe6060f1SDimitry Andric for (opt::Arg *A : Args.filtered(OPT_s, OPT_INPUT)) { 2551fe6060f1SDimitry Andric if (SegSectArgs > 0) { 2552fe6060f1SDimitry Andric --SegSectArgs; 2553fe6060f1SDimitry Andric SegSect.push_back(A->getValue()); 2554fe6060f1SDimitry Andric } else if (A->getOption().matches(OPT_s)) { 2555fe6060f1SDimitry Andric SegSectArgs = 2; 2556fe6060f1SDimitry Andric } else { 2557fe6060f1SDimitry Andric InputFilenames.push_back(A->getValue()); 2558fe6060f1SDimitry Andric } 2559fe6060f1SDimitry Andric } 25600b57cec5SDimitry Andric if (!SegSect.empty() && SegSect.size() != 2) 25610b57cec5SDimitry Andric error("bad number of arguments (must be two arguments)", 25620b57cec5SDimitry Andric "for the -s option"); 25630b57cec5SDimitry Andric 2564fe6060f1SDimitry Andric if (InputFilenames.empty()) 2565fe6060f1SDimitry Andric InputFilenames.push_back("a.out"); 2566fe6060f1SDimitry Andric if (InputFilenames.size() > 1) 2567fe6060f1SDimitry Andric MultipleFiles = true; 2568fe6060f1SDimitry Andric 25690b57cec5SDimitry Andric if (NoDyldInfo && (AddDyldInfo || DyldInfoOnly)) 25700b57cec5SDimitry Andric error("--no-dyldinfo can't be used with --add-dyldinfo or --dyldinfo-only"); 25710b57cec5SDimitry Andric 257281ad6265SDimitry Andric if (ExportSymbols) 257381ad6265SDimitry Andric exportSymbolNamesFromFiles(InputFilenames); 257481ad6265SDimitry Andric else 25750b57cec5SDimitry Andric llvm::for_each(InputFilenames, dumpSymbolNamesFromFile); 25760b57cec5SDimitry Andric 25770b57cec5SDimitry Andric if (HadError) 25780b57cec5SDimitry Andric return 1; 2579bdd1243dSDimitry Andric return 0; 25800b57cec5SDimitry Andric } 2581