jj10306 updated this revision to Diff 438449.
jj10306 marked 2 inline comments as done.
jj10306 added a comment.

rebase and use SBFileSpec constructor with that requires an explicit `resolve` 
flag before landing


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D128107/new/

https://reviews.llvm.org/D128107

Files:
  lldb/bindings/interface/SBDebugger.i
  lldb/include/lldb/API/SBDebugger.h
  lldb/include/lldb/API/SBFileSpec.h
  lldb/include/lldb/API/SBTrace.h
  lldb/include/lldb/Target/Trace.h
  lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
  lldb/source/API/SBDebugger.cpp
  lldb/source/API/SBTrace.cpp
  lldb/source/Commands/CommandObjectTrace.cpp
  lldb/source/Target/Trace.cpp
  lldb/test/API/commands/trace/TestTraceLoad.py

Index: lldb/test/API/commands/trace/TestTraceLoad.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceLoad.py
+++ lldb/test/API/commands/trace/TestTraceLoad.py
@@ -7,10 +7,11 @@
 class TestTraceLoad(TraceIntelPTTestCaseBase):
     NO_DEBUG_INFO_TESTCASE = True
 
+    @testSBAPIAndCommands
     def testLoadMultiCoreTrace(self):
         src_dir = self.getSourceDir()
