1 | //===-- TraceIntelPTGDBRemotePackets.cpp ------------------------*- C++ -*-===// |
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 "lldb/Utility/TraceIntelPTGDBRemotePackets.h" |
10 | |
11 | using namespace llvm; |
12 | using namespace llvm::json; |
13 | |
14 | namespace lldb_private { |
15 | |
16 | const char *IntelPTDataKinds::kProcFsCpuInfo = "procfsCpuInfo" ; |
17 | const char *IntelPTDataKinds::kIptTrace = "iptTrace" ; |
18 | const char *IntelPTDataKinds::kPerfContextSwitchTrace = |
19 | "perfContextSwitchTrace" ; |
20 | |
21 | bool TraceIntelPTStartRequest::IsPerCpuTracing() const { |
22 | return per_cpu_tracing.value_or(u: false); |
23 | } |
24 | |
25 | json::Value toJSON(const JSONUINT64 &uint64, bool hex) { |
26 | if (hex) |
27 | return json::Value(formatv(Fmt: "{0:x+}" , Vals: uint64.value)); |
28 | else |
29 | return json::Value(formatv(Fmt: "{0}" , Vals: uint64.value)); |
30 | } |
31 | |
32 | bool fromJSON(const json::Value &value, JSONUINT64 &uint64, Path path) { |
33 | if (std::optional<uint64_t> val = value.getAsUINT64()) { |
34 | uint64.value = *val; |
35 | return true; |
36 | } else if (std::optional<StringRef> val = value.getAsString()) { |
37 | if (!val->getAsInteger(/*radix=*/Radix: 0, Result&: uint64.value)) |
38 | return true; |
39 | path.report(Message: "invalid string number" ); |
40 | } |
41 | path.report(Message: "invalid number or string number" ); |
42 | return false; |
43 | } |
44 | |
45 | bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet, |
46 | Path path) { |
47 | ObjectMapper o(value, path); |
48 | if (!(o && fromJSON(value, packet&: (TraceStartRequest &)packet, path) && |
49 | o.map(Prop: "enableTsc" , Out&: packet.enable_tsc) && |
50 | o.map(Prop: "psbPeriod" , Out&: packet.psb_period) && |
51 | o.map(Prop: "iptTraceSize" , Out&: packet.ipt_trace_size))) |
52 | return false; |
53 | |
54 | if (packet.IsProcessTracing()) { |
55 | if (!o.map(Prop: "processBufferSizeLimit" , Out&: packet.process_buffer_size_limit) || |
56 | !o.map(Prop: "perCpuTracing" , Out&: packet.per_cpu_tracing) || |
57 | !o.map(Prop: "disableCgroupTracing" , Out&: packet.disable_cgroup_filtering)) |
58 | return false; |
59 | } |
60 | return true; |
61 | } |
62 | |
63 | json::Value toJSON(const TraceIntelPTStartRequest &packet) { |
64 | json::Value base = toJSON(packet: (const TraceStartRequest &)packet); |
65 | json::Object &obj = *base.getAsObject(); |
66 | obj.try_emplace(K: "iptTraceSize" , Args: packet.ipt_trace_size); |
67 | obj.try_emplace(K: "processBufferSizeLimit" , Args: packet.process_buffer_size_limit); |
68 | obj.try_emplace(K: "psbPeriod" , Args: packet.psb_period); |
69 | obj.try_emplace(K: "enableTsc" , Args: packet.enable_tsc); |
70 | obj.try_emplace(K: "perCpuTracing" , Args: packet.per_cpu_tracing); |
71 | obj.try_emplace(K: "disableCgroupTracing" , Args: packet.disable_cgroup_filtering); |
72 | return base; |
73 | } |
74 | |
75 | uint64_t LinuxPerfZeroTscConversion::ToNanos(uint64_t tsc) const { |
76 | uint64_t quot = tsc >> time_shift; |
77 | uint64_t rem_flag = (((uint64_t)1 << time_shift) - 1); |
78 | uint64_t rem = tsc & rem_flag; |
79 | return time_zero.value + quot * time_mult + ((rem * time_mult) >> time_shift); |
80 | } |
81 | |
82 | uint64_t LinuxPerfZeroTscConversion::ToTSC(uint64_t nanos) const { |
83 | uint64_t time = nanos - time_zero.value; |
84 | uint64_t quot = time / time_mult; |
85 | uint64_t rem = time % time_mult; |
86 | return (quot << time_shift) + (rem << time_shift) / time_mult; |
87 | } |
88 | |
89 | json::Value toJSON(const LinuxPerfZeroTscConversion &packet) { |
90 | return json::Value(json::Object{ |
91 | {.K: "timeMult" , .V: packet.time_mult}, |
92 | {.K: "timeShift" , .V: packet.time_shift}, |
93 | {.K: "timeZero" , .V: toJSON(uint64: packet.time_zero, /*hex=*/false)}, |
94 | }); |
95 | } |
96 | |
97 | bool fromJSON(const json::Value &value, LinuxPerfZeroTscConversion &packet, |
98 | json::Path path) { |
99 | ObjectMapper o(value, path); |
100 | uint64_t time_mult, time_shift; |
101 | if (!(o && o.map(Prop: "timeMult" , Out&: time_mult) && o.map(Prop: "timeShift" , Out&: time_shift) && |
102 | o.map(Prop: "timeZero" , Out&: packet.time_zero))) |
103 | return false; |
104 | packet.time_mult = time_mult; |
105 | packet.time_shift = time_shift; |
106 | return true; |
107 | } |
108 | |
109 | bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet, |
110 | json::Path path) { |
111 | ObjectMapper o(value, path); |
112 | return o && fromJSON(value, packet&: (TraceGetStateResponse &)packet, path) && |
113 | o.map(Prop: "tscPerfZeroConversion" , Out&: packet.tsc_perf_zero_conversion) && |
114 | o.map(Prop: "usingCgroupFiltering" , Out&: packet.using_cgroup_filtering); |
115 | } |
116 | |
117 | json::Value toJSON(const TraceIntelPTGetStateResponse &packet) { |
118 | json::Value base = toJSON(packet: (const TraceGetStateResponse &)packet); |
119 | json::Object &obj = *base.getAsObject(); |
120 | obj.insert(E: {.K: "tscPerfZeroConversion" , .V: packet.tsc_perf_zero_conversion}); |
121 | obj.insert(E: {.K: "usingCgroupFiltering" , .V: packet.using_cgroup_filtering}); |
122 | return base; |
123 | } |
124 | |
125 | } // namespace lldb_private |
126 | |