bcc tools - devel
This package provides development libraries.
+%package dbus
+Summary: Tools for monitoring dbus
+License: Apache-2.0
+
+%description dbus
+bcc tools - dbus
+This package provides tools for tracking dbus.
+
+
%prep
%setup -q -n bcc-tools-%{version}
%{_prefix}/lib/python2.7/site-packages/bcc*
%{_datadir}/bcc/*
+%files dbus
+%{_datadir}/bcc/tools/dbus-*
+
%files devel
%{_includedir}/*
%{_libdir}/libbcc.so
--- /dev/null
+#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+struct DBusString {
+ void *str;
+ int len;
+ unsigned int allocated;
+ unsigned int constant : 1;
+ unsigned int locked : 1;
+ unsigned int invalid : 1;
+ unsigned int align_offset : 3;
+};
+
+struct DBusHeaderFields {
+ int value_pos;
+};
+
+struct DBusHeader {
+ struct DBusString data;
+
+ struct DBusHeaderFields fields[9];
+
+ u32 padding;
+ u32 byte_order;
+ unsigned char protocol_version;
+};
+
+struct DBusMessage {
+ int refcount;
+ struct DBusHeader header;
+ struct DBusString body;
+
+ unsigned int locked : 1;
+
+ void * list;
+ long size_counter_delta;
+ int timeout_ms;
+
+ u32 changed_stamp : 21;
+ void *slot_list;
+
+ int generation;
+
+ int *unix_fds;
+
+ unsigned n_unix_fds;
+ unsigned n_unix_fds_allocated;
+
+ long unix_fd_counter_delta;
+
+ struct DBusString *signature;
+ struct DBusString *unique_sender;
+ size_t gvariant_body_last_offset;
+ size_t gvariant_body_last_pos;
+};
+
+struct data_t {
+ u32 pid;
+ char comm[TASK_COMM_LEN];
+};
+
+struct bytes_t {
+ int bytes;
+};
+
+BPF_HASH(g_message, struct data_t, unsigned long *)
+BPF_HASH(msg_size, struct data_t, struct bytes_t)
+BPF_HISTOGRAM(msg_size_hist)
+
+static int get_process_data(struct data_t *data) {
+ data->pid = bpf_get_current_pid_tgid();
+ bpf_get_current_comm(&data->comm, sizeof(data->comm));
+ return 0;
+}
+
+static int message_size(unsigned long size) {
+ struct data_t data = {};
+ get_process_data(&data);
+ if (size != 0) {
+ msg_size_hist.increment(bpf_log2l(size));
+ struct bytes_t bytes_sent = {size};
+ struct bytes_t *bytes_prev = msg_size.lookup(&data);
+ if (bytes_prev != 0) {
+ bytes_sent.bytes += bytes_prev->bytes;
+ msg_size.update(&data, &bytes_sent);
+ }
+ else {
+ msg_size.insert(&data, &bytes_sent);
+ }
+ }
+ return 0;
+}
+
+int g_get_size_pointer (struct pt_regs *ctx, void *dummy, unsigned long *size) {
+ struct data_t data = {};
+ get_process_data(&data);
+ g_message.insert(&data, &size);
+ return 0;
+}
+
+int g_get_message_size(struct pt_regs *ctx) {
+ struct data_t data = {};
+ get_process_data(&data);
+ unsigned long **ptr_gsize;
+ ptr_gsize = g_message.lookup(&data);
+ if (ptr_gsize == 0) {
+ return 0;
+ }
+ unsigned long *gsize = *ptr_gsize;
+ unsigned long size = 0;
+ bpf_probe_read(&size, sizeof(size), gsize);
+ if(size > 0 && size < 1000000) {
+ message_size(size);
+ }
+ return 0;
+}
+
+int dbus_message_size(struct pt_regs *ctx, void *conn, struct DBusMessage *message) {
+ unsigned long size = 0;
+ if (message->header.data.len > 0) {
+ size += message->header.data.len;
+ }
+ if (message->body.len > 0) {
+ size += message->body.len;
+ }
+ if (size != 0) {
+ message_size(size);
+ }
+ return 0;
+}
--- /dev/null
+#!/usr/bin/python
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int
+from sys import argv
+
+def usage():
+ print("USAGE: %s [--process|histogram]" % argv[0])
+ exit()
+
+display_mode = 0
+if len(argv) != 2:
+ usage()
+if argv[1] == "--histogram":
+ display_mode = 1
+elif argv[1] != "--process":
+ usage()
+
+
+b=BPF(src_file="dbus-connection-message-size.c", debug=0)
+b.attach_uprobe(name="dbus-1", sym="_dbus_connection_message_sent_unlocked", fn_name="dbus_message_size")
+b.attach_uprobe(name="gio-2.0", sym="g_dbus_message_to_blob", fn_name="g_get_size_pointer")
+b.attach_uretprobe(name="gio-2.0", sym="g_dbus_message_to_blob", fn_name="g_get_message_size")
+
+interval = 5
+loops = 100
+count = 0
+
+while (1):
+ count += 1
+ if count == loops:
+ exit()
+ sleep(interval)
+ print ("\n%d:\n" % count)
+ if display_mode == 0:
+ stats = b["msg_size"]
+ for v, p in sorted(stats.items(), key=lambda stats: stats[1].bytes, reverse=True):
+ print("%10d %20s %20ld" %(v.pid, v.comm.encode('string-escape'), int(p.bytes)))
+ else:
+ b["msg_size_hist"].print_log2_hist("bytes")
--- /dev/null
+#!/usr/bin/python
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int, c_ulonglong
+from sys import argv
+
+
+print("Hit Ctrl-C to end.")
+count = 100
+interval = 5
+loop = 0
+# load BPF program
+bpf_text="""#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+typedef struct pdata_T {
+ u32 pid;
+ char buf[TASK_COMM_LEN];
+ u64 drun;
+ u64 dwait;
+ u64 grun;
+ u64 gwait;
+ u64 usage;
+}pdata_t;
+
+BPF_HASH(timestamp_b, u64);
+BPF_HASH(timestamp_e, u64);
+BPF_HASH(stats, u32, pdata_t, sizeof(pdata_t));
+BPF_HASH(run_start, u32);
+BPF_HASH(wait_start, u32);
+
+BPF_HISTOGRAM(dist);
+
+int do_entry_dbus(struct pt_regs *ctx) {
+ u64 time = 0;
+ pdata_t pdata;
+ pdata_t new_pdata = {0, ' ', 0, 0, 0, 0, 0};
+ u64 ts, *tsp, delta;
+ u32 pid;
+
+ ts = bpf_ktime_get_ns() / 1000;
+ if(timestamp_b.lookup(&time) == 0){
+ timestamp_b.update(&time, &ts);
+ }
+ timestamp_e.update(&time, &ts);
+
+ pid = bpf_get_current_pid_tgid();
+ tsp = run_start.lookup(&pid);
+ run_start.delete(&pid);
+ wait_start.update(&pid, &ts);
+ if(tsp != 0) {
+ delta = ts -*tsp;
+ }
+ else {
+ return 0;
+ }
+ new_pdata.pid = pid;
+ pdata = *(stats.lookup_or_init(&pid, &new_pdata));
+ pdata.drun += delta;
+ pdata.usage += delta;
+ bpf_get_current_comm(&(pdata.buf), sizeof(pdata.buf));
+ stats.update(&pid, &pdata);
+ return 0;
+}
+
+int do_return_dbus(struct pt_regs *ctx) {
+ u64 time = 0;
+ pdata_t pdata;
+ pdata_t new_pdata = {0, ' ', 0, 0, 0, 0, 0};
+ u64 ts, *tsp, delta;
+ u32 pid;
+
+ ts = bpf_ktime_get_ns() / 1000;
+ if(timestamp_b.lookup(&time) == 0){
+ timestamp_b.update(&time, &ts);
+ }
+ timestamp_e.update(&time, &ts);
+
+ pid = bpf_get_current_pid_tgid();
+ tsp = wait_start.lookup(&pid);
+ wait_start.delete(&pid);
+ run_start.update(&pid, &ts);
+ if(tsp != 0) {
+ delta = ts - *tsp;
+ }
+ else {
+ return 0;
+ }
+ new_pdata.pid = pid;
+ pdata = *(stats.lookup_or_init(&pid, &new_pdata));
+ pdata.dwait += delta;
+ bpf_get_current_comm(&(pdata.buf), sizeof(pdata.buf));
+ stats.update(&pid, &pdata);
+ return 0;
+}
+
+int do_entry_glib(struct pt_regs *ctx) {
+ u64 time = 0;
+ pdata_t pdata;
+ pdata_t new_pdata = {0, ' ', 0, 0, 0, 0, 0};
+ u64 ts, *tsp, delta;
+ u32 pid;
+
+ ts = bpf_ktime_get_ns() / 1000;
+ if(timestamp_b.lookup(&time) == 0){
+ timestamp_b.update(&time, &ts);
+ }
+ timestamp_e.update(&time, &ts);
+
+ pid = bpf_get_current_pid_tgid();
+ tsp = run_start.lookup(&pid);
+ run_start.delete(&pid);
+ wait_start.update(&pid, &ts);
+ if(tsp != 0) {
+ delta = ts -*tsp;
+ }
+ else {
+ return 0;
+ }
+ new_pdata.pid = pid;
+ pdata = *(stats.lookup_or_init(&pid, &new_pdata));
+ pdata.grun += delta;
+ pdata.usage += delta;
+ bpf_get_current_comm(&(pdata.buf), sizeof(pdata.buf));
+ stats.update(&pid, &pdata);
+ return 0;
+}
+
+int do_return_glib(struct pt_regs *ctx) {
+ u64 time = 0;
+ pdata_t pdata;
+ pdata_t new_pdata = {0, ' ', 0, 0, 0, 0, 0};
+ u64 ts, *tsp, delta;
+ u32 pid;
+
+ ts = bpf_ktime_get_ns() / 1000;
+ if(timestamp_b.lookup(&time) == 0){
+ timestamp_b.update(&time, &ts);
+ }
+ timestamp_e.update(&time, &ts);
+
+ pid = bpf_get_current_pid_tgid();
+ tsp = wait_start.lookup(&pid);
+ wait_start.delete(&pid);
+ run_start.update(&pid, &ts);
+ if(tsp != 0) {
+ delta = ts - *tsp;
+ }
+ else {
+ return 0;
+ }
+ new_pdata.pid = pid;
+ pdata = *(stats.lookup_or_init(&pid, &new_pdata));
+ pdata.gwait += delta;
+ bpf_get_current_comm(&(pdata.buf), sizeof(pdata.buf));
+ stats.update(&pid, &pdata);
+ return 0;
+}
+"""
+
+b = BPF(text=bpf_text)
+
+b.attach_uprobe(name="glib-2.0", sym="g_poll", fn_name="do_entry_glib")
+b.attach_uprobe(name="dbus-1", sym="_dbus_poll", fn_name="do_entry_dbus")
+
+b.attach_uretprobe(name="dbus-1", sym="_dbus_poll", fn_name="do_return_dbus")
+b.attach_uretprobe(name="glib-2.0", sym="g_poll", fn_name="do_return_glib")
+
+while (1):
+ if count > 0:
+
+ loop += 1
+ if loop > count:
+ exit()
+ sleep(interval)
+ print ("%d : \n" % loop)
+ b["dist"].print_log2_hist("usecs")
+ b["dist"].clear()
+ stats_t = b["stats"]
+ timestamp = b["timestamp_e"]
+ timeframe = 0
+ for v in timestamp.values():
+ timeframe = v.value
+ timestamp = b["timestamp_b"]
+ for v in timestamp.values():
+ timeframe -= v.value
+ #print("%d\n" % stats_t[0].pid)
+ print ("%10s %20s %10s %10s" % ("PID", "NAME", "DBUS", "GLIB"))
+ for v in sorted(stats_t.values(), key=lambda stats_t: stats_t.usage, reverse=True):
+ print("%10d %20s %10.6f %10.6f" % (v.pid, v.buf.encode('string-escape'), float(v.drun) / float(timeframe), float(v.grun) / float(timeframe)))
--- /dev/null
+#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+typedef enum {
+ G_DBUS_MESSAGE_TYPE_INVALID,
+ G_DBUS_MESSAGE_TYPE_METHOD_CALL,
+ G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ G_DBUS_MESSAGE_TYPE_ERROR,
+ G_DBUS_MESSAGE_TYPE_SIGNAL
+} GDBusMessageType;
+
+typedef enum {
+ G_DBUS_MESSAGE_FLAGS_NONE = 0,
+ G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED = (1<<0),
+ G_DBUS_MESSAGE_FLAGS_NO_AUTO_START = (1<<1)
+} GDBusMessageFlags;
+
+typedef enum
+{
+ G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN = 'B',
+ G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN = 'l'
+} GDBusMessageByteOrder;
+
+typedef enum
+{
+ G_DBUS_SEND_MESSAGE_FLAGS_NONE = 0,
+ G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL = (1<<0)
+} GDBusSendMessageFlags;
+
+struct GTypeInstance {
+ void *g_class;
+};
+
+struct GObject {
+ struct GTypeInstance g_type_instance;
+
+ volatile unsigned int ref_count;
+ void *qdata;
+};
+
+struct GDBusMessage {
+ struct GObject parent_instance;
+ GDBusMessageType type;
+ GDBusMessageFlags flags;
+ bool locked;
+ GDBusMessageByteOrder byte_order;
+ unsigned char major_protocol_version;
+ unsigned int serial;
+ void *headers;
+ void *body;
+};
+
+struct DBusString {
+ void *str;
+ int len;
+ unsigned int allocated;
+ unsigned int constant : 1;
+ unsigned int locked : 1;
+ unsigned int invalid : 1;
+ unsigned int align_offset : 3;
+};
+
+struct DBusLink {
+ struct DBusLink *prev;
+ struct DBusLink *next;
+ void *data;
+};
+
+struct DBusHeaderFields {
+ int value_pos;
+};
+
+struct DBusHeader {
+ struct DBusString data;
+
+ struct DBusHeaderFields fields[9];
+
+ u32 padding;
+ u32 byte_order;
+ unsigned char protocol_version;
+};
+
+struct DBusDataSlot {
+ void *data;
+ void *dummy1;
+};
+
+struct DBusDataSlotList {
+ struct DBusDataSlot *slots;
+ int n_slots;
+};
+
+struct DBusList {
+ struct DBusList *prev;
+ struct DbusList *next;
+ void *data;
+};
+
+struct DBusMessage {
+ int refcount;
+ struct DBusHeader header;
+ struct DBusString body;
+
+ unsigned int locked : 1;
+ unsigned int in_cache : 1;
+
+ void *counters;
+ long size_counter_delta;
+ int timeout_ms;
+
+ u32 changed_stamp : 21;
+ struct DBusDataSlotList *slot_list;
+
+ int generation;
+
+ int *unix_fds;
+
+ unsigned n_unix_fds;
+ unsigned n_unix_fds_allocated;
+
+ long unix_fd_counter_delta;
+
+ struct DBusString *signature;
+ struct DBusString *unique_sender;
+ size_t gvariant_body_last_offset;
+ size_t gvariant_body_last_pos;
+};
+
+struct DBusConnection {
+ int refcount;
+
+ void *mutex;
+
+ void *dispatch_mutex;
+ void *dispatch_cond;
+ void *io_path_mutex;
+ void *io_path_cond;
+
+ struct DBusList *outgoing_messages;
+ struct DBusList *incoming_messages;
+ struct DBusList *expired_messages;
+
+ struct DBusMessage *message_borrowed;
+
+ int n_outgoing;
+ int n_incoming;
+};
+
+struct data_t {
+ int pid;
+ char comm[TASK_COMM_LEN];
+ u32 ts;
+};
+
+struct header_data {
+ char flag;
+ char type;
+ char bitewise;
+ char protocol;
+ u32 len;
+ u32 serial;
+};
+
+struct stats_t {
+ int min;
+ u32 avg;
+ int count;
+ int max;
+};
+
+BPF_HASH(msg_sent_addr, u32 , struct data_t)
+BPF_HASH(msg_latency, struct data_t , struct stats_t)
+BPF_HASH(g_serial_addr, struct data_t, struct GDBusMessage *)
+BPF_HISTOGRAM(latency_histo)
+
+static void get_process_data(struct data_t *data) {
+ data->pid = bpf_get_current_pid_tgid();
+ bpf_get_current_comm(&data->comm, sizeof(data->comm));
+ data->ts = bpf_ktime_get_ns() / 1000;
+}
+
+static int get_delay(int serial, struct data_t receiver_data) {
+ int delta;
+ struct stats_t *stat;
+ struct data_t *sender_data = msg_sent_addr.lookup(&serial);
+ if (sender_data != 0 && sender_data->pid != receiver_data.pid) {
+ msg_sent_addr.delete(&serial);
+ delta = receiver_data.ts - sender_data->ts;
+ if (delta > 5000 || delta <= 0) {
+ return 0;
+ }
+ latency_histo.increment(bpf_log2l(delta));
+ receiver_data.pid = sender_data->pid;
+ receiver_data.ts = 0;
+ bpf_probe_read(&receiver_data.comm, sizeof(receiver_data.comm), sender_data->comm);
+ stat = msg_latency.lookup(&receiver_data);
+ if (stat == 0) {
+ struct stats_t stats = {delta, delta, 1, delta};
+ msg_latency.insert(&receiver_data, &stats);
+ return 0;
+ }
+ struct stats_t stats = {stat->min, stat->avg, stat->count, stat->max};
+ if (stats.min > delta) {
+ stats.min = delta;
+ }
+ else if (stats.max < delta) {
+ stats.max = delta;
+ }
+ u32 avg = stats.avg;
+ if (stats.count > 1000) {
+ avg *= 1000;
+ }
+ else {
+ avg *= stats.count;
+ stats.count++;
+ }
+ avg += delta;
+ stats.avg = (avg / stats.count);
+ msg_latency.update(&receiver_data, &stats);
+ }
+ return 0;
+}
+
+int get_msg_addr(struct pt_regs *ctx, struct DBusConnection *conn, struct DBusMessage *msg){
+ struct data_t data = {};
+ get_process_data(&data);
+ struct header_data *header = msg->header.data.str;
+ u32 serial = header->serial;
+ msg_sent_addr.update(&serial,&data);
+ return 0;
+}
+
+int get_msg_latency(struct pt_regs *ctx, struct DBusConnection *conn) {
+ struct data_t receiver_data = {};
+ struct DBusMessage *msg;
+ struct header_data *header;
+ int serial;
+ struct DBusList *link = conn->incoming_messages;
+
+ if (link == 0) {
+ return 0;
+ }
+
+ get_process_data(&receiver_data);
+ msg = conn->incoming_messages->data;
+ header = msg->header.data.str;
+ serial = header->serial;
+ get_delay(serial, receiver_data);
+ return 0;
+}
+
+int g_get_latency(struct pt_regs *ctx, struct GDBusMessage *msg) {
+ struct data_t *receiver_data;
+ u32 serial = msg->serial;
+ receiver_data = msg_sent_addr.lookup(&serial);
+ struct data_t data = {};
+ get_process_data(&data);
+ data.ts = 0;
+ if ((receiver_data == 0) || (receiver_data->pid == data.pid)){
+ msg_sent_addr.delete(&serial);
+ get_delay(serial, data);
+ return 0;
+ }
+ msg_sent_addr.update(&serial, &data);
+ bpf_trace_printk("sender: %d\n", serial);
+ return 0;
+}
--- /dev/null
+#!/usr/bin/python
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int, c_ulonglong
+from sys import argv
+
+def usage():
+ print("USAGE: %s [--process|histogram]" % argv[0])
+ exit()
+
+print("Hit Ctrl-C to end.")
+count = 100
+interval = 5
+loop = 0
+
+mode = "histogram"
+if len(argv) != 2:
+ usage()
+if argv[1] == "--histogram":
+ mode = "histogram"
+elif argv[1] == "--process":
+ mode = "process"
+else:
+ usage()
+
+b = BPF(src_file="dbus-latency.c")
+
+b.attach_uprobe(name="dbus-1", sym="_dbus_connection_message_sent_unlocked", fn_name="get_msg_addr")
+b.attach_uprobe(name="dbus-1", sym="dbus_connection_dispatch", fn_name="get_msg_latency")
+b.attach_uprobe(name="gio-2.0", sym="g_dbus_message_lock", fn_name="g_get_latency")
+
+
+while (1):
+ sleep(interval)
+ loop = loop + 1
+ print("\n%d:" % loop)
+ if mode =="histogram":
+ b["latency_histo"].print_log2_hist("ms")
+ else:
+ print ("%10s %20s %10s %10s %10s" % ("PID", "COMM", "MIN", "AVG", "MAX"))
+ latency = b["msg_latency"]
+ for v, p in sorted(latency.items(), key=lambda latency: latency[1].avg, reverse=True):
+ print("%10d %20s %10d %10d %10d" % (v.pid, v.comm.encode('string-escape'), int(p.min), int(p.avg), int(p.max)))
+
--- /dev/null
+#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+#define COUNTS COUNTS_T
+
+struct data_t {
+ int pid;
+ char comm[TASK_COMM_LEN];
+};
+
+struct bytes_t {
+ u32 bytes;
+};
+
+BPF_HASH(size_sent, struct data_t, struct bytes_t)
+
+BPF_HISTOGRAM(sizes);
+
+int do_write_exit(struct pt_regs *ctx) {
+ struct data_t data = {};
+ data.pid = bpf_get_current_pid_tgid();
+ bpf_get_current_comm(&data.comm, sizeof(data.comm));
+ struct bytes_t *bytes;
+ bytes = size_sent.lookup(&data);
+ if (bytes != 0 & bytes->bytes > 0) {
+ sizes.increment(bpf_log2l(bytes->bytes));
+ }
+ size_sent.delete(&data);
+ return 0;
+}
+
+int do_return(struct pt_regs *ctx){
+ struct bytes_t size = {};
+ size.bytes = PT_REGS_RC(ctx);
+ struct bytes_t zero = {0}, *val;
+ if (size.bytes > 0) {
+ struct data_t data = {};
+ bpf_get_current_comm(&data.comm, sizeof(data.comm));
+ data.pid = bpf_get_current_pid_tgid();
+ val = size_sent.lookup_or_init(&data, &zero);
+ size.bytes += val->bytes;
+ size_sent.update(&data, &size);
+ }
+ return 0;
+}
--- /dev/null
+#works only on sockets
+#!/usr/bin/python
+
+#old version
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int, c_ulonglong
+from sys import argv
+
+
+def usage():
+ print("USAGE: %s [--histogram]" % argv[0])
+ exit()
+
+mode = 0
+
+if len(argv) > 2:
+ usage()
+ exit(1)
+if len(argv) == 2:
+ if argv[1] == "--histogram":
+ mode = 1
+ else:
+ usage()
+
+print("Hit Ctrl-C to end.")
+count = 100
+interval = 5
+loop = 0
+
+# load BPF program
+
+b = BPF(src_file="dbus-message-size.c")
+if mode == 1:
+ b.attach_uretprobe(name="dbus-1", sym="do_writing", fn_name="do_write_exit")
+ b.attach_uretprobe(name="dbus-1", sym="do_authentication", fn_name="do_write_exit")
+b.attach_uretprobe(name="dbus-1", sym="_dbus_write_socket_with_unix_fds_two", fn_name="do_return")
+b.attach_uretprobe(name="dbus-1", sym="_dbus_write_socket_two", fn_name="do_return")
+b.attach_uretprobe(name="dbus-1", sym="_dbus_write_socket", fn_name="do_return")
+
+while (1):
+ if count > 0:
+ loop += 1
+ if loop > count:
+ exit()
+ sleep(interval)
+ print ("%d : \n" % loop)
+ stats_t = b["size_sent"]
+ if mode == 0:
+ print ("%10s %20s %20s" % ("PID", "NAME", "BYTES SENT"))
+ for v, p in sorted(stats_t.items(), key=lambda stats_t: stats_t[1].bytes, reverse=True):
+ print("%10d %20s %20d \n" % (v.pid, v.comm.encode('string-escape'), p.bytes))
+ b["sizes"].print_log2_hist("bytes");
--- /dev/null
+#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+#define DBUS_TYPE_OFFSET 1
+
+typedef enum {
+ G_DBUS_MESSAGE_TYPE_INVALID,
+ G_DBUS_MESSAGE_TYPE_METHOD_CALL,
+ G_DBUS_MESSAGE_TYPE_METHOD_RETURN,
+ G_DBUS_MESSAGE_TYPE_ERROR,
+ G_DBUS_MESSAGE_TYPE_SIGNAL
+} GDBusMessageType;
+
+typedef enum {
+ G_DBUS_MESSAGE_FLAGS_NONE = 0,
+ G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED = (1<<0),
+ G_DBUS_MESSAGE_FLAGS_NO_AUTO_START = (1<<1)
+} GDBusMessageFlags;
+
+typedef enum
+{
+ G_DBUS_MESSAGE_BYTE_ORDER_BIG_ENDIAN = 'B',
+ G_DBUS_MESSAGE_BYTE_ORDER_LITTLE_ENDIAN = 'l'
+} GDBusMessageByteOrder;
+
+struct GTypeInstance {
+ void *g_class;
+};
+
+struct GObject {
+ struct GTypeInstance g_type_instance;
+
+ volatile unsigned int ref_count;
+ void *qdata;
+};
+
+struct GHashTable {
+ int size;
+ int mod;
+ unsigned int mask;
+ int nnodes;
+ int noccupied;
+
+ void *keys;
+ void *hashes;
+ void *values;
+};
+
+struct GVariant {
+ void *type_info;
+ unsigned long size;
+
+ union {
+ struct {
+ void *bytes;
+ const char *gconstpointer;
+ } serialised;
+
+ struct {
+ struct GVariant **children;
+ unsigned long n_children;
+ } tree;
+ } content;
+
+ int state;
+ int ref_count;
+};
+
+struct GDBusMessage {
+ struct GObject parent_instance;
+ GDBusMessageType type;
+ GDBusMessageFlags flags;
+ bool locked;
+ GDBusMessageByteOrder byte_order;
+ unsigned char major_protocol_version;
+ unsigned int serial;
+ struct GHashTable *headers;
+ struct GVariant *body;
+};
+
+struct DBusString {
+ void *str;
+ int len;
+ unsigned int allocated;
+ unsigned int constant : 1;
+ unsigned int locked : 1;
+ unsigned int invalid : 1;
+ unsigned int align_offset : 3;
+};
+
+struct DBusHeaderFields {
+ int value_pos;
+};
+
+struct DBusHeader {
+ struct DBusString data;
+
+ struct DBusHeaderFields fields[9];
+
+ u32 padding;
+ u32 byte_order;
+ unsigned char protocol_version;
+};
+
+struct DBusMessage {
+ int refcount;
+ struct DBusHeader header;
+ struct DBusString body;
+
+ unsigned int locked : 1;
+
+ void * list;
+ long size_counter_delta;
+ int timeout_ms;
+
+ u32 changed_stamp : 21;
+ void *slot_list;
+
+ int generation;
+
+ int *unix_fds;
+
+ unsigned n_unix_fds;
+ unsigned n_unix_fds_allocated;
+
+ long unix_fd_counter_delta;
+
+ struct DBusString *signature;
+ struct DBusString *unique_sender;
+ size_t gvariant_body_last_offset;
+ size_t gvariant_body_last_pos;
+};
+
+struct data_t {
+ u32 pid;
+ char comm[TASK_COMM_LEN];
+};
+
+BPF_HASH(message, struct data_t, int)
+BPF_HISTOGRAM(msg_type, int)
+
+int g_get_message_type(struct pt_regs *ctx, void *conn, struct GDBusMessage *message) {
+ msg_type.increment(message->type);
+ return 0;
+}
+
+int dbus_get_message_type(struct pt_regs *ctx, void *conn, struct DBusMessage *message) {
+ bpf_trace_printk("dbus: %d\n", PT_REGS_RC(ctx));
+ return 0;
+}
+
+int message_type(struct pt_regs *ctx, void *conn, struct DBusMessage *message) {
+ const char *c = message->header.data.str;
+ c++;
+ msg_type.increment(*c);
+ return 0;
+}
--- /dev/null
+#!/usr/bin/python
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int, c_ulonglong
+from sys import argv
+
+b = BPF(src_file="dbus-message-type.c")
+
+b.attach_uprobe(name="gio-2.0", sym="g_dbus_connection_send_message", fn_name="g_get_message_type")
+#b.attach_uretprobe(name="dbus-1", sym="_dbus_header_get_message_type", fn_name="dbus_get_message_type")
+b.attach_uprobe(name="dbus-1", sym="_dbus_connection_message_sent_unlocked", fn_name="message_type")
+
+#b.trace_print()
+count = 0
+while(1):
+ count += 1
+ sleep(5)
+ print("%d:" % count)
+ print("%20s %20s" % ("MESSAGE_TYPE", "NUMBER\n"))
+ print("%20s %20d" % ("INVALID", b["msg_type"][0].value))
+ print("%20s %20d" % ("METHOD_CALL", b["msg_type"][1].value))
+ print("%20s %20d" % ("METHOD_RETURN", b["msg_type"][2].value))
+ print("%20s %20d" % ("ERROR", b["msg_type"][3].value))
+ print("%20s %20d" % ("SIGNAL", b["msg_type"][4].value))
--- /dev/null
+#!/usr/bin/python
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int, c_ulonglong
+from sys import argv
+
+
+print("Hit Ctrl-C to end.")
+count = 100
+interval = 5
+loop = 0
+# load BPF program
+bpf_text="""#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+struct p_name{
+ char buf[80];
+ u32 pid;
+};
+
+BPF_HASH(counter, struct p_name);
+BPF_HASH(licznik);
+
+int sending_message(struct pt_regs *ctx, void *ptri, void *message){
+ struct p_name process = {' ', 0};
+ u64 zero = 0;
+ u32 ret = PT_REGS_RC(ctx);
+ process.pid = bpf_get_current_pid_tgid();
+ bpf_get_current_comm(&(process.buf), sizeof(process.buf));
+ counter.increment(process);
+ return 0;
+}
+
+"""
+bpf_text = bpf_text.replace('INTERVAL', '%d' % interval)
+b = BPF(text=bpf_text)
+
+b.attach_uprobe(name="dbus-1", sym="dbus_connection_send", fn_name="sending_message")
+b.attach_uprobe(name="dbus-1", sym="dbus_connection_send_preallocated", fn_name="sending_message")
+b.attach_uprobe(name="dbus-1", sym="dbus_connection_send_with_reply", fn_name="sending_message")
+b.attach_uprobe(name="dbus-1", sym="dbus_connection_send_with_reply_and_block", fn_name="sending_message")
+
+
+while (1):
+ if count > 0:
+ loop += 1
+ if loop > count:
+ exit()
+ sleep(interval)
+ print ("%d:" % loop)
+ stats = b["counter"]
+ print("%10s %20s %20s" % ("PID", "NAME", "MESSAGES SENT"))
+ for k, v in stats.items():
+ print("%10d %20s %20d\n" % (k.pid, k.buf.encode('string-escape'), v.value ))
--- /dev/null
+#include <uapi/linux/ptrace.h>
+#include <linux/sched.h>
+
+typedef struct pdata_T {
+ u32 pid;
+ char buf[TASK_COMM_LEN];
+ u64 run;
+ u64 wait;
+ u64 usage;
+}pdata_t;
+
+BPF_HASH(timestamp_b, u64);
+BPF_HASH(timestamp_e, u64);
+BPF_HASH(stats, u32, pdata_t, sizeof(pdata_t));
+BPF_HASH(run_start, u32);
+BPF_HASH(wait_start, u32);
+
+
+#define TAKE_PROCESS_DATA u64 time = 0; pdata_t pdata;\
+ pdata_t new_pdata = {0, ' ', 0, 0, 0};\
+ u64 ts, *tsp, delta;\
+ u32 pid = bpf_get_current_pid_tgid();\
+ ts = bpf_ktime_get_ns() / 1000;\
+ new_pdata.pid = pid;\
+
+int do_entry(struct pt_regs *ctx) {
+ TAKE_PROCESS_DATA
+ timestamp_b.insert(&time, &ts);
+ timestamp_e.update(&time, &ts);
+ tsp = run_start.lookup(&pid);
+ run_start.delete(&pid);
+ wait_start.update(&pid, &ts);
+ if(tsp == 0) {
+ return 0;
+ }
+ delta = ts - *tsp;
+ pdata = *(stats.lookup_or_init(&pid, &new_pdata));
+ pdata.run += delta;
+ bpf_get_current_comm(&(pdata.buf), sizeof(pdata.buf));
+ stats.update(&pid, &pdata);
+ return 0;
+}
+
+int do_return(struct pt_regs *ctx) {
+ TAKE_PROCESS_DATA
+ timestamp_b.insert(&time, &ts);
+ timestamp_e.update(&time, &ts);
+ tsp = wait_start.lookup(&pid);
+ wait_start.delete(&pid);
+ run_start.update(&pid, &ts);
+ if(tsp == 0) {
+ return 0;
+ }
+ delta = ts - *tsp;
+ pdata = *(stats.lookup_or_init(&pid, &new_pdata));
+ pdata.wait += delta;
+ bpf_get_current_comm(&(pdata.buf), sizeof(pdata.buf));
+ stats.update(&pid, &pdata);
+ return 0;
+}
+
--- /dev/null
+#!/usr/bin/python
+
+from bcc import BPF
+from time import sleep
+from ctypes import c_ushort, c_int, c_ulonglong
+from sys import argv
+
+def usage():
+ print("[interval] [count]")
+ exit(0)
+
+print("Hit Ctrl-C to end.")
+count = 100
+interval = 5
+loop = 0
+# load BPF program
+b = BPF(src_file="dbus-tok.c")
+
+b.attach_uprobe(name="dbus-1", sym="_dbus_poll", fn_name="do_entry")
+
+b.attach_uretprobe(name="dbus-1", sym="_dbus_poll", fn_name="do_return")
+
+while (1):
+ if count > 0:
+
+ loop += 1
+ if loop > count:
+ exit()
+ sleep(interval)
+ print ("%d : \n" % loop)
+ stats_t = b["stats"]
+ timestamp = b["timestamp_e"]
+ timeframe = 0
+ for v in timestamp.values():
+ timeframe = v.value
+ timestamp = b["timestamp_b"]
+ for v in timestamp.values():
+ timeframe -= v.value
+ for v in stats_t.values():
+ v.usage = (v.run * 100 / timeframe)
+ for v in sorted(stats_t.values(), key=lambda stats_t: stats_t.run, reverse=True):
+ print("%10d %20s %10.6f" % (v.pid, v.buf.encode('string-escape'), float(v.run) / float(timeframe)))