Re: [PATCH perf/core v13 04/15] perf/sdt: ELF support for SDT

2016-07-03 Thread Masami Hiramatsu
On Fri, 1 Jul 2016 15:56:49 -0300
Arnaldo Carvalho de Melo  wrote:

> Em Fri, Jul 01, 2016 at 05:03:46PM +0900, Masami Hiramatsu escreveu:
> > From: Hemant Kumar 
> > 
> > This patch serves the initial support to identify and list SDT events in 
> > binaries.
> > When programs containing SDT markers are compiled, gcc with the help of 
> > assembler
> > directives identifies them and places them in the section ".note.stapsdt". 
> > To find
> > these markers from the binaries, one needs to traverse through this section 
> > and
> > parse the relevant details like the name, type and location of the marker. 
> > Also,
> > the original location could be skewed due to the effect of prelinking. If 
> > that is
> > the case, the locations need to be adjusted.
> > 
> > The functions in this patch open a given ELF, find out the SDT section, 
> > parse the
> > relevant details, adjust the location (if necessary) and populate them in a 
> > list.
> 
> Breaks the build on older systems:
> 
> 
> [root@jouet perf]# dm
> centos:5: FAIL
>   CC   /tmp/build/perf/util/symbol-elf.o
> cc1: warnings being treated as errors
> util/symbol-elf.c: In function 'construct_sdt_notes_list':
> util/symbol-elf.c:1927: warning: implicit declaration of function 
> 'elf_getshdrstrndx'
> util/symbol-elf.c:1927: warning: nested extern declaration of 
> 'elf_getshdrstrndx'
> mv: cannot stat `/tmp/build/perf/util/.symbol-elf.o.tmp': No such file or 
> directory
> make[3]: *** [/tmp/build/perf/util/symbol-elf.o] Error 1
> make[3]: *** Waiting for unfinished jobs
> make[2]: *** [util] Error 2
> make[1]: *** [/tmp/build/perf/libperf-in.o] Error 2
> make: *** [install-bin] Error 2
> make: Leaving directory `/git/linux/tools/perf'
> centos:6: Ok
> centos:7: Ok
> debian:experimental: Ok
> debian:7: Ok
> debian:8: Ok
> fedora:21: Ok
> fedora:22: Ok
> fedora:23: Ok
> fedora:24: Ok
> opensuse:13.2: Ok
> opensuse:42.1: Ok
> ubuntu:14.04.4: Ok
> ubuntu:15.10: Ok
> ubuntu:16.04: Ok
> ubuntu:12.04.5: Ok
> 
> -

OK, that API is newer one. We have to check wheter it is supported by libelf.

> 
> Needs a feature detection test, I will try to contribute that.

Thanks!

