1 //===-- TraceIntelPTJSONStructs.cpp ---------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "TraceIntelPTJSONStructs.h"
10 
11 #include "llvm/Support/JSON.h"
12 #include <string>
13 
14 using namespace lldb;
15 using namespace lldb_private;
16 using namespace lldb_private::trace_intel_pt;
17 using namespace llvm;
18 using namespace llvm::json;
19 
20 namespace lldb_private {
21 namespace trace_intel_pt {
22 
23 Optional<std::vector<lldb::cpu_id_t>> JSONTraceBundleDescription::GetCpuIds() {
24   if (!cpus)
25     return None;
26   std::vector<lldb::cpu_id_t> cpu_ids;
27   for (const JSONCpu &cpu : *cpus)
28     cpu_ids.push_back(cpu.id);
29   return cpu_ids;
30 }
31 
32 json::Value toJSON(const JSONModule &module) {
33   json::Object json_module;
34   json_module["systemPath"] = module.system_path;
35   if (module.file)
36     json_module["file"] = *module.file;
37   json_module["loadAddress"] = toJSON(module.load_address, true);
38   if (module.uuid)
39     json_module["uuid"] = *module.uuid;
40   return std::move(json_module);
41 }
42 
43 bool fromJSON(const json::Value &value, JSONModule &module, Path path) {
44   ObjectMapper o(value, path);
45   return o && o.map("systemPath", module.system_path) &&
46          o.map("file", module.file) &&
47          o.map("loadAddress", module.load_address) &&
48          o.map("uuid", module.uuid);
49 }
50 
51 json::Value toJSON(const JSONThread &thread) {
52   json::Object obj{{"tid", thread.tid}};
53   if (thread.ipt_trace)
54     obj["iptTrace"] = *thread.ipt_trace;
55   return obj;
56 }
57 
58 bool fromJSON(const json::Value &value, JSONThread &thread, Path path) {
59   ObjectMapper o(value, path);
60   return o && o.map("tid", thread.tid) && o.map("iptTrace", thread.ipt_trace);
61 }
62 
63 json::Value toJSON(const JSONProcess &process) {
64   return Object{
65       {"pid", process.pid},
66       {"triple", process.triple},
67       {"threads", process.threads},
68       {"modules", process.modules},
69   };
70 }
71 
72 bool fromJSON(const json::Value &value, JSONProcess &process, Path path) {
73   ObjectMapper o(value, path);
74   return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
75          o.map("threads", process.threads) && o.map("modules", process.modules);
76 }
77 
78 json::Value toJSON(const JSONCpu &cpu) {
79   return Object{
80       {"id", cpu.id},
81       {"iptTrace", cpu.ipt_trace},
82       {"contextSwitchTrace", cpu.context_switch_trace},
83   };
84 }
85 
86 bool fromJSON(const json::Value &value, JSONCpu &cpu, Path path) {
87   ObjectMapper o(value, path);
88   uint64_t cpu_id;
89   if (!(o && o.map("id", cpu_id) && o.map("iptTrace", cpu.ipt_trace) &&
90         o.map("contextSwitchTrace", cpu.context_switch_trace)))
91     return false;
92   cpu.id = cpu_id;
93   return true;
94 }
95 
96 json::Value toJSON(const pt_cpu &cpu_info) {
97   return Object{
98       {"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"},
99       {"family", cpu_info.family},
100       {"model", cpu_info.model},
101       {"stepping", cpu_info.stepping},
102   };
103 }
104 
105 bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) {
106   ObjectMapper o(value, path);
107   std::string vendor;
108   uint64_t family, model, stepping;
109   if (!(o && o.map("vendor", vendor) && o.map("family", family) &&
110         o.map("model", model) && o.map("stepping", stepping)))
111     return false;
112   cpu_info.vendor = vendor == "GenuineIntel" ? pcv_intel : pcv_unknown;
113   cpu_info.family = family;
114   cpu_info.model = model;
115   cpu_info.stepping = stepping;
116   return true;
117 }
118 
119 json::Value toJSON(const JSONTraceBundleDescription &bundle_description) {
120   return Object{{"type", bundle_description.type},
121                 {"processes", bundle_description.processes},
122                 // We have to do this because the compiler fails at doing it
123                 // automatically because pt_cpu is not in a namespace
124                 {"cpuInfo", toJSON(bundle_description.cpu_info)},
125                 {"cpus", bundle_description.cpus},
126                 {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion}};
127 }
128 
129 bool fromJSON(const json::Value &value, JSONTraceBundleDescription &bundle_description, Path path) {
130   ObjectMapper o(value, path);
131   if (!(o && o.map("processes", bundle_description.processes) &&
132         o.map("type", bundle_description.type) && o.map("cpus", bundle_description.cpus) &&
133         o.map("tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion)))
134     return false;
135   if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) {
136     path.report(
137         "\"tscPerfZeroConversion\" is required when \"cpus\" is provided");
138     return false;
139   }
140   // We have to do this because the compiler fails at doing it automatically
141   // because pt_cpu is not in a namespace
142   if (!fromJSON(*value.getAsObject()->get("cpuInfo"), bundle_description.cpu_info,
143                 path.field("cpuInfo")))
144     return false;
145   return true;
146 }
147 
148 } // namespace trace_intel_pt
149 } // namespace lldb_private
150