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 @@ -1887,282 +1887,192 @@ return true; } -static void dumpSymbolNamesFromFile(std::string &Filename) { - ErrorOr> BufferOrErr = - MemoryBuffer::getFileOrSTDIN(Filename); - if (error(BufferOrErr.getError(), Filename)) - return; - - LLVMContext Context; - LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context; - Expected> BinaryOrErr = - createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr); - if (!BinaryOrErr) { - error(BinaryOrErr.takeError(), Filename); - return; +static void dumpArchiveMap(Archive *A, std::string &Filename) { + Archive::symbol_iterator I = A->symbol_begin(); + Archive::symbol_iterator E = A->symbol_end(); + if (I != E) { + outs() << "Archive map\n"; + for (; I != E; ++I) { + Expected C = I->getMember(); + if (!C) { + error(C.takeError(), Filename); + break; + } + Expected FileNameOrErr = C->getName(); + if (!FileNameOrErr) { + error(FileNameOrErr.takeError(), Filename); + break; + } + StringRef SymName = I->getName(); + outs() << SymName << " in " << FileNameOrErr.get() << "\n"; + } + outs() << "\n"; } - Binary &Bin = *BinaryOrErr.get(); +} - if (Archive *A = dyn_cast(&Bin)) { - if (ArchiveMap) { - Archive::symbol_iterator I = A->symbol_begin(); - Archive::symbol_iterator E = A->symbol_end(); - if (I != E) { - outs() << "Archive map\n"; - for (; I != E; ++I) { - Expected C = I->getMember(); - if (!C) { - error(C.takeError(), Filename); - break; - } - Expected FileNameOrErr = C->getName(); - if (!FileNameOrErr) { - error(FileNameOrErr.takeError(), Filename); - break; - } - StringRef SymName = I->getName(); - outs() << SymName << " in " << FileNameOrErr.get() << "\n"; - } +static void dumpArchive(Archive *A, std::string &Filename, + LLVMContext *ContextPtr) { + if (ArchiveMap) + dumpArchiveMap(A, Filename); + + Error Err = Error::success(); + for (auto &C : A->children(Err)) { + Expected> ChildOrErr = C.getAsBinary(ContextPtr); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), Filename, C); + continue; + } + if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { + if (!MachOPrintSizeWarning && PrintSize && isa(O)) { + WithColor::warning(errs(), ToolName) + << "sizes with -print-size for Mach-O files are always zero.\n"; + MachOPrintSizeWarning = true; + } + if (!checkMachOAndArchFlags(O, Filename)) + return; + if (!PrintFileName && !ExportSymbols) { outs() << "\n"; + if (isa(O)) { + outs() << Filename << "(" << O->getFileName() << ")"; + } else + outs() << O->getFileName(); + outs() << ":\n"; } + dumpSymbolNamesFromObject(*O, false, Filename); } + } + if (Err) + error(std::move(Err), A->getFileName()); +} - { - Error Err = Error::success(); - for (auto &C : A->children(Err)) { - Expected> ChildOrErr = - C.getAsBinary(ContextPtr); - if (!ChildOrErr) { - if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) - error(std::move(E), Filename, C); - continue; - } - if (SymbolicFile *O = dyn_cast(&*ChildOrErr.get())) { - if (!MachOPrintSizeWarning && PrintSize && isa(O)) { - WithColor::warning(errs(), ToolName) - << "sizes with -print-size for Mach-O files are always zero.\n"; - MachOPrintSizeWarning = true; - } - if (!checkMachOAndArchFlags(O, Filename)) - return; - if (!PrintFileName && !ExportSymbols) { - outs() << "\n"; - if (isa(O)) { - outs() << Filename << "(" << O->getFileName() << ")"; - } else - outs() << O->getFileName(); - outs() << ":\n"; +static void dumpMachOUniversalBinaryMatchArchFlags(MachOUniversalBinary *UB, + std::string &Filename, + LLVMContext *ContextPtr) { + // Look for a slice in the universal binary that matches each ArchFlag. + bool ArchFound; + for (unsigned i = 0; i < ArchFlags.size(); ++i) { + ArchFound = false; + for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), + E = UB->end_objects(); + I != E; ++I) { + if (ArchFlags[i] == I->getArchFlagName()) { + ArchFound = true; + Expected> ObjOrErr = I->getAsObjectFile(); + std::string ArchiveName; + std::string ArchitectureName; + ArchiveName.clear(); + 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(*O, false, Filename); - } - } - if (Err) - error(std::move(Err), A->getFileName()); - } - return; - } - if (MachOUniversalBinary *UB = dyn_cast(&Bin)) { - // If we have a list of architecture flags specified dump only those. - if (!ArchAll && !ArchFlags.empty()) { - // Look for a slice in the universal binary that matches each ArchFlag. - bool ArchFound; - for (unsigned i = 0; i < ArchFlags.size(); ++i) { - ArchFound = false; - for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), - E = UB->end_objects(); - I != E; ++I) { - if (ArchFlags[i] == I->getArchFlagName()) { - ArchFound = true; - Expected> ObjOrErr = - I->getAsObjectFile(); - std::string ArchiveName; - std::string ArchitectureName; - ArchiveName.clear(); - 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); + } else if (auto E = + isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { + error(std::move(E), Filename, + ArchFlags.size() > 1 ? StringRef(I->getArchFlagName()) + : StringRef()); + continue; + } else if (Expected> AOrErr = + I->getAsArchive()) { + std::unique_ptr &A = *AOrErr; + Error Err = Error::success(); + for (auto &C : A->children(Err)) { + Expected> ChildOrErr = + C.getAsBinary(ContextPtr); + if (!ChildOrErr) { + if (auto E = + isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) { + error(std::move(E), Filename, C, + ArchFlags.size() > 1 ? StringRef(I->getArchFlagName()) + : StringRef()); } - dumpSymbolNamesFromObject(Obj, false, ArchiveName, - ArchitectureName); - } else if (auto E = isNotObjectErrorInvalidFileType( - ObjOrErr.takeError())) { - error(std::move(E), Filename, ArchFlags.size() > 1 ? - StringRef(I->getArchFlagName()) : StringRef()); continue; - } else if (Expected> AOrErr = - I->getAsArchive()) { - std::unique_ptr &A = *AOrErr; - Error Err = Error::success(); - for (auto &C : A->children(Err)) { - Expected> ChildOrErr = - C.getAsBinary(ContextPtr); - if (!ChildOrErr) { - if (auto E = isNotObjectErrorInvalidFileType( - ChildOrErr.takeError())) { - error(std::move(E), Filename, C, ArchFlags.size() > 1 ? - StringRef(I->getArchFlagName()) : StringRef()); - } - 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, - ArchitectureName); + } + 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"; } - if (Err) - error(std::move(Err), A->getFileName()); - } else { - consumeError(AOrErr.takeError()); - error(Filename + " for architecture " + - StringRef(I->getArchFlagName()) + - " is not a Mach-O file or an archive file", - "Mach-O universal file"); + dumpSymbolNamesFromObject(*O, false, ArchiveName, + ArchitectureName); } } - } - if (!ArchFound) { - error(ArchFlags[i], - "file: " + Filename + " does not contain architecture"); - return; + if (Err) + error(std::move(Err), A->getFileName()); + } else { + consumeError(AOrErr.takeError()); + error(Filename + " for architecture " + + StringRef(I->getArchFlagName()) + + " is not a Mach-O file or an archive file", + "Mach-O universal file"); } } - return; } - // No architecture flags were specified so if this contains a slice that - // matches the host architecture dump only that. - if (!ArchAll) { - Triple HostTriple = MachOObjectFile::getHostArch(); - StringRef HostArchName = HostTriple.getArchName(); - for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), - E = UB->end_objects(); - I != E; ++I) { - if (HostArchName == I->getArchFlagName()) { - Expected> ObjOrErr = I->getAsObjectFile(); - std::string ArchiveName; - if (ObjOrErr) { - ObjectFile &Obj = *ObjOrErr.get(); - dumpSymbolNamesFromObject(Obj, false); - } else if (auto E = isNotObjectErrorInvalidFileType( - ObjOrErr.takeError())) { - error(std::move(E), Filename); - return; - } else if (Expected> AOrErr = - I->getAsArchive()) { - std::unique_ptr &A = *AOrErr; - Error Err = Error::success(); - for (auto &C : A->children(Err)) { - Expected> ChildOrErr = - C.getAsBinary(ContextPtr); - if (!ChildOrErr) { - if (auto E = isNotObjectErrorInvalidFileType( - ChildOrErr.takeError())) - error(std::move(E), Filename, C); - 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); - } - } - if (Err) - error(std::move(Err), A->getFileName()); - } else { - consumeError(AOrErr.takeError()); - error(Filename + " for architecture " + - StringRef(I->getArchFlagName()) + - " is not a Mach-O file or an archive file", - "Mach-O universal file"); - } - return; - } - } + if (!ArchFound) { + error(ArchFlags[i], + "file: " + Filename + " does not contain architecture"); + return; } - // Either all architectures have been specified or none have been specified - // and this does not contain the host architecture so dump all the slices. - bool moreThanOneArch = UB->getNumberOfObjects() > 1; - for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) { - Expected> ObjOrErr = O.getAsObjectFile(); + } +} + +static bool dumpMachOUniversalBinaryMatchHost(MachOUniversalBinary *UB, + std::string &Filename, + LLVMContext *ContextPtr) { + Triple HostTriple = MachOObjectFile::getHostArch(); + StringRef HostArchName = HostTriple.getArchName(); + for (MachOUniversalBinary::object_iterator I = UB->begin_objects(), + E = UB->end_objects(); + I != E; ++I) { + if (HostArchName == I->getArchFlagName()) { + Expected> ObjOrErr = I->getAsObjectFile(); std::string ArchiveName; - std::string ArchitectureName; - ArchiveName.clear(); - 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); - } else if (auto E = isNotObjectErrorInvalidFileType( - ObjOrErr.takeError())) { - error(std::move(E), Filename, moreThanOneArch ? - StringRef(O.getArchFlagName()) : StringRef()); - continue; + dumpSymbolNamesFromObject(Obj, false); + } else if (auto E = + isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { + error(std::move(E), Filename); + return true; } else if (Expected> AOrErr = - O.getAsArchive()) { + I->getAsArchive()) { std::unique_ptr &A = *AOrErr; Error Err = Error::success(); for (auto &C : A->children(Err)) { Expected> ChildOrErr = - C.getAsBinary(ContextPtr); + C.getAsBinary(ContextPtr); if (!ChildOrErr) { - if (auto E = isNotObjectErrorInvalidFileType( - ChildOrErr.takeError())) - error(std::move(E), Filename, C, moreThanOneArch ? - StringRef(ArchitectureName) : StringRef()); + if (auto E = + isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), Filename, C); continue; } - if (SymbolicFile *F = dyn_cast(&*ChildOrErr.get())) { - if (PrintFileName) { + if (SymbolicFile *O = 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); + else + outs() << "\n" + << A->getFileName() << "(" << O->getFileName() << ")" + << ":\n"; + dumpSymbolNamesFromObject(*O, false, ArchiveName); } } if (Err) @@ -2170,49 +2080,161 @@ } else { consumeError(AOrErr.takeError()); error(Filename + " for architecture " + - StringRef(O.getArchFlagName()) + - " is not a Mach-O file or an archive file", + StringRef(I->getArchFlagName()) + + " is not a Mach-O file or an archive file", "Mach-O universal file"); } + return true; } - return; } + return false; +} - if (TapiUniversal *TU = dyn_cast(&Bin)) { - for (const TapiUniversal::ObjectForArch &I : TU->objects()) { - StringRef ArchName = I.getArchFlagName(); - const bool ShowArch = - ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName); - if (!ShowArch) - 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())) { - error(std::move(E), Filename, ArchName); +static void dumpMachOUniversalBinaryArchAll(MachOUniversalBinary *UB, + std::string &Filename, + LLVMContext *ContextPtr) { + bool moreThanOneArch = UB->getNumberOfObjects() > 1; + for (const MachOUniversalBinary::ObjectForArch &O : UB->objects()) { + Expected> ObjOrErr = O.getAsObjectFile(); + std::string ArchiveName; + std::string ArchitectureName; + ArchiveName.clear(); + 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); + } else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) { + error(std::move(E), Filename, + moreThanOneArch ? StringRef(O.getArchFlagName()) : StringRef()); + continue; + } else if (Expected> AOrErr = O.getAsArchive()) { + std::unique_ptr &A = *AOrErr; + Error Err = Error::success(); + for (auto &C : A->children(Err)) { + Expected> ChildOrErr = + C.getAsBinary(ContextPtr); + if (!ChildOrErr) { + if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError())) + error(std::move(E), Filename, C, + moreThanOneArch ? StringRef(ArchitectureName) : StringRef()); + 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); + } + } + if (Err) + error(std::move(Err), A->getFileName()); + } else { + consumeError(AOrErr.takeError()); + error(Filename + " for architecture " + StringRef(O.getArchFlagName()) + + " is not a Mach-O file or an archive file", + "Mach-O universal file"); } + } +} +static void dumpMachOUniversalBinary(MachOUniversalBinary *UB, + std::string &Filename, + LLVMContext *ContextPtr) { + // If we have a list of architecture flags specified dump only those. + if (!ArchAll && !ArchFlags.empty()) { + dumpMachOUniversalBinaryMatchArchFlags(UB, Filename, ContextPtr); return; } - if (SymbolicFile *O = dyn_cast(&Bin)) { - if (!MachOPrintSizeWarning && PrintSize && isa(O)) { - WithColor::warning(errs(), ToolName) - << "sizes with --print-size for Mach-O files are always zero.\n"; - MachOPrintSizeWarning = true; + // No architecture flags were specified so if this contains a slice that + // matches the host architecture dump only that. + if (!ArchAll && dumpMachOUniversalBinaryMatchHost(UB, Filename, ContextPtr)) + return; + + // Either all architectures have been specified or none have been specified + // and this does not contain the host architecture so dump all the slices. + dumpMachOUniversalBinaryArchAll(UB, Filename, ContextPtr); +} + +static void dumpTapiUniversal(TapiUniversal *TU, std::string &Filename) { + for (const TapiUniversal::ObjectForArch &I : TU->objects()) { + StringRef ArchName = I.getArchFlagName(); + const bool ShowArch = + ArchFlags.empty() || llvm::is_contained(ArchFlags, ArchName); + if (!ShowArch) + 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())) { + error(std::move(E), Filename, ArchName); } - if (!checkMachOAndArchFlags(O, Filename)) - return; - dumpSymbolNamesFromObject(*O, true); } } +static void dumpSymbolicFile(SymbolicFile *O, std::string &Filename) { + if (!MachOPrintSizeWarning && PrintSize && isa(O)) { + WithColor::warning(errs(), ToolName) + << "sizes with --print-size for Mach-O files are always zero.\n"; + MachOPrintSizeWarning = true; + } + if (!checkMachOAndArchFlags(O, Filename)) + return; + dumpSymbolNamesFromObject(*O, true); +} + +static void dumpSymbolNamesFromFile(std::string &Filename) { + ErrorOr> BufferOrErr = + MemoryBuffer::getFileOrSTDIN(Filename); + if (error(BufferOrErr.getError(), Filename)) + return; + + LLVMContext Context; + LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context; + Expected> BinaryOrErr = + createBinary(BufferOrErr.get()->getMemBufferRef(), ContextPtr); + if (!BinaryOrErr) { + error(BinaryOrErr.takeError(), Filename); + return; + } + Binary &Bin = *BinaryOrErr.get(); + if (Archive *A = dyn_cast(&Bin)) + dumpArchive(A, Filename, ContextPtr); + else if (MachOUniversalBinary *UB = dyn_cast(&Bin)) + dumpMachOUniversalBinary(UB, Filename, ContextPtr); + else if (TapiUniversal *TU = dyn_cast(&Bin)) + dumpTapiUniversal(TU, Filename); + else if (SymbolicFile *O = dyn_cast(&Bin)) + dumpSymbolicFile(O, Filename); +} + int main(int argc, char **argv) { InitLLVM X(argc, argv); BumpPtrAllocator A;