linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address
@ 2015-08-26 10:57 Wang Nan
  2015-08-26 10:57 ` [PATCH v3 1/6] perf probe: Prevent segfault when reading probe point with " Wang Nan
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

The goal of these 4 patches is to allow perf probing at absolute address
for uprobes and kprobes. During the development several small problem in
'perf probe -l' is found and fixed.

Patch v2 can be found from [1].

Following Masami's suggestion, v3 splits bugfixs into their own
patches instead of merging with feature.

In this series, patch 1/6 to 4/6 are small bugfix. Patch 5/6 is the main
patch which support the new syntax. Patch 6/6 is a kernel side small bugfix.

Patch 1/6 and 6/6 have already been acked by Masami Hiramatsu.

[1] http://lkml.kernel.org/r/1440574825-221187-1-git-send-email-wangnan0@huawei.com

Wang Nan (6):
  perf probe: Prevent segfault when reading probe point with absolute
    address
  perf probe: Fix list result when symbol can't be found
  perf probe: Fix list result when address is zero
  perf probe: Fix error reported when offset without function
  perf probe: Support probing at absolute address
  tracing/uprobes: Do not print '0x (null)' when offset is 0

 kernel/trace/trace_uprobe.c    |  17 +++-
 tools/perf/util/probe-event.c  | 210 +++++++++++++++++++++++++++++++++++++----
 tools/perf/util/probe-event.h  |   4 +
 tools/perf/util/probe-finder.c |  21 +----
 4 files changed, 216 insertions(+), 36 deletions(-)

-- 
1.8.3.4


^ permalink raw reply	[flat|nested] 18+ messages in thread

* [PATCH v3 1/6] perf probe: Prevent segfault when reading probe point with absolute address
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when neither dwarf nor map can't find symbol Wang Nan
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

'perf probe -l' panic if there is a manually inserted probing point
with absolute address. For example:

 # echo 'p:probe/abs_ffffffff811e6615 0xffffffff811e6615' > /sys/kernel/debug/tracing/kprobe_events
 # perf probe -l
 Segmentation fault (core dumped)

This patch fixes this problem by considering the situation that
"tp->symbol == NULL" in find_perf_probe_point_from_dwarf() and
find_perf_probe_point_from_map().

After this patch:

 # perf probe -l
 probe:abs_ffffffff811e6615 (on SyS_write+5@fs/read_write.c)

And when debug info is missing:

 # rm -rf ~/.debug
 # mv /lib/modules/4.2.0-rc1+/build/vmlinux /lib/modules/4.2.0-rc1+/build/vmlinux.bak
 # perf probe -l
 probe:abs_ffffffff811e6615 (on sys_write+5)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1440509256-193590-1-git-send-email-wangnan0@huawei.com
---
 tools/perf/util/probe-event.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f07374b..6c7e538 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -515,7 +515,7 @@ static int find_perf_probe_point_from_dwarf(struct probe_trace_point *tp,
 		if (ret < 0)
 			goto error;
 		addr += stext;
-	} else {
+	} else if (tp->symbol) {
 		addr = kernel_get_symbol_address_by_name(tp->symbol, false);
 		if (addr == 0)
 			goto error;
@@ -1815,17 +1815,17 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
 {
 	struct symbol *sym = NULL;
 	struct map *map;
-	u64 addr;
+	u64 addr = tp->address;
 	int ret = -ENOENT;
 
 	if (!is_kprobe) {
 		map = dso__new_map(tp->module);
 		if (!map)
 			goto out;
-		addr = tp->address;
 		sym = map__find_symbol(map, addr, NULL);
 	} else {
-		addr = kernel_get_symbol_address_by_name(tp->symbol, true);
+		if (tp->symbol)
+			addr = kernel_get_symbol_address_by_name(tp->symbol, true);
 		if (addr) {
 			addr += tp->offset;
 			sym = __find_kernel_function(addr, &map);
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3 2/6] perf probe: Fix list result when neither dwarf nor map can't find symbol
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
  2015-08-26 10:57 ` [PATCH v3 1/6] perf probe: Prevent segfault when reading probe point with " Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-26 11:03   ` Wangnan (F)
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found Wang Nan
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

'perf probe -l' reports error if it is unable find symbol through
address. Here is an example.

 # echo 'p:probe_libc/abs_5 /lib64/libc.so.6:0x5' >
          /sys/kernel/debug/tracing/uprobe_events
 # cat /sys/kernel/debug/tracing/uprobe_events
  p:probe_libc/abs_5 /lib64/libc.so.6:0x0000000000000005
 # perf probe -l
   Error: Failed to show event list

Also, this situation triggers a logical inconsistency in
convert_to_perf_probe_point() that, it returns ENOMEM but actually
it never try strdup().

This patch removes !tp->module && !is_kprobe condition, so it
always uses address to build function name if symbol not found.

