Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf trace: Pretty print buffer data

Define TRACE_AUG_MAX_BUF in trace_augment.h data, which is the maximum
buffer size we can augment. BPF will include this header too.

Print buffer in a way that's different than just printing a string, we
print all the control characters in \digits (such as \0 for null, and
\10 for newline, LF).

For character that has a bigger value than 127, we print the digits
instead of the character itself as well.

Committer notes:

Simplified the buffer scnprintf to avoid using multiple buffers as
discussed in the patch review thread.

We can't really all 'buf' args to SCA_BUF as we're collecting so far
just on the sys_enter path, so we would be printing the previous 'read'
arg buffer contents, not what the kernel puts there.

So instead of:
static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1987,8 +1989,6 @@ syscall_arg_fmt__init_array(struct syscall_arg_fmt *arg, struct tep_format_field
- else if (strstr(field->type, "char *") && strstr(field->name, "buf"))
- arg->scnprintf = SCA_BUF;

Do:

static const struct syscall_fmt syscall_fmts[] = {
+ { .name = "write", .errpid = true,
+ .arg = { [1] = { .scnprintf = SCA_BUF /* buf */, from_user = true, }, }, },

Signed-off-by: Howard Chu <howardchu95@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240815013626.935097-8-howardchu95@gmail.com
Link: https://lore.kernel.org/r/20240824163322.60796-6-howardchu95@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Howard Chu and committed by
Arnaldo Carvalho de Melo
b257fac1 cb320352

+39
+33
tools/perf/builtin-trace.c
··· 65 65 #include "syscalltbl.h" 66 66 #include "rb_resort.h" 67 67 #include "../perf.h" 68 + #include "trace_augment.h" 68 69 69 70 #include <errno.h> 70 71 #include <inttypes.h> ··· 865 864 { .scnprintf = SCA_FILENAME, \ 866 865 .from_user = true, } 867 866 867 + static size_t syscall_arg__scnprintf_buf(char *bf, size_t size, struct syscall_arg *arg); 868 + 869 + #define SCA_BUF syscall_arg__scnprintf_buf 870 + 868 871 static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, 869 872 struct syscall_arg *arg) 870 873 { ··· 1392 1387 .arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, }, 1393 1388 { .name = "waitid", .errpid = true, 1394 1389 .arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, }, 1390 + { .name = "write", .errpid = true, 1391 + .arg = { [1] = { .scnprintf = SCA_BUF /* buf */, .from_user = true, }, }, }, 1395 1392 }; 1396 1393 1397 1394 static int syscall_fmt__cmp(const void *name, const void *fmtp) ··· 1763 1756 1764 1757 thread__set_filename_pos(arg->thread, bf, ptr); 1765 1758 return 0; 1759 + } 1760 + 1761 + #define MAX_CONTROL_CHAR 31 1762 + #define MAX_ASCII 127 1763 + 1764 + static size_t syscall_arg__scnprintf_buf(char *bf, size_t size, struct syscall_arg *arg) 1765 + { 1766 + struct augmented_arg *augmented_arg = arg->augmented.args; 1767 + unsigned char *orig = (unsigned char *)augmented_arg->value; 1768 + size_t printed = 0; 1769 + int consumed; 1770 + 1771 + if (augmented_arg == NULL) 1772 + return 0; 1773 + 1774 + for (int j = 0; j < augmented_arg->size; ++j) { 1775 + bool control_char = orig[j] <= MAX_CONTROL_CHAR || orig[j] >= MAX_ASCII; 1776 + /* print control characters (0~31 and 127), and non-ascii characters in \(digits) */ 1777 + printed += scnprintf(bf + printed, size - printed, control_char ? "\\%d" : "%c", (int)orig[j]); 1778 + } 1779 + 1780 + consumed = sizeof(*augmented_arg) + augmented_arg->size; 1781 + arg->augmented.args = ((void *)arg->augmented.args) + consumed; 1782 + arg->augmented.size -= consumed; 1783 + 1784 + return printed; 1766 1785 } 1767 1786 1768 1787 static bool trace__filter_duration(struct trace *trace, double t)
+6
tools/perf/util/trace_augment.h
··· 1 + #ifndef TRACE_AUGMENT_H 2 + #define TRACE_AUGMENT_H 3 + 4 + #define TRACE_AUG_MAX_BUF 32 /* for buffer augmentation in perf trace */ 5 + 6 + #endif