Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/TraceIntelPTJSONStructs.cpp
39645 views
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
#include "llvm/Support/JSON.h"
11
#include <optional>
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
std::optional<std::vector<lldb::cpu_id_t>>
24
JSONTraceBundleDescription::GetCpuIds() {
25
if (!cpus)
26
return std::nullopt;
27
std::vector<lldb::cpu_id_t> cpu_ids;
28
for (const JSONCpu &cpu : *cpus)
29
cpu_ids.push_back(cpu.id);
30
return cpu_ids;
31
}
32
33
json::Value toJSON(const JSONModule &module) {
34
json::Object json_module;
35
json_module["systemPath"] = module.system_path;
36
if (module.file)
37
json_module["file"] = *module.file;
38
json_module["loadAddress"] = toJSON(module.load_address, true);
39
if (module.uuid)
40
json_module["uuid"] = *module.uuid;
41
return std::move(json_module);
42
}
43
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);
50
}
51
52
json::Value toJSON(const JSONThread &thread) {
53
json::Object obj{{"tid", thread.tid}};
54
if (thread.ipt_trace)
55
obj["iptTrace"] = *thread.ipt_trace;
56
return obj;
57
}
58
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);
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 JSONCpu &cpu) {
80
return Object{
81
{"id", cpu.id},
82
{"iptTrace", cpu.ipt_trace},
83
{"contextSwitchTrace", cpu.context_switch_trace},
84
};
85
}
86
87
bool fromJSON(const json::Value &value, JSONCpu &cpu, Path path) {
88
ObjectMapper o(value, path);
89
uint64_t cpu_id;
90
if (!(o && o.map("id", cpu_id) && o.map("iptTrace", cpu.ipt_trace) &&
91
o.map("contextSwitchTrace", cpu.context_switch_trace)))
92
return false;
93
cpu.id = cpu_id;
94
return true;
95
}
96
97
json::Value toJSON(const pt_cpu &cpu_info) {
98
return Object{
99
{"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"},
100
{"family", cpu_info.family},
101
{"model", cpu_info.model},
102
{"stepping", cpu_info.stepping},
103
};
104
}
105
106
bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) {
107
ObjectMapper o(value, path);
108
std::string vendor;
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)))
112
return false;
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;
117
return true;
118
}
119
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);
126
}
127
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);
132
}
133
134
json::Value toJSON(const JSONTraceBundleDescription &bundle_description) {
135
return Object{
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}};
144
}
145
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)))
155
return false;
156
if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) {
157
path.report(
158
"\"tscPerfZeroConversion\" is required when \"cpus\" is provided");
159
return false;
160
}
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")))
165
return false;
166
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
169
// present.
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");
174
return false;
175
}
176
if (!bundle_description.cpus) {
177
path.report("\"cpus\" is required when \"kernel\" is provided");
178
return false;
179
}
180
} else if (!bundle_description.processes) {
181
// Usermode tracing requires processes section.
182
path.report("\"processes\" is required when \"kernel\" is not provided");
183
return false;
184
}
185
return true;
186
}
187
188
} // namespace trace_intel_pt
189
} // namespace lldb_private
190
191