Test result:

 # perf probe -l
   probe_libc:abs_5     (on 0x5 in /lib64/libc.so.6)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
 tools/perf/util/probe-event.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6c7e538..f7bacbb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1866,7 +1866,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
 	if (tp->symbol) {
 		pp->function = strdup(tp->symbol);
 		pp->offset = tp->offset;
-	} else if (!tp->module && !is_kprobe) {
+	} else {
 		ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
 		if (ret < 0)
 			return ret;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
  2015-08-26 10:57 ` [PATCH v3 1/6] perf probe: Prevent segfault when reading probe point with " Wang Nan
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when neither dwarf nor map can't find symbol Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-26 12:27   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:41   ` [tip:perf/core] perf probe: Fix list result when symbol can' t " tip-bot for Wang Nan
  2015-08-26 10:57 ` [PATCH v3 3/6] perf probe: Fix list result when address is zero Wang Nan
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

'perf probe -l' reports error if it is unable find symbol through
address. Here is an example.

 # echo 'p:probe_libc/abs_5 /lib64/libc.so.6:0x5' >
          /sys/kernel/debug/tracing/uprobe_events
 # cat /sys/kernel/debug/tracing/uprobe_events
  p:probe_libc/abs_5 /lib64/libc.so.6:0x0000000000000005
 # perf probe -l
   Error: Failed to show event list

Also, this situation triggers a logical inconsistency in
convert_to_perf_probe_point() that, it returns ENOMEM but actually
it never try strdup().

This patch removes !tp->module && !is_kprobe condition, so it
always uses address to build function name if symbol not found.

Test result:

 # perf probe -l
   probe_libc:abs_5     (on 0x5 in /lib64/libc.so.6)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
 tools/perf/util/probe-event.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6c7e538..f7bacbb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1866,7 +1866,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
 	if (tp->symbol) {
 		pp->function = strdup(tp->symbol);
 		pp->offset = tp->offset;
-	} else if (!tp->module && !is_kprobe) {
+	} else {
 		ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
 		if (ret < 0)
 			return ret;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3 3/6] perf probe: Fix list result when address is zero
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
                   ` (2 preceding siblings ...)
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-26 12:14   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
  2015-08-26 10:57 ` [PATCH v3 4/6] perf probe: Fix error reported when offset without function Wang Nan
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

When manually added uprobe point with zero address, 'perf probe -l'
reports error. For example:

 # echo p:probe_libc/abs_0 /path/to/lib.bin:0x0 arg1=%ax > \
           /sys/kernel/debug/tracing/uprobe_events

 # perf probe -l
 Error: Failed to show event list.

Probing at 0x0 is possible and useful when lib.bin is not a normal
shared object but is manually mapped. However, in this case kernel
report:

 # cat /sys/kernel/debug/tracing/uprobe_events
 p:probe_libc/abs_0 /path/to/lib.bin:0x          (null) arg1=%ax

This patch supports the above kernel output.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
 tools/perf/util/probe-event.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f7bacbb..926bcec 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1519,9 +1519,31 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 	} else
 		p = argv[1];
 	fmt1_str = strtok_r(p, "+", &fmt);
-	if (fmt1_str[0] == '0')	/* only the address started with 0x */
-		tp->address = strtoul(fmt1_str, NULL, 0);
-	else {
+	/* only the address started with 0x */
+	if (fmt1_str[0] == '0')	{
+		/*
+		 * Fix a special case:
+		 * if address == 0, kernel reports something like:
+		 * p:probe_libc/abs_0 /lib/libc-2.18.so:0x          (null) arg1=%ax
+		 * Newer kernel may fix that, but we want to
+		 * support old kernel also.
+		 */
+		if (strcmp(fmt1_str, "0x") == 0) {
+			if (!argv[2] || strcmp(argv[2], "(null)")) {
+				ret = -EINVAL;
+				goto out;
+			}
+			tp->address = 0;
+
+			free(argv[2]);
+			for (i = 2; argv[i + 1] != NULL; i++)
+				argv[i] = argv[i + 1];
+
+			argv[i] = NULL;
+			argc -= 1;
+		} else
+			tp->address = strtoul(fmt1_str, NULL, 0);
+	} else {
 		/* Only the symbol-based probe has offset */
 		tp->symbol = strdup(fmt1_str);
 		if (tp->symbol == NULL) {
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3 4/6] perf probe: Fix error reported when offset without function
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
                   ` (3 preceding siblings ...)
  2015-08-26 10:57 ` [PATCH v3 3/6] perf probe: Fix list result when address is zero Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-26 12:21   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
  2015-08-26 10:57 ` [PATCH v3 5/6] perf probe: Support probing at absolute address Wang Nan
  2015-08-26 10:57 ` [PATCH v3 6/6] tracing/uprobes: Do not print '0x (null)' when offset is 0 Wang Nan
  6 siblings, 2 replies; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

This patch fixes a bug that, when offset is provided but function is
lost, parse_perf_probe_point() will give a "" string as function name,
so the checking code at the end of parse_perf_probe_point() become useless.
For example:

 # perf probe +0x1234
 Failed to find symbol  in kernel
   Error: Failed to add events.

After this patch:

 # perf probe +0x1234
 Semantic error :Offset requires an entry function.
   Error: Command Parse Error.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
 tools/perf/util/probe-event.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 926bcec..eaacb58 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1194,9 +1194,13 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 		*ptr++ = '\0';
 	}
 
-	tmp = strdup(arg);
-	if (tmp == NULL)
-		return -ENOMEM;
+	if (arg[0] == '\0')
+		tmp = NULL;
+	else {
+		tmp = strdup(arg);
+		if (tmp == NULL)
+			return -ENOMEM;
+	}
 
 	if (file_spec)
 		pp->file = tmp;
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3 5/6] perf probe: Support probing at absolute address
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
                   ` (4 preceding siblings ...)
  2015-08-26 10:57 ` [PATCH v3 4/6] perf probe: Fix error reported when offset without function Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-26 12:16   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
  2015-08-26 10:57 ` [PATCH v3 6/6] tracing/uprobes: Do not print '0x (null)' when offset is 0 Wang Nan
  6 siblings, 2 replies; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

It should be useful to allow 'perf probe' probe at absolute offset of
a target. For example, when (u)probing at a instruction of a shared
object in a embedded system where debuginfo is not avaliable but we
know the offset of that instruction by manually digging.

This patch enables following perf probe command syntax:

 # perf probe 0xffffffff811e6615

And

 # perf probe /lib/x86_64-linux-gnu/libc-2.19.so 0xeb860

In the above example, we don't need a anchor symbol, so it is possible
to compute absolute addresses using other methods and then use
'perf probe' to create the probing points.

v1 -> v2:
  Drop the leading '+' in cmdline;
  Allow uprobing at offset 0x0;
  Improve 'perf probe -l' result when uprobe at area without debuginfo.

v2 -> v3:
  Split bugfix to a separated patch.

Test result:

 # perf probe 0xffffffff8119d175 %ax
 # perf probe sys_write %ax
 # perf probe /lib64/libc-2.18.so 0x0 %ax
 # perf probe /lib64/libc-2.18.so 0x5 %ax
 # perf probe /lib64/libc-2.18.so 0xd8e40 %ax
 # perf probe /lib64/libc-2.18.so __write %ax
 # perf probe /lib64/libc-2.18.so 0xd8e49 %ax
 # cat /sys/kernel/debug/tracing/uprobe_events

 p:probe_libc/abs_0 /lib64/libc-2.18.so:0x          (null) arg1=%ax
 p:probe_libc/abs_5 /lib64/libc-2.18.so:0x0000000000000005 arg1=%ax
 p:probe_libc/abs_d8e40 /lib64/libc-2.18.so:0x00000000000d8e40 arg1=%ax
 p:probe_libc/__write /lib64/libc-2.18.so:0x00000000000d8e40 arg1=%ax
 p:probe_libc/abs_d8e49 /lib64/libc-2.18.so:0x00000000000d8e49 arg1=%ax

 # cat /sys/kernel/debug/tracing/kprobe_events

 p:probe/abs_ffffffff8119d175 0xffffffff8119d175 arg1=%ax
 p:probe/sys_write _text+1692016 arg1=%ax

 # perf probe -l

 Failed to find debug information for address 5
   probe:abs_ffffffff8119d175 (on sys_write+5 with arg1)
   probe:sys_write      (on sys_write with arg1)
   probe_libc:__write   (on @unix/syscall-template.S:81 in /lib64/libc-2.18.so with arg1)
   probe_libc:abs_0     (on 0x0 in /lib64/libc-2.18.so with arg1)
   probe_libc:abs_5     (on 0x5 in /lib64/libc-2.18.so with arg1)
   probe_libc:abs_d8e40 (on @unix/syscall-template.S:81 in /lib64/libc-2.18.so with arg1)
   probe_libc:abs_d8e49 (on __GI___libc_write+9 in /lib64/libc-2.18.so with arg1)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
 tools/perf/util/probe-event.c  | 162 +++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-event.h  |   4 +
 tools/perf/util/probe-finder.c |  21 +-----
 3 files changed, 163 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eaacb58..eb5f18b 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1204,9 +1204,27 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 
 	if (file_spec)
 		pp->file = tmp;
-	else
+	else {
 		pp->function = tmp;
 
+		/*
+		 * Keep pp->function even if this is absolute address,
+		 * so it can mark whether abs_address is valid.
+		 * Which make 'perf probe lib.bin 0x0' possible.
+		 *
+		 * Note that checking length of tmp is not needed
+		 * because when we access tmp[1] we know tmp[0] is '0',
+		 * so tmp[1] should always valid (but could be '\0').
+		 */
+		if (tmp && !strncmp(tmp, "0x", 2)) {
+			pp->abs_address = strtoul(pp->function, &tmp, 0);
+			if (*tmp != '\0') {
+				semantic_error("Invalid absolute address.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
 	/* Parse other options */
 	while (ptr) {
 		arg = ptr;
@@ -1804,14 +1822,29 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
 	if (len <= 0)
 		goto error;
 
-	/* Uprobes must have tp->address and tp->module */
-	if (tev->uprobes && (!tp->address || !tp->module))
+	/* Uprobes must have tp->module */
+	if (tev->uprobes && !tp->module)
 		goto error;
+	/*
+	 * If tp->address == 0, then this point must be a
+	 * absolute address uprobe.
+	 * try_to_find_absolute_address() should have made
+	 * tp->symbol to "0x0".
+	 */
+	if (tev->uprobes && !tp->address) {
+		if (!tp->symbol || strcmp(tp->symbol, "0x0"))
+			goto error;
+	}
 
 	/* Use the tp->address for uprobes */
 	if (tev->uprobes)
 		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
 				 tp->module, tp->address);
+	else if (!strncmp(tp->symbol, "0x", 2))
+		/* Absolute address. See try_to_find_absolute_address() */
+		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx",
+				 tp->module ?: "", tp->module ? ":" : "",
+				 tp->address);
 	else
 		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
 				 tp->module ?: "", tp->module ? ":" : "",
@@ -1874,8 +1907,8 @@ out:
 }
 
 static int convert_to_perf_probe_point(struct probe_trace_point *tp,
-					struct perf_probe_point *pp,
-					bool is_kprobe)
+				       struct perf_probe_point *pp,
+				       bool is_kprobe)
 {
 	char buf[128];
 	int ret;
@@ -2331,7 +2364,9 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	if (pev->event)
 		event = pev->event;
 	else
-		if (pev->point.function && !strisglob(pev->point.function))
+		if (pev->point.function &&
+			(strncmp(pev->point.function, "0x", 2) != 0) &&
+			!strisglob(pev->point.function))
 			event = pev->point.function;
 		else
 			event = tev->point.realname;
@@ -2598,6 +2633,98 @@ err_out:
 	goto out;
 }
 
+static int try_to_find_absolute_address(struct perf_probe_event *pev,
+					struct probe_trace_event **tevs)
+{
+	struct perf_probe_point *pp = &pev->point;
+	struct probe_trace_event *tev;
+	struct probe_trace_point *tp;
+	int i, err;
+
+	if (!(pev->point.function && !strncmp(pev->point.function, "0x", 2)))
+		return -EINVAL;
+	if (perf_probe_event_need_dwarf(pev))
+		return -EINVAL;
+
+	/*
+	 * This is 'perf probe /lib/libc.so 0xabcd'. Try to probe at
+	 * absolute address.
+	 *
+	 * Only one tev can be generated by this.
+	 */
+	*tevs = zalloc(sizeof(*tev));
+	if (!*tevs)
+		return -ENOMEM;
+
+	tev = *tevs;
+	tp = &tev->point;
+
+	/*
+	 * Don't use tp->offset, use address directly, because
+	 * in synthesize_probe_trace_command() address cannot be
+	 * zero.
+	 */
+	tp->address = pev->point.abs_address;
+	tp->retprobe = pp->retprobe;
+	tev->uprobes = pev->uprobes;
+
+	err = -ENOMEM;
+	/*
+	 * Give it a '0x' leading symbol name.
+	 * In __add_probe_trace_events, a NULL symbol is interpreted as
+	 * invalud.
+	 */
+	if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
+		goto errout;
+
+	/* For kprobe, check range */
+	if ((!tev->uprobes) &&
+	    (kprobe_warn_out_range(tev->point.symbol,
+				   tev->point.address))) {
+		err = -EACCES;
+		goto errout;
+	}
+
+	if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0)
+		goto errout;
+
+	if (pev->target) {
+		tp->module = strdup(pev->target);
+		if (!tp->module)
+			goto errout;
+	}
+
+	if (tev->group) {
+		tev->group = strdup(pev->group);
+		if (!tev->group)
+			goto errout;
+	}
+
+	if (pev->event) {
+		tev->event = strdup(pev->event);
+		if (!tev->event)
+			goto errout;
+	}
+
+	tev->nargs = pev->nargs;
+	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
+	if (!tev->args) {
+		err = -ENOMEM;
+		goto errout;
+	}
+	for (i = 0; i < tev->nargs; i++)
+		copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]);
+
+	return 1;
+
+errout:
+	if (*tevs) {
+		clear_probe_trace_events(*tevs, 1);
+		*tevs = NULL;
+	}
+	return err;
+}
+
 bool __weak arch__prefers_symtab(void) { return false; }
 
 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
@@ -2614,6 +2741,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		}
 	}
 
+	ret = try_to_find_absolute_address(pev, tevs);
+	if (ret > 0)
+		return ret;
+
 	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
 		ret = find_probe_trace_events_from_map(pev, tevs);
 		if (ret > 0)
@@ -2784,3 +2915,22 @@ end:
 	return ret;
 }
 
+int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
+			    struct perf_probe_arg *pvar)
+{
+	tvar->value = strdup(pvar->var);
+	if (tvar->value == NULL)
+		return -ENOMEM;
+	if (pvar->type) {
+		tvar->type = strdup(pvar->type);
+		if (tvar->type == NULL)
+			return -ENOMEM;
+	}
+	if (pvar->name) {
+		tvar->name = strdup(pvar->name);
+		if (tvar->name == NULL)
+			return -ENOMEM;
+	} else
+		tvar->name = NULL;
+	return 0;
+}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 83ee95e..6e7ec68 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -59,6 +59,7 @@ struct perf_probe_point {
 	bool		retprobe;	/* Return probe flag */
 	char		*lazy_line;	/* Lazy matching pattern */
 	unsigned long	offset;		/* Offset from function entry */
+	unsigned long	abs_address;	/* Absolute address of the point */
 };
 
 /* Perf probe probing argument field chain */
@@ -156,4 +157,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
 /* Maximum index number of event-name postfix */
 #define MAX_EVENT_INDEX	1024
 
+int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
+			    struct perf_probe_arg *pvar);
+
 #endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 7b80f8c..29c43c068 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -553,24 +553,9 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 	char buf[32], *ptr;
 	int ret = 0;
 
-	if (!is_c_varname(pf->pvar->var)) {
-		/* Copy raw parameters */
-		pf->tvar->value = strdup(pf->pvar->var);
-		if (pf->tvar->value == NULL)
-			return -ENOMEM;
-		if (pf->pvar->type) {
-			pf->tvar->type = strdup(pf->pvar->type);
-			if (pf->tvar->type == NULL)
-				return -ENOMEM;
-		}
-		if (pf->pvar->name) {
-			pf->tvar->name = strdup(pf->pvar->name);
-			if (pf->tvar->name == NULL)
-				return -ENOMEM;
-		} else
-			pf->tvar->name = NULL;
-		return 0;
-	}
+	/* Copy raw parameters */
+	if (!is_c_varname(pf->pvar->var))
+		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
 
 	if (pf->pvar->name)
 		pf->tvar->name = strdup(pf->pvar->name);
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [PATCH v3 6/6] tracing/uprobes: Do not print '0x (null)' when offset is 0
  2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
                   ` (5 preceding siblings ...)
  2015-08-26 10:57 ` [PATCH v3 5/6] perf probe: Support probing at absolute address Wang Nan
@ 2015-08-26 10:57 ` Wang Nan
  2015-08-28  6:43   ` [tip:perf/core] " tip-bot for Wang Nan
  6 siblings, 1 reply; 18+ messages in thread
From: Wang Nan @ 2015-08-26 10:57 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, Wang Nan

When manually added uprobe point with zero address, 'uprobe_events' output
'(null)' instead of 0x00000000:

 # echo p:probe_libc/abs_0 /path/to/lib.bin:0x0 arg1=%ax > \
            /sys/kernel/debug/tracing/uprobe_events

 # cat /sys/kernel/debug/tracing/uprobe_events
   p:probe_libc/abs_0 /path/to/lib.bin:0x          (null) arg1=%ax

This patch fixes this behavior:

 # cat /sys/kernel/debug/tracing/uprobe_events
 p:probe_libc/abs_0 /path/to/lib.bin:0x0000000000000000

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
---
 kernel/trace/trace_uprobe.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index f97479f..d2f6d0b 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -601,7 +601,22 @@ static int probes_seq_show(struct seq_file *m, void *v)
 
 	seq_printf(m, "%c:%s/%s", c, tu->tp.call.class->system,
 			trace_event_name(&tu->tp.call));
-	seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset);
+	seq_printf(m, " %s:", tu->filename);
+
+	/* Don't print "0x  (null)" when offset is 0 */
+	if (tu->offset) {
+		seq_printf(m, "0x%p", (void *)tu->offset);
+	} else {
+		switch (sizeof(void *)) {
+		case 4:
+			seq_printf(m, "0x00000000");
+			break;
+		case 8:
+		default:
+			seq_printf(m, "0x0000000000000000");
+			break;
+		}
+	}
 
 	for (i = 0; i < tu->tp.nr_args; i++)
 		seq_printf(m, " %s=%s", tu->tp.args[i].name, tu->tp.args[i].comm);
-- 
1.8.3.4


^ permalink raw reply related	[flat|nested] 18+ messages in thread

* Re: [PATCH v3 2/6] perf probe: Fix list result when neither dwarf nor map can't find symbol
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when neither dwarf nor map can't find symbol Wang Nan
@ 2015-08-26 11:03   ` Wangnan (F)
  0 siblings, 0 replies; 18+ messages in thread
From: Wangnan (F) @ 2015-08-26 11:03 UTC (permalink / raw)
  To: acme, masami.hiramatsu.pt, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel

Please ignore this one, and use the identical one with shorter title.

Sorry for the noisy.

On 2015/8/26 18:57, Wang Nan wrote:
> 'perf probe -l' reports error if it is unable find symbol through
> address. Here is an example.
>
>   # echo 'p:probe_libc/abs_5 /lib64/libc.so.6:0x5' >
>            /sys/kernel/debug/tracing/uprobe_events
>   # cat /sys/kernel/debug/tracing/uprobe_events
>    p:probe_libc/abs_5 /lib64/libc.so.6:0x0000000000000005
>   # perf probe -l
>     Error: Failed to show event list
>
> Also, this situation triggers a logical inconsistency in
> convert_to_perf_probe_point() that, it returns ENOMEM but actually
> it never try strdup().
>
> This patch removes !tp->module && !is_kprobe condition, so it
> always uses address to build function name if symbol not found.
>
> Test result:
>
>   # perf probe -l
>     probe_libc:abs_5     (on 0x5 in /lib64/libc.so.6)
>
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> ---
>   tools/perf/util/probe-event.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 6c7e538..f7bacbb 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -1866,7 +1866,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
>   	if (tp->symbol) {
>   		pp->function = strdup(tp->symbol);
>   		pp->offset = tp->offset;
> -	} else if (!tp->module && !is_kprobe) {
> +	} else {
>   		ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
>   		if (ret < 0)
>   			return ret;



^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH v3 3/6] perf probe: Fix list result when address is zero
  2015-08-26 10:57 ` [PATCH v3 3/6] perf probe: Fix list result when address is zero Wang Nan
