wallace updated this revision to Diff 296562.
wallace marked 10 inline comments as done.
wallace added a comment.

Address issues based on this diff's comments and from conversations with Greg.

- I'm still keeping the TraceSessionFile name instead of TraceSettings, as 
later there'll be actual trace settings (e.g. size of an Intel PT trace buffer, 
whether to trace in a ring or non-ring buffer, etc.).
- As Greg asked, I'm bringing back the top-level TraceSessionFileParser class, 
which each plug-in should override to perform parsing. This time the 
implementation is much cleaner and the implementation class can decide what to 
reuse from the base class. This will help ensuring that all Trace plug-ins 
consistently use the same common schema and parsing logic.
- Improved comments overall.
- Now, as Pavel suggested, I'm storing the schema in the PluginInstance, which 
allows fetching schemas without needing to instantiate any class. With this I 
was able able to simplify and remove several constructors.
- Fixed the header guards
- Some small fixes here are there, following the comments in the diff.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D88841

Files:
  lldb/include/lldb/Core/PluginManager.h
  lldb/include/lldb/Target/Trace.h
  lldb/include/lldb/Target/TraceSessionFileParser.h
  lldb/include/lldb/Target/TraceSettingsParser.h
  lldb/include/lldb/lldb-forward.h
  lldb/include/lldb/lldb-private-interfaces.h
  lldb/source/Commands/CommandObjectTrace.cpp
  lldb/source/Core/PluginManager.cpp
  lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
  lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h
  lldb/source/Target/CMakeLists.txt
  lldb/source/Target/Trace.cpp
  lldb/source/Target/TraceSessionFileParser.cpp
  lldb/source/Target/TraceSettingsParser.cpp
  lldb/test/API/commands/trace/TestTraceLoad.py

Index: lldb/test/API/commands/trace/TestTraceLoad.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceLoad.py
+++ lldb/test/API/commands/trace/TestTraceLoad.py
@@ -40,7 +40,7 @@
         src_dir = self.getSourceDir()
         # We test first an invalid type
         self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad.json"), error=True,
