This revision was not accepted when it landed; it landed in state "Needs
Review".
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGea1f49741ec4: [intel pt] Refactor parsing (authored by
Walter Erquinigo <[email protected]>).
Changed prior to commit:
https://reviews.llvm.org/D88841?vs=297075&id=297368#toc
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)
+ : 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)
+LLDB_PLUGIN_DEFINE(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,31 @@
/// 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);
-
- /// Get the JSON schema of the settings for the trace plug-in.
- llvm::StringRef GetSchema();
-
-protected:
- Trace() {}
-
- /// The actual plug-in should define its own implementation of \a
- /// TraceSettingsParser for doing any custom parsing.
- virtual std::unique_ptr<lldb_private::TraceSettingsParser> CreateParser() = 0;
-
-private:
- Trace(const Trace &) = delete;
- const Trace &operator=(const Trace &) = delete;
-
-protected:
- friend class TraceSettingsParser;
- /// JSON object that holds all settings for this trace session.
- llvm::json::Object m_settings;
- /// The directory that contains the settings file.
- std::string m_settings_dir;
-
- std::map<lldb::pid_t, std::map<lldb::tid_t, lldb_private::FileSpec>>
- m_thread_to_trace_file_map;
- std::vector<lldb::TargetSP> m_targets;
+ /// The JSON schema of this Trace plug-in.
+ virtual llvm::StringRef GetSchema() = 0;
};
} // 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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits