wallace updated this revision to Diff 297075.
wallace added a comment.

- Added “trace schema all”, following the pattern from "trace <command> all", 
and added a test for this.
- Created a non-static version of GetSchema in Trace.h
- Cannot delete Trace() {}, as there’s a compilation error. Could be because 
some constructors have been marked as deleted, so the compiler wants explicit 
declarations.
- Created the lldb_private::trace_intel_pt namespace
- Deleted all unnecessary namespace and “using namespace” usages.
- Using StringRef more ubiquitously now and other small fixes requested by Pavel


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
  lldb/test/API/commands/trace/TestTraceSchema.py

Index: lldb/test/API/commands/trace/TestTraceSchema.py
===================================================================
--- lldb/test/API/commands/trace/TestTraceSchema.py
+++ lldb/test/API/commands/trace/TestTraceSchema.py
@@ -20,3 +20,15 @@
     def testInvalidPluginSchema(self):
         self.expect("trace schema invalid-plugin", error=True,
             substrs=['error: no trace plug-in matches the specified type: "invalid-plugin"'])
+
+    def testAllSchemas(self):
+        self.expect("trace schema all", substrs=['''{
+  "trace": {
+    "type": "intel-pt",
+    "pt_cpu": {
+      "vendor": "intel" | "unknown",
+      "family": integer,
+      "model": integer,
+      "stepping": integer
+    }
+  },'''])
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,133 @@
+//===-- 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);
+}
+
+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();
+}
+
+Error TraceSessionFileParser::CreateJSONError(json::Path::Root &root,
+                                              const 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",
+      toString(root.getError()).c_str(), os.str().c_str(), m_schema.data());
+}
+
+std::string TraceSessionFileParser::BuildSchema(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) {
+  Optional<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,78 +18,61 @@
 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;
 };
 
 namespace llvm {
 namespace json {
 
-bool fromJSON(const json::Value &value,
-              JSONSimplePluginSettings &plugin_settings, json::Path path) {
+bool fromJSON(const Value &value, JSONSimplePluginSettings &plugin_settings,
+              Path path) {
   json::ObjectMapper o(value, path);
   return o && o.map("type", plugin_settings.type);
 }
 
-bool fromJSON(const json::Value &value, JSONSimpleTraceSettings &settings,
-              json::Path path) {
+bool fromJSON(const Value &value, JSONSimpleTraceSession &session, 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))
-    return root.getError();
-
-  ConstString plugin_name(json_settings.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);
-    return instance;
-  }
-
+static Error createInvalidPlugInError(StringRef plugin_name) {
   return createStringError(
       std::errc::invalid_argument,
       "no trace plug-in matches the specified type: \"%s\"",
-      plugin_name.AsCString());
+      plugin_name.data());
 }
 
-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();
+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();
 
-  return createStringError(
-      std::errc::invalid_argument,
-      "no trace plug-in matches the specified type: \"%s\"",
-      plugin_name.AsCString());
+  ConstString plugin_name(json_session.trace.type);
+  if (auto create_callback = PluginManager::GetTraceCreateCallback(plugin_name))
+    return create_callback(trace_session_file, session_file_dir, debugger);
+
+  return createInvalidPlugInError(json_session.trace.type);
 }
 
-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;
+Expected<StringRef> Trace::FindPluginSchema(StringRef name) {
+  ConstString plugin_name(name);
+  StringRef schema = PluginManager::GetTraceSchema(plugin_name);
+  if (!schema.empty())
+    return schema;
 
-  return llvm::Error::success();
+  return createInvalidPlugInError(name);
 }
