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