linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location
@ 2016-01-04  9:48 Hemant Kumar
  2016-01-12 11:04 ` 平松雅巳 / HIRAMATU,MASAMI
  0 siblings, 1 reply; 3+ messages in thread
From: Hemant Kumar @ 2016-01-04  9:48 UTC (permalink / raw)
  To: linux-kernel
  Cc: mjw, masami.hiramatsu.pt, sukadev, linuxppc-dev, srikar, acme

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      : 0x100007b8

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 :

000000d8 00000024 00000000 FDE cie=00000000 pc=100007b8..10000838
  DW_CFA_advance_loc: 16 to 100007c8
  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 0x100007b8
  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 <hemant@linux.vnet.ibm.com>
---
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, &frame) != 0 ||
+		if ((dwarf_cfi_addrframe(pf->cfi_eh, pf->addr, &frame) != 0 &&
+		     (dwarf_cfi_addrframe(pf->cfi_dbg, pf->addr, &frame) != 0)) ||
 		    dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 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 = &pf->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, &ehdr) == NULL)
-		return -EINVAL;
-
-	if (elf_section_by_name(elf, &ehdr, &shdr, ".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 = dwarf_getelf(dbg->dbg);
+	if (elf == NULL)
+		return -EINVAL;
+
+	if (gelf_getehdr(elf, &ehdr) == NULL)
+		return -EINVAL;
+
+	if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
+	    shdr.sh_type == SHT_PROGBITS) {
+		pf->cfi_eh = dwarf_getcfi_elf(elf);
+	} else {
+		pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
+	}
+#endif
+
+	ret = debuginfo__find_probe_location(dbg, pf);
+	return ret;
+}
+
 struct local_vars_finder {
 	struct probe_finder *pf;
 	struct perf_probe_arg *args;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index bed8271..0aec770 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -76,7 +76,10 @@ struct probe_finder {
 
 	/* For variable searching */
 #if _ELFUTILS_PREREQ(0, 142)
-	Dwarf_CFI		*cfi;		/* Call Frame Information */
+	/* Call Frame Information from .eh_frame */
+	Dwarf_CFI		*cfi_eh;
+	/* Call Frame Information from .debug_frame */
+	Dwarf_CFI		*cfi_dbg;
 #endif
 	Dwarf_Op		*fb_ops;	/* Frame base attribute */
 	struct perf_probe_arg	*pvar;		/* Current target variable */
-- 
1.9.3

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

* RE: [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location
  2016-01-04  9:48 [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location Hemant Kumar
@ 2016-01-12 11:04 ` 平松雅巳 / HIRAMATU,MASAMI
  2016-01-13  9:59   ` Hemant Kumar
  0 siblings, 1 reply; 3+ messages in thread
From: 平松雅巳 / HIRAMATU,MASAMI @ 2016-01-12 11:04 UTC (permalink / raw)
  To: 'Hemant Kumar', linux-kernel
  Cc: mjw, sukadev, linuxppc-dev, srikar, acme

SGkgSGVtYW50LA0KDQo+RnJvbTogSGVtYW50IEt1bWFyIFttYWlsdG86aGVtYW50QGxpbnV4LnZu
ZXQuaWJtLmNvbV0NCj4NCj5wZXJmIHByb2JlIHRocm91Z2ggZGVidWdpbmZvX19maW5kX3Byb2Jl
cygpIGluIHV0aWwvcHJvYmUtZmluZGVyLmMNCj5jaGVja3MgZm9yIHRoZSBmdW5jdGlvbnMnIGZy
YW1lIGRlc2NyaXB0aW9ucyBpbiBlaXRoZXIgLmVoX2ZyYW1lIHNlY3Rpb24NCj5vZiBhbiBFTEYg
b3IgdGhlIC5kZWJ1Z19mcmFtZS4gVGhlIGNoZWNrIGlzIGJhc2VkIG9uIHdoZXRoZXIgZWl0aGVy
IG9uZQ0KPm9mIHRoZXNlIHNlY3Rpb25zIGlzIHByZXNlbnQuIERlcGVuZGluZyBvbiBkaXN0cm8s
IHRvb2xjaGFpbiBkZWZhdWx0cywNCj5hcmNoaXRldGN1dHJlLCBidWlsZCBmbGFncywgZXRjLiwg
Q0ZJIG1pZ2h0IGJlIGZvdW5kIGluIGVpdGhlciAuZWhfZnJhbWUNCj5hbmQvb3IgLmRlYnVnX2Zy
YW1lLiBTb21ldGltZXMsIGl0IG1heSBoYXBwZW4gdGhhdCwgLmVoX2ZyYW1lLCBldmVuIGlmDQo+
cHJlc2VudCwgbWF5IG5vdCBiZSBjb21wbGV0ZSBhbmQgbWF5IG1pc3Mgc29tZSBkZXNjcmlwdGlv
bnMuIFRoZXJlZm9yZSwNCj50byBiZSBzdXJlLCB0byBmaW5kIHRoZSBDRkkgY292ZXJpbmcgYW4g
YWRkcmVzcyB3ZSB3aWxsIGFsd2F5cyBoYXZlIHRvDQo+aW52ZXN0aWdhdGUgYm90aCBpZiBhdmFp
bGFibGUuDQoNCk9LLCBzbyB3ZSdkIGJldHRlciBjaGVjayBib3RoIGNmaSdzLg0KIFsuLi5dDQo+
Ky8qIEZpbmQgcHJvYmUgcG9pbnRzIGZyb20gZGVidWdpbmZvICovDQo+K3N0YXRpYyBpbnQgZGVi
dWdpbmZvX19maW5kX3Byb2JlcyhzdHJ1Y3QgZGVidWdpbmZvICpkYmcsDQo+KwkJCQkgIHN0cnVj
dCBwcm9iZV9maW5kZXIgKnBmKQ0KPit7DQo+KwlpbnQgcmV0ID0gMDsNCj4rDQo+KyNpZiBfRUxG
VVRJTFNfUFJFUkVRKDAsIDE0MikNCj4rCUVsZiAqZWxmOw0KPisJR0VsZl9FaGRyIGVoZHI7DQo+
KwlHRWxmX1NoZHIgc2hkcjsNCj4rDQo+KwlpZiAocGYtPmNmaV9laCB8fCBwZi0+Y2ZpX2RiZykN
Cj4rCQlyZXR1cm4gZGVidWdpbmZvX19maW5kX3Byb2JlX2xvY2F0aW9uKGRiZywgcGYpOw0KPisN
Cj4rCS8qIEdldCB0aGUgY2FsbCBmcmFtZSBpbmZvcm1hdGlvbiBmcm9tIHRoaXMgZHdhcmYgKi8N
Cj4rCWVsZiA9IGR3YXJmX2dldGVsZihkYmctPmRiZyk7DQo+KwlpZiAoZWxmID09IE5VTEwpDQo+
KwkJcmV0dXJuIC1FSU5WQUw7DQo+Kw0KPisJaWYgKGdlbGZfZ2V0ZWhkcihlbGYsICZlaGRyKSA9
PSBOVUxMKQ0KPisJCXJldHVybiAtRUlOVkFMOw0KPisNCj4rCWlmIChlbGZfc2VjdGlvbl9ieV9u
YW1lKGVsZiwgJmVoZHIsICZzaGRyLCAiLmVoX2ZyYW1lIiwgTlVMTCkgJiYNCj4rCSAgICBzaGRy
LnNoX3R5cGUgPT0gU0hUX1BST0dCSVRTKSB7DQo+KwkJcGYtPmNmaV9laCA9IGR3YXJmX2dldGNm
aV9lbGYoZWxmKTsNCj4rCX0gZWxzZSB7DQo+KwkJcGYtPmNmaV9kYmcgPSBkd2FyZl9nZXRjZmko
ZGJnLT5kYmcpOw0KPisJfQ0KDQpIbW0sIGlmIHlvdSB3YW50IHRvIGNoZWNrIGJvdGggb2YgdGhv
c2UgY2ZpJ3MsIGRvbid0IHdlIGhhdmUgdG8gZG8gYmVsb3c/DQoNCglpZiAoZWxmX3NlY3Rpb25f
YnlfbmFtZShlbGYsICZlaGRyLCAmc2hkciwgIi5laF9mcmFtZSIsIE5VTEwpICYmDQoJICAgIHNo
ZHIuc2hfdHlwZSA9PSBTSFRfUFJPR0JJVFMpDQoJCXBmLT5jZmlfZWggPSBkd2FyZl9nZXRjZmlf
ZWxmKGVsZik7DQoNCglwZi0+Y2ZpX2RiZyA9IGR3YXJmX2dldGNmaShkYmctPmRiZyk7DQoNClRo
ZW4sIGJvdGggb2YgcGYtPmNmaV8qIHdpbGwgYmUgZmlsbGVkIChpZiB0aGUgZWxmIGhhcyAiLmVo
X2ZyYW1lIikuDQoNClRoYW5rcyENCg0KDQoNCg==

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

* Re: [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location
  2016-01-12 11:04 ` 平松雅巳 / HIRAMATU,MASAMI
@ 2016-01-13  9:59   ` Hemant Kumar
  0 siblings, 0 replies; 3+ messages in thread
From: Hemant Kumar @ 2016-01-13  9:59 UTC (permalink / raw)
  To: 平松雅巳 / HIRAMATU,MASAMI, linux-kernel
  Cc: mjw, sukadev, linuxppc-dev, srikar, acme



On 01/12/2016 04:34 PM, 平松雅巳 / HIRAMATU,MASAMI wrote:
> Hi Hemant,
>
>> From: Hemant Kumar [mailto:hemant@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, &ehdr) == NULL)
>> +		return -EINVAL;
>> +
>> +	if (elf_section_by_name(elf, &ehdr, &shdr, ".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, &ehdr, &shdr, ".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

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

end of thread, other threads:[~2016-01-13 10:00 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-01-04  9:48 [PATCH v2] perf/probe: Search both .eh_frame and .debug_frame sections for probe location Hemant Kumar
2016-01-12 11:04 ` 平松雅巳 / HIRAMATU,MASAMI
2016-01-13  9:59   ` Hemant Kumar

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