| //===-- TraceIntelPTGDBRemotePackets.cpp ------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" |
| |
| using namespace llvm; |
| using namespace llvm::json; |
| |
| namespace lldb_private { |
| |
| const char *IntelPTDataKinds::kProcFsCpuInfo = "procfsCpuInfo"; |
| const char *IntelPTDataKinds::kIptTrace = "iptTrace"; |
| const char *IntelPTDataKinds::kPerfContextSwitchTrace = |
| "perfContextSwitchTrace"; |
| |
| bool TraceIntelPTStartRequest::IsPerCpuTracing() const { |
| return per_cpu_tracing.value_or(false); |
| } |
| |
| json::Value toJSON(const JSONUINT64 &uint64, bool hex) { |
| if (hex) |
| return json::Value(formatv("{0:x+}", uint64.value)); |
| else |
| return json::Value(formatv("{0}", uint64.value)); |
| } |
| |
| bool fromJSON(const json::Value &value, JSONUINT64 &uint64, Path path) { |
| if (Optional<uint64_t> val = value.getAsUINT64()) { |
| uint64.value = *val; |
| return true; |
| } else if (Optional<StringRef> val = value.getAsString()) { |
| if (!val->getAsInteger(/*radix=*/0, uint64.value)) |
| return true; |
| path.report("invalid string number"); |
| } |
| path.report("invalid number or string number"); |
| return false; |
| } |
| |
| bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet, |
| Path path) { |
| ObjectMapper o(value, path); |
| if (!(o && fromJSON(value, (TraceStartRequest &)packet, path) && |
| o.map("enableTsc", packet.enable_tsc) && |
| o.map("psbPeriod", packet.psb_period) && |
| o.map("iptTraceSize", packet.ipt_trace_size))) |
| return false; |
| |
| if (packet.IsProcessTracing()) { |
| if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) || |
| !o.map("perCpuTracing", packet.per_cpu_tracing) || |
| !o.map("disableCgroupTracing", packet.disable_cgroup_filtering)) |
| return false; |
| } |
| return true; |
| } |
| |
| json::Value toJSON(const TraceIntelPTStartRequest &packet) { |
| json::Value base = toJSON((const TraceStartRequest &)packet); |
| json::Object &obj = *base.getAsObject(); |
| obj.try_emplace("iptTraceSize", packet.ipt_trace_size); |
| obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit); |
| obj.try_emplace("psbPeriod", packet.psb_period); |
| obj.try_emplace("enableTsc", packet.enable_tsc); |
| obj.try_emplace("perCpuTracing", packet.per_cpu_tracing); |
| obj.try_emplace("disableCgroupTracing", packet.disable_cgroup_filtering); |
| return base; |
| } |
| |
| uint64_t LinuxPerfZeroTscConversion::ToNanos(uint64_t tsc) const { |
| uint64_t quot = tsc >> time_shift; |
| uint64_t rem_flag = (((uint64_t)1 << time_shift) - 1); |
| uint64_t rem = tsc & rem_flag; |
| return time_zero.value + quot * time_mult + ((rem * time_mult) >> time_shift); |
| } |
| |
| uint64_t LinuxPerfZeroTscConversion::ToTSC(uint64_t nanos) const { |
| uint64_t time = nanos - time_zero.value; |
| uint64_t quot = time / time_mult; |
| uint64_t rem = time % time_mult; |
| return (quot << time_shift) + (rem << time_shift) / time_mult; |
| } |
| |
| json::Value toJSON(const LinuxPerfZeroTscConversion &packet) { |
| return json::Value(json::Object{ |
| {"timeMult", packet.time_mult}, |
| {"timeShift", packet.time_shift}, |
| {"timeZero", toJSON(packet.time_zero, /*hex=*/false)}, |
| }); |
| } |
| |
| bool fromJSON(const json::Value &value, LinuxPerfZeroTscConversion &packet, |
| json::Path path) { |
| ObjectMapper o(value, path); |
| uint64_t time_mult, time_shift; |
| if (!(o && o.map("timeMult", time_mult) && o.map("timeShift", time_shift) && |
| o.map("timeZero", packet.time_zero))) |
| return false; |
| packet.time_mult = time_mult; |
| packet.time_shift = time_shift; |
| return true; |
| } |
| |
| bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet, |
| json::Path path) { |
| ObjectMapper o(value, path); |
| return o && fromJSON(value, (TraceGetStateResponse &)packet, path) && |
| o.map("tscPerfZeroConversion", packet.tsc_perf_zero_conversion) && |
| o.map("usingCgroupFiltering", packet.using_cgroup_filtering); |
| } |
| |
| json::Value toJSON(const TraceIntelPTGetStateResponse &packet) { |
| json::Value base = toJSON((const TraceGetStateResponse &)packet); |
| json::Object &obj = *base.getAsObject(); |
| obj.insert({"tscPerfZeroConversion", packet.tsc_perf_zero_conversion}); |
| obj.insert({"usingCgroupFiltering", packet.using_cgroup_filtering}); |
| return base; |
| } |
| |
| } // namespace lldb_private |