-          substrs=['''error: expected object at settings.processes[0]
+          substrs=['''error: expected object at traceSession.processes[0]
 
 Context:
 {
@@ -53,7 +53,7 @@
 
 Schema:
 {
- "trace": {
+  "trace": {
     "type": "intel-pt",
     "pt_cpu": {
       "vendor": "intel" | "unknown",
@@ -63,32 +63,35 @@
     }
   },'''])
 
-        # Now we test a missing field in the global settings
+        # Now we test a missing field in the global session file
         self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad2.json"), error=True,
-            substrs=['error: missing value at settings.processes[1].triple', "Context", "Schema"])
+            substrs=['error: missing value at traceSession.processes[1].triple', "Context", "Schema"])
 
         # Now we test a missing field in the intel-pt settings
         self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad4.json"), error=True,
-            substrs=['''error: missing value at settings.trace.pt_cpu.family
+            substrs=['''error: missing value at traceSession.trace.pt_cpu.family
 
 Context:
 {
-  "pt_cpu": /* error: missing value */ {
-    "model": 79,
-    "stepping": 1,
-    "vendor": "intel"
-  },
-  "type": "intel-pt"
+  "processes": [],
+  "trace": {
+    "pt_cpu": /* error: missing value */ {
+      "model": 79,
+      "stepping": 1,
+      "vendor": "intel"
+    },
+    "type": "intel-pt"
+  }
 }''', "Schema"])
 
         # Now we test an incorrect load address in the intel-pt settings
         self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad5.json"), error=True,
-            substrs=['error: expected numeric string at settings.processes[0].modules[0].loadAddress',
+            substrs=['error: expected numeric string at traceSession.processes[0].modules[0].loadAddress',
                      '"loadAddress": /* error: expected numeric string */ 400000,', "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)
         self.expect("trace load -v " + os.path.join(src_dir, "intelpt-trace", "trace_bad3.json"), error=True,
-            substrs=['error: missing value at settings.processes[1].pid'])
+            substrs=['error: missing value at traceSession.processes[1].pid'])
         self.assertEqual(self.dbg.GetNumTargets(), 0)
Index: lldb/source/Target/TraceSettingsParser.cpp
===================================================================
--- lldb/source/Target/TraceSettingsParser.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-//===-- 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 <sstream>
-
-#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;
-
-StringRef TraceSettingsParser::GetSchema() {
-  static std::string schema;
-  if (schema.empty()) {
-    std::ostringstream schema_builder;
-    schema_builder << "{\n \"trace\": ";
-    schema_builder << GetPluginSchema().str() << ",\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);
-}
-
-void TraceSettingsParser::ParseThread(ProcessSP &process_sp,
-                                      const JSONThread &thread) {
-  lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
-
-  FileSpec spec(thread.trace_file);
-  NormalizePath(spec);
-  m_thread_to_trace_file_map[process_sp->GetID()][tid] = spec;
-
-  ThreadSP thread_sp(new HistoryThread(*process_sp, tid, /*callstack*/ {}));
-  process_sp->GetThreadList().AddThread(thread_sp);
-}
-
-llvm::Error TraceSettingsParser::ParseModule(TargetSP &target_sp,
-                                             const JSONModule &module) {
-  FileSpec system_file_spec(module.system_path);
-  NormalizePath(system_file_spec);
-
-  FileSpec local_file_spec(module.file.hasValue() ? *module.file
-                                                  : module.system_path);
-  NormalizePath(local_file_spec);
-
-  ModuleSpec module_spec;
-  module_spec.GetFileSpec() = local_file_spec;
-  module_spec.GetPlatformFileSpec() = system_file_spec;
-  module_spec.SetObjectOffset(module.load_address.value);
-
-  if (module.uuid.hasValue())
-    module_spec.GetUUID().SetFromStringRef(*module.uuid);
-
-  Status error;
-  ModuleSP module_sp =
-      target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error);
-  return error.ToError();
-}
-
-llvm::Error TraceSettingsParser::ParseProcess(Debugger &debugger,
-                                              const JSONProcess &process) {
-  TargetSP target_sp;
-  Status error = debugger.GetTargetList().CreateTarget(
-      debugger, /*user_exe_path*/ llvm::StringRef(), process.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>(process.pid));
-
-  for (const JSONThread &thread : process.threads)
-    ParseThread(process_sp, thread);
-
-  for (const JSONModule &module : process.modules) {
-    if (llvm::Error err = ParseModule(target_sp, module))
-      return err;
-  }
-  return llvm::Error::success();
-}
-
-llvm::Error
-TraceSettingsParser::CreateJSONError(json::Path::Root &root,
-                                     const llvm::json::Value &value) {
-  std::string err;
-  raw_string_ostream os(err);
-  root.printErrorContext(value, os);
-  return createStringError(std::errc::invalid_argument,
-                           "%s\n\nContext:\n%s\n\nSchema:\n%s",
-                           llvm::toString(root.getError()).c_str(),
-                           os.str().c_str(), GetSchema().data());
-}
-
-llvm::Error
-TraceSettingsParser::ParseSettingsImpl(Debugger &debugger,
-                                       const llvm::json::Value &raw_settings) {
-  json::Path::Root root("settings");
-  JSONTraceSettings settings;
-  if (!json::fromJSON(raw_settings, settings, root))
-    return CreateJSONError(root, raw_settings);
-
-  for (const JSONProcess &process : settings.processes) {
-    if (llvm::Error err = ParseProcess(debugger, process))
-      return err;
-  }
-
-  json::Object plugin_obj = *raw_settings.getAsObject()->getObject("trace");
-  json::Value plugin_settings(std::move(plugin_obj));
-  return ParsePluginSettings(plugin_settings);
-}
-
-llvm::Error
-TraceSettingsParser::ParseSettings(Debugger &debugger,
-                                   const llvm::json::Value &raw_settings,
-                                   llvm::StringRef settings_dir) {
-  m_settings_dir = settings_dir.str();
-
-  if (llvm::Error err = ParseSettingsImpl(debugger, raw_settings)) {
-    // 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 err;
-  }
-
-  m_trace.m_settings = *raw_settings.getAsObject();
-  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();
-}
Index: lldb/source/Target/TraceSessionFileParser.cpp
===================================================================
--- /dev/null
+++ lldb/source/Target/TraceSessionFileParser.cpp
@@ -0,0 +1,145 @@
+//===-- TraceSessionFileParser.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/TraceSessionFileParser.h"
+
+#include <sstream>
+
+#include "lldb/Core/Module.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+void TraceSessionFileParser::NormalizePath(lldb_private::FileSpec &file_spec) {
+  if (file_spec.IsRelative())
+    file_spec.PrependPathComponent(m_session_file_dir);
+}
+
+llvm::Error TraceSessionFileParser::ParseModule(lldb::TargetSP &target_sp,
+                                                const JSONModule &module) {
+  FileSpec system_file_spec(module.system_path);
+  NormalizePath(system_file_spec);
+
+  FileSpec local_file_spec(module.file.hasValue() ? *module.file
+                                                  : module.system_path);
+  NormalizePath(local_file_spec);
+
+  ModuleSpec module_spec;
+  module_spec.GetFileSpec() = local_file_spec;
+  module_spec.GetPlatformFileSpec() = system_file_spec;
+  module_spec.SetObjectOffset(module.load_address.value);
+
+  if (module.uuid.hasValue())
+    module_spec.GetUUID().SetFromStringRef(*module.uuid);
+
+  Status error;
+  ModuleSP module_sp =
+      target_sp->GetOrCreateModule(module_spec, /*notify*/ false, &error);
+  return error.ToError();
+}
+
+/// Create a user-friendly error message upon a JSON-parsing failure using the
+/// \a json::ObjectMapper functionality.
+///
+/// \param[in] root
+///   The \a llvm::json::Path::Root used to parse the JSON \a value.
+///
+/// \param[in] value
+///   The json value that failed to parse.
+///
+/// \return
+///   An \a llvm::Error containing the user-friendly error message.
+llvm::Error
+TraceSessionFileParser::CreateJSONError(llvm::json::Path::Root &root,
+                                        const llvm::json::Value &value) {
+  std::string err;
+  raw_string_ostream os(err);
+  root.printErrorContext(value, os);
+  return createStringError(std::errc::invalid_argument,
+                           "%s\n\nContext:\n%s\n\nSchema:\n%s",
+                           llvm::toString(root.getError()).c_str(),
+                           os.str().c_str(), m_schema.data());
+}
+
+std::string TraceSessionFileParser::BuildSchema(llvm::StringRef plugin_schema) {
+  std::ostringstream schema_builder;
+  schema_builder << "{\n  \"trace\": ";
+  schema_builder << plugin_schema.data() << ",";
+  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 session file.)";
+  return schema_builder.str();
+}
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONAddress &address,
+              Path path) {
+  llvm::Optional<llvm::StringRef> s = value.getAsString();
+  if (s.hasValue() && !s->getAsInteger(0, address.value))
+    return true;
+
+  path.report("expected numeric string");
+  return false;
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONModule &module,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("systemPath", module.system_path) &&
+         o.map("file", module.file) &&
+         o.map("loadAddress", module.load_address) &&
+         o.map("uuid", module.uuid);
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONThread &thread,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("tid", thread.tid) && o.map("traceFile", thread.trace_file);
+}
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONProcess &process,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
+         o.map("threads", process.threads) && o.map("modules", process.modules);
+}
+
+bool fromJSON(const Value &value,
+              TraceSessionFileParser::JSONTracePluginSettings &plugin_settings,
+              Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("type", plugin_settings.type);
+}
+
+} // namespace json
+} // namespace llvm
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -18,14 +18,14 @@
 using namespace lldb_private;
 using namespace llvm;
 
