xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1349cc55cSDimitry Andric //===-- TraceIntelPTJSONStructs.cpp ---------------------------------------===//
2349cc55cSDimitry Andric //
3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6349cc55cSDimitry Andric //
7349cc55cSDimitry Andric //===----------------------------------------------------------------------===//
8349cc55cSDimitry Andric 
9349cc55cSDimitry Andric #include "TraceIntelPTJSONStructs.h"
10349cc55cSDimitry Andric #include "llvm/Support/JSON.h"
11*bdd1243dSDimitry Andric #include <optional>
12349cc55cSDimitry Andric #include <string>
13349cc55cSDimitry Andric 
14349cc55cSDimitry Andric using namespace lldb;
15349cc55cSDimitry Andric using namespace lldb_private;
16349cc55cSDimitry Andric using namespace lldb_private::trace_intel_pt;
17349cc55cSDimitry Andric using namespace llvm;
1881ad6265SDimitry Andric using namespace llvm::json;
19349cc55cSDimitry Andric 
2081ad6265SDimitry Andric namespace lldb_private {
2181ad6265SDimitry Andric namespace trace_intel_pt {
22349cc55cSDimitry Andric 
23*bdd1243dSDimitry Andric std::optional<std::vector<lldb::cpu_id_t>>
GetCpuIds()24*bdd1243dSDimitry Andric JSONTraceBundleDescription::GetCpuIds() {
2581ad6265SDimitry Andric   if (!cpus)
26*bdd1243dSDimitry Andric     return std::nullopt;
2781ad6265SDimitry Andric   std::vector<lldb::cpu_id_t> cpu_ids;
2881ad6265SDimitry Andric   for (const JSONCpu &cpu : *cpus)
2981ad6265SDimitry Andric     cpu_ids.push_back(cpu.id);
3081ad6265SDimitry Andric   return cpu_ids;
31349cc55cSDimitry Andric }
32349cc55cSDimitry Andric 
toJSON(const JSONModule & module)3381ad6265SDimitry Andric json::Value toJSON(const JSONModule &module) {
3481ad6265SDimitry Andric   json::Object json_module;
3581ad6265SDimitry Andric   json_module["systemPath"] = module.system_path;
3681ad6265SDimitry Andric   if (module.file)
3781ad6265SDimitry Andric     json_module["file"] = *module.file;
3881ad6265SDimitry Andric   json_module["loadAddress"] = toJSON(module.load_address, true);
3981ad6265SDimitry Andric   if (module.uuid)
4081ad6265SDimitry Andric     json_module["uuid"] = *module.uuid;
4181ad6265SDimitry Andric   return std::move(json_module);
42349cc55cSDimitry Andric }
43349cc55cSDimitry Andric 
fromJSON(const json::Value & value,JSONModule & module,Path path)4481ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONModule &module, Path path) {
4581ad6265SDimitry Andric   ObjectMapper o(value, path);
4681ad6265SDimitry Andric   return o && o.map("systemPath", module.system_path) &&
4781ad6265SDimitry Andric          o.map("file", module.file) &&
4881ad6265SDimitry Andric          o.map("loadAddress", module.load_address) &&
4981ad6265SDimitry Andric          o.map("uuid", module.uuid);
5081ad6265SDimitry Andric }
5181ad6265SDimitry Andric 
toJSON(const JSONThread & thread)5281ad6265SDimitry Andric json::Value toJSON(const JSONThread &thread) {
5381ad6265SDimitry Andric   json::Object obj{{"tid", thread.tid}};
5481ad6265SDimitry Andric   if (thread.ipt_trace)
5581ad6265SDimitry Andric     obj["iptTrace"] = *thread.ipt_trace;
5681ad6265SDimitry Andric   return obj;
5781ad6265SDimitry Andric }
5881ad6265SDimitry Andric 
fromJSON(const json::Value & value,JSONThread & thread,Path path)5981ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONThread &thread, Path path) {
6081ad6265SDimitry Andric   ObjectMapper o(value, path);
6181ad6265SDimitry Andric   return o && o.map("tid", thread.tid) && o.map("iptTrace", thread.ipt_trace);
6281ad6265SDimitry Andric }
6381ad6265SDimitry Andric 
toJSON(const JSONProcess & process)6481ad6265SDimitry Andric json::Value toJSON(const JSONProcess &process) {
6581ad6265SDimitry Andric   return Object{
6681ad6265SDimitry Andric       {"pid", process.pid},
6781ad6265SDimitry Andric       {"triple", process.triple},
6881ad6265SDimitry Andric       {"threads", process.threads},
6981ad6265SDimitry Andric       {"modules", process.modules},
7081ad6265SDimitry Andric   };
7181ad6265SDimitry Andric }
7281ad6265SDimitry Andric 
fromJSON(const json::Value & value,JSONProcess & process,Path path)7381ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONProcess &process, Path path) {
7481ad6265SDimitry Andric   ObjectMapper o(value, path);
7581ad6265SDimitry Andric   return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
7681ad6265SDimitry Andric          o.map("threads", process.threads) && o.map("modules", process.modules);
7781ad6265SDimitry Andric }
7881ad6265SDimitry Andric 
toJSON(const JSONCpu & cpu)7981ad6265SDimitry Andric json::Value toJSON(const JSONCpu &cpu) {
8081ad6265SDimitry Andric   return Object{
8181ad6265SDimitry Andric       {"id", cpu.id},
8281ad6265SDimitry Andric       {"iptTrace", cpu.ipt_trace},
8381ad6265SDimitry Andric       {"contextSwitchTrace", cpu.context_switch_trace},
8481ad6265SDimitry Andric   };
8581ad6265SDimitry Andric }
8681ad6265SDimitry Andric 
fromJSON(const json::Value & value,JSONCpu & cpu,Path path)8781ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONCpu &cpu, Path path) {
8881ad6265SDimitry Andric   ObjectMapper o(value, path);
8981ad6265SDimitry Andric   uint64_t cpu_id;
9081ad6265SDimitry Andric   if (!(o && o.map("id", cpu_id) && o.map("iptTrace", cpu.ipt_trace) &&
9181ad6265SDimitry Andric         o.map("contextSwitchTrace", cpu.context_switch_trace)))
9281ad6265SDimitry Andric     return false;
9381ad6265SDimitry Andric   cpu.id = cpu_id;
9481ad6265SDimitry Andric   return true;
9581ad6265SDimitry Andric }
9681ad6265SDimitry Andric 
toJSON(const pt_cpu & cpu_info)9781ad6265SDimitry Andric json::Value toJSON(const pt_cpu &cpu_info) {
9881ad6265SDimitry Andric   return Object{
9981ad6265SDimitry Andric       {"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"},
10081ad6265SDimitry Andric       {"family", cpu_info.family},
101349cc55cSDimitry Andric       {"model", cpu_info.model},
102349cc55cSDimitry Andric       {"stepping", cpu_info.stepping},
10381ad6265SDimitry Andric   };
104349cc55cSDimitry Andric }
105349cc55cSDimitry Andric 
fromJSON(const json::Value & value,pt_cpu & cpu_info,Path path)10681ad6265SDimitry Andric bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) {
10781ad6265SDimitry Andric   ObjectMapper o(value, path);
10881ad6265SDimitry Andric   std::string vendor;
10981ad6265SDimitry Andric   uint64_t family, model, stepping;
11081ad6265SDimitry Andric   if (!(o && o.map("vendor", vendor) && o.map("family", family) &&
11181ad6265SDimitry Andric         o.map("model", model) && o.map("stepping", stepping)))
11281ad6265SDimitry Andric     return false;
11381ad6265SDimitry Andric   cpu_info.vendor = vendor == "GenuineIntel" ? pcv_intel : pcv_unknown;
11481ad6265SDimitry Andric   cpu_info.family = family;
11581ad6265SDimitry Andric   cpu_info.model = model;
11681ad6265SDimitry Andric   cpu_info.stepping = stepping;
11781ad6265SDimitry Andric   return true;
118349cc55cSDimitry Andric }
119349cc55cSDimitry Andric 
toJSON(const JSONKernel & kernel)120*bdd1243dSDimitry Andric json::Value toJSON(const JSONKernel &kernel) {
121*bdd1243dSDimitry Andric   json::Object json_module;
122*bdd1243dSDimitry Andric   if (kernel.load_address)
123*bdd1243dSDimitry Andric     json_module["loadAddress"] = toJSON(*kernel.load_address, true);
124*bdd1243dSDimitry Andric   json_module["file"] = kernel.file;
125*bdd1243dSDimitry Andric   return std::move(json_module);
126*bdd1243dSDimitry Andric }
127*bdd1243dSDimitry Andric 
fromJSON(const json::Value & value,JSONKernel & kernel,Path path)128*bdd1243dSDimitry Andric bool fromJSON(const json::Value &value, JSONKernel &kernel, Path path) {
129*bdd1243dSDimitry Andric   ObjectMapper o(value, path);
130*bdd1243dSDimitry Andric   return o && o.map("loadAddress", kernel.load_address) &&
131*bdd1243dSDimitry Andric          o.map("file", kernel.file);
132*bdd1243dSDimitry Andric }
133*bdd1243dSDimitry Andric 
toJSON(const JSONTraceBundleDescription & bundle_description)13481ad6265SDimitry Andric json::Value toJSON(const JSONTraceBundleDescription &bundle_description) {
135*bdd1243dSDimitry Andric   return Object{
136*bdd1243dSDimitry Andric       {"type", bundle_description.type},
13781ad6265SDimitry Andric       {"processes", bundle_description.processes},
13881ad6265SDimitry Andric       // We have to do this because the compiler fails at doing it
13981ad6265SDimitry Andric       // automatically because pt_cpu is not in a namespace
14081ad6265SDimitry Andric       {"cpuInfo", toJSON(bundle_description.cpu_info)},
14181ad6265SDimitry Andric       {"cpus", bundle_description.cpus},
142*bdd1243dSDimitry Andric       {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion},
143*bdd1243dSDimitry Andric       {"kernel", bundle_description.kernel}};
144349cc55cSDimitry Andric }
145349cc55cSDimitry Andric 
fromJSON(const json::Value & value,JSONTraceBundleDescription & bundle_description,Path path)146*bdd1243dSDimitry Andric bool fromJSON(const json::Value &value,
147*bdd1243dSDimitry Andric               JSONTraceBundleDescription &bundle_description, Path path) {
14881ad6265SDimitry Andric   ObjectMapper o(value, path);
14981ad6265SDimitry Andric   if (!(o && o.map("processes", bundle_description.processes) &&
150*bdd1243dSDimitry Andric         o.map("type", bundle_description.type) &&
151*bdd1243dSDimitry Andric         o.map("cpus", bundle_description.cpus) &&
152*bdd1243dSDimitry Andric         o.map("tscPerfZeroConversion",
153*bdd1243dSDimitry Andric               bundle_description.tsc_perf_zero_conversion) &&
154*bdd1243dSDimitry Andric         o.map("kernel", bundle_description.kernel)))
15581ad6265SDimitry Andric     return false;
15681ad6265SDimitry Andric   if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) {
15781ad6265SDimitry Andric     path.report(
15881ad6265SDimitry Andric         "\"tscPerfZeroConversion\" is required when \"cpus\" is provided");
15981ad6265SDimitry Andric     return false;
16081ad6265SDimitry Andric   }
16181ad6265SDimitry Andric   // We have to do this because the compiler fails at doing it automatically
16281ad6265SDimitry Andric   // because pt_cpu is not in a namespace
163*bdd1243dSDimitry Andric   if (!fromJSON(*value.getAsObject()->get("cpuInfo"),
164*bdd1243dSDimitry Andric                 bundle_description.cpu_info, path.field("cpuInfo")))
16581ad6265SDimitry Andric     return false;
166*bdd1243dSDimitry Andric 
167*bdd1243dSDimitry Andric   // When kernel section is present, this is kernel-only tracing. Thus, throw an
168*bdd1243dSDimitry Andric   // error if the "processes" section is non-empty or the "cpus" section is not
169*bdd1243dSDimitry Andric   // present.
170*bdd1243dSDimitry Andric   if (bundle_description.kernel) {
171*bdd1243dSDimitry Andric     if (bundle_description.processes &&
172*bdd1243dSDimitry Andric         !bundle_description.processes->empty()) {
173*bdd1243dSDimitry Andric       path.report("\"processes\" must be empty when \"kernel\" is provided");
174*bdd1243dSDimitry Andric       return false;
175*bdd1243dSDimitry Andric     }
176*bdd1243dSDimitry Andric     if (!bundle_description.cpus) {
177*bdd1243dSDimitry Andric       path.report("\"cpus\" is required when \"kernel\" is provided");
178*bdd1243dSDimitry Andric       return false;
179*bdd1243dSDimitry Andric     }
180*bdd1243dSDimitry Andric   } else if (!bundle_description.processes) {
181*bdd1243dSDimitry Andric     // Usermode tracing requires processes section.
182*bdd1243dSDimitry Andric     path.report("\"processes\" is required when \"kernel\" is not provided");
183*bdd1243dSDimitry Andric     return false;
184*bdd1243dSDimitry Andric   }
18581ad6265SDimitry Andric   return true;
18681ad6265SDimitry Andric }
18781ad6265SDimitry Andric 
18881ad6265SDimitry Andric } // namespace trace_intel_pt
18981ad6265SDimitry Andric } // namespace lldb_private
190