Author: Dave Lee Date: 2022-07-13T16:56:53-07:00 New Revision: b5ccfeb6bfbbc5436b91a1e317f88e2c499c9306
URL: https://github.com/llvm/llvm-project/commit/b5ccfeb6bfbbc5436b91a1e317f88e2c499c9306 DIFF: https://github.com/llvm/llvm-project/commit/b5ccfeb6bfbbc5436b91a1e317f88e2c499c9306.diff LOG: [lldb] Add image dump pcm-info command Add `pcm-info` to the `target module dump` subcommands. This dump command shows information about clang .pcm files. This command effectively runs `clang -module-file-info` and produces identical output. The .pcm file format is tightly coupled to the clang version. The clang embedded in lldb is not guaranteed to match the version of the clang executable available on the local system. There have been times when I've needed to view the details about a .pcm file produced by lldb's embedded clang, but because the clang executable was a slightly different version, the `-module-file-info` invocation failed. With this command, users can inspect .pcm files generated by lldb too. Differential Revision: https://reviews.llvm.org/D129456 Added: lldb/test/API/commands/target/dump-pcm-info/Makefile lldb/test/API/commands/target/dump-pcm-info/TestDumpPCMInfo.py lldb/test/API/commands/target/dump-pcm-info/main.m Modified: clang/include/clang/Frontend/FrontendActions.h clang/lib/Frontend/FrontendActions.cpp lldb/source/Commands/CommandObjectTarget.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index ae829d741152a..fe399850bd447 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -190,6 +190,10 @@ class SyntaxOnlyAction : public ASTFrontendAction { /// Dump information about the given module file, to be used for /// basic debugging and discovery. class DumpModuleInfoAction : public ASTFrontendAction { +public: + // Allow other tools (ex lldb) to direct output for their use. + llvm::raw_ostream *OutputStream = nullptr; + protected: std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index f61c83a2a465e..f833541caa25c 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -854,8 +854,9 @@ void DumpModuleInfoAction::ExecuteAction() { std::error_code EC; OutFile.reset(new llvm::raw_fd_ostream(OutputFileName.str(), EC, llvm::sys::fs::OF_TextWithCRLF)); + OutputStream = OutFile.get(); } - llvm::raw_ostream &Out = OutFile.get()? *OutFile.get() : llvm::outs(); + llvm::raw_ostream &Out = OutputStream ? *OutputStream : llvm::outs(); Out << "Information for module file '" << getCurrentFile() << "':\n"; auto &FileMgr = getCompilerInstance().getFileManager(); diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 2b71f1bc7bc86..51978878c8b9d 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -47,12 +47,18 @@ #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadSpec.h" #include "lldb/Utility/Args.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/FileSpec.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/State.h" #include "lldb/Utility/Timer.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-private-enumerations.h" +#include "clang/CodeGen/ObjectFilePCHContainerOperations.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/FrontendActions.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FormatAdapters.h" @@ -2155,6 +2161,59 @@ class CommandObjectTargetModulesDumpSections } }; +class CommandObjectTargetModulesDumpClangPCMInfo : public CommandObjectParsed { +public: + CommandObjectTargetModulesDumpClangPCMInfo(CommandInterpreter &interpreter) + : CommandObjectParsed( + interpreter, "target modules dump pcm-info", + "Dump information about the given clang module (pcm).") { + // Take a single file argument. + CommandArgumentData arg{eArgTypeFilename, eArgRepeatPlain}; + m_arguments.push_back({arg}); + } + + ~CommandObjectTargetModulesDumpClangPCMInfo() override = default; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 1) { + result.AppendErrorWithFormat("'%s' takes exactly one pcm path argument.", + m_cmd_name.c_str()); + return false; + } + + const char *pcm_path = command.GetArgumentAtIndex(0); + FileSpec pcm_file{pcm_path}; + + if (pcm_file.GetFileNameExtension().GetStringRef() != ".pcm") { + result.AppendError("file must have a .pcm extension"); + return false; + } + + if (!FileSystem::Instance().Exists(pcm_file)) { + result.AppendError("pcm file does not exist"); + return false; + } + + clang::CompilerInstance compiler; + compiler.createDiagnostics(); + + const char *clang_args[] = {"clang", pcm_path}; + compiler.setInvocation(clang::createInvocation(clang_args)); + + clang::DumpModuleInfoAction dump_module_info; + dump_module_info.OutputStream = &result.GetOutputStream().AsRawOstream(); + // DumpModuleInfoAction requires ObjectFilePCHContainerReader. + compiler.getPCHContainerOperations()->registerReader( + std::make_unique<clang::ObjectFilePCHContainerReader>()); + + if (compiler.ExecuteAction(dump_module_info)) + result.SetStatus(eReturnStatusSuccessFinishResult); + + return result.Succeeded(); + } +}; + #pragma mark CommandObjectTargetModulesDumpClangAST // Clang AST dumping command @@ -2406,10 +2465,10 @@ class CommandObjectTargetModulesDump : public CommandObjectMultiword { CommandObjectTargetModulesDump(CommandInterpreter &interpreter) : CommandObjectMultiword( interpreter, "target modules dump", - "Commands for dumping information about one or " - "more target modules.", + "Commands for dumping information about one or more target " + "modules.", "target modules dump " - "[headers|symtab|sections|ast|symfile|line-table] " + "[objfile|symtab|sections|ast|symfile|line-table|pcm-info] " "[<file1> <file2> ...]") { LoadSubCommand("objfile", CommandObjectSP( @@ -2429,6 +2488,10 @@ class CommandObjectTargetModulesDump : public CommandObjectMultiword { LoadSubCommand("line-table", CommandObjectSP(new CommandObjectTargetModulesDumpLineTable( interpreter))); + LoadSubCommand( + "pcm-info", + CommandObjectSP( + new CommandObjectTargetModulesDumpClangPCMInfo(interpreter))); } ~CommandObjectTargetModulesDump() override = default; diff --git a/lldb/test/API/commands/target/dump-pcm-info/Makefile b/lldb/test/API/commands/target/dump-pcm-info/Makefile new file mode 100644 index 0000000000000..2d19fa74b8cf2 --- /dev/null +++ b/lldb/test/API/commands/target/dump-pcm-info/Makefile @@ -0,0 +1,4 @@ +OBJC_SOURCES := main.m +USE_PRIVATE_MODULE_CACHE = YES +include Makefile.rules + diff --git a/lldb/test/API/commands/target/dump-pcm-info/TestDumpPCMInfo.py b/lldb/test/API/commands/target/dump-pcm-info/TestDumpPCMInfo.py new file mode 100644 index 0000000000000..a3c9dda7bb160 --- /dev/null +++ b/lldb/test/API/commands/target/dump-pcm-info/TestDumpPCMInfo.py @@ -0,0 +1,40 @@ +""" +Test 'target modules dump pcm-info'. +""" + +import os +import shutil +import glob + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCase(TestBase): + @no_debug_info_test + @skipUnlessDarwin + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint( + self, "return", lldb.SBFileSpec("main.m")) + + mod_cache = self.getBuildArtifact("private-module-cache") + if os.path.isdir(mod_cache): + shutil.rmtree(mod_cache) + + self.runCmd(f"settings set symbols.clang-modules-cache-path '{mod_cache}'") + + # Cause lldb to generate a Darwin-*.pcm + self.runCmd("p @import Darwin") + + # root/<config-hash>/<module-name>-<modulemap-path-hash>.pcm + pcm_paths = glob.glob(os.path.join(mod_cache, '*', 'Darwin-*.pcm')) + self.assertEqual(len(pcm_paths), 1, "Expected one Darwin pcm") + pcm_path = pcm_paths[0] + + self.expect( + f"target modules dump pcm-info '{pcm_path}'", + startstr=f"Information for module file '{pcm_path}'", + substrs=["Module name: Darwin"]) diff --git a/lldb/test/API/commands/target/dump-pcm-info/main.m b/lldb/test/API/commands/target/dump-pcm-info/main.m new file mode 100644 index 0000000000000..76e8197013aab --- /dev/null +++ b/lldb/test/API/commands/target/dump-pcm-info/main.m @@ -0,0 +1 @@ +int main() { return 0; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits