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

perf tools: Make it possible to see perf's kernel and module memory mappings

Dump kmaps if using 'perf --debug kmaps' or verbose > 2 (e.g. -vvv) for
tools 'perf script' and 'perf report' if there is no browser.

Example:

$ perf --debug kmaps script 2>&1 >/dev/null | grep kvm.intel
build id event received for /lib/modules/6.7.2-local/kernel/arch/x86/kvm/kvm-intel.ko: 0691d75e10e72ebbbd45a44c59f6d00a5604badf [20]
Map: 0-3a3 4f5d8 [kvm_intel].modinfo
Map: 0-5240 5f280 [kvm_intel]__versions
Map: 0-30 64 [kvm_intel].note.Linux
Map: 0-14 644c0 [kvm_intel].orc_header
Map: 0-5297 43680 [kvm_intel].rodata
Map: 0-5bee 3b837 [kvm_intel].text.unlikely
Map: 0-7e0 41430 [kvm_intel].noinstr.text
Map: 0-2080 713c0 [kvm_intel].bss
Map: 0-26 705c8 [kvm_intel].data..read_mostly
Map: 0-5888 6a4c0 [kvm_intel].data
Map: 0-22 70220 [kvm_intel].data.once
Map: 0-40 705f0 [kvm_intel].data..percpu
Map: 0-1685 41d20 [kvm_intel].init.text
Map: 0-4b8 6fd60 [kvm_intel].init.data
Map: 0-380 70248 [kvm_intel]__dyndbg
Map: 0-8 70218 [kvm_intel].exit.data
Map: 0-438 4f980 [kvm_intel]__param
Map: 0-5f5 4ca0f [kvm_intel].rodata.str1.1
Map: 0-3657 493b8 [kvm_intel].rodata.str1.8
Map: 0-e0 70640 [kvm_intel].data..ro_after_init
Map: 0-500 70ec0 [kvm_intel].gnu.linkonce.this_module
Map: ffffffffc13a7000-ffffffffc1421000 a0 /lib/modules/6.7.2-local/kernel/arch/x86/kvm/kvm-intel.ko

The example above shows how the module section mappings are all wrong
except for the main .text mapping at 0xffffffffc13a7000.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: Like Xu <like.xu.linux@gmail.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240208085326.13432-2-adrian.hunter@intel.com

authored by

Adrian Hunter and committed by
Namhyung Kim
0bdfbd04 5b9e4eef

+25
+2
tools/perf/Documentation/perf.txt
··· 63 63 in browser mode 64 64 perf-event-open - Print perf_event_open() arguments and 65 65 return value 66 + kmaps - Print kernel and module maps (perf script 67 + and perf report without browser) 66 68 67 69 --debug-file:: 68 70 Write debug output to a specified file.
+2
tools/perf/builtin-report.c
··· 1766 1766 } else 1767 1767 ret = 0; 1768 1768 1769 + if (!use_browser && (verbose > 2 || debug_kmaps)) 1770 + perf_session__dump_kmaps(session); 1769 1771 error: 1770 1772 if (report.ptime_range) { 1771 1773 itrace_synth_opts__clear_time_range(&itrace_synth_opts);
+3
tools/perf/builtin-script.c
··· 4378 4378 4379 4379 flush_scripting(); 4380 4380 4381 + if (verbose > 2 || debug_kmaps) 4382 + perf_session__dump_kmaps(session); 4383 + 4381 4384 out_delete: 4382 4385 if (script.ptime_range) { 4383 4386 itrace_synth_opts__clear_time_range(&itrace_synth_opts);
+3
tools/perf/util/debug.c
··· 33 33 #endif 34 34 35 35 int verbose; 36 + int debug_kmaps; 36 37 int debug_peo_args; 37 38 bool dump_trace = false, quiet = false; 38 39 int debug_ordered_events; ··· 230 229 { .name = "stderr", .value_ptr = &redirect_to_stderr}, 231 230 { .name = "data-convert", .value_ptr = &debug_data_convert }, 232 231 { .name = "perf-event-open", .value_ptr = &debug_peo_args }, 232 + { .name = "kmaps", .value_ptr = &debug_kmaps }, 233 233 { .name = NULL, } 234 234 }; 235 235 ··· 269 267 /* For debug variables that are used as bool types, set to 0. */ 270 268 redirect_to_stderr = 0; 271 269 debug_peo_args = 0; 270 + debug_kmaps = 0; 272 271 273 272 return 0; 274 273 }
+1
tools/perf/util/debug.h
··· 9 9 #include <linux/compiler.h> 10 10 11 11 extern int verbose; 12 + extern int debug_kmaps; 12 13 extern int debug_peo_args; 13 14 extern bool quiet, dump_trace; 14 15 extern int debug_ordered_events;
+1
tools/perf/util/python.c
··· 181 181 * implementing 'verbose' and 'eprintf'. 182 182 */ 183 183 int verbose; 184 + int debug_kmaps; 184 185 int debug_peo_args; 185 186 186 187 int eprintf(int level, int var, const char *fmt, ...);
+11
tools/perf/util/session.c
··· 2720 2720 return machine__fprintf(&session->machines.host, fp); 2721 2721 } 2722 2722 2723 + void perf_session__dump_kmaps(struct perf_session *session) 2724 + { 2725 + int save_verbose = verbose; 2726 + 2727 + fflush(stdout); 2728 + fprintf(stderr, "Kernel and module maps:\n"); 2729 + verbose = 0; /* Suppress verbose to print a summary only */ 2730 + maps__fprintf(machine__kernel_maps(&session->machines.host), stderr); 2731 + verbose = save_verbose; 2732 + } 2733 + 2723 2734 struct evsel *perf_session__find_first_evtype(struct perf_session *session, 2724 2735 unsigned int type) 2725 2736 {
+2
tools/perf/util/session.h
··· 133 133 size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp, 134 134 bool skip_empty); 135 135 136 + void perf_session__dump_kmaps(struct perf_session *session); 137 + 136 138 struct evsel *perf_session__find_first_evtype(struct perf_session *session, 137 139 unsigned int type); 138 140