diff --git a/llvm/test/Object/nm-universal-binary.test b/llvm/test/Object/nm-universal-binary.test --- a/llvm/test/Object/nm-universal-binary.test +++ b/llvm/test/Object/nm-universal-binary.test @@ -35,25 +35,27 @@ CHECK-OBJ-foobar: error: for the --arch option: Unknown architecture named 'foobar' -CHECK-AR: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64): -CHECK-AR: 0000000000000068 s EH_frame0 -CHECK-AR: 000000000000003b s L_.str -CHECK-AR: 0000000000000000 T _main -CHECK-AR: 0000000000000080 S _main.eh -CHECK-AR: U _printf +CHECK-AR: {{^$}} +CHECK-AR-NEXT: macho-universal-archive.x86_64.i386(hello.o) (for architecture x86_64): +CHECK-AR: 0000000000000068 s EH_frame0 +CHECK-AR: 000000000000003b s L_.str +CHECK-AR: 0000000000000000 T _main +CHECK-AR: 0000000000000080 S _main.eh +CHECK-AR: U _printf CHECK-AR: macho-universal-archive.x86_64.i386(foo.o) (for architecture i386): CHECK-AR: 00000008 D _bar CHECK-AR: 00000000 T _foo -CHECK-64-AR: macho-universal64-archive.x86_64.i386(foo.o) (for architecture i386): -CHECK-64-AR: 00000008 D _bar -CHECK-64-AR: 00000000 T _foo -CHECK-64-AR: macho-universal64-archive.x86_64.i386(hello.o) (for architecture x86_64): -CHECK-64-AR: 0000000000000068 s EH_frame0 -CHECK-64-AR: 000000000000003b s L_.str -CHECK-64-AR: 0000000000000000 T _main -CHECK-64-AR: 0000000000000080 S _main.eh -CHECK-64-AR: U _printf +CHECK-64-AR: {{^$}} +CHECK-64-AR-NEXT: macho-universal64-archive.x86_64.i386(foo.o) (for architecture i386): +CHECK-64-AR: 00000008 D _bar +CHECK-64-AR: 00000000 T _foo +CHECK-64-AR: macho-universal64-archive.x86_64.i386(hello.o) (for architecture x86_64): +CHECK-64-AR: 0000000000000068 s EH_frame0 +CHECK-64-AR: 000000000000003b s L_.str +CHECK-64-AR: 0000000000000000 T _main +CHECK-64-AR: 0000000000000080 S _main.eh +CHECK-64-AR: U _printf CHECK-AR-i386: macho-universal-archive.x86_64.i386(foo.o): CHECK-AR-i386: 00000008 D _bar diff --git a/llvm/tools/llvm-nm/llvm-nm.cpp b/llvm/tools/llvm-nm/llvm-nm.cpp --- a/llvm/tools/llvm-nm/llvm-nm.cpp +++ b/llvm/tools/llvm-nm/llvm-nm.cpp @@ -1154,7 +1154,7 @@ // getNsectForSegSect() is used to implement the Mach-O "-s segname sectname" // option to dump only those symbols from that section in a Mach-O file. -// It is called once for each Mach-O file from dumpSymbolNamesFromObject() +// It is called once for each Mach-O file from getSymbolNamesFromObject() // to get the section number for that named section from the command line // arguments. It returns the section number for that section in the Mach-O // file or zero it is not present. @@ -1176,7 +1176,7 @@ // getNsectInMachO() is used to implement the Mach-O "-s segname sectname" // option to dump only those symbols from that section in a Mach-O file. // It is called once for each symbol in a Mach-O file from -// dumpSymbolNamesFromObject() and returns the section number for that symbol +// getSymbolNamesFromObject() and returns the section number for that symbol // if it is in a section, else it returns 0. static unsigned getNsectInMachO(MachOObjectFile &Obj, BasicSymbolRef Sym) { DataRefImpl Symb = Sym.getRawDataRefImpl(); @@ -1742,37 +1742,37 @@ } } -static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool printName, - StringRef ArchiveName = {}, - StringRef ArchitectureName = {}) { - if (!shouldDump(Obj)) - return; - - if (ExportSymbols && Obj.isXCOFF()) { - XCOFFObjectFile *XCOFFObj = cast(&Obj); - getXCOFFExports(XCOFFObj, ArchiveName); - return; - } +static Expected +getDynamicSyms(SymbolicFile &Obj) { + const auto *E = dyn_cast(&Obj); + if (!E) + return createError("File format has no dynamic symbol table"); + return E->getDynamicSymbolIterators(); +} +// Returns false if an error is encounted or true otherwise. +static bool getSymbolNamesFromObject(SymbolicFile &Obj) { auto Symbols = Obj.symbols(); std::vector SymbolVersions; + if (DynamicSyms) { - const auto *E = dyn_cast(&Obj); - if (!E) { - error("File format has no dynamic symbol table", Obj.getFileName()); - return; + Expected SymbolsOrErr = + getDynamicSyms(Obj); + if (!SymbolsOrErr) { + error(SymbolsOrErr.takeError(), Obj.getFileName()); + return false; + } + Symbols = *SymbolsOrErr; + if (const auto *E = dyn_cast(&Obj)) { + if (Expected> VersionsOrErr = + E->readDynsymVersions()) + SymbolVersions = std::move(*VersionsOrErr); + else + WithColor::warning(errs(), ToolName) + << "unable to read symbol versions: " + << toString(VersionsOrErr.takeError()) << "\n"; } - Symbols = E->getDynamicSymbolIterators(); - - if (Expected> VersionsOrErr = - E->readDynsymVersions()) - SymbolVersions = std::move(*VersionsOrErr); - else - WithColor::warning(errs(), ToolName) - << "unable to read symbol versions: " - << toString(VersionsOrErr.takeError()) << "\n"; } - // If a "-s segname sectname" option was specified and this is a Mach-O // file get the section number for that section in this object file. unsigned int Nsect = 0; @@ -1781,7 +1781,7 @@ Nsect = getNsectForSegSect(MachO); // If this section is not in the object file no symbols are printed. if (Nsect == 0) - return; + return false; } if (!(MachO && DyldInfoOnly)) { @@ -1791,7 +1791,7 @@ Expected SymFlagsOrErr = Sym.getFlags(); if (!SymFlagsOrErr) { error(SymFlagsOrErr.takeError(), Obj.getFileName()); - return; + return false; } // Don't drop format specifc symbols for ARM and AArch64 ELF targets, they @@ -1857,19 +1857,64 @@ // all symbols from the dyld export trie as well as the bind info. if (MachO && !NoDyldInfo) dumpSymbolsFromDLInfoMachO(*MachO); + return true; +} - if (ExportSymbols) +static void printObjectLabel(bool PrintArchiveName, StringRef ArchiveName, + StringRef ArchitectureName, + StringRef ObjectFileName) { + outs() << "\n"; + if (ArchiveName.empty() || !PrintArchiveName) + outs() << ObjectFileName; + else + outs() << ArchiveName << "(" << ObjectFileName << ")"; + if (!ArchitectureName.empty()) + outs() << " (for architecture " << ArchitectureName << ")"; + outs() << ":\n"; +} + +static Expected hasSymbols(SymbolicFile &Obj) { + if (DynamicSyms) { + Expected DynamicSymsOrErr = + getDynamicSyms(Obj); + if (!DynamicSymsOrErr) + return DynamicSymsOrErr.takeError(); + return !DynamicSymsOrErr->empty(); + } + return !Obj.symbols().empty(); +} + +static void dumpSymbolNamesFromObject(SymbolicFile &Obj, bool PrintSymbolObject, + bool PrintObjectLabel, + StringRef ArchiveName = {}, + StringRef ArchitectureName = {}, + StringRef ObjectName = {}, + bool PrintArchiveName = true) { + if (!shouldDump(Obj)) return; + if (ExportSymbols && Obj.isXCOFF()) { + XCOFFObjectFile *XCOFFObj = cast(&Obj); + getXCOFFExports(XCOFFObj, ArchiveName); + return; + } + + if (PrintObjectLabel && !ExportSymbols) + printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName, + ObjectName.empty() ? Obj.getFileName() : ObjectName); + if (!getSymbolNamesFromObject(Obj) || ExportSymbols) + return; CurrentFilename = Obj.getFileName(); - if (Symbols.empty() && SymbolList.empty() && !Quiet) { + // If there is an error in hasSymbols(), the error should be encountered in + // function getSymbolNamesFromObject first. + if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) { writeFileName(errs(), ArchiveName, ArchitectureName); errs() << "no symbols\n"; } sortSymbolList(); - printSymbolList(Obj, printName, ArchiveName, ArchitectureName); + printSymbolList(Obj, PrintSymbolObject, ArchiveName, ArchitectureName); } // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file @@ -1948,15 +1993,10 @@ } if (!checkMachOAndArchFlags(O, Filename)) return; - if (!PrintFileName && shouldDump(*O) && !ExportSymbols) { - outs() << "\n"; - if (isa(O)) { - outs() << Filename << "(" << O->getFileName() << ")"; - } else - outs() << O->getFileName(); - outs() << ":\n"; - } - dumpSymbolNamesFromObject(*O, false, Filename); + dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/false, !PrintFileName, + Filename, + /*ArchitectureName=*/{}, O->getFileName(), + /*PrintArchiveName=*/false); } } if (Err) @@ -1982,16 +2022,11 @@ ArchitectureName.clear(); if (ObjOrErr) { ObjectFile &Obj = *ObjOrErr.get(); - if (ArchFlags.size() > 1) { - if (PrintFileName) - ArchitectureName = I->getArchFlagName(); - else - outs() << "\n" - << Obj.getFileName() << " (for architecture " - << I->getArchFlagName() << ")" - << ":\n"; - } - dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName); + if (ArchFlags.size() > 1) + ArchitectureName = I->getArchFlagName(); + dumpSymbolNamesFromObject(Obj, /*PrintSymbolObject=*/false, + (ArchFlags.size() > 1) && !PrintFileName, + ArchiveName, ArchitectureName); } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { error(std::move(E), Filename, @@ -2015,20 +2050,11 @@ continue; } if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { - if (PrintFileName) { - ArchiveName = std::string(A->getFileName()); - if (ArchFlags.size() > 1) - ArchitectureName = I->getArchFlagName(); - } else { - outs() << "\n" << A->getFileName(); - outs() << "(" << O->getFileName() << ")"; - if (ArchFlags.size() > 1) { - outs() << " (for architecture " << I->getArchFlagName() - << ")"; - } - outs() << ":\n"; - } - dumpSymbolNamesFromObject(*O, false, ArchiveName, + ArchiveName = std::string(A->getFileName()); + if (ArchFlags.size() > 1) + ArchitectureName = I->getArchFlagName(); + dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/false, + !PrintFileName, ArchiveName, ArchitectureName); } } @@ -2066,7 +2092,8 @@ std::string ArchiveName; if (ObjOrErr) { ObjectFile &Obj = *ObjOrErr.get(); - dumpSymbolNamesFromObject(Obj, false); + dumpSymbolNamesFromObject(Obj, /*PrintSymbolObject=*/false, + /*PrintObjectLabel=*/false); } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) error(std::move(E), Filename); else if (Expected> AOrErr = I->getAsArchive()) { @@ -2082,13 +2109,9 @@ continue; } if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { - if (PrintFileName) - ArchiveName = std::string(A->getFileName()); - else - outs() << "\n" - << A->getFileName() << "(" << O->getFileName() << ")" - << ":\n"; - dumpSymbolNamesFromObject(*O, false, ArchiveName); + ArchiveName = std::string(A->getFileName()); + dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/false, + !PrintFileName, ArchiveName); } } if (Err) @@ -2118,18 +2141,10 @@ ArchitectureName.clear(); if (ObjOrErr) { ObjectFile &Obj = *ObjOrErr.get(); - if (PrintFileName) { - if (isa(Obj) && moreThanOneArch) - ArchitectureName = O.getArchFlagName(); - } else { - if (moreThanOneArch) - outs() << "\n"; - outs() << Obj.getFileName(); - if (isa(Obj) && moreThanOneArch) - outs() << " (for architecture " << O.getArchFlagName() << ")"; - outs() << ":\n"; - } - dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName); + if (isa(Obj) && moreThanOneArch) + ArchitectureName = O.getArchFlagName(); + dumpSymbolNamesFromObject(Obj, /*PrintSymbolObject=*/false, + !PrintFileName, ArchiveName, ArchitectureName); } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { error(std::move(E), Filename, moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef()); @@ -2147,21 +2162,12 @@ continue; } if (SymbolicFile *F = dyn_cast(&*ChildOrErr.get())) { - if (PrintFileName) { - ArchiveName = std::string(A->getFileName()); - if (isa(F) && moreThanOneArch) - ArchitectureName = O.getArchFlagName(); - } else { - outs() << "\n" << A->getFileName(); - if (isa(F)) { - outs() << "(" << F->getFileName() << ")"; - if (moreThanOneArch) - outs() << " (for architecture " << O.getArchFlagName() << ")"; - } else - outs() << ":" << F->getFileName(); - outs() << ":\n"; - } - dumpSymbolNamesFromObject(*F, false, ArchiveName, ArchitectureName); + ArchiveName = std::string(A->getFileName()); + if (isa(F) && moreThanOneArch) + ArchitectureName = O.getArchFlagName(); + dumpSymbolNamesFromObject(*F, /*PrintSymbolObject=*/false, + !PrintFileName, ArchiveName, + ArchitectureName); } } if (Err) @@ -2203,13 +2209,12 @@ continue; if (!AddInlinedInfo && !I.isTopLevelLib()) continue; - if (auto ObjOrErr = I.getAsObjectFile()) { - outs() << "\n" - << I.getInstallName() << " (for architecture " << ArchName << ")" - << ":\n"; - dumpSymbolNamesFromObject(*ObjOrErr.get(), false, {}, ArchName); - } else if (Error E = - isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { + if (auto ObjOrErr = I.getAsObjectFile()) + dumpSymbolNamesFromObject(*ObjOrErr.get(), /*PrintSymbolObject=*/false, + /*PrintObjectLabel=*/true, + /*ArchiveName=*/{}, ArchName, + I.getInstallName()); + else if (Error E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { error(std::move(E), Filename, ArchName); } } @@ -2223,7 +2228,8 @@ } if (!checkMachOAndArchFlags(O, Filename)) return; - dumpSymbolNamesFromObject(*O, true); + dumpSymbolNamesFromObject(*O, /*PrintSymbolObject=*/true, + /*PrintObjectLabel=*/false); } static void dumpSymbolNamesFromFile(std::string &Filename) {