/** * taskdump.stp * * Prints information about current task once per second * Extracts data from `task_struct` * * Tested on CentOS 7.0 */ /** * Structures `dentry` and `vfsmnt` were separate in older kernels. * Newer kernels feature unified `path` structures that contain them both. * * SystemTap doesn't cache full path, so we have to use function task_dentry_path(), * to get entire path in this manner: * dentry = @cast(file, "file")->f_path->dentry; * vfsmnt = @cast(file, "file")->f_path->mnt; * return task_dentry_path(task, dentry, vfsmnt); * * Unfortunately, SystemTap has bug 16991, fixed in 2.6, so * we limit output to a basename */ function file_path:string(task:long, file:long) { if(@defined(@cast(file, "file")->f_vfsmnt)) return d_name(@cast(file, "file")->f_dentry); return d_name(@cast(file, "file")->f_path->dentry); } function task_root_path:string(task:long, fs_ptr:long) { if(@defined(@cast(fs_ptr, "fs_struct")->rootmnt)) return d_name(@cast(fs_ptr, "fs_struct")->root); return d_name(@cast(fs_ptr, "fs_struct")->root->dentry); } function task_pwd_path:string(task:long, fs_ptr:long) { if(@defined(@cast(fs_ptr, "fs_struct")->pwdmnt)) return d_name(@cast(fs_ptr, "fs_struct")->pwd); return d_name(@cast(fs_ptr, "fs_struct")->pwd->dentry); } /** * Prints exectuable file name from `mm->exe_file` */ function task_exefile(task:long, mm_ptr:long) { if(mm_ptr) { printf("\texe: %s\n", file_path(task, @cast(mm_ptr, "mm_struct")->exe_file)); } } /** * Prints root and current dir of a task */ function task_paths(task:long, fs_ptr:long) { if(fs_ptr) { printf("\troot: %s\n", task_root_path(task, fs_ptr)); printf("\tcwd: %s\n", task_pwd_path(task, fs_ptr)); } } /** * Prints arguments vector. Arguments are copied into process memory (stack) * and located in memory area (mm->arg_start; mm_arg_end), of the strings that * separated with NULL-terminators, i.e.: * +-----+----+-------------+----+ * | cat | \0 | /etc/passwd | \0 | * +-----+----+-------------+----+ * ^ ^ * arg_start arg_end * * WARNING: This is only a demostration functions, use cmdline_*() functions * instead * * NOTE: functions user_string* read from current address space * To get arguments from other processes, use Embedded C and * function that look like proc_pid_cmdline */ function task_args(mm_ptr:long) { if(mm_ptr) { arg_start = @cast(mm_ptr, "mm_struct")->arg_start; arg_end = @cast(mm_ptr, "mm_struct")->arg_end; if (arg_start != 0 && arg_end != 0) { len = arg_end - arg_start; nr = 0; /* Pick first argument */ arg = user_string2(arg_start, ""); while (len > 0) { printf("\targ%d: %s\n", nr, arg); arg_len = strlen(arg); arg_start += arg_len + 1; len -= arg_len + 1; nr++; arg = user_string2(arg_start, ""); } } } } /** * Returns file descriptor using fd * NOTE: see pfiles.stp */ function task_fd_filp:long(files:long, fd:long) { return @cast(files, "files_struct")->fdt->fd[fd]; } function task_fds(task:long) { task_files = @cast(task, "task_struct", "kernel")->files; if(task_files) { max_fds = task_max_file_handles(task); for (fd = 0; fd < max_fds; fd++) { filp = task_fd_filp(task_files, fd); if(filp) { printf("\tfile%d: %s\n", fd, file_path(task, filp)); } } } } /** * Prints start time of a process in seconds * start time - monotonic * real start time - boot time based * * NOTE: This function assumes that `timespec` is used, but these * variables were replaced with u64 in kernel 3.17 */ function task_start_time_x(task:long) { if(@defined(@cast(task, "task_struct", "kernel") ->start_time)) { start_time_sec = @cast(task, "task_struct", "kernel") ->start_time->tv_sec; real_time_sec = @cast(task, "task_struct", "kernel") ->real_time->tv_sec; printf("\tstart time: %ds\t real start time: %ds\n", start_time_sec, real_time_sec); } else { real_time_sec = @cast(task, "task_struct", "kernel") ->real_start_time->tv_sec; printf("\treal start time: %ds\n", real_time_sec); } } /** * Prints scheduler stats */ function task_time_stats(task:long) { user = @cast(task, "task_struct", "kernel")->utime; kernel = @cast(task, "task_struct", "kernel")->stime; printf("\tuser: %s\t kernel: %s\n", cputime_to_string(user), cputime_to_string(kernel)); } function dump_task(task:long) { task_mm = @cast(task, "task_struct", "kernel")->mm; task_fs = @cast(task, "task_struct", "kernel")->fs; printf("Task %p is %d@%d %s\n", task, task_pid(task), task_cpu(task), task_execname(task)); task_exefile(task, task_mm); task_paths(task, task_fs); task_args(task_mm); task_fds(task); task_start_time_x(task); task_time_stats(task); } probe timer.s(1) { dump_task(task_current()); }