-// Helper structs used to extract the type of a trace settings json without
+// Helper structs used to extract the type of a trace session json without
 // having to parse the entire object.
 
 struct JSONSimplePluginSettings {
   std::string type;
 };
 
-struct JSONSimpleTraceSettings {
+struct JSONSimpleTraceSession {
   JSONSimplePluginSettings trace;
 };
 
@@ -38,29 +38,31 @@
   return o && o.map("type", plugin_settings.type);
 }
 
-bool fromJSON(const json::Value &value, JSONSimpleTraceSettings &settings,
+bool fromJSON(const json::Value &value, JSONSimpleTraceSession &session,
               json::Path path) {
   json::ObjectMapper o(value, path);
-  return o && o.map("trace", settings.trace);
+  return o && o.map("trace", session.trace);
 }
 
 } // namespace json
 } // namespace llvm
 
-llvm::Expected<lldb::TraceSP> Trace::FindPlugin(Debugger &debugger,
-                                                const json::Value &settings,
-                                                StringRef info_dir) {
-  JSONSimpleTraceSettings json_settings;
-  json::Path::Root root("settings");
-  if (!json::fromJSON(settings, json_settings, root))
+llvm::Expected<lldb::TraceSP>
+Trace::FindPlugin(Debugger &debugger, const json::Value &trace_session_file,
+                  StringRef session_file_dir) {
+  JSONSimpleTraceSession json_session;
+  json::Path::Root root("traceSession");
+  if (!json::fromJSON(trace_session_file, json_session, root))
     return root.getError();
 
-  ConstString plugin_name(json_settings.trace.type);
+  ConstString plugin_name(json_session.trace.type);
   auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name);
   if (create_callback) {
-    TraceSP instance = create_callback();
-    if (llvm::Error err = instance->ParseSettings(debugger, settings, info_dir))
-      return std::move(err);
+    Status error;
+    TraceSP instance =
+        create_callback(trace_session_file, session_file_dir, debugger, error);
+    if (error.Fail())
+      return error.ToError();
     return instance;
   }
 
@@ -70,26 +72,14 @@
       plugin_name.AsCString());
 }
 
-llvm::Expected<lldb::TraceSP> Trace::FindPlugin(StringRef name) {
+llvm::Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
   ConstString plugin_name(name);
-  auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name);
-  if (create_callback)
-    return create_callback();
+  const char *schema = PluginManager::GetTraceSchema(plugin_name);
+  if (schema != nullptr)
+    return schema;
 
   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::Value &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(); }
Index: lldb/source/Target/CMakeLists.txt
===================================================================
--- lldb/source/Target/CMakeLists.txt
+++ lldb/source/Target/CMakeLists.txt
@@ -66,7 +66,7 @@
   ThreadPlanStack.cpp
   ThreadSpec.cpp
   Trace.cpp
-  TraceSettingsParser.cpp
+  TraceSessionFileParser.cpp
   UnixSignals.cpp
   UnwindAssembly.cpp
   UnwindLLDB.cpp
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.h
+++ /dev/null
@@ -1,73 +0,0 @@
-//===-- 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:
-  struct JSONPTCPU {
-    std::string vendor;
-    int64_t family;
-    int64_t model;
-    int64_t stepping;
-  };
-
-  struct JSONIntelPTSettings {
-    JSONPTCPU pt_cpu;
-  };
-
-  TraceIntelPTSettingsParser(TraceIntelPT &trace)
-      : lldb_private::TraceSettingsParser((lldb_private::Trace &)trace),
-        m_trace(trace) {}
-
-protected:
-  llvm::StringRef GetPluginSchema() override;
-
-  llvm::Error
-  ParsePluginSettings(const llvm::json::Value &plugin_settings) override;
-
-private:
-  void ParsePTCPU(const JSONPTCPU &pt_cpu);
-
-  TraceIntelPT &m_trace;
-  pt_cpu m_pt_cpu;
-};
-
-namespace llvm {
-namespace json {
-
-inline bool fromJSON(const llvm::json::Value &value,
-                     TraceIntelPTSettingsParser::JSONPTCPU &pt_cpu,
-                     llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("vendor", pt_cpu.vendor) &&
-         o.map("family", pt_cpu.family) && o.map("model", pt_cpu.model) &&
-         o.map("stepping", pt_cpu.stepping);
-}
-
-inline bool
-fromJSON(const llvm::json::Value &value,
-         TraceIntelPTSettingsParser::JSONIntelPTSettings &intel_pt_settings,
-         llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("pt_cpu", intel_pt_settings.pt_cpu);
-}
-
-} // namespace json
-} // namespace llvm
-
-#endif // liblldb_TraceIntelPTSettingsParser_h_
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSettingsParser.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===-- 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
-    }
-  })";
-}
-
-void TraceIntelPTSettingsParser::ParsePTCPU(const JSONPTCPU &pt_cpu) {
-  m_pt_cpu = {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
-              static_cast<uint16_t>(pt_cpu.family),
-              static_cast<uint8_t>(pt_cpu.model),
-              static_cast<uint8_t>(pt_cpu.stepping)};
-}
-
-llvm::Error TraceIntelPTSettingsParser::ParsePluginSettings(
-    const llvm::json::Value &plugin_settings) {
-  json::Path::Root root("settings.trace");
-  JSONIntelPTSettings settings;
-  if (!json::fromJSON(plugin_settings, settings, root))
-    return CreateJSONError(root, plugin_settings);
-
-  ParsePTCPU(settings.pt_cpu);
-
-  m_trace.m_pt_cpu = m_pt_cpu;
-  return llvm::Error::success();
-}
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.h
@@ -0,0 +1,90 @@
+//===-- TraceIntelPTSessionFileParser.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_TRACEINTELPTSESSIONFILEPARSER_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H
+
+#include "intel-pt.h"
+
+#include "TraceIntelPT.h"
+#include "lldb/Target/TraceSessionFileParser.h"
+
+class TraceIntelPT;
+
+class TraceIntelPTSessionFileParser
+    : public lldb_private::TraceSessionFileParser {
+public:
+  struct JSONPTCPU {
+    std::string vendor;
+    int64_t family;
+    int64_t model;
+    int64_t stepping;
+  };
+
+  struct JSONTraceIntelPTSettings
+      : lldb_private::TraceSessionFileParser::JSONTracePluginSettings {
+    JSONPTCPU pt_cpu;
+  };
+
+  /// See \a TraceSessionFileParser::TraceSessionFileParser for the description
+  /// of these fields.
+  TraceIntelPTSessionFileParser(lldb_private::Debugger &debugger,
+                                const llvm::json::Value &trace_session_file,
+                                llvm::StringRef session_file_dir)
+      : lldb_private::TraceSessionFileParser(session_file_dir, GetSchema()),
+        m_debugger(debugger), m_trace_session_file(trace_session_file) {}
+
+  /// \return
+  ///   The JSON schema for the session data.
+  static llvm::StringRef GetSchema();
+
+  /// Parse the structured data trace session and create the corresponding \a
+  /// Target objects. In case of an error, no targets are created.
+  ///
+  /// \return
+  ///   A \a lldb::TraceSP instance with the trace session data. In case of
+  ///   errors, return a null pointer.
+  llvm::Expected<lldb::TraceSP> Parse();
+
+private:
+  llvm::Error ParseImpl();
+
+  llvm::Error ParseProcess(
+      const lldb_private::TraceSessionFileParser::JSONProcess &process);
+
+  void
+  ParseThread(lldb::ProcessSP &process_sp,
+              const lldb_private::TraceSessionFileParser::JSONThread &thread);
+
+  void ParsePTCPU(const JSONPTCPU &pt_cpu);
+
+  lldb_private::Debugger &m_debugger;
+  const llvm::json::Value &m_trace_session_file;
+
+  /// Objects created as product of the parsing
+  /// \{
+  pt_cpu m_pt_cpu;
+  std::vector<lldb::TargetSP> m_targets;
+  /// \}
+};
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value,
+              TraceIntelPTSessionFileParser::JSONPTCPU &pt_cpu, Path path);
+
+bool fromJSON(
+    const Value &value,
+    TraceIntelPTSessionFileParser::JSONTraceIntelPTSettings &plugin_settings,
+    Path path);
+
+} // namespace json
+} // namespace llvm
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPTSESSIONFILEPARSER_H
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPTSessionFileParser.cpp
@@ -0,0 +1,134 @@
+//===-- TraceIntelPTSessionFileParser.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 "TraceIntelPTSessionFileParser.h"
+
+#include "ThreadIntelPT.h"
+#include "lldb/Core/Debugger.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace llvm;
+
+StringRef TraceIntelPTSessionFileParser::GetSchema() {
+  static std::string schema;
+  if (schema.empty()) {
+    schema = TraceSessionFileParser::BuildSchema(R"({
+    "type": "intel-pt",
+    "pt_cpu": {
+      "vendor": "intel" | "unknown",
+      "family": integer,
+      "model": integer,
+      "stepping": integer
+    }
+  })");
+  }
+  return schema;
+}
+
+void TraceIntelPTSessionFileParser::ParseThread(
+    ProcessSP &process_sp, const TraceSessionFileParser::JSONThread &thread) {
+  lldb::tid_t tid = static_cast<lldb::tid_t>(thread.tid);
+
+  FileSpec trace_file(thread.trace_file);
+  NormalizePath(trace_file);
+
+  ThreadSP thread_sp(new ThreadIntelPT(*process_sp, tid, trace_file));
+  process_sp->GetThreadList().AddThread(thread_sp);
+}
+
+llvm::Error TraceIntelPTSessionFileParser::ParseProcess(
+    const TraceSessionFileParser::JSONProcess &process) {
+  TargetSP target_sp;
+  Status error = m_debugger.GetTargetList().CreateTarget(
+      m_debugger, /*user_exe_path*/ llvm::StringRef(), process.triple,
+      eLoadDependentsNo,
+      /*platform_options*/ nullptr, target_sp);
+
+  if (!target_sp)
+    return error.ToError();
+
+  m_targets.push_back(target_sp);
+  m_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>(process.pid));
+
+  for (const TraceSessionFileParser::JSONThread &thread : process.threads)
+    ParseThread(process_sp, thread);
+
+  for (const TraceSessionFileParser::JSONModule &module : process.modules) {
+    if (llvm::Error err = ParseModule(target_sp, module))
+      return err;
+  }
+  return llvm::Error::success();
+}
+
+void TraceIntelPTSessionFileParser::ParsePTCPU(const JSONPTCPU &pt_cpu) {
+  m_pt_cpu = {pt_cpu.vendor.compare("intel") == 0 ? pcv_intel : pcv_unknown,
+              static_cast<uint16_t>(pt_cpu.family),
+              static_cast<uint8_t>(pt_cpu.model),
+              static_cast<uint8_t>(pt_cpu.stepping)};
+}
+
+llvm::Error TraceIntelPTSessionFileParser::ParseImpl() {
+  json::Path::Root root("traceSession");
+  TraceSessionFileParser::JSONTraceSession<JSONTraceIntelPTSettings> session;
+  if (!json::fromJSON(m_trace_session_file, session, root)) {
+    return CreateJSONError(root, m_trace_session_file);
+  }
+
+  ParsePTCPU(session.trace.pt_cpu);
+  for (const TraceSessionFileParser::JSONProcess &process : session.processes) {
+    if (llvm::Error err = ParseProcess(process))
+      return err;
+  }
+  return llvm::Error::success();
+}
+
+llvm::Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
+  if (llvm::Error err = ParseImpl()) {
+    // Delete all targets that were created
+    for (auto target_sp : m_targets)
+      m_debugger.GetTargetList().DeleteTarget(target_sp);
+    m_targets.clear();
+    return std::move(err);
+  }
+
+  return std::make_shared<TraceIntelPT>(m_pt_cpu, m_targets);
+}
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(const Value &value,
+              TraceIntelPTSessionFileParser::JSONPTCPU &pt_cpu, Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("vendor", pt_cpu.vendor) &&
+         o.map("family", pt_cpu.family) && o.map("model", pt_cpu.model) &&
+         o.map("stepping", pt_cpu.stepping);
+}
+
+bool fromJSON(
+    const Value &value,
+    TraceIntelPTSessionFileParser::JSONTraceIntelPTSettings &plugin_settings,
+    Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("pt_cpu", plugin_settings.pt_cpu) &&
+         fromJSON(
+             value,
+             (TraceSessionFileParser::JSONTracePluginSettings &)plugin_settings,
+             path);
+}
+
+} // namespace json
+} // namespace llvm
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -6,13 +6,13 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef liblldb_TraceIntelPT_h_
-#define liblldb_TraceIntelPT_h_
+#ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
 
 #include "intel-pt.h"
 #include "llvm/ADT/Optional.h"
 
