kastiglione created this revision.
kastiglione added reviewers: JDevlieghere, mib, augusto2112.
Herald added subscribers: kbarton, nemanjai.
Herald added a project: All.
kastiglione requested review of this revision.
Herald added projects: clang, LLDB.
Herald added subscribers: lldb-commits, cfe-commits.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D129456

Files:
  clang/include/clang/Frontend/FrontendActions.h
  clang/lib/Frontend/FrontendActions.cpp
  lldb/source/Commands/CommandObjectTarget.cpp
  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

Index: lldb/test/API/commands/target/dump-pcm-info/main.m
===================================================================
--- /dev/null
+++ lldb/test/API/commands/target/dump-pcm-info/main.m
@@ -0,0 +1 @@
+int main() { return 0; }
Index: lldb/test/API/commands/target/dump-pcm-info/TestDumpPCMInfo.py
===================================================================
--- /dev/null
+++ 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
+    def test(self):
+        self.build()
+
+        # lldbutil.run_break_set_by_symbol(self, "main")
+        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"])
Index: lldb/test/API/commands/target/dump-pcm-info/Makefile
===================================================================
--- /dev/null
+++ 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
+
Index: lldb/source/Commands/CommandObjectTarget.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTarget.cpp
+++ lldb/source/Commands/CommandObjectTarget.cpp
@@ -53,6 +53,10 @@
 #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 +2159,41 @@
   }
 };
 
+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 {
+    clang::CompilerInstance compiler;
+    compiler.createDiagnostics();
+
+    const char *pcm_path = command.GetArgumentAtIndex(0);
+    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 +2445,10 @@
   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 +2468,10 @@
     LoadSubCommand("line-table",
                    CommandObjectSP(new CommandObjectTargetModulesDumpLineTable(
                        interpreter)));
+    LoadSubCommand(
+        "pcm-info",
+        CommandObjectSP(
+            new CommandObjectTargetModulesDumpClangPCMInfo(interpreter)));
   }
 
   ~CommandObjectTargetModulesDump() override = default;
Index: clang/lib/Frontend/FrontendActions.cpp
===================================================================
--- clang/lib/Frontend/FrontendActions.cpp
+++ clang/lib/Frontend/FrontendActions.cpp
@@ -854,8 +854,9 @@
     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();
Index: clang/include/clang/Frontend/FrontendActions.h
===================================================================
--- clang/include/clang/Frontend/FrontendActions.h
+++ clang/include/clang/Frontend/FrontendActions.h
@@ -190,6 +190,10 @@
 /// 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;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to