From: Steven Rostedt Date: Wed, 23 Jul 2025 16:42:02 +0000 (-0400) Subject: tracing: Have eprobes handle arrays X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dabd3e7dcc5881d5d3d6dc60c6f14780fee9a9bd;p=thirdparty%2Fkernel%2Fstable.git tracing: Have eprobes handle arrays eprobes are dynamic events that can read other events using their fields to create new events. Currently it doesn't work with arrays. When the new event field is attached to the old event field, it looks at the size of the field to determine what type of field the new field should be. For 1 byte fields it's a char, for 2 bytes, it's a short and for 4 bytes it's an integer. For all other sizes it just defaults to "long". This also reads the contents of the field for such cases. For arrays that are bigger than the size of long, return the value of the address of the content itself. This will allow eprobes to read other values in the array of the old event. This is useful when raw_syscalls is enabled but the syscall events are not. The syscall events are created from the raw_syscalls as they have an array of "args" that holds the 6 long words passed to the syscall entry point. To read the value of "filename" from sys_openat, the eprobe could attach to the raw_syscall and read the second value. It can then even be passed to a synthetic event and converted back to another eprobe to get the value of "filename" after it has been read by the kernel during the system call: [ Create an eprobe called "sys" and attach it to sys_enter. Read the id of the system call and the second argument ] # echo 'e:sys raw_syscalls.sys_enter nr=$id:u32 arg2=+8($args):u64' >> /sys/kernel/tracing/dynamic_events [ Create a synthetic event "path" that will hold the address of the sys_openat filename. This is on a 64bit machine, so make it 64 bits ] # echo 's:path u64 file;' >> /sys/kernel/tracing/dynamic_events [ Add a histogram to the eprobe/sys which tiggers if the "nr" field is 257 (sys_openat), and save the filename in the "file" variable. ] # echo 'hist:keys=common_pid:file=arg2 if nr == 257' > /sys/kernel/tracing/events/eprobes/sys/trigger [ Attach a histogram to sys_exit event that triggers the "path" synthetic event and records the "filename" that was passed from the sys eprobe. ] # echo 'hist:keys=common_pid:f=$file:onmatch(eprobes.sys).trace(path,$f)' >> /sys/kernel/tracing/events/raw_syscalls/sys_exit/trigger [ Create another eprobe that dereferences the "file" field as a user space string and displays it. ] # echo 'e:open synthetic.path file=+0($file):ustring' >> /sys/kernel/tracing/dynamic_events # echo 1 > /sys/kernel/tracing/events/eprobes/open/enable # cat trace_pipe cat-1142 [003] ...5. 799.521912: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.521934: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.522065: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.522080: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.522296: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" cat-1142 [003] ...5. 799.522319: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" less-1143 [005] ...5. 799.522327: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.522333: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" cat-1142 [003] ...5. 799.522348: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" less-1143 [005] ...5. 799.522349: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.522363: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" less-1143 [005] ...5. 799.522477: open: (synthetic.path) file="/etc/ld.so.cache" cat-1142 [003] ...5. 799.522489: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" less-1143 [005] ...5. 799.522492: open: (synthetic.path) file="/etc/ld.so.cache" less-1143 [005] ...5. 799.522720: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libtinfo.so.6" less-1143 [005] ...5. 799.522744: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libtinfo.so.6" less-1143 [005] ...5. 799.522759: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libtinfo.so.6" cat-1142 [003] ...5. 799.522850: open: (synthetic.path) file="/lib/x86_64-linux-gnu/libc.so.6" Link: https://lore.kernel.org/all/20250723124202.4f7475be@batman.local.home/ Signed-off-by: Steven Rostedt (Google) Signed-off-by: Masami Hiramatsu (Google) --- diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c index f16a0ab0b001..a1d402124836 100644 --- a/kernel/trace/trace_eprobe.c +++ b/kernel/trace/trace_eprobe.c @@ -344,10 +344,15 @@ get_event_field(struct fetch_insn *code, void *rec) val = *(unsigned int *)addr; break; default: - if (field->is_signed) - val = *(long *)addr; - else - val = *(unsigned long *)addr; + if (field->size == sizeof(long)) { + if (field->is_signed) + val = *(long *)addr; + else + val = *(unsigned long *)addr; + break; + } + /* This is an array, point to the addr itself */ + val = (unsigned long)addr; break; } return val;