[Lldb-commits] [lldb] 566146c - [lldb][trace] Add a basic function call dumpdump [1] - Add the command scaffolding

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Tue Oct 18 13:58:00 PDT 2022


Author: Walter Erquinigo
Date: 2022-10-18T13:57:52-07:00
New Revision: 566146c03b054db2530f6b5997dfd0cd1a243657

URL: https://github.com/llvm/llvm-project/commit/566146c03b054db2530f6b5997dfd0cd1a243657
DIFF: https://github.com/llvm/llvm-project/commit/566146c03b054db2530f6b5997dfd0cd1a243657.diff

LOG: [lldb][trace] Add a basic function call dumpdump [1] - Add the command scaffolding

The command is thread trace dump function-calls and as minimum will
require printing to a file in json and non-json format

I added a test

Differential Revision: https://reviews.llvm.org/D135521

Added: 
    lldb/test/API/commands/trace/TestTraceDumpFunctionCalls.py

Modified: 
    lldb/source/Commands/CommandObjectThread.cpp
    lldb/source/Commands/Options.td

Removed: 
    


################################################################################
diff  --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 2a22900793ce5..ae2a8edd12d40 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -2090,6 +2090,113 @@ class CommandObjectTraceStop : public CommandObjectMultipleThreads {
   }
 };
 
+static ThreadSP GetSingleThreadFromArgs(ExecutionContext &exe_ctx, Args &args,
+                                        CommandReturnObject &result) {
+  if (args.GetArgumentCount() == 0)
+    return exe_ctx.GetThreadSP();
+
+  const char *arg = args.GetArgumentAtIndex(0);
+  uint32_t thread_idx;
+
+  if (!llvm::to_integer(arg, thread_idx)) {
+    result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n", arg);
+    return nullptr;
+  }
+  ThreadSP thread_sp =
+      exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(thread_idx);
+  if (!thread_sp)
+    result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg);
+  return thread_sp;
+}
+
+// CommandObjectTraceDumpFunctionCalls
+#define LLDB_OPTIONS_thread_trace_dump_function_calls
+#include "CommandOptions.inc"
+
+class CommandObjectTraceDumpFunctionCalls : public CommandObjectParsed {
+public:
+  class CommandOptions : public Options {
+  public:
+    CommandOptions() { OptionParsingStarting(nullptr); }
+
+    ~CommandOptions() override = default;
+
+    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+                          ExecutionContext *execution_context) override {
+      Status error;
+      const int short_option = m_getopt_table[option_idx].val;
+
+      switch (short_option) {
+      case 'j': {
+        m_json = true;
+        break;
+      }
+      case 'J': {
+        m_pretty_json = true;
+        break;
+      }
+      case 'F': {
+        m_output_file.emplace(option_arg);
+        break;
+      }
+      default:
+        llvm_unreachable("Unimplemented option");
+      }
+      return error;
+    }
+
+    void OptionParsingStarting(ExecutionContext *execution_context) override {
+      m_json = false;
+      m_pretty_json = false;
+      m_output_file = llvm::None;
+    }
+
+    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+      return llvm::makeArrayRef(g_thread_trace_dump_function_calls_options);
+    }
+
+    static const size_t kDefaultCount = 20;
+
+    // Instance variables to hold the values for command options.
+    bool m_json;
+    bool m_pretty_json;
+    llvm::Optional<FileSpec> m_output_file;
+  };
+
+  CommandObjectTraceDumpFunctionCalls(CommandInterpreter &interpreter)
+      : CommandObjectParsed(
+            interpreter, "thread trace dump function-calls",
+            "Dump the traced function-calls for one thread. If no "
+            "thread is specified, the current thread is used.",
+            nullptr,
+            eCommandRequiresProcess | eCommandRequiresThread |
+                eCommandTryTargetAPILock | eCommandProcessMustBeLaunched |
+                eCommandProcessMustBePaused | eCommandProcessMustBeTraced) {
+    CommandArgumentData thread_arg{eArgTypeThreadIndex, eArgRepeatOptional};
+    m_arguments.push_back({thread_arg});
+  }
+
+  ~CommandObjectTraceDumpFunctionCalls() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+protected:
+  bool DoExecute(Args &args, CommandReturnObject &result) override {
+    ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result);
+    if (!thread_sp) {
+      result.AppendError("invalid thread\n");
+      return false;
+    }
+    result.AppendMessageWithFormatv(
+        "json = {0}, pretty_json = {1}, file = {2}, thread = {3}",
+        m_options.m_json, m_options.m_pretty_json, !!m_options.m_output_file,
+        thread_sp->GetID());
+    return true;
+  }
+
+  CommandOptions m_options;
+};
+
 // CommandObjectTraceDumpInstructions
 #define LLDB_OPTIONS_thread_trace_dump_instructions
 #include "CommandOptions.inc"
