[Lldb-commits] [lldb] bf9f21a - [trace][intel-pt] Create basic SB API

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Thu Jun 17 15:23:33 PDT 2021


Author: Walter Erquinigo
Date: 2021-06-17T15:14:47-07:00
New Revision: bf9f21a28be171dc500cc68b4cb1fcd3fc33f229

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

LOG: [trace][intel-pt] Create basic SB API

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.

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

Added: 
    lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
    lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h

Modified: 
    lldb/bindings/headers.swig
    lldb/bindings/interface/SBProcess.i
    lldb/bindings/interface/SBStructuredData.i
    lldb/bindings/interface/SBTarget.i
    lldb/bindings/interface/SBTrace.i
    lldb/bindings/interfaces.swig
    lldb/docs/.htaccess
    lldb/docs/design/overview.rst
    lldb/docs/lldb-gdb-remote.txt
    lldb/include/lldb/API/LLDB.h
    lldb/include/lldb/API/SBDefines.h
    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/Target/Process.h
    lldb/include/lldb/Target/Target.h
    lldb/include/lldb/Target/Trace.h
    lldb/include/lldb/Utility/TraceGDBRemotePackets.h
    lldb/include/lldb/lldb-forward.h
    lldb/packages/Python/lldbsuite/test/dotest.py
    lldb/source/API/CMakeLists.txt
    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/Commands/CommandObjectProcess.cpp
    lldb/source/Commands/CommandObjectThread.cpp
    lldb/source/Commands/CommandObjectThreadUtil.h
    lldb/source/Commands/CommandObjectTrace.cpp
    lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
    lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
    lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
    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/Target/Target.cpp
    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

Removed: 
    lldb/bindings/interface/SBTraceOptions.i
    lldb/include/lldb/API/SBTraceOptions.h
    lldb/include/lldb/Utility/TraceOptions.h
    lldb/source/API/SBTraceOptions.cpp


################################################################################
diff  --git a/lldb/bindings/headers.swig b/lldb/bindings/headers.swig
index 6e1668ea4c42..3c2cd85f504d 100644
--- a/lldb/bindings/headers.swig
+++ b/lldb/bindings/headers.swig
@@ -62,7 +62,6 @@
 #include "lldb/API/SBThreadCollection.h"
 #include "lldb/API/SBThreadPlan.h"
 #include "lldb/API/SBTrace.h"
-#include "lldb/API/SBTraceOptions.h"
 #include "lldb/API/SBType.h"
 #include "lldb/API/SBTypeCategory.h"
 #include "lldb/API/SBTypeEnumMember.h"

diff  --git a/lldb/bindings/interface/SBProcess.i b/lldb/bindings/interface/SBProcess.i
index e30b89d1ed39..27c015df85cd 100644
--- a/lldb/bindings/interface/SBProcess.i
+++ b/lldb/bindings/interface/SBProcess.i
@@ -400,9 +400,6 @@ public:
     lldb::SBError
     SaveCore(const char *file_name);
 
-    lldb::SBTrace
-    StartTrace(SBTraceOptions &options, lldb::SBError &error);
-
     lldb::SBError
     GetMemoryRegionInfo(lldb::addr_t load_addr, lldb::SBMemoryRegionInfo &region_info);
 

diff  --git a/lldb/bindings/interface/SBStructuredData.i b/lldb/bindings/interface/SBStructuredData.i
index 5aba35229855..ba5b7e075065 100644
--- a/lldb/bindings/interface/SBStructuredData.i
+++ b/lldb/bindings/interface/SBStructuredData.i
@@ -58,5 +58,8 @@ This class wraps the event type generated by StructuredData features."
 
         lldb::SBError
         SetFromJSON(lldb::SBStream &stream);
+
+        lldb::SBError
+        SetFromJSON(const char *json);
     };
 }

diff  --git a/lldb/bindings/interface/SBTarget.i b/lldb/bindings/interface/SBTarget.i
index 772ee1a2eb73..3f9e4cdc6d67 100644
--- a/lldb/bindings/interface/SBTarget.i
+++ b/lldb/bindings/interface/SBTarget.i
@@ -974,6 +974,12 @@ public:
 
     STRING_EXTENSION_LEVEL(SBTarget, lldb::eDescriptionLevelBrief)
 
+    lldb::SBTrace
+    GetTrace ();
+
+    lldb::SBTrace
+    CreateTrace (lldb::SBError &error);
+
 #ifdef SWIGPYTHON
     %pythoncode %{
         class modules_access(object):

diff  --git a/lldb/bindings/interface/SBTrace.i b/lldb/bindings/interface/SBTrace.i
index 6d4b7e6be27d..0f5bf0ecc8d9 100644
--- a/lldb/bindings/interface/SBTrace.i
+++ b/lldb/bindings/interface/SBTrace.i
@@ -14,25 +14,19 @@ namespace lldb {
 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);
+  const char *GetStartConfigurationHelp();
 
-  void StopTrace(SBError &error,
-                 lldb::tid_t thread_id);
+  SBError Start(const SBStructuredData &configuration);
 
-  void GetTraceConfig(SBTraceOptions &options,
-                      SBError &error);
+  SBError Start(const SBThread &thread, const SBStructuredData &configuration);
 
-  lldb::user_id_t GetTraceUID();
+  SBError Stop();
+
+  SBError Stop(const SBThread &thread);
 
   explicit operator bool() const;
 
   bool IsValid();
-
 };
-} // namespace lldb
\ No newline at end of file
+} // namespace lldb

diff  --git a/lldb/bindings/interface/SBTraceOptions.i b/lldb/bindings/interface/SBTraceOptions.i
deleted file mode 100644
index 4a1878b5b76f..000000000000
--- a/lldb/bindings/interface/SBTraceOptions.i
+++ /dev/null
@@ -1,44 +0,0 @@
-//===-- SWIG Interface for SBTraceOptions -----------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-namespace lldb {
-
-%feature("docstring",
-"Represents the possible options when doing processor tracing.
-
-See :py:class:`SBProcess.StartTrace`."
-) SBTraceOptions;
-class LLDB_API SBTraceOptions {
-public:
-  SBTraceOptions();
-
-  lldb::TraceType getType() const;
-
-  uint64_t getTraceBufferSize() const;
-
-  lldb::SBStructuredData getTraceParams(lldb::SBError &error);
-
-  uint64_t getMetaDataBufferSize() const;
-
-  void setTraceParams(lldb::SBStructuredData &params);
-
-  void setType(lldb::TraceType type);
-
-  void setTraceBufferSize(uint64_t size);
-
-  void setMetaDataBufferSize(uint64_t size);
-
-  void setThreadID(lldb::tid_t thread_id);
-
-  lldb::tid_t getThreadID();
-
-  explicit operator bool() const;
-
-  bool IsValid();
-};
-}

