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::core_id_t>> JSONTraceSession::GetCoreIds() {
24   if (!cores)
25     return None;
26   std::vector<lldb::core_id_t> core_ids;
27   for (const JSONCore &core : *cores)
28     core_ids.push_back(core.core_id);
29   return core_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"] = module.load_address;
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.trace_buffer)
54     obj["traceBuffer"] = *thread.trace_buffer;
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) &&
61          o.map("traceBuffer", thread.trace_buffer);
62 }
63 
64 json::Value toJSON(const JSONProcess &process) {
65   return Object{
66       {"pid", process.pid},
67       {"triple", process.triple},
68       {"threads", process.threads},
69       {"modules", process.modules},
70   };
71 }
72 
73 bool fromJSON(const json::Value &value, JSONProcess &process, Path path) {
74   ObjectMapper o(value, path);
75   return o && o.map("pid", process.pid) && o.map("triple", process.triple) &&
76          o.map("threads", process.threads) && o.map("modules", process.modules);
77 }
78 
79 json::Value toJSON(const JSONCore &core) {
80   return Object{
81       {"coreId", core.core_id},
82       {"traceBuffer", core.trace_buffer},
83       {"contextSwitchTrace", core.context_switch_trace},
84   };
85 }
86 
87 bool fromJSON(const json::Value &value, JSONCore &core, Path path) {
88   ObjectMapper o(value, path);
89   uint64_t core_id;
90   if (!o || !o.map("coreId", core_id) ||
91       !o.map("traceBuffer", core.trace_buffer) ||
92       !o.map("contextSwitchTrace", core.context_switch_trace))
93     return false;
94   core.core_id = core_id;
95   return true;
96 }
97 
98 json::Value toJSON(const pt_cpu &cpu_info) {
99   return Object{
100       {"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"},
101       {"family", cpu_info.family},
102       {"model", cpu_info.model},
103       {"stepping", cpu_info.stepping},
104   };
105 }
106 
107 bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) {
108   ObjectMapper o(value, path);
109   std::string vendor;
110   uint64_t family, model, stepping;
111   if (!o || !o.map("vendor", vendor) || !o.map("family", family) ||
112       !o.map("model", model) || !o.map("stepping", stepping))
113     return false;
114   cpu_info.vendor = vendor == "GenuineIntel" ? pcv_intel : pcv_unknown;
115   cpu_info.family = family;
116   cpu_info.model = model;
117   cpu_info.stepping = stepping;
118   return true;
119 }
120 
121 json::Value toJSON(const JSONTraceSession &session) {
122   return Object{{"type", session.type},
123                 {"processes", session.processes},
124                 // We have to do this because the compiler fails at doing it
125                 // automatically because pt_cpu is not in a namespace
126                 {"cpuInfo", toJSON(session.cpu_info)},
127                 {"cores", session.cores},
128                 {"tscPerfZeroConversion", session.tsc_perf_zero_conversion}};
129 }
130 
131 bool fromJSON(const json::Value &value, JSONTraceSession &session, Path path) {
132   ObjectMapper o(value, path);
133   if (!o || !o.map("processes", session.processes) ||
134       !o.map("type", session.type) || !o.map("cores", session.cores) ||
135       !o.map("tscPerfZeroConversion", session.tsc_perf_zero_conversion))
136     return false;
137   if (session.cores && !session.tsc_perf_zero_conversion) {
138     path.report(
139         "\"tscPerfZeroConversion\" is required when \"cores\" is provided");
140     return false;
141   }
142   // We have to do this because the compiler fails at doing it automatically
143   // because pt_cpu is not in a namespace
144   if (!fromJSON(*value.getAsObject()->get("cpuInfo"), session.cpu_info,
145                 path.field("cpuInfo")))
146     return false;
147   return true;
148 }
149 
150 } // namespace trace_intel_pt
151 } // namespace lldb_private
152