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

perf probe: Check address correctness by map instead of _etext

Since commit 03db8b583d1c ("perf tools: Fix
maps__find_symbol_by_name()") introduced map address range check in
maps__find_symbol_by_name(), we can not get "_etext" from kernel map
because _etext is placed on the edge of the kernel .text section (=
kernel map in perf.)

To fix this issue, this checks the address correctness by map address
range information (map->start and map->end) instead of using _etext
address.

This can cause an error if the target inlined function is embedded in
both __init function and normal function.

For exaample, request_resource() is a normal function but also embedded
in __init reserve_setup(). In this case, the probe point in
reserve_setup() must be skipped.

However, without this fix, it failes to setup all probe points:

# ./perf probe -v request_resource
probe-definition(0): request_resource
symbol:request_resource file:(null) line:0 offset:0 return:0 lazy:(null)
0 arguments
Looking at the vmlinux_path (8 entries long)
Using /usr/lib/debug/lib/modules/5.5.17-200.fc31.x86_64/vmlinux for symbols
Open Debuginfo file: /usr/lib/debug/lib/modules/5.5.17-200.fc31.x86_64/vmlinux
Try to find probe point from debuginfo.
Matched function: request_resource [15e29ad]
found inline addr: 0xffffffff82fbf892
Probe point found: reserve_setup+204
found inline addr: 0xffffffff810e9790
Probe point found: request_resource+0
Found 2 probe_trace_events.
Opening /sys/kernel/debug/tracing//kprobe_events write=1
Opening /sys/kernel/debug/tracing//README write=0
Writing event: p:probe/request_resource _text+33290386
Failed to write event: Invalid argument
Error: Failed to add events. Reason: Invalid argument (Code: -22)
#

With this fix,

# ./perf probe request_resource
reserve_setup is out of .text, skip it.
Added new events:
(null):(null) (on request_resource)
probe:request_resource (on request_resource)

You can now use it in all perf tools, such as:

perf record -e probe:request_resource -aR sleep 1

#

Fixes: 03db8b583d1c ("perf tools: Fix maps__find_symbol_by_name()")
Reported-by: Arnaldo Carvalho de Melo <acme@kernel.org>
Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: stable@vger.kernel.org
Link: http://lore.kernel.org/lkml/158763967332.30755.4922496724365529088.stgit@devnote2
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Masami Hiramatsu and committed by
Arnaldo Carvalho de Melo
2ae5d0d7 80526491

+13 -12
+13 -12
tools/perf/util/probe-event.c
··· 236 236 static bool kprobe_blacklist__listed(unsigned long address); 237 237 static bool kprobe_warn_out_range(const char *symbol, unsigned long address) 238 238 { 239 - u64 etext_addr = 0; 240 - int ret; 239 + struct map *map; 240 + bool ret = false; 241 241 242 - /* Get the address of _etext for checking non-probable text symbol */ 243 - ret = kernel_get_symbol_address_by_name("_etext", &etext_addr, 244 - false, false); 245 - 246 - if (ret == 0 && etext_addr < address) 247 - pr_warning("%s is out of .text, skip it.\n", symbol); 248 - else if (kprobe_blacklist__listed(address)) 242 + map = kernel_get_module_map(NULL); 243 + if (map) { 244 + ret = address <= map->start || map->end < address; 245 + if (ret) 246 + pr_warning("%s is out of .text, skip it.\n", symbol); 247 + map__put(map); 248 + } 249 + if (!ret && kprobe_blacklist__listed(address)) { 249 250 pr_warning("%s is blacklisted function, skip it.\n", symbol); 250 - else 251 - return false; 251 + ret = true; 252 + } 252 253 253 - return true; 254 + return ret; 254 255 } 255 256 256 257 /*