-
-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,96 @@
+//===-- 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"
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class TraceIntelPT;
+
+class TraceIntelPTSessionFileParser : public TraceSessionFileParser {
+public:
+  struct JSONPTCPU {
+    std::string vendor;
+    int64_t family;
+    int64_t model;
+    int64_t stepping;
+  };
+
+  struct JSONTraceIntelPTSettings
+      : TraceSessionFileParser::JSONTracePluginSettings {
+    JSONPTCPU pt_cpu;
+  };
+
+  /// See \a TraceSessionFileParser::TraceSessionFileParser for the description
+  /// of these fields.
+  TraceIntelPTSessionFileParser(Debugger &debugger,
+                                const llvm::json::Value &trace_session_file,
+                                llvm::StringRef session_file_dir)
+      : 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 TraceSessionFileParser::JSONProcess &process);
+
+  void ParseThread(lldb::ProcessSP &process_sp,
+                   const TraceSessionFileParser::JSONThread &thread);
+
+  void ParsePTCPU(const JSONPTCPU &pt_cpu);
+
+  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 trace_intel_pt
+} // namespace lldb_private
+
+namespace llvm {
+namespace json {
+
+bool fromJSON(
+    const Value &value,
+    lldb_private::trace_intel_pt::TraceIntelPTSessionFileParser::JSONPTCPU
+        &pt_cpu,
+    Path path);
+
+bool fromJSON(const Value &value,
+              lldb_private::trace_intel_pt::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,135 @@
+//===-- 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 lldb_private::trace_intel_pt;
+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);
+}
+
+Error TraceIntelPTSessionFileParser::ParseProcess(
+    const TraceSessionFileParser::JSONProcess &process) {
+  TargetSP target_sp;
+  Status error = m_debugger.GetTargetList().CreateTarget(
+      m_debugger, /*user_exe_path*/ 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*/ 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 (Error err = ParseModule(target_sp, module))
+      return err;
+  }
+  return 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)};
+}
+
+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 (Error err = ParseProcess(process))
+      return err;
+  }
+  return Error::success();
+}
+
+Expected<TraceSP> TraceIntelPTSessionFileParser::Parse() {
+  if (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,45 +6,71 @@
 //
 //===----------------------------------------------------------------------===//
 
-#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"
 
-class TraceIntelPT : public lldb_private::Trace {
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class TraceIntelPT : public Trace {
 public:
-  void Dump(lldb_private::Stream *s) const override;
+  void Dump(Stream *s) const override;
 
   ~TraceIntelPT() override = default;
 
   /// PluginInterface protocol
   /// \{
-  lldb_private::ConstString GetPluginName() override;
+  ConstString GetPluginName() override;
 
   static void Initialize();
 
   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.
+  ///
+  /// \return
+  ///     A trace instance or an error in case of failures.
+  static llvm::Expected<lldb::TraceSP>
+  CreateInstance(const llvm::json::Value &trace_session_file,
+                 llvm::StringRef session_file_dir, Debugger &debugger);
 
-  static lldb_private::ConstString GetPluginNameStatic();
+  static ConstString GetPluginNameStatic();
 
   uint32_t GetPluginVersion() override;
   /// \}
 
-protected:
-  TraceIntelPT() : Trace() {}
+  llvm::StringRef GetSchema() override;
 
-  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 (const lldb::TargetSP &target_sp : targets)
+      m_targets.push_back(target_sp);
+  }
 
 private:
-  friend class TraceIntelPTSettingsParser;
   pt_cpu m_pt_cpu;
+  std::vector<std::weak_ptr<Target>> m_targets;
 };
 
-#endif // liblldb_TraceIntelPT_h_
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#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,18 +8,20 @@
 
 #include "TraceIntelPT.h"
 
-#include "TraceIntelPTSettingsParser.h"
+#include "TraceIntelPTSessionFileParser.h"
 #include "lldb/Core/PluginManager.h"
 
 using namespace lldb;
 using namespace lldb_private;
+using namespace lldb_private::trace_intel_pt;
 using namespace llvm;
 
 LLDB_PLUGIN_DEFINE_ADV(TraceIntelPT, TraceIntelPT)
 
 void TraceIntelPT::Initialize() {
   PluginManager::RegisterPlugin(GetPluginNameStatic(), "Intel Processor Trace",
-                                CreateInstance);
+                                CreateInstance,
+                                TraceIntelPTSessionFileParser::GetSchema());
 }
 
 void TraceIntelPT::Terminate() {
@@ -31,9 +33,8 @@
   return g_name;
 }
 
-std::unique_ptr<lldb_private::TraceSettingsParser>
-TraceIntelPT::CreateParser() {
-  return std::make_unique<TraceIntelPTSettingsParser>(*this);
+StringRef TraceIntelPT::GetSchema() {
+  return TraceIntelPTSessionFileParser::GetSchema();
 }
 
 //------------------------------------------------------------------
@@ -46,6 +47,10 @@
 
 void TraceIntelPT::Dump(lldb_private::Stream *s) const {}
 
-lldb::TraceSP TraceIntelPT::CreateInstance() {
-  return lldb::TraceSP(new TraceIntelPT());
+Expected<lldb::TraceSP>
+TraceIntelPT::CreateInstance(const json::Value &trace_session_file,
+                             StringRef session_file_dir, Debugger &debugger) {
+  return TraceIntelPTSessionFileParser(debugger, trace_session_file,
+                                       session_file_dir)
+      .Parse();
 }
Index: lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h
===================================================================
--- /dev/null
+++ lldb/source/Plugins/Trace/intel-pt/ThreadIntelPT.h
@@ -0,0 +1,54 @@
+//===-- 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"
+
+namespace lldb_private {
+namespace trace_intel_pt {
+
+class ThreadIntelPT : public 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(Process &process, lldb::tid_t tid, const FileSpec &trace_file)
+      : Thread(process, tid), m_trace_file(trace_file) {}
+
+  void RefreshStateAfterStop() override;
+
+  lldb::RegisterContextSP GetRegisterContext() override;
+
+  lldb::RegisterContextSP
+  CreateRegisterContextForFrame(StackFrame *frame) override;
+
+protected:
+  bool CalculateStopInfo() override;
+
+  lldb::RegisterContextSP m_thread_reg_ctx_sp;
+
+private:
+  FileSpec m_trace_file;
+};
+
+} // namespace trace_intel_pt
+} // namespace lldb_private
+
+#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,38 @@
+//===-- 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;
+using namespace lldb_private::trace_intel_pt;
+
+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
@@ -264,12 +264,13 @@
   const std::vector<Instance> &GetInstances() const { return m_instances; }
   std::vector<Instance> &GetInstances() { return m_instances; }
 
-private:
   Instance *GetInstanceAtIndex(uint32_t idx) {
     if (idx < m_instances.size())
       return &m_instances[idx];
     return nullptr;
   }
+
+private:
   std::vector<Instance> m_instances;
 };
 
@@ -1007,7 +1008,16 @@
 
 #pragma mark Trace
 
-typedef PluginInstance<TraceCreateInstance> TraceInstance;
+struct TraceInstance : public PluginInstance<TraceCreateInstance> {
+  TraceInstance(ConstString name, std::string description,
+                CallbackType create_callback, llvm::StringRef schema)
+      : PluginInstance<TraceCreateInstance>(name, std::move(description),
+                                            create_callback),
+        schema(schema) {}
+
+  llvm::StringRef schema;
+};
+
 typedef PluginInstances<TraceInstance> TraceInstances;
 
 static TraceInstances &GetTraceInstances() {
@@ -1016,8 +1026,10 @@
 }
 
 bool PluginManager::RegisterPlugin(ConstString name, const char *description,
-                                   TraceCreateInstance create_callback) {
-  return GetTraceInstances().RegisterPlugin(name, description, create_callback);
+                                   TraceCreateInstance create_callback,
+                                   llvm::StringRef schema) {
+  return GetTraceInstances().RegisterPlugin(name, description, create_callback,
+                                            schema);
 }
 
 bool PluginManager::UnregisterPlugin(TraceCreateInstance create_callback) {
@@ -1029,6 +1041,19 @@
   return GetTraceInstances().GetCallbackForName(plugin_name);
 }
 
+llvm::StringRef PluginManager::GetTraceSchema(ConstString plugin_name) {
+  for (const TraceInstance &instance : GetTraceInstances().GetInstances())
+    if (instance.name == plugin_name)
+      return instance.schema;
+  return llvm::StringRef();
+}
+
+llvm::StringRef PluginManager::GetTraceSchema(size_t index) {
+  if (TraceInstance *instance = GetTraceInstances().GetInstanceAtIndex(index))
+    return instance->schema;
+  return llvm::StringRef();
+}
+
 #pragma mark UnwindAssembly
 
 typedef PluginInstance<UnwindAssemblyCreateInstance> UnwindAssemblyInstance;
Index: lldb/source/Commands/CommandObjectTrace.cpp
===================================================================
--- lldb/source/Commands/CommandObjectTrace.cpp
+++ lldb/source/Commands/CommandObjectTrace.cpp
@@ -12,6 +12,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 
 #include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Host/OptionParser.h"
 #include "lldb/Interpreter/CommandInterpreter.h"
 #include "lldb/Interpreter/CommandObject.h"
@@ -71,7 +72,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 +83,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 +107,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",
@@ -237,7 +240,8 @@
   CommandObjectTraceSchema(CommandInterpreter &interpreter)
       : CommandObjectParsed(interpreter, "trace schema",
                             "Show the schema of the given trace plugin.",
-                            "trace schema <plug-in>"),
+                            "trace schema <plug-in>. Use the plug-in name "
+                            "\"all\" to see all schemas.\n"),
         m_options() {}
 
   ~CommandObjectTraceSchema() override = default;