-#include "TraceIntelPTSettingsParser.h"
+#include "TraceIntelPTSessionFileParser.h"
 #include "lldb/Target/Trace.h"
 #include "lldb/lldb-private.h"
 
@@ -30,21 +30,44 @@
 
   static void Terminate();
 
-  static lldb::TraceSP CreateInstance();
+  /// Create an instance of this class.
+  ///
+  /// \param[in] trace_session_file
+  ///     The contents of the trace session file. See \a Trace::FindPlugin.
+  ///
+  /// \param[in] session_file_dir
+  ///     The path to the directory that contains the session file. It's used to
+  ///     resolved relative paths in the session file.
+  ///
+  /// \param[in] debugger
+  ///     The debugger instance where new Targets will be created as part of the
+  ///     JSON data parsing.
+  ///
+  /// \param[in] error
+  ///     A \a Status instance where errors will be stored if the Trace instance
+  ///     could not be created.
+  ///
+  /// \return
+  ///     A trace instance or a null pointer if there were errors.
+  static lldb::TraceSP
+  CreateInstance(const llvm::json::Value &trace_session_file,
+                 llvm::StringRef session_file_dir,
+                 lldb_private::Debugger &debugger, lldb_private::Status &error);
 
   static lldb_private::ConstString GetPluginNameStatic();
 
   uint32_t GetPluginVersion() override;
   /// \}
 
-protected:
-  TraceIntelPT() : Trace() {}
-
-  std::unique_ptr<lldb_private::TraceSettingsParser> CreateParser() override;
+  TraceIntelPT(const pt_cpu &pt_cpu, const std::vector<lldb::TargetSP> &targets)
+      : Trace(), m_pt_cpu(pt_cpu) {
+    for (auto target_sp : targets)
+      m_targets.push_back(target_sp);
+  }
 
 private:
-  friend class TraceIntelPTSettingsParser;
   pt_cpu m_pt_cpu;
+  std::vector<std::weak_ptr<lldb_private::Target>> m_targets;
 };
 
-#endif // liblldb_TraceIntelPT_h_
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -8,7 +8,7 @@
 
 #include "TraceIntelPT.h"
 
-#include "TraceIntelPTSettingsParser.h"
+#include "TraceIntelPTSessionFileParser.h"
 #include "lldb/Core/PluginManager.h"
 
 using namespace lldb;
@@ -18,8 +18,9 @@
 LLDB_PLUGIN_DEFINE_ADV(TraceIntelPT, TraceIntelPT)
 
 void TraceIntelPT::Initialize() {
-  PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor Trace",
-                                CreateInstance);
+  PluginManager::RegisterPlugin(
+      GetPluginNameStatic(), "Intel Processor Trace", CreateInstance,
+      TraceIntelPTSessionFileParser::GetSchema().data());
 }
 
 void TraceIntelPT::Terminate() {
@@ -31,11 +32,6 @@
   return g_name;
 }
 
-std::unique_ptr<lldb_private::TraceSettingsParser>
-TraceIntelPT::CreateParser() {
-  return std::make_unique<TraceIntelPTSettingsParser>(*this);
-}
-
 //------------------------------------------------------------------
 // PluginInterface protocol
 //------------------------------------------------------------------
@@ -46,6 +42,17 @@
 
 void TraceIntelPT::Dump(lldb_private::Stream *s) const {}
 
