1 //===-- TraceIntelPTJSONStructs.cpp ---------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "TraceIntelPTJSONStructs.h"
10 #include "llvm/Support/JSON.h"
15 using namespace lldb_private
;
16 using namespace lldb_private::trace_intel_pt
;
18 using namespace llvm::json
;
20 namespace lldb_private
{
21 namespace trace_intel_pt
{
23 std::optional
<std::vector
<lldb::cpu_id_t
>>
24 JSONTraceBundleDescription::GetCpuIds() {
27 std::vector
<lldb::cpu_id_t
> cpu_ids
;
28 for (const JSONCpu
&cpu
: *cpus
)
29 cpu_ids
.push_back(cpu
.id
);
33 json::Value
toJSON(const JSONModule
&module
) {
34 json::Object json_module
;
35 json_module
["systemPath"] = module
.system_path
;
37 json_module
["file"] = *module
.file
;
38 json_module
["loadAddress"] = toJSON(module
.load_address
, true);
40 json_module
["uuid"] = *module
.uuid
;
41 return std::move(json_module
);
44 bool fromJSON(const json::Value
&value
, JSONModule
&module
, Path path
) {
45 ObjectMapper
o(value
, path
);
46 return o
&& o
.map("systemPath", module
.system_path
) &&
47 o
.map("file", module
.file
) &&
48 o
.map("loadAddress", module
.load_address
) &&
49 o
.map("uuid", module
.uuid
);
52 json::Value
toJSON(const JSONThread
&thread
) {
53 json::Object obj
{{"tid", thread
.tid
}};
55 obj
["iptTrace"] = *thread
.ipt_trace
;
59 bool fromJSON(const json::Value
&value
, JSONThread
&thread
, Path path
) {
60 ObjectMapper
o(value
, path
);
61 return o
&& o
.map("tid", thread
.tid
) && o
.map("iptTrace", thread
.ipt_trace
);
64 json::Value
toJSON(const JSONProcess
&process
) {
67 {"triple", process
.triple
},
68 {"threads", process
.threads
},
69 {"modules", process
.modules
},
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
);
79 json::Value
toJSON(const JSONCpu
&cpu
) {
82 {"iptTrace", cpu
.ipt_trace
},
83 {"contextSwitchTrace", cpu
.context_switch_trace
},
87 bool fromJSON(const json::Value
&value
, JSONCpu
&cpu
, Path path
) {
88 ObjectMapper
o(value
, path
);
90 if (!(o
&& o
.map("id", cpu_id
) && o
.map("iptTrace", cpu
.ipt_trace
) &&
91 o
.map("contextSwitchTrace", cpu
.context_switch_trace
)))
97 json::Value
toJSON(const pt_cpu
&cpu_info
) {
99 {"vendor", cpu_info
.vendor
== pcv_intel
? "GenuineIntel" : "Unknown"},
100 {"family", cpu_info
.family
},
101 {"model", cpu_info
.model
},
102 {"stepping", cpu_info
.stepping
},
106 bool fromJSON(const json::Value
&value
, pt_cpu
&cpu_info
, Path path
) {
107 ObjectMapper
o(value
, path
);
109 uint64_t family
, model
, stepping
;
110 if (!(o
&& o
.map("vendor", vendor
) && o
.map("family", family
) &&
111 o
.map("model", model
) && o
.map("stepping", stepping
)))
113 cpu_info
.vendor
= vendor
== "GenuineIntel" ? pcv_intel
: pcv_unknown
;
114 cpu_info
.family
= family
;
115 cpu_info
.model
= model
;
116 cpu_info
.stepping
= stepping
;
120 json::Value
toJSON(const JSONKernel
&kernel
) {
121 json::Object json_module
;
122 if (kernel
.load_address
)
123 json_module
["loadAddress"] = toJSON(*kernel
.load_address
, true);
124 json_module
["file"] = kernel
.file
;
125 return std::move(json_module
);
128 bool fromJSON(const json::Value
&value
, JSONKernel
&kernel
, Path path
) {
129 ObjectMapper
o(value
, path
);
130 return o
&& o
.map("loadAddress", kernel
.load_address
) &&
131 o
.map("file", kernel
.file
);
134 json::Value
toJSON(const JSONTraceBundleDescription
&bundle_description
) {
136 {"type", bundle_description
.type
},
137 {"processes", bundle_description
.processes
},
138 // We have to do this because the compiler fails at doing it
139 // automatically because pt_cpu is not in a namespace
140 {"cpuInfo", toJSON(bundle_description
.cpu_info
)},
141 {"cpus", bundle_description
.cpus
},
142 {"tscPerfZeroConversion", bundle_description
.tsc_perf_zero_conversion
},
143 {"kernel", bundle_description
.kernel
}};
146 bool fromJSON(const json::Value
&value
,
147 JSONTraceBundleDescription
&bundle_description
, Path path
) {
148 ObjectMapper
o(value
, path
);
149 if (!(o
&& o
.map("processes", bundle_description
.processes
) &&
150 o
.map("type", bundle_description
.type
) &&
151 o
.map("cpus", bundle_description
.cpus
) &&
152 o
.map("tscPerfZeroConversion",
153 bundle_description
.tsc_perf_zero_conversion
) &&
154 o
.map("kernel", bundle_description
.kernel
)))
156 if (bundle_description
.cpus
&& !bundle_description
.tsc_perf_zero_conversion
) {
158 "\"tscPerfZeroConversion\" is required when \"cpus\" is provided");
161 // We have to do this because the compiler fails at doing it automatically
162 // because pt_cpu is not in a namespace
163 if (!fromJSON(*value
.getAsObject()->get("cpuInfo"),
164 bundle_description
.cpu_info
, path
.field("cpuInfo")))
167 // When kernel section is present, this is kernel-only tracing. Thus, throw an
168 // error if the "processes" section is non-empty or the "cpus" section is not
170 if (bundle_description
.kernel
) {
171 if (bundle_description
.processes
&&
172 !bundle_description
.processes
->empty()) {
173 path
.report("\"processes\" must be empty when \"kernel\" is provided");
176 if (!bundle_description
.cpus
) {
177 path
.report("\"cpus\" is required when \"kernel\" is provided");
180 } else if (!bundle_description
.processes
) {
181 // Usermode tracing requires processes section.
182 path
.report("\"processes\" is required when \"kernel\" is not provided");
188 } // namespace trace_intel_pt
189 } // namespace lldb_private