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

perf trace: Remove arg_fmt->is_enum, we can get that from the BTF type

This is to pave the way for other BTF types, i.e. we try to find BTF
type then use things like btf_is_enum(btf_type) that we cached to find
the right strtoul and scnprintf routines.

For now only enum is supported, all the other types simple return zero
for scnprintf which makes it have the same behaviour as when BTF isn't
available, i.e. fallback to no pretty printing. Ditto for strtoul.

root@x1:~# perf test -v enum
124: perf trace enum augmentation tests : Ok
root@x1:~# perf test -v enum
124: perf trace enum augmentation tests : Ok
root@x1:~# perf test -v enum
124: perf trace enum augmentation tests : Ok
root@x1:~# perf test -v enum
124: perf trace enum augmentation tests : Ok
root@x1:~# perf test -v enum
124: perf trace enum augmentation tests : Ok
root@x1:~#

Signed-off-by: Howard Chu <howardchu95@gmail.com>
Tested-by: Howard Chu <howardchu95@gmail.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Howard Chu <howardchu95@gmail.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/20240624181345.124764-9-howardchu95@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

+58 -48
+57 -48
tools/perf/builtin-trace.c
··· 111 111 const char *name; 112 112 u16 nr_entries; // for arrays 113 113 bool show_zero; 114 - bool is_enum; 115 114 #ifdef HAVE_LIBBPF_SUPPORT 116 115 const struct btf_type *type; 117 116 #endif ··· 909 910 #define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags 910 911 911 912 #ifdef HAVE_LIBBPF_SUPPORT 912 - static int syscall_arg_fmt__cache_btf_enum(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type) 913 + static void syscall_arg_fmt__cache_btf_enum(struct syscall_arg_fmt *arg_fmt, struct btf *btf, char *type) 913 914 { 914 915 int id; 915 916 916 - // Already cached? 917 - if (arg_fmt->type != NULL) 918 - return 0; 919 - 920 917 type = strstr(type, "enum "); 921 918 if (type == NULL) 922 - return -1; 919 + return; 923 920 924 921 type += 5; // skip "enum " to get the enumeration name 925 922 926 923 id = btf__find_by_name(btf, type); 927 924 if (id < 0) 928 - return -1; 925 + return; 929 926 930 927 arg_fmt->type = btf__type_by_id(btf, id); 931 - return arg_fmt->type == NULL ? -1 : 0; 932 928 } 933 929 934 930 static bool syscall_arg__strtoul_btf_enum(char *bf, size_t size, struct syscall_arg *arg, u64 *val) 935 931 { 936 - const struct btf_type *bt; 937 - char *type = arg->parm; 938 - struct btf_enum *be; 939 - struct btf *btf; 932 + const struct btf_type *bt = arg->fmt->type; 933 + struct btf *btf = arg->trace->btf; 934 + struct btf_enum *be = btf_enum(bt); 940 935 941 - trace__load_vmlinux_btf(arg->trace); 942 - 943 - btf = arg->trace->btf; 944 - if (btf == NULL) 945 - return false; 946 - 947 - if (syscall_arg_fmt__cache_btf_enum(arg->fmt, btf, type) < 0) 948 - return false; 949 - 950 - bt = arg->fmt->type; 951 - be = btf_enum(bt); 952 936 for (int i = 0; i < btf_vlen(bt); ++i, ++be) { 953 937 const char *name = btf__name_by_offset(btf, be->name_off); 954 938 int max_len = max(size, strlen(name)); ··· 941 959 return true; 942 960 } 943 961 } 962 + 963 + return false; 964 + } 965 + 966 + static bool syscall_arg__strtoul_btf_type(char *bf, size_t size, struct syscall_arg *arg, u64 *val) 967 + { 968 + const struct btf_type *bt; 969 + char *type = arg->type_name; 970 + struct btf *btf; 971 + 972 + trace__load_vmlinux_btf(arg->trace); 973 + 974 + btf = arg->trace->btf; 975 + if (btf == NULL) 976 + return false; 977 + 978 + if (arg->fmt->type == NULL) { 979 + // See if this is an enum 980 + syscall_arg_fmt__cache_btf_enum(arg->fmt, btf, type); 981 + } 982 + 983 + // Now let's see if we have a BTF type resolved 984 + bt = arg->fmt->type; 985 + if (bt == NULL) 986 + return false; 987 + 988 + // If it is an enum: 989 + if (btf_is_enum(arg->fmt->type)) 990 + return syscall_arg__strtoul_btf_enum(bf, size, arg, val); 944 991 945 992 return false; 946 993 } ··· 989 978 return 0; 990 979 } 991 980 992 - static size_t trace__btf_enum_scnprintf(struct trace *trace, struct syscall_arg_fmt *arg_fmt, char *bf, 993 - size_t size, int val, char *type) 994 - { 995 - if (syscall_arg_fmt__cache_btf_enum(arg_fmt, trace->btf, type) < 0) 996 - return 0; 997 - 998 - return btf_enum_scnprintf(arg_fmt->type, trace->btf, bf, size, val); 999 - } 1000 - 1001 981 static size_t trace__btf_scnprintf(struct trace *trace, struct syscall_arg_fmt *arg_fmt, char *bf, 1002 982 size_t size, int val, char *type) 1003 983 { 1004 984 if (trace->btf == NULL) 1005 985 return 0; 1006 986 1007 - if (arg_fmt->is_enum) 1008 - return trace__btf_enum_scnprintf(trace, arg_fmt, bf, size, val, type); 987 + if (arg_fmt->type == NULL) { 988 + // Check if this is an enum and if we have the BTF type for it. 989 + syscall_arg_fmt__cache_btf_enum(arg_fmt, trace->btf, type); 990 + } 991 + 992 + // Did we manage to find a BTF type for the syscall/tracepoint argument? 993 + if (arg_fmt->type == NULL) 994 + return 0; 995 + 996 + if (btf_is_enum(arg_fmt->type)) 997 + return btf_enum_scnprintf(arg_fmt->type, trace->btf, bf, size, val); 1009 998 1010 999 return 0; 1011 1000 } ··· 1018 1007 return 0; 1019 1008 } 1020 1009 1021 - static bool syscall_arg__strtoul_btf_enum(char *bf __maybe_unused, size_t size __maybe_unused, 1010 + static bool syscall_arg__strtoul_btf_type(char *bf __maybe_unused, size_t size __maybe_unused, 1022 1011 struct syscall_arg *arg __maybe_unused, u64 *val __maybe_unused) 1023 1012 { 1024 1013 return false; 1025 1014 } 1026 1015 #endif // HAVE_LIBBPF_SUPPORT 1027 1016 1028 - #define STUL_BTF_ENUM syscall_arg__strtoul_btf_enum 1017 + #define STUL_BTF_TYPE syscall_arg__strtoul_btf_type 1029 1018 1030 1019 #define STRARRAY(name, array) \ 1031 1020 { .scnprintf = SCA_STRARRAY, \ ··· 1898 1887 continue; 1899 1888 1900 1889 len = strlen(field->name); 1901 - arg->is_enum = false; 1902 1890 1903 1891 if (strcmp(field->type, "const char *") == 0 && 1904 1892 ((len >= 4 && strcmp(field->name + len - 4, "name") == 0) || ··· 1925 1915 */ 1926 1916 arg->scnprintf = SCA_FD; 1927 1917 } else if (strstr(field->type, "enum") && use_btf != NULL) { 1928 - *use_btf = arg->is_enum = true; 1929 - arg->strtoul = STUL_BTF_ENUM; 1918 + *use_btf = true; 1919 + arg->strtoul = STUL_BTF_TYPE; 1930 1920 } else { 1931 1921 const struct syscall_arg_fmt *fmt = 1932 1922 syscall_arg_fmt__find_by_name(field->name); ··· 2246 2236 /* 2247 2237 * Suppress this argument if its value is zero and show_zero 2248 2238 * property isn't set. 2239 + * 2240 + * If it has a BTF type, then override the zero suppression knob 2241 + * as the common case is for zero in an enum to have an associated entry. 2249 2242 */ 2250 2243 if (val == 0 && !trace->show_zeros && 2251 2244 !(sc->arg_fmt && sc->arg_fmt[arg.idx].show_zero) && 2252 - !(sc->arg_fmt && sc->arg_fmt[arg.idx].is_enum)) 2245 + !(sc->arg_fmt && sc->arg_fmt[arg.idx].strtoul == STUL_BTF_TYPE)) 2253 2246 continue; 2254 2247 2255 2248 printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); ··· 2955 2942 val = syscall_arg_fmt__mask_val(arg, &syscall_arg, val); 2956 2943 2957 2944 /* Suppress this argument if its value is zero and show_zero property isn't set. */ 2958 - if (val == 0 && !trace->show_zeros && !arg->show_zero && !arg->is_enum) 2945 + if (val == 0 && !trace->show_zeros && !arg->show_zero && arg->strtoul != STUL_BTF_TYPE) 2959 2946 continue; 2960 2947 2961 2948 printed += scnprintf(bf + printed, size - printed, "%s", printed ? ", " : ""); ··· 3923 3910 struct syscall_arg syscall_arg = { 3924 3911 .trace = trace, 3925 3912 .fmt = fmt, 3913 + .type_name = type, 3914 + .parm = fmt->parm, 3926 3915 }; 3927 - 3928 - if (fmt->is_enum) { 3929 - syscall_arg.parm = type; 3930 - } else { 3931 - syscall_arg.parm = fmt->parm; 3932 - } 3933 3916 3934 3917 if (fmt->strtoul(right, right_size, &syscall_arg, &val)) { 3935 3918 char *n, expansion[19];
+1
tools/perf/trace/beauty/beauty.h
··· 113 113 struct thread *thread; 114 114 struct trace *trace; 115 115 void *parm; 116 + char *type_name; 116 117 u16 len; 117 118 u8 idx; 118 119 u8 mask;