-lldb::TraceSP TraceIntelPT::CreateInstance() {
-  return lldb::TraceSP(new TraceIntelPT());
+lldb::TraceSP
+TraceIntelPT::CreateInstance(const llvm::json::Value &trace_session_file,
+                             llvm::StringRef session_file_dir,
+                             Debugger &debugger, Status &error) {
+  if (llvm::Expected<lldb::TraceSP> instance =
+          TraceIntelPTSessionFileParser(debugger, trace_session_file,
+                                        session_file_dir)
+              .Parse())
+    return *instance;
+  else {
+    error = Status(instance.takeError());
+    return lldb::TraceSP();
+  }
 }
Index: lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h
@@ -0,0 +1,49 @@
+//===-- ThreadIntelPT.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_THREADINTELPT_H
+#define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_THREADINTELPT_H
+
+#include "lldb/Target/Thread.h"
+
+class ThreadIntelPT : public lldb_private::Thread {
+public:
+  /// Create an Intel PT-traced thread.
+  ///
+  /// \param[in] process
+  ///     The process that owns this thread.
+  ///
+  /// \param[in] tid
+  ///     The thread id of this thread.
+  ///
+  /// \param[in] trace_file
+  ///     The trace file for this thread.
+  ///
+  /// \param[in] pt_cpu
+  ///     The Intel CPU information required to decode the \a trace_file.
+  ThreadIntelPT(lldb_private::Process &process, lldb::tid_t tid,
+                const lldb_private::FileSpec &trace_file)
+      : Thread(process, tid), m_trace_file(trace_file) {}
+
+  void RefreshStateAfterStop() override;
+
+  lldb::RegisterContextSP GetRegisterContext() override;
+
+  lldb::RegisterContextSP
+  CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+
+protected:
+  bool CalculateStopInfo() override;
+
+  lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+private:
+  lldb_private::FileSpec m_trace_file;
+};
+
+#endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_THREADINTELPT_H
Index: lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.cpp
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.cpp
@@ -0,0 +1,37 @@
+//===-- ThreadIntelPT.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 "ThreadIntelPT.h"
+
+#include <memory>
+
+#include "Plugins/Process/Utility/RegisterContextHistory.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/RegisterContext.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+void ThreadIntelPT::RefreshStateAfterStop() {}
+
+RegisterContextSP ThreadIntelPT::GetRegisterContext() {
+  if (!m_reg_context_sp) {
+    m_reg_context_sp = CreateRegisterContextForFrame(nullptr);
+  }
+  return m_reg_context_sp;
+}
+
+RegisterContextSP
+ThreadIntelPT::CreateRegisterContextForFrame(StackFrame *frame) {
+  // Eventually this will calculate the register context based on the current
+  // trace position.
+  return std::make_shared<RegisterContextHistory>(
+      *this, 0, GetProcess()->GetAddressByteSize(), LLDB_INVALID_ADDRESS);
+}
+
+bool ThreadIntelPT::CalculateStopInfo() { return false; }
Index: lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
+++ lldb/source/Plugins/Trace/intel-pt/CMakeLists.txt
@@ -11,7 +11,8 @@
 
 add_lldb_library(lldbPluginTraceIntelPT PLUGIN
   TraceIntelPT.cpp
-  TraceIntelPTSettingsParser.cpp
+  TraceIntelPTSessionFileParser.cpp
+  ThreadIntelPT.cpp
 
   LINK_LIBS
     lldbCore
Index: lldb/source/Core/PluginManager.cpp
===================================================================
--- lldb/source/Core/PluginManager.cpp
+++ lldb/source/Core/PluginManager.cpp
@@ -1007,7 +1007,16 @@
 
 #pragma mark Trace
 
-typedef PluginInstance<TraceCreateInstance> TraceInstance;
+struct TraceInstance : public PluginInstance<TraceCreateInstance> {
+  TraceInstance(ConstString name, std::string description,
+                CallbackType create_callback, std::string schema)
+      : PluginInstance<TraceCreateInstance>(name, std::move(description),
+                                            create_callback),
+        schema(std::move(schema)) {}
+
+  std::string schema;
+};
+
 typedef PluginInstances<TraceInstance> TraceInstances;
 
 static TraceInstances &GetTraceInstances() {
@@ -1016,8 +1025,10 @@
 }
 
 bool PluginManager::RegisterPlugin(ConstString name, const char *description,
-                                   TraceCreateInstance create_callback) {
-  return GetTraceInstances().RegisterPlugin(name, description, create_callback);
+                                   TraceCreateInstance create_callback,
+                                   const char *schema) {
+  return GetTraceInstances().RegisterPlugin(name, description, create_callback,
+                                            schema);
 }
 
 bool PluginManager::UnregisterPlugin(TraceCreateInstance create_callback) {
@@ -1029,6 +1040,13 @@
   return GetTraceInstances().GetCallbackForName(plugin_name);
 }
 
+const char *PluginManager::GetTraceSchema(ConstString name) {
+  for (const TraceInstance &instance : GetTraceInstances().GetInstances())
+    if (instance.name == name)
+      return instance.schema.c_str();
+  return nullptr;
+}
+
 #pragma mark UnwindAssembly
 
 typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance;
Index: lldb/source/Commands/CommandObjectTrace.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTrace.cpp
+++ lldb/source/Commands/CommandObjectTrace.cpp
@@ -71,7 +71,7 @@
 
   CommandObjectTraceLoad(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "trace load",
-                            "Load processor trace data from a JSON file.",
+                            "Load a processor trace session from a JSON file.",
                             "trace load"),
         m_options() {}
 
@@ -82,8 +82,9 @@
 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.AppendError(
+          "a single path to a JSON file containing a trace session"
+          "is required");
       result.SetStatus(eReturnStatusFailed);
       return false;
     }
@@ -105,13 +106,14 @@
           buffer_or_error.getError().message().c_str()));
     }
 
-    llvm::Expected<json::Value> settings =
+    llvm::Expected<json::Value> session_file =
         json::parse(buffer_or_error.get()->getBuffer().str());
-    if (!settings)
-      return end_with_failure(settings.takeError());
+    if (!session_file)
+      return end_with_failure(session_file.takeError());
 