-        trace_definition_file = os.path.join(src_dir, "intelpt-multi-core-trace", "trace.json")
-        self.expect("trace load -v " + trace_definition_file, substrs=["intel-pt"])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-multi-core-trace", "trace.json")
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"])
         self.expect("thread trace dump instructions 2 -t",
           substrs=["19521: [tsc=0x008fb5211c143fd8] error: expected tracing enabled event",
                    "m.out`foo() + 65 at multi_thread.cpp:12:21",
@@ -19,10 +20,11 @@
           substrs=["67910: [tsc=0x008fb5211bfdf270] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",
                    "m.out`bar() + 26 at multi_thread.cpp:20:6"])
 
+    @testSBAPIAndCommands
     def testLoadMultiCoreTraceWithStringNumbers(self):
         src_dir = self.getSourceDir()
-        trace_definition_file = os.path.join(src_dir, "intelpt-multi-core-trace", "trace_with_string_numbers.json")
-        self.expect("trace load -v " + trace_definition_file, substrs=["intel-pt"])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-multi-core-trace", "trace_with_string_numbers.json")
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"])
         self.expect("thread trace dump instructions 2 -t",
           substrs=["19521: [tsc=0x008fb5211c143fd8] error: expected tracing enabled event",
                    "m.out`foo() + 65 at multi_thread.cpp:12:21",
@@ -31,10 +33,11 @@
           substrs=["67910: [tsc=0x008fb5211bfdf270] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",
                    "m.out`bar() + 26 at multi_thread.cpp:20:6"])
 
+    @testSBAPIAndCommands
     def testLoadMultiCoreTraceWithMissingThreads(self):
         src_dir = self.getSourceDir()
-        trace_definition_file = os.path.join(src_dir, "intelpt-multi-core-trace", "trace_missing_threads.json")
-        self.expect("trace load -v " + trace_definition_file, substrs=["intel-pt"])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-multi-core-trace", "trace_missing_threads.json")
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"])
         self.expect("thread trace dump instructions 3 -t",
           substrs=["19521: [tsc=0x008fb5211c143fd8] error: expected tracing enabled event",
                    "m.out`foo() + 65 at multi_thread.cpp:12:21",
@@ -43,10 +46,11 @@
           substrs=["67910: [tsc=0x008fb5211bfdf270] 0x0000000000400bd7    addl   $0x1, -0x4(%rbp)",
                    "m.out`bar() + 26 at multi_thread.cpp:20:6"])
 
+    @testSBAPIAndCommands
     def testLoadTrace(self):
         src_dir = self.getSourceDir()
-        trace_definition_file = os.path.join(src_dir, "intelpt-trace", "trace.json")
-        self.expect("trace load -v " + trace_definition_file, substrs=["intel-pt"])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-trace", "trace.json")
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, substrs=["intel-pt"])
 
         target = self.dbg.GetSelectedTarget()
         process = target.GetProcess()
@@ -88,11 +92,13 @@
   Errors:
     Number of TSC decoding errors: 0'''])
 
+    @testSBAPIAndCommands
     def testLoadInvalidTraces(self):
         src_dir = self.getSourceDir()
+
         # We test first an invalid type
-        self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad.json"), error=True,
-          substrs=['''error: expected object at traceSession.processes[0]
+        trace_description_file_path = os.path.join(src_dir, "intelpt-trace", "trace_bad.json")
+        expected_substrs = ['''error: expected object at traceSession.processes[0]
 
 Context:
 {
@@ -114,15 +120,19 @@
     "family": integer,
     "model": integer,
     "stepping": integer
-  },'''])
+  },''']
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, error=True, substrs=expected_substrs)
+
 
         # Now we test a wrong cpu family field in the global session file
-        self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad2.json"), error=True,
-            substrs=['error: expected uint64_t at traceSession.cpuInfo.family', "Context", "Schema"])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-trace", "trace_bad2.json")
+        expected_substrs = ['error: expected uint64_t at traceSession.cpuInfo.family', "Context", "Schema"]
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, error=True, substrs=expected_substrs)
+
 
         # Now we test a missing field in the intel-pt settings
-        self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad4.json"), error=True,
-            substrs=['''error: missing value at traceSession.cpuInfo.family
+        trace_description_file_path = os.path.join(src_dir, "intelpt-trace", "trace_bad4.json")
+        expected_substrs = ['''error: missing value at traceSession.cpuInfo.family
 
 Context:
 {
@@ -133,15 +143,20 @@
   },
   "processes": [],
   "type": "intel-pt"
-}''', "Schema"])
+}''', "Schema"]
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, error=True, substrs=expected_substrs)
+
 
         # Now we test an incorrect load address in the intel-pt settings
-        self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad5.json"), error=True,
-            substrs=['error: missing value at traceSession.processes[1].pid', "Schema"])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-trace", "trace_bad5.json")
+        expected_substrs = ['error: missing value at traceSession.processes[1].pid', "Schema"]
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, error=True, substrs=expected_substrs)
+
 
         # The following wrong schema will have a valid target and an invalid one. In the case of failure,
         # no targets should be created.
         self.assertEqual(self.dbg.GetNumTargets(), 0)
-        self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad3.json"), error=True,
-            substrs=['error: missing value at traceSession.processes[1].pid'])
+        trace_description_file_path = os.path.join(src_dir, "intelpt-trace", "trace_bad3.json")
+        expected_substrs = ['error: missing value at traceSession.processes[1].pid']
+        self.traceLoad(traceDescriptionFilePath=trace_description_file_path, error=True, substrs=expected_substrs)
         self.assertEqual(self.dbg.GetNumTargets(), 0)
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -89,6 +89,30 @@
       plugin_name.data());
 }
 
+Expected<lldb::TraceSP>
+Trace::LoadPostMortemTraceFromFile(Debugger &debugger,
+                                   const FileSpec &trace_description_file) {
+
+  auto buffer_or_error =
+      MemoryBuffer::getFile(trace_description_file.GetPath());
+  if (!buffer_or_error) {
+    return createStringError(std::errc::invalid_argument,
+                             "could not open input file: %s - %s.",
+                             trace_description_file.GetPath().c_str(),
+                             buffer_or_error.getError().message().c_str());
+  }
+
+  Expected<json::Value> session_file =
+      json::parse(buffer_or_error.get()->getBuffer().str());
+  if (!session_file) {
+    return session_file.takeError();
+  }
+
+  return Trace::FindPluginForPostMortemProcess(
+      debugger, *session_file,
+      trace_description_file.GetDirectory().AsCString());
+}
+
 Expected<lldb::TraceSP>
 Trace::FindPluginForPostMortemProcess(Debugger &debugger,
                                       const json::Value &trace_session_file,
Index: lldb/source/Commands/CommandObjectTrace.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTrace.cpp
+++ lldb/source/Commands/CommandObjectTrace.cpp
@@ -85,41 +85,26 @@
     if (command.size() != 1) {
       result.AppendError(
           "a single path to a JSON file containing a trace session"
-          "is required");
+          " is required");
       return false;
     }
 
-    auto end_with_failure = [&result](llvm::Error err) -> bool {
-      result.AppendErrorWithFormat("%s\n",
-                                   llvm::toString(std::move(err)).c_str());
-      return false;
-    };
+    const FileSpec trace_description_file(command[0].ref());
 
-    FileSpec json_file(command[0].ref());
+    llvm::Expected<lldb::TraceSP> trace_or_err =
+        Trace::LoadPostMortemTraceFromFile(GetDebugger(),
+                                           trace_description_file);
 
-    auto buffer_or_error = llvm::MemoryBuffer::getFile(json_file.GetPath());
-    if (!buffer_or_error) {
-      return end_with_failure(llvm::createStringError(
-          std::errc::invalid_argument, "could not open input file: %s - %s.",
-          json_file.GetPath().c_str(),
-          buffer_or_error.getError().message().c_str()));
+    if (!trace_or_err) {
+      result.AppendErrorWithFormat(
+          "%s\n", llvm::toString(trace_or_err.takeError()).c_str());
+      return false;
     }
 
-    llvm::Expected<json::Value> session_file =
-        json::parse(buffer_or_error.get()->getBuffer().str());
-    if (!session_file)
-      return end_with_failure(session_file.takeError());
-
-    if (Expected<lldb::TraceSP> traceOrErr =
-            Trace::FindPluginForPostMortemProcess(
-                GetDebugger(), *session_file,
-                json_file.GetDirectory().AsCString())) {
-      lldb::TraceSP trace_sp = traceOrErr.get();
-      if (m_options.m_verbose && trace_sp)
-        result.AppendMessageWithFormatv("loading trace with plugin {0}\n",
-                                        trace_sp->GetPluginName());
-    } else
-      return end_with_failure(traceOrErr.takeError());
+    if (m_options.m_verbose) {
+      result.AppendMessageWithFormatv("loading trace with plugin {0}\n",
+                                      trace_or_err.get()->GetPluginName());
+    }
 
     result.SetStatus(eReturnStatusSuccessFinishResult);
     return true;
Index: lldb/source/API/SBTrace.cpp
===================================================================
--- lldb/source/API/SBTrace.cpp
+++ lldb/source/API/SBTrace.cpp
@@ -9,6 +9,7 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Utility/Instrumentation.h"
 
+#include "lldb/API/SBDebugger.h"
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBThread.h"
 #include "lldb/API/SBTrace.h"
@@ -19,6 +20,7 @@
 
 using namespace lldb;
 using namespace lldb_private;
+using namespace llvm;
 
 SBTrace::SBTrace() { LLDB_INSTRUMENT_VA(this); }
 
@@ -26,6 +28,21 @@
   LLDB_INSTRUMENT_VA(this, trace_sp);
 }
 
+SBTrace SBTrace::LoadTraceFromFile(SBError &error, SBDebugger &debugger,
+                                   const SBFileSpec &trace_description_file) {
+  LLDB_INSTRUMENT_VA(error, debugger, trace_description_file);
+
+  Expected<lldb::TraceSP> trace_or_err = Trace::LoadPostMortemTraceFromFile(
+      debugger.ref(), trace_description_file.ref());
+
+  if (!trace_or_err) {
+    error.SetErrorString(toString(trace_or_err.takeError()).c_str());
+    return SBTrace();
+  }
+
+  return SBTrace(trace_or_err.get());
+}
+
 const char *SBTrace::GetStartConfigurationHelp() {
   LLDB_INSTRUMENT_VA(this);
   return m_opaque_sp ? m_opaque_sp->GetStartConfigurationHelp() : nullptr;
Index: lldb/source/API/SBDebugger.cpp
===================================================================
--- lldb/source/API/SBDebugger.cpp
+++ lldb/source/API/SBDebugger.cpp
@@ -27,6 +27,7 @@
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBTarget.h"
 #include "lldb/API/SBThread.h"
+#include "lldb/API/SBTrace.h"
 #include "lldb/API/SBTypeCategory.h"
 #include "lldb/API/SBTypeFilter.h"
 #include "lldb/API/SBTypeFormat.h"
@@ -1633,3 +1634,10 @@
     return m_opaque_sp->SetLoggingCallback(log_callback, baton);
   }
 }
+
+SBTrace
+SBDebugger::LoadTraceFromFile(SBError &error,
+                              const SBFileSpec &trace_description_file) {
+  LLDB_INSTRUMENT_VA(this, error, trace_description_file);
+  return SBTrace::LoadTraceFromFile(error, *this, trace_description_file);
+}
Index: lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
+++ lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
@@ -133,3 +133,13 @@
             if thread is not None:
                 command += " " + str(thread.GetIndexID())
             self.expect(command, error=error, substrs=substrs)
+
+    def traceLoad(self, traceDescriptionFilePath="trace.json", error=False, substrs=None):
+        if self.USE_SB_API:
+            traceDescriptionFile = lldb.SBFileSpec(traceDescriptionFilePath, True)
+            loadTraceError = lldb.SBError()
+            _trace = self.dbg.LoadTraceFromFile(loadTraceError, traceDescriptionFile)
+            self.assertSBError(loadTraceError, error)
+        else:
+            command = f"trace load -v {traceDescriptionFilePath}"
+            self.expect(command, error=error, substrs=substrs)
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -137,6 +137,23 @@
   static llvm::Expected<llvm::StringRef>
   FindPluginSchema(llvm::StringRef plugin_name);
 
+  /// Load a trace from a trace description file and create Targets,
+  /// Processes and Threads based on the contents of such file.
+  ///
+  /// \param[in] debugger
+  ///     The debugger instance where new Targets will be created as part of the
+  ///     JSON data parsing.
+  ///
+  /// \param[in] trace_description_file
+  ///   The file containing the necessary information to load the trace.
+  ///
+  /// \return
+  ///     A \a TraceSP instance, or an \a llvm::Error if loading the trace
+  ///     fails.
+  static llvm::Expected<lldb::TraceSP>
+  LoadPostMortemTraceFromFile(Debugger &debugger,
+                              const FileSpec &trace_description_file);
+
   /// Get the command handle for the "process trace start" command.
   virtual lldb::CommandObjectSP
   GetProcessTraceStartCommand(CommandInterpreter &interpreter) = 0;
Index: lldb/include/lldb/API/SBTrace.h
===================================================================
--- lldb/include/lldb/API/SBTrace.h
+++ lldb/include/lldb/API/SBTrace.h
@@ -12,8 +12,6 @@
 #include "lldb/API/SBDefines.h"
 #include "lldb/API/SBError.h"
 
-class TraceImpl;
-
 namespace lldb {
 
 class LLDB_API SBTrace {
@@ -23,6 +21,10 @@
 
   SBTrace(const lldb::TraceSP &trace_sp);
 
+  /// See SBDebugger::LoadTraceFromFile.
+  static SBTrace LoadTraceFromFile(SBError &error, SBDebugger &debugger,
+                                   const SBFileSpec &trace_description_file);
+
   /// \return
   ///     A description of the parameters to use for the \a SBTrace::Start
   ///     method, or \b null if the object is invalid.
Index: lldb/include/lldb/API/SBFileSpec.h
===================================================================
--- lldb/include/lldb/API/SBFileSpec.h
+++ lldb/include/lldb/API/SBFileSpec.h
@@ -74,6 +74,7 @@
   friend class SBSourceManager;
   friend class SBTarget;
   friend class SBThread;
+  friend class SBTrace;
 
   SBFileSpec(const lldb_private::FileSpec &fspec);
 
Index: lldb/include/lldb/API/SBDebugger.h
===================================================================
--- lldb/include/lldb/API/SBDebugger.h
+++ lldb/include/lldb/API/SBDebugger.h
@@ -391,6 +391,17 @@
 
   SBError RunREPL(lldb::LanguageType language, const char *repl_options);
 
+  /// Load a trace from a trace description file and create Targets,
+  /// Processes and Threads based on the contents of such file.
+  ///
+  /// \param[out] error
+  ///   An error if the trace could not be created.
+  ///
+  /// \param[in] trace_description_file
+  ///   The file containing the necessary information to load the trace.
+  SBTrace LoadTraceFromFile(SBError &error,
+                            const SBFileSpec &trace_description_file);
+
 private:
   friend class SBCommandInterpreter;
   friend class SBInputReader;
@@ -398,6 +409,7 @@
   friend class SBProcess;
   friend class SBSourceManager;
   friend class SBTarget;
+  friend class SBTrace;
 
   lldb::SBTarget FindTargetWithLLDBProcess(const lldb::ProcessSP &processSP);
 
Index: lldb/bindings/interface/SBDebugger.i
===================================================================
--- lldb/bindings/interface/SBDebugger.i
+++ lldb/bindings/interface/SBDebugger.i
@@ -542,6 +542,8 @@
     lldb::SBError
     RunREPL (lldb::LanguageType language, const char *repl_options);
 
+    SBTrace LoadTraceFromFile(SBError &error, const SBFileSpec &trace_description_file);
+
 #ifdef SWIGPYTHON
     %pythoncode%{
     def __iter__(self):
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to