1602497d6SWalter Erquinigo //===-- TraceIntelPTJSONStructs.cpp ---------------------------------------===//
2602497d6SWalter Erquinigo //
3602497d6SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4602497d6SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
5602497d6SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6602497d6SWalter Erquinigo //
7602497d6SWalter Erquinigo //===----------------------------------------------------------------------===//
8602497d6SWalter Erquinigo 
9602497d6SWalter Erquinigo #include "TraceIntelPTJSONStructs.h"
10602497d6SWalter Erquinigo 
11602497d6SWalter Erquinigo #include "llvm/Support/JSON.h"
12602497d6SWalter Erquinigo #include <string>
13602497d6SWalter Erquinigo 
14602497d6SWalter Erquinigo using namespace lldb;
15602497d6SWalter Erquinigo using namespace lldb_private;
16602497d6SWalter Erquinigo using namespace lldb_private::trace_intel_pt;
17602497d6SWalter Erquinigo using namespace llvm;
18fc5ef57cSWalter Erquinigo using namespace llvm::json;
19602497d6SWalter Erquinigo 
20fc5ef57cSWalter Erquinigo namespace lldb_private {
21fc5ef57cSWalter Erquinigo namespace trace_intel_pt {
22602497d6SWalter Erquinigo 
GetCpuIds()23*b8dcd0baSWalter Erquinigo Optional<std::vector<lldb::cpu_id_t>> JSONTraceBundleDescription::GetCpuIds() {
246a5355e8SWalter Erquinigo   if (!cpus)
25fc5ef57cSWalter Erquinigo     return None;
266a5355e8SWalter Erquinigo   std::vector<lldb::cpu_id_t> cpu_ids;
276a5355e8SWalter Erquinigo   for (const JSONCpu &cpu : *cpus)
286a5355e8SWalter Erquinigo     cpu_ids.push_back(cpu.id);
296a5355e8SWalter Erquinigo   return cpu_ids;
30602497d6SWalter Erquinigo }
31602497d6SWalter Erquinigo 
toJSON(const JSONModule & module)32fc5ef57cSWalter Erquinigo json::Value toJSON(const JSONModule &module) {
33fc5ef57cSWalter Erquinigo   json::Object json_module;
34fc5ef57cSWalter Erquinigo   json_module["systemPath"] = module.system_path;
35fc5ef57cSWalter Erquinigo   if (module.file)
36fc5ef57cSWalter Erquinigo     json_module["file"] = *module.file;
379f45f23dSWalter Erquinigo   json_module["loadAddress"] = toJSON(module.load_address, true);
38fc5ef57cSWalter Erquinigo   if (module.uuid)
39fc5ef57cSWalter Erquinigo     json_module["uuid"] = *module.uuid;
40fc5ef57cSWalter Erquinigo   return std::move(json_module);
41602497d6SWalter Erquinigo }
42602497d6SWalter Erquinigo 
fromJSON(const json::Value & value,JSONModule & module,Path path)43fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, JSONModule &module, Path path) {
44fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
45fc5ef57cSWalter Erquinigo   return o && o.map("systemPath", module.system_path) &&
46fc5ef57cSWalter Erquinigo          o.map("file", module.file) &&
47fc5ef57cSWalter Erquinigo          o.map("loadAddress", module.load_address) &&
48fc5ef57cSWalter Erquinigo          o.map("uuid", module.uuid);
49fc5ef57cSWalter Erquinigo }
50fc5ef57cSWalter Erquinigo 
toJSON(const JSONThread & thread)51fc5ef57cSWalter Erquinigo json::Value toJSON(const JSONThread &thread) {
52a19fcc2bSWalter Erquinigo   json::Object obj{{"tid", thread.tid}};
536a5355e8SWalter Erquinigo   if (thread.ipt_trace)
546a5355e8SWalter Erquinigo     obj["iptTrace"] = *thread.ipt_trace;
55a19fcc2bSWalter Erquinigo   return obj;
56fc5ef57cSWalter Erquinigo }
57fc5ef57cSWalter Erquinigo 
fromJSON(const json::Value & value,JSONThread & thread,Path path)58fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, JSONThread &thread, Path path) {
59fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
606a5355e8SWalter Erquinigo   return o && o.map("tid", thread.tid) && o.map("iptTrace", thread.ipt_trace);
61fc5ef57cSWalter Erquinigo }
62fc5ef57cSWalter Erquinigo 
toJSON(const JSONProcess & process)63fc5ef57cSWalter Erquinigo json::Value toJSON(const JSONProcess &process) {
64fc5ef57cSWalter Erquinigo   return Object{
65fc5ef57cSWalter Erquinigo       {"pid", process.pid},
66fc5ef57cSWalter Erquinigo       {"triple", process.triple},
67fc5ef57cSWalter Erquinigo       {"threads", process.threads},
68fc5ef57cSWalter Erquinigo       {"modules", process.modules},
69fc5ef57cSWalter Erquinigo   };
70fc5ef57cSWalter Erquinigo }
71fc5ef57cSWalter Erquinigo 
fromJSON(const json::Value & value,JSONProcess & process,Path path)72fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, JSONProcess &process, Path path) {
73fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
74fc5ef57cSWalter Erquinigo   return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
75fc5ef57cSWalter Erquinigo          o.map("threads", process.threads) && o.map("modules", process.modules);
76fc5ef57cSWalter Erquinigo }
77fc5ef57cSWalter Erquinigo 
toJSON(const JSONCpu & cpu)786a5355e8SWalter Erquinigo json::Value toJSON(const JSONCpu &cpu) {
79fc5ef57cSWalter Erquinigo   return Object{
806a5355e8SWalter Erquinigo       {"id", cpu.id},
816a5355e8SWalter Erquinigo       {"iptTrace", cpu.ipt_trace},
826a5355e8SWalter Erquinigo       {"contextSwitchTrace", cpu.context_switch_trace},
83fc5ef57cSWalter Erquinigo   };
84fc5ef57cSWalter Erquinigo }
85fc5ef57cSWalter Erquinigo 
fromJSON(const json::Value & value,JSONCpu & cpu,Path path)866a5355e8SWalter Erquinigo bool fromJSON(const json::Value &value, JSONCpu &cpu, Path path) {
87fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
886a5355e8SWalter Erquinigo   uint64_t cpu_id;
896a5355e8SWalter Erquinigo   if (!(o && o.map("id", cpu_id) && o.map("iptTrace", cpu.ipt_trace) &&
906a5355e8SWalter Erquinigo         o.map("contextSwitchTrace", cpu.context_switch_trace)))
91fc5ef57cSWalter Erquinigo     return false;
926a5355e8SWalter Erquinigo   cpu.id = cpu_id;
93fc5ef57cSWalter Erquinigo   return true;
94fc5ef57cSWalter Erquinigo }
95fc5ef57cSWalter Erquinigo 
toJSON(const pt_cpu & cpu_info)96fc5ef57cSWalter Erquinigo json::Value toJSON(const pt_cpu &cpu_info) {
97fc5ef57cSWalter Erquinigo   return Object{
98fc5ef57cSWalter Erquinigo       {"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"},
99fc5ef57cSWalter Erquinigo       {"family", cpu_info.family},
100602497d6SWalter Erquinigo       {"model", cpu_info.model},
101602497d6SWalter Erquinigo       {"stepping", cpu_info.stepping},
102fc5ef57cSWalter Erquinigo   };
103602497d6SWalter Erquinigo }
104602497d6SWalter Erquinigo 
fromJSON(const json::Value & value,pt_cpu & cpu_info,Path path)105fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) {
106fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
107fc5ef57cSWalter Erquinigo   std::string vendor;
108fc5ef57cSWalter Erquinigo   uint64_t family, model, stepping;
109561a61fbSWalter Erquinigo   if (!(o && o.map("vendor", vendor) && o.map("family", family) &&
110561a61fbSWalter Erquinigo         o.map("model", model) && o.map("stepping", stepping)))
111fc5ef57cSWalter Erquinigo     return false;
112fc5ef57cSWalter Erquinigo   cpu_info.vendor = vendor == "GenuineIntel" ? pcv_intel : pcv_unknown;
113fc5ef57cSWalter Erquinigo   cpu_info.family = family;
114fc5ef57cSWalter Erquinigo   cpu_info.model = model;
115fc5ef57cSWalter Erquinigo   cpu_info.stepping = stepping;
116fc5ef57cSWalter Erquinigo   return true;
117602497d6SWalter Erquinigo }
118602497d6SWalter Erquinigo 
toJSON(const JSONTraceBundleDescription & bundle_description)119*b8dcd0baSWalter Erquinigo json::Value toJSON(const JSONTraceBundleDescription &bundle_description) {
120*b8dcd0baSWalter Erquinigo   return Object{{"type", bundle_description.type},
121*b8dcd0baSWalter Erquinigo                 {"processes", bundle_description.processes},
122fc5ef57cSWalter Erquinigo                 // We have to do this because the compiler fails at doing it
123fc5ef57cSWalter Erquinigo                 // automatically because pt_cpu is not in a namespace
124*b8dcd0baSWalter Erquinigo                 {"cpuInfo", toJSON(bundle_description.cpu_info)},
125*b8dcd0baSWalter Erquinigo                 {"cpus", bundle_description.cpus},
126*b8dcd0baSWalter Erquinigo                 {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion}};
127602497d6SWalter Erquinigo }
128602497d6SWalter Erquinigo 
fromJSON(const json::Value & value,JSONTraceBundleDescription & bundle_description,Path path)129*b8dcd0baSWalter Erquinigo bool fromJSON(const json::Value &value, JSONTraceBundleDescription &bundle_description, Path path) {
130fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
131*b8dcd0baSWalter Erquinigo   if (!(o && o.map("processes", bundle_description.processes) &&
132*b8dcd0baSWalter Erquinigo         o.map("type", bundle_description.type) && o.map("cpus", bundle_description.cpus) &&
133*b8dcd0baSWalter Erquinigo         o.map("tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion)))
134fc5ef57cSWalter Erquinigo     return false;
135*b8dcd0baSWalter Erquinigo   if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) {
1361a3f9969SWalter Erquinigo     path.report(
1376a5355e8SWalter Erquinigo         "\"tscPerfZeroConversion\" is required when \"cpus\" is provided");
1381a3f9969SWalter Erquinigo     return false;
1391a3f9969SWalter Erquinigo   }
140fc5ef57cSWalter Erquinigo   // We have to do this because the compiler fails at doing it automatically
141fc5ef57cSWalter Erquinigo   // because pt_cpu is not in a namespace
142*b8dcd0baSWalter Erquinigo   if (!fromJSON(*value.getAsObject()->get("cpuInfo"), bundle_description.cpu_info,
143fc5ef57cSWalter Erquinigo                 path.field("cpuInfo")))
144fc5ef57cSWalter Erquinigo     return false;
145fc5ef57cSWalter Erquinigo   return true;
146fc5ef57cSWalter Erquinigo }
147fc5ef57cSWalter Erquinigo 
148fc5ef57cSWalter Erquinigo } // namespace trace_intel_pt
149fc5ef57cSWalter Erquinigo } // namespace lldb_private
150