> 
> - Arnaldo
> 
>  
> > A typical note entry in ".note.stapsdt" section is as follows :
> > 
> > 
> >  |--nhdr.n_namesz--|
> > 
> > |  nhdr  | "stapsdt"   |
> > -   |--|
> >  |  |  |
> >  |  |   |
> > nhdr.n_descsize |  "provider_name"   "note_name"   |
> >  |  ||
> > -   |--|
> > |  nhdr  | "stapsdt"   |
> > |...
> > 
> > The above shows an excerpt from the section ".note.stapsdt".
> > 'nhdr' is a structure which has the note name size (n_namesz), note
> > description size (n_desc_sz) and note type (n_type). So, in order to
> > parse the note note info, we need nhdr to tell us where to start from.
> > As can be seen from , the name of the SDT notes given is 
> > "stapsdt".
> > But this is not the identifier of the note.
> > After that, we go to description of the note to find out its location, the
> > address of the ".stapsdt.base" section and the semaphore address.
> > Then, we find the provider name and the SDT marker name and then follow the
> > arguments.
> > 
> > Signed-off-by: Hemant Kumar 
> > Reviewed-by: Masami Hiramatsu 
> > Acked-by: Namhyung Kim 
> > ---
> >  tools/perf/util/symbol-elf.c |  252 
> > ++
> >  tools/perf/util/symbol.h |   22 
> >  2 files changed, 274 insertions(+)
> > 
> > diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> > index 87a297d..e74ce17 100644
> > --- a/tools/perf/util/symbol-elf.c
> > +++ b/tools/perf/util/symbol-elf.c
> > @@ -1781,6 +1781,258 @@ void kcore_extract__delete(struct kcore_extract 
> > *kce)
> > unlink(kce->extract_filename);
> >  }
> >  
> > +/**
> > + * populate_sdt_note : Parse raw data and identify SDT note
> > + * @elf: elf of the opened file
> > + * @data: raw data of a section with description offset applied
> > + * @len: note description size
> > + * @type: type of the note
> > + * @sdt_notes: List to add the SDT note
> > + *
> > + * Responsible for parsing the @data in section .note.stapsdt in @elf and
> > + * if its an SDT note, it appends to @sdt_notes list.
> > + */
> > +static int populate_sdt_note(Elf **elf, const char *data, size_t len,
> > +struct list_head *sdt_notes)
> > +{
> > +   const char *provider, *name;
> > +   struct sdt_note *tmp = NULL;
> > +   GElf_Ehdr ehdr;
> > +   GElf_Addr base_off = 0;
> > +   GElf_Shdr shdr;
> > +   int ret = -EINVAL;
> > +
> > +   union {
> > +   Elf64_Addr a64[NR_ADDR];
> > +   Elf32_Addr a32[NR_ADDR];
> > +   } buf;
> > +
> > +  

Re: [PATCH perf/core v13 04/15] perf/sdt: ELF support for SDT

2016-07-01 Thread Arnaldo Carvalho de Melo
Em Fri, Jul 01, 2016 at 05:03:46PM +0900, Masami Hiramatsu escreveu:
> From: Hemant Kumar 
> 
> This patch serves the initial support to identify and list SDT events in 
> binaries.
> When programs containing SDT markers are compiled, gcc with the help of 
> assembler
> directives identifies them and places them in the section ".note.stapsdt". To 
> find
> these markers from the binaries, one needs to traverse through this section 
> and
> parse the relevant details like the name, type and location of the marker. 
> Also,
> the original location could be skewed due to the effect of prelinking. If 
> that is
> the case, the locations need to be adjusted.
> 
> The functions in this patch open a given ELF, find out the SDT section, parse 
> the
> relevant details, adjust the location (if necessary) and populate them in a 
> list.

Breaks the build on older systems:


[root@jouet perf]# dm
centos:5: FAIL
  CC   /tmp/build/perf/util/symbol-elf.o
cc1: warnings being treated as errors
util/symbol-elf.c: In function 'construct_sdt_notes_list':
util/symbol-elf.c:1927: warning: implicit declaration of function 
'elf_getshdrstrndx'
util/symbol-elf.c:1927: warning: nested extern declaration of 
'elf_getshdrstrndx'
mv: cannot stat `/tmp/build/perf/util/.symbol-elf.o.tmp': No such file or 
directory
make[3]: *** [/tmp/build/perf/util/symbol-elf.o] Error 1
make[3]: *** Waiting for unfinished jobs
make[2]: *** [util] Error 2
make[1]: *** [/tmp/build/perf/libperf-in.o] Error 2
make: *** [install-bin] Error 2
make: Leaving directory `/git/linux/tools/perf'
centos:6: Ok
centos:7: Ok
debian:experimental: Ok
debian:7: Ok
debian:8: Ok
fedora:21: Ok
fedora:22: Ok
fedora:23: Ok
fedora:24: Ok
opensuse:13.2: Ok
opensuse:42.1: Ok
ubuntu:14.04.4: Ok
ubuntu:15.10: Ok
ubuntu:16.04: Ok
ubuntu:12.04.5: Ok

-

Needs a feature detection test, I will try to contribute that.

- Arnaldo

 
> A typical note entry in ".note.stapsdt" section is as follows :
> 
> 
>  |--nhdr.n_namesz--|
> 
> |  nhdr  | "stapsdt"   |
> -   |--|
>  |  |  |
>  |  |   |
> nhdr.n_descsize |  "provider_name"   "note_name"   |
>  |  ||
> -   |--|
> |  nhdr  | "stapsdt"   |
> |...
> 
> The above shows an excerpt from the section ".note.stapsdt".
> 'nhdr' is a structure which has the note name size (n_namesz), note
> description size (n_desc_sz) and note type (n_type). So, in order to
> parse the note note info, we need nhdr to tell us where to start from.
> As can be seen from , the name of the SDT notes given is "stapsdt".
> But this is not the identifier of the note.
> After that, we go to description of the note to find out its location, the
> address of the ".stapsdt.base" section and the semaphore address.
> Then, we find the provider name and the SDT marker name and then follow the
> arguments.
> 
> Signed-off-by: Hemant Kumar 
> Reviewed-by: Masami Hiramatsu 
> Acked-by: Namhyung Kim 
> ---
>  tools/perf/util/symbol-elf.c |  252 
> ++
>  tools/perf/util/symbol.h |   22 
>  2 files changed, 274 insertions(+)
> 
> diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
> index 87a297d..e74ce17 100644
> --- a/tools/perf/util/symbol-elf.c
> +++ b/tools/perf/util/symbol-elf.c
> @@ -1781,6 +1781,258 @@ void kcore_extract__delete(struct kcore_extract *kce)
>   unlink(kce->extract_filename);
>  }
>  
> +/**
> + * populate_sdt_note : Parse raw data and identify SDT note
> + * @elf: elf of the opened file
> + * @data: raw data of a section with description offset applied
> + * @len: note description size
> + * @type: type of the note
> + * @sdt_notes: List to add the SDT note
> + *
> + * Responsible for parsing the @data in section .note.stapsdt in @elf and
> + * if its an SDT note, it appends to @sdt_notes list.
> + */
> +static int populate_sdt_note(Elf **elf, const char *data, size_t len,
> +  struct list_head *sdt_notes)
> +{
> + const char *provider, *name;
> + struct sdt_note *tmp = NULL;
> + GElf_Ehdr ehdr;
> + GElf_Addr base_off = 0;
> + GElf_Shdr shdr;
> + int ret = -EINVAL;
> +
> + union {
> + Elf64_Addr a64[NR_ADDR];
> + Elf32_Addr a32[NR_ADDR];
> + } buf;
> +
> + Elf_Data dst = {
> + .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
> + .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT),
> + .d_off = 0, .d_align = 0
> + };
> + Elf_Data src = {
> + .d_buf = (void *) data, .d_type = ELF_T_ADDR,
> + .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
> + .d_alig

[PATCH perf/core v13 04/15] perf/sdt: ELF support for SDT

2016-07-01 Thread Masami Hiramatsu
From: Hemant Kumar 

This patch serves the initial support to identify and list SDT events in 
binaries.
When programs containing SDT markers are compiled, gcc with the help of 
assembler
directives identifies them and places them in the section ".note.stapsdt". To 
find
these markers from the binaries, one needs to traverse through this section and
parse the relevant details like the name, type and location of the marker. Also,
the original location could be skewed due to the effect of prelinking. If that 
is
the case, the locations need to be adjusted.

The functions in this patch open a given ELF, find out the SDT section, parse 
the
relevant details, adjust the location (if necessary) and populate them in a 
list.

A typical note entry in ".note.stapsdt" section is as follows :


 |--nhdr.n_namesz--|

|  nhdr  | "stapsdt"   |
-   |--|
 |  |  |
 |  |   |
nhdr.n_descsize |  "provider_name"   "note_name"   |
 |  ||
-   |--|
|  nhdr  | "stapsdt"   |
|...

The above shows an excerpt from the section ".note.stapsdt".
'nhdr' is a structure which has the note name size (n_namesz), note
description size (n_desc_sz) and note type (n_type). So, in order to
parse the note note info, we need nhdr to tell us where to start from.
As can be seen from , the name of the SDT notes given is "stapsdt".
But this is not the identifier of the note.
After that, we go to description of the note to find out its location, the
address of the ".stapsdt.base" section and the semaphore address.
Then, we find the provider name and the SDT marker name and then follow the
arguments.

Signed-off-by: Hemant Kumar 
Reviewed-by: Masami Hiramatsu 
Acked-by: Namhyung Kim 
---
 tools/perf/util/symbol-elf.c |  252 ++
 tools/perf/util/symbol.h |   22 
 2 files changed, 274 insertions(+)

diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 87a297d..e74ce17 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -1781,6 +1781,258 @@ void kcore_extract__delete(struct kcore_extract *kce)
unlink(kce->extract_filename);
 }
 
