1349cc55cSDimitry Andric //===-- TraceIntelPTJSONStructs.cpp ---------------------------------------===// 2349cc55cSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6349cc55cSDimitry Andric // 7349cc55cSDimitry Andric //===----------------------------------------------------------------------===// 8349cc55cSDimitry Andric 9349cc55cSDimitry Andric #include "TraceIntelPTJSONStructs.h" 10349cc55cSDimitry Andric 11349cc55cSDimitry Andric #include "llvm/Support/JSON.h" 12349cc55cSDimitry Andric #include <string> 13349cc55cSDimitry Andric 14349cc55cSDimitry Andric using namespace lldb; 15349cc55cSDimitry Andric using namespace lldb_private; 16349cc55cSDimitry Andric using namespace lldb_private::trace_intel_pt; 17349cc55cSDimitry Andric using namespace llvm; 18*81ad6265SDimitry Andric using namespace llvm::json; 19349cc55cSDimitry Andric 20*81ad6265SDimitry Andric namespace lldb_private { 21*81ad6265SDimitry Andric namespace trace_intel_pt { 22349cc55cSDimitry Andric 23*81ad6265SDimitry Andric Optional<std::vector<lldb::cpu_id_t>> JSONTraceBundleDescription::GetCpuIds() { 24*81ad6265SDimitry Andric if (!cpus) 25*81ad6265SDimitry Andric return None; 26*81ad6265SDimitry Andric std::vector<lldb::cpu_id_t> cpu_ids; 27*81ad6265SDimitry Andric for (const JSONCpu &cpu : *cpus) 28*81ad6265SDimitry Andric cpu_ids.push_back(cpu.id); 29*81ad6265SDimitry Andric return cpu_ids; 30349cc55cSDimitry Andric } 31349cc55cSDimitry Andric 32*81ad6265SDimitry Andric json::Value toJSON(const JSONModule &module) { 33*81ad6265SDimitry Andric json::Object json_module; 34*81ad6265SDimitry Andric json_module["systemPath"] = module.system_path; 35*81ad6265SDimitry Andric if (module.file) 36*81ad6265SDimitry Andric json_module["file"] = *module.file; 37*81ad6265SDimitry Andric json_module["loadAddress"] = toJSON(module.load_address, true); 38*81ad6265SDimitry Andric if (module.uuid) 39*81ad6265SDimitry Andric json_module["uuid"] = *module.uuid; 40*81ad6265SDimitry Andric return std::move(json_module); 41349cc55cSDimitry Andric } 42349cc55cSDimitry Andric 43*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONModule &module, Path path) { 44*81ad6265SDimitry Andric ObjectMapper o(value, path); 45*81ad6265SDimitry Andric return o && o.map("systemPath", module.system_path) && 46*81ad6265SDimitry Andric o.map("file", module.file) && 47*81ad6265SDimitry Andric o.map("loadAddress", module.load_address) && 48*81ad6265SDimitry Andric o.map("uuid", module.uuid); 49*81ad6265SDimitry Andric } 50*81ad6265SDimitry Andric 51*81ad6265SDimitry Andric json::Value toJSON(const JSONThread &thread) { 52*81ad6265SDimitry Andric json::Object obj{{"tid", thread.tid}}; 53*81ad6265SDimitry Andric if (thread.ipt_trace) 54*81ad6265SDimitry Andric obj["iptTrace"] = *thread.ipt_trace; 55*81ad6265SDimitry Andric return obj; 56*81ad6265SDimitry Andric } 57*81ad6265SDimitry Andric 58*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONThread &thread, Path path) { 59*81ad6265SDimitry Andric ObjectMapper o(value, path); 60*81ad6265SDimitry Andric return o && o.map("tid", thread.tid) && o.map("iptTrace", thread.ipt_trace); 61*81ad6265SDimitry Andric } 62*81ad6265SDimitry Andric 63*81ad6265SDimitry Andric json::Value toJSON(const JSONProcess &process) { 64*81ad6265SDimitry Andric return Object{ 65*81ad6265SDimitry Andric {"pid", process.pid}, 66*81ad6265SDimitry Andric {"triple", process.triple}, 67*81ad6265SDimitry Andric {"threads", process.threads}, 68*81ad6265SDimitry Andric {"modules", process.modules}, 69*81ad6265SDimitry Andric }; 70*81ad6265SDimitry Andric } 71*81ad6265SDimitry Andric 72*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONProcess &process, Path path) { 73*81ad6265SDimitry Andric ObjectMapper o(value, path); 74*81ad6265SDimitry Andric return o && o.map("pid", process.pid) && o.map("triple", process.triple) && 75*81ad6265SDimitry Andric o.map("threads", process.threads) && o.map("modules", process.modules); 76*81ad6265SDimitry Andric } 77*81ad6265SDimitry Andric 78*81ad6265SDimitry Andric json::Value toJSON(const JSONCpu &cpu) { 79*81ad6265SDimitry Andric return Object{ 80*81ad6265SDimitry Andric {"id", cpu.id}, 81*81ad6265SDimitry Andric {"iptTrace", cpu.ipt_trace}, 82*81ad6265SDimitry Andric {"contextSwitchTrace", cpu.context_switch_trace}, 83*81ad6265SDimitry Andric }; 84*81ad6265SDimitry Andric } 85*81ad6265SDimitry Andric 86*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONCpu &cpu, Path path) { 87*81ad6265SDimitry Andric ObjectMapper o(value, path); 88*81ad6265SDimitry Andric uint64_t cpu_id; 89*81ad6265SDimitry Andric if (!(o && o.map("id", cpu_id) && o.map("iptTrace", cpu.ipt_trace) && 90*81ad6265SDimitry Andric o.map("contextSwitchTrace", cpu.context_switch_trace))) 91*81ad6265SDimitry Andric return false; 92*81ad6265SDimitry Andric cpu.id = cpu_id; 93*81ad6265SDimitry Andric return true; 94*81ad6265SDimitry Andric } 95*81ad6265SDimitry Andric 96*81ad6265SDimitry Andric json::Value toJSON(const pt_cpu &cpu_info) { 97*81ad6265SDimitry Andric return Object{ 98*81ad6265SDimitry Andric {"vendor", cpu_info.vendor == pcv_intel ? "GenuineIntel" : "Unknown"}, 99*81ad6265SDimitry Andric {"family", cpu_info.family}, 100349cc55cSDimitry Andric {"model", cpu_info.model}, 101349cc55cSDimitry Andric {"stepping", cpu_info.stepping}, 102*81ad6265SDimitry Andric }; 103349cc55cSDimitry Andric } 104349cc55cSDimitry Andric 105*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, pt_cpu &cpu_info, Path path) { 106*81ad6265SDimitry Andric ObjectMapper o(value, path); 107*81ad6265SDimitry Andric std::string vendor; 108*81ad6265SDimitry Andric uint64_t family, model, stepping; 109*81ad6265SDimitry Andric if (!(o && o.map("vendor", vendor) && o.map("family", family) && 110*81ad6265SDimitry Andric o.map("model", model) && o.map("stepping", stepping))) 111*81ad6265SDimitry Andric return false; 112*81ad6265SDimitry Andric cpu_info.vendor = vendor == "GenuineIntel" ? pcv_intel : pcv_unknown; 113*81ad6265SDimitry Andric cpu_info.family = family; 114*81ad6265SDimitry Andric cpu_info.model = model; 115*81ad6265SDimitry Andric cpu_info.stepping = stepping; 116*81ad6265SDimitry Andric return true; 117349cc55cSDimitry Andric } 118349cc55cSDimitry Andric 119*81ad6265SDimitry Andric json::Value toJSON(const JSONTraceBundleDescription &bundle_description) { 120*81ad6265SDimitry Andric return Object{{"type", bundle_description.type}, 121*81ad6265SDimitry Andric {"processes", bundle_description.processes}, 122*81ad6265SDimitry Andric // We have to do this because the compiler fails at doing it 123*81ad6265SDimitry Andric // automatically because pt_cpu is not in a namespace 124*81ad6265SDimitry Andric {"cpuInfo", toJSON(bundle_description.cpu_info)}, 125*81ad6265SDimitry Andric {"cpus", bundle_description.cpus}, 126*81ad6265SDimitry Andric {"tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion}}; 127349cc55cSDimitry Andric } 128349cc55cSDimitry Andric 129*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONTraceBundleDescription &bundle_description, Path path) { 130*81ad6265SDimitry Andric ObjectMapper o(value, path); 131*81ad6265SDimitry Andric if (!(o && o.map("processes", bundle_description.processes) && 132*81ad6265SDimitry Andric o.map("type", bundle_description.type) && o.map("cpus", bundle_description.cpus) && 133*81ad6265SDimitry Andric o.map("tscPerfZeroConversion", bundle_description.tsc_perf_zero_conversion))) 134*81ad6265SDimitry Andric return false; 135*81ad6265SDimitry Andric if (bundle_description.cpus && !bundle_description.tsc_perf_zero_conversion) { 136*81ad6265SDimitry Andric path.report( 137*81ad6265SDimitry Andric "\"tscPerfZeroConversion\" is required when \"cpus\" is provided"); 138*81ad6265SDimitry Andric return false; 139*81ad6265SDimitry Andric } 140*81ad6265SDimitry Andric // We have to do this because the compiler fails at doing it automatically 141*81ad6265SDimitry Andric // because pt_cpu is not in a namespace 142*81ad6265SDimitry Andric if (!fromJSON(*value.getAsObject()->get("cpuInfo"), bundle_description.cpu_info, 143*81ad6265SDimitry Andric path.field("cpuInfo"))) 144*81ad6265SDimitry Andric return false; 145*81ad6265SDimitry Andric return true; 146*81ad6265SDimitry Andric } 147*81ad6265SDimitry Andric 148*81ad6265SDimitry Andric } // namespace trace_intel_pt 149*81ad6265SDimitry Andric } // namespace lldb_private 150