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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits