All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] perf: add support of SDT probes arguments
@ 2016-11-16 23:55 Alexis Berlemont
  2016-11-16 23:56 ` [PATCH 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
  2016-11-16 23:56 ` [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  0 siblings, 2 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-16 23:55 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin

Hi,

In the perf todo list (https://perf.wiki.kernel.org/index.php/Todo),
there is an entry related with SDT markers support; SDT tracepoints
were already supported by perf but, so far, the probes arguments are
skipped. Here are 2 small patches which adds support of SDT probes
arguments:

$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

The patches were generated against tip/perf/core.

Alexis.

Alexis Berlemont (2):
  perf sdt: add scanning of sdt probles arguments
  perf probe: add sdt probes arguments into the uprobe cmd string

 tools/perf/util/probe-file.c | 176 ++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/symbol-elf.c |  16 +++-
 tools/perf/util/symbol.h     |   1 +
 3 files changed, 188 insertions(+), 5 deletions(-)

-- 
2.10.2

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

* [PATCH 1/2] perf sdt: add scanning of sdt probles arguments
  2016-11-16 23:55 [PATCH 0/2] perf: add support of SDT probes arguments Alexis Berlemont
@ 2016-11-16 23:56 ` Alexis Berlemont
  2016-11-16 23:56 ` [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  1 sibling, 0 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-16 23:56 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin

During a "perf buildid-cache --add" command, the section
".note.stapsdt" of the "added" binary is scanned in order to list the
available SDT markers available in a binary. The parts containing the
probes arguments were left unscanned.

The whole section is now parsed; the probe arguments are extracted for
later use.

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/util/symbol-elf.c | 16 +++++++++++++++-
 tools/perf/util/symbol.h     |  1 +
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 99400b0..0fbe0b2 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 			     struct list_head *sdt_notes)
 {
-	const char *provider, *name;
+	const char *provider, *name, *args;
 	struct sdt_note *tmp = NULL;
 	GElf_Ehdr ehdr;
 	GElf_Addr base_off = 0;
@@ -1881,6 +1881,20 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 		goto out_free_prov;
 	}
 
+	args = (const char *)memchr(name, '\0', data + len - name);
+
+	/*
+	 * There is no argument if:
+	 * - We reached the end of the note;
+	 * - There is not enough room to hold a potential string;
+	 * - The argument string is empty or just contains ':'.
+	 */
+	if (args == NULL || data + len - args < 2 ||
+		args[1] == ':' || args[1] == '\0')
+		tmp->args = NULL;
+	else
+		tmp->args = strdup(++args);
+
 	if (gelf_getclass(*elf) == ELFCLASS32) {
 		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
 		tmp->bit32 = true;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 2d0a905..913be07 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -347,6 +347,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 struct sdt_note {
 	char *name;			/* name of the note*/
 	char *provider;			/* provider name */
+	char *args;
 	bool bit32;			/* whether the location is 32 bits? */
 	union {				/* location, base and semaphore addrs */
 		Elf64_Addr a64[3];
-- 
2.10.2

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

* [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-16 23:55 [PATCH 0/2] perf: add support of SDT probes arguments Alexis Berlemont
  2016-11-16 23:56 ` [PATCH 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-11-16 23:56 ` Alexis Berlemont
  2016-11-17  9:04   ` Hemant Kumar
  1 sibling, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-16 23:56 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

$ perf buildid-cache -v --add test_sdt
$ perf probe -x test_sdt sdt_libfoo:table_frob
$ perf probe -x test_sdt sdt_libfoo:table_diddle
$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/util/probe-file.c | 176 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 172 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..a97a170 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -28,6 +28,46 @@
 #include "probe-file.h"
 #include "session.h"
 
+#ifdef HAVE_GELF_GETNOTE_SUPPORT
+
+/*
+ * Local declarations needed for adjusting gcc/gas-generated registers
+ * before filling the uprobe tracer interface.
+ */
+
+struct sdt_reg_renaming {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+
+#define REG_RENAMING(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define REG_RENAMING_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+static const struct sdt_reg_renaming sdt_reg_renaming_table[] = {
+	REG_RENAMING(eax, ax),
+	REG_RENAMING(rax, ax),
+	REG_RENAMING(ebx, bx),
+	REG_RENAMING(rbx, bx),
+	REG_RENAMING(ecx, cx),
+	REG_RENAMING(rcx, cx),
+	REG_RENAMING(edx, dx),
+	REG_RENAMING(rdx, dx),
+	REG_RENAMING(esi, si),
+	REG_RENAMING(rsi, si),
+	REG_RENAMING(edi, di),
+	REG_RENAMING(rdi, di),
+	REG_RENAMING(ebp, bp),
+	REG_RENAMING(rbp, bp),
+	REG_RENAMING_END,
+};
+
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+#endif /* HAVE_GELF_GETNOTE_SUPPORT */
+
 #define MAX_CMDLEN 256
 
 static void print_open_warning(int err, bool uprobe)
@@ -687,6 +727,133 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	const struct sdt_reg_renaming *rnames;
+	char *tmp, *desc = strdup(arg);
+	const char *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("SDT argument format not supported\n");
+		goto out;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		if (type_idx == LONG_MIN ||
+			type_idx == LONG_MAX) {
+			pr_debug4("Failed to get sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below performs all the needed renamings if needed.
+	 */
+
+	for (rnames = sdt_reg_renaming_table;
+	     rnames->sdt_name != NULL; rnames++) {
+		char *new_desc, *sdt_name;
+		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
+
+		sdt_name = strstr(desc, rnames->sdt_name);
+		if (sdt_name == NULL)
+			continue;
+
+		new_desc = zalloc(strlen(desc) + 1 +
+				strlen(rnames->uprobe_name) -
+				strlen(rnames->sdt_name));
+		if (new_desc == NULL)
+			goto error;
+
+		prefix_len = sdt_name - desc;
+		if (prefix_len != 0)
+			memcpy(new_desc, desc, prefix_len);
+
+		uprobe_len = strlen(rnames->uprobe_name);
+		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+		mid_ofs = prefix_len + strlen(rnames->sdt_name);
+		desc_len = strlen(desc);
+		if (mid_ofs < desc_len)
+			memcpy(new_desc + prefix_len + uprobe_len,
+				desc + mid_ofs, desc_len - mid_ofs);
+
+		free(desc);
+		desc = new_desc;
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s", i, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -723,11 +890,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;
-- 
2.10.2

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

* Re: [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-16 23:56 ` [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
@ 2016-11-17  9:04   ` Hemant Kumar
  2016-11-18 23:56     ` [PATCH v2 0/2] " Alexis Berlemont
                       ` (2 more replies)
  0 siblings, 3 replies; 77+ messages in thread
From: Hemant Kumar @ 2016-11-17  9:04 UTC (permalink / raw)
  To: Alexis Berlemont, linux-kernel; +Cc: peterz, mingo, acme, alexander.shishkin

Hi Alexis,

On 11/17/2016 05:26 AM, Alexis Berlemont wrote:
> An sdt probe can be associated with arguments but they were not passed
> to the user probe tracing interface (uprobe_events); this patch adapts
> the sdt argument descriptors according to the uprobe input format.
>
> As the uprobe parser does not support scaled address mode, perf will
> skip arguments which cannot be adapted to the uprobe format.
>
> Here are the results:
>
> $ perf buildid-cache -v --add test_sdt
> $ perf probe -x test_sdt sdt_libfoo:table_frob
> $ perf probe -x test_sdt sdt_libfoo:table_diddle
> $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> $ perf script
> test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Cool! Thanks for working on this.

I have a comment below.

> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>   tools/perf/util/probe-file.c | 176 ++++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 172 insertions(+), 4 deletions(-)
>
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 436b647..a97a170 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -28,6 +28,46 @@
>   #include "probe-file.h"
>   #include "session.h"
>   
> +#ifdef HAVE_GELF_GETNOTE_SUPPORT
> +
> +/*
> + * Local declarations needed for adjusting gcc/gas-generated registers
> + * before filling the uprobe tracer interface.
> + */
> +
> +struct sdt_reg_renaming {
> +	const char *sdt_name;
> +	const char *uprobe_name;
> +};
> +
> +#define REG_RENAMING(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> +#define REG_RENAMING_END {.sdt_name = NULL, .uprobe_name = NULL}
> +
> +static const struct sdt_reg_renaming sdt_reg_renaming_table[] = {
> +	REG_RENAMING(eax, ax),
> +	REG_RENAMING(rax, ax),
> +	REG_RENAMING(ebx, bx),
> +	REG_RENAMING(rbx, bx),
> +	REG_RENAMING(ecx, cx),
> +	REG_RENAMING(rcx, cx),
> +	REG_RENAMING(edx, dx),
> +	REG_RENAMING(rdx, dx),
> +	REG_RENAMING(esi, si),
> +	REG_RENAMING(rsi, si),
> +	REG_RENAMING(edi, di),
> +	REG_RENAMING(rdi, di),
> +	REG_RENAMING(ebp, bp),
> +	REG_RENAMING(rbp, bp),
> +	REG_RENAMING_END,
> +};

Please put the above in arch helper headers for x86, as these register 
names and their conversions are specific to x86.

[SNIP]

--
Thanks,
Hemant Kumar

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

* [PATCH v2 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-17  9:04   ` Hemant Kumar
@ 2016-11-18 23:56     ` Alexis Berlemont
  2016-11-18 23:56     ` [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
  2016-11-18 23:56     ` [PATCH v2 2/2] perf probe: add " Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-18 23:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

Hi Hemant,

Many thanks for your answer.

Here is another proposal in which the x86 register renaming table has
been moved into the x86-specific part.

Thanks,

Alexis.

Alexis Berlemont (2):
  perf sdt: add scanning of sdt probles arguments
  perf probe: add sdt probes arguments into the uprobe cmd string

 tools/perf/arch/x86/util/perf_regs.c |  18 +++++
 tools/perf/util/perf_regs.c          |   4 +
 tools/perf/util/perf_regs.h          |  13 ++++
 tools/perf/util/probe-file.c         | 141 ++++++++++++++++++++++++++++++++++-
 tools/perf/util/symbol-elf.c         |  16 +++-
 tools/perf/util/symbol.h             |   1 +
 6 files changed, 188 insertions(+), 5 deletions(-)

-- 
2.10.2

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

* [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments
  2016-11-17  9:04   ` Hemant Kumar
  2016-11-18 23:56     ` [PATCH v2 0/2] " Alexis Berlemont
@ 2016-11-18 23:56     ` Alexis Berlemont
  2016-11-25 14:40       ` Arnaldo Carvalho de Melo
  2016-11-18 23:56     ` [PATCH v2 2/2] perf probe: add " Alexis Berlemont
  2 siblings, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-18 23:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

During a "perf buildid-cache --add" command, the section
".note.stapsdt" of the "added" binary is scanned in order to list the
available SDT markers available in a binary. The parts containing the
probes arguments were left unscanned.

The whole section is now parsed; the probe arguments are extracted for
later use.

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/util/symbol-elf.c | 16 +++++++++++++++-
 tools/perf/util/symbol.h     |  1 +
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 99400b0..0fbe0b2 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 			     struct list_head *sdt_notes)
 {
-	const char *provider, *name;
+	const char *provider, *name, *args;
 	struct sdt_note *tmp = NULL;
 	GElf_Ehdr ehdr;
 	GElf_Addr base_off = 0;
@@ -1881,6 +1881,20 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 		goto out_free_prov;
 	}
 
+	args = (const char *)memchr(name, '\0', data + len - name);
+
+	/*
+	 * There is no argument if:
+	 * - We reached the end of the note;
+	 * - There is not enough room to hold a potential string;
+	 * - The argument string is empty or just contains ':'.
+	 */
+	if (args == NULL || data + len - args < 2 ||
+		args[1] == ':' || args[1] == '\0')
+		tmp->args = NULL;
+	else
+		tmp->args = strdup(++args);
+
 	if (gelf_getclass(*elf) == ELFCLASS32) {
 		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
 		tmp->bit32 = true;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 2d0a905..913be07 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -347,6 +347,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 struct sdt_note {
 	char *name;			/* name of the note*/
 	char *provider;			/* provider name */
+	char *args;
 	bool bit32;			/* whether the location is 32 bits? */
 	union {				/* location, base and semaphore addrs */
 		Elf64_Addr a64[3];
-- 
2.10.2

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

* [PATCH v2 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-17  9:04   ` Hemant Kumar
  2016-11-18 23:56     ` [PATCH v2 0/2] " Alexis Berlemont
  2016-11-18 23:56     ` [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-11-18 23:56     ` Alexis Berlemont
  2016-11-21 10:25       ` Hemant Kumar
  2 siblings, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-18 23:56 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

$ perf buildid-cache -v --add test_sdt
$ perf probe -x test_sdt sdt_libfoo:table_frob
$ perf probe -x test_sdt sdt_libfoo:table_diddle
$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  18 +++++
 tools/perf/util/perf_regs.c          |   4 +
 tools/perf/util/perf_regs.h          |  13 ++++
 tools/perf/util/probe-file.c         | 141 ++++++++++++++++++++++++++++++++++-
 4 files changed, 172 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f..52a1e65 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
 	SMPL_REG_END
 };
+
+const struct sdt_name_reg sdt_reg_renamings[] = {
+	SDT_NAME_REG(eax, ax),
+	SDT_NAME_REG(rax, ax),
+	SDT_NAME_REG(ebx, bx),
+	SDT_NAME_REG(rbx, bx),
+	SDT_NAME_REG(ecx, cx),
+	SDT_NAME_REG(rcx, cx),
+	SDT_NAME_REG(edx, dx),
+	SDT_NAME_REG(rdx, dx),
+	SDT_NAME_REG(esi, si),
+	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(edi, di),
+	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(ebp, bp),
+	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG_END,
+};
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f2..1c21150 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
+const struct sdt_name_reg __weak sdt_reg_renamings[] = {
+	SDT_NAME_REG_END,
+};
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e4..41815ca 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,19 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+struct sdt_name_reg {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+extern const struct sdt_name_reg sdt_reg_renamings[];
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..587763d 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
 
 #define MAX_CMDLEN 256
 
@@ -687,6 +688,137 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	const struct sdt_name_reg *rnames;
+	char *tmp, *desc = strdup(arg);
+	const char *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("SDT argument format not supported\n");
+		goto out;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		if (type_idx == LONG_MIN ||
+			type_idx == LONG_MAX) {
+			pr_debug4("Failed to get sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below performs all the needed renamings if needed.
+	 */
+
+	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
+		char *new_desc, *sdt_name;
+		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
+
+		sdt_name = strstr(desc, rnames->sdt_name);
+		if (sdt_name == NULL)
+			continue;
+
+		new_desc = zalloc(strlen(desc) + 1 +
+				strlen(rnames->uprobe_name) -
+				strlen(rnames->sdt_name));
+		if (new_desc == NULL)
+			goto error;
+
+		prefix_len = sdt_name - desc;
+		if (prefix_len != 0)
+			memcpy(new_desc, desc, prefix_len);
+
+		uprobe_len = strlen(rnames->uprobe_name);
+		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+		mid_ofs = prefix_len + strlen(rnames->sdt_name);
+		desc_len = strlen(desc);
+		if (mid_ofs < desc_len)
+			memcpy(new_desc + prefix_len + uprobe_len,
+				desc + mid_ofs, desc_len - mid_ofs);
+
+		free(desc);
+		desc = new_desc;
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s", i, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -723,11 +855,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;
-- 
2.10.2

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

* Re: [PATCH v2 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-18 23:56     ` [PATCH v2 2/2] perf probe: add " Alexis Berlemont
@ 2016-11-21 10:25       ` Hemant Kumar
  2016-11-24 23:13         ` [PATCH v3 0/2] " Alexis Berlemont
                           ` (2 more replies)
  0 siblings, 3 replies; 77+ messages in thread
From: Hemant Kumar @ 2016-11-21 10:25 UTC (permalink / raw)
  To: Alexis Berlemont, linux-kernel; +Cc: peterz, mingo, acme, alexander.shishkin

Hi Alexis,

On 11/19/2016 05:26 AM, Alexis Berlemont wrote:
> An sdt probe can be associated with arguments but they were not passed
> to the user probe tracing interface (uprobe_events); this patch adapts
> the sdt argument descriptors according to the uprobe input format.
>
> As the uprobe parser does not support scaled address mode, perf will
> skip arguments which cannot be adapted to the uprobe format.
>
> Here are the results:
>
> $ perf buildid-cache -v --add test_sdt
> $ perf probe -x test_sdt sdt_libfoo:table_frob

Working for some binaries and not working for others. On some digging, I 
think, this patchset doesn't take care of the offset sign. So, when we 
try to probe with these patches applied :

# ./perf probe -x /lib64/libpthread.so.0 sdt_libpthread:pthread_start

Failed to write event: Invalid argument
   Error: Failed to add events.

With -v, the string to be written in uprobe_events is shown as :
...
Writing event: p:sdt_libpthread/pthread_start 
/usr/lib64/libpthread-2.23.so:0x75b8 arg0=%ax:u64 arg1=1600(%ax):u64 
arg2=1608(%ax):u64
...

The offsets mentioned in the string, for e.g., arg1=1600(%ax):u64 (to be 
written into the uprobe_events file don't have any sign. That is the 
issue here, i.e, we need to have a sign before the offsets.

This works fine :

# echo "p:sdt_libpthread/pthread_start 
/usr/lib64/libpthread-2.23.so:0x75b8 arg0=%ax:u64 arg1=+1600(%ax):u64 
arg2=+1608(%ax):u64" > /sys/kernel/debug/tracing/uprobe_events

For the negative offsets, i.e., '-' sign before the offsets, this works 
fine because, it takes the sign as is.

So, we need to explicitly mention the offset sign.

--
Thanks,
Hemant Kumar

> $ perf probe -x test_sdt sdt_libfoo:table_diddle
> $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> $ perf script
> test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8
>
> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>   tools/perf/arch/x86/util/perf_regs.c |  18 +++++
>   tools/perf/util/perf_regs.c          |   4 +
>   tools/perf/util/perf_regs.h          |  13 ++++
>   tools/perf/util/probe-file.c         | 141 ++++++++++++++++++++++++++++++++++-
>   4 files changed, 172 insertions(+), 4 deletions(-)
>
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index c5db14f..52a1e65 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
>   #endif
>   	SMPL_REG_END
>   };
> +
> +const struct sdt_name_reg sdt_reg_renamings[] = {
> +	SDT_NAME_REG(eax, ax),
> +	SDT_NAME_REG(rax, ax),
> +	SDT_NAME_REG(ebx, bx),
> +	SDT_NAME_REG(rbx, bx),
> +	SDT_NAME_REG(ecx, cx),
> +	SDT_NAME_REG(rcx, cx),
> +	SDT_NAME_REG(edx, dx),
> +	SDT_NAME_REG(rdx, dx),
> +	SDT_NAME_REG(esi, si),
> +	SDT_NAME_REG(rsi, si),
> +	SDT_NAME_REG(edi, di),
> +	SDT_NAME_REG(rdi, di),
> +	SDT_NAME_REG(ebp, bp),
> +	SDT_NAME_REG(rbp, bp),
> +	SDT_NAME_REG_END,
> +};
> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index c4023f2..1c21150 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
>   	SMPL_REG_END
>   };
>
> +const struct sdt_name_reg __weak sdt_reg_renamings[] = {
> +	SDT_NAME_REG_END,
> +};
> +
>   #ifdef HAVE_PERF_REGS_SUPPORT
>   int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
>   {
> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index 679d6e4..41815ca 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -15,6 +15,19 @@ struct sample_reg {
>
>   extern const struct sample_reg sample_reg_masks[];
>
> +struct sdt_name_reg {
> +	const char *sdt_name;
> +	const char *uprobe_name;
> +};
> +#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> +#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
> +
> +/*
> + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> + * registers before filling the uprobe tracer interface.
> + */
> +extern const struct sdt_name_reg sdt_reg_renamings[];
> +
>   #ifdef HAVE_PERF_REGS_SUPPORT
>   #include <perf_regs.h>
>
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 436b647..587763d 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -27,6 +27,7 @@
>   #include "probe-event.h"
>   #include "probe-file.h"
>   #include "session.h"
> +#include "perf_regs.h"
>
>   #define MAX_CMDLEN 256
>
> @@ -687,6 +688,137 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
>   		 : (unsigned long long)note->addr.a64[0];
>   }
>
> +static const char * const type_to_suffix[] = {
> +	":s64", "", "", "", ":s32", "", ":s16", ":s8",
> +	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
> +};
> +
> +static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
> +{
> +	const struct sdt_name_reg *rnames;
> +	char *tmp, *desc = strdup(arg);
> +	const char *suffix = "";
> +	int ret = -1;
> +
> +	if (desc == NULL) {
> +		pr_debug4("Allocation error\n");
> +		return ret;
> +	}
> +
> +	/*
> +	 * The uprobe tracer format does not support all the
> +	 * addressing modes (notably: in x86 the scaled mode); so, we
> +	 * detect ',' characters, if there is just one, there is no
> +	 * use converting the sdt arg into a uprobe one.
> +	 */
> +	if (strchr(desc, ',')) {
> +		pr_debug4("SDT argument format not supported\n");
> +		goto out;
> +	}
> +
> +	tmp = strchr(desc, '@');
> +	if (tmp) {
> +		long type_idx;
> +		/*
> +		 * Isolate the string number and convert it into a
> +		 * binary value; this will be an index to get suffix
> +		 * of the uprobe name (defining the type)
> +		 */
> +		tmp[0] = '\0';
> +		type_idx = strtol(desc, NULL, 10);
> +		if (type_idx == LONG_MIN ||
> +			type_idx == LONG_MAX) {
> +			pr_debug4("Failed to get sdt type\n");
> +			goto error;
> +		}
> +		suffix = type_to_suffix[type_idx + 8];
> +		/* Get rid of the sdt prefix which is now useless */
> +		tmp++;
> +		memmove(desc, tmp, strlen(tmp) + 1);
> +	}
> +
> +	/*
> +	 * The uprobe parser does not support all gas register names;
> +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> +	 * the loop below performs all the needed renamings if needed.
> +	 */
> +
> +	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
> +		char *new_desc, *sdt_name;
> +		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
> +
> +		sdt_name = strstr(desc, rnames->sdt_name);
> +		if (sdt_name == NULL)
> +			continue;
> +
> +		new_desc = zalloc(strlen(desc) + 1 +
> +				strlen(rnames->uprobe_name) -
> +				strlen(rnames->sdt_name));
> +		if (new_desc == NULL)
> +			goto error;
> +
> +		prefix_len = sdt_name - desc;
> +		if (prefix_len != 0)
> +			memcpy(new_desc, desc, prefix_len);
> +
> +		uprobe_len = strlen(rnames->uprobe_name);
> +		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
> +
> +		mid_ofs = prefix_len + strlen(rnames->sdt_name);
> +		desc_len = strlen(desc);
> +		if (mid_ofs < desc_len)
> +			memcpy(new_desc + prefix_len + uprobe_len,
> +				desc + mid_ofs, desc_len - mid_ofs);
> +
> +		free(desc);
> +		desc = new_desc;
> +	}
> +
> +	if (strbuf_addf(buf, " arg%d=%s%s", i, desc, suffix) < 0)
> +		goto error;
> +
> +out:
> +	ret = 0;
> +error:
> +	free(desc);
> +	return ret;
> +}
> +
> +static char *synthesize_sdt_probe_command(struct sdt_note *note,
> +					const char *pathname,
> +					const char *sdtgrp)
> +{
> +	struct strbuf buf;
> +	char *ret = NULL, **args;
> +	int i, args_count;
> +
> +	if (strbuf_init(&buf, 32) < 0)
> +		return NULL;
> +
> +	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
> +				sdtgrp, note->name, pathname,
> +				sdt_note__get_addr(note)) < 0)
> +		goto error;
> +
> +	if (!note->args)
> +		goto out;
> +
> +	if (note->args) {
> +		args = argv_split(note->args, &args_count);
> +
> +		for (i = 0; i < args_count; ++i) {
> +			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
> +				goto error;
> +		}
> +	}
> +
> +out:
> +	ret = strbuf_detach(&buf, NULL);
> +error:
> +	strbuf_release(&buf);
> +	return ret;
> +}
> +
>   int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>   {
>   	struct probe_cache_entry *entry = NULL;
> @@ -723,11 +855,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>   			entry->pev.group = strdup(sdtgrp);
>   			list_add_tail(&entry->node, &pcache->entries);
>   		}
> -		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> -				sdtgrp, note->name, pathname,
> -				sdt_note__get_addr(note));
> -		if (ret < 0)
> +		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
> +		if (!buf) {
> +			ret = -ENOMEM;
>   			break;
> +		}
> +
>   		strlist__add(entry->tevlist, buf);
>   		free(buf);
>   		entry = NULL;

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

* [PATCH v3 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-21 10:25       ` Hemant Kumar
@ 2016-11-24 23:13         ` Alexis Berlemont
  2016-11-24 23:13         ` [PATCH v3 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
  2016-11-24 23:13         ` [PATCH v3 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-24 23:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

Hi Hemant,

Once more thank you for your answer.

Sorry for this bug: I tested the patches only on small sample
binaries. Now it is tested against the systemtap-enabled libraries
libc and libpthread. There were 2 problems:

* The one you disclosed: in indirect addressing mode, positive offsets
  not prefixed with a '+' character;
* Another one still in indirect addressing mode: offsets which were
  not constants but symbols;

The following patches solves them both.

# cat /sys/kernel/tracing/uprobe_events
p:sdt_libpthread/pthread_start /lib/libpthread-2.23.so:0x0000000000007448 arg0=%ax:u64 arg1=+1600(%ax):u64 arg2=+1608(%ax):u64
p:sdt_libpthread/pthread_create /lib/libpthread-2.23.so:0x0000000000007be9 arg0=%ax:u64 arg1=-184(%bp):u64 arg2=-160(%bp):u64 arg3=-168(%bp):u64
p:sdt_libpthread/pthread_join /lib/libpthread-2.23.so:0x000000000000864d arg0=%di:u64
p:sdt_libpthread/pthread_join_ret /lib/libpthread-2.23.so:0x00000000000086fe arg0=%bx:u64 arg1=%ax:s32 arg2=+1584(%bx):u64
p:sdt_libpthread/mutex_init /lib/libpthread-2.23.so:0x000000000000938b arg0=%di:u64
p:sdt_libpthread/mutex_destroy /lib/libpthread-2.23.so:0x0000000000009410 arg0=%di:u64
p:sdt_libpthread/mutex_acquired /lib/libpthread-2.23.so:0x0000000000009685 arg0=%bx:u64
p:sdt_libpthread/mutex_acquired_1 /lib/libpthread-2.23.so:0x0000000000009b31 arg0=%r8:u64
...

# cat /sys/kernel/tracing/uprobe_events
p:sdt_libc/setjmp /lib/libc-2.23.so:0x0000000000033181 arg0=%di:u64 arg1=%si:s32 arg2=%ax:u64
p:sdt_libc/longjmp /lib/libc-2.23.so:0x0000000000033263 arg0=%di:u64 arg1=%si:s32 arg2=%dx:u64
p:sdt_libc/longjmp_1 /lib/libc-2.23.so:0x00000000000f7fc3 arg0=%di:u64 arg1=%si:s32 arg2=%dx:u64
p:sdt_libc/longjmp_target /lib/libc-2.23.so:0x000000000003327f arg0=%di:u64 arg1=%ax:s32 arg2=%dx:u64
p:sdt_libc/longjmp_target_1 /lib/libc-2.23.so:0x00000000000f7fdf arg0=%di:u64 arg1=%ax:s32 arg2=%dx:u64
...

Thanks,

Alexis.


Alexis Berlemont (2):
  perf sdt: add scanning of sdt probles arguments
  perf probe: add sdt probes arguments into the uprobe cmd string

 tools/perf/arch/x86/util/perf_regs.c |  18 ++++
 tools/perf/util/perf_regs.c          |   4 +
 tools/perf/util/perf_regs.h          |  13 +++
 tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
 tools/perf/util/symbol-elf.c         |  16 +++-
 tools/perf/util/symbol.h             |   1 +
 6 files changed, 216 insertions(+), 5 deletions(-)

-- 
2.10.2

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

* [PATCH v3 1/2] perf sdt: add scanning of sdt probles arguments
  2016-11-21 10:25       ` Hemant Kumar
  2016-11-24 23:13         ` [PATCH v3 0/2] " Alexis Berlemont
@ 2016-11-24 23:13         ` Alexis Berlemont
  2016-11-24 23:13         ` [PATCH v3 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-24 23:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

During a "perf buildid-cache --add" command, the section
".note.stapsdt" of the "added" binary is scanned in order to list the
available SDT markers available in a binary. The parts containing the
probes arguments were left unscanned.

The whole section is now parsed; the probe arguments are extracted for
later use.

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/util/symbol-elf.c | 16 +++++++++++++++-
 tools/perf/util/symbol.h     |  1 +
 2 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 99400b0..0fbe0b2 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 			     struct list_head *sdt_notes)
 {
-	const char *provider, *name;
+	const char *provider, *name, *args;
 	struct sdt_note *tmp = NULL;
 	GElf_Ehdr ehdr;
 	GElf_Addr base_off = 0;
@@ -1881,6 +1881,20 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 		goto out_free_prov;
 	}
 
+	args = (const char *)memchr(name, '\0', data + len - name);
+
+	/*
+	 * There is no argument if:
+	 * - We reached the end of the note;
+	 * - There is not enough room to hold a potential string;
+	 * - The argument string is empty or just contains ':'.
+	 */
+	if (args == NULL || data + len - args < 2 ||
+		args[1] == ':' || args[1] == '\0')
+		tmp->args = NULL;
+	else
+		tmp->args = strdup(++args);
+
 	if (gelf_getclass(*elf) == ELFCLASS32) {
 		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
 		tmp->bit32 = true;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 2d0a905..913be07 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -347,6 +347,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 struct sdt_note {
 	char *name;			/* name of the note*/
 	char *provider;			/* provider name */
+	char *args;
 	bool bit32;			/* whether the location is 32 bits? */
 	union {				/* location, base and semaphore addrs */
 		Elf64_Addr a64[3];
-- 
2.10.2

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

* [PATCH v3 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-21 10:25       ` Hemant Kumar
  2016-11-24 23:13         ` [PATCH v3 0/2] " Alexis Berlemont
  2016-11-24 23:13         ` [PATCH v3 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-11-24 23:13         ` Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-24 23:13 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

$ perf buildid-cache -v --add test_sdt
$ perf probe -x test_sdt sdt_libfoo:table_frob
$ perf probe -x test_sdt sdt_libfoo:table_diddle
$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  18 ++++
 tools/perf/util/perf_regs.c          |   4 +
 tools/perf/util/perf_regs.h          |  13 +++
 tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
 4 files changed, 200 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f..52a1e65 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
 	SMPL_REG_END
 };
+
+const struct sdt_name_reg sdt_reg_renamings[] = {
+	SDT_NAME_REG(eax, ax),
+	SDT_NAME_REG(rax, ax),
+	SDT_NAME_REG(ebx, bx),
+	SDT_NAME_REG(rbx, bx),
+	SDT_NAME_REG(ecx, cx),
+	SDT_NAME_REG(rcx, cx),
+	SDT_NAME_REG(edx, dx),
+	SDT_NAME_REG(rdx, dx),
+	SDT_NAME_REG(esi, si),
+	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(edi, di),
+	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(ebp, bp),
+	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG_END,
+};
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f2..1c21150 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
+const struct sdt_name_reg __weak sdt_reg_renamings[] = {
+	SDT_NAME_REG_END,
+};
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e4..41815ca 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,19 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+struct sdt_name_reg {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+extern const struct sdt_name_reg sdt_reg_renamings[];
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..75033c7 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
 
 #define MAX_CMDLEN 256
 
@@ -687,6 +688,165 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	const struct sdt_name_reg *rnames;
+	char *tmp, *desc = strdup(arg);
+	const char *prefix = "", *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		if (type_idx == LONG_MIN ||
+			type_idx == LONG_MAX) {
+			pr_debug4("Failed to get sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("SDT argument format not supported\n");
+		goto out;
+	}
+
+	/*
+	 * If the argument addressing mode is indirect, we must check
+	 * a few things...
+	 */
+	tmp = strchr(desc, '(');
+	if (tmp) {
+		int j;
+
+		/*
+		 * ...if the addressing mode is indirect with a
+		 * positive offset (ex.: "1608(%ax)"), we need to add
+		 * a '+' prefix so as to be compliant with uprobe
+		 * format.
+		 */
+		if (desc[0] != '+' && desc[0] != '-')
+			prefix = "+";
+
+		/*
+		 * ...or if the addressing mode is indirect with a symbol
+		 * as offset, the argument will not be supported by
+		 * the uprobe tracer format; so, let's skip this one.
+		 */
+		for (j = 0; j < tmp - desc; j++) {
+			if (desc[j] != '+' && desc[j] != '-' &&
+				!isdigit(desc[j]))
+				goto out;
+		}
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below performs all the needed renamings if needed.
+	 */
+	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
+		char *new_desc, *sdt_name;
+		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
+
+		sdt_name = strstr(desc, rnames->sdt_name);
+		if (sdt_name == NULL)
+			continue;
+
+		new_desc = zalloc(strlen(desc) + 1 +
+				strlen(rnames->uprobe_name) -
+				strlen(rnames->sdt_name));
+		if (new_desc == NULL)
+			goto error;
+
+		prefix_len = sdt_name - desc;
+		if (prefix_len != 0)
+			memcpy(new_desc, desc, prefix_len);
+
+		uprobe_len = strlen(rnames->uprobe_name);
+		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+		mid_ofs = prefix_len + strlen(rnames->sdt_name);
+		desc_len = strlen(desc);
+		if (mid_ofs < desc_len)
+			memcpy(new_desc + prefix_len + uprobe_len,
+				desc + mid_ofs, desc_len - mid_ofs);
+
+		free(desc);
+		desc = new_desc;
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s%s", i, prefix, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -723,11 +883,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;
-- 
2.10.2

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

* Re: [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments
  2016-11-18 23:56     ` [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-11-25 14:40       ` Arnaldo Carvalho de Melo
  2016-11-26  0:58         ` [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
                           ` (2 more replies)
  0 siblings, 3 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-11-25 14:40 UTC (permalink / raw)
  To: Alexis Berlemont; +Cc: linux-kernel, peterz, mingo, alexander.shishkin, hemant

Em Sat, Nov 19, 2016 at 12:56:36AM +0100, Alexis Berlemont escreveu:
> During a "perf buildid-cache --add" command, the section
> ".note.stapsdt" of the "added" binary is scanned in order to list the
> available SDT markers available in a binary. The parts containing the
> probes arguments were left unscanned.
> 
> The whole section is now parsed; the probe arguments are extracted for
> later use.
> 
> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>  tools/perf/util/symbol-elf.c | 16 +++++++++++++++-
>  tools/perf/util/symbol.h     |  1 +
>  2 files changed, 16 insertions(+), 1 deletion(-)
> 
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 99400b0..0fbe0b2 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
>  static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  			     struct list_head *sdt_notes)
>  {
> -	const char *provider, *name;
> +	const char *provider, *name, *args;
>  	struct sdt_note *tmp = NULL;
>  	GElf_Ehdr ehdr;
>  	GElf_Addr base_off = 0;
> @@ -1881,6 +1881,20 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  		goto out_free_prov;
>  	}
>  
> +	args = (const char *)memchr(name, '\0', data + len - name);

Humm, no need for casting?

> +
> +	/*
> +	 * There is no argument if:
> +	 * - We reached the end of the note;
> +	 * - There is not enough room to hold a potential string;
> +	 * - The argument string is empty or just contains ':'.
> +	 */
> +	if (args == NULL || data + len - args < 2 ||
> +		args[1] == ':' || args[1] == '\0')
> +		tmp->args = NULL;
> +	else
> +		tmp->args = strdup(++args);

Shouldn't we check this and do error back propagation? I.e. if there are
args and we don't handle them, silently, that looks bad

> +
>  	if (gelf_getclass(*elf) == ELFCLASS32) {
>  		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
>  		tmp->bit32 = true;
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index 2d0a905..913be07 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -347,6 +347,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
>  struct sdt_note {
>  	char *name;			/* name of the note*/
>  	char *provider;			/* provider name */
> +	char *args;
>  	bool bit32;			/* whether the location is 32 bits? */
>  	union {				/* location, base and semaphore addrs */
>  		Elf64_Addr a64[3];
> -- 
> 2.10.2

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

* [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-25 14:40       ` Arnaldo Carvalho de Melo
@ 2016-11-26  0:58         ` Alexis Berlemont
  2016-12-05 23:42           ` Alexis Berlemont
  2016-11-26  0:58         ` [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
  2016-11-26  0:58         ` [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2 siblings, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-26  0:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

Hi Arnaldo,

Here is another patch set which fixes the issues you noticed.

Thank you.

Alexis.

Alexis Berlemont (2):
  perf sdt: add scanning of sdt probles arguments
  perf probe: add sdt probes arguments into the uprobe cmd string

 tools/perf/arch/x86/util/perf_regs.c |  18 ++++
 tools/perf/util/perf_regs.c          |   4 +
 tools/perf/util/perf_regs.h          |  13 +++
 tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
 tools/perf/util/symbol-elf.c         |  25 +++++-
 tools/perf/util/symbol.h             |   1 +
 6 files changed, 224 insertions(+), 6 deletions(-)

-- 
2.10.2

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

* [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments
  2016-11-25 14:40       ` Arnaldo Carvalho de Melo
  2016-11-26  0:58         ` [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
@ 2016-11-26  0:58         ` Alexis Berlemont
  2016-12-07  2:44           ` Masami Hiramatsu
  2016-11-26  0:58         ` [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2 siblings, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-26  0:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

During a "perf buildid-cache --add" command, the section
".note.stapsdt" of the "added" binary is scanned in order to list the
available SDT markers available in a binary. The parts containing the
probes arguments were left unscanned.

The whole section is now parsed; the probe arguments are extracted for
later use.

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/util/symbol-elf.c | 25 +++++++++++++++++++++++--
 tools/perf/util/symbol.h     |  1 +
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 99400b0..7725c3f 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 			     struct list_head *sdt_notes)
 {
-	const char *provider, *name;
+	const char *provider, *name, *args;
 	struct sdt_note *tmp = NULL;
 	GElf_Ehdr ehdr;
 	GElf_Addr base_off = 0;
@@ -1881,6 +1881,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 		goto out_free_prov;
 	}
 
+	args = memchr(name, '\0', data + len - name);
+
+	/*
+	 * There is no argument if:
+	 * - We reached the end of the note;
+	 * - There is not enough room to hold a potential string;
+	 * - The argument string is empty or just contains ':'.
+	 */
+	if (args == NULL || data + len - args < 2 ||
+		args[1] == ':' || args[1] == '\0')
+		tmp->args = NULL;
+	else {
+		tmp->args = strdup(++args);
+		if (!tmp->args) {
+			ret = -ENOMEM;
+			goto out_free_name;
+		}
+	}
+
 	if (gelf_getclass(*elf) == ELFCLASS32) {
 		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
 		tmp->bit32 = true;
@@ -1892,7 +1911,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 	if (!gelf_getehdr(*elf, &ehdr)) {
 		pr_debug("%s : cannot get elf header.\n", __func__);
 		ret = -EBADF;
-		goto out_free_name;
+		goto out_free_args;
 	}
 
 	/* Adjust the prelink effect :
@@ -1917,6 +1936,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 	list_add_tail(&tmp->note_list, sdt_notes);
 	return 0;
 
+out_free_args:
+	free(tmp->args);
 out_free_name:
 	free(tmp->name);
 out_free_prov:
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index dec7e2d4..db1953e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -348,6 +348,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 struct sdt_note {
 	char *name;			/* name of the note*/
 	char *provider;			/* provider name */
+	char *args;
 	bool bit32;			/* whether the location is 32 bits? */
 	union {				/* location, base and semaphore addrs */
 		Elf64_Addr a64[3];
-- 
2.10.2

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

* [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-25 14:40       ` Arnaldo Carvalho de Melo
  2016-11-26  0:58         ` [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2016-11-26  0:58         ` [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-11-26  0:58         ` Alexis Berlemont
  2016-12-07  3:26           ` Masami Hiramatsu
  2 siblings, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-11-26  0:58 UTC (permalink / raw)
  To: linux-kernel
  Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin, hemant

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

$ perf buildid-cache -v --add test_sdt
$ perf probe -x test_sdt sdt_libfoo:table_frob
$ perf probe -x test_sdt sdt_libfoo:table_diddle
$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  18 ++++
 tools/perf/util/perf_regs.c          |   4 +
 tools/perf/util/perf_regs.h          |  13 +++
 tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
 4 files changed, 200 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f..52a1e65 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
 	SMPL_REG_END
 };
+
+const struct sdt_name_reg sdt_reg_renamings[] = {
+	SDT_NAME_REG(eax, ax),
+	SDT_NAME_REG(rax, ax),
+	SDT_NAME_REG(ebx, bx),
+	SDT_NAME_REG(rbx, bx),
+	SDT_NAME_REG(ecx, cx),
+	SDT_NAME_REG(rcx, cx),
+	SDT_NAME_REG(edx, dx),
+	SDT_NAME_REG(rdx, dx),
+	SDT_NAME_REG(esi, si),
+	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(edi, di),
+	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(ebp, bp),
+	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG_END,
+};
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f2..1c21150 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
+const struct sdt_name_reg __weak sdt_reg_renamings[] = {
+	SDT_NAME_REG_END,
+};
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e4..41815ca 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,19 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+struct sdt_name_reg {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+extern const struct sdt_name_reg sdt_reg_renamings[];
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..75033c7 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
 
 #define MAX_CMDLEN 256
 
@@ -687,6 +688,165 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	const struct sdt_name_reg *rnames;
+	char *tmp, *desc = strdup(arg);
+	const char *prefix = "", *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		if (type_idx == LONG_MIN ||
+			type_idx == LONG_MAX) {
+			pr_debug4("Failed to get sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("SDT argument format not supported\n");
+		goto out;
+	}
+
+	/*
+	 * If the argument addressing mode is indirect, we must check
+	 * a few things...
+	 */
+	tmp = strchr(desc, '(');
+	if (tmp) {
+		int j;
+
+		/*
+		 * ...if the addressing mode is indirect with a
+		 * positive offset (ex.: "1608(%ax)"), we need to add
+		 * a '+' prefix so as to be compliant with uprobe
+		 * format.
+		 */
+		if (desc[0] != '+' && desc[0] != '-')
+			prefix = "+";
+
+		/*
+		 * ...or if the addressing mode is indirect with a symbol
+		 * as offset, the argument will not be supported by
+		 * the uprobe tracer format; so, let's skip this one.
+		 */
+		for (j = 0; j < tmp - desc; j++) {
+			if (desc[j] != '+' && desc[j] != '-' &&
+				!isdigit(desc[j]))
+				goto out;
+		}
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below performs all the needed renamings if needed.
+	 */
+	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
+		char *new_desc, *sdt_name;
+		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
+
+		sdt_name = strstr(desc, rnames->sdt_name);
+		if (sdt_name == NULL)
+			continue;
+
+		new_desc = zalloc(strlen(desc) + 1 +
+				strlen(rnames->uprobe_name) -
+				strlen(rnames->sdt_name));
+		if (new_desc == NULL)
+			goto error;
+
+		prefix_len = sdt_name - desc;
+		if (prefix_len != 0)
+			memcpy(new_desc, desc, prefix_len);
+
+		uprobe_len = strlen(rnames->uprobe_name);
+		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+		mid_ofs = prefix_len + strlen(rnames->sdt_name);
+		desc_len = strlen(desc);
+		if (mid_ofs < desc_len)
+			memcpy(new_desc + prefix_len + uprobe_len,
+				desc + mid_ofs, desc_len - mid_ofs);
+
+		free(desc);
+		desc = new_desc;
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s%s", i, prefix, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -723,11 +883,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;
-- 
2.10.2

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

* Re: [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-26  0:58         ` [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
@ 2016-12-05 23:42           ` Alexis Berlemont
  2016-12-06 14:45             ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 77+ messages in thread
From: Alexis Berlemont @ 2016-12-05 23:42 UTC (permalink / raw)
  To: linux-kernel; +Cc: peterz, mingo, acme, alexander.shishkin, hemant

Alexis Berlemont wrote:
> Hi Arnaldo,
> 
> Here is another patch set which fixes the issues you noticed.
>

Could you indicate me a way to improve these patches so as to move
forward ?

Regards,

Alexis.

> Thank you.
> 
> Alexis.
> 
> Alexis Berlemont (2):
>   perf sdt: add scanning of sdt probles arguments
>   perf probe: add sdt probes arguments into the uprobe cmd string
> 
>  tools/perf/arch/x86/util/perf_regs.c |  18 ++++
>  tools/perf/util/perf_regs.c          |   4 +
>  tools/perf/util/perf_regs.h          |  13 +++
>  tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
>  tools/perf/util/symbol-elf.c         |  25 +++++-
>  tools/perf/util/symbol.h             |   1 +
>  6 files changed, 224 insertions(+), 6 deletions(-)
> 
> -- 
> 2.10.2
> 

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

* Re: [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-05 23:42           ` Alexis Berlemont
@ 2016-12-06 14:45             ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-06 14:45 UTC (permalink / raw)
  To: Alexis Berlemont
  Cc: linux-kernel, peterz, mingo, alexander.shishkin, hemant,
	Masami Hiramatsu

Em Tue, Dec 06, 2016 at 12:42:45AM +0100, Alexis Berlemont escreveu:
> Alexis Berlemont wrote:
> > Hi Arnaldo,
> > 
> > Here is another patch set which fixes the issues you noticed.
> >
> 
> Could you indicate me a way to improve these patches so as to move
> forward ?

Masami, Hemant, are you guys ok with this? Can I have your Acked-by or
Tested-by, etc?

- Arnaldo
 
> Regards,
> 
> Alexis.
> 
> > Thank you.
> > 
> > Alexis.
> > 
> > Alexis Berlemont (2):
> >   perf sdt: add scanning of sdt probles arguments
> >   perf probe: add sdt probes arguments into the uprobe cmd string
> > 
> >  tools/perf/arch/x86/util/perf_regs.c |  18 ++++
> >  tools/perf/util/perf_regs.c          |   4 +
> >  tools/perf/util/perf_regs.h          |  13 +++
> >  tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
> >  tools/perf/util/symbol-elf.c         |  25 +++++-
> >  tools/perf/util/symbol.h             |   1 +
> >  6 files changed, 224 insertions(+), 6 deletions(-)
> > 
> > -- 
> > 2.10.2
> > 

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

* Re: [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments
  2016-11-26  0:58         ` [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-12-07  2:44           ` Masami Hiramatsu
  0 siblings, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2016-12-07  2:44 UTC (permalink / raw)
  To: Alexis Berlemont
  Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin, hemant

On Sat, 26 Nov 2016 01:58:02 +0100
Alexis Berlemont <alexis.berlemont@gmail.com> wrote:

> During a "perf buildid-cache --add" command, the section
> ".note.stapsdt" of the "added" binary is scanned in order to list the
> available SDT markers available in a binary. The parts containing the
> probes arguments were left unscanned.
> 
> The whole section is now parsed; the probe arguments are extracted for
> later use.
> 

Looks OK for me :)

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>  tools/perf/util/symbol-elf.c | 25 +++++++++++++++++++++++--
>  tools/perf/util/symbol.h     |  1 +
>  2 files changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 99400b0..7725c3f 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
>  static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  			     struct list_head *sdt_notes)
>  {
> -	const char *provider, *name;
> +	const char *provider, *name, *args;
>  	struct sdt_note *tmp = NULL;
>  	GElf_Ehdr ehdr;
>  	GElf_Addr base_off = 0;
> @@ -1881,6 +1881,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  		goto out_free_prov;
>  	}
>  
> +	args = memchr(name, '\0', data + len - name);
> +
> +	/*
> +	 * There is no argument if:
> +	 * - We reached the end of the note;
> +	 * - There is not enough room to hold a potential string;
> +	 * - The argument string is empty or just contains ':'.
> +	 */
> +	if (args == NULL || data + len - args < 2 ||
> +		args[1] == ':' || args[1] == '\0')
> +		tmp->args = NULL;
> +	else {
> +		tmp->args = strdup(++args);
> +		if (!tmp->args) {
> +			ret = -ENOMEM;
> +			goto out_free_name;
> +		}
> +	}
> +
>  	if (gelf_getclass(*elf) == ELFCLASS32) {
>  		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
>  		tmp->bit32 = true;
> @@ -1892,7 +1911,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  	if (!gelf_getehdr(*elf, &ehdr)) {
>  		pr_debug("%s : cannot get elf header.\n", __func__);
>  		ret = -EBADF;
> -		goto out_free_name;
> +		goto out_free_args;
>  	}
>  
>  	/* Adjust the prelink effect :
> @@ -1917,6 +1936,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  	list_add_tail(&tmp->note_list, sdt_notes);
>  	return 0;
>  
> +out_free_args:
> +	free(tmp->args);
>  out_free_name:
>  	free(tmp->name);
>  out_free_prov:
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index dec7e2d4..db1953e 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -348,6 +348,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
>  struct sdt_note {
>  	char *name;			/* name of the note*/
>  	char *provider;			/* provider name */
> +	char *args;
>  	bool bit32;			/* whether the location is 32 bits? */
>  	union {				/* location, base and semaphore addrs */
>  		Elf64_Addr a64[3];
> -- 
> 2.10.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-11-26  0:58         ` [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
@ 2016-12-07  3:26           ` Masami Hiramatsu
  2016-12-09 15:14             ` Arnaldo Carvalho de Melo
                               ` (3 more replies)
  0 siblings, 4 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2016-12-07  3:26 UTC (permalink / raw)
  To: Alexis Berlemont
  Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin, hemant

Hello Alexis,

On Sat, 26 Nov 2016 01:58:03 +0100
Alexis Berlemont <alexis.berlemont@gmail.com> wrote:

> An sdt probe can be associated with arguments but they were not passed
> to the user probe tracing interface (uprobe_events); this patch adapts
> the sdt argument descriptors according to the uprobe input format.

Great!

> 
> As the uprobe parser does not support scaled address mode, perf will
> skip arguments which cannot be adapted to the uprobe format.

OK, it seems that skipping argument is a good idea :)
I just tried to support fixed-number arguments in probe events,
but skipping it is better with older kernel.

I have some comments.

> Here are the results:
> 
> $ perf buildid-cache -v --add test_sdt
> $ perf probe -x test_sdt sdt_libfoo:table_frob
> $ perf probe -x test_sdt sdt_libfoo:table_diddle
> $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> $ perf script
> test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

We'd better start with arg1, since sdt.h and original Dtrace SDT starts
arguments from arg1 (I'm not sure why) and dtrace/systemtap scripts
call it "arg1".

> 
> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>  tools/perf/arch/x86/util/perf_regs.c |  18 ++++
>  tools/perf/util/perf_regs.c          |   4 +
>  tools/perf/util/perf_regs.h          |  13 +++
>  tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
>  4 files changed, 200 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index c5db14f..52a1e65 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
>  #endif
>  	SMPL_REG_END
>  };
> +
> +const struct sdt_name_reg sdt_reg_renamings[] = {
> +	SDT_NAME_REG(eax, ax),
> +	SDT_NAME_REG(rax, ax),
> +	SDT_NAME_REG(ebx, bx),
> +	SDT_NAME_REG(rbx, bx),
> +	SDT_NAME_REG(ecx, cx),
> +	SDT_NAME_REG(rcx, cx),
> +	SDT_NAME_REG(edx, dx),
> +	SDT_NAME_REG(rdx, dx),
> +	SDT_NAME_REG(esi, si),
> +	SDT_NAME_REG(rsi, si),
> +	SDT_NAME_REG(edi, di),
> +	SDT_NAME_REG(rdi, di),
> +	SDT_NAME_REG(ebp, bp),
> +	SDT_NAME_REG(rbp, bp),
> +	SDT_NAME_REG_END,
> +};

It is not enough, rNN registers also have to take care, since
gcc adds 'd', 'w' or 'b'suffixes for those registers to indicate
its size. e.g. r15d means r15 register with 32 lower bits.
What we need is just cut them off, since probe event uses
length modifiers (like :u32)

> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index c4023f2..1c21150 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
>  	SMPL_REG_END
>  };
>  
> +const struct sdt_name_reg __weak sdt_reg_renamings[] = {
> +	SDT_NAME_REG_END,
> +};
> +
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
>  {
> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index 679d6e4..41815ca 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -15,6 +15,19 @@ struct sample_reg {
>  
>  extern const struct sample_reg sample_reg_masks[];
>  
> +struct sdt_name_reg {
> +	const char *sdt_name;
> +	const char *uprobe_name;
> +};
> +#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> +#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
> +
> +/*
> + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> + * registers before filling the uprobe tracer interface.
> + */
> +extern const struct sdt_name_reg sdt_reg_renamings[];
> +
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  #include <perf_regs.h>
>  
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 436b647..75033c7 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -27,6 +27,7 @@
>  #include "probe-event.h"
>  #include "probe-file.h"
>  #include "session.h"
> +#include "perf_regs.h"
>  
>  #define MAX_CMDLEN 256
>  
> @@ -687,6 +688,165 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
>  		 : (unsigned long long)note->addr.a64[0];
>  }
>  
> +static const char * const type_to_suffix[] = {
> +	":s64", "", "", "", ":s32", "", ":s16", ":s8",
> +	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
> +};
> +
> +static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
> +{
> +	const struct sdt_name_reg *rnames;
> +	char *tmp, *desc = strdup(arg);
> +	const char *prefix = "", *suffix = "";
> +	int ret = -1;
> +
> +	if (desc == NULL) {
> +		pr_debug4("Allocation error\n");
> +		return ret;
> +	}
> +
> +	tmp = strchr(desc, '@');
> +	if (tmp) {
> +		long type_idx;
> +		/*
> +		 * Isolate the string number and convert it into a
> +		 * binary value; this will be an index to get suffix
> +		 * of the uprobe name (defining the type)
> +		 */
> +		tmp[0] = '\0';
> +		type_idx = strtol(desc, NULL, 10);
> +		if (type_idx == LONG_MIN ||
> +			type_idx == LONG_MAX) {
> +			pr_debug4("Failed to get sdt type\n");
> +			goto error;
> +		}

	You must ensure 0 <= type_idx + 8 <= 16 here.

> +		suffix = type_to_suffix[type_idx + 8];
> +		/* Get rid of the sdt prefix which is now useless */
> +		tmp++;
> +		memmove(desc, tmp, strlen(tmp) + 1);
> +	}
> +
> +	/*
> +	 * The uprobe tracer format does not support all the
> +	 * addressing modes (notably: in x86 the scaled mode); so, we
> +	 * detect ',' characters, if there is just one, there is no
> +	 * use converting the sdt arg into a uprobe one.
> +	 */
> +	if (strchr(desc, ',')) {
> +		pr_debug4("SDT argument format not supported\n");

	Please print 'desc' by %s too. 

> +		goto out;
> +	}
> +
> +	/*
> +	 * If the argument addressing mode is indirect, we must check
> +	 * a few things...
> +	 */
> +	tmp = strchr(desc, '(');
> +	if (tmp) {
> +		int j;
> +
> +		/*
> +		 * ...if the addressing mode is indirect with a
> +		 * positive offset (ex.: "1608(%ax)"), we need to add
> +		 * a '+' prefix so as to be compliant with uprobe
> +		 * format.
> +		 */
> +		if (desc[0] != '+' && desc[0] != '-')
> +			prefix = "+";
> +
> +		/*
> +		 * ...or if the addressing mode is indirect with a symbol
> +		 * as offset, the argument will not be supported by
> +		 * the uprobe tracer format; so, let's skip this one.
> +		 */
> +		for (j = 0; j < tmp - desc; j++) {
> +			if (desc[j] != '+' && desc[j] != '-' &&
> +				!isdigit(desc[j]))
> +				goto out;
> +		}
> +	}
> +
> +	/*
> +	 * The uprobe parser does not support all gas register names;
> +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> +	 * the loop below performs all the needed renamings if needed.
> +	 */
> +	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
> +		char *new_desc, *sdt_name;
> +		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
> +
> +		sdt_name = strstr(desc, rnames->sdt_name);
> +		if (sdt_name == NULL)
> +			continue;

It is better to search '%' from the desc and parse it.
And here, we also find fixed numbers which starts with '$',
since that is not supported yet.

For example, with your patch, I still see some entries which have fixed num.

$ perf buildid-cache --add /usr/lib64/libglib-2.0.so
$ grep \$[0-9] ~/.debug/usr/lib64/libglib-2.0.so.0.5000.2/fda1ca4181ba7135d41bf3cfadc813a432f31066/probes | tail -n 2
p:sdt_glib/mem__realloc /usr/lib64/libglib-2.0.so.0.5000.2:0x4f670 arg0=%ax:u64 arg1=%bx:u64 arg2=%bp:u32 arg3=$0:s32
p:sdt_glib/mem__realloc /usr/lib64/libglib-2.0.so.0.5000.2:0x4f75d arg0=%ax:u64 arg1=%bp:u64 arg2=%bx:u32 arg3=$1:s32

These arguments should be skipped.

Thank you,

> +
> +		new_desc = zalloc(strlen(desc) + 1 +
> +				strlen(rnames->uprobe_name) -
> +				strlen(rnames->sdt_name));
> +		if (new_desc == NULL)
> +			goto error;
> +
> +		prefix_len = sdt_name - desc;
> +		if (prefix_len != 0)
> +			memcpy(new_desc, desc, prefix_len);
> +
> +		uprobe_len = strlen(rnames->uprobe_name);
> +		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
> +
> +		mid_ofs = prefix_len + strlen(rnames->sdt_name);
> +		desc_len = strlen(desc);
> +		if (mid_ofs < desc_len)
> +			memcpy(new_desc + prefix_len + uprobe_len,
> +				desc + mid_ofs, desc_len - mid_ofs);
> +
> +		free(desc);
> +		desc = new_desc;
> +	}
> +
> +	if (strbuf_addf(buf, " arg%d=%s%s%s", i, prefix, desc, suffix) < 0)
> +		goto error;
> +
> +out:
> +	ret = 0;
> +error:
> +	free(desc);
> +	return ret;
> +}
> +
> +static char *synthesize_sdt_probe_command(struct sdt_note *note,
> +					const char *pathname,
> +					const char *sdtgrp)
> +{
> +	struct strbuf buf;
> +	char *ret = NULL, **args;
> +	int i, args_count;
> +
> +	if (strbuf_init(&buf, 32) < 0)
> +		return NULL;
> +
> +	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
> +				sdtgrp, note->name, pathname,
> +				sdt_note__get_addr(note)) < 0)
> +		goto error;
> +
> +	if (!note->args)
> +		goto out;
> +
> +	if (note->args) {
> +		args = argv_split(note->args, &args_count);
> +
> +		for (i = 0; i < args_count; ++i) {
> +			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
> +				goto error;
> +		}
> +	}
> +
> +out:
> +	ret = strbuf_detach(&buf, NULL);
> +error:
> +	strbuf_release(&buf);
> +	return ret;
> +}
> +
>  int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>  {
>  	struct probe_cache_entry *entry = NULL;
> @@ -723,11 +883,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>  			entry->pev.group = strdup(sdtgrp);
>  			list_add_tail(&entry->node, &pcache->entries);
>  		}
> -		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> -				sdtgrp, note->name, pathname,
> -				sdt_note__get_addr(note));
> -		if (ret < 0)
> +		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
> +		if (!buf) {
> +			ret = -ENOMEM;
>  			break;
> +		}
> +
>  		strlist__add(entry->tevlist, buf);
>  		free(buf);
>  		entry = NULL;
> -- 
> 2.10.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-07  3:26           ` Masami Hiramatsu
@ 2016-12-09 15:14             ` Arnaldo Carvalho de Melo
  2016-12-10 10:00               ` Masami Hiramatsu
  2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
                               ` (2 subsequent siblings)
  3 siblings, 1 reply; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2016-12-09 15:14 UTC (permalink / raw)
  To: Alexis Berlemont
  Cc: Masami Hiramatsu, linux-kernel, peterz, mingo,
	alexander.shishkin, hemant

Em Wed, Dec 07, 2016 at 12:26:10PM +0900, Masami Hiramatsu escreveu:
> Hello Alexis,
> 
> On Sat, 26 Nov 2016 01:58:03 +0100
> Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
> 
> > An sdt probe can be associated with arguments but they were not passed
> > to the user probe tracing interface (uprobe_events); this patch adapts
> > the sdt argument descriptors according to the uprobe input format.
> 
> Great!

Yeah, good to see work in this area!

I applied the first patch, with Masami's ack, waiting for his concerns
on this one to be addressed, ok?

- Arnaldo
 
> > 
> > As the uprobe parser does not support scaled address mode, perf will
> > skip arguments which cannot be adapted to the uprobe format.
> 
> OK, it seems that skipping argument is a good idea :)
> I just tried to support fixed-number arguments in probe events,
> but skipping it is better with older kernel.
> 
> I have some comments.
> 
> > Here are the results:
> > 
> > $ perf buildid-cache -v --add test_sdt
> > $ perf probe -x test_sdt sdt_libfoo:table_frob
> > $ perf probe -x test_sdt sdt_libfoo:table_diddle
> > $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> > $ perf script
> > test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> > test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> > test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> > test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> > test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> > test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8
> 
> We'd better start with arg1, since sdt.h and original Dtrace SDT starts
> arguments from arg1 (I'm not sure why) and dtrace/systemtap scripts
> call it "arg1".
> 
> > 
> > Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> > ---
> >  tools/perf/arch/x86/util/perf_regs.c |  18 ++++
> >  tools/perf/util/perf_regs.c          |   4 +
> >  tools/perf/util/perf_regs.h          |  13 +++
> >  tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
> >  4 files changed, 200 insertions(+), 4 deletions(-)
> > 
> > diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> > index c5db14f..52a1e65 100644
> > --- a/tools/perf/arch/x86/util/perf_regs.c
> > +++ b/tools/perf/arch/x86/util/perf_regs.c
> > @@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
> >  #endif
> >  	SMPL_REG_END
> >  };
> > +
> > +const struct sdt_name_reg sdt_reg_renamings[] = {
> > +	SDT_NAME_REG(eax, ax),
> > +	SDT_NAME_REG(rax, ax),
> > +	SDT_NAME_REG(ebx, bx),
> > +	SDT_NAME_REG(rbx, bx),
> > +	SDT_NAME_REG(ecx, cx),
> > +	SDT_NAME_REG(rcx, cx),
> > +	SDT_NAME_REG(edx, dx),
> > +	SDT_NAME_REG(rdx, dx),
> > +	SDT_NAME_REG(esi, si),
> > +	SDT_NAME_REG(rsi, si),
> > +	SDT_NAME_REG(edi, di),
> > +	SDT_NAME_REG(rdi, di),
> > +	SDT_NAME_REG(ebp, bp),
> > +	SDT_NAME_REG(rbp, bp),
> > +	SDT_NAME_REG_END,
> > +};
> 
> It is not enough, rNN registers also have to take care, since
> gcc adds 'd', 'w' or 'b'suffixes for those registers to indicate
> its size. e.g. r15d means r15 register with 32 lower bits.
> What we need is just cut them off, since probe event uses
> length modifiers (like :u32)
> 
> > diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> > index c4023f2..1c21150 100644
> > --- a/tools/perf/util/perf_regs.c
> > +++ b/tools/perf/util/perf_regs.c
> > @@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
> >  	SMPL_REG_END
> >  };
> >  
> > +const struct sdt_name_reg __weak sdt_reg_renamings[] = {
> > +	SDT_NAME_REG_END,
> > +};
> > +
> >  #ifdef HAVE_PERF_REGS_SUPPORT
> >  int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
> >  {
> > diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> > index 679d6e4..41815ca 100644
> > --- a/tools/perf/util/perf_regs.h
> > +++ b/tools/perf/util/perf_regs.h
> > @@ -15,6 +15,19 @@ struct sample_reg {
> >  
> >  extern const struct sample_reg sample_reg_masks[];
> >  
> > +struct sdt_name_reg {
> > +	const char *sdt_name;
> > +	const char *uprobe_name;
> > +};
> > +#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> > +#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
> > +
> > +/*
> > + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> > + * registers before filling the uprobe tracer interface.
> > + */
> > +extern const struct sdt_name_reg sdt_reg_renamings[];
> > +
> >  #ifdef HAVE_PERF_REGS_SUPPORT
> >  #include <perf_regs.h>
> >  
> > diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> > index 436b647..75033c7 100644
> > --- a/tools/perf/util/probe-file.c
> > +++ b/tools/perf/util/probe-file.c
> > @@ -27,6 +27,7 @@
> >  #include "probe-event.h"
> >  #include "probe-file.h"
> >  #include "session.h"
> > +#include "perf_regs.h"
> >  
> >  #define MAX_CMDLEN 256
> >  
> > @@ -687,6 +688,165 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
> >  		 : (unsigned long long)note->addr.a64[0];
> >  }
> >  
> > +static const char * const type_to_suffix[] = {
> > +	":s64", "", "", "", ":s32", "", ":s16", ":s8",
> > +	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
> > +};
> > +
> > +static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
> > +{
> > +	const struct sdt_name_reg *rnames;
> > +	char *tmp, *desc = strdup(arg);
> > +	const char *prefix = "", *suffix = "";
> > +	int ret = -1;
> > +
> > +	if (desc == NULL) {
> > +		pr_debug4("Allocation error\n");
> > +		return ret;
> > +	}
> > +
> > +	tmp = strchr(desc, '@');
> > +	if (tmp) {
> > +		long type_idx;
> > +		/*
> > +		 * Isolate the string number and convert it into a
> > +		 * binary value; this will be an index to get suffix
> > +		 * of the uprobe name (defining the type)
> > +		 */
> > +		tmp[0] = '\0';
> > +		type_idx = strtol(desc, NULL, 10);
> > +		if (type_idx == LONG_MIN ||
> > +			type_idx == LONG_MAX) {
> > +			pr_debug4("Failed to get sdt type\n");
> > +			goto error;
> > +		}
> 
> 	You must ensure 0 <= type_idx + 8 <= 16 here.
> 
> > +		suffix = type_to_suffix[type_idx + 8];
> > +		/* Get rid of the sdt prefix which is now useless */
> > +		tmp++;
> > +		memmove(desc, tmp, strlen(tmp) + 1);
> > +	}
> > +
> > +	/*
> > +	 * The uprobe tracer format does not support all the
> > +	 * addressing modes (notably: in x86 the scaled mode); so, we
> > +	 * detect ',' characters, if there is just one, there is no
> > +	 * use converting the sdt arg into a uprobe one.
> > +	 */
> > +	if (strchr(desc, ',')) {
> > +		pr_debug4("SDT argument format not supported\n");
> 
> 	Please print 'desc' by %s too. 
> 
> > +		goto out;
> > +	}
> > +
> > +	/*
> > +	 * If the argument addressing mode is indirect, we must check
> > +	 * a few things...
> > +	 */
> > +	tmp = strchr(desc, '(');
> > +	if (tmp) {
> > +		int j;
> > +
> > +		/*
> > +		 * ...if the addressing mode is indirect with a
> > +		 * positive offset (ex.: "1608(%ax)"), we need to add
> > +		 * a '+' prefix so as to be compliant with uprobe
> > +		 * format.
> > +		 */
> > +		if (desc[0] != '+' && desc[0] != '-')
> > +			prefix = "+";
> > +
> > +		/*
> > +		 * ...or if the addressing mode is indirect with a symbol
> > +		 * as offset, the argument will not be supported by
> > +		 * the uprobe tracer format; so, let's skip this one.
> > +		 */
> > +		for (j = 0; j < tmp - desc; j++) {
> > +			if (desc[j] != '+' && desc[j] != '-' &&
> > +				!isdigit(desc[j]))
> > +				goto out;
> > +		}
> > +	}
> > +
> > +	/*
> > +	 * The uprobe parser does not support all gas register names;
> > +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> > +	 * the loop below performs all the needed renamings if needed.
> > +	 */
> > +	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
> > +		char *new_desc, *sdt_name;
> > +		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
> > +
> > +		sdt_name = strstr(desc, rnames->sdt_name);
> > +		if (sdt_name == NULL)
> > +			continue;
> 
> It is better to search '%' from the desc and parse it.
> And here, we also find fixed numbers which starts with '$',
> since that is not supported yet.
> 
> For example, with your patch, I still see some entries which have fixed num.
> 
> $ perf buildid-cache --add /usr/lib64/libglib-2.0.so
> $ grep \$[0-9] ~/.debug/usr/lib64/libglib-2.0.so.0.5000.2/fda1ca4181ba7135d41bf3cfadc813a432f31066/probes | tail -n 2
> p:sdt_glib/mem__realloc /usr/lib64/libglib-2.0.so.0.5000.2:0x4f670 arg0=%ax:u64 arg1=%bx:u64 arg2=%bp:u32 arg3=$0:s32
> p:sdt_glib/mem__realloc /usr/lib64/libglib-2.0.so.0.5000.2:0x4f75d arg0=%ax:u64 arg1=%bp:u64 arg2=%bx:u32 arg3=$1:s32
> 
> These arguments should be skipped.
> 
> Thank you,
> 
> > +
> > +		new_desc = zalloc(strlen(desc) + 1 +
> > +				strlen(rnames->uprobe_name) -
> > +				strlen(rnames->sdt_name));
> > +		if (new_desc == NULL)
> > +			goto error;
> > +
> > +		prefix_len = sdt_name - desc;
> > +		if (prefix_len != 0)
> > +			memcpy(new_desc, desc, prefix_len);
> > +
> > +		uprobe_len = strlen(rnames->uprobe_name);
> > +		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
> > +
> > +		mid_ofs = prefix_len + strlen(rnames->sdt_name);
> > +		desc_len = strlen(desc);
> > +		if (mid_ofs < desc_len)
> > +			memcpy(new_desc + prefix_len + uprobe_len,
> > +				desc + mid_ofs, desc_len - mid_ofs);
> > +
> > +		free(desc);
> > +		desc = new_desc;
> > +	}
> > +
> > +	if (strbuf_addf(buf, " arg%d=%s%s%s", i, prefix, desc, suffix) < 0)
> > +		goto error;
> > +
> > +out:
> > +	ret = 0;
> > +error:
> > +	free(desc);
> > +	return ret;
> > +}
> > +
> > +static char *synthesize_sdt_probe_command(struct sdt_note *note,
> > +					const char *pathname,
> > +					const char *sdtgrp)
> > +{
> > +	struct strbuf buf;
> > +	char *ret = NULL, **args;
> > +	int i, args_count;
> > +
> > +	if (strbuf_init(&buf, 32) < 0)
> > +		return NULL;
> > +
> > +	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
> > +				sdtgrp, note->name, pathname,
> > +				sdt_note__get_addr(note)) < 0)
> > +		goto error;
> > +
> > +	if (!note->args)
> > +		goto out;
> > +
> > +	if (note->args) {
> > +		args = argv_split(note->args, &args_count);
> > +
> > +		for (i = 0; i < args_count; ++i) {
> > +			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
> > +				goto error;
> > +		}
> > +	}
> > +
> > +out:
> > +	ret = strbuf_detach(&buf, NULL);
> > +error:
> > +	strbuf_release(&buf);
> > +	return ret;
> > +}
> > +
> >  int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
> >  {
> >  	struct probe_cache_entry *entry = NULL;
> > @@ -723,11 +883,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
> >  			entry->pev.group = strdup(sdtgrp);
> >  			list_add_tail(&entry->node, &pcache->entries);
> >  		}
> > -		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> > -				sdtgrp, note->name, pathname,
> > -				sdt_note__get_addr(note));
> > -		if (ret < 0)
> > +		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
> > +		if (!buf) {
> > +			ret = -ENOMEM;
> >  			break;
> > +		}
> > +
> >  		strlist__add(entry->tevlist, buf);
> >  		free(buf);
> >  		entry = NULL;
> > -- 
> > 2.10.2
> > 
> 
> 
> -- 
> Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-09 15:14             ` Arnaldo Carvalho de Melo
@ 2016-12-10 10:00               ` Masami Hiramatsu
  0 siblings, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2016-12-10 10:00 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Alexis Berlemont, Masami Hiramatsu, linux-kernel, peterz, mingo,
	alexander.shishkin, hemant

On Fri, 9 Dec 2016 12:14:30 -0300
Arnaldo Carvalho de Melo <acme@kernel.org> wrote:

> Em Wed, Dec 07, 2016 at 12:26:10PM +0900, Masami Hiramatsu escreveu:
> > Hello Alexis,
> > 
> > On Sat, 26 Nov 2016 01:58:03 +0100
> > Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
> > 
> > > An sdt probe can be associated with arguments but they were not passed
> > > to the user probe tracing interface (uprobe_events); this patch adapts
> > > the sdt argument descriptors according to the uprobe input format.
> > 
> > Great!
> 
> Yeah, good to see work in this area!
> 
> I applied the first patch, with Masami's ack, waiting for his concerns
> on this one to be addressed, ok?

Yes, I'm OK. Alexis, I'm happy to review/ack your next version! :)

Thank you,

> 
> - Arnaldo
>  
> > > 
> > > As the uprobe parser does not support scaled address mode, perf will
> > > skip arguments which cannot be adapted to the uprobe format.
> > 
> > OK, it seems that skipping argument is a good idea :)
> > I just tried to support fixed-number arguments in probe events,
> > but skipping it is better with older kernel.
> > 
> > I have some comments.
> > 
> > > Here are the results:
> > > 
> > > $ perf buildid-cache -v --add test_sdt
> > > $ perf probe -x test_sdt sdt_libfoo:table_frob
> > > $ perf probe -x test_sdt sdt_libfoo:table_diddle
> > > $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> > > $ perf script
> > > test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> > > test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> > > test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> > > test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> > > test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> > > test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8
> > 
> > We'd better start with arg1, since sdt.h and original Dtrace SDT starts
> > arguments from arg1 (I'm not sure why) and dtrace/systemtap scripts
> > call it "arg1".
> > 
> > > 
> > > Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> > > ---
> > >  tools/perf/arch/x86/util/perf_regs.c |  18 ++++
> > >  tools/perf/util/perf_regs.c          |   4 +
> > >  tools/perf/util/perf_regs.h          |  13 +++
> > >  tools/perf/util/probe-file.c         | 169 ++++++++++++++++++++++++++++++++++-
> > >  4 files changed, 200 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> > > index c5db14f..52a1e65 100644
> > > --- a/tools/perf/arch/x86/util/perf_regs.c
> > > +++ b/tools/perf/arch/x86/util/perf_regs.c
> > > @@ -26,3 +26,21 @@ const struct sample_reg sample_reg_masks[] = {
> > >  #endif
> > >  	SMPL_REG_END
> > >  };
> > > +
> > > +const struct sdt_name_reg sdt_reg_renamings[] = {
> > > +	SDT_NAME_REG(eax, ax),
> > > +	SDT_NAME_REG(rax, ax),
> > > +	SDT_NAME_REG(ebx, bx),
> > > +	SDT_NAME_REG(rbx, bx),
> > > +	SDT_NAME_REG(ecx, cx),
> > > +	SDT_NAME_REG(rcx, cx),
> > > +	SDT_NAME_REG(edx, dx),
> > > +	SDT_NAME_REG(rdx, dx),
> > > +	SDT_NAME_REG(esi, si),
> > > +	SDT_NAME_REG(rsi, si),
> > > +	SDT_NAME_REG(edi, di),
> > > +	SDT_NAME_REG(rdi, di),
> > > +	SDT_NAME_REG(ebp, bp),
> > > +	SDT_NAME_REG(rbp, bp),
> > > +	SDT_NAME_REG_END,
> > > +};
> > 
> > It is not enough, rNN registers also have to take care, since
> > gcc adds 'd', 'w' or 'b'suffixes for those registers to indicate
> > its size. e.g. r15d means r15 register with 32 lower bits.
> > What we need is just cut them off, since probe event uses
> > length modifiers (like :u32)
> > 
> > > diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> > > index c4023f2..1c21150 100644
> > > --- a/tools/perf/util/perf_regs.c
> > > +++ b/tools/perf/util/perf_regs.c
> > > @@ -6,6 +6,10 @@ const struct sample_reg __weak sample_reg_masks[] = {
> > >  	SMPL_REG_END
> > >  };
> > >  
> > > +const struct sdt_name_reg __weak sdt_reg_renamings[] = {
> > > +	SDT_NAME_REG_END,
> > > +};
> > > +
> > >  #ifdef HAVE_PERF_REGS_SUPPORT
> > >  int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
> > >  {
> > > diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> > > index 679d6e4..41815ca 100644
> > > --- a/tools/perf/util/perf_regs.h
> > > +++ b/tools/perf/util/perf_regs.h
> > > @@ -15,6 +15,19 @@ struct sample_reg {
> > >  
> > >  extern const struct sample_reg sample_reg_masks[];
> > >  
> > > +struct sdt_name_reg {
> > > +	const char *sdt_name;
> > > +	const char *uprobe_name;
> > > +};
> > > +#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> > > +#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
> > > +
> > > +/*
> > > + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> > > + * registers before filling the uprobe tracer interface.
> > > + */
> > > +extern const struct sdt_name_reg sdt_reg_renamings[];
> > > +
> > >  #ifdef HAVE_PERF_REGS_SUPPORT
> > >  #include <perf_regs.h>
> > >  
> > > diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> > > index 436b647..75033c7 100644
> > > --- a/tools/perf/util/probe-file.c
> > > +++ b/tools/perf/util/probe-file.c
> > > @@ -27,6 +27,7 @@
> > >  #include "probe-event.h"
> > >  #include "probe-file.h"
> > >  #include "session.h"
> > > +#include "perf_regs.h"
> > >  
> > >  #define MAX_CMDLEN 256
> > >  
> > > @@ -687,6 +688,165 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
> > >  		 : (unsigned long long)note->addr.a64[0];
> > >  }
> > >  
> > > +static const char * const type_to_suffix[] = {
> > > +	":s64", "", "", "", ":s32", "", ":s16", ":s8",
> > > +	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
> > > +};
> > > +
> > > +static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
> > > +{
> > > +	const struct sdt_name_reg *rnames;
> > > +	char *tmp, *desc = strdup(arg);
> > > +	const char *prefix = "", *suffix = "";
> > > +	int ret = -1;
> > > +
> > > +	if (desc == NULL) {
> > > +		pr_debug4("Allocation error\n");
> > > +		return ret;
> > > +	}
> > > +
> > > +	tmp = strchr(desc, '@');
> > > +	if (tmp) {
> > > +		long type_idx;
> > > +		/*
> > > +		 * Isolate the string number and convert it into a
> > > +		 * binary value; this will be an index to get suffix
> > > +		 * of the uprobe name (defining the type)
> > > +		 */
> > > +		tmp[0] = '\0';
> > > +		type_idx = strtol(desc, NULL, 10);
> > > +		if (type_idx == LONG_MIN ||
> > > +			type_idx == LONG_MAX) {
> > > +			pr_debug4("Failed to get sdt type\n");
> > > +			goto error;
> > > +		}
> > 
> > 	You must ensure 0 <= type_idx + 8 <= 16 here.
> > 
> > > +		suffix = type_to_suffix[type_idx + 8];
> > > +		/* Get rid of the sdt prefix which is now useless */
> > > +		tmp++;
> > > +		memmove(desc, tmp, strlen(tmp) + 1);
> > > +	}
> > > +
> > > +	/*
> > > +	 * The uprobe tracer format does not support all the
> > > +	 * addressing modes (notably: in x86 the scaled mode); so, we
> > > +	 * detect ',' characters, if there is just one, there is no
> > > +	 * use converting the sdt arg into a uprobe one.
> > > +	 */
> > > +	if (strchr(desc, ',')) {
> > > +		pr_debug4("SDT argument format not supported\n");
> > 
> > 	Please print 'desc' by %s too. 
> > 
> > > +		goto out;
> > > +	}
> > > +
> > > +	/*
> > > +	 * If the argument addressing mode is indirect, we must check
> > > +	 * a few things...
> > > +	 */
> > > +	tmp = strchr(desc, '(');
> > > +	if (tmp) {
> > > +		int j;
> > > +
> > > +		/*
> > > +		 * ...if the addressing mode is indirect with a
> > > +		 * positive offset (ex.: "1608(%ax)"), we need to add
> > > +		 * a '+' prefix so as to be compliant with uprobe
> > > +		 * format.
> > > +		 */
> > > +		if (desc[0] != '+' && desc[0] != '-')
> > > +			prefix = "+";
> > > +
> > > +		/*
> > > +		 * ...or if the addressing mode is indirect with a symbol
> > > +		 * as offset, the argument will not be supported by
> > > +		 * the uprobe tracer format; so, let's skip this one.
> > > +		 */
> > > +		for (j = 0; j < tmp - desc; j++) {
> > > +			if (desc[j] != '+' && desc[j] != '-' &&
> > > +				!isdigit(desc[j]))
> > > +				goto out;
> > > +		}
> > > +	}
> > > +
> > > +	/*
> > > +	 * The uprobe parser does not support all gas register names;
> > > +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> > > +	 * the loop below performs all the needed renamings if needed.
> > > +	 */
> > > +	for (rnames = sdt_reg_renamings; rnames->sdt_name != NULL; rnames++) {
> > > +		char *new_desc, *sdt_name;
> > > +		size_t prefix_len, uprobe_len, mid_ofs, desc_len;
> > > +
> > > +		sdt_name = strstr(desc, rnames->sdt_name);
> > > +		if (sdt_name == NULL)
> > > +			continue;
> > 
> > It is better to search '%' from the desc and parse it.
> > And here, we also find fixed numbers which starts with '$',
> > since that is not supported yet.
> > 
> > For example, with your patch, I still see some entries which have fixed num.
> > 
> > $ perf buildid-cache --add /usr/lib64/libglib-2.0.so
> > $ grep \$[0-9] ~/.debug/usr/lib64/libglib-2.0.so.0.5000.2/fda1ca4181ba7135d41bf3cfadc813a432f31066/probes | tail -n 2
> > p:sdt_glib/mem__realloc /usr/lib64/libglib-2.0.so.0.5000.2:0x4f670 arg0=%ax:u64 arg1=%bx:u64 arg2=%bp:u32 arg3=$0:s32
> > p:sdt_glib/mem__realloc /usr/lib64/libglib-2.0.so.0.5000.2:0x4f75d arg0=%ax:u64 arg1=%bp:u64 arg2=%bx:u32 arg3=$1:s32
> > 
> > These arguments should be skipped.
> > 
> > Thank you,
> > 
> > > +
> > > +		new_desc = zalloc(strlen(desc) + 1 +
> > > +				strlen(rnames->uprobe_name) -
> > > +				strlen(rnames->sdt_name));
> > > +		if (new_desc == NULL)
> > > +			goto error;
> > > +
> > > +		prefix_len = sdt_name - desc;
> > > +		if (prefix_len != 0)
> > > +			memcpy(new_desc, desc, prefix_len);
> > > +
> > > +		uprobe_len = strlen(rnames->uprobe_name);
> > > +		memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
> > > +
> > > +		mid_ofs = prefix_len + strlen(rnames->sdt_name);
> > > +		desc_len = strlen(desc);
> > > +		if (mid_ofs < desc_len)
> > > +			memcpy(new_desc + prefix_len + uprobe_len,
> > > +				desc + mid_ofs, desc_len - mid_ofs);
> > > +
> > > +		free(desc);
> > > +		desc = new_desc;
> > > +	}
> > > +
> > > +	if (strbuf_addf(buf, " arg%d=%s%s%s", i, prefix, desc, suffix) < 0)
> > > +		goto error;
> > > +
> > > +out:
> > > +	ret = 0;
> > > +error:
> > > +	free(desc);
> > > +	return ret;
> > > +}
> > > +
> > > +static char *synthesize_sdt_probe_command(struct sdt_note *note,
> > > +					const char *pathname,
> > > +					const char *sdtgrp)
> > > +{
> > > +	struct strbuf buf;
> > > +	char *ret = NULL, **args;
> > > +	int i, args_count;
> > > +
> > > +	if (strbuf_init(&buf, 32) < 0)
> > > +		return NULL;
> > > +
> > > +	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
> > > +				sdtgrp, note->name, pathname,
> > > +				sdt_note__get_addr(note)) < 0)
> > > +		goto error;
> > > +
> > > +	if (!note->args)
> > > +		goto out;
> > > +
> > > +	if (note->args) {
> > > +		args = argv_split(note->args, &args_count);
> > > +
> > > +		for (i = 0; i < args_count; ++i) {
> > > +			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
> > > +				goto error;
> > > +		}
> > > +	}
> > > +
> > > +out:
> > > +	ret = strbuf_detach(&buf, NULL);
> > > +error:
> > > +	strbuf_release(&buf);
> > > +	return ret;
> > > +}
> > > +
> > >  int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
> > >  {
> > >  	struct probe_cache_entry *entry = NULL;
> > > @@ -723,11 +883,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
> > >  			entry->pev.group = strdup(sdtgrp);
> > >  			list_add_tail(&entry->node, &pcache->entries);
> > >  		}
> > > -		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> > > -				sdtgrp, note->name, pathname,
> > > -				sdt_note__get_addr(note));
> > > -		if (ret < 0)
> > > +		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
> > > +		if (!buf) {
> > > +			ret = -ENOMEM;
> > >  			break;
> > > +		}
> > > +
> > >  		strlist__add(entry->tevlist, buf);
> > >  		free(buf);
> > >  		entry = NULL;
> > > -- 
> > > 2.10.2
> > > 
> > 
> > 
> > -- 
> > Masami Hiramatsu <mhiramat@kernel.org>


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-07  3:26           ` Masami Hiramatsu
  2016-12-09 15:14             ` Arnaldo Carvalho de Melo
@ 2016-12-14  0:07             ` Alexis Berlemont
  2016-12-14  7:36               ` Ingo Molnar
                                 ` (2 more replies)
  2016-12-14  0:07             ` [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
  2016-12-14  0:07             ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  3 siblings, 3 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-12-14  0:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin

Hi Masami,

Many thanks for your mail.

Here is another patch set which tries to fix the points you mentioned:

* Skip the arguments containing a constant ($123); 
* Review the code in charge of the register renaming (search for '%'
  and parse it);
* Minor changes (print the argument in case of error, skipping, check
  the sdt arg type index);

Many thanks,

Alexis.

Alexis Berlemont (2):
  perf sdt: add scanning of sdt probles arguments
  perf probe: add sdt probes arguments into the uprobe cmd string

 tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
 tools/perf/util/perf_regs.c          |   6 ++
 tools/perf/util/perf_regs.h          |   6 ++
 tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
 tools/perf/util/symbol-elf.c         |  25 +++++-
 tools/perf/util/symbol.h             |   1 +
 6 files changed, 285 insertions(+), 6 deletions(-)

-- 
2.10.2

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

* [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments
  2016-12-07  3:26           ` Masami Hiramatsu
  2016-12-09 15:14             ` Arnaldo Carvalho de Melo
  2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
@ 2016-12-14  0:07             ` Alexis Berlemont
  2017-03-06 13:39               ` Masami Hiramatsu
  2017-03-24 18:44               ` [tip:perf/core] perf sdt: Add scanning of sdt probes arguments tip-bot for Alexis Berlemont
  2016-12-14  0:07             ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  3 siblings, 2 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-12-14  0:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin

During a "perf buildid-cache --add" command, the section
".note.stapsdt" of the "added" binary is scanned in order to list the
available SDT markers available in a binary. The parts containing the
probes arguments were left unscanned.

The whole section is now parsed; the probe arguments are extracted for
later use.

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/util/symbol-elf.c | 25 +++++++++++++++++++++++--
 tools/perf/util/symbol.h     |  1 +
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 99400b0..7725c3f 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 			     struct list_head *sdt_notes)
 {
-	const char *provider, *name;
+	const char *provider, *name, *args;
 	struct sdt_note *tmp = NULL;
 	GElf_Ehdr ehdr;
 	GElf_Addr base_off = 0;
@@ -1881,6 +1881,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 		goto out_free_prov;
 	}
 
+	args = memchr(name, '\0', data + len - name);
+
+	/*
+	 * There is no argument if:
+	 * - We reached the end of the note;
+	 * - There is not enough room to hold a potential string;
+	 * - The argument string is empty or just contains ':'.
+	 */
+	if (args == NULL || data + len - args < 2 ||
+		args[1] == ':' || args[1] == '\0')
+		tmp->args = NULL;
+	else {
+		tmp->args = strdup(++args);
+		if (!tmp->args) {
+			ret = -ENOMEM;
+			goto out_free_name;
+		}
+	}
+
 	if (gelf_getclass(*elf) == ELFCLASS32) {
 		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
 		tmp->bit32 = true;
@@ -1892,7 +1911,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 	if (!gelf_getehdr(*elf, &ehdr)) {
 		pr_debug("%s : cannot get elf header.\n", __func__);
 		ret = -EBADF;
-		goto out_free_name;
+		goto out_free_args;
 	}
 
 	/* Adjust the prelink effect :
@@ -1917,6 +1936,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 	list_add_tail(&tmp->note_list, sdt_notes);
 	return 0;
 
+out_free_args:
+	free(tmp->args);
 out_free_name:
 	free(tmp->name);
 out_free_prov:
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6c358b7..9222c7e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -351,6 +351,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 struct sdt_note {
 	char *name;			/* name of the note*/
 	char *provider;			/* provider name */
+	char *args;
 	bool bit32;			/* whether the location is 32 bits? */
 	union {				/* location, base and semaphore addrs */
 		Elf64_Addr a64[3];
-- 
2.10.2

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

* [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-07  3:26           ` Masami Hiramatsu
                               ` (2 preceding siblings ...)
  2016-12-14  0:07             ` [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2016-12-14  0:07             ` Alexis Berlemont
  2017-01-24  8:50               ` Ravi Bangoria
                                 ` (2 more replies)
  3 siblings, 3 replies; 77+ messages in thread
From: Alexis Berlemont @ 2016-12-14  0:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: Alexis Berlemont, peterz, mingo, acme, alexander.shishkin

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

$ perf buildid-cache -v --add test_sdt
$ perf probe -x test_sdt sdt_libfoo:table_frob
$ perf probe -x test_sdt sdt_libfoo:table_diddle
$ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
$ perf script
test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
 tools/perf/util/perf_regs.c          |   6 ++
 tools/perf/util/perf_regs.h          |   6 ++
 tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
 4 files changed, 261 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f..09a7f55 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -1,4 +1,7 @@
+#include <string.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
 
 const struct sample_reg sample_reg_masks[] = {
@@ -26,3 +29,83 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
 	SMPL_REG_END
 };
+
+struct sdt_name_reg {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+static const struct sdt_name_reg sdt_reg_renamings[] = {
+	SDT_NAME_REG(eax, ax),
+	SDT_NAME_REG(rax, ax),
+	SDT_NAME_REG(ebx, bx),
+	SDT_NAME_REG(rbx, bx),
+	SDT_NAME_REG(ecx, cx),
+	SDT_NAME_REG(rcx, cx),
+	SDT_NAME_REG(edx, dx),
+	SDT_NAME_REG(rdx, dx),
+	SDT_NAME_REG(esi, si),
+	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(edi, di),
+	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(ebp, bp),
+	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG_END,
+};
+
+int sdt_rename_register(char **pdesc, char *old_name)
+{
+	const struct sdt_name_reg *rnames = sdt_reg_renamings;
+	char *new_desc, *old_desc = *pdesc;
+	size_t prefix_len, sdt_len, uprobe_len, old_desc_len, offset;
+	int ret = -1;
+
+	while (ret != 0 && rnames->sdt_name != NULL) {
+		sdt_len = strlen(rnames->sdt_name);
+		ret = strncmp(old_name, rnames->sdt_name, sdt_len);
+		rnames += !!ret;
+	}
+
+	if (rnames->sdt_name == NULL)
+		return 0;
+
+	sdt_len = strlen(rnames->sdt_name);
+	uprobe_len = strlen(rnames->uprobe_name);
+	old_desc_len = strlen(old_desc) + 1;
+
+	new_desc = zalloc(old_desc_len + uprobe_len - sdt_len);
+	if (new_desc == NULL)
+		return -1;
+
+	/* Copy the chars before the register name (at least '%') */
+	prefix_len = old_name - old_desc;
+	memcpy(new_desc, old_desc, prefix_len);
+
+	/* Copy the new register name */
+	memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+	/* Copy the chars after the register name (if need be) */
+	offset = prefix_len + sdt_len;
+	if (offset < old_desc_len) {
+		/*
+		 * The orginal register name can be suffixed by 'b',
+		 * 'w' or 'd' to indicate its size; so, we need to
+		 * skip this char if we met one.
+		 */
+		char sfx = old_desc[offset];
+
+		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
+			offset++;
+	}
+
+	if (offset < old_desc_len)
+		memcpy(new_desc + prefix_len + uprobe_len,
+			old_desc + offset, old_desc_len - offset);
+
+	free(old_desc);
+	*pdesc = new_desc;
+
+	return 0;
+}
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f2..a37e593 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
+int __weak sdt_rename_register(char **pdesc __maybe_unused,
+			char *old_name __maybe_unused)
+{
+	return 0;
+}
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e4..7544a15 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,12 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+int sdt_rename_register(char **pdesc, char *old_name);
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..d8a169e 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
 
 #define MAX_CMDLEN 256
 
@@ -687,6 +688,166 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	char *tmp, *desc = strdup(arg);
+	const char *prefix = "", *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		/* Check that the conversion went OK */
+		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
+			pr_debug4("Failed to parse sdt type\n");
+			goto error;
+		}
+		/* Check that the converted value is OK */
+		if (type_idx < -8 || type_idx > 8) {
+			pr_debug4("Failed to get a valid sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
+		goto out;
+	}
+
+	/*
+	 * If the argument addressing mode is indirect, we must check
+	 * a few things...
+	 */
+	tmp = strchr(desc, '(');
+	if (tmp) {
+		int j;
+
+		/*
+		 * ...if the addressing mode is indirect with a
+		 * positive offset (ex.: "1608(%ax)"), we need to add
+		 * a '+' prefix so as to be compliant with uprobe
+		 * format.
+		 */
+		if (desc[0] != '+' && desc[0] != '-')
+			prefix = "+";
+
+		/*
+		 * ...or if the addressing mode is indirect with a symbol
+		 * as offset, the argument will not be supported by
+		 * the uprobe tracer format; so, let's skip this one.
+		 */
+		for (j = 0; j < tmp - desc; j++) {
+			if (desc[j] != '+' && desc[j] != '-' &&
+				!isdigit(desc[j])) {
+				pr_debug4("Skipping unsupported SDT argument; "
+					"%s\n", desc);
+				goto out;
+			}
+		}
+	}
+
+	/*
+	 * The uprobe tracer format does not support constants; if we
+	 * find one in the current argument, let's skip the argument.
+	 */
+	if (strchr(desc, '$')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
+		goto out;
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below looks for the register names (starting with
+	 * a '%' and tries to perform the needed renamings.
+	 */
+	tmp = strchr(desc, '%');
+	while (tmp) {
+		size_t offset = tmp - desc;
+
+		ret = sdt_rename_register(&desc, desc + offset);
+		if (ret < 0)
+			goto error;
+
+		/*
+		 * The desc pointer might have changed; so, let's not
+		 * try to reuse tmp for next lookup
+		 */
+		tmp = strchr(desc + offset + 1, '%');
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -723,11 +884,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;
-- 
2.10.2

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
@ 2016-12-14  7:36               ` Ingo Molnar
  2017-01-23 11:23                 ` Ravi Bangoria
  2017-01-24  6:58                 ` Ravi Bangoria
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
  2017-03-21  5:08               ` [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Masami Hiramatsu
  2 siblings, 2 replies; 77+ messages in thread
From: Ingo Molnar @ 2016-12-14  7:36 UTC (permalink / raw)
  To: Alexis Berlemont
  Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin, Jiri Olsa


* Alexis Berlemont <alexis.berlemont@gmail.com> wrote:

> Hi Masami,
> 
> Many thanks for your mail.
> 
> Here is another patch set which tries to fix the points you mentioned:
> 
> * Skip the arguments containing a constant ($123); 
> * Review the code in charge of the register renaming (search for '%'
>   and parse it);
> * Minor changes (print the argument in case of error, skipping, check
>   the sdt arg type index);
> 
> Many thanks,
> 
> Alexis.
> 
> Alexis Berlemont (2):
>   perf sdt: add scanning of sdt probles arguments
>   perf probe: add sdt probes arguments into the uprobe cmd string

I'd like to hijack this thread to report an SDT oddity - one of my boxen reports 
lots of SDT tracepoints in 'perf list':

  mem:<addr>[/len][:access]                          [Hardware breakpoint]

  sdt_libc:lll_lock_wait_private                     [SDT event]
  sdt_libc:longjmp                                   [SDT event]
  sdt_libc:longjmp_target                            [SDT event]
  sdt_libc:memory_arena_new                          [SDT event]
  sdt_libc:memory_arena_retry                        [SDT event]
  sdt_libc:memory_arena_reuse                        [SDT event]
  sdt_libc:memory_arena_reuse_free_list              [SDT event]
  sdt_libc:memory_arena_reuse_wait                   [SDT event]
  sdt_libc:memory_calloc_retry                       [SDT event]
  sdt_libc:memory_heap_free                          [SDT event]
  ...

But none of them work:

  Error:  No permissions to read /sys/kernel/debug/tracing/events/sdt_libc/longjmp
  Hint:   Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'

  ...

  Error:  File /sys/kernel/debug/tracing/events/sdt_libc/longjmp not found.
  Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.

What kind of patches are required for SDT probes to work?

Thanks,

	Ingo

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-14  7:36               ` Ingo Molnar
@ 2017-01-23 11:23                 ` Ravi Bangoria
  2017-02-22 22:41                   ` Alexis Berlemont
  2017-01-24  6:58                 ` Ravi Bangoria
  1 sibling, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-01-23 11:23 UTC (permalink / raw)
  To: Ingo Molnar, Alexis Berlemont
  Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin, Jiri Olsa,
	Ravi Bangoria



On Wednesday 14 December 2016 01:06 PM, Ingo Molnar wrote:
> * Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
>
>> Hi Masami,
>>
>> Many thanks for your mail.
>>
>> Here is another patch set which tries to fix the points you mentioned:
>>
>> * Skip the arguments containing a constant ($123); 
>> * Review the code in charge of the register renaming (search for '%'
>>   and parse it);
>> * Minor changes (print the argument in case of error, skipping, check
>>   the sdt arg type index);
>>
>> Many thanks,
>>
>> Alexis.
>>
>> Alexis Berlemont (2):
>>   perf sdt: add scanning of sdt probles arguments
>>   perf probe: add sdt probes arguments into the uprobe cmd string
> I'd like to hijack this thread to report an SDT oddity - one of my boxen reports 
> lots of SDT tracepoints in 'perf list':
>
>   mem:<addr>[/len][:access]                          [Hardware breakpoint]
>
>   sdt_libc:lll_lock_wait_private                     [SDT event]
>   sdt_libc:longjmp                                   [SDT event]
>   sdt_libc:longjmp_target                            [SDT event]
>   sdt_libc:memory_arena_new                          [SDT event]
>   sdt_libc:memory_arena_retry                        [SDT event]
>   sdt_libc:memory_arena_reuse                        [SDT event]
>   sdt_libc:memory_arena_reuse_free_list              [SDT event]
>   sdt_libc:memory_arena_reuse_wait                   [SDT event]
>   sdt_libc:memory_calloc_retry                       [SDT event]
>   sdt_libc:memory_heap_free                          [SDT event]
>   ...
>
> But none of them work:
>
>   Error:  No permissions to read /sys/kernel/debug/tracing/events/sdt_libc/longjmp
>   Hint:   Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
>
>   ...
>
>   Error:  File /sys/kernel/debug/tracing/events/sdt_libc/longjmp not found.
>   Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
>
> What kind of patches are required for SDT probes to work?

Hi Ingo,

Works for me on my x86 Fedora 25 box. May be some permission issue?

@Alexis, Planning to progress on it :) ? I would like to prepare patch for
powerpc.

Thanks,
Ravi

> Thanks,
>
> 	Ingo
>

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-14  7:36               ` Ingo Molnar
  2017-01-23 11:23                 ` Ravi Bangoria
@ 2017-01-24  6:58                 ` Ravi Bangoria
  2017-01-24  8:22                   ` Ingo Molnar
  1 sibling, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-01-24  6:58 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alexis Berlemont, linux-kernel, peterz, mingo, acme,
	alexander.shishkin, Jiri Olsa, Ravi Bangoria



On Wednesday 14 December 2016 01:06 PM, Ingo Molnar wrote:
> * Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
>
>> Hi Masami,
>>
>> Many thanks for your mail.
>>
>> Here is another patch set which tries to fix the points you mentioned:
>>
>> * Skip the arguments containing a constant ($123); 
>> * Review the code in charge of the register renaming (search for '%'
>>   and parse it);
>> * Minor changes (print the argument in case of error, skipping, check
>>   the sdt arg type index);
>>
>> Many thanks,
>>
>> Alexis.
>>
>> Alexis Berlemont (2):
>>   perf sdt: add scanning of sdt probles arguments
>>   perf probe: add sdt probes arguments into the uprobe cmd string
> I'd like to hijack this thread to report an SDT oddity - one of my boxen reports 
> lots of SDT tracepoints in 'perf list':
>
>   mem:<addr>[/len][:access]                          [Hardware breakpoint]
>
>   sdt_libc:lll_lock_wait_private                     [SDT event]
>   sdt_libc:longjmp                                   [SDT event]
>   sdt_libc:longjmp_target                            [SDT event]
>   sdt_libc:memory_arena_new                          [SDT event]
>   sdt_libc:memory_arena_retry                        [SDT event]
>   sdt_libc:memory_arena_reuse                        [SDT event]
>   sdt_libc:memory_arena_reuse_free_list              [SDT event]
>   sdt_libc:memory_arena_reuse_wait                   [SDT event]
>   sdt_libc:memory_calloc_retry                       [SDT event]
>   sdt_libc:memory_heap_free                          [SDT event]
>   ...
>
> But none of them work:
>
>   Error:  No permissions to read /sys/kernel/debug/tracing/events/sdt_libc/longjmp
>   Hint:   Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
>
>   ...
>
>   Error:  File /sys/kernel/debug/tracing/events/sdt_libc/longjmp not found.
>   Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
>
> What kind of patches are required for SDT probes to work?

Hi Ingo,

I suppose you are trying to record SDT events without probing it.
In that case, first put a probe on an event and then try to record
it. For example,

$ ./perf list | grep sdt_
  sdt_glib:main__after_prepare                       [SDT event]
  sdt_glib:main__before_dispatch                     [SDT event]
  ...

$ ./perf record -a -e sdt_glib:main__after_prepare
  event syntax error: 'sdt_glib:main__after_prepare'
                       \___ unknown tracepoint

  Error:  File /sys/kernel/debug/tracing/events/sdt_glib/main__after_prepare not found.
  Hint: Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
  ...

$ ./perf probe sdt_glib:main__after_prepare
  Added new events:
    sdt_glib:main__after_prepare (on %main__after_prepare in /usr/lib64/libglib-2.0.so.0.5000.2)
    sdt_glib:main__after_prepare_1 (on %main__after_prepare in /usr/lib64/libglib-2.0.so.0.5000.2)

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

    perf record -e sdt_glib:main__after_prepare_1 -aR sleep 1

$ ./perf record -a -e sdt_glib:main__after_prepare
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.191 MB perf.data ]

-Ravi

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2017-01-24  6:58                 ` Ravi Bangoria
@ 2017-01-24  8:22                   ` Ingo Molnar
  2017-01-24  8:36                     ` Ravi Bangoria
  0 siblings, 1 reply; 77+ messages in thread
From: Ingo Molnar @ 2017-01-24  8:22 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: Alexis Berlemont, linux-kernel, peterz, mingo, acme,
	alexander.shishkin, Jiri Olsa


* Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> 
> 
> On Wednesday 14 December 2016 01:06 PM, Ingo Molnar wrote:
> > * Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
> >
> >> Hi Masami,
> >>
> >> Many thanks for your mail.
> >>
> >> Here is another patch set which tries to fix the points you mentioned:
> >>
> >> * Skip the arguments containing a constant ($123); 
> >> * Review the code in charge of the register renaming (search for '%'
> >>   and parse it);
> >> * Minor changes (print the argument in case of error, skipping, check
> >>   the sdt arg type index);
> >>
> >> Many thanks,
> >>
> >> Alexis.
> >>
> >> Alexis Berlemont (2):
> >>   perf sdt: add scanning of sdt probles arguments
> >>   perf probe: add sdt probes arguments into the uprobe cmd string
> > I'd like to hijack this thread to report an SDT oddity - one of my boxen reports 
> > lots of SDT tracepoints in 'perf list':
> >
> >   mem:<addr>[/len][:access]                          [Hardware breakpoint]
> >
> >   sdt_libc:lll_lock_wait_private                     [SDT event]
> >   sdt_libc:longjmp                                   [SDT event]
> >   sdt_libc:longjmp_target                            [SDT event]
> >   sdt_libc:memory_arena_new                          [SDT event]
> >   sdt_libc:memory_arena_retry                        [SDT event]
> >   sdt_libc:memory_arena_reuse                        [SDT event]
> >   sdt_libc:memory_arena_reuse_free_list              [SDT event]
> >   sdt_libc:memory_arena_reuse_wait                   [SDT event]
> >   sdt_libc:memory_calloc_retry                       [SDT event]
> >   sdt_libc:memory_heap_free                          [SDT event]
> >   ...
> >
> > But none of them work:
> >
> >   Error:  No permissions to read /sys/kernel/debug/tracing/events/sdt_libc/longjmp
> >   Hint:   Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
> >
> >   ...
> >
> >   Error:  File /sys/kernel/debug/tracing/events/sdt_libc/longjmp not found.
> >   Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
> >
> > What kind of patches are required for SDT probes to work?
> 
> Hi Ingo,
> 
> I suppose you are trying to record SDT events without probing it.
> In that case, first put a probe on an event and then try to record
> it. For example,


Well, I was mainly complaining about the misleading messages and flow of the 
tooling here. Could you please improve the messages so that if I use it like the 
way I reported it results in me trying the right approach?

Thanks,

	Ingo

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2017-01-24  8:22                   ` Ingo Molnar
@ 2017-01-24  8:36                     ` Ravi Bangoria
  0 siblings, 0 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-01-24  8:36 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Alexis Berlemont, linux-kernel, peterz, mingo, acme,
	alexander.shishkin, Jiri Olsa, Ravi Bangoria, Hemant Kumar



On Tuesday 24 January 2017 01:52 PM, Ingo Molnar wrote:
> * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
>
>>
>> On Wednesday 14 December 2016 01:06 PM, Ingo Molnar wrote:
>>> * Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
>>>
>>>> Hi Masami,
>>>>
>>>> Many thanks for your mail.
>>>>
>>>> Here is another patch set which tries to fix the points you mentioned:
>>>>
>>>> * Skip the arguments containing a constant ($123); 
>>>> * Review the code in charge of the register renaming (search for '%'
>>>>   and parse it);
>>>> * Minor changes (print the argument in case of error, skipping, check
>>>>   the sdt arg type index);
>>>>
>>>> Many thanks,
>>>>
>>>> Alexis.
>>>>
>>>> Alexis Berlemont (2):
>>>>   perf sdt: add scanning of sdt probles arguments
>>>>   perf probe: add sdt probes arguments into the uprobe cmd string
>>> I'd like to hijack this thread to report an SDT oddity - one of my boxen reports 
>>> lots of SDT tracepoints in 'perf list':
>>>
>>>   mem:<addr>[/len][:access]                          [Hardware breakpoint]
>>>
>>>   sdt_libc:lll_lock_wait_private                     [SDT event]
>>>   sdt_libc:longjmp                                   [SDT event]
>>>   sdt_libc:longjmp_target                            [SDT event]
>>>   sdt_libc:memory_arena_new                          [SDT event]
>>>   sdt_libc:memory_arena_retry                        [SDT event]
>>>   sdt_libc:memory_arena_reuse                        [SDT event]
>>>   sdt_libc:memory_arena_reuse_free_list              [SDT event]
>>>   sdt_libc:memory_arena_reuse_wait                   [SDT event]
>>>   sdt_libc:memory_calloc_retry                       [SDT event]
>>>   sdt_libc:memory_heap_free                          [SDT event]
>>>   ...
>>>
>>> But none of them work:
>>>
>>>   Error:  No permissions to read /sys/kernel/debug/tracing/events/sdt_libc/longjmp
>>>   Hint:   Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
>>>
>>>   ...
>>>
>>>   Error:  File /sys/kernel/debug/tracing/events/sdt_libc/longjmp not found.
>>>   Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
>>>
>>> What kind of patches are required for SDT probes to work?
>> Hi Ingo,
>>
>> I suppose you are trying to record SDT events without probing it.
>> In that case, first put a probe on an event and then try to record
>> it. For example,
>
> Well, I was mainly complaining about the misleading messages and flow of the 
> tooling here. Could you please improve the messages so that if I use it like the 
> way I reported it results in me trying the right approach?

Right, message is misleading. Will prepare a patch for this.

Also it's little odd flow for sdt markers, to put a probe first and then
record it while other events can be recorded directly. There was a
patch by Hemant about directly recording SDT marker events. I
don't see any updates on that:

https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1138183.html

-Ravi

> Thanks,
>
> 	Ingo
>

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

* Re: [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-14  0:07             ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
@ 2017-01-24  8:50               ` Ravi Bangoria
  2017-03-06 17:23               ` Masami Hiramatsu
  2017-03-24 18:44               ` [tip:perf/core] perf probe: Add " tip-bot for Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-01-24  8:50 UTC (permalink / raw)
  To: Alexis Berlemont
  Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin, Ravi Bangoria

Hi Alexis,

On Wednesday 14 December 2016 05:37 AM, Alexis Berlemont wrote:
> An sdt probe can be associated with arguments but they were not passed
> to the user probe tracing interface (uprobe_events); this patch adapts
> the sdt argument descriptors according to the uprobe input format.
>
> As the uprobe parser does not support scaled address mode, perf will
> skip arguments which cannot be adapted to the uprobe format.
>
> Here are the results:
>
> $ perf buildid-cache -v --add test_sdt
> $ perf probe -x test_sdt sdt_libfoo:table_frob
> $ perf probe -x test_sdt sdt_libfoo:table_diddle
> $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> $ perf script
> test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8
>
> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>  tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
>  tools/perf/util/perf_regs.c          |   6 ++
>  tools/perf/util/perf_regs.h          |   6 ++
>  tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
>  4 files changed, 261 insertions(+), 4 deletions(-)
>
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index c5db14f..09a7f55 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -1,4 +1,7 @@
> +#include <string.h>
> +
>  #include "../../perf.h"
> +#include "../../util/util.h"
>  #include "../../util/perf_regs.h"
>
>  const struct sample_reg sample_reg_masks[] = {
> @@ -26,3 +29,83 @@ const struct sample_reg sample_reg_masks[] = {
>  #endif
>  	SMPL_REG_END
>  };
> +
> +struct sdt_name_reg {
> +	const char *sdt_name;
> +	const char *uprobe_name;
> +};
> +#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> +#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
> +
> +static const struct sdt_name_reg sdt_reg_renamings[] = {
> +	SDT_NAME_REG(eax, ax),
> +	SDT_NAME_REG(rax, ax),
> +	SDT_NAME_REG(ebx, bx),
> +	SDT_NAME_REG(rbx, bx),
> +	SDT_NAME_REG(ecx, cx),
> +	SDT_NAME_REG(rcx, cx),
> +	SDT_NAME_REG(edx, dx),
> +	SDT_NAME_REG(rdx, dx),
> +	SDT_NAME_REG(esi, si),
> +	SDT_NAME_REG(rsi, si),
> +	SDT_NAME_REG(edi, di),
> +	SDT_NAME_REG(rdi, di),
> +	SDT_NAME_REG(ebp, bp),
> +	SDT_NAME_REG(rbp, bp),
> +	SDT_NAME_REG_END,
> +};

I see many markers uses %rsp. Such markers are failing at perf probe.
Please add renaming entry for %rsp and %esp. For example:

$ readelf -n /usr/lib64/libpython3.5m.so.1.0
  ...
  Name: function__entry
  Arguments: 8@224(%rsp) 8@232(%rsp) -4@240(%rsp) 8@%rbx

$ sudo ./perf probe sdt_python:function__entry
  Failed to write event: Invalid argument
  Please upgrade your kernel to at least 3.14 to have access to feature +224(%rsp):u64
    Error: Failed to add events.


This code does not handle rNN registers with postfix('b', 'w', 'd').
Such markers are failing at perf probe. For example:

$ readelf -n /usr/lib64/libperl.so.5.24.0
  ...
  Name: sub__return
  Arguments: 8@%rax 8@%r8 4@%r9d 8@%rsi

$ sudo ./perf probe -v sdt_perl:sub__entry
  ...
  Opening /sys/kernel/debug/tracing//uprobe_events write=1
  Writing event: p:sdt_perl/sub__entry /usr/lib64/libperl.so.5.24.0:0xbb780 arg1=%ax:u64 arg2=%r8:u64 arg3=%r9d:u32 arg4=%si:u64
  Failed to write event: Invalid argument
    Error: Failed to add events. Reason: Invalid argument (Code: -22)

 Can we add them like:

    /* rNN registers */
    SDT_NAME_REG(r8b,  r8),
    SDT_NAME_REG(r8w,  r8),
    SDT_NAME_REG(r8d,  r8),
    SDT_NAME_REG(r9b,  r9),
    ...
    SDT_NAME_REG(r14d, r14),
    SDT_NAME_REG(r15b, r15),
    SDT_NAME_REG(r15w, r15),
    SDT_NAME_REG(r15d, r15),

and ...

> +
> +int sdt_rename_register(char **pdesc, char *old_name)
> +{
> +	const struct sdt_name_reg *rnames = sdt_reg_renamings;
> +	char *new_desc, *old_desc = *pdesc;
> +	size_t prefix_len, sdt_len, uprobe_len, old_desc_len, offset;
> +	int ret = -1;
> +
> +	while (ret != 0 && rnames->sdt_name != NULL) {
> +		sdt_len = strlen(rnames->sdt_name);
> +		ret = strncmp(old_name, rnames->sdt_name, sdt_len);
> +		rnames += !!ret;
> +	}
> +
> +	if (rnames->sdt_name == NULL)
> +		return 0;
> +
> +	sdt_len = strlen(rnames->sdt_name);
> +	uprobe_len = strlen(rnames->uprobe_name);
> +	old_desc_len = strlen(old_desc) + 1;
> +
> +	new_desc = zalloc(old_desc_len + uprobe_len - sdt_len);
> +	if (new_desc == NULL)
> +		return -1;
> +
> +	/* Copy the chars before the register name (at least '%') */
> +	prefix_len = old_name - old_desc;
> +	memcpy(new_desc, old_desc, prefix_len);
> +
> +	/* Copy the new register name */
> +	memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
> +
> +	/* Copy the chars after the register name (if need be) */
> +	offset = prefix_len + sdt_len;

... remove below if(){} block.

> +	if (offset < old_desc_len) {
> +		/*
> +		 * The orginal register name can be suffixed by 'b',
> +		 * 'w' or 'd' to indicate its size; so, we need to
> +		 * skip this char if we met one.
> +		 */
> +		char sfx = old_desc[offset];
> +
> +		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
> +			offset++;
> +	}
> +
> +	if (offset < old_desc_len)
> +		memcpy(new_desc + prefix_len + uprobe_len,
> +			old_desc + offset, old_desc_len - offset);
> +
> +	free(old_desc);
> +	*pdesc = new_desc;
> +
> +	return 0;
> +}
> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index c4023f2..a37e593 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
>  	SMPL_REG_END
>  };
>
> +int __weak sdt_rename_register(char **pdesc __maybe_unused,
> +			char *old_name __maybe_unused)
> +{
> +	return 0;
> +}
> +
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
>  {
> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index 679d6e4..7544a15 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -15,6 +15,12 @@ struct sample_reg {
>
>  extern const struct sample_reg sample_reg_masks[];
>
> +/*
> + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> + * registers before filling the uprobe tracer interface.
> + */
> +int sdt_rename_register(char **pdesc, char *old_name);
> +
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  #include <perf_regs.h>
>
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 436b647..d8a169e 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -27,6 +27,7 @@
>  #include "probe-event.h"
>  #include "probe-file.h"
>  #include "session.h"
> +#include "perf_regs.h"
>
>  #define MAX_CMDLEN 256
>
> @@ -687,6 +688,166 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
>  		 : (unsigned long long)note->addr.a64[0];
>  }
>
> +static const char * const type_to_suffix[] = {
> +	":s64", "", "", "", ":s32", "", ":s16", ":s8",
> +	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
> +};
> +
> +static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
> +{
> +	char *tmp, *desc = strdup(arg);
> +	const char *prefix = "", *suffix = "";
> +	int ret = -1;
> +
> +	if (desc == NULL) {
> +		pr_debug4("Allocation error\n");
> +		return ret;
> +	}
> +
> +	tmp = strchr(desc, '@');
> +	if (tmp) {
> +		long type_idx;
> +		/*
> +		 * Isolate the string number and convert it into a
> +		 * binary value; this will be an index to get suffix
> +		 * of the uprobe name (defining the type)
> +		 */
> +		tmp[0] = '\0';
> +		type_idx = strtol(desc, NULL, 10);
> +		/* Check that the conversion went OK */
> +		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
> +			pr_debug4("Failed to parse sdt type\n");
> +			goto error;
> +		}
> +		/* Check that the converted value is OK */
> +		if (type_idx < -8 || type_idx > 8) {
> +			pr_debug4("Failed to get a valid sdt type\n");
> +			goto error;
> +		}
> +		suffix = type_to_suffix[type_idx + 8];
> +		/* Get rid of the sdt prefix which is now useless */
> +		tmp++;
> +		memmove(desc, tmp, strlen(tmp) + 1);
> +	}
> +

Below code is x86 specific. For example, Powerpc uses "i" for constant
arguments not "$". Powerpc does not use symbol as offset etc.

SDT marker argument is in N@OP format. Can we divide this function into
two components. One parses N and other parses OP. Parsing OP will be
arch specific code and should be moved under /tools/perf/arch/.

> +	/*
> +	 * The uprobe tracer format does not support all the
> +	 * addressing modes (notably: in x86 the scaled mode); so, we
> +	 * detect ',' characters, if there is just one, there is no
> +	 * use converting the sdt arg into a uprobe one.
> +	 */
> +	if (strchr(desc, ',')) {
> +		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> +		goto out;
> +	}
> +
> +	/*
> +	 * If the argument addressing mode is indirect, we must check
> +	 * a few things...
> +	 */
> +	tmp = strchr(desc, '(');
> +	if (tmp) {
> +		int j;
> +
> +		/*
> +		 * ...if the addressing mode is indirect with a
> +		 * positive offset (ex.: "1608(%ax)"), we need to add
> +		 * a '+' prefix so as to be compliant with uprobe
> +		 * format.
> +		 */
> +		if (desc[0] != '+' && desc[0] != '-')
> +			prefix = "+";
> +
> +		/*
> +		 * ...or if the addressing mode is indirect with a symbol
> +		 * as offset, the argument will not be supported by
> +		 * the uprobe tracer format; so, let's skip this one.
> +		 */
> +		for (j = 0; j < tmp - desc; j++) {
> +			if (desc[j] != '+' && desc[j] != '-' &&
> +				!isdigit(desc[j])) {
> +				pr_debug4("Skipping unsupported SDT argument; "
> +					"%s\n", desc);
> +				goto out;
> +			}
> +		}
> +	}
> +
> +	/*
> +	 * The uprobe tracer format does not support constants; if we
> +	 * find one in the current argument, let's skip the argument.
> +	 */
> +	if (strchr(desc, '$')) {
> +		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> +		goto out;
> +	}
> +
> +	/*
> +	 * The uprobe parser does not support all gas register names;
> +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> +	 * the loop below looks for the register names (starting with
> +	 * a '%' and tries to perform the needed renamings.
> +	 */
> +	tmp = strchr(desc, '%');
> +	while (tmp) {
> +		size_t offset = tmp - desc;
> +
> +		ret = sdt_rename_register(&desc, desc + offset);
> +		if (ret < 0)
> +			goto error;
> +
> +		/*
> +		 * The desc pointer might have changed; so, let's not
> +		 * try to reuse tmp for next lookup
> +		 */
> +		tmp = strchr(desc + offset + 1, '%');
> +	}
> +
> +	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
> +		goto error;
> +
> +out:
> +	ret = 0;
> +error:
> +	free(desc);
> +	return ret;
> +}

Thanks,
Ravi

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

* [PATCH 0/5] perf/sdt: Argument support for x86 and powepc
  2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
  2016-12-14  7:36               ` Ingo Molnar
@ 2017-02-02 11:11               ` Ravi Bangoria
  2017-02-02 11:11                 ` [PATCH 1/5] perf/sdt: Show proper hint Ravi Bangoria
                                   ` (5 more replies)
  2017-03-21  5:08               ` [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Masami Hiramatsu
  2 siblings, 6 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-02 11:11 UTC (permalink / raw)
  To: acme, alexis.berlemont, linux-kernel
  Cc: peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, mhiramat,
	maddy, Ravi Bangoria

The v5 patchset for sdt marker argument support for x86 [1] has
couple  of issues. For example, it still has x86 specific code
in general code. It lacks support for rNN (with size postfix
b/w/d), %rsp, %esp, %sil etc. registers and such sdt markers
are failing at 'perf probe'. It also fails to convert arguments
having no offset but still surrounds register with parenthesis
for ex. 8@(%rdi) is converted to +(%di):u64 which is rejected
by uprobe_events. It's causing failure at 'perf probe' for all
SDT events on all archs except x86. With this patchset, I've
solved these issues. (patch 2,3)

Also, existing perf shows misleading message when user tries to
record sdt event without probing it. I've prepared patch for
the same. (patch 1)

Apart from that, I've also added logic to support arguments with
sdt marker on powerpc. (patch 4)

There are cases where uprobe definition of sdt event goes beyond
current limit MAX_CMDLEN (256) and in such case perf fails with
seg fault. I've solve this issue. (patch 5)

Note: This patchset is prepared on top of Alexis' v5 series.[1]

[1] http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1292251.html

Ravi Bangoria (5):
  perf/sdt: Show proper hint
  perf/sdt/x86: Add renaming logic for rNN and other registers
  perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  perf/sdt/powerpc: Add argument support
  perf/probe: Change MAX_CMDLEN

 tools/lib/api/fs/tracing_path.c          |  16 +++-
 tools/perf/arch/powerpc/util/perf_regs.c | 115 ++++++++++++++++++++++++++
 tools/perf/arch/x86/util/perf_regs.c     | 137 ++++++++++++++++++++++++++++---
 tools/perf/util/perf_regs.c              |   9 +-
 tools/perf/util/perf_regs.h              |   7 +-
 tools/perf/util/probe-event.c            |   1 -
 tools/perf/util/probe-file.c             | 129 ++++++++---------------------
 7 files changed, 294 insertions(+), 120 deletions(-)

-- 
2.9.3

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

* [PATCH 1/5] perf/sdt: Show proper hint
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
@ 2017-02-02 11:11                 ` Ravi Bangoria
  2017-02-02 13:40                   ` Ingo Molnar
  2017-02-02 11:11                 ` [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers Ravi Bangoria
                                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-02 11:11 UTC (permalink / raw)
  To: acme, alexis.berlemont, linux-kernel
  Cc: peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, mhiramat,
	maddy, Ravi Bangoria

All events from 'perf list', except SDT events, can be directly
recorded with 'perf record'. But, the flow is little different
for SDT events. User has to probe on SDT events before recording
them. Perf is showing misleading message when user tries to
record SDT event without probing it. Show proper hint there.

Before patch:
  $ perf record -a -e sdt_glib:idle__add
    event syntax error: 'sdt_glib:idle__add'
                     \___ unknown tracepoint

    Error:  File /sys/kernel/debug/tracing/events/sdt_glib/idle__add ...
    Hint:   Perhaps this kernel misses some CONFIG_ setting to enable...
    ...

After patch:
  $ perf record -e sdt_glib:main__after_check
    event syntax error: 'sdt_glib:idle__add'
                     \___ unknown tracepoint

    Error:  File /sys/kernel/debug/tracing/events/sdt_glib/idle__add ...
    Hint:   SDT event has to be probed before recording it.

Suggested-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/lib/api/fs/tracing_path.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 251b7c3..a0e85df 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -99,10 +99,18 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
 		 * - jirka
 		 */
 		if (debugfs__configured() || tracefs__configured()) {
-			snprintf(buf, size,
-				 "Error:\tFile %s/%s not found.\n"
-				 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
-				 tracing_events_path, filename);
+			/* sdt markers */
+			if (!strncmp(filename, "sdt_", 4)) {
+				snprintf(buf, size,
+					"Error:\tFile %s/%s not found.\n"
+					"Hint:\tSDT event has to be probed before recording it.\n",
+					tracing_events_path, filename);
+			} else {
+				snprintf(buf, size,
+					 "Error:\tFile %s/%s not found.\n"
+					 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
+					 tracing_events_path, filename);
+			}
 			break;
 		}
 		snprintf(buf, size, "%s",
-- 
2.9.3

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

* [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
  2017-02-02 11:11                 ` [PATCH 1/5] perf/sdt: Show proper hint Ravi Bangoria
@ 2017-02-02 11:11                 ` Ravi Bangoria
  2017-02-07  3:11                   ` Masami Hiramatsu
  2017-03-24 18:45                   ` [tip:perf/core] perf sdt x86: " tip-bot for Ravi Bangoria
  2017-02-02 11:11                 ` [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Ravi Bangoria
                                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-02 11:11 UTC (permalink / raw)
  To: acme, alexis.berlemont, linux-kernel
  Cc: peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, mhiramat,
	maddy, Ravi Bangoria

'perf probe' is failing for sdt markers whose arguments has rNN
(with postfix b/w/d), %rsp, %esp, %sil etc. registers. Add renaming
logic for these registers.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/perf/arch/x86/util/perf_regs.c | 44 ++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index 09a7f55..d8a8dcf 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -48,10 +48,42 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
 	SDT_NAME_REG(rdx, dx),
 	SDT_NAME_REG(esi, si),
 	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(sil, si),
 	SDT_NAME_REG(edi, di),
 	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(dil, di),
 	SDT_NAME_REG(ebp, bp),
 	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG(bpl, bp),
+	SDT_NAME_REG(rsp, sp),
+	SDT_NAME_REG(esp, sp),
+	SDT_NAME_REG(spl, sp),
+
+	/* rNN registers */
+	SDT_NAME_REG(r8b,  r8),
+	SDT_NAME_REG(r8w,  r8),
+	SDT_NAME_REG(r8d,  r8),
+	SDT_NAME_REG(r9b,  r9),
+	SDT_NAME_REG(r9w,  r9),
+	SDT_NAME_REG(r9d,  r9),
+	SDT_NAME_REG(r10b, r10),
+	SDT_NAME_REG(r10w, r10),
+	SDT_NAME_REG(r10d, r10),
+	SDT_NAME_REG(r11b, r11),
+	SDT_NAME_REG(r11w, r11),
+	SDT_NAME_REG(r11d, r11),
+	SDT_NAME_REG(r12b, r12),
+	SDT_NAME_REG(r12w, r12),
+	SDT_NAME_REG(r12d, r12),
+	SDT_NAME_REG(r13b, r13),
+	SDT_NAME_REG(r13w, r13),
+	SDT_NAME_REG(r13d, r13),
+	SDT_NAME_REG(r14b, r14),
+	SDT_NAME_REG(r14w, r14),
+	SDT_NAME_REG(r14d, r14),
+	SDT_NAME_REG(r15b, r15),
+	SDT_NAME_REG(r15w, r15),
+	SDT_NAME_REG(r15d, r15),
 	SDT_NAME_REG_END,
 };
 
@@ -88,18 +120,6 @@ int sdt_rename_register(char **pdesc, char *old_name)
 
 	/* Copy the chars after the register name (if need be) */
 	offset = prefix_len + sdt_len;
-	if (offset < old_desc_len) {
-		/*
-		 * The orginal register name can be suffixed by 'b',
-		 * 'w' or 'd' to indicate its size; so, we need to
-		 * skip this char if we met one.
-		 */
-		char sfx = old_desc[offset];
-
-		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
-			offset++;
-	}
-
 	if (offset < old_desc_len)
 		memcpy(new_desc + prefix_len + uprobe_len,
 			old_desc + offset, old_desc_len - offset);
-- 
2.9.3

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

* [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
  2017-02-02 11:11                 ` [PATCH 1/5] perf/sdt: Show proper hint Ravi Bangoria
  2017-02-02 11:11                 ` [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers Ravi Bangoria
@ 2017-02-02 11:11                 ` Ravi Bangoria
  2017-02-07  3:11                   ` Masami Hiramatsu
  2017-03-21 14:55                   ` Masami Hiramatsu
  2017-02-02 11:11                 ` [PATCH 4/5] perf/sdt/powerpc: Add argument support Ravi Bangoria
                                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-02 11:11 UTC (permalink / raw)
  To: acme, alexis.berlemont, linux-kernel
  Cc: peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, mhiramat,
	maddy, Ravi Bangoria

SDT marker argument is in N@OP format. N is the size of argument and
OP is the actual assembly operand. OP is arch dependent component and
hence it's parsing logic also should be placed under tools/perf/arch/.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  93 ++++++++++++++++++++++++-
 tools/perf/util/perf_regs.c          |   9 ++-
 tools/perf/util/perf_regs.h          |   7 +-
 tools/perf/util/probe-file.c         | 127 +++++++++--------------------------
 4 files changed, 134 insertions(+), 102 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index d8a8dcf..34fcb0d 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -3,6 +3,7 @@
 #include "../../perf.h"
 #include "../../util/util.h"
 #include "../../util/perf_regs.h"
+#include "../../util/debug.h"
 
 const struct sample_reg sample_reg_masks[] = {
 	SMPL_REG(AX, PERF_REG_X86_AX),
@@ -87,7 +88,16 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
 	SDT_NAME_REG_END,
 };
 
-int sdt_rename_register(char **pdesc, char *old_name)
+bool arch_sdt_probe_arg_supp(void)
+{
+	return true;
+}
+
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+static int sdt_rename_register(char **pdesc, char *old_name)
 {
 	const struct sdt_name_reg *rnames = sdt_reg_renamings;
 	char *new_desc, *old_desc = *pdesc;
@@ -129,3 +139,84 @@ int sdt_rename_register(char **pdesc, char *old_name)
 
 	return 0;
 }
+
+/*
+ * x86 specific implementation
+ * return value:
+ *	<0 : error
+ *	 0 : success
+ *	>0 : skip
+ */
+int arch_sdt_probe_parse_op(char **desc, const char **prefix)
+{
+	char *tmp;
+	int ret = 0;
+
+	/*
+	 * The uprobe tracer format does not support all the addressing
+	 * modes (notably: in x86 the scaled mode); so, we detect ','
+	 * characters, if there is just one, there is no use converting
+	 * the sdt arg into a uprobe one.
+	 *
+	 * Also it does not support constants; if we find one in the
+	 * current argument, let's skip the argument.
+	 */
+	if (strchr(*desc, ',') || strchr(*desc, '$')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", *desc);
+		return 1;
+	}
+
+	/*
+	 * If the argument addressing mode is indirect, we must check
+	 * a few things...
+	 */
+	tmp = strchr(*desc, '(');
+	if (tmp) {
+		int j;
+
+		/*
+		 * ...if the addressing mode is indirect with a
+		 * positive offset (ex.: "1608(%ax)"), we need to add
+		 * a '+' prefix so as to be compliant with uprobe
+		 * format.
+		 */
+		if ((*desc)[0] != '+' && (*desc)[0] != '-')
+			*prefix = ((*desc)[0] == '(') ? "+0" : "+";
+
+		/*
+		 * ...or if the addressing mode is indirect with a symbol
+		 * as offset, the argument will not be supported by
+		 * the uprobe tracer format; so, let's skip this one.
+		 */
+		for (j = 0; j < tmp - *desc; j++) {
+			if ((*desc)[j] != '+' && (*desc)[j] != '-' &&
+			    !isdigit((*desc)[j])) {
+				pr_debug4("Skipping unsupported SDT argument; "
+					"%s\n", *desc);
+				return 1;
+			}
+		}
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below looks for the register names (starting with
+	 * a '%' and tries to perform the needed renamings.
+	 */
+	tmp = strchr(*desc, '%');
+	while (tmp) {
+		size_t offset = tmp - *desc;
+
+		ret = sdt_rename_register(desc, *desc + offset);
+		if (ret < 0)
+			return ret;
+
+		/*
+		 * The *desc pointer might have changed; so, let's not
+		 * try to reuse tmp for next lookup
+		 */
+		tmp = strchr(*desc + offset + 1, '%');
+	}
+	return 0;
+}
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index a37e593..f2b3d0d 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,8 +6,13 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
-int __weak sdt_rename_register(char **pdesc __maybe_unused,
-			char *old_name __maybe_unused)
+bool __weak arch_sdt_probe_arg_supp(void)
+{
+	return false;
+}
+
+int __weak arch_sdt_probe_parse_op(char **op_ptr __maybe_unused,
+				   const char **prefix __maybe_unused)
 {
 	return 0;
 }
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 7544a15..86a2961 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,11 +15,8 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
-/*
- * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
- * registers before filling the uprobe tracer interface.
- */
-int sdt_rename_register(char **pdesc, char *old_name);
+bool arch_sdt_probe_arg_supp(void);
+int arch_sdt_probe_parse_op(char **op_ptr, const char **prefix);
 
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index d8a169e..38eca3c 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -693,6 +693,25 @@ static const char * const type_to_suffix[] = {
 	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
 };
 
+/*
+ * Isolate the string number and convert it into a decimal value;
+ * this will be an index to get suffix of the uprobe name (defining
+ * the type)
+ */
+static int sdt_probe_parse_n(char *n_ptr, const char **suffix)
+{
+	long type_idx;
+
+	type_idx = strtol(n_ptr, NULL, 10);
+	if (type_idx < -8 || type_idx > 8) {
+		pr_debug4("Failed to get a valid sdt type\n");
+		return -1;
+	}
+
+	*suffix = type_to_suffix[type_idx + 8];
+	return 0;
+}
+
 static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
 {
 	char *tmp, *desc = strdup(arg);
@@ -704,109 +723,29 @@ static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
 		return ret;
 	}
 
+	/*
+	 * Argument is in N@OP format. N is size of the argument and OP is
+	 * the actual assembly operand. N can be omitted; in that case
+	 * argument is just OP(without @).
+	 */
 	tmp = strchr(desc, '@');
 	if (tmp) {
-		long type_idx;
-		/*
-		 * Isolate the string number and convert it into a
-		 * binary value; this will be an index to get suffix
-		 * of the uprobe name (defining the type)
-		 */
 		tmp[0] = '\0';
-		type_idx = strtol(desc, NULL, 10);
-		/* Check that the conversion went OK */
-		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
-			pr_debug4("Failed to parse sdt type\n");
-			goto error;
-		}
-		/* Check that the converted value is OK */
-		if (type_idx < -8 || type_idx > 8) {
-			pr_debug4("Failed to get a valid sdt type\n");
-			goto error;
-		}
-		suffix = type_to_suffix[type_idx + 8];
-		/* Get rid of the sdt prefix which is now useless */
 		tmp++;
-		memmove(desc, tmp, strlen(tmp) + 1);
-	}
 
-	/*
-	 * The uprobe tracer format does not support all the
-	 * addressing modes (notably: in x86 the scaled mode); so, we
-	 * detect ',' characters, if there is just one, there is no
-	 * use converting the sdt arg into a uprobe one.
-	 */
-	if (strchr(desc, ',')) {
-		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
-		goto out;
-	}
-
-	/*
-	 * If the argument addressing mode is indirect, we must check
-	 * a few things...
-	 */
-	tmp = strchr(desc, '(');
-	if (tmp) {
-		int j;
-
-		/*
-		 * ...if the addressing mode is indirect with a
-		 * positive offset (ex.: "1608(%ax)"), we need to add
-		 * a '+' prefix so as to be compliant with uprobe
-		 * format.
-		 */
-		if (desc[0] != '+' && desc[0] != '-')
-			prefix = "+";
-
-		/*
-		 * ...or if the addressing mode is indirect with a symbol
-		 * as offset, the argument will not be supported by
-		 * the uprobe tracer format; so, let's skip this one.
-		 */
-		for (j = 0; j < tmp - desc; j++) {
-			if (desc[j] != '+' && desc[j] != '-' &&
-				!isdigit(desc[j])) {
-				pr_debug4("Skipping unsupported SDT argument; "
-					"%s\n", desc);
-				goto out;
-			}
-		}
-	}
-
-	/*
-	 * The uprobe tracer format does not support constants; if we
-	 * find one in the current argument, let's skip the argument.
-	 */
-	if (strchr(desc, '$')) {
-		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
-		goto out;
-	}
-
-	/*
-	 * The uprobe parser does not support all gas register names;
-	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
-	 * the loop below looks for the register names (starting with
-	 * a '%' and tries to perform the needed renamings.
-	 */
-	tmp = strchr(desc, '%');
-	while (tmp) {
-		size_t offset = tmp - desc;
-
-		ret = sdt_rename_register(&desc, desc + offset);
-		if (ret < 0)
+		if (sdt_probe_parse_n(desc, &suffix))
 			goto error;
-
-		/*
-		 * The desc pointer might have changed; so, let's not
-		 * try to reuse tmp for next lookup
-		 */
-		tmp = strchr(desc + offset + 1, '%');
+		memmove(desc, tmp, strlen(tmp) + 1);
 	}
 
-	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
+	ret = arch_sdt_probe_parse_op(&desc, &prefix);
+	if (ret < 0)
+		goto error;
+
+	if (ret == 0 &&
+	    strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
 		goto error;
 
-out:
 	ret = 0;
 error:
 	free(desc);
@@ -829,7 +768,7 @@ static char *synthesize_sdt_probe_command(struct sdt_note *note,
 				sdt_note__get_addr(note)) < 0)
 		goto error;
 
-	if (!note->args)
+	if (!note->args || !arch_sdt_probe_arg_supp())
 		goto out;
 
 	if (note->args) {
-- 
2.9.3

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

* [PATCH 4/5] perf/sdt/powerpc: Add argument support
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
                                   ` (2 preceding siblings ...)
  2017-02-02 11:11                 ` [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Ravi Bangoria
@ 2017-02-02 11:11                 ` Ravi Bangoria
  2017-02-02 11:11                 ` [PATCH 5/5] perf/probe: Change MAX_CMDLEN Ravi Bangoria
  2017-02-07  2:55                 ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Masami Hiramatsu
  5 siblings, 0 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-02 11:11 UTC (permalink / raw)
  To: acme, alexis.berlemont, linux-kernel
  Cc: peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, mhiramat,
	maddy, Ravi Bangoria

SDT marker argument is in N@OP format. Here OP is arch dependent
component. Add powerpc logic to parse OP and convert it to uprobe
compatible format.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/perf/arch/powerpc/util/perf_regs.c | 115 +++++++++++++++++++++++++++++++
 1 file changed, 115 insertions(+)

diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
index a3c3e1c..bbd6f91 100644
--- a/tools/perf/arch/powerpc/util/perf_regs.c
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -1,5 +1,10 @@
+#include <string.h>
+#include <regex.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
+#include "../../util/debug.h"
 
 const struct sample_reg sample_reg_masks[] = {
 	SMPL_REG(r0, PERF_REG_POWERPC_R0),
@@ -47,3 +52,113 @@ const struct sample_reg sample_reg_masks[] = {
 	SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
 	SMPL_REG_END
 };
+
+bool arch_sdt_probe_arg_supp(void)
+{
+	return true;
+}
+
+static regex_t regex1, regex2;
+
+static int init_op_regex(void)
+{
+	static int initialized;
+
+	if (initialized)
+		return 0;
+
+	/* REG or %rREG */
+	if (regcomp(&regex1, "^(%r)?([1-2]?[0-9]|3[0-1])$", REG_EXTENDED))
+		goto error;
+
+	/* -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) */
+	if (regcomp(&regex2, "^(\\-)?([0-9]+)\\((%r)?([1-2]?[0-9]|3[0-1])\\)$",
+			REG_EXTENDED))
+		goto free_regex1;
+
+	initialized = 1;
+	return 0;
+
+free_regex1:
+	regfree(&regex1);
+error:
+	pr_debug4("Regex compilation error.\n");
+	return -1;
+}
+
+/*
+ * Parse OP and convert it into uprobe format, which is, +/-NUM(%gprREG).
+ * Possible variants of OP are:
+ *	Format		Example
+ *	-------------------------
+ *	NUM(REG)	48(18)
+ *	-NUM(REG)	-48(18)
+ *	NUM(%rREG)	48(%r18)
+ *	-NUM(%rREG)	-48(%r18)
+ *	REG		18
+ *	%rREG		%r18
+ *	iNUM		i0
+ *	i-NUM		i-1
+ *
+ * SDT marker arguments on Powerpc uses %rREG form with -mregnames flag
+ * and REG form with -mno-regnames. Here REG is general purpose register,
+ * which is in 0 to 31 range.
+ *
+ * return value of the function:
+ *	<0 : error
+ *	 0 : success
+ *	>0 : skip
+ */
+int arch_sdt_probe_parse_op(char **desc, const char **prefix)
+{
+	char *tmp = NULL;
+	size_t new_len;
+	regmatch_t rm[5];
+
+	/* Constant argument. Uprobe does not support it */
+	if (*desc[0] == 'i') {
+		pr_debug4("Skipping unsupported SDT argument: %s\n", *desc);
+		return 1;
+	}
+
+	if (init_op_regex() < 0)
+		return -1;
+
+	if (!regexec(&regex1, *desc, 3, rm, 0)) {
+		/* REG or %rREG --> %gprREG */
+		new_len = 5;
+		new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
+
+		tmp = zalloc(new_len);
+		if (!tmp)
+			return -1;
+
+		scnprintf(tmp, new_len, "%%gpr%.*s",
+			(int)(rm[2].rm_eo - rm[2].rm_so), *desc + rm[2].rm_so);
+	} else if (!regexec(&regex2, *desc, 5, rm, 0)) {
+		/*
+		 * -NUM(REG) or NUM(REG) or -NUM(%rREG) or NUM(%rREG) -->
+		 *	+/-NUM(%gprREG)
+		 */
+		*prefix = (rm[1].rm_so == -1) ? "+" : "-";
+
+		new_len = 7;
+		new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
+		new_len += (int)(rm[4].rm_eo - rm[4].rm_so);
+
+		tmp = zalloc(new_len);
+		if (!tmp)
+			return -1;
+
+		scnprintf(tmp, new_len, "%.*s(%%gpr%.*s)",
+			(int)(rm[2].rm_eo - rm[2].rm_so), *desc + rm[2].rm_so,
+			(int)(rm[4].rm_eo - rm[4].rm_so), *desc + rm[4].rm_so);
+	} else {
+		pr_debug4("Skipping unsupported SDT argument: %s\n", *desc);
+		return 1;
+	}
+
+	free(*desc);
+	*desc = tmp;
+	return 0;
+}
-- 
2.9.3

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

* [PATCH 5/5] perf/probe: Change MAX_CMDLEN
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
                                   ` (3 preceding siblings ...)
  2017-02-02 11:11                 ` [PATCH 4/5] perf/sdt/powerpc: Add argument support Ravi Bangoria
@ 2017-02-02 11:11                 ` Ravi Bangoria
  2017-02-07  1:40                   ` Masami Hiramatsu
  2017-02-07  2:55                 ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Masami Hiramatsu
  5 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-02 11:11 UTC (permalink / raw)
  To: acme, alexis.berlemont, linux-kernel
  Cc: peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, mhiramat,
	maddy, Ravi Bangoria

There are many SDT markers in powerpc whose uprobe definition goes
beyond current MAX_CMDLEN, especially when target filename is long
and sdt marker has long list of arguments. For example, definition
of sdt marker

  method__compile__end: 8@17 8@9 8@10 -4@8 8@7 -4@6 8@5 -4@4 1@37(28)

from file

  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.91-2.b14.fc22.ppc64/jre/lib/\
     ppc64/server/libjvm.so

is

  p:sdt_hotspot/method__compile__end /usr/lib/jvm/java-1.8.0-openjdk-\
    1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so:0x4c4e00\
    arg1=%gpr17:u64 arg2=%gpr9:u64 arg3=%gpr10:u64 arg4=%gpr8:s32\
    arg5=%gpr7:u64 arg6=%gpr6:s32 arg7=%gpr5:u64 arg8=%gpr4:s32\
    arg9=+37(%gpr28):u8

Perf probe fails with seg fault for such markers. As uprobe_events file
accepts definition beyond 256 characters, increase value of MAX_CMDLEN
to 512.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/perf/util/probe-event.c | 1 -
 tools/perf/util/probe-file.c  | 2 +-
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 2c1bca2..5f3256f 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
 #include "probe-file.h"
 #include "session.h"
 
-#define MAX_CMDLEN 256
 #define PERFPROBE_GROUP "probe"
 
 bool probe_event_dry_run;	/* Dry run flag */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 38eca3c..1580e26 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -29,7 +29,7 @@
 #include "session.h"
 #include "perf_regs.h"
 
-#define MAX_CMDLEN 256
+#define MAX_CMDLEN 512
 
 static void print_open_warning(int err, bool uprobe)
 {
-- 
2.9.3

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

* Re: [PATCH 1/5] perf/sdt: Show proper hint
  2017-02-02 11:11                 ` [PATCH 1/5] perf/sdt: Show proper hint Ravi Bangoria
@ 2017-02-02 13:40                   ` Ingo Molnar
  2017-02-02 16:20                     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 77+ messages in thread
From: Ingo Molnar @ 2017-02-02 13:40 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy


* Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> After patch:
>   $ perf record -e sdt_glib:main__after_check
>     event syntax error: 'sdt_glib:idle__add'
>                      \___ unknown tracepoint
> 
>     Error:  File /sys/kernel/debug/tracing/events/sdt_glib/idle__add ...
>     Hint:   SDT event has to be probed before recording it.

So what is the command line option to 'probe' an SDT event? Could you give an 
example that would make the above command work?

Thanks,

	Ingo

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

* Re: [PATCH 1/5] perf/sdt: Show proper hint
  2017-02-02 13:40                   ` Ingo Molnar
@ 2017-02-02 16:20                     ` Arnaldo Carvalho de Melo
  2017-02-03 10:26                       ` [PATCH v2] " Ravi Bangoria
  0 siblings, 1 reply; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-02-02 16:20 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Ravi Bangoria, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

Em Thu, Feb 02, 2017 at 02:40:48PM +0100, Ingo Molnar escreveu:
> * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
 
> > After patch:
> >   $ perf record -e sdt_glib:main__after_check
> >     event syntax error: 'sdt_glib:idle__add'
> >                      \___ unknown tracepoint

> >     Error:  File /sys/kernel/debug/tracing/events/sdt_glib/idle__add ...
> >     Hint:   SDT event has to be probed before recording it.
> 
> So what is the command line option to 'probe' an SDT event? Could you give an 
> example that would make the above command work?

I also think 'has to be probed' looks confusing, it should be, I
suggest, "put in place using 'perf probe'", what will case it to really
be _probed_ is when it is activated via a tool like 'perf record'.

So yes, I think the message _and_ the example in this commit log must
show what needs to be done, in detail, to overcome the "problem"
mentioned in the message above.

And after that its up to someone to do the logical next step: if it
needs to be put in place, well, do it, automagically.

- Arnaldo

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

* [PATCH v2] perf/sdt: Show proper hint
  2017-02-02 16:20                     ` Arnaldo Carvalho de Melo
@ 2017-02-03 10:26                       ` Ravi Bangoria
  2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
                                           ` (2 more replies)
  0 siblings, 3 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-03 10:26 UTC (permalink / raw)
  To: linux-kernel, mingo, acme
  Cc: alexis.berlemont, peterz, alexander.shishkin, mpe, naveen.n.rao,
	mhiramat, maddy, Ravi Bangoria

All events from 'perf list', except SDT events, can be directly recorded
with 'perf record'. But, the flow is little different for SDT events.
Probe point for SDT event needs to be created using 'perf probe' before
recording it using 'perf record'. Perf shows misleading hint when user
tries to record SDT event without creating a probe point. Show proper
hint there.

Before patch:
  $ perf record -a -e sdt_glib:idle__add
    event syntax error: 'sdt_glib:idle__add'
                         \___ unknown tracepoint

    Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
    Hint:  Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
    ...

After patch:
  $ perf record -a -e sdt_glib:idle__add
    event syntax error: 'sdt_glib:idle__add'
                         \___ unknown tracepoint

    Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
    Hint:  SDT event cannot be directly recorded on. Please use 'perf probe sdt_glib:idle__add' before recording it.
    ...

  $ perf probe sdt_glib:idle__add
    Added new event:
      sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)

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

        perf record -e sdt_glib:idle__add -aR sleep 1

  $ perf record -a -e sdt_glib:idle__add
    [ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.175 MB perf.data ]

Suggested-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
Changes in v2:
  - More precise hint

 tools/lib/api/fs/tracing_path.c | 31 +++++++++++++++++--------------
 1 file changed, 17 insertions(+), 14 deletions(-)

diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 251b7c3..aaafc99 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -86,9 +86,13 @@ void put_tracing_file(char *file)
 	free(file);
 }
 
-static int strerror_open(int err, char *buf, size_t size, const char *filename)
+int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
+				   const char *sys, const char *name)
 {
 	char sbuf[128];
+	char filename[PATH_MAX];
+
+	snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
 
 	switch (err) {
 	case ENOENT:
@@ -99,10 +103,18 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
 		 * - jirka
 		 */
 		if (debugfs__configured() || tracefs__configured()) {
-			snprintf(buf, size,
-				 "Error:\tFile %s/%s not found.\n"
-				 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
-				 tracing_events_path, filename);
+			/* sdt markers */
+			if (!strncmp(filename, "sdt_", 4)) {
+				snprintf(buf, size,
+					"Error:\tFile %s/%s not found.\n"
+					"Hint:\tSDT event cannot be directly recorded on. Please use 'perf probe %s:%s' before recording it.\n",
+					tracing_events_path, filename, sys, name);
+			} else {
+				snprintf(buf, size,
+					 "Error:\tFile %s/%s not found.\n"
+					 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
+					 tracing_events_path, filename);
+			}
 			break;
 		}
 		snprintf(buf, size, "%s",
@@ -125,12 +137,3 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
 
 	return 0;
 }
-
-int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
-{
-	char path[PATH_MAX];
-
-	snprintf(path, PATH_MAX, "%s/%s", sys, name ?: "*");
-
-	return strerror_open(err, buf, size, path);
-}
-- 
2.9.3

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

* Re: [PATCH v2] perf/sdt: Show proper hint
  2017-02-03 10:26                       ` [PATCH v2] " Ravi Bangoria
@ 2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
  2017-02-07  7:53                           ` Ingo Molnar
                                             ` (2 more replies)
  2017-02-07  1:13                         ` [PATCH v2] perf/sdt: Show proper hint Masami Hiramatsu
  2017-02-10  7:44                         ` [tip:perf/core] perf sdt: Show proper hint when event not yet in place via 'perf probe' tip-bot for Ravi Bangoria
  2 siblings, 3 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-02-03 15:18 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: linux-kernel, mingo, alexis.berlemont, peterz,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

Em Fri, Feb 03, 2017 at 03:56:42PM +0530, Ravi Bangoria escreveu:
> After patch:
>   $ perf record -a -e sdt_glib:idle__add
>     event syntax error: 'sdt_glib:idle__add'
>                          \___ unknown tracepoint
> 
>     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
>     Hint:  SDT event cannot be directly recorded on. Please use 'perf probe sdt_glib:idle__add' before recording it.
>     ...
> 
>   $ perf probe sdt_glib:idle__add
>     Added new event:
>       sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)
> 
>     You can now use it in all perf tools, such as:
> 
>         perf record -e sdt_glib:idle__add -aR sleep 1
> 
>   $ perf record -a -e sdt_glib:idle__add
>     [ perf record: Woken up 1 times to write data ]
>     [ perf record: Captured and wrote 0.175 MB perf.data ]

Looks much better! Thanks!

Unsure if we should state somewhere that this needs to be done only once
per boot.

Ingo, are you ok now? Ack?

- Arnaldo

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

* Re: [PATCH v2] perf/sdt: Show proper hint
  2017-02-03 10:26                       ` [PATCH v2] " Ravi Bangoria
  2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
@ 2017-02-07  1:13                         ` Masami Hiramatsu
  2017-02-10  7:44                         ` [tip:perf/core] perf sdt: Show proper hint when event not yet in place via 'perf probe' tip-bot for Ravi Bangoria
  2 siblings, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2017-02-07  1:13 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: linux-kernel, mingo, acme, alexis.berlemont, peterz,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

On Fri,  3 Feb 2017 15:56:42 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> All events from 'perf list', except SDT events, can be directly recorded
> with 'perf record'. But, the flow is little different for SDT events.
> Probe point for SDT event needs to be created using 'perf probe' before
> recording it using 'perf record'. Perf shows misleading hint when user
> tries to record SDT event without creating a probe point. Show proper
> hint there.
> 
> Before patch:
>   $ perf record -a -e sdt_glib:idle__add
>     event syntax error: 'sdt_glib:idle__add'
>                          \___ unknown tracepoint
> 
>     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
>     Hint:  Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
>     ...
> 
> After patch:
>   $ perf record -a -e sdt_glib:idle__add
>     event syntax error: 'sdt_glib:idle__add'
>                          \___ unknown tracepoint
> 
>     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
>     Hint:  SDT event cannot be directly recorded on. Please use 'perf probe sdt_glib:idle__add' before recording it.
>     ...
> 
>   $ perf probe sdt_glib:idle__add
>     Added new event:
>       sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)
> 
>     You can now use it in all perf tools, such as:
> 
>         perf record -e sdt_glib:idle__add -aR sleep 1
> 
>   $ perf record -a -e sdt_glib:idle__add
>     [ perf record: Woken up 1 times to write data ]
>     [ perf record: Captured and wrote 0.175 MB perf.data ]
> 

Looks good to me:)

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> Suggested-by: Ingo Molnar <mingo@redhat.com>
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
> Changes in v2:
>   - More precise hint
> 
>  tools/lib/api/fs/tracing_path.c | 31 +++++++++++++++++--------------
>  1 file changed, 17 insertions(+), 14 deletions(-)
> 
> diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
> index 251b7c3..aaafc99 100644
> --- a/tools/lib/api/fs/tracing_path.c
> +++ b/tools/lib/api/fs/tracing_path.c
> @@ -86,9 +86,13 @@ void put_tracing_file(char *file)
>  	free(file);
>  }
>  
> -static int strerror_open(int err, char *buf, size_t size, const char *filename)
> +int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
> +				   const char *sys, const char *name)
>  {
>  	char sbuf[128];
> +	char filename[PATH_MAX];
> +
> +	snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
>  
>  	switch (err) {
>  	case ENOENT:
> @@ -99,10 +103,18 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
>  		 * - jirka
>  		 */
>  		if (debugfs__configured() || tracefs__configured()) {
> -			snprintf(buf, size,
> -				 "Error:\tFile %s/%s not found.\n"
> -				 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
> -				 tracing_events_path, filename);
> +			/* sdt markers */
> +			if (!strncmp(filename, "sdt_", 4)) {
> +				snprintf(buf, size,
> +					"Error:\tFile %s/%s not found.\n"
> +					"Hint:\tSDT event cannot be directly recorded on. Please use 'perf probe %s:%s' before recording it.\n",
> +					tracing_events_path, filename, sys, name);
> +			} else {
> +				snprintf(buf, size,
> +					 "Error:\tFile %s/%s not found.\n"
> +					 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
> +					 tracing_events_path, filename);
> +			}
>  			break;
>  		}
>  		snprintf(buf, size, "%s",
> @@ -125,12 +137,3 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
>  
>  	return 0;
>  }
> -
> -int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
> -{
> -	char path[PATH_MAX];
> -
> -	snprintf(path, PATH_MAX, "%s/%s", sys, name ?: "*");
> -
> -	return strerror_open(err, buf, size, path);
> -}
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 5/5] perf/probe: Change MAX_CMDLEN
  2017-02-02 11:11                 ` [PATCH 5/5] perf/probe: Change MAX_CMDLEN Ravi Bangoria
@ 2017-02-07  1:40                   ` Masami Hiramatsu
  2017-02-07  5:45                     ` [PATCH v2] " Ravi Bangoria
  0 siblings, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-02-07  1:40 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

On Thu,  2 Feb 2017 16:41:43 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> There are many SDT markers in powerpc whose uprobe definition goes
> beyond current MAX_CMDLEN, especially when target filename is long
> and sdt marker has long list of arguments. For example, definition
> of sdt marker
> 
>   method__compile__end: 8@17 8@9 8@10 -4@8 8@7 -4@6 8@5 -4@4 1@37(28)
> 
> from file
> 
>   /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.91-2.b14.fc22.ppc64/jre/lib/\
>      ppc64/server/libjvm.so
> 
> is
> 
>   p:sdt_hotspot/method__compile__end /usr/lib/jvm/java-1.8.0-openjdk-\
>     1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so:0x4c4e00\
>     arg1=%gpr17:u64 arg2=%gpr9:u64 arg3=%gpr10:u64 arg4=%gpr8:s32\
>     arg5=%gpr7:u64 arg6=%gpr6:s32 arg7=%gpr5:u64 arg8=%gpr4:s32\
>     arg9=+37(%gpr28):u8
> 
> Perf probe fails with seg fault for such markers. As uprobe_events file
> accepts definition beyond 256 characters, increase value of MAX_CMDLEN
> to 512.

OK, actually in the kernel side, it accepts up to 4094 (+"\n\0")
so it is a good time to expand it to 4094.
(I found another buggy message in kernel... will be fixed soon)

Thank you,

> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
>  tools/perf/util/probe-event.c | 1 -
>  tools/perf/util/probe-file.c  | 2 +-
>  2 files changed, 1 insertion(+), 2 deletions(-)
> 
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 2c1bca2..5f3256f 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -47,7 +47,6 @@
>  #include "probe-file.h"
>  #include "session.h"
>  
> -#define MAX_CMDLEN 256
>  #define PERFPROBE_GROUP "probe"
>  
>  bool probe_event_dry_run;	/* Dry run flag */
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 38eca3c..1580e26 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -29,7 +29,7 @@
>  #include "session.h"
>  #include "perf_regs.h"
>  
> -#define MAX_CMDLEN 256
> +#define MAX_CMDLEN 512
>  
>  static void print_open_warning(int err, bool uprobe)
>  {
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 0/5] perf/sdt: Argument support for x86 and powepc
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
                                   ` (4 preceding siblings ...)
  2017-02-02 11:11                 ` [PATCH 5/5] perf/probe: Change MAX_CMDLEN Ravi Bangoria
@ 2017-02-07  2:55                 ` Masami Hiramatsu
  2017-03-06  7:53                   ` Ravi Bangoria
  5 siblings, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-02-07  2:55 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

On Thu,  2 Feb 2017 16:41:38 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> The v5 patchset for sdt marker argument support for x86 [1] has
> couple  of issues. For example, it still has x86 specific code
> in general code. It lacks support for rNN (with size postfix
> b/w/d), %rsp, %esp, %sil etc. registers and such sdt markers
> are failing at 'perf probe'. It also fails to convert arguments
> having no offset but still surrounds register with parenthesis
> for ex. 8@(%rdi) is converted to +(%di):u64 which is rejected
> by uprobe_events. It's causing failure at 'perf probe' for all
> SDT events on all archs except x86. With this patchset, I've
> solved these issues. (patch 2,3)
> 
> Also, existing perf shows misleading message when user tries to
> record sdt event without probing it. I've prepared patch for
> the same. (patch 1)
> 
> Apart from that, I've also added logic to support arguments with
> sdt marker on powerpc. (patch 4)
> 
> There are cases where uprobe definition of sdt event goes beyond
> current limit MAX_CMDLEN (256) and in such case perf fails with
> seg fault. I've solve this issue. (patch 5)
> 
> Note: This patchset is prepared on top of Alexis' v5 series.[1]
> 
> [1] http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1292251.html

Hmm, I must missed it. I'll check it...

Thanks!


> 
> Ravi Bangoria (5):
>   perf/sdt: Show proper hint
>   perf/sdt/x86: Add renaming logic for rNN and other registers
>   perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
>   perf/sdt/powerpc: Add argument support
>   perf/probe: Change MAX_CMDLEN
> 
>  tools/lib/api/fs/tracing_path.c          |  16 +++-
>  tools/perf/arch/powerpc/util/perf_regs.c | 115 ++++++++++++++++++++++++++
>  tools/perf/arch/x86/util/perf_regs.c     | 137 ++++++++++++++++++++++++++++---
>  tools/perf/util/perf_regs.c              |   9 +-
>  tools/perf/util/perf_regs.h              |   7 +-
>  tools/perf/util/probe-event.c            |   1 -
>  tools/perf/util/probe-file.c             | 129 ++++++++---------------------
>  7 files changed, 294 insertions(+), 120 deletions(-)
> 
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-02-02 11:11                 ` [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Ravi Bangoria
@ 2017-02-07  3:11                   ` Masami Hiramatsu
  2017-02-07  5:22                     ` Ravi Bangoria
  2017-03-21 14:55                   ` Masami Hiramatsu
  1 sibling, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-02-07  3:11 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

On Thu,  2 Feb 2017 16:41:41 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> SDT marker argument is in N@OP format. N is the size of argument and
> OP is the actual assembly operand. OP is arch dependent component and
> hence it's parsing logic also should be placed under tools/perf/arch/.
> 

Ok, I have one question. Is there any possibility that N is different
size of OP? e.g. 8@dil, in this case we will record whole rdi.
is that OK?

Thanks,

> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
>  tools/perf/arch/x86/util/perf_regs.c |  93 ++++++++++++++++++++++++-
>  tools/perf/util/perf_regs.c          |   9 ++-
>  tools/perf/util/perf_regs.h          |   7 +-
>  tools/perf/util/probe-file.c         | 127 +++++++++--------------------------
>  4 files changed, 134 insertions(+), 102 deletions(-)
> 
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index d8a8dcf..34fcb0d 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -3,6 +3,7 @@
>  #include "../../perf.h"
>  #include "../../util/util.h"
>  #include "../../util/perf_regs.h"
> +#include "../../util/debug.h"
>  
>  const struct sample_reg sample_reg_masks[] = {
>  	SMPL_REG(AX, PERF_REG_X86_AX),
> @@ -87,7 +88,16 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
>  	SDT_NAME_REG_END,
>  };
>  
> -int sdt_rename_register(char **pdesc, char *old_name)
> +bool arch_sdt_probe_arg_supp(void)
> +{
> +	return true;
> +}
> +
> +/*
> + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> + * registers before filling the uprobe tracer interface.
> + */
> +static int sdt_rename_register(char **pdesc, char *old_name)
>  {
>  	const struct sdt_name_reg *rnames = sdt_reg_renamings;
>  	char *new_desc, *old_desc = *pdesc;
> @@ -129,3 +139,84 @@ int sdt_rename_register(char **pdesc, char *old_name)
>  
>  	return 0;
>  }
> +
> +/*
> + * x86 specific implementation
> + * return value:
> + *	<0 : error
> + *	 0 : success
> + *	>0 : skip
> + */
> +int arch_sdt_probe_parse_op(char **desc, const char **prefix)
> +{
> +	char *tmp;
> +	int ret = 0;
> +
> +	/*
> +	 * The uprobe tracer format does not support all the addressing
> +	 * modes (notably: in x86 the scaled mode); so, we detect ','
> +	 * characters, if there is just one, there is no use converting
> +	 * the sdt arg into a uprobe one.
> +	 *
> +	 * Also it does not support constants; if we find one in the
> +	 * current argument, let's skip the argument.
> +	 */
> +	if (strchr(*desc, ',') || strchr(*desc, '$')) {
> +		pr_debug4("Skipping unsupported SDT argument; %s\n", *desc);
> +		return 1;
> +	}
> +
> +	/*
> +	 * If the argument addressing mode is indirect, we must check
> +	 * a few things...
> +	 */
> +	tmp = strchr(*desc, '(');
> +	if (tmp) {
> +		int j;
> +
> +		/*
> +		 * ...if the addressing mode is indirect with a
> +		 * positive offset (ex.: "1608(%ax)"), we need to add
> +		 * a '+' prefix so as to be compliant with uprobe
> +		 * format.
> +		 */
> +		if ((*desc)[0] != '+' && (*desc)[0] != '-')
> +			*prefix = ((*desc)[0] == '(') ? "+0" : "+";
> +
> +		/*
> +		 * ...or if the addressing mode is indirect with a symbol
> +		 * as offset, the argument will not be supported by
> +		 * the uprobe tracer format; so, let's skip this one.
> +		 */
> +		for (j = 0; j < tmp - *desc; j++) {
> +			if ((*desc)[j] != '+' && (*desc)[j] != '-' &&
> +			    !isdigit((*desc)[j])) {
> +				pr_debug4("Skipping unsupported SDT argument; "
> +					"%s\n", *desc);
> +				return 1;
> +			}
> +		}
> +	}
> +
> +	/*
> +	 * The uprobe parser does not support all gas register names;
> +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> +	 * the loop below looks for the register names (starting with
> +	 * a '%' and tries to perform the needed renamings.
> +	 */
> +	tmp = strchr(*desc, '%');
> +	while (tmp) {
> +		size_t offset = tmp - *desc;
> +
> +		ret = sdt_rename_register(desc, *desc + offset);
> +		if (ret < 0)
> +			return ret;
> +
> +		/*
> +		 * The *desc pointer might have changed; so, let's not
> +		 * try to reuse tmp for next lookup
> +		 */
> +		tmp = strchr(*desc + offset + 1, '%');
> +	}
> +	return 0;
> +}
> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index a37e593..f2b3d0d 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -6,8 +6,13 @@ const struct sample_reg __weak sample_reg_masks[] = {
>  	SMPL_REG_END
>  };
>  
> -int __weak sdt_rename_register(char **pdesc __maybe_unused,
> -			char *old_name __maybe_unused)
> +bool __weak arch_sdt_probe_arg_supp(void)
> +{
> +	return false;
> +}
> +
> +int __weak arch_sdt_probe_parse_op(char **op_ptr __maybe_unused,
> +				   const char **prefix __maybe_unused)
>  {
>  	return 0;
>  }
> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index 7544a15..86a2961 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -15,11 +15,8 @@ struct sample_reg {
>  
>  extern const struct sample_reg sample_reg_masks[];
>  
> -/*
> - * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> - * registers before filling the uprobe tracer interface.
> - */
> -int sdt_rename_register(char **pdesc, char *old_name);
> +bool arch_sdt_probe_arg_supp(void);
> +int arch_sdt_probe_parse_op(char **op_ptr, const char **prefix);
>  
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  #include <perf_regs.h>
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index d8a169e..38eca3c 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -693,6 +693,25 @@ static const char * const type_to_suffix[] = {
>  	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
>  };
>  
> +/*
> + * Isolate the string number and convert it into a decimal value;
> + * this will be an index to get suffix of the uprobe name (defining
> + * the type)
> + */
> +static int sdt_probe_parse_n(char *n_ptr, const char **suffix)
> +{
> +	long type_idx;
> +
> +	type_idx = strtol(n_ptr, NULL, 10);
> +	if (type_idx < -8 || type_idx > 8) {
> +		pr_debug4("Failed to get a valid sdt type\n");
> +		return -1;
> +	}
> +
> +	*suffix = type_to_suffix[type_idx + 8];
> +	return 0;
> +}
> +
>  static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
>  {
>  	char *tmp, *desc = strdup(arg);
> @@ -704,109 +723,29 @@ static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
>  		return ret;
>  	}
>  
> +	/*
> +	 * Argument is in N@OP format. N is size of the argument and OP is
> +	 * the actual assembly operand. N can be omitted; in that case
> +	 * argument is just OP(without @).
> +	 */
>  	tmp = strchr(desc, '@');
>  	if (tmp) {
> -		long type_idx;
> -		/*
> -		 * Isolate the string number and convert it into a
> -		 * binary value; this will be an index to get suffix
> -		 * of the uprobe name (defining the type)
> -		 */
>  		tmp[0] = '\0';
> -		type_idx = strtol(desc, NULL, 10);
> -		/* Check that the conversion went OK */
> -		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
> -			pr_debug4("Failed to parse sdt type\n");
> -			goto error;
> -		}
> -		/* Check that the converted value is OK */
> -		if (type_idx < -8 || type_idx > 8) {
> -			pr_debug4("Failed to get a valid sdt type\n");
> -			goto error;
> -		}
> -		suffix = type_to_suffix[type_idx + 8];
> -		/* Get rid of the sdt prefix which is now useless */
>  		tmp++;
> -		memmove(desc, tmp, strlen(tmp) + 1);
> -	}
>  
> -	/*
> -	 * The uprobe tracer format does not support all the
> -	 * addressing modes (notably: in x86 the scaled mode); so, we
> -	 * detect ',' characters, if there is just one, there is no
> -	 * use converting the sdt arg into a uprobe one.
> -	 */
> -	if (strchr(desc, ',')) {
> -		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> -		goto out;
> -	}
> -
> -	/*
> -	 * If the argument addressing mode is indirect, we must check
> -	 * a few things...
> -	 */
> -	tmp = strchr(desc, '(');
> -	if (tmp) {
> -		int j;
> -
> -		/*
> -		 * ...if the addressing mode is indirect with a
> -		 * positive offset (ex.: "1608(%ax)"), we need to add
> -		 * a '+' prefix so as to be compliant with uprobe
> -		 * format.
> -		 */
> -		if (desc[0] != '+' && desc[0] != '-')
> -			prefix = "+";
> -
> -		/*
> -		 * ...or if the addressing mode is indirect with a symbol
> -		 * as offset, the argument will not be supported by
> -		 * the uprobe tracer format; so, let's skip this one.
> -		 */
> -		for (j = 0; j < tmp - desc; j++) {
> -			if (desc[j] != '+' && desc[j] != '-' &&
> -				!isdigit(desc[j])) {
> -				pr_debug4("Skipping unsupported SDT argument; "
> -					"%s\n", desc);
> -				goto out;
> -			}
> -		}
> -	}
> -
> -	/*
> -	 * The uprobe tracer format does not support constants; if we
> -	 * find one in the current argument, let's skip the argument.
> -	 */
> -	if (strchr(desc, '$')) {
> -		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> -		goto out;
> -	}
> -
> -	/*
> -	 * The uprobe parser does not support all gas register names;
> -	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> -	 * the loop below looks for the register names (starting with
> -	 * a '%' and tries to perform the needed renamings.
> -	 */
> -	tmp = strchr(desc, '%');
> -	while (tmp) {
> -		size_t offset = tmp - desc;
> -
> -		ret = sdt_rename_register(&desc, desc + offset);
> -		if (ret < 0)
> +		if (sdt_probe_parse_n(desc, &suffix))
>  			goto error;
> -
> -		/*
> -		 * The desc pointer might have changed; so, let's not
> -		 * try to reuse tmp for next lookup
> -		 */
> -		tmp = strchr(desc + offset + 1, '%');
> +		memmove(desc, tmp, strlen(tmp) + 1);
>  	}
>  
> -	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
> +	ret = arch_sdt_probe_parse_op(&desc, &prefix);
> +	if (ret < 0)
> +		goto error;
> +
> +	if (ret == 0 &&
> +	    strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
>  		goto error;
>  
> -out:
>  	ret = 0;
>  error:
>  	free(desc);
> @@ -829,7 +768,7 @@ static char *synthesize_sdt_probe_command(struct sdt_note *note,
>  				sdt_note__get_addr(note)) < 0)
>  		goto error;
>  
> -	if (!note->args)
> +	if (!note->args || !arch_sdt_probe_arg_supp())
>  		goto out;
>  
>  	if (note->args) {
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers
  2017-02-02 11:11                 ` [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers Ravi Bangoria
@ 2017-02-07  3:11                   ` Masami Hiramatsu
  2017-03-21 14:08                     ` Arnaldo Carvalho de Melo
  2017-03-24 18:45                   ` [tip:perf/core] perf sdt x86: " tip-bot for Ravi Bangoria
  1 sibling, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-02-07  3:11 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

On Thu,  2 Feb 2017 16:41:40 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> 'perf probe' is failing for sdt markers whose arguments has rNN
> (with postfix b/w/d), %rsp, %esp, %sil etc. registers. Add renaming
> logic for these registers.
> 

Looks good to me.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
>  tools/perf/arch/x86/util/perf_regs.c | 44 ++++++++++++++++++++++++++----------
>  1 file changed, 32 insertions(+), 12 deletions(-)
> 
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index 09a7f55..d8a8dcf 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -48,10 +48,42 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
>  	SDT_NAME_REG(rdx, dx),
>  	SDT_NAME_REG(esi, si),
>  	SDT_NAME_REG(rsi, si),
> +	SDT_NAME_REG(sil, si),
>  	SDT_NAME_REG(edi, di),
>  	SDT_NAME_REG(rdi, di),
> +	SDT_NAME_REG(dil, di),
>  	SDT_NAME_REG(ebp, bp),
>  	SDT_NAME_REG(rbp, bp),
> +	SDT_NAME_REG(bpl, bp),
> +	SDT_NAME_REG(rsp, sp),
> +	SDT_NAME_REG(esp, sp),
> +	SDT_NAME_REG(spl, sp),
> +
> +	/* rNN registers */
> +	SDT_NAME_REG(r8b,  r8),
> +	SDT_NAME_REG(r8w,  r8),
> +	SDT_NAME_REG(r8d,  r8),
> +	SDT_NAME_REG(r9b,  r9),
> +	SDT_NAME_REG(r9w,  r9),
> +	SDT_NAME_REG(r9d,  r9),
> +	SDT_NAME_REG(r10b, r10),
> +	SDT_NAME_REG(r10w, r10),
> +	SDT_NAME_REG(r10d, r10),
> +	SDT_NAME_REG(r11b, r11),
> +	SDT_NAME_REG(r11w, r11),
> +	SDT_NAME_REG(r11d, r11),
> +	SDT_NAME_REG(r12b, r12),
> +	SDT_NAME_REG(r12w, r12),
> +	SDT_NAME_REG(r12d, r12),
> +	SDT_NAME_REG(r13b, r13),
> +	SDT_NAME_REG(r13w, r13),
> +	SDT_NAME_REG(r13d, r13),
> +	SDT_NAME_REG(r14b, r14),
> +	SDT_NAME_REG(r14w, r14),
> +	SDT_NAME_REG(r14d, r14),
> +	SDT_NAME_REG(r15b, r15),
> +	SDT_NAME_REG(r15w, r15),
> +	SDT_NAME_REG(r15d, r15),
>  	SDT_NAME_REG_END,
>  };
>  
> @@ -88,18 +120,6 @@ int sdt_rename_register(char **pdesc, char *old_name)
>  
>  	/* Copy the chars after the register name (if need be) */
>  	offset = prefix_len + sdt_len;
> -	if (offset < old_desc_len) {
> -		/*
> -		 * The orginal register name can be suffixed by 'b',
> -		 * 'w' or 'd' to indicate its size; so, we need to
> -		 * skip this char if we met one.
> -		 */
> -		char sfx = old_desc[offset];
> -
> -		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
> -			offset++;
> -	}
> -
>  	if (offset < old_desc_len)
>  		memcpy(new_desc + prefix_len + uprobe_len,
>  			old_desc + offset, old_desc_len - offset);
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-02-07  3:11                   ` Masami Hiramatsu
@ 2017-02-07  5:22                     ` Ravi Bangoria
  2017-03-21 14:10                       ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-07  5:22 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy, Ravi Bangoria

Thanks Masami for the review.

On Tuesday 07 February 2017 08:41 AM, Masami Hiramatsu wrote:
> On Thu,  2 Feb 2017 16:41:41 +0530
> Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
>
>> SDT marker argument is in N@OP format. N is the size of argument and
>> OP is the actual assembly operand. OP is arch dependent component and
>> hence it's parsing logic also should be placed under tools/perf/arch/.
>>
> Ok, I have one question. Is there any possibility that N is different
> size of OP? e.g. 8@dil, in this case we will record whole rdi.
> is that OK?

By looking at list of markers on my x86 Fedora25 box, yes, it's possible
for case when register size used in OP is more than size specified by N.
For example, -4@68(%rbx). But I don't see any argument which specifies
higher size in N compared to size of register in OP, like you mentioned
in your example.

Ravi

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

* [PATCH v2] perf/probe: Change MAX_CMDLEN
  2017-02-07  1:40                   ` Masami Hiramatsu
@ 2017-02-07  5:45                     ` Ravi Bangoria
  2017-03-21  5:19                       ` Masami Hiramatsu
  2017-03-24 18:43                       ` [tip:perf/core] perf probe: " tip-bot for Ravi Bangoria
  0 siblings, 2 replies; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-07  5:45 UTC (permalink / raw)
  To: acme, linux-kernel, mhiramat
  Cc: alexis.berlemont, peterz, mingo, alexander.shishkin, mpe,
	naveen.n.rao, maddy, Ravi Bangoria

There are many SDT markers in powerpc whose uprobe definition goes
beyond current MAX_CMDLEN, especially when target filename is long
and sdt marker has long list of arguments. For example, definition
of sdt marker

  method__compile__end: 8@17 8@9 8@10 -4@8 8@7 -4@6 8@5 -4@4 1@37(28)

from file

  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.91-2.b14.fc22.ppc64/jre/lib/\
     ppc64/server/libjvm.so

is

  p:sdt_hotspot/method__compile__end /usr/lib/jvm/java-1.8.0-openjdk-\
    1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so:0x4c4e00\
    arg1=%gpr17:u64 arg2=%gpr9:u64 arg3=%gpr10:u64 arg4=%gpr8:s32\
    arg5=%gpr7:u64 arg6=%gpr6:s32 arg7=%gpr5:u64 arg8=%gpr4:s32\
    arg9=+37(%gpr28):u8

Perf probe fails with seg fault for such markers. As uprobe_events file
accepts definition upto 4094 characters(4096 - 2 (\n\0)), increase value
of MAX_CMDLEN to 4094.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
Changes in v2:
  - Set MAX_CMDLEN to 4094 instead of 512

 tools/perf/util/probe-event.c | 1 -
 tools/perf/util/probe-file.c  | 3 ++-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6a6f44d..e6e3244 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
 #include "probe-file.h"
 #include "session.h"
 
-#define MAX_CMDLEN 256
 #define PERFPROBE_GROUP "probe"
 
 bool probe_event_dry_run;	/* Dry run flag */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 38eca3c..fdabe7e 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -29,7 +29,8 @@
 #include "session.h"
 #include "perf_regs.h"
 
-#define MAX_CMDLEN 256
+/* 4096 - 2 ('\n' + '\0') */
+#define MAX_CMDLEN 4094
 
 static void print_open_warning(int err, bool uprobe)
 {
-- 
2.9.3

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

* Re: [PATCH v2] perf/sdt: Show proper hint
  2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
@ 2017-02-07  7:53                           ` Ingo Molnar
  2017-02-07 15:50                             ` Arnaldo Carvalho de Melo
  2017-02-07  8:00                           ` Ingo Molnar
  2017-02-16 10:16                           ` [RFC] perf/sdt: Directly record SDT event with 'perf record' Ravi Bangoria
  2 siblings, 1 reply; 77+ messages in thread
From: Ingo Molnar @ 2017-02-07  7:53 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ravi Bangoria, linux-kernel, mingo, alexis.berlemont, peterz,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy


* Arnaldo Carvalho de Melo <acme@redhat.com> wrote:

> Em Fri, Feb 03, 2017 at 03:56:42PM +0530, Ravi Bangoria escreveu:
> > After patch:
> >   $ perf record -a -e sdt_glib:idle__add
> >     event syntax error: 'sdt_glib:idle__add'
> >                          \___ unknown tracepoint
> > 
> >     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
> >     Hint:  SDT event cannot be directly recorded on. Please use 'perf probe sdt_glib:idle__add' before recording it.
> >     ...
> > 
> >   $ perf probe sdt_glib:idle__add
> >     Added new event:
> >       sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)
> > 
> >     You can now use it in all perf tools, such as:
> > 
> >         perf record -e sdt_glib:idle__add -aR sleep 1
> > 
> >   $ perf record -a -e sdt_glib:idle__add
> >     [ perf record: Woken up 1 times to write data ]
> >     [ perf record: Captured and wrote 0.175 MB perf.data ]
> 
> Looks much better! Thanks!
> 
> Unsure if we should state somewhere that this needs to be done only once
> per boot.
> 
> Ingo, are you ok now? Ack?

Yeah, looks perfect to me!

Acked-by: Ingo Molnar <mingo@kernel.org>

Thanks,

	Ingo

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

* Re: [PATCH v2] perf/sdt: Show proper hint
  2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
  2017-02-07  7:53                           ` Ingo Molnar
@ 2017-02-07  8:00                           ` Ingo Molnar
  2017-02-16 10:16                           ` [RFC] perf/sdt: Directly record SDT event with 'perf record' Ravi Bangoria
  2 siblings, 0 replies; 77+ messages in thread
From: Ingo Molnar @ 2017-02-07  8:00 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ravi Bangoria, linux-kernel, mingo, alexis.berlemont, peterz,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy


* Arnaldo Carvalho de Melo <acme@redhat.com> wrote:

> Em Fri, Feb 03, 2017 at 03:56:42PM +0530, Ravi Bangoria escreveu:
> > After patch:
> >   $ perf record -a -e sdt_glib:idle__add
> >     event syntax error: 'sdt_glib:idle__add'
> >                          \___ unknown tracepoint
> > 
> >     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
> >     Hint:  SDT event cannot be directly recorded on. Please use 'perf probe sdt_glib:idle__add' before recording it.
> >     ...
> > 
> >   $ perf probe sdt_glib:idle__add
> >     Added new event:
> >       sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)
> > 
> >     You can now use it in all perf tools, such as:
> > 
> >         perf record -e sdt_glib:idle__add -aR sleep 1
> > 
> >   $ perf record -a -e sdt_glib:idle__add
> >     [ perf record: Woken up 1 times to write data ]
> >     [ perf record: Captured and wrote 0.175 MB perf.data ]
> 
> Looks much better! Thanks!
> 
> Unsure if we should state somewhere that this needs to be done only once
> per boot.

Forgot to reply to your question - indeed I agree that something like this would 
be even better:

   $ perf record -a -e sdt_glib:idle__add
     event syntax error: 'sdt_glib:idle__add'
                          \___ unknown tracepoint
 
     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
     Hint:  SDT event cannot be directly recorded on.
            Please first use 'perf probe sdt_glib:idle__add' before recording it.

BTW., and I think this is fundamental: why is this interim step forced upon the 
user - cannot we just auto-enable it if it's not enabled yet?

If for some reason it's important for the user to know that we enabled a probe we 
could print that we did so:

     Info: enabling not yet enabled 'perf probe sdt_glib:idle__add' SDT event.

... and that would be even more usable.

A tool printing out the perfect thing for the user to type in is a sign that the 
tool should have done this itself.

See for example how Git handles the bisection workflow. Technically the following 
is required to start a bisection:

  triton:~/tip> git bisect start
  triton:~/tip> git bisect bad
  triton:~/tip> 

But you can also do:

  triton:~/tip> git bisect bad
  You need to start by "git bisect start"
  Do you want me to do it for you [Y/n]? 
  triton:~/tip> 

and the user can start the bisection by hitting Enter.

No fuss, no unnecessary resistance from tooling - and the user is fully informed 
all along. Every extra tooling step forced upon users annoys them and shrinks the 
potential userbase.

Thanks,

	Ingo

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

* Re: [PATCH v2] perf/sdt: Show proper hint
  2017-02-07  7:53                           ` Ingo Molnar
@ 2017-02-07 15:50                             ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-02-07 15:50 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Ravi Bangoria, linux-kernel, mingo, alexis.berlemont, peterz,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

Em Tue, Feb 07, 2017 at 08:53:56AM +0100, Ingo Molnar escreveu:
> 
> * Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> 
> > Em Fri, Feb 03, 2017 at 03:56:42PM +0530, Ravi Bangoria escreveu:
> > > After patch:
> > >   $ perf record -a -e sdt_glib:idle__add
> > >     event syntax error: 'sdt_glib:idle__add'
> > >                          \___ unknown tracepoint
> > > 
> > >     Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
> > >     Hint:  SDT event cannot be directly recorded on. Please use 'perf probe sdt_glib:idle__add' before recording it.
> > >     ...
> > > 
> > >   $ perf probe sdt_glib:idle__add
> > >     Added new event:
> > >       sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)
> > > 
> > >     You can now use it in all perf tools, such as:
> > > 
> > >         perf record -e sdt_glib:idle__add -aR sleep 1
> > > 
> > >   $ perf record -a -e sdt_glib:idle__add
> > >     [ perf record: Woken up 1 times to write data ]
> > >     [ perf record: Captured and wrote 0.175 MB perf.data ]
> > 
> > Looks much better! Thanks!
> > 
> > Unsure if we should state somewhere that this needs to be done only once
> > per boot.
> > 
> > Ingo, are you ok now? Ack?
> 
> Yeah, looks perfect to me!
> 
> Acked-by: Ingo Molnar <mingo@kernel.org>

Thanks, added that "first" and split the Hint line in two.

Automagically setting it up, doing the perf probe and rendering the
above comment irrelevant remains as a task to be performed.

- Arnaldo

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

* [tip:perf/core] perf sdt: Show proper hint when event not yet in place via 'perf probe'
  2017-02-03 10:26                       ` [PATCH v2] " Ravi Bangoria
  2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
  2017-02-07  1:13                         ` [PATCH v2] perf/sdt: Show proper hint Masami Hiramatsu
@ 2017-02-10  7:44                         ` tip-bot for Ravi Bangoria
  2 siblings, 0 replies; 77+ messages in thread
From: tip-bot for Ravi Bangoria @ 2017-02-10  7:44 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, maddy, ravi.bangoria, mingo, tglx, mhiramat, acme,
	peterz, alexis.berlemont, mpe, alexander.shishkin, hpa,
	naveen.n.rao, mingo

Commit-ID:  27cf5706a04e53f6844c71be1cbbf1df665f5d19
Gitweb:     http://git.kernel.org/tip/27cf5706a04e53f6844c71be1cbbf1df665f5d19
Author:     Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
AuthorDate: Fri, 3 Feb 2017 15:56:42 +0530
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Wed, 8 Feb 2017 09:28:54 -0300

perf sdt: Show proper hint when event not yet in place via 'perf probe'

All events from 'perf list', except SDT events, can be directly recorded
with 'perf record'. But, the flow is little different for SDT events.

Probe points for SDT event needs to be created using 'perf probe' before
recording it using 'perf record'.

Perf shows misleading hint when a user tries to record SDT event without
first creating a probe point. Show proper hint there.

Before patch:

  $ perf record -a -e sdt_glib:idle__add
    event syntax error: 'sdt_glib:idle__add'
                         \___ unknown tracepoint

    Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
    Hint:  Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
    ...

After patch:

  $ perf record -a -e sdt_glib:idle__add
    event syntax error: 'sdt_glib:idle__add'
                         \___ unknown tracepoint

    Error: File /sys/kernel/debug/tracing/events/sdt_glib/idle__add not found.
    Hint:  SDT event cannot be directly recorded on.
           Please first use 'perf probe sdt_glib:idle__add' before recording it.
    ...

  $ perf probe sdt_glib:idle__add
    Added new event:
      sdt_glib:idle__add   (on %idle__add in /usr/lib64/libglib-2.0.so.0.5000.2)

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

        perf record -e sdt_glib:idle__add -aR sleep 1

  $ perf record -a -e sdt_glib:idle__add
    [ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.175 MB perf.data ]

Suggested-and-Acked-by: Ingo Molnar <mingo@redhat.com>
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexis Berlemont <alexis.berlemont@gmail.com>
Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170203102642.17258-1-ravi.bangoria@linux.vnet.ibm.com
[ s/Please use/Please first use/ and break the Hint line in two ]
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/api/fs/tracing_path.c | 32 ++++++++++++++++++--------------
 1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index 251b7c3..3e606b9 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -86,9 +86,13 @@ void put_tracing_file(char *file)
 	free(file);
 }
 
-static int strerror_open(int err, char *buf, size_t size, const char *filename)
+int tracing_path__strerror_open_tp(int err, char *buf, size_t size,
+				   const char *sys, const char *name)
 {
 	char sbuf[128];
+	char filename[PATH_MAX];
+
+	snprintf(filename, PATH_MAX, "%s/%s", sys, name ?: "*");
 
 	switch (err) {
 	case ENOENT:
@@ -99,10 +103,19 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
 		 * - jirka
 		 */
 		if (debugfs__configured() || tracefs__configured()) {
-			snprintf(buf, size,
-				 "Error:\tFile %s/%s not found.\n"
-				 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
-				 tracing_events_path, filename);
+			/* sdt markers */
+			if (!strncmp(filename, "sdt_", 4)) {
+				snprintf(buf, size,
+					"Error:\tFile %s/%s not found.\n"
+					"Hint:\tSDT event cannot be directly recorded on.\n"
+					"\tPlease first use 'perf probe %s:%s' before recording it.\n",
+					tracing_events_path, filename, sys, name);
+			} else {
+				snprintf(buf, size,
+					 "Error:\tFile %s/%s not found.\n"
+					 "Hint:\tPerhaps this kernel misses some CONFIG_ setting to enable this feature?.\n",
+					 tracing_events_path, filename);
+			}
 			break;
 		}
 		snprintf(buf, size, "%s",
@@ -125,12 +138,3 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
 
 	return 0;
 }
-
-int tracing_path__strerror_open_tp(int err, char *buf, size_t size, const char *sys, const char *name)
-{
-	char path[PATH_MAX];
-
-	snprintf(path, PATH_MAX, "%s/%s", sys, name ?: "*");
-
-	return strerror_open(err, buf, size, path);
-}

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

* [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
  2017-02-07  7:53                           ` Ingo Molnar
  2017-02-07  8:00                           ` Ingo Molnar
@ 2017-02-16 10:16                           ` Ravi Bangoria
  2017-02-20  7:08                             ` Ingo Molnar
  2 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-16 10:16 UTC (permalink / raw)
  To: mingo, acme, masami.hiramatsu.pt
  Cc: brendan.d.gregg, peterz, alexander.shishkin, wangnan0, jolsa, ak,
	treeze.taeung, mathieu.poirier, hekuang, sukadev, ananth,
	naveen.n.rao, colin.ing, adrian.hunter, linux-kernel, hemant,
	Ravi Bangoria

All events from 'perf list', except SDT events, can be directly recorded
with 'perf record'. But, the flow is little different for SDT events.
Probe point for SDT event needs to be created using 'perf probe' before
recording it using 'perf record'.

As suggested by Ingo[1], it's better to make this process simple by
creating probe points automatically with 'perf record' for SDT events.

This patch disables 'perf probe' on SDT events to simplify usage. It
enables recording SDT event only with 'perf record'.

This removes all those 'multiple events with same name' issues by not
allowing manual probe creation to user. When there are multiple events
with same name, 'perf record' will record all of them (in line with
other tools supporting SDT (systemtap)).

I know 'perf probe' for SDT events has already became interface and
people are using it. But, doing this change will make user interface very
easy and also it will make tool behaviour consistent. Also, it won't
require any changes in uprobe_events structure (suggested by Masami[2]).

After patch:

  $ perf list
      ...
      sdt_libpthread:mutex_entry                         [SDT event]
      ...

  $ perf probe -x /usr/lib64/libpthread-2.24.so %sdt_libpthread:mutex_entry
    SDT events don't need to be put in place using 'perf probe' anymore.
    You can directly record on SDT events using 'perf record'
      Error: Command Parse Error.

  $ perf record -a -e %sdt_libpthread:mutex_entry
    Warning : Recording on 2 occurences of sdt_libpthread:mutex_entry
    ^C[ perf record: Woken up 1 times to write data ]
    [ perf record: Captured and wrote 0.190 MB perf.data (33 samples) ]

  $ perf evlist
    sdt_libpthread:mutex_entry
    sdt_libpthread:mutex_entry_1


Note:
  - This is no way a proper patch. Sending this RFC to get thoughts on the
    idea.
  - This is Hemant's patch[3] rebased to acme/perf/core, with few changes
    to disable 'perf probe' on SDT event.


[1] https://lkml.org/lkml/2017/2/7/59
[2] https://lkml.org/lkml/2016/4/30/50
[3] https://lkml.org/lkml/2016/5/3/810




Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
---
 tools/perf/builtin-record.c    | 21 +++++++++
 tools/perf/perf.h              |  1 +
 tools/perf/util/parse-events.c | 53 ++++++++++++++++++++++-
 tools/perf/util/parse-events.h |  1 +
 tools/perf/util/probe-event.c  | 43 ++++++++++++++++++-
 tools/perf/util/probe-event.h  |  4 ++
 tools/perf/util/probe-file.c   | 97 ++++++++++++++++++++++++++++++++++++++++++
 tools/perf/util/probe-file.h   |  8 ++++
 8 files changed, 225 insertions(+), 3 deletions(-)

diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 2ddf189..37722f0 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -39,6 +39,7 @@
 #include "util/trigger.h"
 #include "util/perf-hooks.h"
 #include "asm/bug.h"
+#include "util/probe-file.h"
 
 #include <unistd.h>
 #include <sched.h>
@@ -73,6 +74,7 @@ struct record {
 	bool			timestamp_filename;
 	struct switch_output	switch_output;
 	unsigned long long	samples;
+	struct list_head	sdt_event_list;
 };
 
 static volatile int auxtrace_record__snapshot_started;
@@ -1502,6 +1504,23 @@ static struct record record = {
 	},
 };
 
+void sdt_event_list__add(struct list_head *sdt_event_list)
+{
+	if (list_empty(sdt_event_list))
+		return;
+	list_splice(sdt_event_list, &record.sdt_event_list);
+}
+
+bool is_cmd_record(void)
+{
+	return (record.evlist != NULL);
+}
+
+static void sdt_event_list__remove(struct list_head *sdt_event_list)
+{
+	return remove_sdt_event_list(sdt_event_list);
+}
+
 const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
 	"\n\t\t\t\tDefault: fp";
 
@@ -1670,6 +1689,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	if (rec->evlist == NULL)
 		return -ENOMEM;
 
+	INIT_LIST_HEAD(&rec->sdt_event_list);
 	err = perf_config(perf_record_config, rec);
 	if (err)
 		return err;
@@ -1836,6 +1856,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
 	perf_evlist__delete(rec->evlist);
 	symbol__exit();
 	auxtrace_record__free(rec->itr);
+	sdt_event_list__remove(&rec->sdt_event_list);
 	return err;
 }
 
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 1c27d94..9d8e5fe 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -76,4 +76,5 @@ struct record_opts {
 struct option;
 extern const char * const *record_usage;
 extern struct option *record_options;
+bool is_cmd_record(void);
 #endif
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 07be076..3400a5a 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1726,13 +1726,64 @@ static void parse_events_print_error(struct parse_events_error *err,
 
 #undef MAX_WIDTH
 
+static int parse_sdt_event(const char *str, struct list_head **sdt_list)
+{
+	char *ptr = NULL;
+	int ret;
+	struct list_head *sdt_evlist;
+
+	ptr = strdup(str);
+	if (ptr == NULL)
+		return -ENOMEM;
+
+	sdt_evlist = zalloc(sizeof(*sdt_evlist));
+	if (!sdt_evlist) {
+		free(ptr);
+		pr_err("Error in sdt_evlist memory allocation\n");
+		return -ENOMEM;
+	}
+	INIT_LIST_HEAD(sdt_evlist);
+
+	/*
+	 * If there is an error in this call, no need to free
+	 * up sdt_evlist, its already free'ed up in the previous
+	 * call. Free up 'ptr' though.
+	 */
+	ret = add_sdt_event(ptr, sdt_evlist);
+
+	free(ptr);
+	if (!ret)
+		*sdt_list = sdt_evlist;
+
+	return ret;
+}
+
 int parse_events_option(const struct option *opt, const char *str,
 			int unset __maybe_unused)
 {
 	struct perf_evlist *evlist = *(struct perf_evlist **)opt->value;
 	struct parse_events_error err = { .idx = 0, };
-	int ret = parse_events(evlist, str, &err);
+	int ret = 0;
+	struct list_head *sdt_list = NULL;
+	struct sdt_event_list *event;
+
+	if (*str == '%' && is_cmd_record()) {
+		ret = parse_sdt_event(str, &sdt_list);
+		if (!ret) {
+			list_for_each_entry(event, sdt_list, list) {
+				ret = parse_events(evlist, event->event_info,
+						   &err);
+				if (ret < 0)
+					goto error;
+			}
+			/* Add it to the record struct */
+			sdt_event_list__add(sdt_list);
+		}
+	} else {
+		ret = parse_events(evlist, str, &err);
+	}
 
+error:
 	if (ret)
 		parse_events_print_error(&err, str);
 
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index da246a3..7dbeb7a 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -194,4 +194,5 @@ int is_valid_tracepoint(const char *event_string);
 int valid_event_mount(const char *eventfs);
 char *parse_events_formats_error_string(char *additional_terms);
 
+void sdt_event_list__add(struct list_head *sdt_event_list);
 #endif /* __PERF_PARSE_EVENTS_H */
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 2c1bca2..5bd5568 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1293,7 +1293,7 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
 	return err;
 }
 
-static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
+int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
 {
 	char *ptr;
 
@@ -1347,7 +1347,8 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
 	if (arg[0] == '%' ||
 	    (!strncmp(arg, "sdt_", 4) &&
 	     !!strchr(arg, ':') && !strchr(arg, '='))) {
-		pev->sdt = true;
+		pr_err("SDT events don't need to be put in place using 'perf probe' anymore.\nYou can directly record on SDT events using 'perf record'\n");
+		return -EINVAL;
 		if (arg[0] == '%')
 			arg++;
 	}
@@ -3173,6 +3174,12 @@ static int find_cached_events_all(struct perf_probe_event *pev,
 	return ret;
 }
 
+int find_sdt_events_from_cache(struct perf_probe_event *pev,
+			       struct probe_trace_event **tevs)
+{
+	return find_cached_events_all(pev, tevs);
+}
+
 static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
 					      struct probe_trace_event **tevs)
 {
@@ -3483,3 +3490,35 @@ int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
 		tvar->name = NULL;
 	return 0;
 }
+
+/*
+ * Record session for SDT events has ended. Delete the SDT events
+ * from uprobe_events file that were created initially.
+ */
+void remove_sdt_event_list(struct list_head *sdt_events)
+{
+	struct sdt_event_list *event;
+	struct strfilter *filter = NULL;
+	const char *err = NULL;
+	int ret = 0;
+
+	if (list_empty(sdt_events))
+		return;
+
+	list_for_each_entry(event, sdt_events, list) {
+		if (!filter) {
+			filter = strfilter__new(event->event_info, &err);
+			if (!filter)
+				goto free_list;
+		} else {
+			ret = strfilter__or(filter, event->event_info, &err);
+		}
+	}
+
+	ret = del_perf_probe_events(filter);
+	if (ret)
+		pr_err("Error in deleting the SDT list\n");
+
+free_list:
+	free_sdt_list(sdt_events);
+}
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5d4e940..5ec648e 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -182,4 +182,8 @@ struct map *get_target_map(const char *target, bool user);
 void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
 					   int ntevs);
 
+int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev);
+
+int find_sdt_events_from_cache(struct perf_probe_event *pev,
+			       struct probe_trace_event **tevs);
 #endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 436b647..2a6ad02 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,8 +27,10 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "probe-finder.h"
 
 #define MAX_CMDLEN 256
+#define MAX_EVENT_LENGTH 512
 
 static void print_open_warning(int err, bool uprobe)
 {
@@ -933,3 +935,98 @@ bool probe_type_is_available(enum probe_type type)
 
 	return ret;
 }
+
+void free_sdt_list(struct list_head *sdt_events)
+{
+	struct sdt_event_list *tmp, *ptr;
+
+	if (list_empty(sdt_events))
+		return;
+	list_for_each_entry_safe(tmp, ptr, sdt_events, list) {
+		list_del(&tmp->list);
+		free(tmp->event_info);
+		free(tmp);
+	}
+}
+
+/*
+ * Find the SDT event from the cache and if found add it/them
+ * to the uprobe_events file
+ */
+int add_sdt_event(char *event, struct list_head *sdt_events)
+{
+	struct perf_probe_event *pev;
+	int ret, i;
+	char *str = event + 1;
+	struct sdt_event_list *tmp;
+
+	pev = zalloc(sizeof(*pev));
+	if (!pev)
+		return -ENOMEM;
+
+	pev->sdt = true;
+	pev->uprobes = true;
+
+	/*
+	 * Parse str to find the group name and event name of
+	 * the sdt event.
+	 */
+	ret = parse_perf_probe_event_name(&str, pev);
+	if (ret) {
+		pr_err("Error in parsing sdt event %s\n", str);
+		free(pev);
+		return ret;
+	}
+
+	probe_conf.max_probes = MAX_PROBES;
+	probe_conf.force_add = 1;
+
+	/*
+	 * Find the sdt event from the cache, only cached SDT
+	 * events can be directly recorded.
+	 */
+	pev->ntevs = find_sdt_events_from_cache(pev, &pev->tevs);
+	if (pev->ntevs) {
+		if (pev->ntevs > 1) {
+			pr_warning("Warning : Recording on %d occurences of %s:%s\n",
+				   pev->ntevs, pev->group, pev->event);
+		}
+		ret = apply_perf_probe_events(pev, 1);
+		if (ret) {
+			pr_err("Error in adding SDT event : %s\n", event);
+			goto free_pev;
+		}
+	} else {
+		pr_err(" %s:%s not found in the cache\n", pev->group,
+			pev->event);
+		ret = -EINVAL;
+		goto free_pev;
+	}
+
+	/* Add the event name to "sdt_events" list */
+	for (i = 0; i < pev->ntevs; i++) {
+		tmp = zalloc(sizeof(*tmp));
+		if (!tmp) {
+			ret = -ENOMEM;
+			goto free_pev;
+		}
+
+		INIT_LIST_HEAD(&tmp->list);
+		tmp->event_info = zalloc(MAX_EVENT_LENGTH * sizeof(char));
+		if (!tmp->event_info) {
+			free_sdt_list(sdt_events);
+			ret = -ENOMEM;
+			goto free_pev;
+		}
+		snprintf(tmp->event_info, strlen(pev->tevs[i].group) +
+			 strlen(pev->tevs[i].event) + 2, "%s:%s",
+			 pev->tevs[i].group, pev->tevs[i].event);
+		list_add(&tmp->list, sdt_events);
+	}
+
+	ret = 0;
+
+free_pev:
+	cleanup_perf_probe_events(pev, 1);
+	return ret;
+}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index eba44c3..3b39681 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -19,6 +19,11 @@ struct probe_cache {
 	struct list_head entries;
 };
 
+struct sdt_event_list {
+	char *event_info;
+	struct list_head list;
+};
+
 enum probe_type {
 	PROBE_TYPE_U = 0,
 	PROBE_TYPE_S,
@@ -64,6 +69,9 @@ struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
 					const char *group, const char *event);
 int probe_cache__show_all_caches(struct strfilter *filter);
 bool probe_type_is_available(enum probe_type type);
+int add_sdt_event(char *event, struct list_head *sdt_event_list);
+void remove_sdt_event_list(struct list_head *sdt_event_list);
+void free_sdt_list(struct list_head *sdt_events);
 #else	/* ! HAVE_LIBELF_SUPPORT */
 static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
 {
-- 
2.9.3

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-16 10:16                           ` [RFC] perf/sdt: Directly record SDT event with 'perf record' Ravi Bangoria
@ 2017-02-20  7:08                             ` Ingo Molnar
  2017-02-20  8:21                               ` Ravi Bangoria
  0 siblings, 1 reply; 77+ messages in thread
From: Ingo Molnar @ 2017-02-20  7:08 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: mingo, acme, masami.hiramatsu.pt, brendan.d.gregg, peterz,
	alexander.shishkin, wangnan0, jolsa, ak, treeze.taeung,
	mathieu.poirier, hekuang, sukadev, ananth, naveen.n.rao,
	colin.ing, adrian.hunter, linux-kernel, hemant


* Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> All events from 'perf list', except SDT events, can be directly recorded
> with 'perf record'. But, the flow is little different for SDT events.
> Probe point for SDT event needs to be created using 'perf probe' before
> recording it using 'perf record'.
> 
> As suggested by Ingo[1], it's better to make this process simple by
> creating probe points automatically with 'perf record' for SDT events.
> 
> This patch disables 'perf probe' on SDT events to simplify usage. It
> enables recording SDT event only with 'perf record'.
> 
> This removes all those 'multiple events with same name' issues by not
> allowing manual probe creation to user. When there are multiple events
> with same name, 'perf record' will record all of them (in line with
> other tools supporting SDT (systemtap)).
> 
> I know 'perf probe' for SDT events has already became interface and
> people are using it. But, doing this change will make user interface very
> easy and also it will make tool behaviour consistent. Also, it won't
> require any changes in uprobe_events structure (suggested by Masami[2]).

So I like the automatism you implemented for 'perf record', but why not keep the 
'perf probe' flow as well, if people got used to it?

It's not like computer software is bad at sorting apart and handling the two cases 
properly, right?

Thanks,

	Ingo

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-20  7:08                             ` Ingo Molnar
@ 2017-02-20  8:21                               ` Ravi Bangoria
  2017-02-20  8:42                                 ` Ingo Molnar
  0 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-20  8:21 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: mingo, acme, masami.hiramatsu.pt, brendan.d.gregg, peterz,
	alexander.shishkin, wangnan0, jolsa, ak, treeze.taeung,
	mathieu.poirier, hekuang, sukadev, ananth, naveen.n.rao,
	colin.ing, adrian.hunter, linux-kernel, hemant, Ravi Bangoria



On Monday 20 February 2017 12:38 PM, Ingo Molnar wrote:
> * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
>
>> All events from 'perf list', except SDT events, can be directly recorded
>> with 'perf record'. But, the flow is little different for SDT events.
>> Probe point for SDT event needs to be created using 'perf probe' before
>> recording it using 'perf record'.
>>
>> As suggested by Ingo[1], it's better to make this process simple by
>> creating probe points automatically with 'perf record' for SDT events.
>>
>> This patch disables 'perf probe' on SDT events to simplify usage. It
>> enables recording SDT event only with 'perf record'.
>>
>> This removes all those 'multiple events with same name' issues by not
>> allowing manual probe creation to user. When there are multiple events
>> with same name, 'perf record' will record all of them (in line with
>> other tools supporting SDT (systemtap)).
>>
>> I know 'perf probe' for SDT events has already became interface and
>> people are using it. But, doing this change will make user interface very
>> easy and also it will make tool behaviour consistent. Also, it won't
>> require any changes in uprobe_events structure (suggested by Masami[2]).
> So I like the automatism you implemented for 'perf record', but why not keep the 
> 'perf probe' flow as well, if people got used to it?
>
> It's not like computer software is bad at sorting apart and handling the two cases 
> properly, right?

Thanks Ingo for the reply,

Yes, initially I thought about allowing both, 'perf probe' and
'perf record' for SDT event. But there are few complications with
it, esp. when multiple SDT events with same name exists. For ex,

  $ readelf -n /usr/lib64/libpthread-2.24.so | grep -A2 Provider
      Provider: libpthread
      Name: mutex_entry
      Location: 0x0000000000009ddb, ...
    --
      Provider: libpthread
      Name: mutex_entry
      Location: 0x000000000000bcbb, ...

At the time of record, perf has to check first if there is any
matching entry exists in uprobe_events with that name. If found,
record it, if not, go look into probe cache. If events exists with
same name in probe cache, record all of them. Like,

If probe point _is not_ created,
  $ perf record -a -e sdt_libpthread:mutex_entry
    /** Record both sdt_libpthread:mutex_entry **/

If probe point _is_ created manually, record that particular event,
  $ perf probe -x /usr/lib64/libpthread-2.24.so sdt_libpthread:mutex_entry
    Added new events:
      sdt_libpthread:mutex_entry   (on %mutex_entry in /usr/lib64/libpthread-2.24.so)
      sdt_libpthread:mutex_entry_1 (on %mutex_entry in /usr/lib64/libpthread-2.24.so)

  $ perf record -a -e sdt_libpthread:mutex_entry
    /** Record only first sdt_libpthread:mutex_entry **/

Here, same command gives different behaviour for different scenarios.

Now consider a scenario when probe point exists for any one event:

  $ perf probe -d sdt_libpthread:mutex_entry_1
  $ perf probe --list
    sdt_libpthread:mutex_entry (on pthread_mutex_lock+11 in /usr/lib64/libpthread-2.24.so)

And user tries to record it by,
  $ perf record -a -e sdt_libpthread:*

What should be the behavior of the tool? Should it record only one
'sdt_libpthread:mutex_entry' which exists in uprobe_events? Or it
should record all the SDT events from libpthread? We can choose either
of two but both the cases are ambiguous.

Not allowing 'perf probe' for SDT event will solve all such issues.
Also it will make user interface simple and consistent. Other current
tooling (systemtap, for instance) also do not allow probing individual
markers when there are multiple markers with the same name.

-Ravi

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-20  8:21                               ` Ravi Bangoria
@ 2017-02-20  8:42                                 ` Ingo Molnar
  2017-02-20 11:01                                   ` Ravi Bangoria
  0 siblings, 1 reply; 77+ messages in thread
From: Ingo Molnar @ 2017-02-20  8:42 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: mingo, acme, masami.hiramatsu.pt, brendan.d.gregg, peterz,
	alexander.shishkin, wangnan0, jolsa, ak, treeze.taeung,
	mathieu.poirier, hekuang, sukadev, ananth, naveen.n.rao,
	colin.ing, adrian.hunter, linux-kernel, hemant


* Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> Yes, initially I thought about allowing both, 'perf probe' and
> 'perf record' for SDT event. But there are few complications with
> it, esp. when multiple SDT events with same name exists. For ex,
> 
>   $ readelf -n /usr/lib64/libpthread-2.24.so | grep -A2 Provider
>       Provider: libpthread
>       Name: mutex_entry
>       Location: 0x0000000000009ddb, ...
>     --
>       Provider: libpthread
>       Name: mutex_entry
>       Location: 0x000000000000bcbb, ...
> 
> At the time of record, perf has to check first if there is any
> matching entry exists in uprobe_events with that name. If found,
> record it, if not, go look into probe cache. If events exists with
> same name in probe cache, record all of them. Like,
> 
> If probe point _is not_ created,
>   $ perf record -a -e sdt_libpthread:mutex_entry
>     /** Record both sdt_libpthread:mutex_entry **/
> 
> If probe point _is_ created manually, record that particular event,
>   $ perf probe -x /usr/lib64/libpthread-2.24.so sdt_libpthread:mutex_entry
>     Added new events:
>       sdt_libpthread:mutex_entry   (on %mutex_entry in /usr/lib64/libpthread-2.24.so)
>       sdt_libpthread:mutex_entry_1 (on %mutex_entry in /usr/lib64/libpthread-2.24.so)
> 
>   $ perf record -a -e sdt_libpthread:mutex_entry
>     /** Record only first sdt_libpthread:mutex_entry **/
> 
> Here, same command gives different behaviour for different scenarios.
> 
> Now consider a scenario when probe point exists for any one event:
> 
>   $ perf probe -d sdt_libpthread:mutex_entry_1
>   $ perf probe --list
>     sdt_libpthread:mutex_entry (on pthread_mutex_lock+11 in /usr/lib64/libpthread-2.24.so)
> 
> And user tries to record it by,
>   $ perf record -a -e sdt_libpthread:*
> 
> What should be the behavior of the tool? Should it record only one
> 'sdt_libpthread:mutex_entry' which exists in uprobe_events? Or it
> should record all the SDT events from libpthread? We can choose either
> of two but both the cases are ambiguous.

They are not ambiguous really if coded right: just pick one of the outcomes and 
maybe print a warning to inform the user that something weird is going on because 
not all markers are enabled?

As a user I'd expect 'perf record' to enable all markers and print a warning that 
the markers were in a partial state. This would result in consistent behaviour.

Does it make sense to only enable some of the markers that alias on the same name? 
If not then maybe disallow that in perf probe - or change perf probe to do the 
same thing as perf record.

I.e. this is IMHO an artificial problem that users should not be exposed to and 
which can be solved by tooling.

In particular if it's possible to enable only a part of the markers then perf 
record not continuing would be a failure mode: if for example a previous perf 
record session segfaulted (or ran out of RAM or was killed in the wrong moment or 
whatever) then it would not be possible to (easily) clean up the mess.

> Not allowing 'perf probe' for SDT event will solve all such issues.
> Also it will make user interface simple and consistent. Other current
> tooling (systemtap, for instance) also do not allow probing individual
> markers when there are multiple markers with the same name.

In any case if others agree with your change in UI flow too then it's fine by me, 
but please make it robust, i.e. if perf record sees partially enabled probes it 
should still continue.

Thanks,

	Ingo

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-20  8:42                                 ` Ingo Molnar
@ 2017-02-20 11:01                                   ` Ravi Bangoria
  2017-02-20 14:11                                     ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-20 11:01 UTC (permalink / raw)
  To: Ingo Molnar, masami.hiramatsu.pt
  Cc: mingo, acme, brendan.d.gregg, peterz, alexander.shishkin,
	wangnan0, jolsa, ak, treeze.taeung, mathieu.poirier, hekuang,
	sukadev, ananth, naveen.n.rao, colin.ing, adrian.hunter,
	linux-kernel, hemant, Ravi Bangoria

Thanks Ingo,

On Monday 20 February 2017 02:12 PM, Ingo Molnar wrote:
> * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
>
>> What should be the behavior of the tool? Should it record only one
>> 'sdt_libpthread:mutex_entry' which exists in uprobe_events? Or it
>> should record all the SDT events from libpthread? We can choose either
>> of two but both the cases are ambiguous.
> They are not ambiguous really if coded right: just pick one of the outcomes and 
> maybe print a warning to inform the user that something weird is going on because 
> not all markers are enabled?
>
> As a user I'd expect 'perf record' to enable all markers and print a warning that 
> the markers were in a partial state. This would result in consistent behaviour.

Yes, makes sense.

> Does it make sense to only enable some of the markers that alias on the same name? 
> If not then maybe disallow that in perf probe - or change perf probe to do the 
> same thing as perf record.

'perf probe' is doing that correctly. It fetches all events with given name from
probe-cache and creates entries for them in uprobe_events.

The problem is the 2-step process of adding probes and then recording,
allowing users to select individual markers to record on.

>
> I.e. this is IMHO an artificial problem that users should not be exposed to and 
> which can be solved by tooling.
>
> In particular if it's possible to enable only a part of the markers then perf 
> record not continuing would be a failure mode: if for example a previous perf 
> record session segfaulted (or ran out of RAM or was killed in the wrong moment or 
> whatever) then it would not be possible to (easily) clean up the mess.

Agreed. We need to make this more robust.

>
>> Not allowing 'perf probe' for SDT event will solve all such issues.
>> Also it will make user interface simple and consistent. Other current
>> tooling (systemtap, for instance) also do not allow probing individual
>> markers when there are multiple markers with the same name.
> In any case if others agree with your change in UI flow too then it's fine by me, 
> but please make it robust, i.e. if perf record sees partially enabled probes it 
> should still continue.

@Masami, can you please provide your thoughts as well.

Thanks,
Ravi

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-20 11:01                                   ` Ravi Bangoria
@ 2017-02-20 14:11                                     ` Arnaldo Carvalho de Melo
  2017-02-23  8:13                                       ` Ravi Bangoria
  0 siblings, 1 reply; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-02-20 14:11 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: Ingo Molnar, masami.hiramatsu.pt, mingo, brendan.d.gregg, peterz,
	alexander.shishkin, wangnan0, jolsa, ak, treeze.taeung,
	mathieu.poirier, hekuang, sukadev, ananth, naveen.n.rao,
	colin.ing, adrian.hunter, linux-kernel, hemant

Em Mon, Feb 20, 2017 at 04:31:50PM +0530, Ravi Bangoria escreveu:
> Thanks Ingo,
> 
> On Monday 20 February 2017 02:12 PM, Ingo Molnar wrote:
> > * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> >
> >> What should be the behavior of the tool? Should it record only one
> >> 'sdt_libpthread:mutex_entry' which exists in uprobe_events? Or it
> >> should record all the SDT events from libpthread? We can choose either
> >> of two but both the cases are ambiguous.
> > They are not ambiguous really if coded right: just pick one of the outcomes and 
> > maybe print a warning to inform the user that something weird is going on because 
> > not all markers are enabled?
> >
> > As a user I'd expect 'perf record' to enable all markers and print a warning that 
> > the markers were in a partial state. This would result in consistent behaviour.
> 
> Yes, makes sense.
> 
> > Does it make sense to only enable some of the markers that alias on the same name? 
> > If not then maybe disallow that in perf probe - or change perf probe to do the 
> > same thing as perf record.
> 
> 'perf probe' is doing that correctly. It fetches all events with given name from
> probe-cache and creates entries for them in uprobe_events.
> 
> The problem is the 2-step process of adding probes and then recording,
> allowing users to select individual markers to record on.

So, the more streamlined one works for most people, i.e. just use perf
record, no need to perf probe anything. But, for people who "know what
they are doing", perf probe can be used first to control exactly which
SDT probes one wants in place, and then those will be used.

We need to make sure that when processing the file there is information
that says which probes were in place and enabled in the record session,
tho. Is that possible?
 
> > I.e. this is IMHO an artificial problem that users should not be exposed to and 
> > which can be solved by tooling.
> >
> > In particular if it's possible to enable only a part of the markers then perf 
> > record not continuing would be a failure mode: if for example a previous perf 
> > record session segfaulted (or ran out of RAM or was killed in the wrong moment or 
> > whatever) then it would not be possible to (easily) clean up the mess.
 
> Agreed. We need to make this more robust.

Right, disambiguating a 'probes left by a session that did auto-probing'
from a 'hey, those probes are there intentionally, just use those' is
important.
 
> >> Not allowing 'perf probe' for SDT event will solve all such issues.
> >> Also it will make user interface simple and consistent. Other current
> >> tooling (systemtap, for instance) also do not allow probing individual
> >> markers when there are multiple markers with the same name.

> > In any case if others agree with your change in UI flow too then it's fine by me, 
> > but please make it robust, i.e. if perf record sees partially enabled probes it 
> > should still continue.
 
> @Masami, can you please provide your thoughts as well.
 
Yeah, if technically possible to allow both variants, we should leave
it up to users to decide what is best?

I.e. most people will do auto-probing, not using 'perf probe' at all,
documentation should state the pitfalls in doing so.

So, after writing the above, perhaps we should warn the user that
pre-existing probes are being used, as this will be the odd case?

The normal flow will be just using perf record with SDT probes, that
will auto-probe them and remove on exit, or better drop a reference to
them, as simultaneous use also needs to be covered?

- Arnaldo

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2017-01-23 11:23                 ` Ravi Bangoria
@ 2017-02-22 22:41                   ` Alexis Berlemont
  0 siblings, 0 replies; 77+ messages in thread
From: Alexis Berlemont @ 2017-02-22 22:41 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: Ingo Molnar, linux-kernel, peterz, mingo, acme,
	alexander.shishkin, Jiri Olsa

Ravi Bangoria wrote:
> 
> 
> On Wednesday 14 December 2016 01:06 PM, Ingo Molnar wrote:
> > * Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
> >
> >> Hi Masami,
> >>
> >> Many thanks for your mail.
> >>
> >> Here is another patch set which tries to fix the points you mentioned:
> >>
> >> * Skip the arguments containing a constant ($123); 
> >> * Review the code in charge of the register renaming (search for '%'
> >>   and parse it);
> >> * Minor changes (print the argument in case of error, skipping, check
> >>   the sdt arg type index);
> >>
> >> Many thanks,
> >>
> >> Alexis.
> >>
> >> Alexis Berlemont (2):
> >>   perf sdt: add scanning of sdt probles arguments
> >>   perf probe: add sdt probes arguments into the uprobe cmd string
> > I'd like to hijack this thread to report an SDT oddity - one of my boxen reports 
> > lots of SDT tracepoints in 'perf list':
> >
> >   mem:<addr>[/len][:access]                          [Hardware breakpoint]
> >
> >   sdt_libc:lll_lock_wait_private                     [SDT event]
> >   sdt_libc:longjmp                                   [SDT event]
> >   sdt_libc:longjmp_target                            [SDT event]
> >   sdt_libc:memory_arena_new                          [SDT event]
> >   sdt_libc:memory_arena_retry                        [SDT event]
> >   sdt_libc:memory_arena_reuse                        [SDT event]
> >   sdt_libc:memory_arena_reuse_free_list              [SDT event]
> >   sdt_libc:memory_arena_reuse_wait                   [SDT event]
> >   sdt_libc:memory_calloc_retry                       [SDT event]
> >   sdt_libc:memory_heap_free                          [SDT event]
> >   ...
> >
> > But none of them work:
> >
> >   Error:  No permissions to read /sys/kernel/debug/tracing/events/sdt_libc/longjmp
> >   Hint:   Try 'sudo mount -o remount,mode=755 /sys/kernel/debug/tracing'
> >
> >   ...
> >
> >   Error:  File /sys/kernel/debug/tracing/events/sdt_libc/longjmp not found.
> >   Hint:   Perhaps this kernel misses some CONFIG_ setting to enable this feature?.
> >
> > What kind of patches are required for SDT probes to work?
> 
> Hi Ingo,
> 
> Works for me on my x86 Fedora 25 box. May be some permission issue?
> 
> @Alexis, Planning to progress on it :) ? I would like to prepare patch for
> powerpc.

Hi,

Just a quick mail to apologize. After a few weeks without answer, I
forgot to regularly poll this thread during my free time.

I've just noticed the patches you sent meanwhile...

Once more sorry,

Alexis.

> 
> Thanks,
> Ravi
> 
> > Thanks,
> >
> > 	Ingo
> >
> 

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-20 14:11                                     ` Arnaldo Carvalho de Melo
@ 2017-02-23  8:13                                       ` Ravi Bangoria
  2017-02-23 12:48                                         ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-02-23  8:13 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ingo Molnar, masami.hiramatsu.pt, mingo, brendan.d.gregg, peterz,
	alexander.shishkin, wangnan0, jolsa, ak, treeze.taeung,
	mathieu.poirier, hekuang, sukadev, ananth, naveen.n.rao,
	colin.ing, adrian.hunter, linux-kernel, hemant, Ravi Bangoria

Thanks Arnaldo,

I'm working on this but it's taking bit longer time. Will post out a patch within
few days.

Ravi

On Monday 20 February 2017 07:41 PM, Arnaldo Carvalho de Melo wrote:
> Em Mon, Feb 20, 2017 at 04:31:50PM +0530, Ravi Bangoria escreveu:
>> Thanks Ingo,
>>
>> On Monday 20 February 2017 02:12 PM, Ingo Molnar wrote:
>>> * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
>>>
>>>> What should be the behavior of the tool? Should it record only one
>>>> 'sdt_libpthread:mutex_entry' which exists in uprobe_events? Or it
>>>> should record all the SDT events from libpthread? We can choose either
>>>> of two but both the cases are ambiguous.
>>> They are not ambiguous really if coded right: just pick one of the outcomes and 
>>> maybe print a warning to inform the user that something weird is going on because 
>>> not all markers are enabled?
>>>
>>> As a user I'd expect 'perf record' to enable all markers and print a warning that 
>>> the markers were in a partial state. This would result in consistent behaviour.
>> Yes, makes sense.
>>
>>> Does it make sense to only enable some of the markers that alias on the same name? 
>>> If not then maybe disallow that in perf probe - or change perf probe to do the 
>>> same thing as perf record.
>> 'perf probe' is doing that correctly. It fetches all events with given name from
>> probe-cache and creates entries for them in uprobe_events.
>>
>> The problem is the 2-step process of adding probes and then recording,
>> allowing users to select individual markers to record on.
> So, the more streamlined one works for most people, i.e. just use perf
> record, no need to perf probe anything. But, for people who "know what
> they are doing", perf probe can be used first to control exactly which
> SDT probes one wants in place, and then those will be used.
>
> We need to make sure that when processing the file there is information
> that says which probes were in place and enabled in the record session,
> tho. Is that possible?
>
>>> I.e. this is IMHO an artificial problem that users should not be exposed to and 
>>> which can be solved by tooling.
>>>
>>> In particular if it's possible to enable only a part of the markers then perf 
>>> record not continuing would be a failure mode: if for example a previous perf 
>>> record session segfaulted (or ran out of RAM or was killed in the wrong moment or 
>>> whatever) then it would not be possible to (easily) clean up the mess.
>> Agreed. We need to make this more robust.
> Right, disambiguating a 'probes left by a session that did auto-probing'
> from a 'hey, those probes are there intentionally, just use those' is
> important.
>
>>>> Not allowing 'perf probe' for SDT event will solve all such issues.
>>>> Also it will make user interface simple and consistent. Other current
>>>> tooling (systemtap, for instance) also do not allow probing individual
>>>> markers when there are multiple markers with the same name.
>>> In any case if others agree with your change in UI flow too then it's fine by me, 
>>> but please make it robust, i.e. if perf record sees partially enabled probes it 
>>> should still continue.
>> @Masami, can you please provide your thoughts as well.
> Yeah, if technically possible to allow both variants, we should leave
> it up to users to decide what is best?
>
> I.e. most people will do auto-probing, not using 'perf probe' at all,
> documentation should state the pitfalls in doing so.
>
> So, after writing the above, perhaps we should warn the user that
> pre-existing probes are being used, as this will be the odd case?
>
> The normal flow will be just using perf record with SDT probes, that
> will auto-probe them and remove on exit, or better drop a reference to
> them, as simultaneous use also needs to be covered?
>
> - Arnaldo
>

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

* Re: [RFC] perf/sdt: Directly record SDT event with 'perf record'
  2017-02-23  8:13                                       ` Ravi Bangoria
@ 2017-02-23 12:48                                         ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-02-23 12:48 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: Ingo Molnar, masami.hiramatsu.pt, mingo, brendan.d.gregg, peterz,
	alexander.shishkin, wangnan0, jolsa, ak, treeze.taeung,
	mathieu.poirier, hekuang, sukadev, ananth, naveen.n.rao,
	colin.ing, adrian.hunter, linux-kernel, hemant

Em Thu, Feb 23, 2017 at 01:43:38PM +0530, Ravi Bangoria escreveu:
> Thanks Arnaldo,
> 
> I'm working on this but it's taking bit longer time. Will post out a patch within
> few days.

Take your time and thanks for giving consideration to my observations,

Regards,

- Arnaldo
 
> Ravi
> 
> On Monday 20 February 2017 07:41 PM, Arnaldo Carvalho de Melo wrote:
> > Em Mon, Feb 20, 2017 at 04:31:50PM +0530, Ravi Bangoria escreveu:
> >> Thanks Ingo,
> >>
> >> On Monday 20 February 2017 02:12 PM, Ingo Molnar wrote:
> >>> * Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> >>>
> >>>> What should be the behavior of the tool? Should it record only one
> >>>> 'sdt_libpthread:mutex_entry' which exists in uprobe_events? Or it
> >>>> should record all the SDT events from libpthread? We can choose either
> >>>> of two but both the cases are ambiguous.
> >>> They are not ambiguous really if coded right: just pick one of the outcomes and 
> >>> maybe print a warning to inform the user that something weird is going on because 
> >>> not all markers are enabled?
> >>>
> >>> As a user I'd expect 'perf record' to enable all markers and print a warning that 
> >>> the markers were in a partial state. This would result in consistent behaviour.
> >> Yes, makes sense.
> >>
> >>> Does it make sense to only enable some of the markers that alias on the same name? 
> >>> If not then maybe disallow that in perf probe - or change perf probe to do the 
> >>> same thing as perf record.
> >> 'perf probe' is doing that correctly. It fetches all events with given name from
> >> probe-cache and creates entries for them in uprobe_events.
> >>
> >> The problem is the 2-step process of adding probes and then recording,
> >> allowing users to select individual markers to record on.
> > So, the more streamlined one works for most people, i.e. just use perf
> > record, no need to perf probe anything. But, for people who "know what
> > they are doing", perf probe can be used first to control exactly which
> > SDT probes one wants in place, and then those will be used.
> >
> > We need to make sure that when processing the file there is information
> > that says which probes were in place and enabled in the record session,
> > tho. Is that possible?
> >
> >>> I.e. this is IMHO an artificial problem that users should not be exposed to and 
> >>> which can be solved by tooling.
> >>>
> >>> In particular if it's possible to enable only a part of the markers then perf 
> >>> record not continuing would be a failure mode: if for example a previous perf 
> >>> record session segfaulted (or ran out of RAM or was killed in the wrong moment or 
> >>> whatever) then it would not be possible to (easily) clean up the mess.
> >> Agreed. We need to make this more robust.
> > Right, disambiguating a 'probes left by a session that did auto-probing'
> > from a 'hey, those probes are there intentionally, just use those' is
> > important.
> >
> >>>> Not allowing 'perf probe' for SDT event will solve all such issues.
> >>>> Also it will make user interface simple and consistent. Other current
> >>>> tooling (systemtap, for instance) also do not allow probing individual
> >>>> markers when there are multiple markers with the same name.
> >>> In any case if others agree with your change in UI flow too then it's fine by me, 
> >>> but please make it robust, i.e. if perf record sees partially enabled probes it 
> >>> should still continue.
> >> @Masami, can you please provide your thoughts as well.
> > Yeah, if technically possible to allow both variants, we should leave
> > it up to users to decide what is best?
> >
> > I.e. most people will do auto-probing, not using 'perf probe' at all,
> > documentation should state the pitfalls in doing so.
> >
> > So, after writing the above, perhaps we should warn the user that
> > pre-existing probes are being used, as this will be the odd case?
> >
> > The normal flow will be just using perf record with SDT probes, that
> > will auto-probe them and remove on exit, or better drop a reference to
> > them, as simultaneous use also needs to be covered?
> >
> > - Arnaldo
> >

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

* Re: [PATCH 0/5] perf/sdt: Argument support for x86 and powepc
  2017-02-07  2:55                 ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Masami Hiramatsu
@ 2017-03-06  7:53                   ` Ravi Bangoria
  2017-03-06 13:42                     ` Masami Hiramatsu
  0 siblings, 1 reply; 77+ messages in thread
From: Ravi Bangoria @ 2017-03-06  7:53 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy, Ravi Bangoria



On Tuesday 07 February 2017 08:25 AM, Masami Hiramatsu wrote:
> On Thu,  2 Feb 2017 16:41:38 +0530
> Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
>
>> The v5 patchset for sdt marker argument support for x86 [1] has
>> couple  of issues. For example, it still has x86 specific code
>> in general code. It lacks support for rNN (with size postfix
>> b/w/d), %rsp, %esp, %sil etc. registers and such sdt markers
>> are failing at 'perf probe'. It also fails to convert arguments
>> having no offset but still surrounds register with parenthesis
>> for ex. 8@(%rdi) is converted to +(%di):u64 which is rejected
>> by uprobe_events. It's causing failure at 'perf probe' for all
>> SDT events on all archs except x86. With this patchset, I've
>> solved these issues. (patch 2,3)
>>
>> Also, existing perf shows misleading message when user tries to
>> record sdt event without probing it. I've prepared patch for
>> the same. (patch 1)
>>
>> Apart from that, I've also added logic to support arguments with
>> sdt marker on powerpc. (patch 4)
>>
>> There are cases where uprobe definition of sdt event goes beyond
>> current limit MAX_CMDLEN (256) and in such case perf fails with
>> seg fault. I've solve this issue. (patch 5)
>>
>> Note: This patchset is prepared on top of Alexis' v5 series.[1]
>>
>> [1] http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1292251.html
> Hmm, I must missed it. I'll check it...
>

Hi Masami,

Can you please review this.

Thanks,
-Ravi

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

* Re: [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments
  2016-12-14  0:07             ` [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
@ 2017-03-06 13:39               ` Masami Hiramatsu
  2017-03-21 13:52                 ` Arnaldo Carvalho de Melo
  2017-03-24 18:44               ` [tip:perf/core] perf sdt: Add scanning of sdt probes arguments tip-bot for Alexis Berlemont
  1 sibling, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-06 13:39 UTC (permalink / raw)
  To: Alexis Berlemont; +Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin

On Wed, 14 Dec 2016 01:07:31 +0100
Alexis Berlemont <alexis.berlemont@gmail.com> wrote:

> During a "perf buildid-cache --add" command, the section
> ".note.stapsdt" of the "added" binary is scanned in order to list the
> available SDT markers available in a binary. The parts containing the
> probes arguments were left unscanned.
> 
> The whole section is now parsed; the probe arguments are extracted for
> later use.
> 

Looks good to me.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>  tools/perf/util/symbol-elf.c | 25 +++++++++++++++++++++++--
>  tools/perf/util/symbol.h     |  1 +
>  2 files changed, 24 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 99400b0..7725c3f 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
>  static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  			     struct list_head *sdt_notes)
>  {
> -	const char *provider, *name;
> +	const char *provider, *name, *args;
>  	struct sdt_note *tmp = NULL;
>  	GElf_Ehdr ehdr;
>  	GElf_Addr base_off = 0;
> @@ -1881,6 +1881,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  		goto out_free_prov;
>  	}
>  
> +	args = memchr(name, '\0', data + len - name);
> +
> +	/*
> +	 * There is no argument if:
> +	 * - We reached the end of the note;
> +	 * - There is not enough room to hold a potential string;
> +	 * - The argument string is empty or just contains ':'.
> +	 */
> +	if (args == NULL || data + len - args < 2 ||
> +		args[1] == ':' || args[1] == '\0')
> +		tmp->args = NULL;
> +	else {
> +		tmp->args = strdup(++args);
> +		if (!tmp->args) {
> +			ret = -ENOMEM;
> +			goto out_free_name;
> +		}
> +	}
> +
>  	if (gelf_getclass(*elf) == ELFCLASS32) {
>  		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
>  		tmp->bit32 = true;
> @@ -1892,7 +1911,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  	if (!gelf_getehdr(*elf, &ehdr)) {
>  		pr_debug("%s : cannot get elf header.\n", __func__);
>  		ret = -EBADF;
> -		goto out_free_name;
> +		goto out_free_args;
>  	}
>  
>  	/* Adjust the prelink effect :
> @@ -1917,6 +1936,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
>  	list_add_tail(&tmp->note_list, sdt_notes);
>  	return 0;
>  
> +out_free_args:
> +	free(tmp->args);
>  out_free_name:
>  	free(tmp->name);
>  out_free_prov:
> diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> index 6c358b7..9222c7e 100644
> --- a/tools/perf/util/symbol.h
> +++ b/tools/perf/util/symbol.h
> @@ -351,6 +351,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
>  struct sdt_note {
>  	char *name;			/* name of the note*/
>  	char *provider;			/* provider name */
> +	char *args;
>  	bool bit32;			/* whether the location is 32 bits? */
>  	union {				/* location, base and semaphore addrs */
>  		Elf64_Addr a64[3];
> -- 
> 2.10.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 0/5] perf/sdt: Argument support for x86 and powepc
  2017-03-06  7:53                   ` Ravi Bangoria
@ 2017-03-06 13:42                     ` Masami Hiramatsu
  0 siblings, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-06 13:42 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy

On Mon, 6 Mar 2017 13:23:30 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> 
> 
> On Tuesday 07 February 2017 08:25 AM, Masami Hiramatsu wrote:
> > On Thu,  2 Feb 2017 16:41:38 +0530
> > Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> >
> >> The v5 patchset for sdt marker argument support for x86 [1] has
> >> couple  of issues. For example, it still has x86 specific code
> >> in general code. It lacks support for rNN (with size postfix
> >> b/w/d), %rsp, %esp, %sil etc. registers and such sdt markers
> >> are failing at 'perf probe'. It also fails to convert arguments
> >> having no offset but still surrounds register with parenthesis
> >> for ex. 8@(%rdi) is converted to +(%di):u64 which is rejected
> >> by uprobe_events. It's causing failure at 'perf probe' for all
> >> SDT events on all archs except x86. With this patchset, I've
> >> solved these issues. (patch 2,3)
> >>
> >> Also, existing perf shows misleading message when user tries to
> >> record sdt event without probing it. I've prepared patch for
> >> the same. (patch 1)
> >>
> >> Apart from that, I've also added logic to support arguments with
> >> sdt marker on powerpc. (patch 4)
> >>
> >> There are cases where uprobe definition of sdt event goes beyond
> >> current limit MAX_CMDLEN (256) and in such case perf fails with
> >> seg fault. I've solve this issue. (patch 5)
> >>
> >> Note: This patchset is prepared on top of Alexis' v5 series.[1]
> >>
> >> [1] http://www.mail-archive.com/linux-kernel@vger.kernel.org/msg1292251.html
> > Hmm, I must missed it. I'll check it...
> >
> 
> Hi Masami,
> 
> Can you please review this.

Thanks for kicking me :)


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-14  0:07             ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2017-01-24  8:50               ` Ravi Bangoria
@ 2017-03-06 17:23               ` Masami Hiramatsu
  2017-03-24 18:44               ` [tip:perf/core] perf probe: Add " tip-bot for Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-06 17:23 UTC (permalink / raw)
  To: Alexis Berlemont; +Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin

On Wed, 14 Dec 2016 01:07:32 +0100
Alexis Berlemont <alexis.berlemont@gmail.com> wrote:

> An sdt probe can be associated with arguments but they were not passed
> to the user probe tracing interface (uprobe_events); this patch adapts
> the sdt argument descriptors according to the uprobe input format.
> 
> As the uprobe parser does not support scaled address mode, perf will
> skip arguments which cannot be adapted to the uprobe format.
> 
> Here are the results:
> 
> $ perf buildid-cache -v --add test_sdt
> $ perf probe -x test_sdt sdt_libfoo:table_frob
> $ perf probe -x test_sdt sdt_libfoo:table_diddle
> $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
> $ perf script
> test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
> test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
> test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
> test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
> test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
> test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8
> 

OK, this looks good to me, good job!

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks!

> Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> ---
>  tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
>  tools/perf/util/perf_regs.c          |   6 ++
>  tools/perf/util/perf_regs.h          |   6 ++
>  tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
>  4 files changed, 261 insertions(+), 4 deletions(-)
> 
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index c5db14f..09a7f55 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -1,4 +1,7 @@
> +#include <string.h>
> +
>  #include "../../perf.h"
> +#include "../../util/util.h"
>  #include "../../util/perf_regs.h"
>  
>  const struct sample_reg sample_reg_masks[] = {
> @@ -26,3 +29,83 @@ const struct sample_reg sample_reg_masks[] = {
>  #endif
>  	SMPL_REG_END
>  };
> +
> +struct sdt_name_reg {
> +	const char *sdt_name;
> +	const char *uprobe_name;
> +};
> +#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
> +#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
> +
> +static const struct sdt_name_reg sdt_reg_renamings[] = {
> +	SDT_NAME_REG(eax, ax),
> +	SDT_NAME_REG(rax, ax),
> +	SDT_NAME_REG(ebx, bx),
> +	SDT_NAME_REG(rbx, bx),
> +	SDT_NAME_REG(ecx, cx),
> +	SDT_NAME_REG(rcx, cx),
> +	SDT_NAME_REG(edx, dx),
> +	SDT_NAME_REG(rdx, dx),
> +	SDT_NAME_REG(esi, si),
> +	SDT_NAME_REG(rsi, si),
> +	SDT_NAME_REG(edi, di),
> +	SDT_NAME_REG(rdi, di),
> +	SDT_NAME_REG(ebp, bp),
> +	SDT_NAME_REG(rbp, bp),
> +	SDT_NAME_REG_END,
> +};
> +
> +int sdt_rename_register(char **pdesc, char *old_name)
> +{
> +	const struct sdt_name_reg *rnames = sdt_reg_renamings;
> +	char *new_desc, *old_desc = *pdesc;
> +	size_t prefix_len, sdt_len, uprobe_len, old_desc_len, offset;
> +	int ret = -1;
> +
> +	while (ret != 0 && rnames->sdt_name != NULL) {
> +		sdt_len = strlen(rnames->sdt_name);
> +		ret = strncmp(old_name, rnames->sdt_name, sdt_len);
> +		rnames += !!ret;
> +	}
> +
> +	if (rnames->sdt_name == NULL)
> +		return 0;
> +
> +	sdt_len = strlen(rnames->sdt_name);
> +	uprobe_len = strlen(rnames->uprobe_name);
> +	old_desc_len = strlen(old_desc) + 1;
> +
> +	new_desc = zalloc(old_desc_len + uprobe_len - sdt_len);
> +	if (new_desc == NULL)
> +		return -1;
> +
> +	/* Copy the chars before the register name (at least '%') */
> +	prefix_len = old_name - old_desc;
> +	memcpy(new_desc, old_desc, prefix_len);
> +
> +	/* Copy the new register name */
> +	memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
> +
> +	/* Copy the chars after the register name (if need be) */
> +	offset = prefix_len + sdt_len;
> +	if (offset < old_desc_len) {
> +		/*
> +		 * The orginal register name can be suffixed by 'b',
> +		 * 'w' or 'd' to indicate its size; so, we need to
> +		 * skip this char if we met one.
> +		 */
> +		char sfx = old_desc[offset];
> +
> +		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
> +			offset++;
> +	}
> +
> +	if (offset < old_desc_len)
> +		memcpy(new_desc + prefix_len + uprobe_len,
> +			old_desc + offset, old_desc_len - offset);
> +
> +	free(old_desc);
> +	*pdesc = new_desc;
> +
> +	return 0;
> +}
> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index c4023f2..a37e593 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
>  	SMPL_REG_END
>  };
>  
> +int __weak sdt_rename_register(char **pdesc __maybe_unused,
> +			char *old_name __maybe_unused)
> +{
> +	return 0;
> +}
> +
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
>  {
> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index 679d6e4..7544a15 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -15,6 +15,12 @@ struct sample_reg {
>  
>  extern const struct sample_reg sample_reg_masks[];
>  
> +/*
> + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> + * registers before filling the uprobe tracer interface.
> + */
> +int sdt_rename_register(char **pdesc, char *old_name);
> +
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  #include <perf_regs.h>
>  
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 436b647..d8a169e 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -27,6 +27,7 @@
>  #include "probe-event.h"
>  #include "probe-file.h"
>  #include "session.h"
> +#include "perf_regs.h"
>  
>  #define MAX_CMDLEN 256
>  
> @@ -687,6 +688,166 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
>  		 : (unsigned long long)note->addr.a64[0];
>  }
>  
> +static const char * const type_to_suffix[] = {
> +	":s64", "", "", "", ":s32", "", ":s16", ":s8",
> +	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
> +};
> +
> +static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
> +{
> +	char *tmp, *desc = strdup(arg);
> +	const char *prefix = "", *suffix = "";
> +	int ret = -1;
> +
> +	if (desc == NULL) {
> +		pr_debug4("Allocation error\n");
> +		return ret;
> +	}
> +
> +	tmp = strchr(desc, '@');
> +	if (tmp) {
> +		long type_idx;
> +		/*
> +		 * Isolate the string number and convert it into a
> +		 * binary value; this will be an index to get suffix
> +		 * of the uprobe name (defining the type)
> +		 */
> +		tmp[0] = '\0';
> +		type_idx = strtol(desc, NULL, 10);
> +		/* Check that the conversion went OK */
> +		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
> +			pr_debug4("Failed to parse sdt type\n");
> +			goto error;
> +		}
> +		/* Check that the converted value is OK */
> +		if (type_idx < -8 || type_idx > 8) {
> +			pr_debug4("Failed to get a valid sdt type\n");
> +			goto error;
> +		}
> +		suffix = type_to_suffix[type_idx + 8];
> +		/* Get rid of the sdt prefix which is now useless */
> +		tmp++;
> +		memmove(desc, tmp, strlen(tmp) + 1);
> +	}
> +
> +	/*
> +	 * The uprobe tracer format does not support all the
> +	 * addressing modes (notably: in x86 the scaled mode); so, we
> +	 * detect ',' characters, if there is just one, there is no
> +	 * use converting the sdt arg into a uprobe one.
> +	 */
> +	if (strchr(desc, ',')) {
> +		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> +		goto out;
> +	}
> +
> +	/*
> +	 * If the argument addressing mode is indirect, we must check
> +	 * a few things...
> +	 */
> +	tmp = strchr(desc, '(');
> +	if (tmp) {
> +		int j;
> +
> +		/*
> +		 * ...if the addressing mode is indirect with a
> +		 * positive offset (ex.: "1608(%ax)"), we need to add
> +		 * a '+' prefix so as to be compliant with uprobe
> +		 * format.
> +		 */
> +		if (desc[0] != '+' && desc[0] != '-')
> +			prefix = "+";
> +
> +		/*
> +		 * ...or if the addressing mode is indirect with a symbol
> +		 * as offset, the argument will not be supported by
> +		 * the uprobe tracer format; so, let's skip this one.
> +		 */
> +		for (j = 0; j < tmp - desc; j++) {
> +			if (desc[j] != '+' && desc[j] != '-' &&
> +				!isdigit(desc[j])) {
> +				pr_debug4("Skipping unsupported SDT argument; "
> +					"%s\n", desc);
> +				goto out;
> +			}
> +		}
> +	}
> +
> +	/*
> +	 * The uprobe tracer format does not support constants; if we
> +	 * find one in the current argument, let's skip the argument.
> +	 */
> +	if (strchr(desc, '$')) {
> +		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> +		goto out;
> +	}
> +
> +	/*
> +	 * The uprobe parser does not support all gas register names;
> +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> +	 * the loop below looks for the register names (starting with
> +	 * a '%' and tries to perform the needed renamings.
> +	 */
> +	tmp = strchr(desc, '%');
> +	while (tmp) {
> +		size_t offset = tmp - desc;
> +
> +		ret = sdt_rename_register(&desc, desc + offset);
> +		if (ret < 0)
> +			goto error;
> +
> +		/*
> +		 * The desc pointer might have changed; so, let's not
> +		 * try to reuse tmp for next lookup
> +		 */
> +		tmp = strchr(desc + offset + 1, '%');
> +	}
> +
> +	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
> +		goto error;
> +
> +out:
> +	ret = 0;
> +error:
> +	free(desc);
> +	return ret;
> +}
> +
> +static char *synthesize_sdt_probe_command(struct sdt_note *note,
> +					const char *pathname,
> +					const char *sdtgrp)
> +{
> +	struct strbuf buf;
> +	char *ret = NULL, **args;
> +	int i, args_count;
> +
> +	if (strbuf_init(&buf, 32) < 0)
> +		return NULL;
> +
> +	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
> +				sdtgrp, note->name, pathname,
> +				sdt_note__get_addr(note)) < 0)
> +		goto error;
> +
> +	if (!note->args)
> +		goto out;
> +
> +	if (note->args) {
> +		args = argv_split(note->args, &args_count);
> +
> +		for (i = 0; i < args_count; ++i) {
> +			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
> +				goto error;
> +		}
> +	}
> +
> +out:
> +	ret = strbuf_detach(&buf, NULL);
> +error:
> +	strbuf_release(&buf);
> +	return ret;
> +}
> +
>  int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>  {
>  	struct probe_cache_entry *entry = NULL;
> @@ -723,11 +884,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
>  			entry->pev.group = strdup(sdtgrp);
>  			list_add_tail(&entry->node, &pcache->entries);
>  		}
> -		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
> -				sdtgrp, note->name, pathname,
> -				sdt_note__get_addr(note));
> -		if (ret < 0)
> +		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
> +		if (!buf) {
> +			ret = -ENOMEM;
>  			break;
> +		}
> +
>  		strlist__add(entry->tevlist, buf);
>  		free(buf);
>  		entry = NULL;
> -- 
> 2.10.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string
  2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
  2016-12-14  7:36               ` Ingo Molnar
  2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
@ 2017-03-21  5:08               ` Masami Hiramatsu
  2 siblings, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-21  5:08 UTC (permalink / raw)
  To: Alexis Berlemont; +Cc: linux-kernel, peterz, mingo, acme, alexander.shishkin

Hello Alexis and Arnaldo,

I think this series is now good to go.
Could you pick these? 

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

for this series.

Thank you,

On Wed, 14 Dec 2016 01:07:30 +0100
Alexis Berlemont <alexis.berlemont@gmail.com> wrote:

> Hi Masami,
> 
> Many thanks for your mail.
> 
> Here is another patch set which tries to fix the points you mentioned:
> 
> * Skip the arguments containing a constant ($123); 
> * Review the code in charge of the register renaming (search for '%'
>   and parse it);
> * Minor changes (print the argument in case of error, skipping, check
>   the sdt arg type index);
> 
> Many thanks,
> 
> Alexis.
> 
> Alexis Berlemont (2):
>   perf sdt: add scanning of sdt probles arguments
>   perf probe: add sdt probes arguments into the uprobe cmd string
> 
>  tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
>  tools/perf/util/perf_regs.c          |   6 ++
>  tools/perf/util/perf_regs.h          |   6 ++
>  tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
>  tools/perf/util/symbol-elf.c         |  25 +++++-
>  tools/perf/util/symbol.h             |   1 +
>  6 files changed, 285 insertions(+), 6 deletions(-)
> 
> -- 
> 2.10.2
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v2] perf/probe: Change MAX_CMDLEN
  2017-02-07  5:45                     ` [PATCH v2] " Ravi Bangoria
@ 2017-03-21  5:19                       ` Masami Hiramatsu
  2017-03-21 13:37                         ` Arnaldo Carvalho de Melo
  2017-03-24 18:43                       ` [tip:perf/core] perf probe: " tip-bot for Ravi Bangoria
  1 sibling, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-21  5:19 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, linux-kernel, alexis.berlemont, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy

On Tue,  7 Feb 2017 11:15:47 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> There are many SDT markers in powerpc whose uprobe definition goes
> beyond current MAX_CMDLEN, especially when target filename is long
> and sdt marker has long list of arguments. For example, definition
> of sdt marker
> 
>   method__compile__end: 8@17 8@9 8@10 -4@8 8@7 -4@6 8@5 -4@4 1@37(28)
> 
> from file
> 
>   /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.91-2.b14.fc22.ppc64/jre/lib/\
>      ppc64/server/libjvm.so
> 
> is
> 
>   p:sdt_hotspot/method__compile__end /usr/lib/jvm/java-1.8.0-openjdk-\
>     1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so:0x4c4e00\
>     arg1=%gpr17:u64 arg2=%gpr9:u64 arg3=%gpr10:u64 arg4=%gpr8:s32\
>     arg5=%gpr7:u64 arg6=%gpr6:s32 arg7=%gpr5:u64 arg8=%gpr4:s32\
>     arg9=+37(%gpr28):u8
> 
> Perf probe fails with seg fault for such markers. As uprobe_events file
> accepts definition upto 4094 characters(4096 - 2 (\n\0)), increase value
> of MAX_CMDLEN to 4094.

This looks good to me.

Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks,

> 
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
> Changes in v2:
>   - Set MAX_CMDLEN to 4094 instead of 512
> 
>  tools/perf/util/probe-event.c | 1 -
>  tools/perf/util/probe-file.c  | 3 ++-
>  2 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> index 6a6f44d..e6e3244 100644
> --- a/tools/perf/util/probe-event.c
> +++ b/tools/perf/util/probe-event.c
> @@ -47,7 +47,6 @@
>  #include "probe-file.h"
>  #include "session.h"
>  
> -#define MAX_CMDLEN 256
>  #define PERFPROBE_GROUP "probe"
>  
>  bool probe_event_dry_run;	/* Dry run flag */
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index 38eca3c..fdabe7e 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -29,7 +29,8 @@
>  #include "session.h"
>  #include "perf_regs.h"
>  
> -#define MAX_CMDLEN 256
> +/* 4096 - 2 ('\n' + '\0') */
> +#define MAX_CMDLEN 4094
>  
>  static void print_open_warning(int err, bool uprobe)
>  {
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v2] perf/probe: Change MAX_CMDLEN
  2017-03-21  5:19                       ` Masami Hiramatsu
@ 2017-03-21 13:37                         ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-03-21 13:37 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Ravi Bangoria, linux-kernel, alexis.berlemont, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy

Em Tue, Mar 21, 2017 at 02:19:50PM +0900, Masami Hiramatsu escreveu:
> On Tue,  7 Feb 2017 11:15:47 +0530
> Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> 
> > There are many SDT markers in powerpc whose uprobe definition goes
> > beyond current MAX_CMDLEN, especially when target filename is long
> > and sdt marker has long list of arguments. For example, definition
> > of sdt marker
> > 
> >   method__compile__end: 8@17 8@9 8@10 -4@8 8@7 -4@6 8@5 -4@4 1@37(28)
> > 
> > from file
> > 
> >   /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.91-2.b14.fc22.ppc64/jre/lib/\
> >      ppc64/server/libjvm.so
> > 
> > is
> > 
> >   p:sdt_hotspot/method__compile__end /usr/lib/jvm/java-1.8.0-openjdk-\
> >     1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so:0x4c4e00\
> >     arg1=%gpr17:u64 arg2=%gpr9:u64 arg3=%gpr10:u64 arg4=%gpr8:s32\
> >     arg5=%gpr7:u64 arg6=%gpr6:s32 arg7=%gpr5:u64 arg8=%gpr4:s32\
> >     arg9=+37(%gpr28):u8
> > 
> > Perf probe fails with seg fault for such markers. As uprobe_events file
> > accepts definition upto 4094 characters(4096 - 2 (\n\0)), increase value
> > of MAX_CMDLEN to 4094.
> 
> This looks good to me.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks, applied manually, as the code patched drifted some lines away
from the ones here.

- Arnaldo
 
> Thanks,
> 
> > 
> > Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> > ---
> > Changes in v2:
> >   - Set MAX_CMDLEN to 4094 instead of 512
> > 
> >  tools/perf/util/probe-event.c | 1 -
> >  tools/perf/util/probe-file.c  | 3 ++-
> >  2 files changed, 2 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
> > index 6a6f44d..e6e3244 100644
> > --- a/tools/perf/util/probe-event.c
> > +++ b/tools/perf/util/probe-event.c
> > @@ -47,7 +47,6 @@
> >  #include "probe-file.h"
> >  #include "session.h"
> >  
> > -#define MAX_CMDLEN 256
> >  #define PERFPROBE_GROUP "probe"
> >  
> >  bool probe_event_dry_run;	/* Dry run flag */
> > diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> > index 38eca3c..fdabe7e 100644
> > --- a/tools/perf/util/probe-file.c
> > +++ b/tools/perf/util/probe-file.c
> > @@ -29,7 +29,8 @@
> >  #include "session.h"
> >  #include "perf_regs.h"
> >  
> > -#define MAX_CMDLEN 256
> > +/* 4096 - 2 ('\n' + '\0') */
> > +#define MAX_CMDLEN 4094
> >  
> >  static void print_open_warning(int err, bool uprobe)
> >  {
> > -- 
> > 2.9.3
> > 
> 
> 
> -- 
> Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments
  2017-03-06 13:39               ` Masami Hiramatsu
@ 2017-03-21 13:52                 ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-03-21 13:52 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Alexis Berlemont, linux-kernel, peterz, mingo, alexander.shishkin

Em Mon, Mar 06, 2017 at 02:39:15PM +0100, Masami Hiramatsu escreveu:
> On Wed, 14 Dec 2016 01:07:31 +0100
> Alexis Berlemont <alexis.berlemont@gmail.com> wrote:
> 
> > During a "perf buildid-cache --add" command, the section
> > ".note.stapsdt" of the "added" binary is scanned in order to list the
> > available SDT markers available in a binary. The parts containing the
> > probes arguments were left unscanned.
> > 
> > The whole section is now parsed; the probe arguments are extracted for
> > later use.
> > 
> 
> Looks good to me.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks, applied.
 
> Thanks!
> 
> > Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
> > ---
> >  tools/perf/util/symbol-elf.c | 25 +++++++++++++++++++++++--
> >  tools/perf/util/symbol.h     |  1 +
> >  2 files changed, 24 insertions(+), 2 deletions(-)
> > 
> > diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> > index 99400b0..7725c3f 100644
> > --- a/tools/perf/util/symbol-elf.c
> > +++ b/tools/perf/util/symbol-elf.c
> > @@ -1822,7 +1822,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
> >  static int populate_sdt_note(Elf **elf, const char *data, size_t len,
> >  			     struct list_head *sdt_notes)
> >  {
> > -	const char *provider, *name;
> > +	const char *provider, *name, *args;
> >  	struct sdt_note *tmp = NULL;
> >  	GElf_Ehdr ehdr;
> >  	GElf_Addr base_off = 0;
> > @@ -1881,6 +1881,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
> >  		goto out_free_prov;
> >  	}
> >  
> > +	args = memchr(name, '\0', data + len - name);
> > +
> > +	/*
> > +	 * There is no argument if:
> > +	 * - We reached the end of the note;
> > +	 * - There is not enough room to hold a potential string;
> > +	 * - The argument string is empty or just contains ':'.
> > +	 */
> > +	if (args == NULL || data + len - args < 2 ||
> > +		args[1] == ':' || args[1] == '\0')
> > +		tmp->args = NULL;
> > +	else {
> > +		tmp->args = strdup(++args);
> > +		if (!tmp->args) {
> > +			ret = -ENOMEM;
> > +			goto out_free_name;
> > +		}
> > +	}
> > +
> >  	if (gelf_getclass(*elf) == ELFCLASS32) {
> >  		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
> >  		tmp->bit32 = true;
> > @@ -1892,7 +1911,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
> >  	if (!gelf_getehdr(*elf, &ehdr)) {
> >  		pr_debug("%s : cannot get elf header.\n", __func__);
> >  		ret = -EBADF;
> > -		goto out_free_name;
> > +		goto out_free_args;
> >  	}
> >  
> >  	/* Adjust the prelink effect :
> > @@ -1917,6 +1936,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
> >  	list_add_tail(&tmp->note_list, sdt_notes);
> >  	return 0;
> >  
> > +out_free_args:
> > +	free(tmp->args);
> >  out_free_name:
> >  	free(tmp->name);
> >  out_free_prov:
> > diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
> > index 6c358b7..9222c7e 100644
> > --- a/tools/perf/util/symbol.h
> > +++ b/tools/perf/util/symbol.h
> > @@ -351,6 +351,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
> >  struct sdt_note {
> >  	char *name;			/* name of the note*/
> >  	char *provider;			/* provider name */
> > +	char *args;
> >  	bool bit32;			/* whether the location is 32 bits? */
> >  	union {				/* location, base and semaphore addrs */
> >  		Elf64_Addr a64[3];
> > -- 
> > 2.10.2
> > 
> 
> 
> -- 
> Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers
  2017-02-07  3:11                   ` Masami Hiramatsu
@ 2017-03-21 14:08                     ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-03-21 14:08 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Ravi Bangoria, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy

Em Tue, Feb 07, 2017 at 12:11:59PM +0900, Masami Hiramatsu escreveu:
> On Thu,  2 Feb 2017 16:41:40 +0530
> Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> 
> > 'perf probe' is failing for sdt markers whose arguments has rNN
> > (with postfix b/w/d), %rsp, %esp, %sil etc. registers. Add renaming
> > logic for these registers.
> > 
> 
> Looks good to me.
> 
> Acked-by: Masami Hiramatsu <mhiramat@kernel.org>

Thanks, applied right after that v5 series from Alexis.
 
> Thanks!
> 
> > Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> > ---
> >  tools/perf/arch/x86/util/perf_regs.c | 44 ++++++++++++++++++++++++++----------
> >  1 file changed, 32 insertions(+), 12 deletions(-)
> > 
> > diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> > index 09a7f55..d8a8dcf 100644
> > --- a/tools/perf/arch/x86/util/perf_regs.c
> > +++ b/tools/perf/arch/x86/util/perf_regs.c
> > @@ -48,10 +48,42 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
> >  	SDT_NAME_REG(rdx, dx),
> >  	SDT_NAME_REG(esi, si),
> >  	SDT_NAME_REG(rsi, si),
> > +	SDT_NAME_REG(sil, si),
> >  	SDT_NAME_REG(edi, di),
> >  	SDT_NAME_REG(rdi, di),
> > +	SDT_NAME_REG(dil, di),
> >  	SDT_NAME_REG(ebp, bp),
> >  	SDT_NAME_REG(rbp, bp),
> > +	SDT_NAME_REG(bpl, bp),
> > +	SDT_NAME_REG(rsp, sp),
> > +	SDT_NAME_REG(esp, sp),
> > +	SDT_NAME_REG(spl, sp),
> > +
> > +	/* rNN registers */
> > +	SDT_NAME_REG(r8b,  r8),
> > +	SDT_NAME_REG(r8w,  r8),
> > +	SDT_NAME_REG(r8d,  r8),
> > +	SDT_NAME_REG(r9b,  r9),
> > +	SDT_NAME_REG(r9w,  r9),
> > +	SDT_NAME_REG(r9d,  r9),
> > +	SDT_NAME_REG(r10b, r10),
> > +	SDT_NAME_REG(r10w, r10),
> > +	SDT_NAME_REG(r10d, r10),
> > +	SDT_NAME_REG(r11b, r11),
> > +	SDT_NAME_REG(r11w, r11),
> > +	SDT_NAME_REG(r11d, r11),
> > +	SDT_NAME_REG(r12b, r12),
> > +	SDT_NAME_REG(r12w, r12),
> > +	SDT_NAME_REG(r12d, r12),
> > +	SDT_NAME_REG(r13b, r13),
> > +	SDT_NAME_REG(r13w, r13),
> > +	SDT_NAME_REG(r13d, r13),
> > +	SDT_NAME_REG(r14b, r14),
> > +	SDT_NAME_REG(r14w, r14),
> > +	SDT_NAME_REG(r14d, r14),
> > +	SDT_NAME_REG(r15b, r15),
> > +	SDT_NAME_REG(r15w, r15),
> > +	SDT_NAME_REG(r15d, r15),
> >  	SDT_NAME_REG_END,
> >  };
> >  
> > @@ -88,18 +120,6 @@ int sdt_rename_register(char **pdesc, char *old_name)
> >  
> >  	/* Copy the chars after the register name (if need be) */
> >  	offset = prefix_len + sdt_len;
> > -	if (offset < old_desc_len) {
> > -		/*
> > -		 * The orginal register name can be suffixed by 'b',
> > -		 * 'w' or 'd' to indicate its size; so, we need to
> > -		 * skip this char if we met one.
> > -		 */
> > -		char sfx = old_desc[offset];
> > -
> > -		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
> > -			offset++;
> > -	}
> > -
> >  	if (offset < old_desc_len)
> >  		memcpy(new_desc + prefix_len + uprobe_len,
> >  			old_desc + offset, old_desc_len - offset);
> > -- 
> > 2.9.3
> > 
> 
> 
> -- 
> Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-02-07  5:22                     ` Ravi Bangoria
@ 2017-03-21 14:10                       ` Arnaldo Carvalho de Melo
  2017-03-21 23:00                         ` Masami Hiramatsu
  0 siblings, 1 reply; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-03-21 14:10 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: Masami Hiramatsu, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy

Em Tue, Feb 07, 2017 at 10:52:17AM +0530, Ravi Bangoria escreveu:
> Thanks Masami for the review.
> 
> On Tuesday 07 February 2017 08:41 AM, Masami Hiramatsu wrote:
> > On Thu,  2 Feb 2017 16:41:41 +0530
> > Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> >
> >> SDT marker argument is in N@OP format. N is the size of argument and
> >> OP is the actual assembly operand. OP is arch dependent component and
> >> hence it's parsing logic also should be placed under tools/perf/arch/.
> >>
> > Ok, I have one question. Is there any possibility that N is different
> > size of OP? e.g. 8@dil, in this case we will record whole rdi.
> > is that OK?
> 
> By looking at list of markers on my x86 Fedora25 box, yes, it's possible
> for case when register size used in OP is more than size specified by N.
> For example, -4@68(%rbx). But I don't see any argument which specifies
> higher size in N compared to size of register in OP, like you mentioned
> in your example.

Masami, can I have your Acked-by for 3-5/5 in this series?

- Arnaldo

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

* Re: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-02-02 11:11                 ` [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Ravi Bangoria
  2017-02-07  3:11                   ` Masami Hiramatsu
@ 2017-03-21 14:55                   ` Masami Hiramatsu
  1 sibling, 0 replies; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-21 14:55 UTC (permalink / raw)
  To: Ravi Bangoria
  Cc: acme, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, mhiramat, maddy

On Thu,  2 Feb 2017 16:41:41 +0530
Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:

> SDT marker argument is in N@OP format. N is the size of argument and
> OP is the actual assembly operand. OP is arch dependent component and
> hence it's parsing logic also should be placed under tools/perf/arch/.
> 
> Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
> ---
>  tools/perf/arch/x86/util/perf_regs.c |  93 ++++++++++++++++++++++++-
>  tools/perf/util/perf_regs.c          |   9 ++-
>  tools/perf/util/perf_regs.h          |   7 +-
>  tools/perf/util/probe-file.c         | 127 +++++++++--------------------------
>  4 files changed, 134 insertions(+), 102 deletions(-)
> 
> diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
> index d8a8dcf..34fcb0d 100644
> --- a/tools/perf/arch/x86/util/perf_regs.c
> +++ b/tools/perf/arch/x86/util/perf_regs.c
> @@ -3,6 +3,7 @@
>  #include "../../perf.h"
>  #include "../../util/util.h"
>  #include "../../util/perf_regs.h"
> +#include "../../util/debug.h"
>  
>  const struct sample_reg sample_reg_masks[] = {
>  	SMPL_REG(AX, PERF_REG_X86_AX),
> @@ -87,7 +88,16 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
>  	SDT_NAME_REG_END,
>  };
>  
> -int sdt_rename_register(char **pdesc, char *old_name)
> +bool arch_sdt_probe_arg_supp(void)
> +{
> +	return true;
> +}
> +
> +/*
> + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> + * registers before filling the uprobe tracer interface.
> + */
> +static int sdt_rename_register(char **pdesc, char *old_name)
>  {
>  	const struct sdt_name_reg *rnames = sdt_reg_renamings;
>  	char *new_desc, *old_desc = *pdesc;
> @@ -129,3 +139,84 @@ int sdt_rename_register(char **pdesc, char *old_name)
>  
>  	return 0;
>  }
> +
> +/*
> + * x86 specific implementation
> + * return value:
> + *	<0 : error
> + *	 0 : success
> + *	>0 : skip
> + */
> +int arch_sdt_probe_parse_op(char **desc, const char **prefix)

Frankly to say, I prefer to see the function interface which has clearly
separated in/out arguments. This function, "desc" is used for both of
input and output.
Could you refactor this to separate args? for example,

int arch_sdt_probe_parse_op(const char *desc, struct strbuf *buf)

I think prefix also integrated with output buffer.

> +{
> +	char *tmp;
> +	int ret = 0;
> +
> +	/*
> +	 * The uprobe tracer format does not support all the addressing
> +	 * modes (notably: in x86 the scaled mode); so, we detect ','
> +	 * characters, if there is just one, there is no use converting
> +	 * the sdt arg into a uprobe one.
> +	 *
> +	 * Also it does not support constants; if we find one in the
> +	 * current argument, let's skip the argument.
> +	 */
> +	if (strchr(*desc, ',') || strchr(*desc, '$')) {
> +		pr_debug4("Skipping unsupported SDT argument; %s\n", *desc);
> +		return 1;
> +	}
> +
> +	/*
> +	 * If the argument addressing mode is indirect, we must check
> +	 * a few things...
> +	 */
> +	tmp = strchr(*desc, '(');
> +	if (tmp) {
> +		int j;
> +
> +		/*
> +		 * ...if the addressing mode is indirect with a
> +		 * positive offset (ex.: "1608(%ax)"), we need to add
> +		 * a '+' prefix so as to be compliant with uprobe
> +		 * format.
> +		 */
> +		if ((*desc)[0] != '+' && (*desc)[0] != '-')
> +			*prefix = ((*desc)[0] == '(') ? "+0" : "+";
> +
> +		/*
> +		 * ...or if the addressing mode is indirect with a symbol
> +		 * as offset, the argument will not be supported by
> +		 * the uprobe tracer format; so, let's skip this one.
> +		 */
> +		for (j = 0; j < tmp - *desc; j++) {
> +			if ((*desc)[j] != '+' && (*desc)[j] != '-' &&
> +			    !isdigit((*desc)[j])) {
> +				pr_debug4("Skipping unsupported SDT argument; "
> +					"%s\n", *desc);
> +				return 1;
> +			}
> +		}
> +	}
> +
> +	/*
> +	 * The uprobe parser does not support all gas register names;
> +	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> +	 * the loop below looks for the register names (starting with
> +	 * a '%' and tries to perform the needed renamings.
> +	 */
> +	tmp = strchr(*desc, '%');
> +	while (tmp) {
> +		size_t offset = tmp - *desc;
> +
> +		ret = sdt_rename_register(desc, *desc + offset);
> +		if (ret < 0)
> +			return ret;
> +
> +		/*
> +		 * The *desc pointer might have changed; so, let's not
> +		 * try to reuse tmp for next lookup
> +		 */
> +		tmp = strchr(*desc + offset + 1, '%');
> +	}
> +	return 0;
> +}
> diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
> index a37e593..f2b3d0d 100644
> --- a/tools/perf/util/perf_regs.c
> +++ b/tools/perf/util/perf_regs.c
> @@ -6,8 +6,13 @@ const struct sample_reg __weak sample_reg_masks[] = {
>  	SMPL_REG_END
>  };
>  
> -int __weak sdt_rename_register(char **pdesc __maybe_unused,
> -			char *old_name __maybe_unused)
> +bool __weak arch_sdt_probe_arg_supp(void)
> +{
> +	return false;
> +}
> +
> +int __weak arch_sdt_probe_parse_op(char **op_ptr __maybe_unused,
> +				   const char **prefix __maybe_unused)
>  {
>  	return 0;
>  }

Hmm, why we we need both of these functions?
I think you just need to return 1 from arch_sdt_probe_parse_op(), then
all the arguments are skipped.

> diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
> index 7544a15..86a2961 100644
> --- a/tools/perf/util/perf_regs.h
> +++ b/tools/perf/util/perf_regs.h
> @@ -15,11 +15,8 @@ struct sample_reg {
>  
>  extern const struct sample_reg sample_reg_masks[];
>  
> -/*
> - * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
> - * registers before filling the uprobe tracer interface.
> - */
> -int sdt_rename_register(char **pdesc, char *old_name);
> +bool arch_sdt_probe_arg_supp(void);
> +int arch_sdt_probe_parse_op(char **op_ptr, const char **prefix);
>  
>  #ifdef HAVE_PERF_REGS_SUPPORT
>  #include <perf_regs.h>
> diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
> index d8a169e..38eca3c 100644
> --- a/tools/perf/util/probe-file.c
> +++ b/tools/perf/util/probe-file.c
> @@ -693,6 +693,25 @@ static const char * const type_to_suffix[] = {
>  	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
>  };
>  
> +/*
> + * Isolate the string number and convert it into a decimal value;
> + * this will be an index to get suffix of the uprobe name (defining
> + * the type)
> + */
> +static int sdt_probe_parse_n(char *n_ptr, const char **suffix)

please make it more meaningful name, sdt_probe_parse_size() etc.

Thank you,

> +{
> +	long type_idx;
> +
> +	type_idx = strtol(n_ptr, NULL, 10);
> +	if (type_idx < -8 || type_idx > 8) {
> +		pr_debug4("Failed to get a valid sdt type\n");
> +		return -1;
> +	}
> +
> +	*suffix = type_to_suffix[type_idx + 8];
> +	return 0;
> +}
> +
>  static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
>  {
>  	char *tmp, *desc = strdup(arg);
> @@ -704,109 +723,29 @@ static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
>  		return ret;
>  	}
>  
> +	/*
> +	 * Argument is in N@OP format. N is size of the argument and OP is
> +	 * the actual assembly operand. N can be omitted; in that case
> +	 * argument is just OP(without @).
> +	 */
>  	tmp = strchr(desc, '@');
>  	if (tmp) {
> -		long type_idx;
> -		/*
> -		 * Isolate the string number and convert it into a
> -		 * binary value; this will be an index to get suffix
> -		 * of the uprobe name (defining the type)
> -		 */
>  		tmp[0] = '\0';
> -		type_idx = strtol(desc, NULL, 10);
> -		/* Check that the conversion went OK */
> -		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
> -			pr_debug4("Failed to parse sdt type\n");
> -			goto error;
> -		}
> -		/* Check that the converted value is OK */
> -		if (type_idx < -8 || type_idx > 8) {
> -			pr_debug4("Failed to get a valid sdt type\n");
> -			goto error;
> -		}
> -		suffix = type_to_suffix[type_idx + 8];
> -		/* Get rid of the sdt prefix which is now useless */
>  		tmp++;
> -		memmove(desc, tmp, strlen(tmp) + 1);
> -	}
>  
> -	/*
> -	 * The uprobe tracer format does not support all the
> -	 * addressing modes (notably: in x86 the scaled mode); so, we
> -	 * detect ',' characters, if there is just one, there is no
> -	 * use converting the sdt arg into a uprobe one.
> -	 */
> -	if (strchr(desc, ',')) {
> -		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> -		goto out;
> -	}
> -
> -	/*
> -	 * If the argument addressing mode is indirect, we must check
> -	 * a few things...
> -	 */
> -	tmp = strchr(desc, '(');
> -	if (tmp) {
> -		int j;
> -
> -		/*
> -		 * ...if the addressing mode is indirect with a
> -		 * positive offset (ex.: "1608(%ax)"), we need to add
> -		 * a '+' prefix so as to be compliant with uprobe
> -		 * format.
> -		 */
> -		if (desc[0] != '+' && desc[0] != '-')
> -			prefix = "+";
> -
> -		/*
> -		 * ...or if the addressing mode is indirect with a symbol
> -		 * as offset, the argument will not be supported by
> -		 * the uprobe tracer format; so, let's skip this one.
> -		 */
> -		for (j = 0; j < tmp - desc; j++) {
> -			if (desc[j] != '+' && desc[j] != '-' &&
> -				!isdigit(desc[j])) {
> -				pr_debug4("Skipping unsupported SDT argument; "
> -					"%s\n", desc);
> -				goto out;
> -			}
> -		}
> -	}
> -
> -	/*
> -	 * The uprobe tracer format does not support constants; if we
> -	 * find one in the current argument, let's skip the argument.
> -	 */
> -	if (strchr(desc, '$')) {
> -		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
> -		goto out;
> -	}
> -
> -	/*
> -	 * The uprobe parser does not support all gas register names;
> -	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
> -	 * the loop below looks for the register names (starting with
> -	 * a '%' and tries to perform the needed renamings.
> -	 */
> -	tmp = strchr(desc, '%');
> -	while (tmp) {
> -		size_t offset = tmp - desc;
> -
> -		ret = sdt_rename_register(&desc, desc + offset);
> -		if (ret < 0)
> +		if (sdt_probe_parse_n(desc, &suffix))
>  			goto error;
> -
> -		/*
> -		 * The desc pointer might have changed; so, let's not
> -		 * try to reuse tmp for next lookup
> -		 */
> -		tmp = strchr(desc + offset + 1, '%');
> +		memmove(desc, tmp, strlen(tmp) + 1);
>  	}
>  
> -	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
> +	ret = arch_sdt_probe_parse_op(&desc, &prefix);
> +	if (ret < 0)
> +		goto error;
> +
> +	if (ret == 0 &&
> +	    strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
>  		goto error;
>  
> -out:
>  	ret = 0;
>  error:
>  	free(desc);
> @@ -829,7 +768,7 @@ static char *synthesize_sdt_probe_command(struct sdt_note *note,
>  				sdt_note__get_addr(note)) < 0)
>  		goto error;
>  
> -	if (!note->args)
> +	if (!note->args || !arch_sdt_probe_arg_supp())
>  		goto out;
>  
>  	if (note->args) {
> -- 
> 2.9.3
> 


-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-03-21 14:10                       ` Arnaldo Carvalho de Melo
@ 2017-03-21 23:00                         ` Masami Hiramatsu
  2017-03-22 11:22                           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 77+ messages in thread
From: Masami Hiramatsu @ 2017-03-21 23:00 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: Ravi Bangoria, Masami Hiramatsu, alexis.berlemont, linux-kernel,
	peterz, mingo, alexander.shishkin, mpe, naveen.n.rao, maddy

On Tue, 21 Mar 2017 11:10:49 -0300
Arnaldo Carvalho de Melo <acme@redhat.com> wrote:

> Em Tue, Feb 07, 2017 at 10:52:17AM +0530, Ravi Bangoria escreveu:
> > Thanks Masami for the review.
> > 
> > On Tuesday 07 February 2017 08:41 AM, Masami Hiramatsu wrote:
> > > On Thu,  2 Feb 2017 16:41:41 +0530
> > > Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> > >
> > >> SDT marker argument is in N@OP format. N is the size of argument and
> > >> OP is the actual assembly operand. OP is arch dependent component and
> > >> hence it's parsing logic also should be placed under tools/perf/arch/.
> > >>
> > > Ok, I have one question. Is there any possibility that N is different
> > > size of OP? e.g. 8@dil, in this case we will record whole rdi.
> > > is that OK?
> > 
> > By looking at list of markers on my x86 Fedora25 box, yes, it's possible
> > for case when register size used in OP is more than size specified by N.
> > For example, -4@68(%rbx). But I don't see any argument which specifies
> > higher size in N compared to size of register in OP, like you mentioned
> > in your example.
> 
> Masami, can I have your Acked-by for 3-5/5 in this series?

Arnaldo, as I reviewed, this patch still have some discussion points.
Others are good to me.

Thanks!

-- 
Masami Hiramatsu <mhiramat@kernel.org>

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

* Re: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/
  2017-03-21 23:00                         ` Masami Hiramatsu
@ 2017-03-22 11:22                           ` Arnaldo Carvalho de Melo
  0 siblings, 0 replies; 77+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-03-22 11:22 UTC (permalink / raw)
  To: Masami Hiramatsu
  Cc: Ravi Bangoria, alexis.berlemont, linux-kernel, peterz, mingo,
	alexander.shishkin, mpe, naveen.n.rao, maddy

Em Wed, Mar 22, 2017 at 08:00:18AM +0900, Masami Hiramatsu escreveu:
> On Tue, 21 Mar 2017 11:10:49 -0300
> Arnaldo Carvalho de Melo <acme@redhat.com> wrote:
> 
> > Em Tue, Feb 07, 2017 at 10:52:17AM +0530, Ravi Bangoria escreveu:
> > > Thanks Masami for the review.
> > > 
> > > On Tuesday 07 February 2017 08:41 AM, Masami Hiramatsu wrote:
> > > > On Thu,  2 Feb 2017 16:41:41 +0530
> > > > Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com> wrote:
> > > >
> > > >> SDT marker argument is in N@OP format. N is the size of argument and
> > > >> OP is the actual assembly operand. OP is arch dependent component and
> > > >> hence it's parsing logic also should be placed under tools/perf/arch/.
> > > >>
> > > > Ok, I have one question. Is there any possibility that N is different
> > > > size of OP? e.g. 8@dil, in this case we will record whole rdi.
> > > > is that OK?
> > > 
> > > By looking at list of markers on my x86 Fedora25 box, yes, it's possible
> > > for case when register size used in OP is more than size specified by N.
> > > For example, -4@68(%rbx). But I don't see any argument which specifies
> > > higher size in N compared to size of register in OP, like you mentioned
> > > in your example.
> > 
> > Masami, can I have your Acked-by for 3-5/5 in this series?
> 
> Arnaldo, as I reviewed, this patch still have some discussion points.
> Others are good to me.

That is ok, waiting for the next steps then.

Thanks for the update,

- Arnaldo

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

* [tip:perf/core] perf probe: Change MAX_CMDLEN
  2017-02-07  5:45                     ` [PATCH v2] " Ravi Bangoria
  2017-03-21  5:19                       ` Masami Hiramatsu
@ 2017-03-24 18:43                       ` tip-bot for Ravi Bangoria
  1 sibling, 0 replies; 77+ messages in thread
From: tip-bot for Ravi Bangoria @ 2017-03-24 18:43 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: naveen.n.rao, hpa, acme, mpe, maddy, mhiramat, alexis.berlemont,
	ravi.bangoria, peterz, tglx, linux-kernel, mingo,
	alexander.shishkin

Commit-ID:  2e1f8f7895731a8592d483a7364a23855843af17
Gitweb:     http://git.kernel.org/tip/2e1f8f7895731a8592d483a7364a23855843af17
Author:     Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
AuthorDate: Tue, 7 Feb 2017 11:15:47 +0530
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Mar 2017 10:34:59 -0300

perf probe: Change MAX_CMDLEN

There are many SDT markers in powerpc whose uprobe definition goes
beyond current MAX_CMDLEN, especially when target filename is long and
sdt marker has long list of arguments. For example, definition of sdt
marker

  method__compile__end: 8@17 8@9 8@10 -4@8 8@7 -4@6 8@5 -4@4 1@37(28)

from file

  /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so

is

  p:sdt_hotspot/method__compile__end /usr/lib/jvm/java-1.8.0-openjdk-\
    1.8.0.91-2.b14.fc22.ppc64/jre/lib/ppc64/server/libjvm.so:0x4c4e00\
    arg1=%gpr17:u64 arg2=%gpr9:u64 arg3=%gpr10:u64 arg4=%gpr8:s32\
    arg5=%gpr7:u64 arg6=%gpr6:s32 arg7=%gpr5:u64 arg8=%gpr4:s32\
    arg9=+37(%gpr28):u8

'perf probe' fails with segfault for such markers. As the uprobe_events
file accepts definitions up to 4094 characters(4096 - 2 (\n\0)),
increase value of MAX_CMDLEN match that.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexis Berlemont <alexis.berlemont@gmail.com>
Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170207054547.3690-1-ravi.bangoria@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/probe-event.c | 1 -
 tools/perf/util/probe-file.c  | 3 ++-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6740d68..e4b8894 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -47,7 +47,6 @@
 #include "probe-file.h"
 #include "session.h"
 
-#define MAX_CMDLEN 256
 #define PERFPROBE_GROUP "probe"
 
 bool probe_event_dry_run;	/* Dry run flag */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 1542cd0..c3c2871 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -28,7 +28,8 @@
 #include "probe-file.h"
 #include "session.h"
 
-#define MAX_CMDLEN 256
+/* 4096 - 2 ('\n' + '\0') */
+#define MAX_CMDLEN 4094
 
 static void print_open_warning(int err, bool uprobe)
 {

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

* [tip:perf/core] perf sdt: Add scanning of sdt probes arguments
  2016-12-14  0:07             ` [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
  2017-03-06 13:39               ` Masami Hiramatsu
@ 2017-03-24 18:44               ` tip-bot for Alexis Berlemont
  1 sibling, 0 replies; 77+ messages in thread
From: tip-bot for Alexis Berlemont @ 2017-03-24 18:44 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, acme, mhiramat, peterz, ravi.bangoria,
	alexis.berlemont, hpa, mingo, alexander.shishkin, hemant, tglx

Commit-ID:  be88184b1c7054719296387c6063748fb48fa645
Gitweb:     http://git.kernel.org/tip/be88184b1c7054719296387c6063748fb48fa645
Author:     Alexis Berlemont <alexis.berlemont@gmail.com>
AuthorDate: Wed, 14 Dec 2016 01:07:31 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Mar 2017 10:56:28 -0300

perf sdt: Add scanning of sdt probes arguments

During a "perf buildid-cache --add" command, the section ".note.stapsdt"
of the "added" binary is scanned in order to list the available SDT
markers available in a binary. The parts containing the probes arguments
were left unscanned.

The whole section is now parsed; the probe arguments are extracted for
later use.

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20161214000732.1710-2-alexis.berlemont@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/util/symbol-elf.c | 25 +++++++++++++++++++++++--
 tools/perf/util/symbol.h     |  1 +
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 4e59dde..0e660db 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1828,7 +1828,7 @@ void kcore_extract__delete(struct kcore_extract *kce)
 static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 			     struct list_head *sdt_notes)
 {
-	const char *provider, *name;
+	const char *provider, *name, *args;
 	struct sdt_note *tmp = NULL;
 	GElf_Ehdr ehdr;
 	GElf_Addr base_off = 0;
@@ -1887,6 +1887,25 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 		goto out_free_prov;
 	}
 
+	args = memchr(name, '\0', data + len - name);
+
+	/*
+	 * There is no argument if:
+	 * - We reached the end of the note;
+	 * - There is not enough room to hold a potential string;
+	 * - The argument string is empty or just contains ':'.
+	 */
+	if (args == NULL || data + len - args < 2 ||
+		args[1] == ':' || args[1] == '\0')
+		tmp->args = NULL;
+	else {
+		tmp->args = strdup(++args);
+		if (!tmp->args) {
+			ret = -ENOMEM;
+			goto out_free_name;
+		}
+	}
+
 	if (gelf_getclass(*elf) == ELFCLASS32) {
 		memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
 		tmp->bit32 = true;
@@ -1898,7 +1917,7 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 	if (!gelf_getehdr(*elf, &ehdr)) {
 		pr_debug("%s : cannot get elf header.\n", __func__);
 		ret = -EBADF;
-		goto out_free_name;
+		goto out_free_args;
 	}
 
 	/* Adjust the prelink effect :
@@ -1923,6 +1942,8 @@ static int populate_sdt_note(Elf **elf, const char *data, size_t len,
 	list_add_tail(&tmp->note_list, sdt_notes);
 	return 0;
 
+out_free_args:
+	free(tmp->args);
 out_free_name:
 	free(tmp->name);
 out_free_prov:
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 6c358b7..9222c7e 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -351,6 +351,7 @@ int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 struct sdt_note {
 	char *name;			/* name of the note*/
 	char *provider;			/* provider name */
+	char *args;
 	bool bit32;			/* whether the location is 32 bits? */
 	union {				/* location, base and semaphore addrs */
 		Elf64_Addr a64[3];

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

* [tip:perf/core] perf probe: Add sdt probes arguments into the uprobe cmd string
  2016-12-14  0:07             ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
  2017-01-24  8:50               ` Ravi Bangoria
  2017-03-06 17:23               ` Masami Hiramatsu
@ 2017-03-24 18:44               ` tip-bot for Alexis Berlemont
  2 siblings, 0 replies; 77+ messages in thread
From: tip-bot for Alexis Berlemont @ 2017-03-24 18:44 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexis.berlemont, linux-kernel, ravi.bangoria, tglx, mingo,
	hemant, mhiramat, alexander.shishkin, peterz, hpa, acme

Commit-ID:  3b1f8311f6963cd11a7d1efbcd2fd900d472ba5c
Gitweb:     http://git.kernel.org/tip/3b1f8311f6963cd11a7d1efbcd2fd900d472ba5c
Author:     Alexis Berlemont <alexis.berlemont@gmail.com>
AuthorDate: Wed, 14 Dec 2016 01:07:32 +0100
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Mar 2017 10:59:01 -0300

perf probe: Add sdt probes arguments into the uprobe cmd string

An sdt probe can be associated with arguments but they were not passed
to the user probe tracing interface (uprobe_events); this patch adapts
the sdt argument descriptors according to the uprobe input format.

As the uprobe parser does not support scaled address mode, perf will
skip arguments which cannot be adapted to the uprobe format.

Here are the results:

  $ perf buildid-cache -v --add test_sdt
  $ perf probe -x test_sdt sdt_libfoo:table_frob
  $ perf probe -x test_sdt sdt_libfoo:table_diddle
  $ perf record -e sdt_libfoo:table_frob -e sdt_libfoo:table_diddle test_sdt
  $ perf script
  test_sdt  ...   666.255678:   sdt_libfoo:table_frob: (4004d7) arg0=0 arg1=0
  test_sdt  ...   666.255683: sdt_libfoo:table_diddle: (40051a) arg0=0 arg1=0
  test_sdt  ...   666.255686:   sdt_libfoo:table_frob: (4004d7) arg0=1 arg1=2
  test_sdt  ...   666.255689: sdt_libfoo:table_diddle: (40051a) arg0=3 arg1=4
  test_sdt  ...   666.255692:   sdt_libfoo:table_frob: (4004d7) arg0=2 arg1=4
  test_sdt  ...   666.255694: sdt_libfoo:table_diddle: (40051a) arg0=6 arg1=8

Signed-off-by: Alexis Berlemont <alexis.berlemont@gmail.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Hemant Kumar <hemant@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Link: http://lkml.kernel.org/r/20161214000732.1710-3-alexis.berlemont@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/x86/util/perf_regs.c |  83 +++++++++++++++++
 tools/perf/util/perf_regs.c          |   6 ++
 tools/perf/util/perf_regs.h          |   6 ++
 tools/perf/util/probe-file.c         | 170 ++++++++++++++++++++++++++++++++++-
 4 files changed, 261 insertions(+), 4 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index c5db14f..09a7f55 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -1,4 +1,7 @@
+#include <string.h>
+
 #include "../../perf.h"
+#include "../../util/util.h"
 #include "../../util/perf_regs.h"
 
 const struct sample_reg sample_reg_masks[] = {
@@ -26,3 +29,83 @@ const struct sample_reg sample_reg_masks[] = {
 #endif
 	SMPL_REG_END
 };
+
+struct sdt_name_reg {
+	const char *sdt_name;
+	const char *uprobe_name;
+};
+#define SDT_NAME_REG(n, m) {.sdt_name = "%" #n, .uprobe_name = "%" #m}
+#define SDT_NAME_REG_END {.sdt_name = NULL, .uprobe_name = NULL}
+
+static const struct sdt_name_reg sdt_reg_renamings[] = {
+	SDT_NAME_REG(eax, ax),
+	SDT_NAME_REG(rax, ax),
+	SDT_NAME_REG(ebx, bx),
+	SDT_NAME_REG(rbx, bx),
+	SDT_NAME_REG(ecx, cx),
+	SDT_NAME_REG(rcx, cx),
+	SDT_NAME_REG(edx, dx),
+	SDT_NAME_REG(rdx, dx),
+	SDT_NAME_REG(esi, si),
+	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(edi, di),
+	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(ebp, bp),
+	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG_END,
+};
+
+int sdt_rename_register(char **pdesc, char *old_name)
+{
+	const struct sdt_name_reg *rnames = sdt_reg_renamings;
+	char *new_desc, *old_desc = *pdesc;
+	size_t prefix_len, sdt_len, uprobe_len, old_desc_len, offset;
+	int ret = -1;
+
+	while (ret != 0 && rnames->sdt_name != NULL) {
+		sdt_len = strlen(rnames->sdt_name);
+		ret = strncmp(old_name, rnames->sdt_name, sdt_len);
+		rnames += !!ret;
+	}
+
+	if (rnames->sdt_name == NULL)
+		return 0;
+
+	sdt_len = strlen(rnames->sdt_name);
+	uprobe_len = strlen(rnames->uprobe_name);
+	old_desc_len = strlen(old_desc) + 1;
+
+	new_desc = zalloc(old_desc_len + uprobe_len - sdt_len);
+	if (new_desc == NULL)
+		return -1;
+
+	/* Copy the chars before the register name (at least '%') */
+	prefix_len = old_name - old_desc;
+	memcpy(new_desc, old_desc, prefix_len);
+
+	/* Copy the new register name */
+	memcpy(new_desc + prefix_len, rnames->uprobe_name, uprobe_len);
+
+	/* Copy the chars after the register name (if need be) */
+	offset = prefix_len + sdt_len;
+	if (offset < old_desc_len) {
+		/*
+		 * The orginal register name can be suffixed by 'b',
+		 * 'w' or 'd' to indicate its size; so, we need to
+		 * skip this char if we met one.
+		 */
+		char sfx = old_desc[offset];
+
+		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
+			offset++;
+	}
+
+	if (offset < old_desc_len)
+		memcpy(new_desc + prefix_len + uprobe_len,
+			old_desc + offset, old_desc_len - offset);
+
+	free(old_desc);
+	*pdesc = new_desc;
+
+	return 0;
+}
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index c4023f2..a37e593 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -6,6 +6,12 @@ const struct sample_reg __weak sample_reg_masks[] = {
 	SMPL_REG_END
 };
 
+int __weak sdt_rename_register(char **pdesc __maybe_unused,
+			char *old_name __maybe_unused)
+{
+	return 0;
+}
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
 {
diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h
index 679d6e4..7544a15 100644
--- a/tools/perf/util/perf_regs.h
+++ b/tools/perf/util/perf_regs.h
@@ -15,6 +15,12 @@ struct sample_reg {
 
 extern const struct sample_reg sample_reg_masks[];
 
+/*
+ * The table sdt_reg_renamings is used for adjusting gcc/gas-generated
+ * registers before filling the uprobe tracer interface.
+ */
+int sdt_rename_register(char **pdesc, char *old_name);
+
 #ifdef HAVE_PERF_REGS_SUPPORT
 #include <perf_regs.h>
 
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index c3c2871..d741634 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -27,6 +27,7 @@
 #include "probe-event.h"
 #include "probe-file.h"
 #include "session.h"
+#include "perf_regs.h"
 
 /* 4096 - 2 ('\n' + '\0') */
 #define MAX_CMDLEN 4094
@@ -688,6 +689,166 @@ static unsigned long long sdt_note__get_addr(struct sdt_note *note)
 		 : (unsigned long long)note->addr.a64[0];
 }
 
+static const char * const type_to_suffix[] = {
+	":s64", "", "", "", ":s32", "", ":s16", ":s8",
+	"", ":u8", ":u16", "", ":u32", "", "", "", ":u64"
+};
+
+static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg)
+{
+	char *tmp, *desc = strdup(arg);
+	const char *prefix = "", *suffix = "";
+	int ret = -1;
+
+	if (desc == NULL) {
+		pr_debug4("Allocation error\n");
+		return ret;
+	}
+
+	tmp = strchr(desc, '@');
+	if (tmp) {
+		long type_idx;
+		/*
+		 * Isolate the string number and convert it into a
+		 * binary value; this will be an index to get suffix
+		 * of the uprobe name (defining the type)
+		 */
+		tmp[0] = '\0';
+		type_idx = strtol(desc, NULL, 10);
+		/* Check that the conversion went OK */
+		if (type_idx == LONG_MIN || type_idx == LONG_MAX) {
+			pr_debug4("Failed to parse sdt type\n");
+			goto error;
+		}
+		/* Check that the converted value is OK */
+		if (type_idx < -8 || type_idx > 8) {
+			pr_debug4("Failed to get a valid sdt type\n");
+			goto error;
+		}
+		suffix = type_to_suffix[type_idx + 8];
+		/* Get rid of the sdt prefix which is now useless */
+		tmp++;
+		memmove(desc, tmp, strlen(tmp) + 1);
+	}
+
+	/*
+	 * The uprobe tracer format does not support all the
+	 * addressing modes (notably: in x86 the scaled mode); so, we
+	 * detect ',' characters, if there is just one, there is no
+	 * use converting the sdt arg into a uprobe one.
+	 */
+	if (strchr(desc, ',')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
+		goto out;
+	}
+
+	/*
+	 * If the argument addressing mode is indirect, we must check
+	 * a few things...
+	 */
+	tmp = strchr(desc, '(');
+	if (tmp) {
+		int j;
+
+		/*
+		 * ...if the addressing mode is indirect with a
+		 * positive offset (ex.: "1608(%ax)"), we need to add
+		 * a '+' prefix so as to be compliant with uprobe
+		 * format.
+		 */
+		if (desc[0] != '+' && desc[0] != '-')
+			prefix = "+";
+
+		/*
+		 * ...or if the addressing mode is indirect with a symbol
+		 * as offset, the argument will not be supported by
+		 * the uprobe tracer format; so, let's skip this one.
+		 */
+		for (j = 0; j < tmp - desc; j++) {
+			if (desc[j] != '+' && desc[j] != '-' &&
+				!isdigit(desc[j])) {
+				pr_debug4("Skipping unsupported SDT argument; "
+					"%s\n", desc);
+				goto out;
+			}
+		}
+	}
+
+	/*
+	 * The uprobe tracer format does not support constants; if we
+	 * find one in the current argument, let's skip the argument.
+	 */
+	if (strchr(desc, '$')) {
+		pr_debug4("Skipping unsupported SDT argument; %s\n", desc);
+		goto out;
+	}
+
+	/*
+	 * The uprobe parser does not support all gas register names;
+	 * so, we have to replace them (ex. for x86_64: %rax -> %ax);
+	 * the loop below looks for the register names (starting with
+	 * a '%' and tries to perform the needed renamings.
+	 */
+	tmp = strchr(desc, '%');
+	while (tmp) {
+		size_t offset = tmp - desc;
+
+		ret = sdt_rename_register(&desc, desc + offset);
+		if (ret < 0)
+			goto error;
+
+		/*
+		 * The desc pointer might have changed; so, let's not
+		 * try to reuse tmp for next lookup
+		 */
+		tmp = strchr(desc + offset + 1, '%');
+	}
+
+	if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0)
+		goto error;
+
+out:
+	ret = 0;
+error:
+	free(desc);
+	return ret;
+}
+
+static char *synthesize_sdt_probe_command(struct sdt_note *note,
+					const char *pathname,
+					const char *sdtgrp)
+{
+	struct strbuf buf;
+	char *ret = NULL, **args;
+	int i, args_count;
+
+	if (strbuf_init(&buf, 32) < 0)
+		return NULL;
+
+	if (strbuf_addf(&buf, "p:%s/%s %s:0x%llx",
+				sdtgrp, note->name, pathname,
+				sdt_note__get_addr(note)) < 0)
+		goto error;
+
+	if (!note->args)
+		goto out;
+
+	if (note->args) {
+		args = argv_split(note->args, &args_count);
+
+		for (i = 0; i < args_count; ++i) {
+			if (synthesize_sdt_probe_arg(&buf, i, args[i]) < 0)
+				goto error;
+		}
+	}
+
+out:
+	ret = strbuf_detach(&buf, NULL);
+error:
+	strbuf_release(&buf);
+	return ret;
+}
+
 int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 {
 	struct probe_cache_entry *entry = NULL;
@@ -724,11 +885,12 @@ int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
 			entry->pev.group = strdup(sdtgrp);
 			list_add_tail(&entry->node, &pcache->entries);
 		}
-		ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
-				sdtgrp, note->name, pathname,
-				sdt_note__get_addr(note));
-		if (ret < 0)
+		buf = synthesize_sdt_probe_command(note, pathname, sdtgrp);
+		if (!buf) {
+			ret = -ENOMEM;
 			break;
+		}
+
 		strlist__add(entry->tevlist, buf);
 		free(buf);
 		entry = NULL;

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

* [tip:perf/core] perf sdt x86: Add renaming logic for rNN and other registers
  2017-02-02 11:11                 ` [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers Ravi Bangoria
  2017-02-07  3:11                   ` Masami Hiramatsu
@ 2017-03-24 18:45                   ` tip-bot for Ravi Bangoria
  1 sibling, 0 replies; 77+ messages in thread
From: tip-bot for Ravi Bangoria @ 2017-03-24 18:45 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: alexis.berlemont, peterz, mpe, alexander.shishkin, acme,
	linux-kernel, hpa, mingo, tglx, maddy, naveen.n.rao,
	ravi.bangoria, mhiramat

Commit-ID:  8544d24c3204f94c0ba9788d3113b7a83d5edc0d
Gitweb:     http://git.kernel.org/tip/8544d24c3204f94c0ba9788d3113b7a83d5edc0d
Author:     Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
AuthorDate: Thu, 2 Feb 2017 16:41:40 +0530
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Tue, 21 Mar 2017 11:07:17 -0300

perf sdt x86: Add renaming logic for rNN and other registers

'perf probe' is failing for sdt markers whose arguments has rNN (with
postfix b/w/d), %rsp, %esp, %sil etc. registers. Add renaming logic for
these registers.

Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Acked-by: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexis Berlemont <alexis.berlemont@gmail.com>
Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/20170202111143.14319-3-ravi.bangoria@linux.vnet.ibm.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/perf/arch/x86/util/perf_regs.c | 44 ++++++++++++++++++++++++++----------
 1 file changed, 32 insertions(+), 12 deletions(-)

diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c
index 09a7f55..d8a8dcf 100644
--- a/tools/perf/arch/x86/util/perf_regs.c
+++ b/tools/perf/arch/x86/util/perf_regs.c
@@ -48,10 +48,42 @@ static const struct sdt_name_reg sdt_reg_renamings[] = {
 	SDT_NAME_REG(rdx, dx),
 	SDT_NAME_REG(esi, si),
 	SDT_NAME_REG(rsi, si),
+	SDT_NAME_REG(sil, si),
 	SDT_NAME_REG(edi, di),
 	SDT_NAME_REG(rdi, di),
+	SDT_NAME_REG(dil, di),
 	SDT_NAME_REG(ebp, bp),
 	SDT_NAME_REG(rbp, bp),
+	SDT_NAME_REG(bpl, bp),
+	SDT_NAME_REG(rsp, sp),
+	SDT_NAME_REG(esp, sp),
+	SDT_NAME_REG(spl, sp),
+
+	/* rNN registers */
+	SDT_NAME_REG(r8b,  r8),
+	SDT_NAME_REG(r8w,  r8),
+	SDT_NAME_REG(r8d,  r8),
+	SDT_NAME_REG(r9b,  r9),
+	SDT_NAME_REG(r9w,  r9),
+	SDT_NAME_REG(r9d,  r9),
+	SDT_NAME_REG(r10b, r10),
+	SDT_NAME_REG(r10w, r10),
+	SDT_NAME_REG(r10d, r10),
+	SDT_NAME_REG(r11b, r11),
+	SDT_NAME_REG(r11w, r11),
+	SDT_NAME_REG(r11d, r11),
+	SDT_NAME_REG(r12b, r12),
+	SDT_NAME_REG(r12w, r12),
+	SDT_NAME_REG(r12d, r12),
+	SDT_NAME_REG(r13b, r13),
+	SDT_NAME_REG(r13w, r13),
+	SDT_NAME_REG(r13d, r13),
+	SDT_NAME_REG(r14b, r14),
+	SDT_NAME_REG(r14w, r14),
+	SDT_NAME_REG(r14d, r14),
+	SDT_NAME_REG(r15b, r15),
+	SDT_NAME_REG(r15w, r15),
+	SDT_NAME_REG(r15d, r15),
 	SDT_NAME_REG_END,
 };
 
@@ -88,18 +120,6 @@ int sdt_rename_register(char **pdesc, char *old_name)
 
 	/* Copy the chars after the register name (if need be) */
 	offset = prefix_len + sdt_len;
-	if (offset < old_desc_len) {
-		/*
-		 * The orginal register name can be suffixed by 'b',
-		 * 'w' or 'd' to indicate its size; so, we need to
-		 * skip this char if we met one.
-		 */
-		char sfx = old_desc[offset];
-
-		if (sfx == 'b' || sfx == 'w'  || sfx == 'd')
-			offset++;
-	}
-
 	if (offset < old_desc_len)
 		memcpy(new_desc + prefix_len + uprobe_len,
 			old_desc + offset, old_desc_len - offset);

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

end of thread, other threads:[~2017-03-24 18:52 UTC | newest]

Thread overview: 77+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-11-16 23:55 [PATCH 0/2] perf: add support of SDT probes arguments Alexis Berlemont
2016-11-16 23:56 ` [PATCH 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-11-16 23:56 ` [PATCH 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2016-11-17  9:04   ` Hemant Kumar
2016-11-18 23:56     ` [PATCH v2 0/2] " Alexis Berlemont
2016-11-18 23:56     ` [PATCH v2 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-11-25 14:40       ` Arnaldo Carvalho de Melo
2016-11-26  0:58         ` [PATCH v4 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2016-12-05 23:42           ` Alexis Berlemont
2016-12-06 14:45             ` Arnaldo Carvalho de Melo
2016-11-26  0:58         ` [PATCH v4 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-12-07  2:44           ` Masami Hiramatsu
2016-11-26  0:58         ` [PATCH v4 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2016-12-07  3:26           ` Masami Hiramatsu
2016-12-09 15:14             ` Arnaldo Carvalho de Melo
2016-12-10 10:00               ` Masami Hiramatsu
2016-12-14  0:07             ` [PATCH v5 0/2] " Alexis Berlemont
2016-12-14  7:36               ` Ingo Molnar
2017-01-23 11:23                 ` Ravi Bangoria
2017-02-22 22:41                   ` Alexis Berlemont
2017-01-24  6:58                 ` Ravi Bangoria
2017-01-24  8:22                   ` Ingo Molnar
2017-01-24  8:36                     ` Ravi Bangoria
2017-02-02 11:11               ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 1/5] perf/sdt: Show proper hint Ravi Bangoria
2017-02-02 13:40                   ` Ingo Molnar
2017-02-02 16:20                     ` Arnaldo Carvalho de Melo
2017-02-03 10:26                       ` [PATCH v2] " Ravi Bangoria
2017-02-03 15:18                         ` Arnaldo Carvalho de Melo
2017-02-07  7:53                           ` Ingo Molnar
2017-02-07 15:50                             ` Arnaldo Carvalho de Melo
2017-02-07  8:00                           ` Ingo Molnar
2017-02-16 10:16                           ` [RFC] perf/sdt: Directly record SDT event with 'perf record' Ravi Bangoria
2017-02-20  7:08                             ` Ingo Molnar
2017-02-20  8:21                               ` Ravi Bangoria
2017-02-20  8:42                                 ` Ingo Molnar
2017-02-20 11:01                                   ` Ravi Bangoria
2017-02-20 14:11                                     ` Arnaldo Carvalho de Melo
2017-02-23  8:13                                       ` Ravi Bangoria
2017-02-23 12:48                                         ` Arnaldo Carvalho de Melo
2017-02-07  1:13                         ` [PATCH v2] perf/sdt: Show proper hint Masami Hiramatsu
2017-02-10  7:44                         ` [tip:perf/core] perf sdt: Show proper hint when event not yet in place via 'perf probe' tip-bot for Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 2/5] perf/sdt/x86: Add renaming logic for rNN and other registers Ravi Bangoria
2017-02-07  3:11                   ` Masami Hiramatsu
2017-03-21 14:08                     ` Arnaldo Carvalho de Melo
2017-03-24 18:45                   ` [tip:perf/core] perf sdt x86: " tip-bot for Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Ravi Bangoria
2017-02-07  3:11                   ` Masami Hiramatsu
2017-02-07  5:22                     ` Ravi Bangoria
2017-03-21 14:10                       ` Arnaldo Carvalho de Melo
2017-03-21 23:00                         ` Masami Hiramatsu
2017-03-22 11:22                           ` Arnaldo Carvalho de Melo
2017-03-21 14:55                   ` Masami Hiramatsu
2017-02-02 11:11                 ` [PATCH 4/5] perf/sdt/powerpc: Add argument support Ravi Bangoria
2017-02-02 11:11                 ` [PATCH 5/5] perf/probe: Change MAX_CMDLEN Ravi Bangoria
2017-02-07  1:40                   ` Masami Hiramatsu
2017-02-07  5:45                     ` [PATCH v2] " Ravi Bangoria
2017-03-21  5:19                       ` Masami Hiramatsu
2017-03-21 13:37                         ` Arnaldo Carvalho de Melo
2017-03-24 18:43                       ` [tip:perf/core] perf probe: " tip-bot for Ravi Bangoria
2017-02-07  2:55                 ` [PATCH 0/5] perf/sdt: Argument support for x86 and powepc Masami Hiramatsu
2017-03-06  7:53                   ` Ravi Bangoria
2017-03-06 13:42                     ` Masami Hiramatsu
2017-03-21  5:08               ` [PATCH v5 0/2] perf probe: add sdt probes arguments into the uprobe cmd string Masami Hiramatsu
2016-12-14  0:07             ` [PATCH v5 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2017-03-06 13:39               ` Masami Hiramatsu
2017-03-21 13:52                 ` Arnaldo Carvalho de Melo
2017-03-24 18:44               ` [tip:perf/core] perf sdt: Add scanning of sdt probes arguments tip-bot for Alexis Berlemont
2016-12-14  0:07             ` [PATCH v5 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont
2017-01-24  8:50               ` Ravi Bangoria
2017-03-06 17:23               ` Masami Hiramatsu
2017-03-24 18:44               ` [tip:perf/core] perf probe: Add " tip-bot for Alexis Berlemont
2016-11-18 23:56     ` [PATCH v2 2/2] perf probe: add " Alexis Berlemont
2016-11-21 10:25       ` Hemant Kumar
2016-11-24 23:13         ` [PATCH v3 0/2] " Alexis Berlemont
2016-11-24 23:13         ` [PATCH v3 1/2] perf sdt: add scanning of sdt probles arguments Alexis Berlemont
2016-11-24 23:13         ` [PATCH v3 2/2] perf probe: add sdt probes arguments into the uprobe cmd string Alexis Berlemont

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.