@ 2015-08-26 12:14   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: 平松雅巳 / HIRAMATU,MASAMI @ 2015-08-26 12:14 UTC (permalink / raw)
  To: 'Wang Nan', acme, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, sysp-manager

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 2631 bytes --]

> From: Wang Nan [mailto:wangnan0@huawei.com]
> 
> When manually added uprobe point with zero address, 'perf probe -l'
> reports error. For example:
> 
>  # echo p:probe_libc/abs_0 /path/to/lib.bin:0x0 arg1=%ax > \
>            /sys/kernel/debug/tracing/uprobe_events
> 
>  # perf probe -l
>  Error: Failed to show event list.
> 
> Probing at 0x0 is possible and useful when lib.bin is not a normal
> shared object but is manually mapped. However, in this case kernel
> report:
> 
>  # cat /sys/kernel/debug/tracing/uprobe_events
>  p:probe_libc/abs_0 /path/to/lib.bin:0x          (null) arg1=%ax
> 
> This patch supports the above kernel output.

OK, Looks good to me:)


Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Thanks!


> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> ---
>  tools/perf/util/probe-event.c | 28 +++++++++++++++++++++++++---
>  1 file changed, 25 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index f7bacbb..926bcec 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -1519,9 +1519,31 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
>  	} else
>  		p = argv[1];
>  	fmt1_str = strtok_r(p, "+", &fmt);
> -	if (fmt1_str[0] == '0')	/* only the address started with 0x */
> -		tp->address = strtoul(fmt1_str, NULL, 0);
> -	else {
> +	/* only the address started with 0x */
> +	if (fmt1_str[0] == '0')	{
> +		/*
> +		 * Fix a special case:
> +		 * if address == 0, kernel reports something like:
> +		 * p:probe_libc/abs_0 /lib/libc-2.18.so:0x          (null) arg1=%ax
> +		 * Newer kernel may fix that, but we want to
> +		 * support old kernel also.
> +		 */
> +		if (strcmp(fmt1_str, "0x") == 0) {
> +			if (!argv[2] || strcmp(argv[2], "(null)")) {
> +				ret = -EINVAL;
> +				goto out;
> +			}
> +			tp->address = 0;
> +
> +			free(argv[2]);
> +			for (i = 2; argv[i + 1] != NULL; i++)
> +				argv[i] = argv[i + 1];
> +
> +			argv[i] = NULL;
> +			argc -= 1;
> +		} else
> +			tp->address = strtoul(fmt1_str, NULL, 0);
> +	} else {
>  		/* Only the symbol-based probe has offset */
>  		tp->symbol = strdup(fmt1_str);
>  		if (tp->symbol == NULL) {
> --
> 1.8.3.4

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH v3 5/6] perf probe: Support probing at absolute address
  2015-08-26 10:57 ` [PATCH v3 5/6] perf probe: Support probing at absolute address Wang Nan
@ 2015-08-26 12:16   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: 平松雅巳 / HIRAMATU,MASAMI @ 2015-08-26 12:16 UTC (permalink / raw)
  To: 'Wang Nan', acme, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, sysp-manager

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 11180 bytes --]

> From: Wang Nan [mailto:wangnan0@huawei.com]
> 
> It should be useful to allow 'perf probe' probe at absolute offset of
> a target. For example, when (u)probing at a instruction of a shared
> object in a embedded system where debuginfo is not avaliable but we
> know the offset of that instruction by manually digging.
> 
> This patch enables following perf probe command syntax:
> 
>  # perf probe 0xffffffff811e6615
> 
> And
> 
>  # perf probe /lib/x86_64-linux-gnu/libc-2.19.so 0xeb860
> 
> In the above example, we don't need a anchor symbol, so it is possible
> to compute absolute addresses using other methods and then use
> 'perf probe' to create the probing points.

OK, now looks good to me :D

Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Thank you,

> 
> v1 -> v2:
>   Drop the leading '+' in cmdline;
>   Allow uprobing at offset 0x0;
>   Improve 'perf probe -l' result when uprobe at area without debuginfo.
> 
> v2 -> v3:
>   Split bugfix to a separated patch.
> 
> Test result:
> 
>  # perf probe 0xffffffff8119d175 %ax
>  # perf probe sys_write %ax
>  # perf probe /lib64/libc-2.18.so 0x0 %ax
>  # perf probe /lib64/libc-2.18.so 0x5 %ax
>  # perf probe /lib64/libc-2.18.so 0xd8e40 %ax
>  # perf probe /lib64/libc-2.18.so __write %ax
>  # perf probe /lib64/libc-2.18.so 0xd8e49 %ax
>  # cat /sys/kernel/debug/tracing/uprobe_events
> 
>  p:probe_libc/abs_0 /lib64/libc-2.18.so:0x          (null) arg1=%ax
>  p:probe_libc/abs_5 /lib64/libc-2.18.so:0x0000000000000005 arg1=%ax
>  p:probe_libc/abs_d8e40 /lib64/libc-2.18.so:0x00000000000d8e40 arg1=%ax
>  p:probe_libc/__write /lib64/libc-2.18.so:0x00000000000d8e40 arg1=%ax
>  p:probe_libc/abs_d8e49 /lib64/libc-2.18.so:0x00000000000d8e49 arg1=%ax
> 
>  # cat /sys/kernel/debug/tracing/kprobe_events
> 
>  p:probe/abs_ffffffff8119d175 0xffffffff8119d175 arg1=%ax
>  p:probe/sys_write _text+1692016 arg1=%ax
> 
>  # perf probe -l
> 
>  Failed to find debug information for address 5
>    probe:abs_ffffffff8119d175 (on sys_write+5 with arg1)
>    probe:sys_write      (on sys_write with arg1)
>    probe_libc:__write   (on @unix/syscall-template.S:81 in /lib64/libc-2.18.so with arg1)
>    probe_libc:abs_0     (on 0x0 in /lib64/libc-2.18.so with arg1)
>    probe_libc:abs_5     (on 0x5 in /lib64/libc-2.18.so with arg1)
>    probe_libc:abs_d8e40 (on @unix/syscall-template.S:81 in /lib64/libc-2.18.so with arg1)
>    probe_libc:abs_d8e49 (on __GI___libc_write+9 in /lib64/libc-2.18.so with arg1)
> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> ---
>  tools/perf/util/probe-event.c  | 162 +++++++++++++++++++++++++++++++++++++++--
>  tools/perf/util/probe-event.h  |   4 +
>  tools/perf/util/probe-finder.c |  21 +-----
>  3 files changed, 163 insertions(+), 24 deletions(-)
> 
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index eaacb58..eb5f18b 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -1204,9 +1204,27 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
> 
>  	if (file_spec)
>  		pp->file = tmp;
> -	else
> +	else {
>  		pp->function = tmp;
> 
> +		/*
> +		 * Keep pp->function even if this is absolute address,
> +		 * so it can mark whether abs_address is valid.
> +		 * Which make 'perf probe lib.bin 0x0' possible.
> +		 *
> +		 * Note that checking length of tmp is not needed
> +		 * because when we access tmp[1] we know tmp[0] is '0',
> +		 * so tmp[1] should always valid (but could be '\0').
> +		 */
> +		if (tmp && !strncmp(tmp, "0x", 2)) {
> +			pp->abs_address = strtoul(pp->function, &tmp, 0);
> +			if (*tmp != '\0') {
> +				semantic_error("Invalid absolute address.\n");
> +				return -EINVAL;
> +			}
> +		}
> +	}
> +
>  	/* Parse other options */
>  	while (ptr) {
>  		arg = ptr;
> @@ -1804,14 +1822,29 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
>  	if (len <= 0)
>  		goto error;
> 
> -	/* Uprobes must have tp->address and tp->module */
> -	if (tev->uprobes && (!tp->address || !tp->module))
> +	/* Uprobes must have tp->module */
> +	if (tev->uprobes && !tp->module)
>  		goto error;
> +	/*
> +	 * If tp->address == 0, then this point must be a
> +	 * absolute address uprobe.
> +	 * try_to_find_absolute_address() should have made
> +	 * tp->symbol to "0x0".
> +	 */
> +	if (tev->uprobes && !tp->address) {
> +		if (!tp->symbol || strcmp(tp->symbol, "0x0"))
> +			goto error;
> +	}
> 
>  	/* Use the tp->address for uprobes */
>  	if (tev->uprobes)
>  		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
>  				 tp->module, tp->address);
> +	else if (!strncmp(tp->symbol, "0x", 2))
> +		/* Absolute address. See try_to_find_absolute_address() */
> +		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx",
> +				 tp->module ?: "", tp->module ? ":" : "",
> +				 tp->address);
>  	else
>  		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
>  				 tp->module ?: "", tp->module ? ":" : "",
> @@ -1874,8 +1907,8 @@ out:
>  }
> 
>  static int convert_to_perf_probe_point(struct probe_trace_point *tp,
> -					struct perf_probe_point *pp,
> -					bool is_kprobe)
> +				       struct perf_probe_point *pp,
> +				       bool is_kprobe)
>  {
>  	char buf[128];
>  	int ret;
> @@ -2331,7 +2364,9 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
>  	if (pev->event)
>  		event = pev->event;
>  	else
> -		if (pev->point.function && !strisglob(pev->point.function))
> +		if (pev->point.function &&
> +			(strncmp(pev->point.function, "0x", 2) != 0) &&
> +			!strisglob(pev->point.function))
>  			event = pev->point.function;
>  		else
>  			event = tev->point.realname;
> @@ -2598,6 +2633,98 @@ err_out:
>  	goto out;
>  }
> 
> +static int try_to_find_absolute_address(struct perf_probe_event *pev,
> +					struct probe_trace_event **tevs)
> +{
> +	struct perf_probe_point *pp = &pev->point;
> +	struct probe_trace_event *tev;
> +	struct probe_trace_point *tp;
> +	int i, err;
> +
> +	if (!(pev->point.function && !strncmp(pev->point.function, "0x", 2)))
> +		return -EINVAL;
> +	if (perf_probe_event_need_dwarf(pev))
> +		return -EINVAL;
> +
> +	/*
> +	 * This is 'perf probe /lib/libc.so 0xabcd'. Try to probe at
> +	 * absolute address.
> +	 *
> +	 * Only one tev can be generated by this.
> +	 */
> +	*tevs = zalloc(sizeof(*tev));
> +	if (!*tevs)
> +		return -ENOMEM;
> +
> +	tev = *tevs;
> +	tp = &tev->point;
> +
> +	/*
> +	 * Don't use tp->offset, use address directly, because
> +	 * in synthesize_probe_trace_command() address cannot be
> +	 * zero.
> +	 */
> +	tp->address = pev->point.abs_address;
> +	tp->retprobe = pp->retprobe;
> +	tev->uprobes = pev->uprobes;
> +
> +	err = -ENOMEM;
> +	/*
> +	 * Give it a '0x' leading symbol name.
> +	 * In __add_probe_trace_events, a NULL symbol is interpreted as
> +	 * invalud.
> +	 */
> +	if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
> +		goto errout;
> +
> +	/* For kprobe, check range */
> +	if ((!tev->uprobes) &&
> +	    (kprobe_warn_out_range(tev->point.symbol,
> +				   tev->point.address))) {
> +		err = -EACCES;
> +		goto errout;
> +	}
> +
> +	if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0)
> +		goto errout;
> +
> +	if (pev->target) {
> +		tp->module = strdup(pev->target);
> +		if (!tp->module)
> +			goto errout;
> +	}
> +
> +	if (tev->group) {
> +		tev->group = strdup(pev->group);
> +		if (!tev->group)
> +			goto errout;
> +	}
> +
> +	if (pev->event) {
> +		tev->event = strdup(pev->event);
> +		if (!tev->event)
> +			goto errout;
> +	}
> +
> +	tev->nargs = pev->nargs;
> +	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
> +	if (!tev->args) {
> +		err = -ENOMEM;
> +		goto errout;
> +	}
> +	for (i = 0; i < tev->nargs; i++)
> +		copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]);
> +
> +	return 1;
> +
> +errout:
> +	if (*tevs) {
> +		clear_probe_trace_events(*tevs, 1);
> +		*tevs = NULL;
> +	}
> +	return err;
> +}
> +
>  bool __weak arch__prefers_symtab(void) { return false; }
> 
>  static int convert_to_probe_trace_events(struct perf_probe_event *pev,
> @@ -2614,6 +2741,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
>  		}
>  	}
> 
> +	ret = try_to_find_absolute_address(pev, tevs);
> +	if (ret > 0)
> +		return ret;
> +
>  	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
>  		ret = find_probe_trace_events_from_map(pev, tevs);
>  		if (ret > 0)
> @@ -2784,3 +2915,22 @@ end:
>  	return ret;
>  }
> 
> +int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
> +			    struct perf_probe_arg *pvar)
> +{
> +	tvar->value = strdup(pvar->var);
> +	if (tvar->value == NULL)
> +		return -ENOMEM;
> +	if (pvar->type) {
> +		tvar->type = strdup(pvar->type);
> +		if (tvar->type == NULL)
> +			return -ENOMEM;
> +	}
> +	if (pvar->name) {
> +		tvar->name = strdup(pvar->name);
> +		if (tvar->name == NULL)
> +			return -ENOMEM;
> +	} else
> +		tvar->name = NULL;
> +	return 0;
> +}
> diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
> index 83ee95e..6e7ec68 100644
> --- a/tools/perf/util/probe-event.h
> +++ b/tools/perf/util/probe-event.h
> @@ -59,6 +59,7 @@ struct perf_probe_point {
>  	bool		retprobe;	/* Return probe flag */
>  	char		*lazy_line;	/* Lazy matching pattern */
>  	unsigned long	offset;		/* Offset from function entry */
> +	unsigned long	abs_address;	/* Absolute address of the point */
>  };
> 
>  /* Perf probe probing argument field chain */
> @@ -156,4 +157,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
>  /* Maximum index number of event-name postfix */
>  #define MAX_EVENT_INDEX	1024
> 
> +int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
> +			    struct perf_probe_arg *pvar);
> +
>  #endif /*_PROBE_EVENT_H */
> diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
> index 7b80f8c..29c43c068 100644
> --- a/tools/perf/util/probe-finder.c
> +++ b/tools/perf/util/probe-finder.c
> @@ -553,24 +553,9 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
>  	char buf[32], *ptr;
>  	int ret = 0;
> 
> -	if (!is_c_varname(pf->pvar->var)) {
> -		/* Copy raw parameters */
> -		pf->tvar->value = strdup(pf->pvar->var);
> -		if (pf->tvar->value == NULL)
> -			return -ENOMEM;
> -		if (pf->pvar->type) {
> -			pf->tvar->type = strdup(pf->pvar->type);
> -			if (pf->tvar->type == NULL)
> -				return -ENOMEM;
> -		}
> -		if (pf->pvar->name) {
> -			pf->tvar->name = strdup(pf->pvar->name);
> -			if (pf->tvar->name == NULL)
> -				return -ENOMEM;
> -		} else
> -			pf->tvar->name = NULL;
> -		return 0;
> -	}
> +	/* Copy raw parameters */
> +	if (!is_c_varname(pf->pvar->var))
> +		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
> 
>  	if (pf->pvar->name)
>  		pf->tvar->name = strdup(pf->pvar->name);
> --
> 1.8.3.4

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH v3 4/6] perf probe: Fix error reported when offset without function
  2015-08-26 10:57 ` [PATCH v3 4/6] perf probe: Fix error reported when offset without function Wang Nan
@ 2015-08-26 12:21   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: 平松雅巳 / HIRAMATU,MASAMI @ 2015-08-26 12:21 UTC (permalink / raw)
  To: 'Wang Nan', acme, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, sysp-manager

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1726 bytes --]

> From: Wang Nan [mailto:wangnan0@huawei.com]
> 
> This patch fixes a bug that, when offset is provided but function is
> lost, parse_perf_probe_point() will give a "" string as function name,
> so the checking code at the end of parse_perf_probe_point() become useless.
> For example:
> 
>  # perf probe +0x1234
>  Failed to find symbol  in kernel
>    Error: Failed to add events.
> 
> After this patch:
> 
>  # perf probe +0x1234
>  Semantic error :Offset requires an entry function.
>    Error: Command Parse Error.

OK, seems sane now :)

Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Thanks!