diff  --git a/lldb/bindings/interfaces.swig b/lldb/bindings/interfaces.swig
index 2df7a05b4f48..c9a6d0f06056 100644
--- a/lldb/bindings/interfaces.swig
+++ b/lldb/bindings/interfaces.swig
@@ -69,7 +69,6 @@
 %include "./interface/SBThreadCollection.i"
 %include "./interface/SBThreadPlan.i"
 %include "./interface/SBTrace.i"
-%include "./interface/SBTraceOptions.i"
 %include "./interface/SBType.i"
 %include "./interface/SBTypeCategory.i"
 %include "./interface/SBTypeEnumMember.i"

diff  --git a/lldb/docs/.htaccess b/lldb/docs/.htaccess
index 7f84a78df0a6..91b25fb504f1 100644
--- a/lldb/docs/.htaccess
+++ b/lldb/docs/.htaccess
@@ -82,7 +82,6 @@ Redirect 301 /python_reference/lldb.SBThread-class.html https://lldb.llvm.org/py
 Redirect 301 /python_reference/lldb.SBThreadCollection-class.html https://lldb.llvm.org/python_api/lldb.SBThreadCollection.html
 Redirect 301 /python_reference/lldb.SBThreadPlan-class.html https://lldb.llvm.org/python_api/lldb.SBThreadPlan.html
 Redirect 301 /python_reference/lldb.SBTrace-class.html https://lldb.llvm.org/python_api/lldb.SBTrace.html
-Redirect 301 /python_reference/lldb.SBTraceOptions-class.html https://lldb.llvm.org/python_api/lldb.SBTraceOptions.html
 Redirect 301 /python_reference/lldb.SBType-class.html https://lldb.llvm.org/python_api/lldb.SBType.html
 Redirect 301 /python_reference/lldb.SBTypeCategory-class.html https://lldb.llvm.org/python_api/lldb.SBTypeCategory.html
 Redirect 301 /python_reference/lldb.SBTypeEnumMember-class.html https://lldb.llvm.org/python_api/lldb.SBTypeEnumMember.html

diff  --git a/lldb/docs/design/overview.rst b/lldb/docs/design/overview.rst
index 06f8370c613b..1555ea35bfba 100644
--- a/lldb/docs/design/overview.rst
+++ b/lldb/docs/design/overview.rst
@@ -174,9 +174,9 @@ This module contains the lowest layers of LLDB. A lot of these classes don't
 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:
 

diff  --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt
index fb92c5665be6..9d6b41ad086e 100644
--- a/lldb/docs/lldb-gdb-remote.txt
+++ b/lldb/docs/lldb-gdb-remote.txt
@@ -348,7 +348,7 @@ read packet: OK/E<error code>;AAAAAAAAA
 //  response is returned, or an error otherwise.
 //
 // PROCESS TRACE STOPPING
-//  Stopping a process trace doesn't stop the active traces initiated with
+//  Stopping a process trace stops the active traces initiated with
 //  "thread tracing".
 //
 // THREAD TRACE STOPPING

diff  --git a/lldb/include/lldb/API/LLDB.h b/lldb/include/lldb/API/LLDB.h
index f7390cfabf01..eacbbeafcf1c 100644
--- a/lldb/include/lldb/API/LLDB.h
+++ b/lldb/include/lldb/API/LLDB.h
@@ -65,7 +65,6 @@
 #include "lldb/API/SBThreadCollection.h"
 #include "lldb/API/SBThreadPlan.h"
 #include "lldb/API/SBTrace.h"
-#include "lldb/API/SBTraceOptions.h"
 #include "lldb/API/SBType.h"
 #include "lldb/API/SBTypeCategory.h"
 #include "lldb/API/SBTypeEnumMember.h"

diff  --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h
index a5b639c6dc73..3ab10ad8e061 100644
--- a/lldb/include/lldb/API/SBDefines.h
+++ b/lldb/include/lldb/API/SBDefines.h
@@ -76,7 +76,6 @@ class LLDB_API SBThread;
 class LLDB_API SBThreadCollection;
 class LLDB_API SBThreadPlan;
 class LLDB_API SBTrace;
-class LLDB_API SBTraceOptions;
 class LLDB_API SBType;
 class LLDB_API SBTypeCategory;
 class LLDB_API SBTypeEnumMember;

