SystemTap tracks the typing information of the target variable and can examine the fields of a structure with the ->
operator. The ->
operator can be chained to look at data structures contained within data structures and follow pointers to other data structures. The ->
operator will obtain the value in the field of the structure. The ->
operator is used regardless whether accessing a field in a substructure or accessing another structure through a pointer.
3.3.2.1. Pretty Printing Target Variables
SystemTap scripts are often used to observe what is happening within the code. In many cases just printing the values of the various context variables is sufficient. SystemTap makes a number operations available that can generate printable strings for target variables:
- $$vars
Expands to a character string that is equivalent to sprintf("parm1=%x ... parmN=%x var1=%x ... varN=%x", parm1, ..., parmN, var1, ..., varN)
for each variable in scope at the probe point. Some values may be printed as “=?
” if their run-time location cannot be found.
- $$locals
Expands to a subset of $$vars
containing only the local variables.
- $$parms
Expands to a subset of $$vars
containing only the function parameters.
- $$return
Is available in return probes only. It expands to a string that is equivalent to sprintf("return=%x", $return)
if the probed function has a return value, or else an empty string.
Below is a command-line script that prints the values of the parameters passed into the function vfs_read
:
stap -e 'probe kernel.function("vfs_read") {printf("%s\n", $$parms); exit(); }'
There are four parameters passed into vfs_read
: file
, buf
, count
, and pos
. The $$parms
generates a string for the parameters passed into the function. In this case all but the count
parameter are pointers. The following is an example of the output from the previous command-line script:
file=0xffff8800b40d4c80 buf=0x7fff634403e0 count=0x2004 pos=0xffff8800af96df48
Having the address a pointer points to may not be useful. You might be more interested in the fields of the data structure the pointer points to. You can use the the “$
” suffix to pretty print the data structure. The following command-line example uses the pretty printing suffix to print more details about the data structures passed into the function vfs_read
:
stap -e 'probe kernel.function("vfs_read") {printf("%s\n", $$parms$); exit(); }'
The previous command line will generate something similar to the following with the fields of the data structure included in the output:
file={.f_u={...}, .f_path={...}, .f_op=0xffffffffa06e1d80, .f_lock={...}, .f_count={...}, .f_flags=34818, .f_mode=31, .f_pos=0, .f_owner={...}, .f_cred=0xffff88013148fc80, .f_ra={...}, .f_version=0, .f_security=0xffff8800b8dce560, .private_data=0x0, .f_ep_links={...}, .f_mapping=0xffff880037f8fdf8} buf="" count=8196 pos=-131938753921208
With the “$
” suffix fields that are composed of data structures are not expanded. The “$$
” suffix will print the values contained within the nested data structures. Below is an example using the “$$
” suffix:
stap -e 'probe kernel.function("vfs_read") {printf("%s\n", $$parms$$); exit(); }'
The “$$
” suffix, like all strings, is limited to the maximum string size. Below is a represenative output from the previous command-line script, which is truncated because of the string size limit:
file={.f_u={.fu_list={.next=0xffff8801336ca0e8, .prev=0xffff88012ded0840}, .fu_rcuhead={.next=0xffff8801336ca0e8, .func=0xffff88012ded0840}}, .f_path={.mnt=0xffff880132fc97c0, .dentry=0xffff88001a889cc0}, .f_op=0xffffffffa06f64c0, .f_lock={.raw_lock={.slock=196611}}, .f_count={.counter=2}, .f_flags=34818, .f_mode=31, .f_pos=0, .f_owner={.lock={.raw_lock={.lock=16777216}}, .pid=0x0, .pid_type=0, .uid=0, .euid=0, .signum=0}, .f_cred=0xffff880130129a80, .f_ra={.start=0, .size=0, .async_size=0, .ra_pages=32, .