> 
> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> ---
>  tools/perf/util/probe-event.c | 10 +++++++---
>  1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 926bcec..eaacb58 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -1194,9 +1194,13 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
>  		*ptr++ = '\0';
>  	}
> 
> -	tmp = strdup(arg);
> -	if (tmp == NULL)
> -		return -ENOMEM;
> +	if (arg[0] == '\0')
> +		tmp = NULL;
> +	else {
> +		tmp = strdup(arg);
> +		if (tmp == NULL)
> +			return -ENOMEM;
> +	}
> 
>  	if (file_spec)
>  		pp->file = tmp;
> --
> 1.8.3.4

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 18+ messages in thread

* RE: [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found Wang Nan
@ 2015-08-26 12:27   ` 平松雅巳 / HIRAMATU,MASAMI
  2015-08-28  6:41   ` [tip:perf/core] perf probe: Fix list result when symbol can' t " tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: 平松雅巳 / HIRAMATU,MASAMI @ 2015-08-26 12:27 UTC (permalink / raw)
  To: 'Wang Nan', acme, rostedt
  Cc: mingo, namhyung, pi3orama, lizefan, linux-kernel, sysp-manager

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="utf-8", Size: 1974 bytes --]

> From: Wang Nan [mailto:wangnan0@huawei.com]
> 
> 'perf probe -l' reports error if it is unable find symbol through
> address. Here is an example.
> 
>  # echo 'p:probe_libc/abs_5 /lib64/libc.so.6:0x5' >
>           /sys/kernel/debug/tracing/uprobe_events
>  # cat /sys/kernel/debug/tracing/uprobe_events
>   p:probe_libc/abs_5 /lib64/libc.so.6:0x0000000000000005
>  # perf probe -l
>    Error: Failed to show event list
> 
> Also, this situation triggers a logical inconsistency in
> convert_to_perf_probe_point() that, it returns ENOMEM but actually
> it never try strdup().
> 
> This patch removes !tp->module && !is_kprobe condition, so it
> always uses address to build function name if symbol not found.
> 
> Test result:
> 
>  # perf probe -l
>    probe_libc:abs_5     (on 0x5 in /lib64/libc.so.6)
> 

