wallace created this revision.
wallace added a reviewer: clayborg.
Herald added a subscriber: dang.
wallace requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

This adds a basic SB API for creating and stopping traces.
Note: This doesn't add any APIs for inspecting individual instructions. That'd 
be a more complicated change and it might be better to enhande the dump 
functionality to output the data in binary format. I'll leave that for a later 
diff.

This also enhances the existing tests so that they test the same flow using 
both the command interface and the SB API.

I also did some cleanup of legacy code.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D103500

Files:
  lldb/bindings/interface/SBStructuredData.i
  lldb/bindings/interface/SBTarget.i
  lldb/bindings/interface/SBTrace.i
  lldb/bindings/interface/SBTraceOptions.i
  lldb/docs/design/overview.rst
  lldb/include/lldb/API/SBProcess.h
  lldb/include/lldb/API/SBStructuredData.h
  lldb/include/lldb/API/SBTarget.h
  lldb/include/lldb/API/SBThread.h
  lldb/include/lldb/API/SBTrace.h
  lldb/include/lldb/API/SBTraceOptions.h
  lldb/include/lldb/Target/Process.h
  lldb/include/lldb/Target/Trace.h
  lldb/include/lldb/Utility/TraceGDBRemotePackets.h
  lldb/include/lldb/Utility/TraceOptions.h
  lldb/include/lldb/lldb-forward.h
  lldb/packages/Python/lldbsuite/test/dotest.py
  lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
  lldb/source/API/SBProcess.cpp
  lldb/source/API/SBReproducer.cpp
  lldb/source/API/SBStructuredData.cpp
  lldb/source/API/SBTarget.cpp
  lldb/source/API/SBTrace.cpp
  lldb/source/API/SBTraceOptions.cpp
  lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
  lldb/source/Plugins/Trace/intel-pt/constants.h
  lldb/source/Target/Trace.cpp
  lldb/test/API/commands/trace/TestTraceDumpInstructions.py
  lldb/test/API/commands/trace/TestTraceLoad.py
  lldb/test/API/commands/trace/TestTraceSchema.py
  lldb/test/API/commands/trace/TestTraceStartStop.py
  
lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
  lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp

Index: lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
===================================================================
--- lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -12,7 +12,6 @@
 #include "lldb/Target/MemoryRegionInfo.h"
 #include "lldb/Utility/DataBuffer.h"
 #include "lldb/Utility/StructuredData.h"
-#include "lldb/Utility/TraceOptions.h"
 #include "lldb/lldb-enumerations.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/Testing/Support/Error.h"
Index: lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
===================================================================
--- lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
+++ lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
@@ -1,53 +1,49 @@
 import lldb
+from intelpt_testcase import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 
-ADDRESS_REGEX = '0x[0-9a-fA-F]*'
-
-class TestTraceStartStopMultipleThreads(TestBase):
+class TestTraceStartStopMultipleThreads(TraceIntelPTTestCaseBase):
 
     mydir = TestBase.compute_mydir(__file__)
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def setUp(self):
-        TestBase.setUp(self)
-        if 'intel-pt' not in configuration.enabled_plugins:
-            self.skipTest("The intel-pt test plugin is not enabled")
 
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
+    @testSBAPIAndCommands
     def testStartMultipleLiveThreads(self):
         self.build()
-        target = self.createTestTarget()
+        exe = self.getBuildArtifact("a.out")
+
+        self.dbg.CreateTarget(exe)
 
         self.expect("b main")
         self.expect("b 6")
         self.expect("b 11")
 
         self.expect("r")
-        self.expect("proce trace start")
-
+        self.traceStartProcess()
 
-        # We'll see here the first thread
         self.expect("continue")
         self.expect("thread trace dump instructions", substrs=['main.cpp:9'])
-        
+
         # We'll see here the second thread
         self.expect("continue")
         self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
 
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
+    @testSBAPIAndCommands
     def testStartMultipleLiveThreadsWithStops(self):
         self.build()
-        target = self.createTestTarget()
+        exe = self.getBuildArtifact("a.out")
+
+        self.dbg.CreateTarget(exe)
 
         self.expect("b main")
         self.expect("b 6")
         self.expect("b 11")
 
         self.expect("r")
-        self.expect("process trace start")
-
+        self.traceStartProcess()
 
         # We'll see here the first thread
         self.expect("continue")
@@ -61,7 +57,7 @@
 
         # The trace is still in memory
         self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
-        
+
         # We'll stop at the next breakpoint, thread 2 will be still alive, but not traced. Thread 3 will be traced
         self.expect("continue")
         self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
@@ -70,17 +66,19 @@
         self.expect("thread trace dump instructions 2", substrs=['not traced'])
 
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
+    @testSBAPIAndCommands
     def testStartMultipleLiveThreadsWithStops(self):
         self.build()
         exe = self.getBuildArtifact("a.out")
-        target = self.dbg.CreateTarget(exe)
+        self.dbg.CreateTarget(exe)
 
         self.expect("b main")
         self.expect("b 6")
         self.expect("b 11")
 
         self.expect("r")
-        self.expect("process trace start")
+
+        self.traceStartProcess()
 
         # We'll see here the first thread
         self.expect("continue")
@@ -94,7 +92,7 @@
 
         # The trace is still in memory
         self.expect("thread trace dump instructions 2", substrs=['main.cpp:9'])
-        
+
         # We'll stop at the next breakpoint in thread 3, thread 2 and 3 will be alive, but only 3 traced.
         self.expect("continue")
         self.expect("thread trace dump instructions", substrs=['main.cpp:4'])
@@ -127,7 +125,7 @@
 
         # The trace is still in memory
         self.expect("thread trace dump instructions 2", substrs=['main.cpp:11'])
-        
+
         # We'll stop at the next breakpoint in thread 3, and nothing should be traced
         self.expect("continue")
         self.expect("thread trace dump instructions 3", substrs=['not traced'])
@@ -135,16 +133,22 @@
         self.expect("thread trace dump instructions 2", substrs=['not traced'])
 
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
+    @testSBAPIAndCommands
     def testStartMultipleLiveThreadsWithSmallTotalLimit(self):
         self.build()
         exe = self.getBuildArtifact("a.out")
-        target = self.dbg.CreateTarget(exe)
+
+        self.dbg.CreateTarget(exe)
 
         self.expect("b main")
         self.expect("r")
+
         # trace the entire process with enough total size for 1 thread trace
-        self.expect("process trace start -l 5000")
+        self.traceStartProcess(processBufferSizeLimit=5000)
+
         # we get the stop event when trace 2 appears and can't be traced
         self.expect("c", substrs=['Thread', "can't be traced"])
         # we get the stop event when trace 3 appears and can't be traced
         self.expect("c", substrs=['Thread', "can't be traced"])
+
+        self.traceStopProcess()
Index: lldb/test/API/commands/trace/TestTraceStartStop.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceStartStop.py
+++ lldb/test/API/commands/trace/TestTraceStartStop.py
@@ -1,52 +1,52 @@
 import lldb
+from intelpt_testcase import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 
-ADDRESS_REGEX = '0x[0-9a-fA-F]*'
-
-class TestTraceStartStop(TestBase):
+class TestTraceStartStop(TraceIntelPTTestCaseBase):
 
     mydir = TestBase.compute_mydir(__file__)
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def setUp(self):
-        TestBase.setUp(self)
-        if 'intel-pt' not in configuration.enabled_plugins:
-            self.skipTest("The intel-pt test plugin is not enabled")
 
     def expectGenericHelpMessageForStartCommand(self):
         self.expect("help thread trace start",
             substrs=["Syntax: thread trace start [<trace-options>]"])
 
+    @testSBAPIAndCommands
     def testStartStopSessionFileThreads(self):
         # it should fail for processes from json session files
         self.expect("trace load -v " + os.path.join(self.getSourceDir(), "intelpt-trace", "trace.json"))
-        self.expect("thread trace start", error=True,
-            substrs=["error: Process must be alive"])
 
         # the help command should be the generic one, as it's not a live process
         self.expectGenericHelpMessageForStartCommand()
 
-        self.expect("thread trace stop", error=True)
+        self.traceStartThread(error=True)
 
-    def testStartWithNoProcess(self):
-        self.expect("thread trace start", error=True, 
-            substrs=["error: Process not available."])
+        self.traceStopThread(error=True)
 
+    @testSBAPIAndCommands
+    def testStartWithNoProcess(self):
+        self.traceStartThread(error=True)
 
