xref: /llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp (revision 2fe8327406050d2585d2ced910a678e28caefcf5)
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 #include "llvm/Support/JSON.h"
11f190ce62SKazu Hirata #include <optional>
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 
23*2fe83274SKazu Hirata std::optional<std::vector<lldb::cpu_id_t>>
GetCpuIds()24*2fe83274SKazu Hirata JSONTraceBundleDescription::GetCpuIds() {
256a5355e8SWalter Erquinigo   if (!cpus)
26d920ab4aSKazu Hirata     return std::nullopt;
276a5355e8SWalter Erquinigo   std::vector<lldb::cpu_id_t> cpu_ids;
286a5355e8SWalter Erquinigo   for (const JSONCpu &cpu : *cpus)
296a5355e8SWalter Erquinigo     cpu_ids.push_back(cpu.id);
306a5355e8SWalter Erquinigo   return cpu_ids;
31602497d6SWalter Erquinigo }
32602497d6SWalter Erquinigo 
toJSON(const JSONModule & module)33fc5ef57cSWalter Erquinigo json::Value toJSON(const JSONModule &module) {
34fc5ef57cSWalter Erquinigo   json::Object json_module;
35fc5ef57cSWalter Erquinigo   json_module["systemPath"] = module.system_path;
36fc5ef57cSWalter Erquinigo   if (module.file)
37fc5ef57cSWalter Erquinigo     json_module["file"] = *module.file;
389f45f23dSWalter Erquinigo   json_module["loadAddress"] = toJSON(module.load_address, true);
39fc5ef57cSWalter Erquinigo   if (module.uuid)
40fc5ef57cSWalter Erquinigo     json_module["uuid"] = *module.uuid;
41fc5ef57cSWalter Erquinigo   return std::move(json_module);
42602497d6SWalter Erquinigo }
43602497d6SWalter Erquinigo 
fromJSON(const json::Value & value,JSONModule & module,Path path)44fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, JSONModule &module, Path path) {
45fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
46fc5ef57cSWalter Erquinigo   return o && o.map("systemPath", module.system_path) &&
47fc5ef57cSWalter Erquinigo          o.map("file", module.file) &&
48fc5ef57cSWalter Erquinigo          o.map("loadAddress", module.load_address) &&
49fc5ef57cSWalter Erquinigo          o.map("uuid", module.uuid);
50fc5ef57cSWalter Erquinigo }
51fc5ef57cSWalter Erquinigo 
toJSON(const JSONThread & thread)52fc5ef57cSWalter Erquinigo json::Value toJSON(const JSONThread &thread) {
53a19fcc2bSWalter Erquinigo   json::Object obj{{"tid", thread.tid}};
546a5355e8SWalter Erquinigo   if (thread.ipt_trace)
556a5355e8SWalter Erquinigo     obj["iptTrace"] = *thread.ipt_trace;
56a19fcc2bSWalter Erquinigo   return obj;
57fc5ef57cSWalter Erquinigo }
58fc5ef57cSWalter Erquinigo 
fromJSON(const json::Value & value,JSONThread & thread,Path path)59fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, JSONThread &thread, Path path) {
60fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
616a5355e8SWalter Erquinigo   return o && o.map("tid", thread.tid) && o.map("iptTrace", thread.ipt_trace);
62fc5ef57cSWalter Erquinigo }
63fc5ef57cSWalter Erquinigo 
toJSON(const JSONProcess & process)64fc5ef57cSWalter Erquinigo json::Value toJSON(const JSONProcess &process) {
65fc5ef57cSWalter Erquinigo   return Object{
66fc5ef57cSWalter Erquinigo       {"pid", process.pid},
67fc5ef57cSWalter Erquinigo       {"triple", process.triple},
68fc5ef57cSWalter Erquinigo       {"threads", process.threads},
69fc5ef57cSWalter Erquinigo       {"modules", process.modules},
70fc5ef57cSWalter Erquinigo   };
71fc5ef57cSWalter Erquinigo }
72fc5ef57cSWalter Erquinigo 
fromJSON(const json::Value & value,JSONProcess & process,Path path)73fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, JSONProcess &process, Path path) {
74fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
75fc5ef57cSWalter Erquinigo   return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
76fc5ef57cSWalter Erquinigo          o.map("threads", process.threads) && o.map("modules", process.modules);
77fc5ef57cSWalter Erquinigo }
78fc5ef57cSWalter Erquinigo 
toJSON(const JSONCpu & cpu)796a5355e8SWalter Erquinigo json::Value toJSON(const JSONCpu &cpu) {
80fc5ef57cSWalter Erquinigo   return Object{
816a5355e8SWalter Erquinigo       {"id", cpu.id},
826a5355e8SWalter Erquinigo       {"iptTrace", cpu.ipt_trace},
836a5355e8SWalter Erquinigo       {"contextSwitchTrace", cpu.context_switch_trace},
84fc5ef57cSWalter Erquinigo   };
85fc5ef57cSWalter Erquinigo }
86fc5ef57cSWalter Erquinigo 
fromJSON(const json::Value & value,JSONCpu & cpu,Path path)876a5355e8SWalter Erquinigo bool fromJSON(const json::Value &value, JSONCpu &cpu, Path path) {
88fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
896a5355e8SWalter Erquinigo   uint64_t cpu_id;
906a5355e8SWalter Erquinigo   if (!(o && o.map("id", cpu_id) && o.map("iptTrace", cpu.ipt_trace) &&
916a5355e8SWalter Erquinigo         o.map("contextSwitchTrace", cpu.context_switch_trace)))
92fc5ef57cSWalter Erquinigo     return false;
936a5355e8SWalter Erquinigo   cpu.id = cpu_id;
94fc5ef57cSWalter Erquinigo   return true;
95fc5ef57cSWalter Erquinigo }
96fc5ef57cSWalter Erquinigo 
toJSON(const pt_cpu & cpu_info)97fc5ef57cSWalter Erquinigo json::Value toJSON(const pt_cpu &cpu_info) {
98fc5ef57cSWalter Erquinigo   return Object{
99fc5ef57cSWalter Erquinigo       {"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"},
100fc5ef57cSWalter Erquinigo       {"family", cpu_info.family},
101602497d6SWalter Erquinigo       {"model", cpu_info.model},
102602497d6SWalter Erquinigo       {"stepping", cpu_info.stepping},
103fc5ef57cSWalter Erquinigo   };
104602497d6SWalter Erquinigo }
105602497d6SWalter Erquinigo 
fromJSON(const json::Value & value,pt_cpu & cpu_info,Path path)106fc5ef57cSWalter Erquinigo bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) {
107fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
108fc5ef57cSWalter Erquinigo   std::string vendor;
109fc5ef57cSWalter Erquinigo   uint64_t family, model, stepping;
110561a61fbSWalter Erquinigo   if (!(o && o.map("vendor", vendor) && o.map("family", family) &&
111561a61fbSWalter Erquinigo         o.map("model", model) && o.map("stepping", stepping)))
112fc5ef57cSWalter Erquinigo     return false;
113fc5ef57cSWalter Erquinigo   cpu_info.vendor = vendor == "GenuineIntel" ? pcv_intel : pcv_unknown;
114fc5ef57cSWalter Erquinigo   cpu_info.family = family;
115fc5ef57cSWalter Erquinigo   cpu_info.model = model;
116fc5ef57cSWalter Erquinigo   cpu_info.stepping = stepping;
117fc5ef57cSWalter Erquinigo   return true;
118602497d6SWalter Erquinigo }
119602497d6SWalter Erquinigo 
toJSON(const JSONKernel & kernel)1206fb744beSWalter Erquinigo json::Value toJSON(const JSONKernel &kernel) {
1216fb744beSWalter Erquinigo   json::Object json_module;
1226fb744beSWalter Erquinigo   if (kernel.load_address)
1236fb744beSWalter Erquinigo     json_module["loadAddress"] = toJSON(*kernel.load_address, true);
1246fb744beSWalter Erquinigo   json_module["file"] = kernel.file;
1256fb744beSWalter Erquinigo   return std::move(json_module);
1266fb744beSWalter Erquinigo }
1276fb744beSWalter Erquinigo 
fromJSON(const json::Value & value,JSONKernel & kernel,Path path)1286fb744beSWalter Erquinigo bool fromJSON(const json::Value &value, JSONKernel &kernel, Path path) {
1296fb744beSWalter Erquinigo   ObjectMapper o(value, path);
1306fb744beSWalter Erquinigo   return o && o.map("loadAddress", kernel.load_address) &&
1316fb744beSWalter Erquinigo          o.map("file", kernel.file);
1326fb744beSWalter Erquinigo }
1336fb744beSWalter Erquinigo 
toJSON(const JSONTraceBundleDescription & bundle_description)134b8dcd0baSWalter Erquinigo json::Value toJSON(const JSONTraceBundleDescription &bundle_description) {
135d179ea12SWalter Erquinigo   return Object{
136d179ea12SWalter Erquinigo       {"type", bundle_description.type},
137b8dcd0baSWalter Erquinigo       {"processes", bundle_description.processes},
138fc5ef57cSWalter Erquinigo       // We have to do this because the compiler fails at doing it
139fc5ef57cSWalter Erquinigo       // automatically because pt_cpu is not in a namespace
140b8dcd0baSWalter Erquinigo       {"cpuInfo", toJSON(bundle_description.cpu_info)},
141b8dcd0baSWalter Erquinigo       {"cpus", bundle_description.cpus},
1426fb744beSWalter Erquinigo       {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion},
1436fb744beSWalter Erquinigo       {"kernel", bundle_description.kernel}};
144602497d6SWalter Erquinigo }
145602497d6SWalter Erquinigo 
fromJSON(const json::Value & value,JSONTraceBundleDescription & bundle_description,Path path)146d179ea12SWalter Erquinigo bool fromJSON(const json::Value &value,
147d179ea12SWalter Erquinigo               JSONTraceBundleDescription &bundle_description, Path path) {
148fc5ef57cSWalter Erquinigo   ObjectMapper o(value, path);
149b8dcd0baSWalter Erquinigo   if (!(o && o.map("processes", bundle_description.processes) &&
150d179ea12SWalter Erquinigo         o.map("type", bundle_description.type) &&
151d179ea12SWalter Erquinigo         o.map("cpus", bundle_description.cpus) &&
152d179ea12SWalter Erquinigo         o.map("tscPerfZeroConversion",
1536fb744beSWalter Erquinigo               bundle_description.tsc_perf_zero_conversion) &&
1546fb744beSWalter Erquinigo         o.map("kernel", bundle_description.kernel)))
155fc5ef57cSWalter Erquinigo     return false;
156b8dcd0baSWalter Erquinigo   if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) {
1571a3f9969SWalter Erquinigo     path.report(
1586a5355e8SWalter Erquinigo         "\"tscPerfZeroConversion\" is required when \"cpus\" is provided");
1591a3f9969SWalter Erquinigo     return false;
1601a3f9969SWalter Erquinigo   }
161fc5ef57cSWalter Erquinigo   // We have to do this because the compiler fails at doing it automatically
162fc5ef57cSWalter Erquinigo   // because pt_cpu is not in a namespace
163d179ea12SWalter Erquinigo   if (!fromJSON(*value.getAsObject()->get("cpuInfo"),
164d179ea12SWalter Erquinigo                 bundle_description.cpu_info, path.field("cpuInfo")))
165fc5ef57cSWalter Erquinigo     return false;
1666fb744beSWalter Erquinigo 
1676fb744beSWalter Erquinigo   // When kernel section is present, this is kernel-only tracing. Thus, throw an
1686fb744beSWalter Erquinigo   // error if the "processes" section is non-empty or the "cpus" section is not
1696fb744beSWalter Erquinigo   // present.
1706fb744beSWalter Erquinigo   if (bundle_description.kernel) {
1716fb744beSWalter Erquinigo     if (bundle_description.processes &&
1726fb744beSWalter Erquinigo         !bundle_description.processes->empty()) {
1736fb744beSWalter Erquinigo       path.report("\"processes\" must be empty when \"kernel\" is provided");
1746fb744beSWalter Erquinigo       return false;
1756fb744beSWalter Erquinigo     }
1766fb744beSWalter Erquinigo     if (!bundle_description.cpus) {
1776fb744beSWalter Erquinigo       path.report("\"cpus\" is required when \"kernel\" is provided");
1786fb744beSWalter Erquinigo       return false;
1796fb744beSWalter Erquinigo     }
1806fb744beSWalter Erquinigo   } else if (!bundle_description.processes) {
1816fb744beSWalter Erquinigo     // Usermode tracing requires processes section.
1826fb744beSWalter Erquinigo     path.report("\"processes\" is required when \"kernel\" is not provided");
1836fb744beSWalter Erquinigo     return false;
1846fb744beSWalter Erquinigo   }
185fc5ef57cSWalter Erquinigo   return true;
186fc5ef57cSWalter Erquinigo }
187fc5ef57cSWalter Erquinigo 
188fc5ef57cSWalter Erquinigo } // namespace trace_intel_pt
189fc5ef57cSWalter Erquinigo } // namespace lldb_private
190