jj10306 updated this revision to Diff 411862.
jj10306 marked 3 inline comments as done.
jj10306 edited the summary of this revision.
jj10306 added a comment.
Address comments, still need to handle uint64_t JSON serialization correctly. I
plan to proceed with decoder and schema changes now that initial feedback has
been received and addressed.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D120595/new/
https://reviews.llvm.org/D120595
Files:
lldb/docs/lldb-gdb-remote.txt
lldb/include/lldb/Target/Trace.h
lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
lldb/source/Plugins/Process/Linux/IntelPTManager.h
lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
lldb/source/Target/Trace.cpp
lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
Index: lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
===================================================================
--- lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
+++ lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
+#include "lldb/Utility/TraceGDBRemotePackets.h"
using namespace llvm;
using namespace llvm::json;
@@ -43,4 +44,51 @@
return base;
}
+uint64_t PerfTimestampCounterRate::ToNanos(uint64_t tsc) {
+ // conversion logic here
+ return 1;
+}
+
+bool fromJSON(const llvm::json::Value &value, TimestampCounterRateSP &tsc_rate, llvm::json::Path path) {
+ std::string tsc_rate_kind;
+ ObjectMapper o(value, path);
+
+ if(!o.map("kind", tsc_rate_kind))
+ return false;
+
+ if (tsc_rate_kind == "perf") {
+ int a, b, c;
+ if (!o.map("a", a) || !o.map("b", b) || !o.map("c", c))
+ return false;
+ tsc_rate = std::make_shared<PerfTimestampCounterRate>((uint32_t)a, (uint16_t)b, (uint64_t)c);
+ }
+ return false;
+}
+
+bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet, Path path) {
+ ObjectMapper o(value, path);
+ bool base_bool = o && fromJSON(value, (TraceGetStateResponse &)packet, path) && o.mapOptional("tsc_rate", packet.tsc_rate);
+ return base_bool;
+
+}
+
+llvm::json::Value PerfTimestampCounterRate::toJSON() {
+ return json::Value(json::Object{
+ {"kind", "perf"},
+ {"time_mult", (int64_t) m_time_mult},
+ {"time_shift", (int64_t) m_time_shift},
+ {"time_zero", (int64_t) m_time_zero}, // TODO: handle the potential lossy conversion correctly
+ });
+}
+
+json::Value toJSON(const TraceIntelPTGetStateResponse &packet) {
+ json::Value base = toJSON((const TraceGetStateResponse &)packet);
+ auto tsc_rate = packet.tsc_rate;
+ // is there a better way to check that it's not None nor nullptr?
+ if (tsc_rate && *tsc_rate) {
+ json::Value tsc_converter_json = tsc_rate.getValue()->toJSON();
+ base.getAsObject()->try_emplace("tsc_rate", std::move(tsc_converter_json));
+ }
+ return base;
+}
} // namespace lldb_private
Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -18,6 +18,7 @@
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Stream.h"
+#include "lldb/Utility/TraceGDBRemotePackets.h"
using namespace lldb;
using namespace lldb_private;
@@ -187,28 +188,17 @@
m_stop_id = new_stop_id;
m_live_thread_data.clear();
- Expected<std::string> json_string = GetLiveProcessState();
- if (!json_string) {
- DoRefreshLiveProcessState(json_string.takeError());
- return;
- }
- Expected<TraceGetStateResponse> live_process_state =
- json::parse<TraceGetStateResponse>(*json_string, "TraceGetStateResponse");
- if (!live_process_state) {
- DoRefreshLiveProcessState(live_process_state.takeError());
- return;
- }
+ if (std::unique_ptr<TraceGetStateResponse> live_process_state = DoRefreshLiveProcessState(GetLiveProcessState())) {
+ for (const TraceThreadState &thread_state :
+ live_process_state->tracedThreads) {
+ for (const TraceBinaryData &item : thread_state.binaryData)
+ m_live_thread_data[thread_state.tid][item.kind] = item.size;
+ }
- for (const TraceThreadState &thread_state :
- live_process_state->tracedThreads) {
- for (const TraceBinaryData &item : thread_state.binaryData)
- m_live_thread_data[thread_state.tid][item.kind] = item.size;
+ for (const TraceBinaryData &item : live_process_state->processBinaryData)
+ m_live_process_data[item.kind] = item.size;
}
- for (const TraceBinaryData &item : live_process_state->processBinaryData)
- m_live_process_data[item.kind] = item.size;
-
- DoRefreshLiveProcessState(std::move(live_process_state));
}
uint32_t Trace::GetStopID() {
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -12,6 +12,7 @@
#include "IntelPTDecoder.h"
#include "TraceIntelPTSessionFileParser.h"
#include "lldb/Utility/FileSpec.h"
+#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
#include "lldb/lldb-types.h"
#include "llvm/Support/raw_ostream.h"
@@ -74,8 +75,8 @@
llvm::Optional<size_t> GetRawTraceSize(Thread &thread);
- void DoRefreshLiveProcessState(
- llvm::Expected<TraceGetStateResponse> state) override;
+ std::unique_ptr<TraceGetStateResponse> DoRefreshLiveProcessState(
+ llvm::Expected<std::string> json_string) override;
bool IsTraced(lldb::tid_t tid) override;
@@ -183,6 +184,8 @@
std::map<lldb::tid_t, std::unique_ptr<ThreadDecoder>> m_thread_decoders;
/// Error gotten after a failed live process update, if any.
llvm::Optional<std::string> m_live_refresh_error;
+ /// TSC to nano conversion rate. `nullptr` if no conversion exists.
+ llvm::Optional<TimestampCounterRateSP> m_tsc_rate;
};
} // namespace trace_intel_pt
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -17,6 +17,7 @@
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
+#include "lldb/Utility/TraceGDBRemotePackets.h"
#include "llvm/ADT/None.h"
using namespace lldb;
@@ -185,13 +186,22 @@
Process *TraceIntelPT::GetLiveProcess() { return m_live_process; }
-void TraceIntelPT::DoRefreshLiveProcessState(
- Expected<TraceGetStateResponse> state) {
+std::unique_ptr<TraceGetStateResponse> TraceIntelPT::DoRefreshLiveProcessState(
+ Expected<std::string> json_string) {
+
+ if (!json_string) {
+ m_live_refresh_error = toString(json_string.takeError());
+ return nullptr;
+ }
+
m_thread_decoders.clear();
+ Expected<TraceIntelPTGetStateResponse> state =
+ json::parse<TraceIntelPTGetStateResponse>(*json_string, "TraceIntelPTGetStateResponse");
+
if (!state) {
m_live_refresh_error = toString(state.takeError());
- return;
+ return nullptr;
}
for (const TraceThreadState &thread_state : state->tracedThreads) {
@@ -200,6 +210,9 @@
m_thread_decoders.emplace(
thread_state.tid, std::make_unique<LiveThreadDecoder>(thread, *this));
}
+ m_tsc_rate = state->tsc_rate;
+
+ return std::make_unique<TraceGetStateResponse>(state.get());
}
bool TraceIntelPT::IsTraced(lldb::tid_t tid) {
Index: lldb/source/Plugins/Process/Linux/IntelPTManager.h
===================================================================
--- lldb/source/Plugins/Process/Linux/IntelPTManager.h
+++ lldb/source/Plugins/Process/Linux/IntelPTManager.h
@@ -208,6 +208,8 @@
IntelPTManager(lldb::pid_t pid) : m_pid(pid), m_thread_traces(pid) {}
static bool IsSupported();
+ static void GetPerfTscRate(perf_event_mmap_page &mmap_meta);
+
/// If "process tracing" is enabled, then trace the given thread.
llvm::Error OnThreadCreated(lldb::tid_t tid);
@@ -235,6 +237,8 @@
/// Dispose of all traces
void Clear();
+ static llvm::Optional<TimestampCounterRateSP> g_tsc_rate;
+
private:
llvm::Error TraceStop(lldb::tid_t tid);
Index: lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
===================================================================
--- lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
+++ lldb/source/Plugins/Process/Linux/IntelPTManager.cpp
@@ -42,6 +42,8 @@
const char *kPSBPeriodBitOffsetFile =
"/sys/bus/event_source/devices/intel_pt/format/psb_period";
+llvm::Optional<TimestampCounterRateSP> IntelPTManager::g_tsc_rate = llvm::None;
+
enum IntelPTConfigFileType {
Hex = 0,
// 0 or 1
@@ -252,6 +254,8 @@
reinterpret_cast<perf_event_mmap_page *>(base),
munmap_delete(buffer_size + page_size));
+ IntelPTManager::GetPerfTscRate(*m_mmap_meta);
+
m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size;
m_mmap_meta->aux_size = buffer_size;
@@ -628,7 +632,7 @@
if (!cpu_info)
return cpu_info.takeError();
- TraceGetStateResponse state;
+ TraceIntelPTGetStateResponse state;
state.processBinaryData.push_back(
{"cpuInfo", static_cast<int64_t>(cpu_info->size())});
@@ -642,6 +646,9 @@
state.tracedThreads.insert(state.tracedThreads.end(), thread_states.begin(),
thread_states.end());
}
+
+ state.tsc_rate = IntelPTManager::g_tsc_rate;
+
return toJSON(state);
}
@@ -687,3 +694,13 @@
ClearProcessTracing();
m_thread_traces.Clear();
}
+
+void IntelPTManager::GetPerfTscRate(perf_event_mmap_page &mmap_meta) {
+ if (!IntelPTManager::g_tsc_rate) {
+ if (mmap_meta.cap_user_time_zero) {
+ IntelPTManager::g_tsc_rate = std::make_shared<PerfTimestampCounterRate>(mmap_meta.time_mult, mmap_meta.time_shift, mmap_meta.time_zero);
+ }
+ } else {
+ IntelPTManager::g_tsc_rate = nullptr;
+ }
+}
Index: lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
===================================================================
--- lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
+++ lldb/include/lldb/Utility/TraceIntelPTGDBRemotePackets.h
@@ -11,6 +11,7 @@
#include "lldb/Utility/TraceGDBRemotePackets.h"
+
/// See docs/lldb-gdb-remote.txt for more information.
namespace lldb_private {
@@ -38,6 +39,48 @@
llvm::json::Path path);
llvm::json::Value toJSON(const TraceIntelPTStartRequest &packet);
+
+/// TSC to nanosecond conversion.
+class TimestampCounterRate {
+ public:
+ virtual ~TimestampCounterRate() = default;
+ /// Convert TSC value to nanoseconds. This represents the number of nanoseconds since
+ /// the TSC register's reset.
+ virtual uint64_t ToNanos(uint64_t tsc) = 0;
+ virtual llvm::json::Value toJSON() = 0;
+};
+
+typedef std::shared_ptr<TimestampCounterRate> TimestampCounterRateSP;
+
+/// TSC to nanoseconds conversion values defined in struct perf_event_mmap_page.
+/// See https://man7.org/linux/man-pages/man2/perf_event_open.2.html for more information.
+class PerfTimestampCounterRate : public TimestampCounterRate {
+ public:
+ PerfTimestampCounterRate() = default;
+ PerfTimestampCounterRate(uint32_t time_mult, uint16_t time_shift, uint64_t time_zero) :
+ m_time_mult(time_mult), m_time_shift(time_shift), m_time_zero(static_cast<int64_t>(time_zero)) {}
+ uint64_t ToNanos(uint64_t tsc) override;
+ llvm::json::Value toJSON() override;
+
+ // TODO: make implementation details private.
+ uint32_t m_time_mult;
+ uint16_t m_time_shift;
+ uint64_t m_time_zero;
+};
+
+/// jLLDBTraceGetState gdb-remote packet
+/// Contains additional information related to TSC -> nanosecond conversion.
+struct TraceIntelPTGetStateResponse : TraceGetStateResponse {
+ /// `nullptr` if no tsc conversion rate exists.
+ llvm::Optional<TimestampCounterRateSP> tsc_rate;
+};
+
+bool fromJSON(const llvm::json::Value &value, TimestampCounterRateSP &tsc_converter, llvm::json::Path path);
+
+bool fromJSON(const llvm::json::Value &value, TraceIntelPTGetStateResponse &packet, llvm::json::Path path);
+
+llvm::json::Value toJSON(const TraceIntelPTGetStateResponse &packet);
+
/// \}
} // namespace lldb_private
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -302,10 +302,13 @@
///
/// This is invoked by RefreshLiveProcessState when a new state is found.
///
- /// \param[in] state
- /// The jLLDBTraceGetState response.
- virtual void
- DoRefreshLiveProcessState(llvm::Expected<TraceGetStateResponse> state) = 0;
+ /// \param[in] json_string
+ /// String representation of the jLLDBTraceGetState response.
+ ///
+ /// \return
+ /// Unique pointer to the packet response, nullptr if response parsing failed.
+ virtual std::unique_ptr<TraceGetStateResponse>
+ DoRefreshLiveProcessState(llvm::Expected<std::string> json_string) = 0;
/// Method to be invoked by the plug-in to refresh the live process state.
///
Index: lldb/docs/lldb-gdb-remote.txt
===================================================================
--- lldb/docs/lldb-gdb-remote.txt
+++ lldb/docs/lldb-gdb-remote.txt
@@ -451,7 +451,8 @@
// "size": <decimal integer>,
// Size in bytes of this thread data.
// },
-// }]
+// }],
+// ... other parameters specific to the provided tracing type
// }
//
// NOTES
@@ -463,6 +464,19 @@
// Binary data kinds:
// - threadTraceBuffer: trace buffer for a thread.
// - cpuInfo: contents of the /proc/cpuinfo file.
+// Additional parameters in the output schema:
+//
+// tsc_rate: {
+// kind: "perf",
+// time_mult: int,
+// time_shift: int,
+// time_zero: int
+// |
+// kind: "freq"
+// freq_conversion: int,
+// }
+
+}
//----------------------------------------------------------------------
send packet: jLLDBTraceGetState:{"type":<type>}]
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits