Re: [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location

2016-01-13 Thread Hemant Kumar



On 01/12/2016 04:34 PM, 平松雅巳 / HIRAMATU,MASAMI wrote:

Hi Hemant,


From: Hemant Kumar [mailto:hem...@linux.vnet.ibm.com]

perf probe through debuginfo__find_probes() in util/probe-finder.c
checks for the functions' frame descriptions in either .eh_frame section
of an ELF or the .debug_frame. The check is based on whether either one
of these sections is present. Depending on distro, toolchain defaults,
architetcutre, build flags, etc., CFI might be found in either .eh_frame
and/or .debug_frame. Sometimes, it may happen that, .eh_frame, even if
present, may not be complete and may miss some descriptions. Therefore,
to be sure, to find the CFI covering an address we will always have to
investigate both if available.

OK, so we'd better check both cfi's.
  [...]

+/* Find probe points from debuginfo */
+static int debuginfo__find_probes(struct debuginfo *dbg,
+ struct probe_finder *pf)
+{
+   int ret = 0;
+
+#if _ELFUTILS_PREREQ(0, 142)
+   Elf *elf;
+   GElf_Ehdr ehdr;
+   GElf_Shdr shdr;
+
+   if (pf->cfi_eh || pf->cfi_dbg)
+   return debuginfo__find_probe_location(dbg, pf);
+
+   /* Get the call frame information from this dwarf */
+   elf = dwarf_getelf(dbg->dbg);
+   if (elf == NULL)
+   return -EINVAL;
+
+   if (gelf_getehdr(elf, ) == NULL)
+   return -EINVAL;
+
+   if (elf_section_by_name(elf, , , ".eh_frame", NULL) &&
+   shdr.sh_type == SHT_PROGBITS) {
+   pf->cfi_eh = dwarf_getcfi_elf(elf);
+   } else {
+   pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
+   }

Hmm, if you want to check both of those cfi's, don't we have to do below?

if (elf_section_by_name(elf, , , ".eh_frame", NULL) &&
shdr.sh_type == SHT_PROGBITS)
pf->cfi_eh = dwarf_getcfi_elf(elf);

pf->cfi_dbg = dwarf_getcfi(dbg->dbg);

Then, both of pf->cfi_* will be filled (if the elf has ".eh_frame").

Thanks!


Ah, right. Fixed in v3.






--
Thanks,
Hemant Kumar

___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

RE: [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location

2016-01-12 Thread 平松雅巳 / HIRAMATU,MASAMI
Hi Hemant,

>From: Hemant Kumar [mailto:hem...@linux.vnet.ibm.com]
>
>perf probe through debuginfo__find_probes() in util/probe-finder.c
>checks for the functions' frame descriptions in either .eh_frame section
>of an ELF or the .debug_frame. The check is based on whether either one
>of these sections is present. Depending on distro, toolchain defaults,
>architetcutre, build flags, etc., CFI might be found in either .eh_frame
>and/or .debug_frame. Sometimes, it may happen that, .eh_frame, even if
>present, may not be complete and may miss some descriptions. Therefore,
>to be sure, to find the CFI covering an address we will always have to
>investigate both if available.

OK, so we'd better check both cfi's.
 [...]
>+/* Find probe points from debuginfo */
>+static int debuginfo__find_probes(struct debuginfo *dbg,
>+struct probe_finder *pf)
>+{
>+  int ret = 0;
>+
>+#if _ELFUTILS_PREREQ(0, 142)
>+  Elf *elf;
>+  GElf_Ehdr ehdr;
>+  GElf_Shdr shdr;
>+
>+  if (pf->cfi_eh || pf->cfi_dbg)
>+  return debuginfo__find_probe_location(dbg, pf);
>+
>+  /* Get the call frame information from this dwarf */
>+  elf = dwarf_getelf(dbg->dbg);
>+  if (elf == NULL)
>+  return -EINVAL;
>+
>+  if (gelf_getehdr(elf, ) == NULL)
>+  return -EINVAL;
>+
>+  if (elf_section_by_name(elf, , , ".eh_frame", NULL) &&
>+  shdr.sh_type == SHT_PROGBITS) {
>+  pf->cfi_eh = dwarf_getcfi_elf(elf);
>+  } else {
>+  pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
>+  }

Hmm, if you want to check both of those cfi's, don't we have to do below?

if (elf_section_by_name(elf, , , ".eh_frame", NULL) &&
shdr.sh_type == SHT_PROGBITS)
pf->cfi_eh = dwarf_getcfi_elf(elf);

pf->cfi_dbg = dwarf_getcfi(dbg->dbg);

Then, both of pf->cfi_* will be filled (if the elf has ".eh_frame").

Thanks!



___
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev

[PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location

2016-01-04 Thread Hemant Kumar
perf probe through debuginfo__find_probes() in util/probe-finder.c
checks for the functions' frame descriptions in either .eh_frame section
of an ELF or the .debug_frame. The check is based on whether either one
of these sections is present. Depending on distro, toolchain defaults,
architetcutre, build flags, etc., CFI might be found in either .eh_frame
and/or .debug_frame. Sometimes, it may happen that, .eh_frame, even if
present, may not be complete and may miss some descriptions. Therefore,
to be sure, to find the CFI covering an address we will always have to
investigate both if available.

For e.g., in powerpc, this may happen :
 $ gcc -g bin.c -o bin

 $ objdump --dwarf ./bin
 <1><145>: Abbrev Number: 7 (DW_TAG_subprogram)
<146>   DW_AT_external: 1
<146>   DW_AT_name: (indirect string, offset: 0x9e): main
<14a>   DW_AT_decl_file   : 1
<14b>   DW_AT_decl_line   : 39
<14c>   DW_AT_prototyped  : 1
<14c>   DW_AT_type: <0x57>
<150>   DW_AT_low_pc  : 0x17b8

If the .eh_frame and .debug_frame are checked for the same binary, we
will find that, .eh_frame (although present) doesn't contain a
description for "main" function.
But, .debug_frame has a description :

00d8 0024  FDE cie= pc=17b8..1838
  DW_CFA_advance_loc: 16 to 17c8
  DW_CFA_def_cfa_offset: 144
  DW_CFA_offset_extended_sf: r65 at cfa+16
...

Due to this (since, perf checks whether .eh_frame is present and goes on
searching for that address inside that frame), perf is unable to process
the probes :
 # perf probe -x ./bin main
Failed to get call frame on 0x17b8
  Error: Failed to add events.

To avoid this issue, we need to check both the sections (.eh_frame and
.debug_frame), which is done in this patch.

Note that, we can always force everything into both .eh_frame and
.debug_frame by :
 $ gcc bin.c -fasynchronous-unwind-tables  -fno-dwarf2-cfi-asm -g -o bin

Signed-off-by: Hemant Kumar 
---
Changes since v1:
- pf->cfi is now cached as pf->cfi_eh and pf->cfi_dbg depending on the source 
of CFI
  (Suggested by Mark Wielard).

 tools/perf/util/probe-finder.c | 63 +-
 tools/perf/util/probe-finder.h |  5 +++-
 2 files changed, 42 insertions(+), 26 deletions(-)

diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 05012bb..71bf27e 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -685,9 +685,10 @@ static int call_probe_finder(Dwarf_Die *sc_die, struct 
probe_finder *pf)
pf->fb_ops = NULL;
 #if _ELFUTILS_PREREQ(0, 142)
} else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa &&
-  pf->cfi != NULL) {
+  (pf->cfi_eh != NULL || pf->cfi_dbg != NULL)) {
Dwarf_Frame *frame;
-   if (dwarf_cfi_addrframe(pf->cfi, pf->addr, ) != 0 ||
+   if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, ) != 0 &&
+(dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, ) != 0)) 
||
dwarf_frame_cfa(frame, >fb_ops, ) != 0) {
pr_warning("Failed to get call frame on 0x%jx\n",
   (uintmax_t)pf->addr);
@@ -1013,8 +1014,7 @@ static int pubname_search_cb(Dwarf *dbg, Dwarf_Global 
*gl, void *data)
return DWARF_CB_OK;
 }
 
-/* Find probe points from debuginfo */
-static int debuginfo__find_probes(struct debuginfo *dbg,
+static int debuginfo__find_probe_location(struct debuginfo *dbg,
  struct probe_finder *pf)
 {
struct perf_probe_point *pp = >pev->point;
@@ -1023,27 +1023,6 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
Dwarf_Die *diep;
int ret = 0;
 
-#if _ELFUTILS_PREREQ(0, 142)
-   Elf *elf;
-   GElf_Ehdr ehdr;
-   GElf_Shdr shdr;
-
-   /* Get the call frame information from this dwarf */
-   elf = dwarf_getelf(dbg->dbg);
-   if (elf == NULL)
-   return -EINVAL;
-
-   if (gelf_getehdr(elf, ) == NULL)
-   return -EINVAL;
-
-   if (elf_section_by_name(elf, , , ".eh_frame", NULL) &&
-   shdr.sh_type == SHT_PROGBITS) {
-   pf->cfi = dwarf_getcfi_elf(elf);
-   } else {
-   pf->cfi = dwarf_getcfi(dbg->dbg);
-   }
-#endif
-
off = 0;
pf->lcache = intlist__new(NULL);
if (!pf->lcache)
@@ -1106,6 +1085,40 @@ found:
return ret;
 }
 
+/* Find probe points from debuginfo */
+static int debuginfo__find_probes(struct debuginfo *dbg,
+ struct probe_finder *pf)
+{
+   int ret = 0;
+
+#if _ELFUTILS_PREREQ(0, 142)
+   Elf *elf;
+   GElf_Ehdr ehdr;
+   GElf_Shdr shdr;
+
+   if (pf->cfi_eh || pf->cfi_dbg)
+   return debuginfo__find_probe_location(dbg, pf);
+
+   /* Get the call frame information from this dwarf */
+   elf =