+/**
+ * populate_sdt_note : Parse raw data and identify SDT note
+ * @elf: elf of the opened file
+ * @data: raw data of a section with description offset applied
+ * @len: note description size
+ * @type: type of the note
+ * @sdt_notes: List to add the SDT note
+ *
+ * Responsible for parsing the @data in section .note.stapsdt in @elf and
+ * if its an SDT note, it appends to @sdt_notes list.
+ */
+static int populate_sdt_note(Elf **elf, const char *data, size_t len,
+struct list_head *sdt_notes)
+{
+   const char *provider, *name;
+   struct sdt_note *tmp = NULL;
+   GElf_Ehdr ehdr;
+   GElf_Addr base_off = 0;
+   GElf_Shdr shdr;
+   int ret = -EINVAL;
+
+   union {
+   Elf64_Addr a64[NR_ADDR];
+   Elf32_Addr a32[NR_ADDR];
+   } buf;
+
+   Elf_Data dst = {
+   .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+   .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT),
+   .d_off = 0, .d_align = 0
+   };
+   Elf_Data src = {
+   .d_buf = (void *) data, .d_type = ELF_T_ADDR,
+   .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
+   .d_align = 0
+   };
+
+   tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note));
+   if (!tmp) {
+   ret = -ENOMEM;
+   goto out_err;
+   }
+
+   INIT_LIST_HEAD(&tmp->note_list);
+
+   if (len < dst.d_size + 3)
+   goto out_free_note;
+
+   /* Translation from file representation to memory representation */
+   if (gelf_xlatetom(*elf, &dst, &src,
+ elf_getident(*elf, NULL)[EI_DATA]) == NULL) {
+   pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1));
+   goto out_free_note;
+   }
+
+   /* Populate the fields of sdt_note */
+   provider = data + dst.d_size;
+
+   name = (const char *)memchr(provider, '\0', data + len - provider);
+   if (name++ == NULL)
+   goto out_free_note;
+
+   tmp->provider = strdup(provider);
+   if (!tmp->provider) {
+   ret = -ENOMEM;
+   goto out_free_note;
+   }
+   tmp->name = strdup(name);
+   if (!tmp->name) {
+   ret = -ENOMEM;
+   goto out_free_prov;
+   }
+
+   if (gelf_getclass(*elf) == ELFCLASS32) {
+   memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
+   tmp->bit32 = true;
+   } else {
+