Systemtap: learning notes
Before using stap, the kernel-debuginfo-$(uname -r), kernel-debuginfo-common-$(uname -m)-$(uname -r) and kernel-devel-$(uname -r) should be installed. (CentOS)
stap-prep is a shortcut, but in the end, the above 3 packages should present.
verbose manpage over stap: man stapprobes
Another doc of stap will be included as file of this blog.
Normal usage of stap file: (its format is loose)
#!/bin/stap global cntread, cntwrite, cntother probe kernel.function("vfs_read"), kernel.function("vfs_write"), kernel.function(@1) { if (probefunc() == "vfs_read") cntread++; else if (probefunc() == "vfs_write") cntwrite++; else cntother++; } probe timer.s(5){ exit(); } probe end { printf("Read: %d\nWrite: %d\nOther: %d\n", cntread, cntwrite, cntother); }
Run by: stap stap.stp -v/-vvv -- vfs_open (Note: vfs_open as first argument passed to stp script which replaces @1)
More usages can be viewed through installing systemtap-testsuite, normally sits at /usr/share/systemtap/testsuite/
And many predefined kernel probe functions can be found at /usr/share/systemtap/tapset/, functions/probes defined in these files can be used directly in user defined stp files. Learning stap first need to check these functions.
# These functions utilizes the available kernel probes listed in /sys/kernel/debug/tracing/available_events.
---Adding more info about writing self using stp files----
Quote from here:
#!/bin/stap -g // using embedded C code should be under guru-mode %{ #include <linux/in.h> #include <linux/ip.h> %} /* <-- top level */ function read_iphdr:long(skb:long) %{ /* pure */ struct iphdr *iph = ip_hdr((struct sk_buff *)STAP_ARG_skb); STAP_RETVALUE = (long)iph; %} /* <-- function body */ /* Determines whether an IP packet is TCP, based on the iphdr: */ function is_tcp_packet:long(iphdr) { protocol = @cast(iphdr, "iphdr")->protocol return (protocol == %{ IPPROTO_TCP %}) /* <-- expression */ } probe begin { printf("SystemTap start!\n"); } probe kernel.function("ip_local_deliver") { iph = read_iphdr(pointer_arg(1)); printf("tcp packet ? %s\n", is_tcp_packet(iph) ? "yes" : "no"); }
In the above example, we probe the kernel function ip_local_deliver which is on the way of resolving packet in layer 3(after accepting the packet as local destined packet). The function prototype is:
int ip_local_deliver(struct sk_buff *skb)
where skb is passed in as one packet (GRO-ed).
So when we probe this funcction, we refer to this skb by function pointer_arg(1). The definition of function pointer_arg is located at
./tapset/x86_64/registers.stp:240:
..... and this is to push probe while entering function(prelogue), if need to put probe while leaving function(epilogue), use kernel.function("..").return
------------
And stap has several different code pattern:
- PRE-PROCESSING: %(condition %? then [%: else ] %)
- embedded C code: %{ c codes %}
- normal codes: { stp codes }
- embedded C code as r-value: a=1+%{IPPROTO_TCP%} //Should #include <linux/in.h> first