Looks good!

Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>

Thank you!

> Signed-off-by: Wang Nan <wangnan0@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Namhyung Kim <namhyung@kernel.org>
> Cc: Steven Rostedt <rostedt@goodmis.org>
> ---
>  tools/perf/util/probe-event.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 6c7e538..f7bacbb 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -1866,7 +1866,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
>  	if (tp->symbol) {
>  		pp->function = strdup(tp->symbol);
>  		pp->offset = tp->offset;
> -	} else if (!tp->module && !is_kprobe) {
> +	} else {
>  		ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
>  		if (ret < 0)
>  			return ret;
> --
> 1.8.3.4

ÿôèº{.nÇ+‰·Ÿ®‰­†+%ŠËÿ±éݶ\x17¥Šwÿº{.nÇ+‰·¥Š{±þG«éÿŠ{ayº\x1dʇڙë,j\a­¢f£¢·hšïêÿ‘êçz_è®\x03(­éšŽŠÝ¢j"ú\x1a¶^[m§ÿÿ¾\a«þG«éÿ¢¸?™¨è­Ú&£ø§~á¶iO•æ¬z·švØ^\x14\x04\x1a¶^[m§ÿÿÃ\fÿ¶ìÿ¢¸?–I¥

^ permalink raw reply	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf probe: Fix list result when symbol can' t be found
  2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found Wang Nan
  2015-08-26 12:27   ` 平松雅巳 / HIRAMATU,MASAMI
@ 2015-08-28  6:41   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot for Wang Nan @ 2015-08-28  6:41 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: lizefan, wangnan0, tglx, namhyung, linux-kernel, acme, mingo,
	masami.hiramatsu.pt, rostedt, hpa

Commit-ID:  614e2fdbd79b47ddf63a1ccd3f2343e98c3077fb
Gitweb:     http://git.kernel.org/tip/614e2fdbd79b47ddf63a1ccd3f2343e98c3077fb
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Wed, 26 Aug 2015 10:57:42 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 26 Aug 2015 10:36:04 -0300

perf probe: Fix list result when symbol can't be found

'perf probe -l' reports error if it is unable find symbol through
address. Here is an example.

  # echo 'p:probe_libc/abs_5 /lib64/libc.so.6:0x5' >
          /sys/kernel/debug/tracing/uprobe_events
  # cat /sys/kernel/debug/tracing/uprobe_events
   p:probe_libc/abs_5 /lib64/libc.so.6:0x0000000000000005
  # perf probe -l
    Error: Failed to show event list

Also, this situation triggers a logical inconsistency in
convert_to_perf_probe_point() that, it returns ENOMEM but actually it
never try strdup().

This patch removes !tp->module && !is_kprobe condition, so it always
uses address to build function name if symbol not found.

Test result:

  # perf probe -l
    probe_libc:abs_5     (on 0x5 in /lib64/libc.so.6)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1440586666-235233-4-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/probe-event.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6c7e538..f7bacbb 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1866,7 +1866,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
 	if (tp->symbol) {
 		pp->function = strdup(tp->symbol);
 		pp->offset = tp->offset;
-	} else if (!tp->module && !is_kprobe) {
+	} else {
 		ret = e_snprintf(buf, 128, "0x%" PRIx64, (u64)tp->address);
 		if (ret < 0)
 			return ret;

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf probe: Fix list result when address is zero
  2015-08-26 10:57 ` [PATCH v3 3/6] perf probe: Fix list result when address is zero Wang Nan
  2015-08-26 12:14   ` 平松雅巳 / HIRAMATU,MASAMI
@ 2015-08-28  6:42   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot for Wang Nan @ 2015-08-28  6:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, namhyung, hpa, lizefan, tglx, masami.hiramatsu.pt,
	acme, wangnan0, rostedt, mingo

Commit-ID:  be07afe92a09638db9159d2c0794487d66a437a2
Gitweb:     http://git.kernel.org/tip/be07afe92a09638db9159d2c0794487d66a437a2
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Wed, 26 Aug 2015 10:57:43 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 26 Aug 2015 10:39:20 -0300

perf probe: Fix list result when address is zero

When manually added uprobe point with zero address, 'perf probe -l'
reports error. For example:

  # echo p:probe_libc/abs_0 /path/to/lib.bin:0x0 arg1=%ax > \
           /sys/kernel/debug/tracing/uprobe_events

  # perf probe -l
  Error: Failed to show event list.

Probing at 0x0 is possible and useful when lib.bin is not a normal
shared object but is manually mapped. However, in this case kernel
report:

  # cat /sys/kernel/debug/tracing/uprobe_events
  p:probe_libc/abs_0 /path/to/lib.bin:0x          (null) arg1=%ax

This patch supports the above kernel output.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1440586666-235233-5-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/probe-event.c | 28 +++++++++++++++++++++++++---
 1 file changed, 25 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index f7bacbb..926bcec 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1519,9 +1519,31 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
 	} else
 		p = argv[1];
 	fmt1_str = strtok_r(p, "+", &fmt);
-	if (fmt1_str[0] == '0')	/* only the address started with 0x */
-		tp->address = strtoul(fmt1_str, NULL, 0);
-	else {
+	/* only the address started with 0x */
+	if (fmt1_str[0] == '0')	{
+		/*
+		 * Fix a special case:
+		 * if address == 0, kernel reports something like:
+		 * p:probe_libc/abs_0 /lib/libc-2.18.so:0x          (null) arg1=%ax
+		 * Newer kernel may fix that, but we want to
+		 * support old kernel also.
+		 */
+		if (strcmp(fmt1_str, "0x") == 0) {
+			if (!argv[2] || strcmp(argv[2], "(null)")) {
+				ret = -EINVAL;
+				goto out;
+			}
+			tp->address = 0;
+
+			free(argv[2]);
+			for (i = 2; argv[i + 1] != NULL; i++)
+				argv[i] = argv[i + 1];
+
+			argv[i] = NULL;
+			argc -= 1;
+		} else
+			tp->address = strtoul(fmt1_str, NULL, 0);
+	} else {
 		/* Only the symbol-based probe has offset */
 		tp->symbol = strdup(fmt1_str);
 		if (tp->symbol == NULL) {

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf probe: Fix error reported when offset without function
  2015-08-26 10:57 ` [PATCH v3 4/6] perf probe: Fix error reported when offset without function Wang Nan
  2015-08-26 12:21   ` 平松雅巳 / HIRAMATU,MASAMI
@ 2015-08-28  6:42   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot for Wang Nan @ 2015-08-28  6:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rostedt, wangnan0, namhyung, hpa, linux-kernel, acme, mingo,
	masami.hiramatsu.pt, tglx, lizefan

Commit-ID:  6c6e024f0a62a6a08c06002fd3caa2307cc54fd0
Gitweb:     http://git.kernel.org/tip/6c6e024f0a62a6a08c06002fd3caa2307cc54fd0
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Wed, 26 Aug 2015 10:57:44 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 26 Aug 2015 10:40:34 -0300

perf probe: Fix error reported when offset without function

This patch fixes a bug that, when offset is provided but function is
lost, parse_perf_probe_point() will give a "" string as function name,
so the checking code at the end of parse_perf_probe_point() become
useless.  For example:

  # perf probe +0x1234
  Failed to find symbol  in kernel
    Error: Failed to add events.

After this patch:

  # perf probe +0x1234
  Semantic error :Offset requires an entry function.
    Error: Command Parse Error.

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1440586666-235233-6-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/probe-event.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 926bcec..eaacb58 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1194,9 +1194,13 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 		*ptr++ = '\0';
 	}
 
-	tmp = strdup(arg);
-	if (tmp == NULL)
-		return -ENOMEM;
+	if (arg[0] == '\0')
+		tmp = NULL;
+	else {
+		tmp = strdup(arg);
+		if (tmp == NULL)
+			return -ENOMEM;
+	}
 
 	if (file_spec)
 		pp->file = tmp;

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [tip:perf/core] perf probe: Support probing at absolute address
  2015-08-26 10:57 ` [PATCH v3 5/6] perf probe: Support probing at absolute address Wang Nan
  2015-08-26 12:16   ` 平松雅巳 / HIRAMATU,MASAMI
@ 2015-08-28  6:42   ` tip-bot for Wang Nan
  1 sibling, 0 replies; 18+ messages in thread
From: tip-bot for Wang Nan @ 2015-08-28  6:42 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: wangnan0, lizefan, mingo, tglx, rostedt, linux-kernel, acme,
	namhyung, hpa, masami.hiramatsu.pt

Commit-ID:  da15bd9df4afd2f9f78cf29f85f013e3a38402b5
Gitweb:     http://git.kernel.org/tip/da15bd9df4afd2f9f78cf29f85f013e3a38402b5
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Wed, 26 Aug 2015 10:57:45 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 26 Aug 2015 10:41:12 -0300

perf probe: Support probing at absolute address

It should be useful to allow 'perf probe' probe at absolute offset of a
target. For example, when (u)probing at a instruction of a shared object
in a embedded system where debuginfo is not avaliable but we know the
offset of that instruction by manually digging.

This patch enables following perf probe command syntax:

  # perf probe 0xffffffff811e6615

And

  # perf probe /lib/x86_64-linux-gnu/libc-2.19.so 0xeb860

In the above example, we don't need a anchor symbol, so it is possible
to compute absolute addresses using other methods and then use 'perf
probe' to create the probing points.

v1 -> v2:
  Drop the leading '+' in cmdline;
  Allow uprobing at offset 0x0;
  Improve 'perf probe -l' result when uprobe at area without debuginfo.

v2 -> v3:
  Split bugfix to a separated patch.

Test result:

  # perf probe 0xffffffff8119d175 %ax
  # perf probe sys_write %ax
  # perf probe /lib64/libc-2.18.so 0x0 %ax
  # perf probe /lib64/libc-2.18.so 0x5 %ax
  # perf probe /lib64/libc-2.18.so 0xd8e40 %ax
  # perf probe /lib64/libc-2.18.so __write %ax
  # perf probe /lib64/libc-2.18.so 0xd8e49 %ax
  # cat /sys/kernel/debug/tracing/uprobe_events

  p:probe_libc/abs_0 /lib64/libc-2.18.so:0x          (null) arg1=%ax
  p:probe_libc/abs_5 /lib64/libc-2.18.so:0x0000000000000005 arg1=%ax
  p:probe_libc/abs_d8e40 /lib64/libc-2.18.so:0x00000000000d8e40 arg1=%ax
  p:probe_libc/__write /lib64/libc-2.18.so:0x00000000000d8e40 arg1=%ax
  p:probe_libc/abs_d8e49 /lib64/libc-2.18.so:0x00000000000d8e49 arg1=%ax

  # cat /sys/kernel/debug/tracing/kprobe_events

  p:probe/abs_ffffffff8119d175 0xffffffff8119d175 arg1=%ax
  p:probe/sys_write _text+1692016 arg1=%ax

  # perf probe -l

  Failed to find debug information for address 5
    probe:abs_ffffffff8119d175 (on sys_write+5 with arg1)
    probe:sys_write      (on sys_write with arg1)
    probe_libc:__write   (on @unix/syscall-template.S:81 in /lib64/libc-2.18.so with arg1)
    probe_libc:abs_0     (on 0x0 in /lib64/libc-2.18.so with arg1)
    probe_libc:abs_5     (on 0x5 in /lib64/libc-2.18.so with arg1)
    probe_libc:abs_d8e40 (on @unix/syscall-template.S:81 in /lib64/libc-2.18.so with arg1)
    probe_libc:abs_d8e49 (on __GI___libc_write+9 in /lib64/libc-2.18.so with arg1)

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1440586666-235233-7-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/probe-event.c  | 162 +++++++++++++++++++++++++++++++++++++++--
 tools/perf/util/probe-event.h  |   4 +
 tools/perf/util/probe-finder.c |  21 +-----
 3 files changed, 163 insertions(+), 24 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index eaacb58..eb5f18b 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1204,9 +1204,27 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 
 	if (file_spec)
 		pp->file = tmp;
-	else
+	else {
 		pp->function = tmp;
 
+		/*
+		 * Keep pp->function even if this is absolute address,
+		 * so it can mark whether abs_address is valid.
+		 * Which make 'perf probe lib.bin 0x0' possible.
+		 *
+		 * Note that checking length of tmp is not needed
+		 * because when we access tmp[1] we know tmp[0] is '0',
+		 * so tmp[1] should always valid (but could be '\0').
+		 */
+		if (tmp && !strncmp(tmp, "0x", 2)) {
+			pp->abs_address = strtoul(pp->function, &tmp, 0);
+			if (*tmp != '\0') {
+				semantic_error("Invalid absolute address.\n");
+				return -EINVAL;
+			}
+		}
+	}
+
 	/* Parse other options */
 	while (ptr) {
 		arg = ptr;
@@ -1804,14 +1822,29 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
 	if (len <= 0)
 		goto error;
 
-	/* Uprobes must have tp->address and tp->module */
-	if (tev->uprobes && (!tp->address || !tp->module))
+	/* Uprobes must have tp->module */
+	if (tev->uprobes && !tp->module)
 		goto error;
+	/*
+	 * If tp->address == 0, then this point must be a
+	 * absolute address uprobe.
+	 * try_to_find_absolute_address() should have made
+	 * tp->symbol to "0x0".
+	 */
+	if (tev->uprobes && !tp->address) {
+		if (!tp->symbol || strcmp(tp->symbol, "0x0"))
+			goto error;
+	}
 
 	/* Use the tp->address for uprobes */
 	if (tev->uprobes)
 		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",
 				 tp->module, tp->address);
+	else if (!strncmp(tp->symbol, "0x", 2))
+		/* Absolute address. See try_to_find_absolute_address() */
+		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx",
+				 tp->module ?: "", tp->module ? ":" : "",
+				 tp->address);
 	else
 		ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",
 				 tp->module ?: "", tp->module ? ":" : "",
@@ -1874,8 +1907,8 @@ out:
 }
 
 static int convert_to_perf_probe_point(struct probe_trace_point *tp,
-					struct perf_probe_point *pp,
-					bool is_kprobe)
+				       struct perf_probe_point *pp,
+				       bool is_kprobe)
 {
 	char buf[128];
 	int ret;
@@ -2331,7 +2364,9 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
 	if (pev->event)
 		event = pev->event;
 	else
-		if (pev->point.function && !strisglob(pev->point.function))
+		if (pev->point.function &&
+			(strncmp(pev->point.function, "0x", 2) != 0) &&
+			!strisglob(pev->point.function))
 			event = pev->point.function;
 		else
 			event = tev->point.realname;
@@ -2598,6 +2633,98 @@ err_out:
 	goto out;
 }
 
+static int try_to_find_absolute_address(struct perf_probe_event *pev,
+					struct probe_trace_event **tevs)
+{
+	struct perf_probe_point *pp = &pev->point;
+	struct probe_trace_event *tev;
+	struct probe_trace_point *tp;
+	int i, err;
+
+	if (!(pev->point.function && !strncmp(pev->point.function, "0x", 2)))
+		return -EINVAL;
+	if (perf_probe_event_need_dwarf(pev))
+		return -EINVAL;
+
+	/*
+	 * This is 'perf probe /lib/libc.so 0xabcd'. Try to probe at
+	 * absolute address.
+	 *
+	 * Only one tev can be generated by this.
+	 */
+	*tevs = zalloc(sizeof(*tev));
+	if (!*tevs)
+		return -ENOMEM;
+
+	tev = *tevs;
+	tp = &tev->point;
+
+	/*
+	 * Don't use tp->offset, use address directly, because
+	 * in synthesize_probe_trace_command() address cannot be
+	 * zero.
+	 */
+	tp->address = pev->point.abs_address;
+	tp->retprobe = pp->retprobe;
+	tev->uprobes = pev->uprobes;
+
+	err = -ENOMEM;
+	/*
+	 * Give it a '0x' leading symbol name.
+	 * In __add_probe_trace_events, a NULL symbol is interpreted as
+	 * invalud.
+	 */
+	if (asprintf(&tp->symbol, "0x%lx", tp->address) < 0)
+		goto errout;
+
+	/* For kprobe, check range */
+	if ((!tev->uprobes) &&
+	    (kprobe_warn_out_range(tev->point.symbol,
+				   tev->point.address))) {
+		err = -EACCES;
+		goto errout;
+	}
+
+	if (asprintf(&tp->realname, "abs_%lx", tp->address) < 0)
+		goto errout;
+
+	if (pev->target) {
+		tp->module = strdup(pev->target);
+		if (!tp->module)
+			goto errout;
+	}
+
+	if (tev->group) {
+		tev->group = strdup(pev->group);
+		if (!tev->group)
+			goto errout;
+	}
+
+	if (pev->event) {
+		tev->event = strdup(pev->event);
+		if (!tev->event)
+			goto errout;
+	}
+
+	tev->nargs = pev->nargs;
+	tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs);
+	if (!tev->args) {
+		err = -ENOMEM;
+		goto errout;
+	}
+	for (i = 0; i < tev->nargs; i++)
+		copy_to_probe_trace_arg(&tev->args[i], &pev->args[i]);
+
+	return 1;
+
+errout:
+	if (*tevs) {
+		clear_probe_trace_events(*tevs, 1);
+		*tevs = NULL;
+	}
+	return err;
+}
+
 bool __weak arch__prefers_symtab(void) { return false; }
 
 static int convert_to_probe_trace_events(struct perf_probe_event *pev,
@@ -2614,6 +2741,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
 		}
 	}
 
+	ret = try_to_find_absolute_address(pev, tevs);
+	if (ret > 0)
+		return ret;
+
 	if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) {
 		ret = find_probe_trace_events_from_map(pev, tevs);
 		if (ret > 0)
@@ -2784,3 +2915,22 @@ end:
 	return ret;
 }
 
