Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752127AbbKZDXI (ORCPT ); Wed, 25 Nov 2015 22:23:08 -0500 Received: from szxga01-in.huawei.com ([58.251.152.64]:36055 "EHLO szxga01-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751119AbbKZDXG (ORCPT ); Wed, 25 Nov 2015 22:23:06 -0500 From: Wang Nan To: CC: , , "Wang Nan" , Arnaldo Carvalho de Melo , Masami Hiramatsu , Namhyung Kim , Zefan Li , Subject: [PATCH v2] perf probe: Adjust dso->long_name for offline module Date: Thu, 26 Nov 2015 03:19:09 +0000 Message-ID: <1448507949-187812-1-git-send-email-wangnan0@huawei.com> X-Mailer: git-send-email 1.8.3.4 In-Reply-To: <1448451059-156220-1-git-send-email-wangnan0@huawei.com> References: <1448451059-156220-1-git-send-email-wangnan0@huawei.com> MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.107.193.248] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A090204.56567AFD.0027,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 77e410ba404373026e9084c334578446 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 5920 Lines: 156 Something unexpected may happen if copy statically linked perf to a production environment: # ./perf probe -m ./mymodule.ko my_func [mymodule] with build id 326ab42550ef3d24944f53c817533728367effeb not found, continuing without symbols Failed to find symbol my_func in /home/wangnan/kmodule/mymodule.ko Error: Failed to add events. # ./perf buildid-cache -a ./mymodule.ko # ./perf probe -m ./mymodule.ko my_func Added new event: probe:my_func (on my_func in /home/wangnan/kmodule/mymodule.ko) You can now use it in all perf tools, such as: perf record -e probe:my_func -aR sleep 1 Where: # ldd ./perf not a dynamic executable # strace -e open ./perf probe -m ./mymodule.ko my_func ... open("/home/wangnan/kmodule/mymodule.ko", O_RDONLY) = 3 open("/home/wangnan/kmodule/../lib64/elfutils/libebl_x86_64.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) ... open("/lib64/tls/libebl_x86_64.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/lib64/libebl_x86_64.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/lib64/tls/libebl_x86_64.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("/usr/lib64/libebl_x86_64.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) open("[mymodule]", O_RDONLY) = -1 ENOENT (No such file or directory) open("/home/wangnan/.debug/.build-id/32/6ab42550ef3d24944f53c817533728367effeb", O_RDONLY) = -1 ENOENT (No such file or directory) open("[mymodule]", O_RDONLY) = -1 ENOENT (No such file or directory) In the above example, probe fails before we put the module into buildid-cache. However, user would expect it success in both case because perf is able to find probe points actually. The reason is because perf won't utilize module's full path if it failed to open debuginfo. In convert_to_probe_trace_events -> find_probe_trace_events_from_map -> get_target_map -> kernel_get_module_map -> machine__findnew_module_map -> map_groups__find_by_name map_groups__find_by_name() is able to find the map of that module, but this information is found from /proc/module before it knows the real path of the offline module. Therefore, the map->dso->long_name is set to something like '[mymodule]', which prevent dso__load() find the real path of the module file. In another aspect, if dso__load() can get the offline module through buildid cache, it can read symble table from that ko. Even if debuginfo is not available, 'perf probe' can success if the '.symtab' can be found. This patch improves machine__findnew_module_map(): when dso->long_name is leading with '[' (doesn't find path of module when parsing /proc/modules), fixes it by dso__set_long_name(), so following dso__load() is possible to find the symbol table. This patch won't interfere with buildid matching. Here is the test result: # ./perf probe -m ./mymodule.ko my_func Added new event: probe:my_func (on my_func in /home/wangnan/kmodule/mymodule.ko) You can now use it in all perf tools, such as: perf record -e probe:my_func -aR sleep 1 # ./perf probe -d '*' Removed event: probe:my_func # mv ./mymodule.{ko,.bak} # mv ./moduleb.ko mymodule.ko # ./perf probe -m ./mymodule.ko my_func /home/wangnan/kmodule/mymodule.ko with build id 326ab42550ef3d24944f53c817533728367effeb not found, continuing without symbols Failed to find symbol my_func in /home/wangnan/kmodule/mymodule.ko Error: Failed to add events. # ./perf probe -v -m ./mymodule.ko my_func probe-definition(0): my_func symbol:my_func file:(null) line:0 offset:0 return:0 lazy:(null) 0 arguments Could not open debuginfo. Try to use symbols. symsrc__init: build id mismatch for /home/wangnan/kmodule/mymodule.ko. /home/wangnan/kmodule/mymodule.ko with build id 326ab42550ef3d24944f53c817533728367effeb not found, continuing without symbols Failed to find symbol my_func in /home/wangnan/kmodule/mymodule.ko Error: Failed to add events. Reason: No such file or directory (Code: -2) Signed-off-by: Wang Nan Cc: Arnaldo Carvalho de Melo Cc: Masami Hiramatsu Cc: Namhyung Kim Cc: Zefan Li Cc: pi3orama@163.com --- tools/perf/util/machine.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index 7f5071a..cdfa97f 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -561,6 +561,24 @@ int machine__process_switch_event(struct machine *machine __maybe_unused, return 0; } +static void adjust_dso_long_name(struct map *map, const char *filename) +{ + const char *dup_filename; + + if (!filename || !map->dso || !map->dso->long_name) + return; + if (map->dso->long_name[0] != '[') + return; + if (!strchr(filename, '/')) + return; + + dup_filename = strdup(filename); + if (!dup_filename) + return; + + dso__set_long_name(map->dso, filename, true); +} + struct map *machine__findnew_module_map(struct machine *machine, u64 start, const char *filename) { @@ -573,8 +591,15 @@ struct map *machine__findnew_module_map(struct machine *machine, u64 start, map = map_groups__find_by_name(&machine->kmaps, MAP__FUNCTION, m.name); - if (map) + if (map) { + /* + * If the map's dso is an offline module, give dso__load() + * a chance to find the file path of that module by fixing + * long_name. + */ + adjust_dso_long_name(map, filename); goto out; + } dso = machine__findnew_module_dso(machine, &m, filename); if (dso == NULL) -- 1.8.3.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/