1 #include <uapi/linux/ptrace.h>
2 #include <linux/sched.h>
5 G_DBUS_MESSAGE_TYPE_INVALID,
6 G_DBUS_MESSAGE_TYPE_METHOD_CALL,
7 G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
8 G_DBUS_MESSAGE_TYPE_ERROR,
9 G_DBUS_MESSAGE_TYPE_SIGNAL
13 G_DBUS_MESSAGE_FLAGS_NONE = 0,
14 G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED = (1<<0),
15 G_DBUS_MESSAGE_FLAGS_NO_AUTO_START = (1<<1)
20 G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN = 'B',
21 G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN = 'l'
22 } GDBusMessageByteOrder;
26 G_DBUS_SEND_MESSAGE_FLAGS_NONE = 0,
27 G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL = (1<<0)
28 } GDBusSendMessageFlags;
30 struct GTypeInstance {
35 struct GTypeInstance g_type_instance;
37 volatile unsigned int ref_count;
42 struct GObject parent_instance;
43 GDBusMessageType type;
44 GDBusMessageFlags flags;
46 GDBusMessageByteOrder byte_order;
47 unsigned char major_protocol_version;
56 unsigned int allocated;
57 unsigned int constant : 1;
58 unsigned int locked : 1;
59 unsigned int invalid : 1;
60 unsigned int align_offset : 3;
64 struct DBusLink *prev;
65 struct DBusLink *next;
69 struct DBusHeaderFields {
74 struct DBusString data;
76 struct DBusHeaderFields fields[9];
80 unsigned char protocol_version;
88 struct DBusDataSlotList {
89 struct DBusDataSlot *slots;
94 struct DBusList *prev;
95 struct DbusList *next;
101 struct DBusHeader header;
102 struct DBusString body;
104 unsigned int locked : 1;
105 unsigned int in_cache : 1;
108 long size_counter_delta;
111 u32 changed_stamp : 21;
112 struct DBusDataSlotList *slot_list;
119 unsigned n_unix_fds_allocated;
121 long unix_fd_counter_delta;
123 struct DBusString *signature;
124 struct DBusString *unique_sender;
125 size_t gvariant_body_last_offset;
126 size_t gvariant_body_last_pos;
129 struct DBusConnection {
134 void *dispatch_mutex;
139 struct DBusList *outgoing_messages;
140 struct DBusList *incoming_messages;
141 struct DBusList *expired_messages;
143 struct DBusMessage *message_borrowed;
151 char comm[TASK_COMM_LEN];
171 BPF_HASH(msg_sent_addr, u32 , struct data_t);
172 BPF_HASH(msg_latency, struct data_t , struct stats_t);
173 BPF_HASH(g_serial_addr, struct data_t, struct GDBusMessage *);
174 BPF_HISTOGRAM(latency_histo);
176 static void get_process_data(struct data_t *data) {
177 data->pid = bpf_get_current_pid_tgid();
178 bpf_get_current_comm(&data->comm, sizeof(data->comm));
179 data->ts = bpf_ktime_get_ns() / 1000;
182 static int get_delay(int serial, struct data_t receiver_data) {
184 struct stats_t *stat;
185 struct data_t *sender_data = msg_sent_addr.lookup(&serial);
186 if (sender_data != 0 && sender_data->pid != receiver_data.pid) {
187 msg_sent_addr.delete(&serial);
188 delta = receiver_data.ts - sender_data->ts;
189 if (delta > 5000 || delta <= 0) {
192 latency_histo.increment(bpf_log2l(delta));
193 receiver_data.pid = sender_data->pid;
194 receiver_data.ts = 0;
195 bpf_probe_read(&receiver_data.comm, sizeof(receiver_data.comm), sender_data->comm);
196 stat = msg_latency.lookup(&receiver_data);
198 struct stats_t stats = {delta, delta, 1, delta};
199 msg_latency.insert(&receiver_data, &stats);
202 struct stats_t stats = {stat->min, stat->avg, stat->count, stat->max};
203 if (stats.min > delta) {
206 else if (stats.max < delta) {
210 if (stats.count > 1000) {
218 stats.avg = (avg / stats.count);
219 msg_latency.update(&receiver_data, &stats);
224 int get_msg_addr(struct pt_regs *ctx, struct DBusConnection *conn, struct DBusMessage *msg){
225 struct data_t data = {};
226 get_process_data(&data);
227 struct header_data *header = 0;
228 bpf_probe_read(&header, sizeof(header), (char*)msg + offsetof(struct DBusMessage, header.data.str));
230 bpf_probe_read(&serial, sizeof(serial), (char*)header + offsetof(struct header_data, serial));
231 msg_sent_addr.update(&serial,&data);
235 int get_msg_latency(struct pt_regs *ctx, struct DBusConnection *conn) {
236 struct data_t receiver_data = {};
237 struct DBusMessage *msg = 0;
238 struct header_data *header = 0;
240 struct DBusList *link = 0;
242 bpf_probe_read(&link, sizeof(link), (char *)conn + offsetof(struct DBusConnection, incoming_messages));
248 get_process_data(&receiver_data);
249 bpf_probe_read(&msg, sizeof(msg), (char *)link + offsetof(struct DBusList, data));
250 bpf_probe_read(&header, sizeof(header), (char*)msg + offsetof(struct DBusMessage, header.data.str));
251 bpf_probe_read(&serial, sizeof(serial), (char*)header + offsetof(struct header_data, serial));
252 get_delay(serial, receiver_data);
256 int g_get_latency(struct pt_regs *ctx, struct GDBusMessage *msg) {
257 struct data_t *receiver_data;
258 u32 serial = msg->serial;
259 receiver_data = msg_sent_addr.lookup(&serial);
260 struct data_t data = {};
261 get_process_data(&data);
263 if ((receiver_data == 0) || (receiver_data->pid == data.pid)){
264 msg_sent_addr.delete(&serial);
265 get_delay(serial, data);
268 msg_sent_addr.update(&serial, &data);
269 bpf_trace_printk("sender: %d\n", serial);