+int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
+			    struct perf_probe_arg *pvar)
+{
+	tvar->value = strdup(pvar->var);
+	if (tvar->value == NULL)
+		return -ENOMEM;
+	if (pvar->type) {
+		tvar->type = strdup(pvar->type);
+		if (tvar->type == NULL)
+			return -ENOMEM;
+	}
+	if (pvar->name) {
+		tvar->name = strdup(pvar->name);
+		if (tvar->name == NULL)
+			return -ENOMEM;
+	} else
+		tvar->name = NULL;
+	return 0;
+}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 83ee95e..6e7ec68 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -59,6 +59,7 @@ struct perf_probe_point {
 	bool		retprobe;	/* Return probe flag */
 	char		*lazy_line;	/* Lazy matching pattern */
 	unsigned long	offset;		/* Offset from function entry */
+	unsigned long	abs_address;	/* Absolute address of the point */
 };
 
 /* Perf probe probing argument field chain */
@@ -156,4 +157,7 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
 /* Maximum index number of event-name postfix */
 #define MAX_EVENT_INDEX	1024
 
+int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
+			    struct perf_probe_arg *pvar);
+
 #endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 7b80f8c..29c43c068 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -553,24 +553,9 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
 	char buf[32], *ptr;
 	int ret = 0;
 
