190 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "TraceIntelPTJSONStructs.h"10#include "llvm/Support/JSON.h"11#include <optional>12#include <string>13 14using namespace lldb;15using namespace lldb_private;16using namespace lldb_private::trace_intel_pt;17using namespace llvm;18using namespace llvm::json;19 20namespace lldb_private {21namespace trace_intel_pt {22 23std::optional<std::vector<lldb::cpu_id_t>>24JSONTraceBundleDescription::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 33json::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 44bool 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 52json::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 59bool 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 64json::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 73bool 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 79json::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 87bool 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 97json::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 106bool 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 120json::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 128bool 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 134json::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 it139 // automatically because pt_cpu is not in a namespace140 {"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 146bool 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 automatically162 // because pt_cpu is not in a namespace163 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 an168 // error if the "processes" section is non-empty or the "cpus" section is not169 // 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_pt189} // namespace lldb_private190