@@ -2238,28 +2345,8 @@ class CommandObjectTraceDumpInstructions : public CommandObjectParsed {
   }
 
 protected:
-  ThreadSP GetThread(Args &args, CommandReturnObject &result) {
-    if (args.GetArgumentCount() == 0)
-      return m_exe_ctx.GetThreadSP();
-
-    const char *arg = args.GetArgumentAtIndex(0);
-    uint32_t thread_idx;
-
-    if (!llvm::to_integer(arg, thread_idx)) {
-      result.AppendErrorWithFormat("invalid thread specification: \"%s\"\n",
-                                   arg);
-      return nullptr;
-    }
-    ThreadSP thread_sp =
-        m_exe_ctx.GetProcessRef().GetThreadList().FindThreadByIndexID(
-            thread_idx);
-    if (!thread_sp)
-      result.AppendErrorWithFormat("no thread with index: \"%s\"\n", arg);
-    return thread_sp;
-  }
-
   bool DoExecute(Args &args, CommandReturnObject &result) override {
-    ThreadSP thread_sp = GetThread(args, result);
+    ThreadSP thread_sp = GetSingleThreadFromArgs(m_exe_ctx, args, result);
     if (!thread_sp) {
       result.AppendError("invalid thread\n");
       return false;
@@ -2401,6 +2488,9 @@ class CommandObjectMultiwordTraceDump : public CommandObjectMultiword {
     LoadSubCommand(
         "instructions",
         CommandObjectSP(new CommandObjectTraceDumpInstructions(interpreter)));
+    LoadSubCommand(
+        "function-calls",
+        CommandObjectSP(new CommandObjectTraceDumpFunctionCalls(interpreter)));
     LoadSubCommand(
         "info", CommandObjectSP(new CommandObjectTraceDumpInfo(interpreter)));
   }

diff  --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index eafe85f4873ae..6d2da2532b474 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -1093,6 +1093,19 @@ let Command = "thread plan list" in {
     Desc<"Display thread plans for unreported threads">;
 }
 
+let Command = "thread trace dump function calls" in {
+  def thread_trace_dump_function_calls_file : Option<"file", "F">, Group<1>,
+    Arg<"Filename">,
+    Desc<"Dump the function calls to a file instead of the standard output.">;
+  def thread_trace_dump_function_calls_json: Option<"json", "j">,
+    Group<1>,
+    Desc<"Dump in simple JSON format.">;
+  def thread_trace_dump_function_calls_pretty_json: Option<"pretty-json", "J">,
+    Group<1>,
+    Desc<"Dump in JSON format but pretty printing the output for easier "
+    "readability.">;
+}
+
 let Command = "thread trace dump instructions" in {
   def thread_trace_dump_instructions_forwards: Option<"forwards", "f">,
     Group<1>,

diff  --git a/lldb/test/API/commands/trace/TestTraceDumpFunctionCalls.py b/lldb/test/API/commands/trace/TestTraceDumpFunctionCalls.py
new file mode 100644
index 0000000000000..147a5c9051a7f
--- /dev/null
+++ b/lldb/test/API/commands/trace/TestTraceDumpFunctionCalls.py
@@ -0,0 +1,17 @@
+from intelpt_testcase import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+
+class TestTraceDumpInfo(TraceIntelPTTestCaseBase):
+    def testDumpFunctionCalls(self):
+      self.expect("trace load -v " +
+        os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"))
+
+      self.expect("thread trace dump function-calls 2",
+        error=True, substrs=['error: no thread with index: "2"'])
+
+      self.expect("thread trace dump function-calls 1 -j",
+        substrs=['json = true, pretty_json = false, file = false, thread = 3842849'])
+
+      self.expect("thread trace dump function-calls 1 -F /tmp -J",
+        substrs=['false, pretty_json = true, file = true, thread = 3842849'])


        


More information about the lldb-commits mailing list