@@ -254,12 +258,21 @@
     }
 
     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());
+    if (plugin_name == "all") {
+      size_t index = 0;
+      while (true) {
+        StringRef schema = PluginManager::GetTraceSchema(index++);
+        if (schema.empty())
+          break;
+
+        result.AppendMessage(schema);
+      }
     } else {
-      error.SetErrorString(llvm::toString(traceOrErr.takeError()));
+      if (Expected<StringRef> schemaOrErr =
+              Trace::FindPluginSchema(plugin_name))
+        result.AppendMessage(*schemaOrErr);
+      else
+        error = schemaOrErr.takeError();
     }
 
     if (error.Success()) {
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,9 @@
                                            const char *repl_options);
 typedef int (*ComparisonFunction)(const void *, const void *);
 typedef void (*DebuggerInitializeCallback)(Debugger &debugger);
-typedef lldb::TraceSP (*TraceCreateInstance)();
+typedef llvm::Expected<lldb::TraceSP> (*TraceCreateInstance)(
+    const llvm::json::Value &trace_session_file,
+    llvm::StringRef session_file_dir, lldb_private::Debugger &debugger);
 
 } // 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,142 @@
+//===-- 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_TRACESESSIONPARSER_H
+#define LLDB_TARGET_TRACESESSIONPARSER_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 {
+
+bool fromJSON(const Value &value,
+              lldb_private::TraceSessionFileParser::JSONAddress &address,
+              Path path);
+
+bool fromJSON(const Value &value,
+              lldb_private::TraceSessionFileParser::JSONModule &module,
+              Path path);
+
+bool fromJSON(const Value &value,
+              lldb_private::TraceSessionFileParser::JSONThread &thread,
+              Path path);
+
+bool fromJSON(const Value &value,
+              lldb_private::TraceSessionFileParser::JSONProcess &process,
+              Path path);
+
+bool fromJSON(const Value &value,
+              lldb_private::TraceSessionFileParser::JSONTracePluginSettings
+                  &plugin_settings,
+              Path path);
+
+template <class TPluginSettings>
+bool fromJSON(
+    const Value &value,
+    lldb_private::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_TRACESESSIONPARSER_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,37 @@
   ///       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);
+  static llvm::Expected<llvm::StringRef>
+  FindPluginSchema(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);
+  ///     The JSON schema of this Trace plug-in.
+  virtual llvm::StringRef GetSchema() = 0;
 
-  /// 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;
+  Trace() = default;
 
 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,35 @@
 
   // Trace
   static bool RegisterPlugin(ConstString name, const char *description,
-                             TraceCreateInstance create_callback);
+                             TraceCreateInstance create_callback,
+                             llvm::StringRef schema);
 
   static bool UnregisterPlugin(TraceCreateInstance create_callback);
 
   static TraceCreateInstance GetTraceCreateCallback(ConstString plugin_name);
 
+  /// Get the JSON schema for a trace session file corresponding to the given
+  /// plugin.
+  ///
+  /// \param[in] plugin_name
+  ///     The name of the plugin.
+  ///
+  /// \return
+  ///     An empty \a StringRef if no plugin was found with that plugin name,
+  ///     otherwise the actual schema is returned.
+  static llvm::StringRef GetTraceSchema(ConstString plugin_name);
+
+  /// Get the JSON schema for a trace session file corresponding to the plugin
+  /// given by its index.
+  ///
+  /// \param[in] index
+  ///     The index of the plugin to get the schema of.
+  ///
+  /// \return
+  ///     An empty \a StringRef if the index is greater than or equal to the
+  ///     number plugins, otherwise the actual schema is returned.
+  static llvm::StringRef GetTraceSchema(size_t index);
+
   // 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