+    @testSBAPIAndCommands
     def testStartSessionWithWrongSize(self):
         self.expect("file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
         self.expect("b main")
         self.expect("r")
-        self.expect("thread trace start -s 2000", error=True, 
+
+        self.traceStartThread(
+            error=True, threadBufferSize=2000,
             substrs=["The trace buffer size must be a power of 2", "It was 2000"])
-        self.expect("thread trace start -s 5000", error=True,
+
+        self.traceStartThread(
+            error=True, threadBufferSize=5000,
             substrs=["The trace buffer size must be a power of 2", "It was 5000"])
-        self.expect("thread trace start -s 0", error=True,
+
+        self.traceStartThread(
+            error=True, threadBufferSize=0,
             substrs=["The trace buffer size must be a power of 2", "It was 0"])
-        self.expect("thread trace start -s 1048576")
-        
+
+        self.traceStartThread(threadBufferSize=1048576)
 
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
     def testStartStopLiveThreads(self):
@@ -79,21 +79,21 @@
 
         # We start tracing with a small buffer size
         self.expect("thread trace start 1 --size 4096")
-        
+
         # We fail if we try to trace again
-        self.expect("thread trace start", error=True, 
+        self.expect("thread trace start", error=True,
             substrs=["error: Thread ", "already traced"])
 
         # We can reconstruct the single instruction executed in the first line
         self.expect("n")
-        self.expect("thread trace dump instructions", 
+        self.expect("thread trace dump instructions",
             patterns=[f'''thread #1: tid = .*, total instructions = 1
   a.out`main \+ 4 at main.cpp:2
     \[0\] {ADDRESS_REGEX}    movl'''])
 
         # We can reconstruct the instructions up to the second line
         self.expect("n")
-        self.expect("thread trace dump instructions", 
+        self.expect("thread trace dump instructions",
             patterns=[f'''thread #1: tid = .*, total instructions = 5
   a.out`main \+ 4 at main.cpp:2
     \[0\] {ADDRESS_REGEX}    movl .*
@@ -114,7 +114,7 @@
         # thread
         self.expect("thread trace start")
         self.expect("n")
-        self.expect("thread trace dump instructions", 
+        self.expect("thread trace dump instructions",
             patterns=[f'''thread #1: tid = .*, total instructions = 1
   a.out`main \+ 20 at main.cpp:5
     \[0\] {ADDRESS_REGEX}    xorl'''])
Index: lldb/test/API/commands/trace/TestTraceSchema.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceSchema.py
+++ lldb/test/API/commands/trace/TestTraceSchema.py
@@ -1,18 +1,12 @@
 import lldb
+from intelpt_testcase import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 
-class TestTraceLoad(TestBase):
+class TestTraceLoad(TraceIntelPTTestCaseBase):
 
     mydir = TestBase.compute_mydir(__file__)
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def setUp(self):
-        TestBase.setUp(self)
-        if 'intel-pt' not in configuration.enabled_plugins:
-            self.skipTest("The intel-pt test plugin is not enabled")
-
 
     def testSchema(self):
         self.expect("trace schema intel-pt", substrs=["trace", "triple", "threads", "traceFile"])
Index: lldb/test/API/commands/trace/TestTraceLoad.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceLoad.py
+++ lldb/test/API/commands/trace/TestTraceLoad.py
@@ -1,19 +1,14 @@
 import lldb
+from intelpt_testcase import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 
-class TestTraceLoad(TestBase):
+class TestTraceLoad(TraceIntelPTTestCaseBase):
 
     mydir = TestBase.compute_mydir(__file__)
     NO_DEBUG_INFO_TESTCASE = True
 
-    def setUp(self):
-        TestBase.setUp(self)
-        if 'intel-pt' not in configuration.enabled_plugins:
-            self.skipTest("The intel-pt test plugin is not enabled")
-
-
     def testLoadTrace(self):
         src_dir = self.getSourceDir()
         trace_definition_file = os.path.join(src_dir, "intelpt-trace", "trace.json")
Index: lldb/test/API/commands/trace/TestTraceDumpInstructions.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceDumpInstructions.py
+++ lldb/test/API/commands/trace/TestTraceDumpInstructions.py
@@ -1,17 +1,12 @@
 import lldb
+from intelpt_testcase import *
 from lldbsuite.test.lldbtest import *
 from lldbsuite.test import lldbutil
 from lldbsuite.test.decorators import *
 
-class TestTraceDumpInstructions(TestBase):
+class TestTraceDumpInstructions(TraceIntelPTTestCaseBase):
 
     mydir = TestBase.compute_mydir(__file__)
-    NO_DEBUG_INFO_TESTCASE = True
-
-    def setUp(self):
-        TestBase.setUp(self)
-        if 'intel-pt' not in configuration.enabled_plugins:
-            self.skipTest("The intel-pt test plugin is not enabled")
 
     def testErrorMessages(self):
         # We first check the output when there are no targets
@@ -20,7 +15,7 @@
             error=True)
 
         # We now check the output when there's a non-running target
-        self.expect("target create " + 
+        self.expect("target create " +
             os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
 
         self.expect("thread trace dump instructions",
@@ -42,34 +37,34 @@
 
         self.expect("thread trace dump instructions --raw",
             substrs=['''thread #1: tid = 3842849, total instructions = 21
-    [ 1] 0x0000000000400518    
-    [ 2] 0x000000000040051f    
-    [ 3] 0x0000000000400529    
-    [ 4] 0x000000000040052d    
-    [ 5] 0x0000000000400521    
-    [ 6] 0x0000000000400525    
-    [ 7] 0x0000000000400529    
-    [ 8] 0x000000000040052d    
-    [ 9] 0x0000000000400521    
-    [10] 0x0000000000400525    
-    [11] 0x0000000000400529    
-    [12] 0x000000000040052d    
-    [13] 0x0000000000400521    
-    [14] 0x0000000000400525    
-    [15] 0x0000000000400529    
-    [16] 0x000000000040052d    
-    [17] 0x0000000000400521    
-    [18] 0x0000000000400525    
-    [19] 0x0000000000400529    
+    [ 1] 0x0000000000400518
+    [ 2] 0x000000000040051f
+    [ 3] 0x0000000000400529
+    [ 4] 0x000000000040052d
+    [ 5] 0x0000000000400521
+    [ 6] 0x0000000000400525
+    [ 7] 0x0000000000400529
+    [ 8] 0x000000000040052d
+    [ 9] 0x0000000000400521
+    [10] 0x0000000000400525
+    [11] 0x0000000000400529
+    [12] 0x000000000040052d
+    [13] 0x0000000000400521
+    [14] 0x0000000000400525
+    [15] 0x0000000000400529
+    [16] 0x000000000040052d
+    [17] 0x0000000000400521
+    [18] 0x0000000000400525
+    [19] 0x0000000000400529
     [20] 0x000000000040052d'''])
 
         # We check if we can pass count and position
         self.expect("thread trace dump instructions --count 5 --position 10 --raw",
             substrs=['''thread #1: tid = 3842849, total instructions = 21
-    [ 6] 0x0000000000400525    
-    [ 7] 0x0000000000400529    
-    [ 8] 0x000000000040052d    
-    [ 9] 0x0000000000400521    
+    [ 6] 0x0000000000400525
+    [ 7] 0x0000000000400529
+    [ 8] 0x000000000040052d
+    [ 9] 0x0000000000400521
     [10] 0x0000000000400525'''])
 
         # We check if we can access the thread by index id
@@ -83,7 +78,7 @@
 
     def testDumpFullInstructionsWithMultipleThreads(self):
         # We load a trace with two threads
-        self.expect("trace load -v " + 
+        self.expect("trace load -v " +
             os.path.join(self.getSourceDir(), "intelpt-trace", "trace_2threads.json"))
 
         # We print the instructions of two threads simultaneously
@@ -181,7 +176,7 @@
         # - Then, the dump continues in the next synchronization point showing
         #   a call to an inlined function, which is displayed as [inlined].
         # - Finally, a call to libfoo is performed, which invokes libbar inside.
-        # 
+        #
         # Whenever there's a line or symbol change, including the inline case, a
         # line is printed showing the symbol context change.
         #
@@ -241,7 +236,7 @@
   libbar.so`bar() + 22 at bar.cpp:4
     [32] 0x00007ffff79d76a6    movl   -0x4(%rbp), %eax
     [33] 0x00007ffff79d76a9    popq   %rbp
-    [34] 0x00007ffff79d76aa    retq   
+    [34] 0x00007ffff79d76aa    retq
   libfoo.so`foo() + 13 at foo.cpp:4
     [35] 0x00007ffff7bd96ed    movl   %eax, -0x4(%rbp)
   libfoo.so`foo() + 16 at foo.cpp:5
@@ -252,7 +247,7 @@
     [39] 0x00007ffff7bd96fb    movl   -0x4(%rbp), %eax
     [40] 0x00007ffff7bd96fe    addq   $0x10, %rsp
     [41] 0x00007ffff7bd9702    popq   %rbp
-    [42] 0x00007ffff7bd9703    retq   
+    [42] 0x00007ffff7bd9703    retq
   a.out`main + 68 at main.cpp:16
     [43] 0x00000000004006a4    movl   -0xc(%rbp), %ecx
     [44] 0x00000000004006a7    addl   %eax, %ecx
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -291,6 +291,8 @@
 static void DumpInstructionDisassembly(Stream &s, InstructionSymbolInfo &insn) {
   if (!insn.instruction)
     return;
+
+  s.Printf("    ");
   insn.instruction->Dump(&s, /*show_address*/ false, /*show_bytes*/ false,
                          /*max_opcode_byte_size*/ 0, &insn.exe_ctx, &insn.sc,
                          /*prev_sym_ctx*/ nullptr,
@@ -341,7 +343,7 @@
             DumpInstructionSymbolContext(s, prev_insn, *insn);
 
           printInstructionIndex(index);
-          s.Printf("0x%016" PRIx64 "    ", insn->load_address);
+          s.Printf("0x%016" PRIx64, insn->load_address);
 
           if (!raw)
             DumpInstructionDisassembly(s, *insn);
Index: lldb/source/Plugins/Trace/intel-pt/constants.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Trace/intel-pt/constants.h
@@ -0,0 +1,21 @@
+//===-- constants.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+const size_t kThreadBufferSize = 4 * 1024;              // 4KB
+const size_t kProcessBufferSizeLimit = 5 * 1024 * 1024; // 500MB
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_CONSTANTS_H
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
@@ -13,7 +13,6 @@
 #include "lldb/Target/Target.h"
 #include "lldb/Target/ThreadList.h"
 #include "lldb/Target/ThreadPostMortemTrace.h"
-#include "lldb/Utility/TraceOptions.h"
 
 using namespace lldb;
 using namespace lldb_private;
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
@@ -23,6 +23,7 @@
          "the sum of the sizes of all thread traces of this process, excluding "
          "the ones created with the \"thread trace start\" command. "
          "Whenever a thread is attempted to be traced due to this command and "
-         "the limit would be reached, the process is stopped with a \"tracing\" "
-         "reason, so that the user can retrace the process if needed.">;
+         "the limit would be reached, the process is stopped with a "
+         "\"processor trace\" reason, so that the user can retrace the process "
+         "if needed. Defaults to 500MB.">;
 }
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -96,9 +96,14 @@
   /// \return
   ///     \a llvm::Error::success if the operation was successful, or
   ///     \a llvm::Error otherwise.
-  llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit);
+  llvm::Error StartProcess(size_t thread_buffer_size,
+                           size_t total_buffer_size_limit);
 
-  /// Start tracing a live threads.
+  /// \copydoc Trace::StartProcess
+  llvm::Error StartProcess(StructuredData::ObjectSP configuration =
+                               StructuredData::ObjectSP()) override;
+
+  /// Start tracing live threads.
   ///
   /// \param[in] tids
   ///     Threads to trace.
@@ -109,8 +114,13 @@
   /// \return
   ///     \a llvm::Error::success if the operation was successful, or
   ///     \a llvm::Error otherwise.
-  llvm::Error Start(const std::vector<lldb::tid_t> &tids,
-                    size_t thread_buffer_size);
+  llvm::Error StartThreads(const std::vector<lldb::tid_t> &tids,
+                           size_t thread_buffer_size);
+
+  /// \copydoc Trace::StartProcess
+  llvm::Error StartThreads(const std::vector<lldb::tid_t> &tids,
+                           StructuredData::ObjectSP configuration =
+                               StructuredData::ObjectSP()) override;
 
   /// Get the thread buffer content for a live thread
   llvm::Expected<std::vector<uint8_t>> GetLiveThreadBuffer(lldb::tid_t tid);
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -10,6 +10,7 @@
 
 #include "CommandObjectTraceStartIntelPT.h"
 #include "TraceIntelPTSessionFileParser.h"
+#include "constants.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
@@ -209,11 +210,12 @@
 }
 
 bool TraceIntelPT::IsTraced(const Thread &thread) {
+  RefreshLiveProcessState();
   return m_thread_decoders.count(&thread);
 }
 
-Error TraceIntelPT::Start(size_t thread_buffer_size,
-                          size_t total_buffer_size_limit) {
+Error TraceIntelPT::StartProcess(size_t thread_buffer_size,
+                                 size_t total_buffer_size_limit) {
   TraceIntelPTStartRequest request;
   request.threadBufferSize = thread_buffer_size;
   request.processBufferSizeLimit = total_buffer_size_limit;
@@ -221,8 +223,26 @@
   return Trace::Start(toJSON(request));
 }
 
-llvm::Error TraceIntelPT::Start(const std::vector<lldb::tid_t> &tids,
-                                size_t thread_buffer_size) {
+Error TraceIntelPT::StartProcess(StructuredData::ObjectSP configuration) {
+  size_t thread_buffer_size = kThreadBufferSize;
+  size_t process_buffer_size_limit = kProcessBufferSizeLimit;
+
+  if (configuration) {
+    if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
+      dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+      dict->GetValueForKeyAsInteger("processBufferSizeLimit",
+                                    process_buffer_size_limit);
+    } else {
+      return createStringError(inconvertibleErrorCode(),
+                               "configuration object is not a dictionary");
+    }
+  }
+
+  return StartProcess(thread_buffer_size, process_buffer_size_limit);
+}
+
+llvm::Error TraceIntelPT::StartThreads(const std::vector<lldb::tid_t> &tids,
+                                       size_t thread_buffer_size) {
   TraceIntelPTStartRequest request;
   request.threadBufferSize = thread_buffer_size;
   request.type = GetPluginName().AsCString();
@@ -232,6 +252,22 @@
   return Trace::Start(toJSON(request));
 }
 
+Error TraceIntelPT::StartThreads(const std::vector<lldb::tid_t> &tids,
+                                 StructuredData::ObjectSP configuration) {
+  size_t thread_buffer_size = kThreadBufferSize;
+
+  if (configuration) {
+    if (StructuredData::Dictionary *dict = configuration->GetAsDictionary()) {
+      dict->GetValueForKeyAsInteger("threadBufferSize", thread_buffer_size);
+    } else {
+      return createStringError(inconvertibleErrorCode(),
+                               "configuration object is not a dictionary");
+    }
+  }
+
+  return StartThreads(tids, thread_buffer_size);
+}
+
 Expected<std::vector<uint8_t>>
 TraceIntelPT::GetLiveThreadBuffer(lldb::tid_t tid) {
   return Trace::GetLiveThreadBinaryData(tid, "threadTraceBuffer");
Index: lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
@@ -9,6 +9,7 @@
 #include "CommandObjectTraceStartIntelPT.h"
 
 #include "TraceIntelPT.h"
+#include "constants.h"
 #include "lldb/Host/OptionParser.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Trace.h"
@@ -48,7 +49,7 @@
 
 void CommandObjectThreadTraceStartIntelPT::CommandOptions::
     OptionParsingStarting(ExecutionContext *execution_context) {
-  m_thread_buffer_size = 4 * 1024; // 4KB
+  m_thread_buffer_size = kThreadBufferSize;
 }
 
 llvm::ArrayRef<OptionDefinition>
@@ -59,7 +60,7 @@
 bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
     Args &command, CommandReturnObject &result,
     const std::vector<lldb::tid_t> &tids) {
-  if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size))
+  if (Error err = m_trace.StartThreads(tids, m_options.m_thread_buffer_size))
     result.SetError(toString(std::move(err)));
   else
     result.SetStatus(eReturnStatusSuccessFinishResult);
@@ -108,8 +109,8 @@
 
 void CommandObjectProcessTraceStartIntelPT::CommandOptions::
     OptionParsingStarting(ExecutionContext *execution_context) {
-  m_thread_buffer_size = 4 * 1024;               // 4KB
-  m_process_buffer_size_limit = 5 * 1024 * 1024; // 500MB
+  m_thread_buffer_size = kThreadBufferSize;
+  m_process_buffer_size_limit = kProcessBufferSizeLimit;
 }
 
 llvm::ArrayRef<OptionDefinition>
@@ -119,8 +120,8 @@
 
 bool CommandObjectProcessTraceStartIntelPT::DoExecute(
     Args &command, CommandReturnObject &result) {
-  if (Error err = m_trace.Start(m_options.m_thread_buffer_size,
-                                m_options.m_process_buffer_size_limit))
+  if (Error err = m_trace.StartProcess(m_options.m_thread_buffer_size,
+                                       m_options.m_process_buffer_size_limit))
     result.SetError(toString(std::move(err)));
   else
     result.SetStatus(eReturnStatusSuccessFinishResult);
Index: lldb/source/API/SBTraceOptions.cpp
===================================================================
--- lldb/source/API/SBTraceOptions.cpp
+++ lldb/source/API/SBTraceOptions.cpp
@@ -7,12 +7,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "lldb/API/SBTraceOptions.h"
-#include "SBReproducerPrivate.h"
 #include "lldb/API/SBError.h"
 #include "lldb/API/SBStructuredData.h"
-#include "lldb/Core/StructuredDataImpl.h"
-#include "lldb/Utility/Log.h"
-#include "lldb/Utility/TraceOptions.h"
 
 #include <memory>
 
@@ -20,140 +16,46 @@
 using namespace lldb_private;
 
 SBTraceOptions::SBTraceOptions() {
-  LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTraceOptions);
-
-  m_traceoptions_sp = std::make_shared<TraceOptions>();
 }
 
 lldb::TraceType SBTraceOptions::getType() const {
-  LLDB_RECORD_METHOD_CONST_NO_ARGS(lldb::TraceType, SBTraceOptions, getType);
-
-  if (m_traceoptions_sp)
-    return m_traceoptions_sp->getType();
   return lldb::TraceType::eTraceTypeNone;
 }
 
 uint64_t SBTraceOptions::getTraceBufferSize() const {
-  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint64_t, SBTraceOptions,
-                                   getTraceBufferSize);
-
-  if (m_traceoptions_sp)
-    return m_traceoptions_sp->getTraceBufferSize();
   return 0;
 }
 
 lldb::SBStructuredData SBTraceOptions::getTraceParams(lldb::SBError &error) {
-  LLDB_RECORD_METHOD(lldb::SBStructuredData, SBTraceOptions, getTraceParams,
-                     (lldb::SBError &), error);
-
-  error.Clear();
-  const lldb_private::StructuredData::DictionarySP dict_obj =
-      m_traceoptions_sp->getTraceParams();
-  lldb::SBStructuredData structData;
-  if (dict_obj && structData.m_impl_up)
-    structData.m_impl_up->SetObjectSP(dict_obj->shared_from_this());
-  else
-    error.SetErrorString("Empty trace params");
-  return LLDB_RECORD_RESULT(structData);
+  error.SetErrorString("deprecated");
+  return lldb::SBStructuredData();
 }
 
 uint64_t SBTraceOptions::getMetaDataBufferSize() const {
-  LLDB_RECORD_METHOD_CONST_NO_ARGS(uint64_t, SBTraceOptions,
-                                   getMetaDataBufferSize);
-
-  if (m_traceoptions_sp)
-    return m_traceoptions_sp->getTraceBufferSize();
   return 0;
 }
 
 void SBTraceOptions::setTraceParams(lldb::SBStructuredData &params) {
-  LLDB_RECORD_METHOD(void, SBTraceOptions, setTraceParams,
-                     (lldb::SBStructuredData &), params);
-
-  if (m_traceoptions_sp && params.m_impl_up) {
-    StructuredData::ObjectSP obj_sp = params.m_impl_up->GetObjectSP();
-    if (obj_sp && obj_sp->GetAsDictionary() != nullptr)
-      m_traceoptions_sp->setTraceParams(
-          std::static_pointer_cast<StructuredData::Dictionary>(obj_sp));
-  }
   return;
 }
 
 void SBTraceOptions::setType(lldb::TraceType type) {
-  LLDB_RECORD_METHOD(void, SBTraceOptions, setType, (lldb::TraceType), type);
-
-  if (m_traceoptions_sp)
-    m_traceoptions_sp->setType(type);
 }
 
 void SBTraceOptions::setTraceBufferSize(uint64_t size) {
-  LLDB_RECORD_METHOD(void, SBTraceOptions, setTraceBufferSize, (uint64_t),
-                     size);
-
-  if (m_traceoptions_sp)
-    m_traceoptions_sp->setTraceBufferSize(size);
 }
 
 void SBTraceOptions::setMetaDataBufferSize(uint64_t size) {
-  LLDB_RECORD_METHOD(void, SBTraceOptions, setMetaDataBufferSize, (uint64_t),
-                     size);
-
-  if (m_traceoptions_sp)
-    m_traceoptions_sp->setMetaDataBufferSize(size);
 }
 
-bool SBTraceOptions::IsValid() {
-  LLDB_RECORD_METHOD_NO_ARGS(bool, SBTraceOptions, IsValid);
-  return this->operator bool();
-}
+bool SBTraceOptions::IsValid() { return false; }
 SBTraceOptions::operator bool() const {
-  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTraceOptions, operator bool);
-
-  if (m_traceoptions_sp)
-    return true;
   return false;
 }
 
 void SBTraceOptions::setThreadID(lldb::tid_t thread_id) {
-  LLDB_RECORD_METHOD(void, SBTraceOptions, setThreadID, (lldb::tid_t),
-                     thread_id);
-
-  if (m_traceoptions_sp)
-    m_traceoptions_sp->setThreadID(thread_id);
 }
 
 lldb::tid_t SBTraceOptions::getThreadID() {
-  LLDB_RECORD_METHOD_NO_ARGS(lldb::tid_t, SBTraceOptions, getThreadID);
-
-  if (m_traceoptions_sp)
-    return m_traceoptions_sp->getThreadID();
   return LLDB_INVALID_THREAD_ID;
 }
-
-namespace lldb_private {
-namespace repro {
-
-template <>
-void RegisterMethods<SBTraceOptions>(Registry &R) {
-  LLDB_REGISTER_CONSTRUCTOR(SBTraceOptions, ());
-  LLDB_REGISTER_METHOD_CONST(lldb::TraceType, SBTraceOptions, getType, ());
-  LLDB_REGISTER_METHOD_CONST(uint64_t, SBTraceOptions, getTraceBufferSize,
-                             ());
-  LLDB_REGISTER_METHOD(lldb::SBStructuredData, SBTraceOptions, getTraceParams,
-                       (lldb::SBError &));
-  LLDB_REGISTER_METHOD_CONST(uint64_t, SBTraceOptions, getMetaDataBufferSize,
-                             ());
-  LLDB_REGISTER_METHOD(void, SBTraceOptions, setTraceParams,
-                       (lldb::SBStructuredData &));
-  LLDB_REGISTER_METHOD(void, SBTraceOptions, setType, (lldb::TraceType));
-  LLDB_REGISTER_METHOD(void, SBTraceOptions, setTraceBufferSize, (uint64_t));
-  LLDB_REGISTER_METHOD(void, SBTraceOptions, setMetaDataBufferSize,
-                       (uint64_t));
-  LLDB_REGISTER_METHOD(bool, SBTraceOptions, IsValid, ());
-  LLDB_REGISTER_METHOD_CONST(bool, SBTraceOptions, operator bool, ());
-  LLDB_REGISTER_METHOD(void, SBTraceOptions, setThreadID, (lldb::tid_t));
-  LLDB_REGISTER_METHOD(lldb::tid_t, SBTraceOptions, getThreadID, ());
-}
-
-}
-}
Index: lldb/source/API/SBTrace.cpp
===================================================================
--- lldb/source/API/SBTrace.cpp
+++ lldb/source/API/SBTrace.cpp
@@ -9,125 +9,142 @@
 #include "SBReproducerPrivate.h"
 #include "lldb/Target/Process.h"
 
+#include "lldb/API/SBStructuredData.h"
+#include "lldb/API/SBThread.h"
 #include "lldb/API/SBTrace.h"
 #include "lldb/API/SBTraceOptions.h"
 
+#include "lldb/Core/StructuredDataImpl.h"
+
 #include <memory>
 
 using namespace lldb;
 using namespace lldb_private;
 
-class TraceImpl {
-public:
-  lldb::user_id_t uid;
-};
+SBTrace::SBTrace() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTrace); }
 
-lldb::ProcessSP SBTrace::GetSP() const { return m_opaque_wp.lock(); }
+SBTrace::SBTrace(const lldb::TraceSP &trace_sp) : m_opaque_sp(trace_sp) {
+  LLDB_RECORD_CONSTRUCTOR(SBTrace, (const lldb::TraceSP &), trace_sp);
+}
 
-size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size,
-                             size_t offset, lldb::tid_t thread_id) {
-  LLDB_RECORD_DUMMY(size_t, SBTrace, GetTraceData,
-                    (lldb::SBError &, void *, size_t, size_t, lldb::tid_t),
-                    error, buf, size, offset, thread_id);
+SBError SBTrace::StartProcess() {
+  LLDB_RECORD_METHOD_NO_ARGS(SBError, SBTrace, StartProcess);
+  return LLDB_RECORD_RESULT(StartProcess(SBStructuredData()));
+}
 
-  ProcessSP process_sp(GetSP());
-  llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
-  error.Clear();
+SBError SBTrace::StartProcess(const SBStructuredData &configuration) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, StartProcess, (const SBStructuredData &),
+                     configuration);
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err = m_opaque_sp->StartProcess(
+               configuration.m_impl_up->GetObjectSP()))
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
+}
 
-  if (!process_sp) {
-    error.SetErrorString("invalid process");
-  } else {
-    error.SetError(
-        process_sp->GetData(GetTraceUID(), thread_id, buffer, offset));
-  }
-  return buffer.size();
+SBError SBTrace::StartThread(const SBThread &thread) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, StartThread, (const SBThread &), thread);
+  return LLDB_RECORD_RESULT(StartThread(thread, SBStructuredData()));
 }
 
-size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size,
-                            size_t offset, lldb::tid_t thread_id) {
-  LLDB_RECORD_DUMMY(size_t, SBTrace, GetMetaData,
-                    (lldb::SBError &, void *, size_t, size_t, lldb::tid_t),
-                    error, buf, size, offset, thread_id);
+SBError SBTrace::StartThread(const SBThread &thread,
+                             const SBStructuredData &configuration) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, StartThread,
+                     (const SBThread &, const SBStructuredData &), thread,
+                     configuration);
+
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err = m_opaque_sp->StartThreads(
+               {thread.GetThreadID()}, configuration.m_impl_up->GetObjectSP()))
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
+}
 
-  ProcessSP process_sp(GetSP());
-  llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
-  error.Clear();
+SBError SBTrace::StopProcess() {
+  LLDB_RECORD_METHOD_NO_ARGS(SBError, SBTrace, StopProcess);
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err = m_opaque_sp->StopProcess())
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
+}
 
-  if (!process_sp) {
-    error.SetErrorString("invalid process");
-  } else {
-    error.SetError(
-        process_sp->GetMetaData(GetTraceUID(), thread_id, buffer, offset));
-  }
-  return buffer.size();
+SBError SBTrace::StopThread(const SBThread &thread) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, StopThread, (const SBThread &), thread);
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err = m_opaque_sp->StopThreads({thread.GetThreadID()}))
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
 }
 
 void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
   LLDB_RECORD_METHOD(void, SBTrace, StopTrace, (lldb::SBError &, lldb::tid_t),
                      error, thread_id);
-
-  ProcessSP process_sp(GetSP());
   error.Clear();
-
-  if (!process_sp) {
-    error.SetErrorString("invalid process");
-    return;
-  }
-  error.SetError(process_sp->StopTrace(GetTraceUID(), thread_id));
+  if (thread_id == LLDB_INVALID_THREAD_ID)
+    error = StopProcess();
+  else
+    error.SetErrorString("error: unimplemented");
 }
 
-void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
-  error.SetErrorString("deprecated");
+bool SBTrace::IsValid() {
+  LLDB_RECORD_METHOD_NO_ARGS(bool, SBTrace, IsValid);
+  return LLDB_RECORD_RESULT(this->operator bool());
 }
 
-lldb::user_id_t SBTrace::GetTraceUID() {
-  LLDB_RECORD_METHOD_NO_ARGS(lldb::user_id_t, SBTrace, GetTraceUID);
-
-  if (m_trace_impl_sp)
-    return m_trace_impl_sp->uid;
-  return LLDB_INVALID_UID;
+SBTrace::operator bool() const {
+  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTrace, operator bool);
+  return LLDB_RECORD_RESULT((bool)m_opaque_sp);
 }
 
-void SBTrace::SetTraceUID(lldb::user_id_t uid) {
-  if (m_trace_impl_sp)
-    m_trace_impl_sp->uid = uid;
+/// Deprecated
+size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size,
+                             size_t offset, lldb::tid_t thread_id) {
+  LLDB_RECORD_DUMMY(size_t, SBTrace, GetTraceData,
+                    (lldb::SBError &, void *, size_t, size_t, lldb::tid_t),
+                    error, buf, size, offset, thread_id);
+  error.SetErrorString("error: deprecated");
+  return 0;
 }
 
-SBTrace::SBTrace() {
-  LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTrace);
-
-  m_trace_impl_sp = std::make_shared<TraceImpl>();
-  if (m_trace_impl_sp)
-    m_trace_impl_sp->uid = LLDB_INVALID_UID;
+/// Deprecated
+size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size,
+                            size_t offset, lldb::tid_t thread_id) {
+  error.SetErrorString("error: deprecated");
+  return 0;
 }
 
-void SBTrace::SetSP(const ProcessSP &process_sp) { m_opaque_wp = process_sp; }
-
-bool SBTrace::IsValid() {
-  LLDB_RECORD_METHOD_NO_ARGS(bool, SBTrace, IsValid);
-  return this->operator bool();
+/// Deprecated
+void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
+  error.SetErrorString("error: deprecated");
 }
-SBTrace::operator bool() const {
-  LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBTrace, operator bool);
 
-  if (!m_trace_impl_sp)
-    return false;
-  if (!GetSP())
-    return false;
-  return true;
-}
+/// Deprecated
+lldb::user_id_t SBTrace::GetTraceUID() { return LLDB_INVALID_UID; }
 
 namespace lldb_private {
 namespace repro {
 
 template <>
 void RegisterMethods<SBTrace>(Registry &R) {
+  LLDB_REGISTER_CONSTRUCTOR(SBTrace, ());
+  LLDB_REGISTER_CONSTRUCTOR(SBTrace, (const lldb::TraceSP &));
   LLDB_REGISTER_METHOD(void, SBTrace, StopTrace,
                        (lldb::SBError &, lldb::tid_t));
-  LLDB_REGISTER_METHOD(void, SBTrace, GetTraceConfig,
-                       (lldb::SBTraceOptions &, lldb::SBError &));
-  LLDB_REGISTER_METHOD(lldb::user_id_t, SBTrace, GetTraceUID, ());
-  LLDB_REGISTER_CONSTRUCTOR(SBTrace, ());
+  LLDB_REGISTER_METHOD(SBError, SBTrace, StartProcess,
+                       (const SBStructuredData &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, StartThread, (const SBThread &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, StartThread,
+                       (const SBThread &, const SBStructuredData &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, StopProcess, ());
+  LLDB_REGISTER_METHOD(SBError, SBTrace, StopThread, (const SBThread &));
   LLDB_REGISTER_METHOD(bool, SBTrace, IsValid, ());
   LLDB_REGISTER_METHOD_CONST(bool, SBTrace, operator bool, ());
 }
Index: lldb/source/API/SBTarget.cpp
===================================================================
--- lldb/source/API/SBTarget.cpp
+++ lldb/source/API/SBTarget.cpp
@@ -26,6 +26,7 @@
 #include "lldb/API/SBStringList.h"
 #include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBSymbolContextList.h"
+#include "lldb/API/SBTrace.h"
 #include "lldb/Breakpoint/BreakpointID.h"
 #include "lldb/Breakpoint/BreakpointIDList.h"
 #include "lldb/Breakpoint/BreakpointList.h"
@@ -2454,6 +2455,35 @@
   return LLDB_RECORD_RESULT(SBEnvironment());
 }
 
+lldb::SBTrace SBTarget::GetTrace() {
+  LLDB_RECORD_METHOD_NO_ARGS(lldb::SBTrace, SBTarget, GetTrace);
+  TargetSP target_sp(GetSP());
+
+  if (target_sp)
+    return LLDB_RECORD_RESULT(SBTrace(target_sp->GetTrace()));
+
+  return LLDB_RECORD_RESULT(SBTrace());
+}
+
+lldb::SBTrace SBTarget::GetTraceOrCreate(lldb::SBError &error) {
+  LLDB_RECORD_METHOD(lldb::SBTrace, SBTarget, GetTraceOrCreate,
+                     (lldb::SBError &), error);
+  TargetSP target_sp(GetSP());
+  error.Clear();
+
+  if (target_sp) {
+    if (llvm::Expected<lldb::TraceSP &> trace_sp =
+            target_sp->GetTraceOrCreate()) {
+      return LLDB_RECORD_RESULT(SBTrace(*trace_sp));
+    } else {
+      error.SetErrorString(llvm::toString(trace_sp.takeError()).c_str());
+    }
+  } else {
+    error.SetErrorString("missing target");
+  }
+  return LLDB_RECORD_RESULT(SBTrace());
+}
+
 namespace lldb_private {
 namespace repro {
 
@@ -2715,6 +2745,9 @@
                        GetInstructionsWithFlavor,
                        (lldb::addr_t, const char *, const void *, size_t));
   LLDB_REGISTER_METHOD(lldb::SBEnvironment, SBTarget, GetEnvironment, ());
+  LLDB_REGISTER_METHOD(lldb::SBTrace, SBTarget, GetTrace, ());
+  LLDB_REGISTER_METHOD(lldb::SBTrace, SBTarget, GetTraceOrCreate,
+                       (lldb::SBError &));
 }
 
 }
Index: lldb/source/API/SBStructuredData.cpp
===================================================================
--- lldb/source/API/SBStructuredData.cpp
+++ lldb/source/API/SBStructuredData.cpp
@@ -72,10 +72,19 @@
   return LLDB_RECORD_RESULT(error);
 }
 
+lldb::SBError SBStructuredData::SetFromJSON(const char *json) {
+  LLDB_RECORD_METHOD(lldb::SBError, SBStructuredData, SetFromJSON,
+                     (const char *), json);
+  lldb::SBStream s;
+  s.Print(json);
+  return LLDB_RECORD_RESULT(SetFromJSON(s));
+}
+
 bool SBStructuredData::IsValid() const {
   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStructuredData, IsValid);
   return this->operator bool();
 }
+
 SBStructuredData::operator bool() const {
   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBStructuredData, operator bool);
 
@@ -207,6 +216,8 @@
       SBStructuredData, operator=,(const lldb::SBStructuredData &));
   LLDB_REGISTER_METHOD(lldb::SBError, SBStructuredData, SetFromJSON,
                        (lldb::SBStream &));
+  LLDB_REGISTER_METHOD(lldb::SBError, SBStructuredData, SetFromJSON,
+                       (const char *));
   LLDB_REGISTER_METHOD_CONST(bool, SBStructuredData, IsValid, ());
   LLDB_REGISTER_METHOD_CONST(bool, SBStructuredData, operator bool, ());
   LLDB_REGISTER_METHOD(void, SBStructuredData, Clear, ());
Index: lldb/source/API/SBReproducer.cpp
===================================================================
--- lldb/source/API/SBReproducer.cpp
+++ lldb/source/API/SBReproducer.cpp
@@ -117,7 +117,6 @@
   RegisterMethods<SBThreadCollection>(R);
   RegisterMethods<SBThreadPlan>(R);
   RegisterMethods<SBTrace>(R);
-  RegisterMethods<SBTraceOptions>(R);
   RegisterMethods<SBType>(R);
   RegisterMethods<SBTypeCategory>(R);
   RegisterMethods<SBTypeEnumMember>(R);
Index: lldb/source/API/SBProcess.cpp
===================================================================
--- lldb/source/API/SBProcess.cpp
+++ lldb/source/API/SBProcess.cpp
@@ -316,20 +316,8 @@
                                     lldb::SBError &error) {
   LLDB_RECORD_METHOD(lldb::SBTrace, SBProcess, StartTrace,
                      (lldb::SBTraceOptions &, lldb::SBError &), options, error);
-
-  ProcessSP process_sp(GetSP());
-  error.Clear();
-  SBTrace trace_instance;
-  trace_instance.SetSP(process_sp);
-  lldb::user_id_t uid = LLDB_INVALID_UID;
-
-  if (!process_sp) {
-    error.SetErrorString("invalid process");
-  } else {
-    uid = process_sp->StartTrace(*(options.m_traceoptions_sp), error.ref());
-    trace_instance.SetTraceUID(uid);
-  }
-  return LLDB_RECORD_RESULT(trace_instance);
+  error.SetErrorString("deprecated");
+  return LLDB_RECORD_RESULT(SBTrace());
 }
 
 void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const {
Index: lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
===================================================================
--- /dev/null
+++ lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
@@ -0,0 +1,105 @@
+from lldbsuite.test.lldbtest import *
+import os
+import time
+import json
+
+ADDRESS_REGEX = '0x[0-9a-fA-F]*'
+
+# Decorator that runs a test with both modes of USE_SB_API
+def testSBAPIAndCommands(func):
+    def wrapper(*args, **kwargs):
+        USE_SB_API = True
+        func(*args, **kwargs)
+        USE_SB_API = False
+        func(*args, **kwargs)
+    return wrapper
+
+# Class that should be used by all python Intel PT tests.
+#
+# It has a handy check that skips the test if the intel-pt plugin is not enabled.
+#
+# It also contains many functions that can test both the SB API or the command line version
+# of the most important tracing actions.
+class TraceIntelPTTestCaseBase(TestBase):
+
+    NO_DEBUG_INFO_TESTCASE = True
+
+    # If True, the trace test methods will use the SB API, otherwise they'll use raw commands.
+    USE_SB_API = False
+
+    def setUp(self):
+        TestBase.setUp(self)
+        if 'intel-pt' not in configuration.enabled_plugins:
+            self.skipTest("The intel-pt test plugin is not enabled")
+
+    def assertSBError(self, sberror, error=False):
+        if error:
+            self.assertTrue(sberror.Fail())
+        else:
+            self.assertSuccess(sberror)
+
+    def createConfiguration(self, threadBufferSize=None, processBufferSizeLimit=None):
+        obj = {}
+        if processBufferSizeLimit is not None:
+            obj["processBufferSizeLimit"] = processBufferSizeLimit
+        if threadBufferSize is not None:
+            obj["threadBufferSize"]  = threadBufferSize
+
+        configuration = lldb.SBStructuredData()
+        configuration.SetFromJSON(json.dumps(obj))
+        return configuration
+
+    def traceStartThread(self, thread=None, error=False, substrs=None, threadBufferSize=None):
+        if self.USE_SB_API:
+            sberror = lldb.SBError()
+            trace = self.target().GetTraceOrCreate(sberror)
+
+            thread = thread if thread is not None else self.thread()
+
+            # We do the following to test both APIs
+            if threadBufferSize is None:
+                self.assertSBError(trace.StartThread(thread), error)
+            else:
+                configuration = self.createConfiguration(threadBufferSize=threadBufferSize)
+                self.assertSBError(trace.StartThread(thread, configuration), error)
+        else:
+            command = "thread trace start"
+            if thread is not None:
+                command += " " + str(thread.GetIndexID())
+            if threadBufferSize is not None:
+                command += " -s " + str(threadBufferSize)
+            self.expect(command, error=error, substrs=substrs)
+
+    def traceStartProcess(self, processBufferSizeLimit=None, error=False, substrs=None):
+        if self.USE_SB_API:
+            error = lldb.SBError()
+            trace = self.target().GetTraceOrCreate(error)
+
+            # We do the following to test both APIs
+            if processBufferSizeLimit is None:
+                self.assertSBError(trace.StartProcess(), error=error)
+            else:
+                configuration = self.createConfiguration(processBufferSizeLimit=processBufferSizeLimit)
+                self.assertSBError(trace.StartProcess(configuration), error=error)
+        else:
+            command = "process trace start"
+            if processBufferSizeLimit != None:
+                command += " -l " + str(processBufferSizeLimit)
+            self.expect(command, error=error, substrs=substrs)
+
+    def traceStopProcess(self):
+        if self.USE_SB_API:
+            self.assertSuccess(self.target().GetTrace().StopProcess())
+        else:
+            self.expect("process trace stop")
+
+    def traceStopThread(self, thread=None, error=False):
+        if self.USE_SB_API:
+            thread = thread if thread is not None else self.thread()
+            self.assertSBError(self.target().GetTrace().StopThread(thread), error)
+
+        else:
+            command = "thread trace stop"
+            if thread is not None:
+                command += " " + str(thread.GetIndexID())
+            self.expect(command, error=error)
Index: lldb/packages/Python/lldbsuite/test/dotest.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/dotest.py
+++ lldb/packages/Python/lldbsuite/test/dotest.py
@@ -477,6 +477,7 @@
     pluginPath = os.path.join(scriptPath, 'plugins')
     toolsLLDBVSCode = os.path.join(scriptPath, 'tools', 'lldb-vscode')
     toolsLLDBServerPath = os.path.join(scriptPath, 'tools', 'lldb-server')
+    intelpt = os.path.join(scriptPath, 'tools', 'intelpt')
 
     # Insert script dir, plugin dir and lldb-server dir to the sys.path.
     sys.path.insert(0, pluginPath)
@@ -484,8 +485,11 @@
     # "import lldb_vscode_testcase" from the VSCode tests
     sys.path.insert(0, toolsLLDBVSCode)
     # Adding test/tools/lldb-server to the path makes it easy
-    sys.path.insert(0, toolsLLDBServerPath)
     # to "import lldbgdbserverutils" from the lldb-server tests
+    sys.path.insert(0, toolsLLDBServerPath)
+    # Adding test/tools/intelpt to the path makes it easy
+    # to "import intelpt_testcase" from the lldb-server tests
+    sys.path.insert(0, intelpt)
 
     # This is the root of the lldb git/svn checkout
     # When this changes over to a package instead of a standalone script, this
Index: lldb/include/lldb/lldb-forward.h
===================================================================
--- lldb/include/lldb/lldb-forward.h
+++ lldb/include/lldb/lldb-forward.h
@@ -230,7 +230,6 @@
 class ThreadPostMortemTrace;
 class Trace;
 class TraceSessionFileParser;
-class TraceOptions;
 class Type;
 class TypeAndOrName;
 class TypeCategoryImpl;
@@ -442,7 +441,6 @@
 typedef std::weak_ptr<lldb_private::ThreadPlan> ThreadPlanWP;
 typedef std::shared_ptr<lldb_private::ThreadPlanTracer> ThreadPlanTracerSP;
 typedef std::shared_ptr<lldb_private::Trace> TraceSP;
-typedef std::shared_ptr<lldb_private::TraceOptions> TraceOptionsSP;
 typedef std::shared_ptr<lldb_private::Type> TypeSP;
 typedef std::weak_ptr<lldb_private::Type> TypeWP;
 typedef std::shared_ptr<lldb_private::TypeCategoryImpl> TypeCategoryImplSP;
Index: lldb/include/lldb/Utility/TraceOptions.h
===================================================================
--- lldb/include/lldb/Utility/TraceOptions.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===-- TraceOptions.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLDB_UTILITY_TRACEOPTIONS_H
-#define LLDB_UTILITY_TRACEOPTIONS_H
-
-#include "lldb/lldb-defines.h"
-#include "lldb/lldb-enumerations.h"
-
-#include "lldb/Utility/StructuredData.h"
-
-namespace lldb_private {
-
-/// Deprecated
-class TraceOptions {
-public:
-  TraceOptions() : m_trace_params(new StructuredData::Dictionary()) {}
-
-  const StructuredData::DictionarySP &getTraceParams() const {
-    return m_trace_params;
-  }
-
-  lldb::TraceType getType() const { return m_type; }
-
-  uint64_t getTraceBufferSize() const { return m_trace_buffer_size; }
-
-  uint64_t getMetaDataBufferSize() const { return m_meta_data_buffer_size; }
-
-  void setTraceParams(const StructuredData::DictionarySP &dict_obj) {
-    m_trace_params = dict_obj;
-  }
-
-  void setType(lldb::TraceType type) { m_type = type; }
-
-  void setTraceBufferSize(uint64_t size) { m_trace_buffer_size = size; }
-
-  void setMetaDataBufferSize(uint64_t size) { m_meta_data_buffer_size = size; }
-
-  void setThreadID(lldb::tid_t thread_id) { m_thread_id = thread_id; }
-
-  lldb::tid_t getThreadID() const { return m_thread_id; }
-
-private:
-  lldb::TraceType m_type;
-  uint64_t m_trace_buffer_size;
-  uint64_t m_meta_data_buffer_size;
-  lldb::tid_t m_thread_id;
-
-  /// m_trace_params is meant to hold any custom parameters
-  /// apart from meta buffer size and trace size.
-  /// The interpretation of such parameters is left to
-  /// the lldb-server.
-  StructuredData::DictionarySP m_trace_params;
-};
-
-} // namespace lldb_private
-
-#endif // LLDB_UTILITY_TRACEOPTIONS_H
Index: lldb/include/lldb/Utility/TraceGDBRemotePackets.h
===================================================================
--- lldb/include/lldb/Utility/TraceGDBRemotePackets.h
+++ lldb/include/lldb/Utility/TraceGDBRemotePackets.h
@@ -41,10 +41,13 @@
 struct TraceStartRequest {
   /// Tracing technology name, e.g. intel-pt, arm-coresight.
   std::string type;
+
   /// If \a llvm::None, then this starts tracing the whole process. Otherwise,
   /// only tracing for the specified threads is enabled.
   llvm::Optional<std::vector<int64_t>> tids;
 
+  /// \return
+  ///     \b true if \a tids is \a None, i.e. whole process tracing.
   bool IsProcessTracing() const;
 };
 
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -223,6 +223,35 @@
   ///     \b true if the thread is traced by this instance, \b false otherwise.
   virtual bool IsTraced(const Thread &thread) = 0;
 
+  /// Start tracing a live process.
+  ///
+  /// \param[in] configuration
+  ///     See \a SBTrace::StartProcess(const lldb::SBStructuredData &) for more
+  ///     information.
+  ///
+  /// \return
+  ///     \a llvm::Error::success if the operation was successful, or
+  ///     \a llvm::Error otherwise.
+  virtual llvm::Error StartProcess(
+      StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0;
+
+  /// Start tracing live threads.
+  ///
+  /// \param[in] tids
+  ///     Threads to trace. This method tries to trace as many threads as
+  ///     possible.
+  ///
+  /// \param[in] configuration
+  ///     See \a SBTrace::StartThread(const lldb::SBThread &, const
+  ///     lldb::SBStructuredData &) for more information.
+  ///
+  /// \return
+  ///     \a llvm::Error::success if the operation was successful, or
+  ///     \a llvm::Error otherwise.
+  virtual llvm::Error StartThreads(
+      const std::vector<lldb::tid_t> &tids,
+      StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0;
+
   /// Stop tracing live threads.
   ///
   /// \param[in] tids
Index: lldb/include/lldb/Target/Process.h
===================================================================
--- lldb/include/lldb/Target/Process.h
+++ lldb/include/lldb/Target/Process.h
@@ -2470,56 +2470,6 @@
   lldb::StructuredDataPluginSP
   GetStructuredDataPlugin(ConstString type_name) const;
 
-  /// Deprecated
-  ///
-  /// Starts tracing with the configuration provided in options. To enable
-  /// tracing on the complete process the thread_id in the options should be
-  /// set to LLDB_INVALID_THREAD_ID. The API returns a user_id which is needed
-  /// by other API's that manipulate the trace instance. The handling of
-  /// erroneous or unsupported configuration is left to the trace technology
-  /// implementations in the server, as they could be returned as an error, or
-  /// rounded to a valid configuration to start tracing. In the later case the
-  /// GetTraceConfig should supply the actual used trace configuration.
-  virtual lldb::user_id_t StartTrace(const TraceOptions &options,
-                                     Status &error) {
-    error.SetErrorString("Not implemented");
-    return LLDB_INVALID_UID;
-  }
-
-  /// Deprecated
-  ///
-  /// Stops the tracing instance leading to deletion of the trace data. The
-  /// tracing instance is identified by the user_id which is obtained when
-  /// tracing was started from the StartTrace. In case tracing of the complete
-  /// process needs to be stopped the thread_id should be set to
-  /// LLDB_INVALID_THREAD_ID. In the other case that tracing on an individual
-  /// thread needs to be stopped a thread_id can be supplied.
-  virtual Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
-    return Status("Not implemented");
-  }
-
-  /// Deprecated
-  ///
-  /// Provides the trace data as raw bytes. A buffer needs to be supplied to
-  /// copy the trace data. The exact behavior of this API may vary across
-  /// trace technology, as some may support partial reading of the trace data
-  /// from a specified offset while some may not. The thread_id should be used
-  /// to select a particular thread for trace extraction.
-  virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
-                         llvm::MutableArrayRef<uint8_t> &buffer,
-                         size_t offset = 0) {
-    return Status("Not implemented");
-  }
-
-  /// Deprecated
-  ///
-  /// Similar API as above except for obtaining meta data
-  virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
-                             llvm::MutableArrayRef<uint8_t> &buffer,
-                             size_t offset = 0) {
-    return Status("Not implemented");
-  }
-
 protected:
   friend class Trace;
   ///  Get the processor tracing type supported for this process.
Index: lldb/include/lldb/API/SBTraceOptions.h
===================================================================
--- lldb/include/lldb/API/SBTraceOptions.h
+++ lldb/include/lldb/API/SBTraceOptions.h
@@ -13,47 +13,52 @@
 
 namespace lldb {
 
+/// Deprecated
 class LLDB_API SBTraceOptions {
 public:
+  /// Deprecated
   SBTraceOptions();
 
+  /// Deprecated
   lldb::TraceType getType() const;
 
+  /// Deprecated
   uint64_t getTraceBufferSize() const;
 
-  /// The trace parameters consist of any custom parameters
-  /// apart from the generic parameters such as
-  /// TraceType, trace_buffer_size and meta_data_buffer_size.
-  /// The returned parameters would be formatted as a JSON Dictionary.
+  /// Deprecated
   lldb::SBStructuredData getTraceParams(lldb::SBError &error);
 
+  /// Deprecated
   uint64_t getMetaDataBufferSize() const;
 
-  /// SBStructuredData is meant to hold any custom parameters
-  /// apart from meta buffer size and trace size. They should
-  /// be formatted as a JSON Dictionary.
+  /// Deprecated
   void setTraceParams(lldb::SBStructuredData &params);
 
+  /// Deprecated
   void setType(lldb::TraceType type);
 
+  /// Deprecated
   void setTraceBufferSize(uint64_t size);
 
+  /// Deprecated
   void setMetaDataBufferSize(uint64_t size);
 
+  /// Deprecated
   void setThreadID(lldb::tid_t thread_id);
 
+  /// Deprecated
   lldb::tid_t getThreadID();
 
+  /// Deprecated
   explicit operator bool() const;
 
+  /// Deprecated
   bool IsValid();
 
 protected:
   friend class SBProcess;
   friend class SBTrace;
-
-  lldb::TraceOptionsSP m_traceoptions_sp;
 };
-}
+} // namespace lldb
 
 #endif // LLDB_API_SBTRACEOPTIONS_H
Index: lldb/include/lldb/API/SBTrace.h
===================================================================
--- lldb/include/lldb/API/SBTrace.h
+++ lldb/include/lldb/API/SBTrace.h
@@ -18,98 +18,109 @@
 
 class LLDB_API SBTrace {
 public:
+  /// Default constructor for an invalid Trace object.
   SBTrace();
-  /// Obtain the trace data as raw bytes.
-  ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
+
+  SBTrace(const lldb::TraceSP &trace_sp);
+
+  /// Start tracing a live process using a default configuration.
   ///
-  /// \param[in] buf
-  ///     Buffer to write the trace data to.
+  /// \return
+  ///     An error explaining any failures.
+  SBError StartProcess();
+
+  /// Start tracing a live process using a provided configuration.
   ///
-  /// \param[in] size
-  ///     The size of the buffer used to read the data. This is
-  ///     also the size of the data intended to read. It is also
-  ///     possible to partially read the trace data for some trace
-  ///     technologies by specifying a smaller buffer.
+  /// \param[in] configuration
+  ///     Dictionary object with custom fields for the corresponding trace
+  ///     technology.
   ///
-  /// \param[in] offset
-  ///     The start offset to begin reading the trace data.
+  ///     If a parameter is not specified, a default value will be used.
   ///
-  /// \param[in] thread_id
-  ///     Tracing could be started for the complete process or a
-  ///     single thread, in the first case the traceid obtained would
-  ///     map to all the threads existing within the process and the
-  ///     ones spawning later. The thread_id parameter can be used in
-  ///     such a scenario to select the trace data for a specific
-  ///     thread.
+  ///     For intel-pt:
+  ///       - int threadBufferSize (defaults to 4096 bytes):
+  ///         Trace size in bytes per thread. It must be a power of 2 greater
+  ///         than or equal to 4096 (2^12). The trace is circular keeping the
+  ///         the most recent data.
+  ///       - int processBufferSizeLimit (defaults to 500 MB):
+  ///         Maximum total trace size per process in bytes. This limit applies
+  ///         to the sum of the sizes of all thread traces of this process,
+  ///         excluding the ones created with \a SBTrace::StartThread().
+  ///         Whenever a thread is attempted to be traced due to this command
+  ///         and the limit would be reached, the process is stopped with a
+  ///         "processor trace" reason, so that the user can retrace the process
+  ///         if needed. Defaults to 500MB.
   ///
   /// \return
-  ///     The size of the trace data effectively read by the API call.
-  size_t GetTraceData(SBError &error, void *buf, size_t size, size_t offset = 0,
-                      lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
+  ///     An error explaining any failures.
+  SBError StartProcess(const SBStructuredData &configuration);
 
-  /// Obtain any meta data as raw bytes for the tracing instance.
-  /// The input parameter definition is similar to the previous
-  /// function.
-  size_t GetMetaData(SBError &error, void *buf, size_t size, size_t offset = 0,
-                     lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
+  /// Start tracing a live thread using a default configuration.
+  ///
+  /// \return
+  ///     An error explaining any failures.
+  SBError StartThread(const SBThread &thread);
 
-  /// Stop the tracing instance. Stopping the trace will also
-  /// lead to deletion of any gathered trace data.
+  /// Start tracing a live thread using a provided configuration.
   ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
+  /// \param[in] configuration
+  ///     Dictionary object with custom fields for the corresponding trace
+  ///     technology.
   ///
-  /// \param[in] thread_id
-  ///     The trace id could map to a tracing instance for a thread
-  ///     or could also map to a group of threads being traced with
-  ///     the same trace options. A thread_id is normally optional
-  ///     except in the case of tracing a complete process and tracing
-  ///     needs to switched off on a particular thread.
-  ///     A situation could occur where initially a thread (lets say
-  ///     thread A) is being individually traced with a particular
-  ///     trace id and then tracing is started on the complete
-  ///     process, in this case thread A will continue without any
-  ///     change. All newly spawned threads would be traced with the
-  ///     trace id of the process.
-  ///     Now if the StopTrace API is called for the whole process,
-  ///     thread A will not be stopped and must be stopped separately.
-  void StopTrace(SBError &error,
-                 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
+  ///     If a parameter is not specified, a default value will be used.
+  ///
+  ///     For intel-pt:
+  ///       - int threadBufferSize (defaults to 4096 bytes):
+  ///         Trace size in bytes per thread. It must be a power of 2 greater
+  ///         than or equal to 4096 (2^12). The trace is circular keeping the
+  ///         the most recent data.
+  ///
+  /// \return
+  ///     An error explaining any failures.
+  SBError StartThread(const SBThread &thread,
+                      const SBStructuredData &configuration);
 
-  /// Get the trace configuration being used for the trace instance.
-  /// The threadid in the SBTraceOptions needs to be set when the
-  /// configuration used by a specific thread is being requested.
+  /// Stop tracing a live process.
   ///
-  /// \param[out] options
-  ///     The trace options actually used by the trace instance
-  ///     would be filled by the API.
+  /// \return
+  ///     An error explaining any failures.
+  SBError StopProcess();
+
+  /// Stop tracing a live thread.
   ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
-  void GetTraceConfig(SBTraceOptions &options, SBError &error);
+  /// \return
+  ///     An error explaining any failures.
+  SBError StopThread(const SBThread &thread);
 
-  lldb::user_id_t GetTraceUID();
+  /// Legacy.
+  ///
+  /// Stop tracing for a thread or the entire process.
+  ///
+  /// \param[in] thread_id
+  ///     If \b LLDB_INVALID_THREAD_ID, stops tracing the given thread_id,
+  ///     otherwise stops tracing the entire process.
+  void StopTrace(SBError &error,
+                 lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
 
   explicit operator bool() const;
 
   bool IsValid();
 
-protected:
-  typedef std::shared_ptr<TraceImpl> TraceImplSP;
-
-  friend class SBProcess;
-
-  void SetTraceUID(lldb::user_id_t uid);
+  /// Deprecated
+  /// \{
+  size_t GetTraceData(SBError &error, void *buf, size_t size, size_t offset = 0,
+                      lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
 
-  TraceImplSP m_trace_impl_sp;
+  size_t GetMetaData(SBError &error, void *buf, size_t size, size_t offset = 0,
+                     lldb::tid_t thread_id = LLDB_INVALID_THREAD_ID);
 
-  lldb::ProcessSP GetSP() const;
+  void GetTraceConfig(SBTraceOptions &options, SBError &error);
 
-  void SetSP(const ProcessSP &process_sp);
+  lldb::user_id_t GetTraceUID();
+  /// \}
 
-  lldb::ProcessWP m_opaque_wp;
+protected:
+  lldb::TraceSP m_opaque_sp;
 };
 } // namespace lldb
 
Index: lldb/include/lldb/API/SBThread.h
===================================================================
--- lldb/include/lldb/API/SBThread.h
+++ lldb/include/lldb/API/SBThread.h
@@ -220,6 +220,7 @@
   friend class lldb_private::QueueImpl;
   friend class SBQueueItem;
   friend class SBThreadPlan;
+  friend class SBTrace;
 
   void SetThread(const lldb::ThreadSP &lldb_object_sp);
 
Index: lldb/include/lldb/API/SBTarget.h
===================================================================
--- lldb/include/lldb/API/SBTarget.h
+++ lldb/include/lldb/API/SBTarget.h
@@ -643,7 +643,7 @@
   lldb::SBBreakpoint BreakpointCreateByAddress(addr_t address);
 
   lldb::SBBreakpoint BreakpointCreateBySBAddress(SBAddress &address);
-  
+
   /// Create a breakpoint using a scripted resolver.
   ///
   /// \param[in] class_name
@@ -651,16 +651,16 @@
   ///
   /// \param[in] extra_args
   ///    This is an SBStructuredData object that will get passed to the
-  ///    constructor of the class in class_name.  You can use this to 
-  ///    reuse the same class, parametrizing with entries from this 
+  ///    constructor of the class in class_name.  You can use this to
+  ///    reuse the same class, parametrizing with entries from this
   ///    dictionary.
   ///
   /// \param module_list
-  ///    If this is non-empty, this will be used as the module filter in the 
+  ///    If this is non-empty, this will be used as the module filter in the
   ///    SearchFilter created for this breakpoint.
   ///
   /// \param file_list
-  ///    If this is non-empty, this will be used as the comp unit filter in the 
+  ///    If this is non-empty, this will be used as the comp unit filter in the
   ///    SearchFilter created for this breakpoint.
   ///
   /// \return
@@ -840,6 +840,21 @@
 
   void SetLaunchInfo(const lldb::SBLaunchInfo &launch_info);
 
+  /// Get a \a SBTrace object the can manage the processor trace information of
+  /// this target.
+  ///
+  /// \return
+  ///   The trace object. It might be undefined.
+  lldb::SBTrace GetTrace();
+
+  /// Similar to \a GetTrace, but this also tries to create a \a Trace object
+  /// if not available using the default supported tracing technology for
+  /// this process.
+  ///
+  /// \param[out] error
+  ///     An error explaining why the trace couldn't be created.
+  lldb::SBTrace GetTraceOrCreate(SBError &error);
+
 protected:
   friend class SBAddress;
   friend class SBBlock;
Index: lldb/include/lldb/API/SBStructuredData.h
===================================================================
--- lldb/include/lldb/API/SBStructuredData.h
+++ lldb/include/lldb/API/SBStructuredData.h
@@ -21,7 +21,7 @@
   SBStructuredData(const lldb::SBStructuredData &rhs);
 
   SBStructuredData(const lldb::EventSP &event_sp);
-  
+
   SBStructuredData(lldb_private::StructuredDataImpl *impl);
 
   ~SBStructuredData();
@@ -34,6 +34,8 @@
 
   lldb::SBError SetFromJSON(lldb::SBStream &stream);
 
+  lldb::SBError SetFromJSON(const char *json);
+
   void Clear();
 
   lldb::SBError GetAsJSON(lldb::SBStream &stream) const;
@@ -42,7 +44,7 @@
 
   /// Return the type of data in this data structure
   lldb::StructuredDataType GetType() const;
-  
+
   /// Return the size (i.e. number of elements) in this data structure
   /// if it is an array or dictionary type. For other types, 0 will be
   //  returned.
@@ -51,7 +53,7 @@
   /// Fill keys with the keys in this object and return true if this data
   /// structure is a dictionary.  Returns false otherwise.
    bool GetKeys(lldb::SBStringList &keys) const;
-  
+
   /// Return the value corresponding to a key if this data structure
   /// is a dictionary type.
   lldb::SBStructuredData GetValueForKey(const char *key) const;
@@ -98,6 +100,7 @@
   friend class SBBreakpoint;
   friend class SBBreakpointLocation;
   friend class SBBreakpointName;
+  friend class SBTrace;
 
   StructuredDataImplUP m_impl_up;
 };
Index: lldb/include/lldb/API/SBProcess.h
===================================================================
--- lldb/include/lldb/API/SBProcess.h
+++ lldb/include/lldb/API/SBProcess.h
@@ -94,6 +94,7 @@
 
   lldb::SBThread GetThreadByIndexID(uint32_t index_id);
 
+  /// Deprecated
   lldb::SBThread GetSelectedThread() const;
 
   // Function for lazily creating a thread using the current OS plug-in. This
@@ -301,13 +302,13 @@
   /// paths till you find a matching library.
   ///
   /// \param[in] image_spec
-  ///     The name of the shared library that you want to load.  
+  ///     The name of the shared library that you want to load.
   ///     If image_spec is a relative path, the relative path will be
   ///     appended to the search paths.
   ///     If the image_spec is an absolute path, just the basename is used.
   ///
   /// \param[in] paths
-  ///     A list of paths to search for the library whose basename is 
+  ///     A list of paths to search for the library whose basename is
   ///     local_spec.
   ///
   /// \param[out] loaded_path
@@ -325,7 +326,7 @@
   ///     library can't be opened.
   uint32_t LoadImageUsingPaths(const lldb::SBFileSpec &image_spec,
                                SBStringList &paths,
-                               lldb::SBFileSpec &loaded_path, 
+                               lldb::SBFileSpec &loaded_path,
                                lldb::SBError &error);
 
   lldb::SBError UnloadImage(uint32_t image_token);
Index: lldb/docs/design/overview.rst
===================================================================
--- lldb/docs/design/overview.rst
+++ lldb/docs/design/overview.rst
@@ -174,9 +174,9 @@
 really have anything to do with debugging -- they are just there because the
 higher layers of the debugger use these classes to implement their
 functionality. Others are data structures used in many other parts of the
-debugger (TraceOptions). Most of the functionality in this module could be
-useful in an application that is not a debugger; however, providing a general
-purpose C++ library is an explicit non-goal of this module.
+debugger. Most of the functionality in this module could be useful in an
+application that is not a debugger; however, providing a general purpose C++
+library is an explicit non-goal of this module..
 
 This module provides following functionality:
 
Index: lldb/bindings/interface/SBTraceOptions.i
===================================================================
--- lldb/bindings/interface/SBTraceOptions.i
+++ lldb/bindings/interface/SBTraceOptions.i
@@ -9,36 +9,48 @@
 namespace lldb {
 
 %feature("docstring",
-"Represents the possible options when doing processor tracing.
-
-See :py:class:`SBProcess.StartTrace`."
+"deprecated"
 ) SBTraceOptions;
+// deprecated
 class LLDB_API SBTraceOptions {
 public:
+  // deprecated
   SBTraceOptions();
 
+  // deprecated
   lldb::TraceType getType() const;
 
+  // deprecated
   uint64_t getTraceBufferSize() const;
 
+  // deprecated
   lldb::SBStructuredData getTraceParams(lldb::SBError &error);
 
+  // deprecated
   uint64_t getMetaDataBufferSize() const;
 
+  // deprecated
   void setTraceParams(lldb::SBStructuredData &params);
 
+  // deprecated
   void setType(lldb::TraceType type);
 
+  // deprecated
   void setTraceBufferSize(uint64_t size);
 
+  // deprecated
   void setMetaDataBufferSize(uint64_t size);
 
+  // deprecated
   void setThreadID(lldb::tid_t thread_id);
 
+  // deprecated
   lldb::tid_t getThreadID();
 
+  // deprecated
   explicit operator bool() const;
 
+  // deprecated
   bool IsValid();
 };
 }
Index: lldb/bindings/interface/SBTrace.i
===================================================================
--- lldb/bindings/interface/SBTrace.i
+++ lldb/bindings/interface/SBTrace.i
@@ -14,25 +14,42 @@
 class LLDB_API SBTrace {
 public:
   SBTrace();
-  size_t GetTraceData(SBError &error, void *buf,
-                      size_t size, size_t offset,
-                      lldb::tid_t thread_id);
 
-  size_t GetMetaData(SBError &error, void *buf,
-                     size_t size, size_t offset,
-                     lldb::tid_t thread_id);
+  SBError StartProcess();
+
+  SBError StartProcess(const SBStructuredData &configuration);
+
+  SBError StartThread(const SBThread &thread);
+
+  SBError StartThread(const SBThread &thread, const SBStructuredData &configuration);
+
+  SBError StopProcess();
+
+  SBError StopThread(const SBThread &thread);
+
+  explicit operator bool() const;
+
+  bool IsValid();
 
+  /// legacy
   void StopTrace(SBError &error,
                  lldb::tid_t thread_id);
 
+  /// deprecated
   void GetTraceConfig(SBTraceOptions &options,
                       SBError &error);
 
+  /// deprecated
   lldb::user_id_t GetTraceUID();
 
-  explicit operator bool() const;
-
-  bool IsValid();
+  /// deprecated
+  size_t GetTraceData(SBError &error, void *buf,
+                      size_t size, size_t offset,
+                      lldb::tid_t thread_id);
 
+  /// deprecated
+  size_t GetMetaData(SBError &error, void *buf,
+                     size_t size, size_t offset,
+                     lldb::tid_t thread_id);
 };
-} // namespace lldb
\ No newline at end of file
+} // namespace lldb
Index: lldb/bindings/interface/SBTarget.i
===================================================================
--- lldb/bindings/interface/SBTarget.i
+++ lldb/bindings/interface/SBTarget.i
@@ -974,6 +974,12 @@
 
     STRING_EXTENSION_LEVEL(SBTarget, lldb::eDescriptionLevelBrief)
 
+    lldb::SBTrace
+    GetTrace ();
+
+    lldb::SBTrace
+    GetTraceOrCreate (lldb::SBError &error);
+
 #ifdef SWIGPYTHON
     %pythoncode %{
         class modules_access(object):
Index: lldb/bindings/interface/SBStructuredData.i
===================================================================
--- lldb/bindings/interface/SBStructuredData.i
+++ lldb/bindings/interface/SBStructuredData.i
@@ -58,5 +58,8 @@
 
         lldb::SBError
         SetFromJSON(lldb::SBStream &stream);
+
+        lldb::SBError
+        SetFromJSON(const char *json);
     };
 }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to