-	if (!is_c_varname(pf->pvar->var)) {
-		/* Copy raw parameters */
-		pf->tvar->value = strdup(pf->pvar->var);
-		if (pf->tvar->value == NULL)
-			return -ENOMEM;
-		if (pf->pvar->type) {
-			pf->tvar->type = strdup(pf->pvar->type);
-			if (pf->tvar->type == NULL)
-				return -ENOMEM;
-		}
-		if (pf->pvar->name) {
-			pf->tvar->name = strdup(pf->pvar->name);
-			if (pf->tvar->name == NULL)
-				return -ENOMEM;
-		} else
-			pf->tvar->name = NULL;
-		return 0;
-	}
+	/* Copy raw parameters */
+	if (!is_c_varname(pf->pvar->var))
+		return copy_to_probe_trace_arg(pf->tvar, pf->pvar);
 
 	if (pf->pvar->name)
 		pf->tvar->name = strdup(pf->pvar->name);

^ permalink raw reply related	[flat|nested] 18+ messages in thread

* [tip:perf/core] tracing/uprobes: Do not print '0x (null)' when offset is 0
  2015-08-26 10:57 ` [PATCH v3 6/6] tracing/uprobes: Do not print '0x (null)' when offset is 0 Wang Nan
@ 2015-08-28  6:43   ` tip-bot for Wang Nan
  0 siblings, 0 replies; 18+ messages in thread
From: tip-bot for Wang Nan @ 2015-08-28  6:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: rostedt, wangnan0, linux-kernel, namhyung, lizefan, mingo, tglx,
	acme, hpa, masami.hiramatsu.pt

Commit-ID:  a2fb3382edbea83c6f2bf6ac15e3673b2e254aad
Gitweb:     http://git.kernel.org/tip/a2fb3382edbea83c6f2bf6ac15e3673b2e254aad
Author:     Wang Nan <wangnan0@huawei.com>
AuthorDate: Wed, 26 Aug 2015 10:57:46 +0000
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 26 Aug 2015 10:43:01 -0300

tracing/uprobes: Do not print '0x (null)' when offset is 0

When manually added uprobe point with zero address, 'uprobe_events'
output '(null)' instead of 0x00000000:

  # echo p:probe_libc/abs_0 /path/to/lib.bin:0x0 arg1=%ax > \
            /sys/kernel/debug/tracing/uprobe_events

  # cat /sys/kernel/debug/tracing/uprobe_events
    p:probe_libc/abs_0 /path/to/lib.bin:0x          (null) arg1=%ax

 This patch fixes this behavior:

  # cat /sys/kernel/debug/tracing/uprobe_events
  p:probe_libc/abs_0 /path/to/lib.bin:0x0000000000000000

Signed-off-by: Wang Nan <wangnan0@huawei.com>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Zefan Li <lizefan@huawei.com>
Cc: pi3orama@163.com
Link: http://lkml.kernel.org/r/1440586666-235233-8-git-send-email-wangnan0@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 kernel/trace/trace_uprobe.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index f97479f..d2f6d0b 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -601,7 +601,22 @@ static int probes_seq_show(struct seq_file *m, void *v)
 
 	seq_printf(m, "%c:%s/%s", c, tu->tp.call.class->system,
 			trace_event_name(&tu->tp.call));
-	seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset);
+	seq_printf(m, " %s:", tu->filename);
+
+	/* Don't print "0x  (null)" when offset is 0 */
+	if (tu->offset) {
+		seq_printf(m, "0x%p", (void *)tu->offset);
+	} else {
+		switch (sizeof(void *)) {
+		case 4:
+			seq_printf(m, "0x00000000");
+			break;
+		case 8:
+		default:
+			seq_printf(m, "0x0000000000000000");
+			break;
+		}
+	}
 
 	for (i = 0; i < tu->tp.nr_args; i++)
 		seq_printf(m, " %s=%s", tu->tp.args[i].name, tu->tp.args[i].comm);

^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2015-08-28  6:43 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-26 10:57 [PATCH v3 0/6] perf probe, tracing/uprobes: Support probing at absolute address Wang Nan
2015-08-26 10:57 ` [PATCH v3 1/6] perf probe: Prevent segfault when reading probe point with " Wang Nan
2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when neither dwarf nor map can't find symbol Wang Nan
2015-08-26 11:03   ` Wangnan (F)
2015-08-26 10:57 ` [PATCH v3 2/6] perf probe: Fix list result when symbol can't be found Wang Nan
2015-08-26 12:27   ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-28  6:41   ` [tip:perf/core] perf probe: Fix list result when symbol can' t " tip-bot for Wang Nan
2015-08-26 10:57 ` [PATCH v3 3/6] perf probe: Fix list result when address is zero Wang Nan
2015-08-26 12:14   ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
2015-08-26 10:57 ` [PATCH v3 4/6] perf probe: Fix error reported when offset without function Wang Nan
2015-08-26 12:21   ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
2015-08-26 10:57 ` [PATCH v3 5/6] perf probe: Support probing at absolute address Wang Nan
2015-08-26 12:16   ` 平松雅巳 / HIRAMATU,MASAMI
2015-08-28  6:42   ` [tip:perf/core] " tip-bot for Wang Nan
2015-08-26 10:57 ` [PATCH v3 6/6] tracing/uprobes: Do not print '0x (null)' when offset is 0 Wang Nan
2015-08-28  6:43   ` [tip:perf/core] " tip-bot for Wang Nan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).