-    if (Expected<lldb::TraceSP> traceOrErr = Trace::FindPlugin(
-            GetDebugger(), *settings, json_file.GetDirectory().AsCString())) {
+    if (Expected<lldb::TraceSP> traceOrErr =
+            Trace::FindPlugin(GetDebugger(), *session_file,
+                              json_file.GetDirectory().AsCString())) {
       lldb::TraceSP trace_sp = traceOrErr.get();
       if (m_options.m_verbose)
         result.AppendMessageWithFormat("loading trace with plugin %s\n",
@@ -255,12 +257,10 @@
 
     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 (Expected<StringRef> schemaOrErr = Trace::FindPluginSchema(plugin_name))
+      result.AppendMessage(*schemaOrErr);
+    else
+      error.SetErrorString(llvm::toString(schemaOrErr.takeError()));
 
     if (error.Success()) {
       result.SetStatus(eReturnStatusSuccessFinishResult);
Index: lldb/include/lldb/lldb-private-interfaces.h
===================================================================
--- lldb/include/lldb/lldb-private-interfaces.h
+++ lldb/include/lldb/lldb-private-interfaces.h
@@ -21,6 +21,7 @@
 namespace llvm {
 namespace json {
 class Object;
+class Value;
 }
 } // namespace llvm
 
@@ -110,7 +111,10 @@
                                            const char *repl_options);
 typedef int (*ComparisonFunction)(const void *, const void *);
 typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
-typedef lldb::TraceSP (*TraceCreateInstance)();
+typedef lldb::TraceSP (*TraceCreateInstance)(
+    const llvm::json::Value &trace_session_file,
+    llvm::StringRef session_file_dir, lldb_private::Debugger &debugger,
+    lldb_private::Status &status);
 
 } // namespace lldb_private
 
Index: lldb/include/lldb/lldb-forward.h
===================================================================
--- lldb/include/lldb/lldb-forward.h
+++ lldb/include/lldb/lldb-forward.h
@@ -227,7 +227,7 @@
 class ThreadPlanTracer;
 class ThreadSpec;
 class Trace;
-class TraceSettingsParser;
+class TraceSessionFileParser;
 class TraceOptions;
 class Type;
 class TypeAndOrName;
Index: lldb/include/lldb/Target/TraceSettingsParser.h
===================================================================
--- lldb/include/lldb/Target/TraceSettingsParser.h
+++ /dev/null
@@ -1,200 +0,0 @@
-//===-- 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:
-  struct JSONAddress {
-    lldb::addr_t value;
-  };
-
-  struct JSONModule {
-    std::string system_path;
-    llvm::Optional<std::string> file;
-    JSONAddress load_address;
-    llvm::Optional<std::string> uuid;
-  };
-
-  struct JSONThread {
-    int64_t tid;
-    std::string trace_file;
-  };
-
-  struct JSONProcess {
-    int64_t pid;
-    std::string triple;
-    std::vector<JSONThread> threads;
-    std::vector<JSONModule> modules;
-  };
-
-  struct JSONTracePluginSettings {
-    std::string type;
-  };
-
-  struct JSONTraceSettings {
-    std::vector<JSONProcess> processes;
-    JSONTracePluginSettings trace;
-  };
-
-  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::Value &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.
-  ///
-  /// \param[in] plugin_settings
-  ///   The settings to parse specific to the plugin.
-  ///
-  /// \return
-  ///   An error object containing the reason if there is a failure.
-  virtual llvm::Error
-  ParsePluginSettings(const llvm::json::Value &plugin_settings) = 0;
-
-  /// Create a user-friendly error message upon a JSON-parsing failure using the
-  /// \a json::ObjectMapper functionality.
-  ///
-  /// \param[in] root
-  ///   The \a llvm::json::Path::Root used to parse the JSON \a value.
-  ///
-  /// \param[in] value
-  ///   The json value that failed to parse.
-  ///
-  /// \return
-  ///   An \a llvm::Error containing the user-friendly error message.
-  llvm::Error CreateJSONError(llvm::json::Path::Root &root,
-                              const llvm::json::Value &value);
-
-private:
-  /// Resolve non-absolute paths relativeto the settings folder
-  void NormalizePath(lldb_private::FileSpec &file_spec);
-
-  llvm::Error ParseProcess(lldb_private::Debugger &debugger,
-                           const JSONProcess &process);
-  void ParseThread(lldb::ProcessSP &process_sp, const JSONThread &thread);
-  llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module);
-  llvm::Error ParseSettingsImpl(lldb_private::Debugger &debugger,
-                                const llvm::json::Value &settings);
-
-  Trace &m_trace;
-
-protected:
-  /// Objects created as product of the parsing
-  /// \{
-  /// 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 llvm {
-namespace json {
-
-inline bool fromJSON(const llvm::json::Value &value,
-                     lldb_private::TraceSettingsParser::JSONAddress &address,
-                     llvm::json::Path path) {
-  llvm::Optional<llvm::StringRef> s = value.getAsString();
-  if (s.hasValue() && !s->getAsInteger(0, address.value))
-    return true;
-
-  path.report("expected numeric string");
-  return false;
-}
-
-inline bool fromJSON(const llvm::json::Value &value,
-                     lldb_private::TraceSettingsParser::JSONModule &module,
-                     llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("systemPath", module.system_path) &&
-         o.map("file", module.file) &&
-         o.map("loadAddress", module.load_address) &&
-         o.map("uuid", module.uuid);
-}
-
-inline bool fromJSON(const llvm::json::Value &value,
-                     lldb_private::TraceSettingsParser::JSONThread &thread,
-                     llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("tid", thread.tid) && o.map("traceFile", thread.trace_file);
-}
-
-inline bool fromJSON(const llvm::json::Value &value,
-                     lldb_private::TraceSettingsParser::JSONProcess &process,
-                     llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
-         o.map("threads", process.threads) && o.map("modules", process.modules);
-}
-
-inline bool fromJSON(
-    const llvm::json::Value &value,
-    lldb_private::TraceSettingsParser::JSONTracePluginSettings &plugin_settings,
-    llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("type", plugin_settings.type);
-}
-
-inline bool
-fromJSON(const llvm::json::Value &value,
-         lldb_private::TraceSettingsParser::JSONTraceSettings &settings,
-         llvm::json::Path path) {
-  llvm::json::ObjectMapper o(value, path);
-  return o && o.map("trace", settings.trace) &&
-         o.map("processes", settings.processes);
-}
-
-} // namespace json
-} // namespace llvm
-
-#endif // LLDB_TARGET_TRACE_SETTINGS_PARSER_H
Index: lldb/include/lldb/Target/TraceSessionFileParser.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Target/TraceSessionFileParser.h
@@ -0,0 +1,138 @@
+//===-- TraceSessionFileParser.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_SESSION_PARSER_H
+#define LLDB_TARGET_TRACE_SESSION_PARSER_H
+
+#include "llvm/Support/JSON.h"
+
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+
+/// \class TraceSessionFileParser TraceSessionFileParser.h
+///
+/// Base class for parsing the common information of JSON trace session files.
+/// Contains the basic C++ structs that represent the JSON data, which include
+/// \a JSONTraceSession as the root object.
+///
+/// See \a Trace::FindPlugin for more information regarding these JSON files.
+class TraceSessionFileParser {
+public:
+  /// C++ structs representing the JSON trace session.
+  /// \{
+  struct JSONAddress {
+    lldb::addr_t value;
+  };
+
+  struct JSONModule {
+    std::string system_path;
+    llvm::Optional<std::string> file;
+    JSONAddress load_address;
+    llvm::Optional<std::string> uuid;
+  };
+
+  struct JSONThread {
+    int64_t tid;
+    std::string trace_file;
+  };
+
+  struct JSONProcess {
+    int64_t pid;
+    std::string triple;
+    std::vector<JSONThread> threads;
+    std::vector<JSONModule> modules;
+  };
+
+  struct JSONTracePluginSettings {
+    std::string type;
+  };
+
+  /// The trace plug-in implementation should provide its own TPluginSettings,
+  /// which corresponds to the "trace" section of the schema.
+  template <class TPluginSettings> struct JSONTraceSession {
+    std::vector<JSONProcess> processes;
+    TPluginSettings trace;
+  };
+  /// \}
+
+  TraceSessionFileParser(llvm::StringRef session_file_dir,
+                         llvm::StringRef schema)
+      : m_session_file_dir(session_file_dir), m_schema(schema) {}
+
+  /// Build the full schema for a Trace plug-in.
+  ///
+  /// \param[in] plugin_schema
+  ///   The subschema that corresponds to the "trace" section of the schema.
+  ///
+  /// \return
+  ///   The full schema containing the common attributes and the plug-in
+  ///   specific attributes.
+  static std::string BuildSchema(llvm::StringRef plugin_schema);
+
+protected:
+  /// Resolve non-absolute paths relative to the session file folder. It
+  /// modifies the given file_spec.
+  void NormalizePath(lldb_private::FileSpec &file_spec);
+
+  llvm::Error ParseModule(lldb::TargetSP &target_sp, const JSONModule &module);
+
+  /// Create a user-friendly error message upon a JSON-parsing failure using the
+  /// \a json::ObjectMapper functionality.
+  ///
+  /// \param[in] root
+  ///   The \a llvm::json::Path::Root used to parse the JSON \a value.
+  ///
+  /// \param[in] value
+  ///   The json value that failed to parse.
+  ///
+  /// \return
+  ///   An \a llvm::Error containing the user-friendly error message.
+  llvm::Error CreateJSONError(llvm::json::Path::Root &root,
+                              const llvm::json::Value &value);
+
+  std::string m_session_file_dir;
+  llvm::StringRef m_schema;
+};
+} // namespace lldb_private
+
+namespace llvm {
+namespace json {
+
+using namespace lldb_private;
+
+inline bool fromJSON(const Value &value,
+                     TraceSessionFileParser::JSONAddress &address, Path path);
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONModule &module,
+              Path path);
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONThread &thread,
+              Path path);
+
+bool fromJSON(const Value &value, TraceSessionFileParser::JSONProcess &process,
+              Path path);
+
+bool fromJSON(const Value &value,
+              TraceSessionFileParser::JSONTracePluginSettings &plugin_settings,
+              Path path);
+
+template <class TPluginSettings>
+inline bool
+fromJSON(const Value &value,
+         TraceSessionFileParser::JSONTraceSession<TPluginSettings> &session,
+         Path path) {
+  ObjectMapper o(value, path);
+  return o && o.map("trace", session.trace) &&
+         o.map("processes", session.processes);
+}
+
+} // namespace json
+} // namespace llvm
+
+#endif // LLDB_TARGET_TRACE_SESSION_PARSER_H
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -12,7 +12,6 @@
 #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"
 
