Hey Walter,

Really excited to see that this landed! I have one post-commit review comment 
inline --

> On Sep 21, 2020, at 5:13 PM, Walter Erquinigo via lldb-commits 
> <lldb-commits@lists.llvm.org> wrote:
> 
> 
> Author: Walter Erquinigo
> Date: 2020-09-21T17:13:18-07:00
> New Revision: 74c93956e1c1f1054dfb040ce26830016e0f3095
> 
> URL: 
> https://github.com/llvm/llvm-project/commit/74c93956e1c1f1054dfb040ce26830016e0f3095
> DIFF: 
> https://github.com/llvm/llvm-project/commit/74c93956e1c1f1054dfb040ce26830016e0f3095.diff
> 
> LOG: Add a "Trace" plug-in to LLDB to add process trace support in stages.
> 
> This is the first in a series of patches that will adds a new processor trace 
> plug-in to LLDB.
> 
> The idea for this first patch to to add the plug-in interface with simple 
> commands for the trace files that can "load" and "dump" the trace 
> information. We can test the functionality and ensure people are happy with 
> the way things are done and how things are organized before moving on to 
> adding more functionality.
> 
> Processor trace information can be view in a few different ways:
> - post mortem where a trace is saved off that can be viewed later in the 
> debugger
> - gathered while a process is running and allow the user to step back in time 
> (with no variables, memory or registers) to see how each thread arrived at 
> where it is currently stopped.
> 
> This patch attempts to start with the first solution of loading a trace file 
> after the fact. The idea is that we will use a JSON file to load the trace 
> information. JSON allows us to specify information about the trace like:
> - plug-in name in LLDB
> - path to trace file
> - shared library load information so we can re-create a target and 
> symbolicate the information in the trace
> - any other info that the trace plug-in will need to be able to successfully 
> parse the trace information
>  - cpu type
>  - version info
>  - ???
> 
> A new "trace" command was added at the top level of the LLDB commmands:
> - "trace load"
> - "trace dump"
> 
> I did this because if we load trace information we don't need to have a 
> process and we might end up creating a new target for the trace information 
> that will become active. If anyone has any input on where this would be 
> better suited, please let me know. Walter Erquinigo will end up filling in 
> the Intel PT specific plug-in so that it works and is tested once we can 
> agree that the direction of this patch is the correct one, so please feel 
> free to chime in with ideas on comments!
> 
> Reviewed By: clayborg
> 
> Differential Revision: https://reviews.llvm.org/D85705
> 
> Added: 
>    lldb/include/lldb/Target/Trace.h
>    lldb/include/lldb/Target/TraceSettingsParser.h
>    lldb/source/Commands/CommandObjectTrace.cpp
>    lldb/source/Commands/CommandObjectTrace.h
>    lldb/source/Plugins/Trace/CMakeLists.txt
>    lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
>    lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
>    lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
>    lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp
>    lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h
>    lldb/source/Target/Trace.cpp
>    lldb/source/Target/TraceSettingsParser.cpp
>    lldb/test/API/commands/trace/TestTraceLoad.py
>    lldb/test/API/commands/trace/TestTraceSchema.py
>    lldb/test/API/commands/trace/intelpt-trace/3842849.trace
>    lldb/test/API/commands/trace/intelpt-trace/a.out
>    lldb/test/API/commands/trace/intelpt-trace/main.cpp
>    lldb/test/API/commands/trace/intelpt-trace/trace.json
>    lldb/test/API/commands/trace/intelpt-trace/trace_bad.json
>    lldb/test/API/commands/trace/intelpt-trace/trace_bad2.json
>    lldb/test/API/commands/trace/intelpt-trace/trace_bad3.json
> 
> Modified: 
>    lldb/include/lldb/Core/PluginManager.h
>    lldb/include/lldb/lldb-forward.h
>    lldb/include/lldb/lldb-private-interfaces.h
>    lldb/source/Commands/CMakeLists.txt
>    lldb/source/Commands/Options.td
>    lldb/source/Core/PluginManager.cpp
>    lldb/source/Interpreter/CommandInterpreter.cpp
>    lldb/source/Plugins/CMakeLists.txt
>    lldb/source/Target/CMakeLists.txt
>    lldb/source/Utility/StructuredData.cpp
> 
> Removed: 
> 
> 
> 
> ################################################################################
> diff  --git a/lldb/include/lldb/Core/PluginManager.h 
> b/lldb/include/lldb/Core/PluginManager.h
> index 5e0c9395dae0..cd962b668163 100644
> --- a/lldb/include/lldb/Core/PluginManager.h
> +++ b/lldb/include/lldb/Core/PluginManager.h
> @@ -330,6 +330,14 @@ class PluginManager {
>   static SymbolVendorCreateInstance
>   GetSymbolVendorCreateCallbackAtIndex(uint32_t idx);
> 
> +  // Trace
> +  static bool RegisterPlugin(ConstString name, const char *description,
> +                             TraceCreateInstance create_callback);
> +
> +  static bool UnregisterPlugin(TraceCreateInstance create_callback);
> +
> +  static TraceCreateInstance GetTraceCreateCallback(ConstString plugin_name);
> +
>   // UnwindAssembly
>   static bool RegisterPlugin(ConstString name, const char *description,
>                              UnwindAssemblyCreateInstance create_callback);
> 
> diff  --git a/lldb/include/lldb/Target/Trace.h 
> b/lldb/include/lldb/Target/Trace.h
> new file mode 100644
> index 000000000000..2328fba822a2
> --- /dev/null
> +++ b/lldb/include/lldb/Target/Trace.h
> @@ -0,0 +1,145 @@
> +//===-- Trace.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_TARGET_TRACE_H
> +#define LLDB_TARGET_TRACE_H
> +
> +#include "llvm/Support/JSON.h"
> +
> +#include "lldb/Core/PluginInterface.h"
> +#include "lldb/Target/TraceSettingsParser.h"
> +#include "lldb/Utility/ArchSpec.h"
> +#include "lldb/lldb-private.h"
> +
> +namespace lldb_private {
> +
> +/// \class Trace Trace.h "lldb/Target/Trace.h"
> +/// A plug-in interface definition class for trace information.
> +///
> +/// Trace plug-ins allow processor trace information to be loaded into LLDB 
> so
> +/// that the data can be dumped, used for reverse and forward stepping to 
> allow
> +/// introspection into the reason your process crashed or found its way to 
> its
> +/// current state.
> +///
> +/// Trace information can be loaded into a target without a process to allow
> +/// introspection of the trace information during post mortem analysis, such 
> as
> +/// when loading core files.
> +///
> +/// Processor trace information can also be fetched through the process
> +/// interfaces during a live debug session if your process supports gathering
> +/// this information.
> +class Trace : public PluginInterface {
> +public:
> +  ~Trace() override = default;

Does this need to be `virtual ~Trace() = ...`?

Otherwise, when a std::shared_ptr<Trace> is destroyed, the destructor for the 
derived TraceIntelPT instance won't run.

vedant

> +
> +  /// Dump the trace data that this plug-in has access to.
> +  ///
> +  /// This function will dump all of the trace data for all threads in a user
> +  /// readable format. Options for dumping can be added as this API is 
> iterated
> +  /// on.
> +  ///
> +  /// \param[in] s
> +  ///     A stream object to dump the information to.
> +  virtual void Dump(Stream *s) const = 0;
> +
> +  /// Find a trace plug-in using JSON data.
> +  ///
> +  /// When loading trace data from disk, the information for the trace data
> +  /// can be contained in multiple files and require plug-in specific
> +  /// information about the CPU. Using data like JSON provides an
> +  /// easy way to specify all of the settings and information that we will 
> need
> +  /// to load trace data into LLDB. This structured data can include:
> +  ///   - The plug-in name (this allows a specific plug-in to be selected)
> +  ///   - Architecture or target triple
> +  ///   - one or more paths to the trace data file on disk
> +  ///     - core trace data
> +  ///     - thread events or related information
> +  ///   - shared library load information to use for this trace data that
> +  ///     allows a target to be created so the trace information can be
> +  ///     symbolicated so that the trace information can be displayed to the
> +  ///     user
> +  ///     - shared library path
> +  ///     - load address
> +  ///     - information on how to fetch the shared library
> +  ///       - path to locally cached file on disk
> +  ///       - URL to download the file
> +  ///   - Any information needed to load the trace file
> +  ///     - CPU information
> +  ///     - Custom plug-in information needed to decode the trace information
> +  ///       correctly.
> +  ///
> +  /// \param[in] debugger
> +  ///     The debugger instance were new Target will be created as part of 
> the
> +  ///     JSON data parsing.
> +  ///
> +  /// \param[in] settings
> +  ///     JSON object describing a trace.
> +  ///
> +  /// \param[in] settings_dir
> +  ///     Path to a directory used to resolve relative paths in the JSON 
> data.
> +  ///     If the JSON data is defined in a file, this should be the
> +  ///     folder containing it.
> +  static llvm::Expected<lldb::TraceSP>
> +  FindPlugin(Debugger &debugger, const llvm::json::Value &settings,
> +             llvm::StringRef settings_dir);
> +
> +  /// Create an instance of trace plug-in by name.
> +  ///
> +  /// \param[in] plugin_name
> +  ///     Name of the trace plugin.
> +  static llvm::Expected<lldb::TraceSP> FindPlugin(llvm::StringRef 
> plugin_name);
> +
> +  /// Parse the JSON settings and create the corresponding \a Target
> +  /// objects. In case of an error, no targets are created.
> +  ///
> +  /// \param[in] debugger
> +  ///   The debugger instance where the targets are created.
> +  ///
> +  /// \param[in] settings
> +  ///     JSON object describing a trace.
> +  ///
> +  /// \param[in] settings_dir
> +  ///     Path to a directory used to resolve relative paths in the JSON 
> data.
> +  ///     If the JSON data is defined in a file, this should be the
> +  ///     folder containing it.
> +  ///
> +  /// \return
> +  ///   An error object containing the reason if there is a failure.
> +  llvm::Error ParseSettings(Debugger &debugger,
> +                            const llvm::json::Object &settings,
> +                            llvm::StringRef settings_dir);
> +
> +  /// Get the JSON schema of the settings for the trace plug-in.
> +  llvm::StringRef GetSchema();
> +
> +protected:
> +  Trace() {}
> +
> +  /// The actual plug-in should define its own implementation of \a
> +  /// TraceSettingsParser for doing any custom parsing.
> +  virtual std::unique_ptr<lldb_private::TraceSettingsParser> CreateParser() 
> = 0;
> +
> +private:
> +  Trace(const Trace &) = delete;
> +  const Trace &operator=(const Trace &) = delete;
> +
> +protected:
> +  friend class TraceSettingsParser;
> +  /// JSON object that holds all settings for this trace session.
> +  llvm::json::Object m_settings;
> +  /// The directory that contains the settings file.
> +  std::string m_settings_dir;
> +
> +  std::map<lldb::pid_t, std::map<lldb::tid_t, lldb_private::FileSpec>>
> +      m_thread_to_trace_file_map;
> +  std::vector<lldb::TargetSP> m_targets;
> +};
> +
> +} // namespace lldb_private
> +
> +#endif // LLDB_TARGET_TRACE_H
> 
> diff  --git a/lldb/include/lldb/Target/TraceSettingsParser.h 
> b/lldb/include/lldb/Target/TraceSettingsParser.h
> new file mode 100644
> index 000000000000..bc18c107ed83
> --- /dev/null
> +++ b/lldb/include/lldb/Target/TraceSettingsParser.h
> @@ -0,0 +1,136 @@
> +//===-- TraceSettingsParser.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_TARGET_TRACE_SETTINGS_PARSER_H
> +#define LLDB_TARGET_TRACE_SETTINGS_PARSER_H
> +
> +#include "llvm/ADT/Optional.h"
> +
> +#include "lldb/Target/Trace.h"
> +#include "lldb/lldb-private.h"
> +
> +namespace lldb_private {
> +
> +/// \class TraceSettingsParser TraceSettingsParser.h
> +/// A plug-in interface definition class for parsing \a Trace settings.
> +///
> +/// As \a Trace plug-ins support plug-in specific settings, this class 
> should be
> +/// overriden and implement the plug-in specific parsing logic.
> +class TraceSettingsParser {
> +public:
> +  TraceSettingsParser(Trace &trace) : m_trace(trace) {}
> +
> +  virtual ~TraceSettingsParser() = default;
> +
> +  /// Get the JSON schema of the settings for the trace plug-in.
> +  llvm::StringRef GetSchema();
> +
> +  /// Parse the structured data settings and create the corresponding \a 
> Target
> +  /// objects. In case of and error, no targets are created.
> +  ///
> +  /// \param[in] debugger
> +  ///   The debugger instance where the targets are created.
> +  ///
> +  /// \param[in] settings
> +  ///   The settings to parse.
> +  ///
> +  /// \param[in] settings_dir
> +  ///   The directory that contains the settings file used to resolve 
> relative
> +  ///   paths.
> +  ///
> +  /// \return
> +  ///   An error object containing the reason if there is a failure.
> +  llvm::Error ParseSettings(Debugger &debugger,
> +                            const llvm::json::Object &settings,
> +                            llvm::StringRef settings_dir);
> +
> +protected:
> +  /// Method that should be overriden by implementations of this class to
> +  /// provide the specific plug-in schema inside the "trace" section of the
> +  /// global schema.
> +  virtual llvm::StringRef GetPluginSchema() = 0;
> +
> +  /// Method that should be overriden to parse the plug-in specific settings.
> +  ///
> +  /// \return
> +  ///   An error object containing the reason if there is a failure.
> +  virtual llvm::Error ParsePluginSettings() = 0;
> +
> +private:
> +  /// Resolve non-absolute paths relativejto the settings folder
> +  void NormalizePath(lldb_private::FileSpec &file_spec);
> +  llvm::Error ParseProcess(lldb_private::Debugger &debugger,
> +                           const llvm::json::Object &process);
> +  llvm::Error ParseProcesses(lldb_private::Debugger &debugger);
> +  llvm::Error ParseThread(lldb::ProcessSP &process_sp,
> +                          const llvm::json::Object &thread);
> +  llvm::Error ParseThreads(lldb::ProcessSP &process_sp,
> +                           const llvm::json::Object &process);
> +  llvm::Error ParseModule(lldb::TargetSP &target_sp,
> +                          const llvm::json::Object &module);
> +  llvm::Error ParseModules(lldb::TargetSP &target_sp,
> +                           const llvm::json::Object &process);
> +  llvm::Error ParseSettingsImpl(lldb_private::Debugger &debugger);
> +
> +  Trace &m_trace;
> +
> +protected:
> +  /// Objects created as product of the parsing
> +  /// \{
> +  /// JSON object that holds all settings for this trace session.
> +  llvm::json::Object m_settings;
> +  /// The directory that contains the settings file.
> +  std::string m_settings_dir;
> +
> +  std::map<lldb::pid_t, std::map<lldb::tid_t, lldb_private::FileSpec>>
> +      m_thread_to_trace_file_map;
> +  std::vector<lldb::TargetSP> m_targets;
> +  /// \}
> +};
> +
> +} // namespace lldb_private
> +
> +namespace json_helpers {
> +/// JSON parsing helpers based on \a llvm::Expected.
> +/// \{
> +llvm::Error CreateWrongTypeError(const llvm::json::Value &value,
> +                                 llvm::StringRef type);
> +
> +llvm::Expected<int64_t> ToIntegerOrError(const llvm::json::Value &value);
> +
> +llvm::Expected<llvm::StringRef> ToStringOrError(const llvm::json::Value 
> &value);
> +
> +llvm::Expected<const llvm::json::Array &>
> +ToArrayOrError(const llvm::json::Value &value);
> +
> +llvm::Expected<const llvm::json::Object &>
> +ToObjectOrError(const llvm::json::Value &value);
> +
> +llvm::Error CreateMissingKeyError(llvm::json::Object obj, llvm::StringRef 
> key);
> +
> +llvm::Expected<const llvm::json::Value &>
> +GetValueOrError(const llvm::json::Object &obj, llvm::StringRef key);
> +
> +llvm::Expected<int64_t> GetIntegerOrError(const llvm::json::Object &obj,
> +                                          llvm::StringRef key);
> +
> +llvm::Expected<llvm::StringRef> GetStringOrError(const llvm::json::Object 
> &obj,
> +                                                 llvm::StringRef key);
> +
> +llvm::Expected<const llvm::json::Array &>
> +GetArrayOrError(const llvm::json::Object &obj, llvm::StringRef key);
> +
> +llvm::Expected<const llvm::json::Object &>
> +GetObjectOrError(const llvm::json::Object &obj, llvm::StringRef key);
> +
> +llvm::Expected<llvm::Optional<llvm::StringRef>>
> +GetOptionalStringOrError(const llvm::json::Object &obj, llvm::StringRef key);
> +/// \}
> +} // namespace json_helpers
> +
> +#endif // LLDB_TARGET_TRACE_SETTINGS_PARSER_H
> 
> diff  --git a/lldb/include/lldb/lldb-forward.h 
> b/lldb/include/lldb/lldb-forward.h
> index 6682413820d6..0a7f08c95571 100644
> --- a/lldb/include/lldb/lldb-forward.h
> +++ b/lldb/include/lldb/lldb-forward.h
> @@ -226,6 +226,8 @@ class ThreadPlanStepRange;
> class ThreadPlanStepThrough;
> class ThreadPlanTracer;
> class ThreadSpec;
> +class Trace;
> +class TraceSettingsParser;
> class TraceOptions;
> class Type;
> class TypeAndOrName;
> @@ -432,6 +434,7 @@ typedef std::shared_ptr<lldb_private::ThreadCollection> 
> ThreadCollectionSP;
> typedef std::shared_ptr<lldb_private::ThreadPlan> ThreadPlanSP;
> 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;
> 
> diff  --git a/lldb/include/lldb/lldb-private-interfaces.h 
> b/lldb/include/lldb/lldb-private-interfaces.h
> index 1568e7a3cb51..9b47b73b772c 100644
> --- a/lldb/include/lldb/lldb-private-interfaces.h
> +++ b/lldb/include/lldb/lldb-private-interfaces.h
> @@ -18,6 +18,12 @@
> #include <memory>
> #include <set>
> 
> +namespace llvm {
> +namespace json {
> +class Object;
> +}
> +} // namespace llvm
> +
> namespace lldb_private {
> typedef lldb::ABISP (*ABICreateInstance)(lldb::ProcessSP process_sp,
>                                          const ArchSpec &arch);
> @@ -104,6 +110,7 @@ typedef lldb::REPLSP (*REPLCreateInstance)(Status &error,
>                                            const char *repl_options);
> typedef int (*ComparisonFunction)(const void *, const void *);
> typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
> +typedef lldb::TraceSP (*TraceCreateInstance)();
> 
> } // namespace lldb_private
> 
> 
> diff  --git a/lldb/source/Commands/CMakeLists.txt 
> b/lldb/source/Commands/CMakeLists.txt
> index 3e57670fd040..e29a2414d8ff 100644
> --- a/lldb/source/Commands/CMakeLists.txt
> +++ b/lldb/source/Commands/CMakeLists.txt
> @@ -31,6 +31,7 @@ add_lldb_library(lldbCommands
>   CommandObjectStats.cpp
>   CommandObjectTarget.cpp
>   CommandObjectThread.cpp
> +  CommandObjectTrace.cpp
>   CommandObjectType.cpp
>   CommandObjectVersion.cpp
>   CommandObjectWatchpoint.cpp
> 
> diff  --git a/lldb/source/Commands/CommandObjectTrace.cpp 
> b/lldb/source/Commands/CommandObjectTrace.cpp
> new file mode 100644
> index 000000000000..c622914e0d79
> --- /dev/null
> +++ b/lldb/source/Commands/CommandObjectTrace.cpp
> @@ -0,0 +1,292 @@
> +//===-- CommandObjectTrace.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 "CommandObjectTrace.h"
> +
> +#include "llvm/Support/JSON.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +
> +#include "lldb/Core/Debugger.h"
> +#include "lldb/Host/OptionParser.h"
> +#include "lldb/Interpreter/CommandInterpreter.h"
> +#include "lldb/Interpreter/CommandObject.h"
> +#include "lldb/Interpreter/CommandReturnObject.h"
> +#include "lldb/Interpreter/OptionArgParser.h"
> +#include "lldb/Interpreter/OptionGroupFormat.h"
> +#include "lldb/Interpreter/OptionValueBoolean.h"
> +#include "lldb/Interpreter/OptionValueLanguage.h"
> +#include "lldb/Interpreter/OptionValueString.h"
> +#include "lldb/Interpreter/Options.h"
> +#include "lldb/Target/Trace.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +using namespace llvm;
> +
> +// CommandObjectTraceLoad
> +#define LLDB_OPTIONS_trace_load
> +#include "CommandOptions.inc"
> +
> +#pragma mark CommandObjectTraceLoad
> +
> +class CommandObjectTraceLoad : public CommandObjectParsed {
> +public:
> +  class CommandOptions : public Options {
> +  public:
> +    CommandOptions() : Options() { OptionParsingStarting(nullptr); }
> +
> +    ~CommandOptions() override = default;
> +
> +    Status SetOptionValue(uint32_t option_idx, StringRef option_arg,
> +                          ExecutionContext *execution_context) override {
> +      Status error;
> +      const int short_option = m_getopt_table[option_idx].val;
> +
> +      switch (short_option) {
> +      case 'v': {
> +        m_verbose = true;
> +        break;
> +      }
> +      default:
> +        llvm_unreachable("Unimplemented option");
> +      }
> +      return error;
> +    }
> +
> +    void OptionParsingStarting(ExecutionContext *execution_context) override 
> {
> +      m_verbose = false;
> +    }
> +
> +    ArrayRef<OptionDefinition> GetDefinitions() override {
> +      return makeArrayRef(g_trace_load_options);
> +    }
> +
> +    bool m_verbose; // Enable verbose logging for debugging purposes.
> +  };
> +
> +  CommandObjectTraceLoad(CommandInterpreter &interpreter)
> +      : CommandObjectParsed(interpreter, "trace load",
> +                            "Load processor trace data from a JSON file.",
> +                            "trace load"),
> +        m_options() {}
> +
> +  ~CommandObjectTraceLoad() override = default;
> +
> +  Options *GetOptions() override { return &m_options; }
> +
> +protected:
> +  bool DoExecute(Args &command, CommandReturnObject &result) override {
> +    if (command.size() != 1) {
> +      result.AppendError("a single path to a JSON file containing trace "
> +                         "information is required");
> +      result.SetStatus(eReturnStatusFailed);
> +      return false;
> +    }
> +
> +    auto end_with_failure = [&result](llvm::Error err) -> bool {
> +      result.AppendErrorWithFormat("%s\n",
> +                                   llvm::toString(std::move(err)).c_str());
> +      result.SetStatus(eReturnStatusFailed);
> +      return false;
> +    };
> +
> +    FileSpec json_file(command[0].ref());
> +
> +    auto buffer_or_error = llvm::MemoryBuffer::getFile(json_file.GetPath());
> +    if (!buffer_or_error) {
> +      return end_with_failure(llvm::createStringError(
> +          std::errc::invalid_argument, "could not open input file: %s - %s.",
> +          json_file.GetPath().c_str(),
> +          buffer_or_error.getError().message().c_str()));
> +    }
> +
> +    llvm::Expected<json::Value> settings =
> +        json::parse(buffer_or_error.get()->getBuffer().str());
> +    if (!settings)
> +      return end_with_failure(settings.takeError());
> +
> +    if (Expected<lldb::TraceSP> traceOrErr = Trace::FindPlugin(
> +            GetDebugger(), *settings, json_file.GetDirectory().AsCString())) 
> {
> +      lldb::TraceSP trace_sp = traceOrErr.get();
> +      if (m_options.m_verbose)
> +        result.AppendMessageWithFormat("loading trace with plugin %s\n",
> +                                       
> trace_sp->GetPluginName().AsCString());
> +    } else
> +      return end_with_failure(traceOrErr.takeError());
> +
> +    result.SetStatus(eReturnStatusSuccessFinishResult);
> +    return true;
> +  }
> +
> +  CommandOptions m_options;
> +};
> +
> +// CommandObjectTraceDump
> +#define LLDB_OPTIONS_trace_dump
> +#include "CommandOptions.inc"
> +
> +#pragma mark CommandObjectTraceDump
> +
> +class CommandObjectTraceDump : public CommandObjectParsed {
> +public:
> +  class CommandOptions : public Options {
> +  public:
> +    CommandOptions() : Options() { OptionParsingStarting(nullptr); }
> +
> +    ~CommandOptions() override = default;
> +
> +    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
> +                          ExecutionContext *execution_context) override {
> +      Status error;
> +      const int short_option = m_getopt_table[option_idx].val;
> +
> +      switch (short_option) {
> +      case 'v': {
> +        m_verbose = true;
> +        break;
> +      }
> +      default:
> +        llvm_unreachable("Unimplemented option");
> +      }
> +      return error;
> +    }
> +
> +    void OptionParsingStarting(ExecutionContext *execution_context) override 
> {
> +      m_verbose = false;
> +    }
> +
> +    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
> +      return llvm::makeArrayRef(g_trace_dump_options);
> +    }
> +
> +    bool m_verbose; // Enable verbose logging for debugging purposes.
> +  };
> +
> +  CommandObjectTraceDump(CommandInterpreter &interpreter)
> +      : CommandObjectParsed(interpreter, "trace dump",
> +                            "Dump the loaded processor trace data.",
> +                            "trace dump"),
> +        m_options() {}
> +
> +  ~CommandObjectTraceDump() override = default;
> +
> +  Options *GetOptions() override { return &m_options; }
> +
> +protected:
> +  bool DoExecute(Args &command, CommandReturnObject &result) override {
> +    Status error;
> +    // TODO: fill in the dumping code here!
> +    if (error.Success()) {
> +      result.SetStatus(eReturnStatusSuccessFinishResult);
> +    } else {
> +      result.AppendErrorWithFormat("%s\n", error.AsCString());
> +      result.SetStatus(eReturnStatusFailed);
> +    }
> +    return result.Succeeded();
> +  }
> +
> +  CommandOptions m_options;
> +};
> +
> +// CommandObjectTraceSchema
> +#define LLDB_OPTIONS_trace_schema
> +#include "CommandOptions.inc"
> +
> +#pragma mark CommandObjectTraceSchema
> +
> +class CommandObjectTraceSchema : public CommandObjectParsed {
> +public:
> +  class CommandOptions : public Options {
> +  public:
> +    CommandOptions() : Options() { OptionParsingStarting(nullptr); }
> +
> +    ~CommandOptions() override = default;
> +
> +    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
> +                          ExecutionContext *execution_context) override {
> +      Status error;
> +      const int short_option = m_getopt_table[option_idx].val;
> +
> +      switch (short_option) {
> +      case 'v': {
> +        m_verbose = true;
> +        break;
> +      }
> +      default:
> +        llvm_unreachable("Unimplemented option");
> +      }
> +      return error;
> +    }
> +
> +    void OptionParsingStarting(ExecutionContext *execution_context) override 
> {
> +      m_verbose = false;
> +    }
> +
> +    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
> +      return llvm::makeArrayRef(g_trace_schema_options);
> +    }
> +
> +    bool m_verbose; // Enable verbose logging for debugging purposes.
> +  };
> +
> +  CommandObjectTraceSchema(CommandInterpreter &interpreter)
> +      : CommandObjectParsed(interpreter, "trace schema",
> +                            "Show the schema of the given trace plugin.",
> +                            "trace schema <plug-in>"),
> +        m_options() {}
> +
> +  ~CommandObjectTraceSchema() override = default;
> +
> +  Options *GetOptions() override { return &m_options; }
> +
> +protected:
> +  bool DoExecute(Args &command, CommandReturnObject &result) override {
> +    Status error;
> +    if (command.empty()) {
> +      result.SetError(
> +          "trace schema cannot be invoked without a plug-in as argument");
> +      return false;
> +    }
> +
> +    StringRef plugin_name(command[0].c_str());
> +
> +    if (Expected<lldb::TraceSP> traceOrErr = Trace::FindPlugin(plugin_name)) 
> {
> +      lldb::TraceSP trace_sp = traceOrErr.get();
> +      result.AppendMessage(trace_sp->GetSchema());
> +    } else {
> +      error.SetErrorString(llvm::toString(traceOrErr.takeError()));
> +    }
> +
> +    if (error.Success()) {
> +      result.SetStatus(eReturnStatusSuccessFinishResult);
> +    } else {
> +      result.AppendErrorWithFormat("%s\n", error.AsCString());
> +      result.SetStatus(eReturnStatusFailed);
> +    }
> +    return result.Succeeded();
> +  }
> +
> +  CommandOptions m_options;
> +};
> +
> +// CommandObjectTrace
> +
> +CommandObjectTrace::CommandObjectTrace(CommandInterpreter &interpreter)
> +    : CommandObjectMultiword(interpreter, "trace",
> +                             "Commands for loading and using processor "
> +                             "trace information.",
> +                             "trace [<sub-command-options>]") {
> +  LoadSubCommand("load",
> +                 CommandObjectSP(new CommandObjectTraceLoad(interpreter)));
> +  LoadSubCommand("dump",
> +                 CommandObjectSP(new CommandObjectTraceDump(interpreter)));
> +  LoadSubCommand("schema",
> +                 CommandObjectSP(new CommandObjectTraceSchema(interpreter)));
> +}
> +
> +CommandObjectTrace::~CommandObjectTrace() = default;
> 
> diff  --git a/lldb/source/Commands/CommandObjectTrace.h 
> b/lldb/source/Commands/CommandObjectTrace.h
> new file mode 100644
> index 000000000000..2dca0e26b243
> --- /dev/null
> +++ b/lldb/source/Commands/CommandObjectTrace.h
> @@ -0,0 +1,25 @@
> +//===-- CommandObjectTrace.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_COMMANDS_COMMANDOBJECTTRACE_H
> +#define LLDB_SOURCE_COMMANDS_COMMANDOBJECTTRACE_H
> +
> +#include "lldb/Interpreter/CommandObjectMultiword.h"
> +
> +namespace lldb_private {
> +
> +class CommandObjectTrace : public CommandObjectMultiword {
> +public:
> +  CommandObjectTrace(CommandInterpreter &interpreter);
> +
> +  ~CommandObjectTrace() override;
> +};
> +
> +} // namespace lldb_private
> +
> +#endif // LLDB_SOURCE_COMMANDS_COMMANDOBJECTTRACE_H
> 
> diff  --git a/lldb/source/Commands/Options.td 
> b/lldb/source/Commands/Options.td
> index b41b1871ad81..f2401dc5f326 100644
> --- a/lldb/source/Commands/Options.td
> +++ b/lldb/source/Commands/Options.td
> @@ -1175,3 +1175,19 @@ let Command = "watchpoint delete" in {
>   def watchpoint_delete_force : Option<"force", "f">, Group<1>,
>     Desc<"Delete all watchpoints without querying for confirmation.">;
> }
> +
> +let Command = "trace load" in {
> +  def trace_load_verbose : Option<"verbose", "v">, Group<1>,
> +    Desc<"Show verbose trace load logging for debugging the plug-in "
> +    "implementation.">;
> +}
> +
> +let Command = "trace dump" in {
> +  def trace_dump_verbose : Option<"verbose", "v">, Group<1>,
> +    Desc<"Show verbose trace information.">;
> +}
> +
> +let Command = "trace schema" in {
> +  def trace_schema_verbose : Option<"verbose", "v">, Group<1>,
> +    Desc<"Show verbose trace schema logging for debugging the plug-in.">;
> +}
> 
> diff  --git a/lldb/source/Core/PluginManager.cpp 
> b/lldb/source/Core/PluginManager.cpp
> index 3545ef66cc38..e025aa1d3cdb 100644
> --- a/lldb/source/Core/PluginManager.cpp
> +++ b/lldb/source/Core/PluginManager.cpp
> @@ -1005,6 +1005,30 @@ 
> PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) {
>   return GetSymbolVendorInstances().GetCallbackAtIndex(idx);
> }
> 
> +#pragma mark Trace
> +
> +typedef PluginInstance<TraceCreateInstance> TraceInstance;
> +typedef PluginInstances<TraceInstance> TraceInstances;
> +
> +static TraceInstances &GetTraceInstances() {
> +  static TraceInstances g_instances;
> +  return g_instances;
> +}
> +
> +bool PluginManager::RegisterPlugin(ConstString name, const char *description,
> +                                   TraceCreateInstance create_callback) {
> +  return GetTraceInstances().RegisterPlugin(name, description, 
> create_callback);
> +}
> +
> +bool PluginManager::UnregisterPlugin(TraceCreateInstance create_callback) {
> +  return GetTraceInstances().UnregisterPlugin(create_callback);
> +}
> +
> +TraceCreateInstance
> +PluginManager::GetTraceCreateCallback(ConstString plugin_name) {
> +  return GetTraceInstances().GetCallbackForName(plugin_name);
> +}
> +
> #pragma mark UnwindAssembly
> 
> typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance;
> 
> diff  --git a/lldb/source/Interpreter/CommandInterpreter.cpp 
> b/lldb/source/Interpreter/CommandInterpreter.cpp
> index 1f6746800097..88b07d5e3a0a 100644
> --- a/lldb/source/Interpreter/CommandInterpreter.cpp
> +++ b/lldb/source/Interpreter/CommandInterpreter.cpp
> @@ -37,6 +37,7 @@
> #include "Commands/CommandObjectStats.h"
> #include "Commands/CommandObjectTarget.h"
> #include "Commands/CommandObjectThread.h"
> +#include "Commands/CommandObjectTrace.h"
> #include "Commands/CommandObjectType.h"
> #include "Commands/CommandObjectVersion.h"
> #include "Commands/CommandObjectWatchpoint.h"
> @@ -512,6 +513,7 @@ void CommandInterpreter::LoadCommandDictionary() {
>   REGISTER_COMMAND_OBJECT("statistics", CommandObjectStats);
>   REGISTER_COMMAND_OBJECT("target", CommandObjectMultiwordTarget);
>   REGISTER_COMMAND_OBJECT("thread", CommandObjectMultiwordThread);
> +  REGISTER_COMMAND_OBJECT("trace", CommandObjectTrace);
>   REGISTER_COMMAND_OBJECT("type", CommandObjectType);
>   REGISTER_COMMAND_OBJECT("version", CommandObjectVersion);
>   REGISTER_COMMAND_OBJECT("watchpoint", CommandObjectMultiwordWatchpoint);
> 
> diff  --git a/lldb/source/Plugins/CMakeLists.txt 
> b/lldb/source/Plugins/CMakeLists.txt
> index d91ba749f86c..3da23eca0773 100644
> --- a/lldb/source/Plugins/CMakeLists.txt
> +++ b/lldb/source/Plugins/CMakeLists.txt
> @@ -19,6 +19,7 @@ add_subdirectory(StructuredData)
> add_subdirectory(SymbolFile)
> add_subdirectory(SystemRuntime)
> add_subdirectory(SymbolVendor)
> +add_subdirectory(Trace)
> add_subdirectory(TypeSystem)
> add_subdirectory(UnwindAssembly)
> 
> 
> diff  --git a/lldb/source/Plugins/Trace/CMakeLists.txt 
> b/lldb/source/Plugins/Trace/CMakeLists.txt
> new file mode 100644
> index 000000000000..edbb5f14b4e6
> --- /dev/null
> +++ b/lldb/source/Plugins/Trace/CMakeLists.txt
> @@ -0,0 +1,5 @@
> +option(LLDB_BUILD_INTEL_PT "Enable Building of Intel(R) Processor Trace 
> Tool" OFF)
> +
> +if (LLDB_BUILD_INTEL_PT)
> +  add_subdirectory(intel-pt)
> +endif()
> 
> diff  --git a/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt 
> b/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
> new file mode 100644
> index 000000000000..aeaba0cdeb20
> --- /dev/null
> +++ b/lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
> @@ -0,0 +1,23 @@
> +if (NOT LIBIPT_INCLUDE_PATH)
> +  message (FATAL_ERROR "libipt include path not provided")
> +endif()
> +
> +if (NOT EXISTS "${LIBIPT_INCLUDE_PATH}")
> +  message (FATAL_ERROR "invalid libipt include path provided")
> +endif()
> +include_directories(${LIBIPT_INCLUDE_PATH})
> +
> +find_library(LIBIPT_LIBRARY ipt PATHS ${LIBIPT_LIBRARY_PATH} REQUIRED)
> +
> +add_lldb_library(lldbPluginTraceIntelPT PLUGIN
> +  TraceIntelPT.cpp
> +  TraceIntelPTSettingsParser.cpp
> +
> +  LINK_LIBS
> +    lldbCore
> +    lldbSymbol
> +    lldbTarget
> +    ${LIBIPT_LIBRARY}
> +  LINK_COMPONENTS
> +    Support
> +  )
> 
> diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp 
> b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
> new file mode 100644
> index 000000000000..13a990470626
> --- /dev/null
> +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
> @@ -0,0 +1,51 @@
> +//===-- TraceIntelPT.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 "TraceIntelPT.h"
> +
> +#include "TraceIntelPTSettingsParser.h"
> +#include "lldb/Core/PluginManager.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +using namespace llvm;
> +
> +LLDB_PLUGIN_DEFINE_ADV(TraceIntelPT, TraceIntelPT)
> +
> +void TraceIntelPT::Initialize() {
> +  PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor 
> Trace",
> +                                CreateInstance);
> +}
> +
> +void TraceIntelPT::Terminate() {
> +  PluginManager::UnregisterPlugin(CreateInstance);
> +}
> +
> +ConstString TraceIntelPT::GetPluginNameStatic() {
> +  static ConstString g_name("intel-pt");
> +  return g_name;
> +}
> +
> +std::unique_ptr<lldb_private::TraceSettingsParser>
> +TraceIntelPT::CreateParser() {
> +  return std::make_unique<TraceIntelPTSettingsParser>(*this);
> +}
> +
> +//------------------------------------------------------------------
> +// PluginInterface protocol
> +//------------------------------------------------------------------
> +
> +ConstString TraceIntelPT::GetPluginName() { return GetPluginNameStatic(); }
> +
> +uint32_t TraceIntelPT::GetPluginVersion() { return 1; }
> +
> +void TraceIntelPT::Dump(lldb_private::Stream *s) const {}
> +
> +lldb::TraceSP TraceIntelPT::CreateInstance() {
> +  return lldb::TraceSP(new TraceIntelPT());
> +}
> 
> diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h 
> b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
> new file mode 100644
> index 000000000000..edc781e08ad4
> --- /dev/null
> +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
> @@ -0,0 +1,48 @@
> +//===-- TraceIntelPT.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 liblldb_TraceIntelPT_h_
> +#define liblldb_TraceIntelPT_h_
> +
> +#include "intel-pt.h"
> +#include "llvm/ADT/Optional.h"
> +
> +#include "TraceIntelPTSettingsParser.h"
> +#include "lldb/Target/Trace.h"
> +#include "lldb/lldb-private.h"
> +
> +class TraceIntelPT : public lldb_private::Trace {
> +public:
> +  void Dump(lldb_private::Stream *s) const override;
> +
> +  /// PluginInterface protocol
> +  /// \{
> +  lldb_private::ConstString GetPluginName() override;
> +
> +  static void Initialize();
> +
> +  static void Terminate();
> +
> +  static lldb::TraceSP CreateInstance();
> +
> +  static lldb_private::ConstString GetPluginNameStatic();
> +
> +  uint32_t GetPluginVersion() override;
> +  /// \}
> +
> +protected:
> +  TraceIntelPT() : Trace() {}
> +
> +  std::unique_ptr<lldb_private::TraceSettingsParser> CreateParser() override;
> +
> +private:
> +  friend class TraceIntelPTSettingsParser;
> +  pt_cpu m_pt_cpu;
> +};
> +
> +#endif // liblldb_TraceIntelPT_h_
> 
> diff  --git 
> a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp 
> b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp
> new file mode 100644
> index 000000000000..c8f90c9a978d
> --- /dev/null
> +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp
> @@ -0,0 +1,69 @@
> +//===-- TraceIntelPTSettingsParser.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 "TraceIntelPTSettingsParser.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +using namespace llvm;
> +
> +StringRef TraceIntelPTSettingsParser::GetPluginSchema() {
> +  return R"({
> +  "type": "intel-pt",
> +  "pt_cpu": {
> +    "vendor": "intel" | "unknown",
> +    "family": integer,
> +    "model": integer,
> +    "stepping": integer
> +  }
> +})";
> +}
> +
> +llvm::Error TraceIntelPTSettingsParser::ParsePTCPU(const json::Object 
> &trace) {
> +  llvm::Expected<const json::Object &> pt_cpu =
> +      json_helpers::GetObjectOrError(trace, "pt_cpu");
> +  if (!pt_cpu)
> +    return pt_cpu.takeError();
> +
> +  llvm::Expected<llvm::StringRef> vendor =
> +      json_helpers::GetStringOrError(*pt_cpu, "vendor");
> +  if (!vendor)
> +    return vendor.takeError();
> +
> +  llvm::Expected<int64_t> family =
> +      json_helpers::GetIntegerOrError(*pt_cpu, "family");
> +  if (!family)
> +    return family.takeError();
> +
> +  llvm::Expected<int64_t> model =
> +      json_helpers::GetIntegerOrError(*pt_cpu, "model");
> +  if (!model)
> +    return model.takeError();
> +
> +  llvm::Expected<int64_t> stepping =
> +      json_helpers::GetIntegerOrError(*pt_cpu, "stepping");
> +  if (!stepping)
> +    return stepping.takeError();
> +
> +  m_pt_cpu = {vendor->compare("intel") == 0 ? pcv_intel : pcv_unknown,
> +              static_cast<uint16_t>(*family), static_cast<uint8_t>(*model),
> +              static_cast<uint8_t>(*stepping)};
> +  return llvm::Error::success();
> +}
> +
> +llvm::Error TraceIntelPTSettingsParser::ParsePluginSettings() {
> +  llvm::Expected<const json::Object &> trace =
> +      json_helpers::GetObjectOrError(m_settings, "trace");
> +  if (!trace)
> +    return trace.takeError();
> +  if (llvm::Error err = ParsePTCPU(*trace))
> +    return err;
> +
> +  m_trace.m_pt_cpu = m_pt_cpu;
> +  return llvm::Error::success();
> +}
> 
> diff  --git a/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h 
> b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h
> new file mode 100644
> index 000000000000..b8aaa106b10d
> --- /dev/null
> +++ b/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h
> @@ -0,0 +1,39 @@
> +//===-- TraceIntelPTSettingsParser.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 liblldb_TraceIntelPTSettingsParser_h_
> +#define liblldb_TraceIntelPTSettingsParser_h_
> +
> +#include "intel-pt.h"
> +
> +#include "TraceIntelPT.h"
> +#include "lldb/Target/TraceSettingsParser.h"
> +#include "lldb/Utility/StructuredData.h"
> +
> +class TraceIntelPT;
> +
> +class TraceIntelPTSettingsParser : public lldb_private::TraceSettingsParser {
> +
> +public:
> +  TraceIntelPTSettingsParser(TraceIntelPT &trace)
> +      : lldb_private::TraceSettingsParser((lldb_private::Trace &)trace),
> +        m_trace(trace) {}
> +
> +protected:
> +  llvm::StringRef GetPluginSchema() override;
> +
> +  llvm::Error ParsePluginSettings() override;
> +
> +private:
> +  llvm::Error ParsePTCPU(const llvm::json::Object &trace);
> +
> +  TraceIntelPT &m_trace;
> +  pt_cpu m_pt_cpu;
> +};
> +
> +#endif // liblldb_TraceIntelPTSettingsParser_h_
> 
> diff  --git a/lldb/source/Target/CMakeLists.txt 
> b/lldb/source/Target/CMakeLists.txt
> index ca80b5b64778..c3a09c6c0098 100644
> --- a/lldb/source/Target/CMakeLists.txt
> +++ b/lldb/source/Target/CMakeLists.txt
> @@ -65,6 +65,8 @@ add_lldb_library(lldbTarget
>   ThreadPlanTracer.cpp
>   ThreadPlanStack.cpp
>   ThreadSpec.cpp
> +  Trace.cpp
> +  TraceSettingsParser.cpp
>   UnixSignals.cpp
>   UnwindAssembly.cpp
>   UnwindLLDB.cpp
> 
> diff  --git a/lldb/source/Target/Trace.cpp b/lldb/source/Target/Trace.cpp
> new file mode 100644
> index 000000000000..6a1f8eadee1b
> --- /dev/null
> +++ b/lldb/source/Target/Trace.cpp
> @@ -0,0 +1,78 @@
> +//===-- Trace.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/Target/Trace.h"
> +
> +#include <regex>
> +#include <sstream>
> +
> +#include "llvm/Support/Format.h"
> +
> +#include "lldb/Core/PluginManager.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +using namespace llvm;
> +
> +llvm::Expected<lldb::TraceSP> Trace::FindPlugin(Debugger &debugger,
> +                                                const json::Value &settings,
> +                                                StringRef info_dir) {
> +  llvm::Expected<const json::Object &> settings_obj =
> +      json_helpers::ToObjectOrError(settings);
> +  if (!settings_obj)
> +    return settings_obj.takeError();
> +
> +  llvm::Expected<const json::Object &> trace =
> +      json_helpers::GetObjectOrError(*settings_obj, "trace");
> +  if (!trace)
> +    return trace.takeError();
> +
> +  llvm::Expected<StringRef> type =
> +      json_helpers::GetStringOrError(*trace, "type");
> +  if (!type)
> +    return type.takeError();
> +
> +  ConstString plugin_name(*type);
> +  auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name);
> +  if (create_callback) {
> +    TraceSP instance = create_callback();
> +    if (llvm::Error err =
> +            instance->ParseSettings(debugger, *settings_obj, info_dir))
> +      return std::move(err);
> +    return instance;
> +  }
> +
> +  return createStringError(
> +      std::errc::invalid_argument,
> +      "no trace plug-in matches the specified type: \"%s\"",
> +      plugin_name.AsCString());
> +}
> +
> +llvm::Expected<lldb::TraceSP> Trace::FindPlugin(StringRef name) {
> +  ConstString plugin_name(name);
> +  auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name);
> +  if (create_callback)
> +    return create_callback();
> +
> +  return createStringError(
> +      std::errc::invalid_argument,
> +      "no trace plug-in matches the specified type: \"%s\"",
> +      plugin_name.AsCString());
> +}
> +
> +llvm::Error Trace::ParseSettings(Debugger &debugger,
> +                                 const llvm::json::Object &settings,
> +                                 llvm::StringRef settings_dir) {
> +  if (llvm::Error err =
> +          CreateParser()->ParseSettings(debugger, settings, settings_dir))
> +    return err;
> +
> +  return llvm::Error::success();
> +}
> +
> +llvm::StringRef Trace::GetSchema() { return CreateParser()->GetSchema(); }
> 
> diff  --git a/lldb/source/Target/TraceSettingsParser.cpp 
> b/lldb/source/Target/TraceSettingsParser.cpp
> new file mode 100644
> index 000000000000..09e60bb35a4a
> --- /dev/null
> +++ b/lldb/source/Target/TraceSettingsParser.cpp
> @@ -0,0 +1,351 @@
> +//===-- TraceSettingParser.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/Target/TraceSettingsParser.h"
> +
> +#include <regex>
> +
> +#include "Plugins/Process/Utility/HistoryThread.h"
> +#include "lldb/Core/Debugger.h"
> +#include "lldb/Target/Process.h"
> +
> +using namespace lldb;
> +using namespace lldb_private;
> +using namespace llvm;
> +
> +namespace json_helpers {
> +
> +llvm::Error CreateWrongTypeError(const json::Value &value,
> +                                 llvm::StringRef type) {
> +  std::string s;
> +  llvm::raw_string_ostream os(s);
> +  os << llvm::formatv("JSON value is expected to be \"{0}\".\nValue:\n{1:2}",
> +                      type, value);
> +  os.flush();
> +
> +  return llvm::createStringError(std::errc::invalid_argument, 
> os.str().c_str());
> +}
> +
> +llvm::Expected<int64_t> ToIntegerOrError(const json::Value &value) {
> +  llvm::Optional<int64_t> v = value.getAsInteger();
> +  if (v.hasValue())
> +    return *v;
> +  return CreateWrongTypeError(value, "integer");
> +}
> +
> +llvm::Expected<StringRef> ToStringOrError(const json::Value &value) {
> +  llvm::Optional<StringRef> v = value.getAsString();
> +  if (v.hasValue())
> +    return *v;
> +  return CreateWrongTypeError(value, "string");
> +}
> +
> +llvm::Expected<const json::Array &> ToArrayOrError(const json::Value &value) 
> {
> +  if (const json::Array *v = value.getAsArray())
> +    return *v;
> +  return CreateWrongTypeError(value, "array");
> +}
> +
> +llvm::Expected<const json::Object &> ToObjectOrError(const json::Value 
> &value) {
> +  if (const json::Object *v = value.getAsObject())
> +    return *v;
> +  return CreateWrongTypeError(value, "object");
> +}
> +
> +llvm::Error CreateMissingKeyError(json::Object obj, llvm::StringRef key) {
> +  std::string str;
> +  llvm::raw_string_ostream os(str);
> +  os << llvm::formatv(
> +      "JSON object is missing the \"{0}\" field.\nValue:\n{1:2}", key,
> +      json::Value(std::move(obj)));
> +  os.flush();
> +
> +  return llvm::createStringError(std::errc::invalid_argument, 
> os.str().c_str());
> +}
> +
> +llvm::Expected<const json::Value &> GetValueOrError(const json::Object &obj,
> +                                                    StringRef key) {
> +  if (const json::Value *v = obj.get(key))
> +    return *v;
> +  else
> +    return CreateMissingKeyError(obj, key);
> +}
> +
> +llvm::Expected<int64_t> GetIntegerOrError(const json::Object &obj,
> +                                          StringRef key) {
> +  if (llvm::Expected<const json::Value &> v = GetValueOrError(obj, key))
> +    return ToIntegerOrError(*v);
> +  else
> +    return v.takeError();
> +}
> +
> +llvm::Expected<StringRef> GetStringOrError(const json::Object &obj,
> +                                           StringRef key) {
> +  if (llvm::Expected<const json::Value &> v = GetValueOrError(obj, key))
> +    return ToStringOrError(*v);
> +  else
> +    return v.takeError();
> +}
> +
> +llvm::Expected<const json::Array &> GetArrayOrError(const json::Object &obj,
> +                                                    StringRef key) {
> +  if (llvm::Expected<const json::Value &> v = GetValueOrError(obj, key))
> +    return ToArrayOrError(*v);
> +  else
> +    return v.takeError();
> +}
> +
> +llvm::Expected<const json::Object &> GetObjectOrError(const json::Object 
> &obj,
> +                                                      StringRef key) {
> +  if (llvm::Expected<const json::Value &> v = GetValueOrError(obj, key))
> +    return ToObjectOrError(*v);
> +  else
> +    return v.takeError();
> +}
> +
> +llvm::Expected<llvm::Optional<StringRef>>
> +GetOptionalStringOrError(const json::Object &obj, StringRef key) {
> +  if (const json::Value *v = obj.get(key))
> +    return ToStringOrError(*v);
> +  return llvm::None;
> +}
> +
> +} // namespace json_helpers
> +
> +StringRef TraceSettingsParser::GetSchema() {
> +  static std::string schema;
> +  if (schema.empty()) {
> +    std::ostringstream schema_builder;
> +    schema_builder << "{\n \"trace\": ";
> +
> +    // We need to add spaces to indent correctly the plugin schema
> +    std::string plugin_schema(GetPluginSchema());
> +    plugin_schema = std::regex_replace(plugin_schema, std::regex("\n"), "\n  
> ");
> +    schema_builder << plugin_schema << ",\n";
> +
> +    schema_builder << R"(  "processes": [
> +    {
> +      "pid": integer,
> +      "triple": string, // llvm-triple
> +      "threads": [
> +        {
> +          "tid": integer,
> +          "traceFile": string
> +        }
> +      ],
> +      "modules": [
> +        {
> +          "systemPath": string, // original path of the module at runtime
> +          "file"?: string, // copy of the file if not available at 
> "systemPath"
> +          "loadAddress": string, // string address in hex or decimal form
> +          "uuid"?: string,
> +        }
> +      ]
> +    }
> +  ]
> +}
> +// Notes:
> +// All paths are either absolute or relative to the settings file.)";
> +    schema = schema_builder.str();
> +  }
> +  return schema;
> +}
> +
> +void TraceSettingsParser::NormalizePath(FileSpec &file_spec) {
> +  if (file_spec.IsRelative())
> +    file_spec.PrependPathComponent(m_settings_dir);
> +}
> +
> +llvm::Error TraceSettingsParser::ParseThread(ProcessSP &process_sp,
> +                                             const json::Object &thread) {
> +  llvm::Expected<lldb::tid_t> raw_tid =
> +      json_helpers::GetIntegerOrError(thread, "tid");
> +  if (!raw_tid)
> +    return raw_tid.takeError();
> +  lldb::tid_t tid = static_cast<lldb::tid_t>(*raw_tid);
> +
> +  if (llvm::Expected<StringRef> trace_file =
> +          json_helpers::GetStringOrError(thread, "traceFile")) {
> +    FileSpec spec(*trace_file);
> +    NormalizePath(spec);
> +    m_thread_to_trace_file_map[process_sp->GetID()][tid] = spec;
> +  } else
> +    return trace_file.takeError();
> +
> +  ThreadSP thread_sp(new HistoryThread(*process_sp, tid, /*callstack*/ {}));
> +  process_sp->GetThreadList().AddThread(thread_sp);
> +  return llvm::Error::success();
> +}
> +
> +llvm::Error TraceSettingsParser::ParseThreads(ProcessSP &process_sp,
> +                                              const json::Object &process) {
> +  llvm::Expected<const json::Array &> threads =
> +      json_helpers::GetArrayOrError(process, "threads");
> +  if (!threads)
> +    return threads.takeError();
> +
> +  for (const json::Value &thread_val : *threads) {
> +    llvm::Expected<const json::Object &> thread =
> +        json_helpers::ToObjectOrError(thread_val);
> +    if (!thread)
> +      return thread.takeError();
> +    if (llvm::Error err = ParseThread(process_sp, *thread))
> +      return err;
> +  }
> +  return llvm::Error::success();
> +}
> +
> +static llvm::Expected<addr_t> ParseAddress(StringRef address_str) {
> +  addr_t address;
> +  if (address_str.getAsInteger(0, address))
> +    return createStringError(std::errc::invalid_argument,
> +                             "\"%s\" does not represent an integer",
> +                             address_str.data());
> +  return address;
> +}
> +
> +llvm::Error TraceSettingsParser::ParseModule(TargetSP &target_sp,
> +                                             const json::Object &module) {
> +  llvm::Expected<StringRef> load_address_str =
> +      json_helpers::GetStringOrError(module, "loadAddress");
> +  if (!load_address_str)
> +    return load_address_str.takeError();
> +  llvm::Expected<addr_t> load_address = ParseAddress(*load_address_str);
> +  if (!load_address)
> +    return load_address.takeError();
> +
> +  llvm::Expected<StringRef> system_path =
> +      json_helpers::GetStringOrError(module, "systemPath");
> +  if (!system_path)
> +    return system_path.takeError();
> +  FileSpec system_file_spec(*system_path);
> +  NormalizePath(system_file_spec);
> +
> +  llvm::Expected<llvm::Optional<StringRef>> file =
> +      json_helpers::GetOptionalStringOrError(module, "file");
> +  if (!file)
> +    return file.takeError();
> +  FileSpec local_file_spec(file->hasValue() ? **file : *system_path);
> +  NormalizePath(local_file_spec);
> +
> +  ModuleSpec module_spec;
> +  module_spec.GetFileSpec() = local_file_spec;
> +  module_spec.GetPlatformFileSpec() = system_file_spec;
> +  module_spec.SetObjectOffset(*load_address);
> +
> +  llvm::Expected<llvm::Optional<StringRef>> uuid_str =
> +      json_helpers::GetOptionalStringOrError(module, "uuid");
> +  if (!uuid_str)
> +    return uuid_str.takeError();
> +  if (uuid_str->hasValue())
> +    module_spec.GetUUID().SetFromStringRef(**uuid_str);
> +
> +  Status error;
> +  ModuleSP module_sp =
> +      target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error);
> +  return error.ToError();
> +}
> +
> +llvm::Error TraceSettingsParser::ParseModules(TargetSP &target_sp,
> +                                              const json::Object &process) {
> +  llvm::Expected<const json::Array &> modules =
> +      json_helpers::GetArrayOrError(process, "modules");
> +  if (!modules)
> +    return modules.takeError();
> +
> +  for (const json::Value &module_val : *modules) {
> +    llvm::Expected<const json::Object &> module =
> +        json_helpers::ToObjectOrError(module_val);
> +    if (!module)
> +      return module.takeError();
> +    if (llvm::Error err = ParseModule(target_sp, *module))
> +      return err;
> +  }
> +  return llvm::Error::success();
> +}
> +
> +llvm::Error TraceSettingsParser::ParseProcess(Debugger &debugger,
> +                                              const json::Object &process) {
> +  llvm::Expected<int64_t> pid = json_helpers::GetIntegerOrError(process, 
> "pid");
> +  if (!pid)
> +    return pid.takeError();
> +
> +  llvm::Expected<StringRef> triple =
> +      json_helpers::GetStringOrError(process, "triple");
> +  if (!triple)
> +    return triple.takeError();
> +
> +  TargetSP target_sp;
> +  Status error = debugger.GetTargetList().CreateTarget(
> +      debugger, /*user_exe_path*/ llvm::StringRef(), *triple, 
> eLoadDependentsNo,
> +      /*platform_options*/ nullptr, target_sp);
> +
> +  if (!target_sp)
> +    return error.ToError();
> +
> +  m_targets.push_back(target_sp);
> +  debugger.GetTargetList().SetSelectedTarget(target_sp.get());
> +
> +  ProcessSP process_sp(target_sp->CreateProcess(
> +      /*listener*/ nullptr, /*plugin_name*/ llvm::StringRef(),
> +      /*crash_file*/ nullptr));
> +  process_sp->SetID(static_cast<lldb::pid_t>(*pid));
> +
> +  if (llvm::Error err = ParseThreads(process_sp, process))
> +    return err;
> +
> +  return ParseModules(target_sp, process);
> +}
> +
> +llvm::Error TraceSettingsParser::ParseProcesses(Debugger &debugger) {
> +  llvm::Expected<const json::Array &> processes =
> +      json_helpers::GetArrayOrError(m_settings, "processes");
> +  if (!processes)
> +    return processes.takeError();
> +
> +  for (const json::Value &process_val : *processes) {
> +    llvm::Expected<const json::Object &> process =
> +        json_helpers::ToObjectOrError(process_val);
> +    if (!process)
> +      return process.takeError();
> +    if (llvm::Error err = ParseProcess(debugger, *process))
> +      return err;
> +  }
> +  return llvm::Error::success();
> +}
> +
> +llvm::Error TraceSettingsParser::ParseSettingsImpl(Debugger &debugger) {
> +  if (llvm::Error err = ParseProcesses(debugger))
> +    return err;
> +  return ParsePluginSettings();
> +}
> +
> +llvm::Error
> +TraceSettingsParser::ParseSettings(Debugger &debugger,
> +                                   const llvm::json::Object &settings,
> +                                   llvm::StringRef settings_dir) {
> +  m_settings = settings;
> +  m_settings_dir = settings_dir.str();
> +  if (llvm::Error err = ParseSettingsImpl(debugger)) {
> +    // We clean all the targets that were created internally, which should 
> leave
> +    // the debugger unchanged
> +    for (auto target_sp : m_targets)
> +      debugger.GetTargetList().DeleteTarget(target_sp);
> +
> +    return createStringError(std::errc::invalid_argument, "%s\nSchema:\n%s",
> +                             llvm::toString(std::move(err)).c_str(),
> +                             GetSchema().data());
> +  }
> +
> +  m_trace.m_settings = m_settings;
> +  m_trace.m_settings_dir = m_settings_dir;
> +  m_trace.m_thread_to_trace_file_map = m_thread_to_trace_file_map;
> +  m_trace.m_targets = m_targets;
> +
> +  return llvm::Error::success();
> +}
> 
> diff  --git a/lldb/source/Utility/StructuredData.cpp 
> b/lldb/source/Utility/StructuredData.cpp
> index 359c49ae254b..cb26329dc726 100644
> --- a/lldb/source/Utility/StructuredData.cpp
> +++ b/lldb/source/Utility/StructuredData.cpp
> @@ -42,7 +42,12 @@ StructuredData::ParseJSONFromFile(const FileSpec 
> &input_spec, Status &error) {
>                                     buffer_or_error.getError().message());
>     return return_sp;
>   }
> -  return ParseJSON(buffer_or_error.get()->getBuffer().str());
> +  llvm::Expected<json::Value> value =
> +      json::parse(buffer_or_error.get()->getBuffer().str());
> +  if (value)
> +    return ParseJSONValue(*value);
> +  error.SetErrorString(toString(value.takeError()));
> +  return StructuredData::ObjectSP();
> }
> 
> static StructuredData::ObjectSP ParseJSONValue(json::Value &value) {
> 
> diff  --git a/lldb/test/API/commands/trace/TestTraceLoad.py 
> b/lldb/test/API/commands/trace/TestTraceLoad.py
> new file mode 100644
> index 000000000000..f418b8d5a822
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/TestTraceLoad.py
> @@ -0,0 +1,57 @@
> +import lldb
> +from lldbsuite.test.lldbtest import *
> +from lldbsuite.test import lldbutil
> +from lldbsuite.test.decorators import *
> +
> +class TestTraceLoad(TestBase):
> +
> +    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")
> +        self.expect("trace load -v " + trace_definition_file, 
> substrs=["intel-pt"])
> +
> +        target = self.dbg.GetSelectedTarget()
> +        process = target.GetProcess()
> +        self.assertEqual(process.GetProcessID(), 1234)
> +
> +        self.assertEqual(process.GetNumThreads(), 1)
> +        self.assertEqual(process.GetThreadAtIndex(0).GetThreadID(), 3842849)
> +
> +        self.assertEqual(target.GetNumModules(), 1)
> +        module = target.GetModuleAtIndex(0)
> +        path = module.GetFileSpec()
> +        self.assertEqual(path.fullpath, os.path.join(src_dir, 
> "intelpt-trace", "a.out"))
> +        self.assertGreater(module.GetNumSections(), 0)
> +        self.assertEqual(module.GetSectionAtIndex(0).GetFileAddress(), 
> 0x400000)
> +
> +        self.assertEqual("6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A", 
> module.GetUUIDString())
> +
> +
> +    def testLoadInvalidTraces(self):
> +        src_dir = self.getSourceDir()
> +        # We test first an invalid type
> +        trace_definition_file = os.path.join(src_dir, "intelpt-trace", 
> "trace_bad.json")
> +        self.expect("trace load -v " + trace_definition_file, error=True,
> +          substrs=['error: JSON value is expected to be "object"', "Value", 
> "123", "Schema"])
> +
> +        # Now we test a missing field
> +        trace_definition_file2 = os.path.join(src_dir, "intelpt-trace", 
> "trace_bad2.json")
> +        self.expect("trace load -v " + trace_definition_file2, error=True,
> +            substrs=['error: JSON object is missing the "triple" field.', 
> "Value", "pid", "12345", "Schema"])
> +
> +        # The following wrong schema will have a valid target and an invalid 
> one. In the case of failure,
> +        # no targets should be created.
> +        self.assertEqual(self.dbg.GetNumTargets(), 0)
> +        trace_definition_file2 = os.path.join(src_dir, "intelpt-trace", 
> "trace_bad3.json")
> +        self.expect("trace load -v " + trace_definition_file2, error=True,
> +            substrs=['error: JSON object is missing the "pid" field.'])
> +        self.assertEqual(self.dbg.GetNumTargets(), 0)
> 
> diff  --git a/lldb/test/API/commands/trace/TestTraceSchema.py 
> b/lldb/test/API/commands/trace/TestTraceSchema.py
> new file mode 100644
> index 000000000000..1549325962ae
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/TestTraceSchema.py
> @@ -0,0 +1,22 @@
> +import lldb
> +from lldbsuite.test.lldbtest import *
> +from lldbsuite.test import lldbutil
> +from lldbsuite.test.decorators import *
> +
> +class TestTraceLoad(TestBase):
> +
> +    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"])
> +
> +    def testInvalidPluginSchema(self):
> +        self.expect("trace schema invalid-plugin", error=True,
> +            substrs=['error: no trace plug-in matches the specified type: 
> "invalid-plugin"'])
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/3842849.trace 
> b/lldb/test/API/commands/trace/intelpt-trace/3842849.trace
> new file mode 100644
> index 000000000000..14f7b5ef4aed
> Binary files /dev/null and 
> b/lldb/test/API/commands/trace/intelpt-trace/3842849.trace 
> diff er
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/a.out 
> b/lldb/test/API/commands/trace/intelpt-trace/a.out
> new file mode 100755
> index 000000000000..98a27fb532d6
> Binary files /dev/null and b/lldb/test/API/commands/trace/intelpt-trace/a.out 
> diff er
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/main.cpp 
> b/lldb/test/API/commands/trace/intelpt-trace/main.cpp
> new file mode 100644
> index 000000000000..3e4ad1c0b843
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/intelpt-trace/main.cpp
> @@ -0,0 +1,8 @@
> +int main() {
> +  int ret = 0;
> +
> +  for (int i = 0; i < 4; i++)
> +    ret ^= 1;
> +
> +  return ret;
> +}
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/trace.json 
> b/lldb/test/API/commands/trace/intelpt-trace/trace.json
> new file mode 100644
> index 000000000000..543b71d0cefe
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/intelpt-trace/trace.json
> @@ -0,0 +1,31 @@
> +{
> +  "trace": {
> +    "type": "intel-pt",
> +    "pt_cpu": {
> +      "vendor": "intel",
> +      "family": 6,
> +      "model": 79,
> +      "stepping": 1
> +    }
> +  },
> +  "processes": [
> +    {
> +      "pid": 1234,
> +      "triple": "x86_64-*-linux",
> +      "threads": [
> +        {
> +          "tid": 3842849,
> +          "traceFile": "3842849.trace"
> +        }
> +      ],
> +      "modules": [
> +        {
> +          "file": "a.out",
> +          "systemPath": "a.out",
> +          "loadAddress": "0x0000000000400000",
> +          "uuid": "6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A"
> +        }
> +      ]
> +    }
> +  ]
> +}
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/trace_bad.json 
> b/lldb/test/API/commands/trace/intelpt-trace/trace_bad.json
> new file mode 100644
> index 000000000000..9d00a82ebcf7
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/intelpt-trace/trace_bad.json
> @@ -0,0 +1,14 @@
> +{
> +  "trace": {
> +    "type": "intel-pt",
> +    "pt_cpu": {
> +      "vendor": "intel",
> +      "family": 6,
> +      "model": 79,
> +      "stepping": 1
> +    }
> +  },
> +  "processes": [
> +    123
> +  ]
> +}
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/trace_bad2.json 
> b/lldb/test/API/commands/trace/intelpt-trace/trace_bad2.json
> new file mode 100644
> index 000000000000..16ece129c8d8
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/intelpt-trace/trace_bad2.json
> @@ -0,0 +1,41 @@
> +{
> +  "trace": {
> +    "type": "intel-pt",
> +    "pt_cpu": {
> +      "vendor": "intel",
> +      "family": 6,
> +      "model": 79,
> +      "stepping": 1
> +    }
> +  },
> +  "processes": [
> +    {
> +      "pid": 1234,
> +      "triple": "x86_64-*-linux",
> +      "threads": [
> +        {
> +          "tid": 5678,
> +          "traceFile": "3842849.trace"
> +        }
> +      ],
> +      "modules": [
> +        {
> +          "file": "a.out",
> +          "systemPath": "a.out",
> +          "loadAddress": "0x0000000000400000",
> +          "uuid": "6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A"
> +        }
> +      ]
> +    },
> +    {
> +      "pid": 12345,
> +      "threads": [
> +        {
> +          "tid": 56789,
> +          "traceFile": "3842849.trace"
> +        }
> +      ],
> +      "modules": []
> +    }
> +  ]
> +}
> 
> diff  --git a/lldb/test/API/commands/trace/intelpt-trace/trace_bad3.json 
> b/lldb/test/API/commands/trace/intelpt-trace/trace_bad3.json
> new file mode 100644
> index 000000000000..dc587a8a4c52
> --- /dev/null
> +++ b/lldb/test/API/commands/trace/intelpt-trace/trace_bad3.json
> @@ -0,0 +1,32 @@
> +{
> +  "trace": {
> +    "type": "intel-pt",
> +    "pt_cpu": {
> +      "vendor": "intel",
> +      "family": 6,
> +      "model": 79,
> +      "stepping": 1
> +    }
> +  },
> +  "processes": [
> +    {
> +      "pid": 1234,
> +      "triple": "x86_64-*-linux",
> +      "threads": [
> +        {
> +          "tid": 5678,
> +          "traceFile": "3842849.trace"
> +        }
> +      ],
> +      "modules": [
> +        {
> +          "file": "a.out",
> +          "systemPath": "a.out",
> +          "loadAddress": "0x0000000000400000",
> +          "uuid": "6AA9A4E2-6F28-2F33-377D-59FECE874C71-5B41261A"
> +        }
> +      ]
> +    },
> +    {}
> +  ]
> +}
> 
> 
> 
> _______________________________________________
> lldb-commits mailing list
> lldb-commits@lists.llvm.org
> https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to