diff  --git a/lldb/include/lldb/API/SBProcess.h b/lldb/include/lldb/API/SBProcess.h
index 5cf5b1f9aadb..a5676c2cab9a 100644
--- a/lldb/include/lldb/API/SBProcess.h
+++ b/lldb/include/lldb/API/SBProcess.h
@@ -224,31 +224,6 @@ class LLDB_API SBProcess {
 
   SBStructuredData GetExtendedCrashInformation();
 
-  /// Start Tracing with the given SBTraceOptions.
-  ///
-  /// \param[in] options
-  ///     Class containing trace options like trace buffer size, meta
-  ///     data buffer size, TraceType and any custom parameters
-  ///     {formatted as a JSON Dictionary}. In case of errors in
-  ///     formatting, an error would be reported.
-  ///     It must be noted that tracing options such as buffer sizes
-  ///     or other custom parameters passed maybe invalid for some
-  ///     trace technologies. In such cases the trace implementations
-  ///     could choose to either throw an error or could round off to
-  ///     the nearest valid options to start tracing if the passed
-  ///     value is not supported. To obtain the actual used trace
-  ///     options please use the GetTraceConfig API. For the custom
-  ///     parameters, only the parameters recognized by the target
-  ///     would be used and others would be ignored.
-  ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
-  ///
-  /// \return
-  ///     A SBTrace instance, which should be used
-  ///     to get the trace data or other trace related operations.
-  lldb::SBTrace StartTrace(SBTraceOptions &options, lldb::SBError &error);
-
   uint32_t GetNumSupportedHardwareWatchpoints(lldb::SBError &error) const;
 
   /// Load a shared library into this process.
@@ -301,13 +276,13 @@ class LLDB_API SBProcess {
   /// 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 +300,7 @@ class LLDB_API SBProcess {
   ///     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);

diff  --git a/lldb/include/lldb/API/SBStructuredData.h b/lldb/include/lldb/API/SBStructuredData.h
index 07763f2de52b..07075abbf1d0 100644
--- a/lldb/include/lldb/API/SBStructuredData.h
+++ b/lldb/include/lldb/API/SBStructuredData.h
@@ -21,7 +21,7 @@ class SBStructuredData {
   SBStructuredData(const lldb::SBStructuredData &rhs);
 
   SBStructuredData(const lldb::EventSP &event_sp);
-  
+
   SBStructuredData(lldb_private::StructuredDataImpl *impl);
 
   ~SBStructuredData();
@@ -34,6 +34,8 @@ class SBStructuredData {
 
   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 @@ class SBStructuredData {
 
   /// 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 @@ class SBStructuredData {
   /// 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;
@@ -89,7 +91,6 @@ class SBStructuredData {
 
 protected:
   friend class SBLaunchInfo;
-  friend class SBTraceOptions;
   friend class SBDebugger;
   friend class SBTarget;
   friend class SBProcess;
@@ -98,6 +99,7 @@ class SBStructuredData {
   friend class SBBreakpoint;
   friend class SBBreakpointLocation;
   friend class SBBreakpointName;
+  friend class SBTrace;
 
   StructuredDataImplUP m_impl_up;
 };

diff  --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index f427404ac1ff..5a6908f040b1 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -643,7 +643,7 @@ class LLDB_API SBTarget {
   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 @@ class LLDB_API SBTarget {
   ///
   /// \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 @@ class LLDB_API SBTarget {
 
   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. The returned SBTrace object might not be valid, so it
+  ///   should be checked with a call to "bool SBTrace::IsValid()".
+  lldb::SBTrace GetTrace();
+
+  /// Create a \a Trace object for the current target using the using the
+  /// default supported tracing technology for this process.
+  ///
+  /// \param[out] error
+  ///     An error if a Trace already exists or the trace couldn't be created.
+  lldb::SBTrace CreateTrace(SBError &error);
+
 protected:
   friend class SBAddress;
   friend class SBBlock;

diff  --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h
index 9960a2224f65..ac1b8407a220 100644
--- a/lldb/include/lldb/API/SBThread.h
+++ b/lldb/include/lldb/API/SBThread.h
@@ -220,6 +220,7 @@ class LLDB_API SBThread {
   friend class lldb_private::QueueImpl;
   friend class SBQueueItem;
   friend class SBThreadPlan;
+  friend class SBTrace;
 
   void SetThread(const lldb::ThreadSP &lldb_object_sp);
 

diff  --git a/lldb/include/lldb/API/SBTrace.h b/lldb/include/lldb/API/SBTrace.h
index 053abaeada19..1685caaf4efa 100644
--- a/lldb/include/lldb/API/SBTrace.h
+++ b/lldb/include/lldb/API/SBTrace.h
@@ -18,97 +18,88 @@ namespace lldb {
 
 class LLDB_API SBTrace {
 public:
+  /// Default constructor for an invalid Trace object.
   SBTrace();
-  /// Obtain the trace data as raw bytes.
+
+  SBTrace(const lldb::TraceSP &trace_sp);
+
+  /// \return
+  ///     A description of the parameters to use for the \a SBTrace::Start
+  ///     method, or \b null if the object is invalid.
+  const char *GetStartConfigurationHelp();
+
+  /// Start tracing all current and future threads in a live process using a
+  /// provided configuration. This is referred as "process tracing" in the
+  /// documentation.
   ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
+  /// This is equivalent to the command "process trace start".
   ///
-  /// \param[in] buf
-  ///     Buffer to write the trace data to.
+  /// This operation fails if it is invoked twice in a row without
+  /// first stopping the process trace with \a SBTrace::Stop().
   ///
-  /// \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.
+  /// If a thread is already being traced explicitly, e.g. with \a
+  /// SBTrace::Start(const SBThread &thread, const SBStructuredData
+  /// &configuration), it is left unaffected by this operation.
   ///
-  /// \param[in] offset
-  ///     The start offset to begin reading the trace data.
+  /// \param[in] configuration
+  ///     Dictionary object with custom fields for the corresponding trace
+  ///     technology.
   ///
-  /// \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.
+  ///     Full details for the trace start parameters that can be set can be
+  ///     retrieved by calling \a SBTrace::GetStartConfigurationHelp().
   ///
   /// \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);
-
-  /// 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);
+  ///     An error explaining any failures.
+  SBError Start(const SBStructuredData &configuration);
 
-  /// Stop the tracing instance. Stopping the trace will also
-  /// lead to deletion of any gathered trace data.
-  ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
-  ///
-  /// \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);
+  /// Start tracing a specific thread in a live process using a provided
+  /// configuration. This is referred as "thread tracing" in the documentation.
+  ///
+  /// This is equivalent to the command "thread trace start".
+  ///
+  /// If the thread is already being traced by a "process tracing" operation,
+  /// e.g. with \a SBTrace::Start(const SBStructuredData &configuration), this
+  /// operation fails.
+  ///
+  /// \param[in] configuration
+  ///     Dictionary object with custom fields for the corresponding trace
+  ///     technology.
+  ///
+  ///     Full details for the trace start parameters that can be set can be
+  ///     retrieved by calling \a SBTrace::GetStartConfigurationHelp().
+  ///
+  /// \return
+  ///     An error explaining any failures.
+  SBError Start(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 all threads in a live process.
   ///
-  /// \param[out] options
-  ///     The trace options actually used by the trace instance
-  ///     would be filled by the API.
+  /// If a "process tracing" operation is active, e.g. \a SBTrace::Start(const
+  /// SBStructuredData &configuration), this effectively prevents future threads
+  /// from being traced.
   ///
-  /// \param[out] error
-  ///     An error explaining what went wrong.
-  void GetTraceConfig(SBTraceOptions &options, SBError &error);
+  /// This is equivalent to the command "process trace stop".
+  ///
+  /// \return
+  ///     An error explaining any failures.
+  SBError Stop();
 
-  lldb::user_id_t GetTraceUID();
+  /// Stop tracing a specific thread in a live process regardless of whether the
+  /// thread was traced explicitly or as part of a "process tracing" operation.
+  ///
+  /// This is equivalent to the command "thread trace stop".
+  ///
+  /// \return
+  ///     An error explaining any failures.
+  SBError Stop(const SBThread &thread);
 
   explicit operator bool() const;
 
   bool IsValid();
 
 protected:
-  typedef std::shared_ptr<TraceImpl> TraceImplSP;
-
-  friend class SBProcess;
-
-  void SetTraceUID(lldb::user_id_t uid);
-
-  TraceImplSP m_trace_impl_sp;
-
-  lldb::ProcessSP GetSP() const;
-
-  void SetSP(const ProcessSP &process_sp);
-
+  lldb::TraceSP m_opaque_sp;
+  /// deprecated
   lldb::ProcessWP m_opaque_wp;
 };
 } // namespace lldb

diff  --git a/lldb/include/lldb/API/SBTraceOptions.h b/lldb/include/lldb/API/SBTraceOptions.h
deleted file mode 100644
index 22d71fbd3828..000000000000
--- a/lldb/include/lldb/API/SBTraceOptions.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===-- SBTraceOptions ------------------------------------------*- 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_API_SBTRACEOPTIONS_H
-#define LLDB_API_SBTRACEOPTIONS_H
-
-#include "lldb/API/SBDefines.h"
-
-namespace lldb {
-
-class LLDB_API SBTraceOptions {
-public:
-  SBTraceOptions();
-
-  lldb::TraceType getType() const;
-
-  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.
-  lldb::SBStructuredData getTraceParams(lldb::SBError &error);
-
-  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.
-  void setTraceParams(lldb::SBStructuredData &params);
-
-  void setType(lldb::TraceType type);
-
-  void setTraceBufferSize(uint64_t size);
-
-  void setMetaDataBufferSize(uint64_t size);
-
-  void setThreadID(lldb::tid_t thread_id);
-
-  lldb::tid_t getThreadID();
-
-  explicit operator bool() const;
-
-  bool IsValid();
-
-protected:
-  friend class SBProcess;
-  friend class SBTrace;
-
-  lldb::TraceOptionsSP m_traceoptions_sp;
-};
-}
-
-#endif // LLDB_API_SBTRACEOPTIONS_H

diff  --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index b7b45184af2a..65806084a7ae 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2469,56 +2469,6 @@ void PruneThreadPlans();
   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.

diff  --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 2d67977dd6a0..0db5209cd1f3 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -1126,12 +1126,19 @@ class Target : public std::enable_shared_from_this<Target>,
   ///
   /// \return
   ///   The trace object. It might be undefined.
-  lldb::TraceSP &GetTrace();
+  lldb::TraceSP 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.
-  llvm::Expected<lldb::TraceSP &> GetTraceOrCreate();
+  /// Create a \a Trace object for the current target using the using the
+  /// default supported tracing technology for this process.
+  ///
+  /// \return
+  ///     The new \a Trace or an \a llvm::Error if a \a Trace already exists or
+  ///     the trace couldn't be created.
+  llvm::Expected<lldb::TraceSP> CreateTrace();
+
+  /// If a \a Trace object is present, this returns it, otherwise a new Trace is
+  /// created with \a Trace::CreateTrace.
+  llvm::Expected<lldb::TraceSP> GetTraceOrCreate();
 
   // Since expressions results can persist beyond the lifetime of a process,
   // and the const expression results are available after a process is gone, we

diff  --git a/lldb/include/lldb/Target/Trace.h b/lldb/include/lldb/Target/Trace.h
index 81585fa7be40..5ff7a149b01e 100644
--- a/lldb/include/lldb/Target/Trace.h
+++ b/lldb/include/lldb/Target/Trace.h
@@ -223,6 +223,39 @@ class Trace : public PluginInterface,
   ///     \b true if the thread is traced by this instance, \b false otherwise.
   virtual bool IsTraced(const Thread &thread) = 0;
 
+  /// \return
+  ///     A description of the parameters to use for the \a Trace::Start method.
+  virtual const char *GetStartConfigurationHelp() = 0;
+
+  /// Start tracing a live process.
+  ///
+  /// \param[in] configuration
+  ///     See \a SBTrace::Start(const lldb::SBStructuredData &) for more
+  ///     information.
+  ///
+  /// \return
+  ///     \a llvm::Error::success if the operation was successful, or
+  ///     \a llvm::Error otherwise.
+  virtual llvm::Error Start(
+      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::Start(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 Start(
+      llvm::ArrayRef<lldb::tid_t> tids,
+      StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0;
+
   /// Stop tracing live threads.
   ///
   /// \param[in] tids
@@ -231,9 +264,9 @@ class Trace : public PluginInterface,
   /// \return
   ///     \a llvm::Error::success if the operation was successful, or
   ///     \a llvm::Error otherwise.
-  llvm::Error StopThreads(const std::vector<lldb::tid_t> &tids);
+  llvm::Error Stop(llvm::ArrayRef<lldb::tid_t> tids);
 
-  /// Stop tracing a live process.
+  /// Stop tracing all current and future threads of a live process.
   ///
   /// \param[in] request
   ///     The information determining which threads or process to stop tracing.
@@ -241,7 +274,7 @@ class Trace : public PluginInterface,
   /// \return
   ///     \a llvm::Error::success if the operation was successful, or
   ///     \a llvm::Error otherwise.
-  llvm::Error StopProcess();
+  llvm::Error Stop();
 
   /// Get the trace file of the given post mortem thread.
   llvm::Expected<const FileSpec &> GetPostMortemTraceFile(lldb::tid_t tid);
@@ -258,7 +291,7 @@ class Trace : public PluginInterface,
   /// \return
   ///     A vector of bytes with the requested data, or an \a llvm::Error in
   ///     case of failures.
-  llvm::Expected<std::vector<uint8_t>>
+  llvm::Expected<llvm::ArrayRef<uint8_t>>
   GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind);
 
   /// Get binary data of the current process given a data identifier.
@@ -269,7 +302,7 @@ class Trace : public PluginInterface,
   /// \return
   ///     A vector of bytes with the requested data, or an \a llvm::Error in
   ///     case of failures.
-  llvm::Expected<std::vector<uint8_t>>
+  llvm::Expected<llvm::ArrayRef<uint8_t>>
   GetLiveProcessBinaryData(llvm::StringRef kind);
 
   /// Get the size of the data returned by \a GetLiveThreadBinaryData

diff  --git a/lldb/include/lldb/Utility/TraceGDBRemotePackets.h b/lldb/include/lldb/Utility/TraceGDBRemotePackets.h
index 66fa5e2f8b51..fbee32ec3e74 100644
--- a/lldb/include/lldb/Utility/TraceGDBRemotePackets.h
+++ b/lldb/include/lldb/Utility/TraceGDBRemotePackets.h
@@ -41,10 +41,13 @@ llvm::json::Value toJSON(const TraceSupportedResponse &packet);
 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;
 };
 

diff  --git a/lldb/include/lldb/Utility/TraceOptions.h b/lldb/include/lldb/Utility/TraceOptions.h
deleted file mode 100644
index 677ba0eabea3..000000000000
--- a/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

diff  --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index a3cba953ea1a..27458f0e9154 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -230,7 +230,6 @@ class ThreadSpec;
 class ThreadPostMortemTrace;
 class Trace;
 class TraceSessionFileParser;
-class TraceOptions;
 class Type;
 class TypeAndOrName;
 class TypeCategoryImpl;
@@ -442,7 +441,6 @@ typedef std::shared_ptr<lldb_private::ThreadPostMortemTrace>
 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;

diff  --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index dc46f21429ed..3e832d91e288 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -477,6 +477,7 @@ def setupSysPath():
     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 @@ def setupSysPath():
     # "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

diff  --git a/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
new file mode 100644
index 000000000000..2b7dfb16d34a
--- /dev/null
+++ b/lldb/packages/Python/lldbsuite/test/tools/intelpt/intelpt_testcase.py
@@ -0,0 +1,99 @@
+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.
+# It assumes that no tests can be executed in parallel.
+def testSBAPIAndCommands(func):
+    def wrapper(*args, **kwargs):
+        TraceIntelPTTestCaseBase.USE_SB_API = True
+        func(*args, **kwargs)
+        TraceIntelPTTestCaseBase.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 getTraceOrCreate(self):
+        if not self.target().GetTrace().IsValid():
+            error = lldb.SBError()
+            self.target().CreateTrace(error)
+        return self.target().GetTrace()
+
+    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:
+            trace = self.getTraceOrCreate()
+            thread = thread if thread is not None else self.thread()
+            configuration = self.createConfiguration(threadBufferSize=threadBufferSize)
+            self.assertSBError(trace.Start(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:
+            trace = self.getTraceOrCreate()
+            configuration = self.createConfiguration(processBufferSizeLimit=processBufferSizeLimit)
+            self.assertSBError(trace.Start(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().Stop())
+        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().Stop(thread), error)
+
+        else:
+            command = "thread trace stop"
+            if thread is not None:
+                command += " " + str(thread.GetIndexID())
+            self.expect(command, error=error)

diff  --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index b74bfd4a2ff8..2e33f5c05c1a 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -76,7 +76,6 @@ add_lldb_library(liblldb SHARED ${option_framework}
   SBThreadCollection.cpp
   SBThreadPlan.cpp
   SBTrace.cpp
-  SBTraceOptions.cpp
   SBType.cpp
   SBTypeCategory.cpp
   SBTypeEnumMember.cpp

diff  --git a/lldb/source/API/SBProcess.cpp b/lldb/source/API/SBProcess.cpp
index be20e8f0e43a..58ed3d76a0bd 100644
--- a/lldb/source/API/SBProcess.cpp
+++ b/lldb/source/API/SBProcess.cpp
@@ -44,7 +44,6 @@
 #include "lldb/API/SBThread.h"
 #include "lldb/API/SBThreadCollection.h"
 #include "lldb/API/SBTrace.h"
-#include "lldb/API/SBTraceOptions.h"
 #include "lldb/API/SBUnixSignals.h"
 
 using namespace lldb;
@@ -312,26 +311,6 @@ size_t SBProcess::GetAsyncProfileData(char *dst, size_t dst_len) const {
   return bytes_read;
 }
 
-lldb::SBTrace SBProcess::StartTrace(SBTraceOptions &options,
-                                    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);
-}
-
 void SBProcess::ReportEventState(const SBEvent &event, SBFile out) const {
   LLDB_RECORD_METHOD_CONST(void, SBProcess, ReportEventState,
                            (const SBEvent &, SBFile), event, out);
@@ -1338,8 +1317,6 @@ void RegisterMethods<SBProcess>(Registry &R) {
                        (lldb::tid_t, lldb::addr_t));
   LLDB_REGISTER_METHOD_CONST(lldb::SBTarget, SBProcess, GetTarget, ());
   LLDB_REGISTER_METHOD(size_t, SBProcess, PutSTDIN, (const char *, size_t));
-  LLDB_REGISTER_METHOD(lldb::SBTrace, SBProcess, StartTrace,
-                       (lldb::SBTraceOptions &, lldb::SBError &));
   LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState,
                              (const lldb::SBEvent &, FILE *));
   LLDB_REGISTER_METHOD_CONST(void, SBProcess, ReportEventState,

diff  --git a/lldb/source/API/SBReproducer.cpp b/lldb/source/API/SBReproducer.cpp
index 4d25fcc4a8f6..68e632da1bde 100644
--- a/lldb/source/API/SBReproducer.cpp
+++ b/lldb/source/API/SBReproducer.cpp
@@ -117,7 +117,6 @@ SBRegistry::SBRegistry() {
   RegisterMethods<SBThreadCollection>(R);
   RegisterMethods<SBThreadPlan>(R);
   RegisterMethods<SBTrace>(R);
-  RegisterMethods<SBTraceOptions>(R);
   RegisterMethods<SBType>(R);
   RegisterMethods<SBTypeCategory>(R);
   RegisterMethods<SBTypeEnumMember>(R);

diff  --git a/lldb/source/API/SBStructuredData.cpp b/lldb/source/API/SBStructuredData.cpp
index 9a37749a64d0..97a9eadcaf07 100644
--- a/lldb/source/API/SBStructuredData.cpp
+++ b/lldb/source/API/SBStructuredData.cpp
@@ -72,10 +72,19 @@ lldb::SBError SBStructuredData::SetFromJSON(lldb::SBStream &stream) {
   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 @@ template <> void RegisterMethods<SBStructuredData>(Registry &R) {
       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, ());

diff  --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index b0b12dc73d88..6f0633288a2b 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/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,34 @@ SBEnvironment SBTarget::GetEnvironment() {
   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::CreateTrace(lldb::SBError &error) {
+  LLDB_RECORD_METHOD(lldb::SBTrace, SBTarget, CreateTrace, (lldb::SBError &),
+                     error);
+  TargetSP target_sp(GetSP());
+  error.Clear();
+
+  if (target_sp) {
+    if (llvm::Expected<lldb::TraceSP> trace_sp = target_sp->CreateTrace()) {
+      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 +2744,8 @@ void RegisterMethods<SBTarget>(Registry &R) {
                        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, CreateTrace, (lldb::SBError &));
 }
 
 }

diff  --git a/lldb/source/API/SBTrace.cpp b/lldb/source/API/SBTrace.cpp
index 242a282f033e..079c33a562c0 100644
--- a/lldb/source/API/SBTrace.cpp
+++ b/lldb/source/API/SBTrace.cpp
@@ -9,112 +9,88 @@
 #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;
-};
-
-lldb::ProcessSP SBTrace::GetSP() const { return m_opaque_wp.lock(); }
-
-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);
-
-  ProcessSP process_sp(GetSP());
-  llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
-  error.Clear();
+SBTrace::SBTrace() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBTrace); }
 
-  if (!process_sp) {
-    error.SetErrorString("invalid process");
-  } else {
-    error.SetError(
-        process_sp->GetData(GetTraceUID(), thread_id, buffer, offset));
-  }
-  return buffer.size();
-}
-
-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);
-
-  ProcessSP process_sp(GetSP());
-  llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
-  error.Clear();
-
-  if (!process_sp) {
-    error.SetErrorString("invalid process");
-  } else {
-    error.SetError(
-        process_sp->GetMetaData(GetTraceUID(), thread_id, buffer, offset));
-  }
-  return buffer.size();
+SBTrace::SBTrace(const lldb::TraceSP &trace_sp) : m_opaque_sp(trace_sp) {
+  LLDB_RECORD_CONSTRUCTOR(SBTrace, (const lldb::TraceSP &), trace_sp);
 }
 
-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));
+const char *SBTrace::GetStartConfigurationHelp() {
+  LLDB_RECORD_METHOD_NO_ARGS(const char *, SBTrace, GetStartConfigurationHelp);
+  return LLDB_RECORD_RESULT(
+      m_opaque_sp ? m_opaque_sp->GetStartConfigurationHelp() : nullptr);
 }
 
-void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
-  error.SetErrorString("deprecated");
+SBError SBTrace::Start(const SBStructuredData &configuration) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, Start, (const SBStructuredData &),
+                     configuration);
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err =
+               m_opaque_sp->Start(configuration.m_impl_up->GetObjectSP()))
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
 }
 
-lldb::user_id_t SBTrace::GetTraceUID() {
-  LLDB_RECORD_METHOD_NO_ARGS(lldb::user_id_t, SBTrace, GetTraceUID);
+SBError SBTrace::Start(const SBThread &thread,
+                       const SBStructuredData &configuration) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, Start,
+                     (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->Start(std::vector<lldb::tid_t>{thread.GetThreadID()},
+                               configuration.m_impl_up->GetObjectSP()))
+      error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  }
 
-  if (m_trace_impl_sp)
-    return m_trace_impl_sp->uid;
-  return LLDB_INVALID_UID;
+  return LLDB_RECORD_RESULT(error);
 }
 
-void SBTrace::SetTraceUID(lldb::user_id_t uid) {
-  if (m_trace_impl_sp)
-    m_trace_impl_sp->uid = uid;
+SBError SBTrace::Stop() {
+  LLDB_RECORD_METHOD_NO_ARGS(SBError, SBTrace, Stop);
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err = m_opaque_sp->Stop())
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
 }
 
-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;
+SBError SBTrace::Stop(const SBThread &thread) {
+  LLDB_RECORD_METHOD(SBError, SBTrace, Stop, (const SBThread &), thread);
+  SBError error;
+  if (!m_opaque_sp)
+    error.SetErrorString("error: invalid trace");
+  else if (llvm::Error err = m_opaque_sp->Stop({thread.GetThreadID()}))
+    error.SetErrorString(llvm::toString(std::move(err)).c_str());
+  return LLDB_RECORD_RESULT(error);
 }
 
-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();
 }
+
 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;
+  return (bool)m_opaque_sp;
 }
 
 namespace lldb_private {
@@ -122,13 +98,15 @@ namespace repro {
 
 template <>
 void RegisterMethods<SBTrace>(Registry &R) {
-  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_CONSTRUCTOR(SBTrace, (const lldb::TraceSP &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, Start, (const SBStructuredData &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, Start,
+                       (const SBThread &, const SBStructuredData &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, Stop, (const SBThread &));
+  LLDB_REGISTER_METHOD(SBError, SBTrace, Stop, ());
   LLDB_REGISTER_METHOD(bool, SBTrace, IsValid, ());
+  LLDB_REGISTER_METHOD(const char *, SBTrace, GetStartConfigurationHelp, ());
   LLDB_REGISTER_METHOD_CONST(bool, SBTrace, operator bool, ());
 }
 

diff  --git a/lldb/source/API/SBTraceOptions.cpp b/lldb/source/API/SBTraceOptions.cpp
deleted file mode 100644
index f1f5a63edf06..000000000000
--- a/lldb/source/API/SBTraceOptions.cpp
+++ /dev/null
@@ -1,159 +0,0 @@
-//===-- SBTraceOptions.cpp ------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#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>
-
-using namespace lldb;
-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);
-}
-
-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();
-}
-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, ());
-}
-
-}
-}

diff  --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp
index 4aeef67bd6a1..ad608a6010be 100644
--- a/lldb/source/Commands/CommandObjectProcess.cpp
+++ b/lldb/source/Commands/CommandObjectProcess.cpp
@@ -1581,7 +1581,7 @@ class CommandObjectProcessTraceStop : public CommandObjectParsed {
 
     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
 
-    if (llvm::Error err = trace_sp->StopProcess())
+    if (llvm::Error err = trace_sp->Stop())
       result.SetError(toString(std::move(err)));
     else
       result.SetStatus(eReturnStatusSuccessFinishResult);

diff  --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp
index 98ace0c7aa11..809dce3c4355 100644
--- a/lldb/source/Commands/CommandObjectThread.cpp
+++ b/lldb/source/Commands/CommandObjectThread.cpp
@@ -1868,11 +1868,11 @@ class CommandObjectThreadPlanPrune : public CommandObjectParsed {
 
   bool DoExecute(Args &args, CommandReturnObject &result) override {
     Process *process = m_exe_ctx.GetProcessPtr();
-    
+
     if (args.GetArgumentCount() == 0) {
       process->PruneThreadPlans();
       result.SetStatus(eReturnStatusSuccessFinishNoResult);
-      return true;  
+      return true;
     }
 
     const size_t num_args = args.GetArgumentCount();
@@ -1960,12 +1960,12 @@ class CommandObjectTraceStop : public CommandObjectMultipleThreads {
   ~CommandObjectTraceStop() override = default;
 
   bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
-                          const std::vector<lldb::tid_t> &tids) override {
+                          llvm::ArrayRef<lldb::tid_t> tids) override {
     ProcessSP process_sp = m_exe_ctx.GetProcessSP();
 
     TraceSP trace_sp = process_sp->GetTarget().GetTrace();
 
-    if (llvm::Error err = trace_sp->StopThreads(tids))
+    if (llvm::Error err = trace_sp->Stop(tids))
       result.SetError(toString(std::move(err)));
     else
       result.SetStatus(eReturnStatusSuccessFinishResult);

diff  --git a/lldb/source/Commands/CommandObjectThreadUtil.h b/lldb/source/Commands/CommandObjectThreadUtil.h
index 18f65813c639..289ffdfc1894 100644
--- a/lldb/source/Commands/CommandObjectThreadUtil.h
+++ b/lldb/source/Commands/CommandObjectThreadUtil.h
@@ -93,7 +93,7 @@ class CommandObjectMultipleThreads : public CommandObjectParsed {
   /// \return
   ///     A boolean result similar to the one expected from \a DoExecute.
   virtual bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
-                                  const std::vector<lldb::tid_t> &tids) = 0;
+                                  llvm::ArrayRef<lldb::tid_t> tids) = 0;
 };
 
 } // namespace lldb_private

diff  --git a/lldb/source/Commands/CommandObjectTrace.cpp b/lldb/source/Commands/CommandObjectTrace.cpp
index e17ae82a10ff..21574e635762 100644
--- a/lldb/source/Commands/CommandObjectTrace.cpp
+++ b/lldb/source/Commands/CommandObjectTrace.cpp
@@ -312,7 +312,7 @@ Expected<CommandObjectSP> CommandObjectTraceProxy::DoGetProxyCommandObject() {
     return createStringError(inconvertibleErrorCode(),
                              "Process must be alive.");
 
-  if (Expected<TraceSP &> trace_sp = process_sp->GetTarget().GetTraceOrCreate())
+  if (Expected<TraceSP> trace_sp = process_sp->GetTarget().GetTraceOrCreate())
     return GetDelegateCommand(**trace_sp);
   else
     return createStringError(inconvertibleErrorCode(),

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp b/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
index 00aed576eb1d..f3680a190c41 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
@@ -442,11 +442,7 @@ Error IntelPTManager::TraceStop(lldb::tid_t tid) {
 
 Error IntelPTManager::TraceStop(const TraceStopRequest &request) {
   if (request.IsProcessTracing()) {
-    if (!IsProcessTracingEnabled()) {
-      return createStringError(inconvertibleErrorCode(),
-                               "Process not currently traced");
-    }
-    ClearProcessTracing();
+    Clear();
     return Error::success();
   } else {
     Error error = Error::success();

diff  --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
index a21e5a2f04fc..fcfa1b01b1d2 100644
--- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
@@ -9,6 +9,7 @@
 #include "CommandObjectTraceStartIntelPT.h"
 
 #include "TraceIntelPT.h"
+#include "TraceIntelPTConstants.h"
 #include "lldb/Host/OptionParser.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Trace.h"
@@ -48,7 +49,7 @@ Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
 
 void CommandObjectThreadTraceStartIntelPT::CommandOptions::
     OptionParsingStarting(ExecutionContext *execution_context) {
-  m_thread_buffer_size = 4 * 1024; // 4KB
+  m_thread_buffer_size = kThreadBufferSize;
 }
 
 llvm::ArrayRef<OptionDefinition>
@@ -58,7 +59,7 @@ CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
 
 bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
     Args &command, CommandReturnObject &result,
-    const std::vector<lldb::tid_t> &tids) {
+    llvm::ArrayRef<lldb::tid_t> tids) {
   if (Error err = m_trace.Start(tids, m_options.m_thread_buffer_size))
     result.SetError(toString(std::move(err)));
   else
@@ -108,8 +109,8 @@ Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
 
 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>

diff  --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
index 7049e4ecbf40..34edbd2995f2 100644
--- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
+++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.h
@@ -53,7 +53,7 @@ class CommandObjectThreadTraceStartIntelPT
 
 protected:
   bool DoExecuteOnThreads(Args &command, CommandReturnObject &result,
-                          const std::vector<lldb::tid_t> &tids) override;
+                          llvm::ArrayRef<lldb::tid_t> tids) override;
 
   TraceIntelPT &m_trace;
   CommandOptions m_options;

diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
index b8b8012fc86a..ce7db5447f1a 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -9,6 +9,7 @@
 #include "TraceIntelPT.h"
 
 #include "CommandObjectTraceStartIntelPT.h"
+#include "TraceIntelPTConstants.h"
 #include "TraceIntelPTSessionFileParser.h"
 #include "lldb/Core/PluginManager.h"
 #include "lldb/Target/Process.h"
@@ -209,9 +210,32 @@ void TraceIntelPT::DoRefreshLiveProcessState(
 }
 
 bool TraceIntelPT::IsTraced(const Thread &thread) {
+  RefreshLiveProcessState();
   return m_thread_decoders.count(&thread);
 }
 
+const char *TraceIntelPT::GetStartConfigurationHelp() {
+  return R"(Parameters:
+
+  Note: If a parameter is not specified, a default value will be used.
+
+  - int threadBufferSize (defaults to 4096 bytes):
+    [process and thread tracing]
+    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):
+    [process tracing only]
+    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 explicitly with "thread tracing".
+    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.)";
+}
+
 Error TraceIntelPT::Start(size_t thread_buffer_size,
                           size_t total_buffer_size_limit) {
   TraceIntelPTStartRequest request;
@@ -221,7 +245,25 @@ Error TraceIntelPT::Start(size_t thread_buffer_size,
   return Trace::Start(toJSON(request));
 }
 
-llvm::Error TraceIntelPT::Start(const std::vector<lldb::tid_t> &tids,
+Error TraceIntelPT::Start(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 Start(thread_buffer_size, process_buffer_size_limit);
+}
+
+llvm::Error TraceIntelPT::Start(llvm::ArrayRef<lldb::tid_t> tids,
                                 size_t thread_buffer_size) {
   TraceIntelPTStartRequest request;
   request.threadBufferSize = thread_buffer_size;
@@ -232,6 +274,22 @@ llvm::Error TraceIntelPT::Start(const std::vector<lldb::tid_t> &tids,
   return Trace::Start(toJSON(request));
 }
 
+Error TraceIntelPT::Start(llvm::ArrayRef<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 Start(tids, thread_buffer_size);
+}
+
 Expected<std::vector<uint8_t>>
 TraceIntelPT::GetLiveThreadBuffer(lldb::tid_t tid) {
   return Trace::GetLiveThreadBinaryData(tid, "threadTraceBuffer");

diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
index 52b336777555..6bee4b827357 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -79,6 +79,8 @@ class TraceIntelPT : public Trace {
 
   bool IsTraced(const Thread &thread) override;
 
+  const char *GetStartConfigurationHelp() override;
+
   /// Start tracing a live process.
   ///
   /// \param[in] thread_buffer_size
@@ -98,7 +100,11 @@ class TraceIntelPT : public Trace {
   ///     \a llvm::Error otherwise.
   llvm::Error Start(size_t thread_buffer_size, size_t total_buffer_size_limit);
 
-  /// Start tracing a live threads.
+  /// \copydoc Trace::Start
+  llvm::Error Start(StructuredData::ObjectSP configuration =
+                        StructuredData::ObjectSP()) override;
+
+  /// Start tracing live threads.
   ///
   /// \param[in] tids
   ///     Threads to trace.
@@ -109,9 +115,14 @@ class TraceIntelPT : public Trace {
   /// \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,
+  llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids,
                     size_t thread_buffer_size);
 
+  /// \copydoc Trace::Start
+  llvm::Error Start(llvm::ArrayRef<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);
 

diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
new file mode 100644
index 000000000000..a9d0d0e30b05
--- /dev/null
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTConstants.h
@@ -0,0 +1,23 @@
+//===-- TraceIntelPTConstants.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
+
+#include <cstddef>
+
+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

diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
index 0dd835bac649..85350e4c585c 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
+++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTOptions.td
@@ -23,6 +23,7 @@ let Command = "process trace start intel pt" in {
          "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.">;
 }

diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
index 288338142263..8c837f138801 100644
--- a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
+++ b/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;

diff  --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 550aa14c4db3..e73de43ef78d 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -3082,28 +3082,39 @@ Status Target::Launch(ProcessLaunchInfo &launch_info, Stream *stream) {
 
 void Target::SetTrace(const TraceSP &trace_sp) { m_trace_sp = trace_sp; }
 
-TraceSP &Target::GetTrace() { return m_trace_sp; }
-
-llvm::Expected<TraceSP &> Target::GetTraceOrCreate() {
-  if (!m_trace_sp && m_process_sp) {
-    llvm::Expected<TraceSupportedResponse> trace_type =
-        m_process_sp->TraceSupported();
-    if (!trace_type)
-      return llvm::createStringError(
-          llvm::inconvertibleErrorCode(), "Tracing is not supported. %s",
-          llvm::toString(trace_type.takeError()).c_str());
-    if (llvm::Expected<TraceSP> trace_sp =
-            Trace::FindPluginForLiveProcess(trace_type->name, *m_process_sp))
-      m_trace_sp = *trace_sp;
-    else
-      return llvm::createStringError(
-          llvm::inconvertibleErrorCode(),
-          "Couldn't start tracing the process. %s",
-          llvm::toString(trace_sp.takeError()).c_str());
-  }
+TraceSP Target::GetTrace() { return m_trace_sp; }
+
+llvm::Expected<TraceSP> Target::CreateTrace() {
+  if (!m_process_sp)
+    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                   "A process is required for tracing");
+  if (m_trace_sp)
+    return llvm::createStringError(llvm::inconvertibleErrorCode(),
+                                   "A trace already exists for the target");
+
+  llvm::Expected<TraceSupportedResponse> trace_type =
+      m_process_sp->TraceSupported();
+  if (!trace_type)
+    return llvm::createStringError(
+        llvm::inconvertibleErrorCode(), "Tracing is not supported. %s",
+        llvm::toString(trace_type.takeError()).c_str());
+  if (llvm::Expected<TraceSP> trace_sp =
+          Trace::FindPluginForLiveProcess(trace_type->name, *m_process_sp))
+    m_trace_sp = *trace_sp;
+  else
+    return llvm::createStringError(
+        llvm::inconvertibleErrorCode(),
+        "Couldn't create a Trace object for the process. %s",
+        llvm::toString(trace_sp.takeError()).c_str());
   return m_trace_sp;
 }
 
+llvm::Expected<TraceSP> Target::GetTraceOrCreate() {
+  if (m_trace_sp)
+    return m_trace_sp;
+  return CreateTrace();
+}
+
 Status Target::Attach(ProcessAttachInfo &attach_info, Stream *stream) {
   auto state = eStateInvalid;
   auto process_sp = GetProcessSP();

diff  --git a/lldb/source/Target/Trace.cpp b/lldb/source/Target/Trace.cpp
index 9b2f39326140..ba8826331314 100644
--- a/lldb/source/Target/Trace.cpp
+++ b/lldb/source/Target/Trace.cpp
@@ -363,7 +363,7 @@ Error Trace::Start(const llvm::json::Value &request) {
   return m_live_process->TraceStart(request);
 }
 
-Error Trace::StopProcess() {
+Error Trace::Stop() {
   if (!m_live_process)
     return createStringError(inconvertibleErrorCode(),
                              "Tracing requires a live process.");
@@ -371,7 +371,7 @@ Error Trace::StopProcess() {
       TraceStopRequest(GetPluginName().AsCString()));
 }
 
-Error Trace::StopThreads(const std::vector<lldb::tid_t> &tids) {
+Error Trace::Stop(llvm::ArrayRef<lldb::tid_t> tids) {
   if (!m_live_process)
     return createStringError(inconvertibleErrorCode(),
                              "Tracing requires a live process.");
@@ -405,7 +405,7 @@ Optional<size_t> Trace::GetLiveProcessBinaryDataSize(llvm::StringRef kind) {
   return data_it->second;
 }
 
-Expected<std::vector<uint8_t>>
+Expected<ArrayRef<uint8_t>>
 Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) {
   if (!m_live_process)
     return createStringError(inconvertibleErrorCode(),
@@ -423,7 +423,7 @@ Trace::GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind) {
   return m_live_process->TraceGetBinaryData(request);
 }
 
-Expected<std::vector<uint8_t>>
+Expected<ArrayRef<uint8_t>>
 Trace::GetLiveProcessBinaryData(llvm::StringRef kind) {
   if (!m_live_process)
     return createStringError(inconvertibleErrorCode(),

diff  --git a/lldb/test/API/commands/trace/TestTraceDumpInstructions.py b/lldb/test/API/commands/trace/TestTraceDumpInstructions.py
index ddcfd16fe937..c1cb9b611d19 100644
--- a/lldb/test/API/commands/trace/TestTraceDumpInstructions.py
+++ b/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

diff  --git a/lldb/test/API/commands/trace/TestTraceLoad.py b/lldb/test/API/commands/trace/TestTraceLoad.py
index 66cb3b0a1056..0ea414f2b059 100644
--- a/lldb/test/API/commands/trace/TestTraceLoad.py
+++ b/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")

diff  --git a/lldb/test/API/commands/trace/TestTraceSchema.py b/lldb/test/API/commands/trace/TestTraceSchema.py
index d0379014cd2a..cd80c5479f72 100644
--- a/lldb/test/API/commands/trace/TestTraceSchema.py
+++ b/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"])

diff  --git a/lldb/test/API/commands/trace/TestTraceStartStop.py b/lldb/test/API/commands/trace/TestTraceStartStop.py
index 7b40c67729f8..22aff1035982 100644
--- a/lldb/test/API/commands/trace/TestTraceStartStop.py
+++ b/lldb/test/API/commands/trace/TestTraceStartStop.py
@@ -1,52 +1,76 @@
 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 testSBAPIHelp(self):
+        self.expect("file " + os.path.join(self.getSourceDir(), "intelpt-trace", "a.out"))
+        self.expect("b main")
+        self.expect("r")
+
+        help = self.getTraceOrCreate().GetStartConfigurationHelp()
+        self.assertIn("threadBufferSize", help)
+        self.assertIn("processBufferSizeLimit", help)
+
+    @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
+    def testStoppingAThread(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")
+        self.expect("n")
+        self.expect("thread trace dump instructions", substrs=["total instructions"])
+        # process stopping should stop the thread
+        self.expect("process trace stop")
+        self.expect("n")
+        self.expect("thread trace dump instructions", substrs=["not traced"])
+
 
     @skipIf(oslist=no_match(['linux']), archs=no_match(['i386', 'x86_64']))
     def testStartStopLiveThreads(self):
@@ -79,21 +103,21 @@ def testStartStopLiveThreads(self):
 
         # 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 +138,7 @@ def testStartStopLiveThreads(self):
         # 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'''])

diff  --git a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
index ce215b081ba5..4b7fbc9f388d 100644
--- a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
+++ b/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 @@ def testStartMultipleLiveThreadsWithStops(self):
 
         # 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 @@ def testStartMultipleLiveThreadsWithStops(self):
         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 @@ def testStartMultipleLiveThreadsWithStops(self):
 
         # 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 @@ def testStartMultipleLiveThreadsWithThreadStartAll(self):
 
         # 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 @@ def testStartMultipleLiveThreadsWithThreadStartAll(self):
         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()

diff  --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
index 4eeec62aee3c..cf5a1a558006 100644
--- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ b/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"


        


More information about the lldb-commits mailing list