@@ -72,70 +71,34 @@
   ///       correctly.
   ///
   /// \param[in] debugger
-  ///     The debugger instance were new Target will be created as part of the
+  ///     The debugger instance where new Targets will be created as part of the
   ///     JSON data parsing.
   ///
-  /// \param[in] settings
-  ///     JSON object describing a trace.
+  /// \param[in] trace_session_file
+  ///     The contents of the trace session file describing the trace session.
+  ///     See \a TraceSessionFileParser::BuildSchema for more information about
+  ///     the schema of this JSON file.
   ///
-  /// \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.
+  /// \param[in] session_file_dir
+  ///     The path to the directory that contains the session file. It's used to
+  ///     resolved relative paths in the session file.
   static llvm::Expected<lldb::TraceSP>
-  FindPlugin(Debugger &debugger, const llvm::json::Value &settings,
-             llvm::StringRef settings_dir);
+  FindPlugin(Debugger &debugger, const llvm::json::Value &trace_session_file,
+             llvm::StringRef session_file_dir);
 
-  /// Create an instance of trace plug-in by name.
+  /// Get the schema of a Trace plug-in given its 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::Value &settings,
-                            llvm::StringRef settings_dir);
-
-  /// Get the JSON schema of the settings for the trace plug-in.
-  llvm::StringRef GetSchema();
+  static llvm::Expected<llvm::StringRef>
+  FindPluginSchema(llvm::StringRef plugin_name);
 
 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
Index: lldb/include/lldb/Core/PluginManager.h
===================================================================
--- lldb/include/lldb/Core/PluginManager.h
+++ lldb/include/lldb/Core/PluginManager.h
@@ -332,12 +332,15 @@
 
   // Trace
   static bool RegisterPlugin(ConstString name, const char *description,
-                             TraceCreateInstance create_callback);
+                             TraceCreateInstance create_callback,
+                             const char *schema);
 
   static bool UnregisterPlugin(TraceCreateInstance create_callback);
 
   static TraceCreateInstance GetTraceCreateCallback(ConstString plugin_name);
 
+  static const char *GetTraceSchema(ConstString name);
+
   // UnwindAssembly
   static bool RegisterPlugin(ConstString name, const char *description,
                              UnwindAssemblyCreateInstance create_callback);
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to