From: David Ahern <dsahern@gmail.com>
To: Jean Pihet <jean.pihet@linaro.org>, Jiri Olsa <jolsa@redhat.com>
Cc: linux-kernel@vger.kernel.org
Subject: Re: Fwd: perf: callchain feature on ARM - question about libunwind API
Date: Tue, 27 Aug 2013 10:12:08 -0600 [thread overview]
Message-ID: <521CCFD8.90201@gmail.com> (raw)
In-Reply-To: <CAFrcx1nr4-qyzC=zFRdnMavHy5p_r9Ng+zSVwNPk6snYtBm6gw@mail.gmail.com>
[Added Jiri who added the feature to perf]
On 8/27/13 5:58 AM, Jean Pihet wrote:
> Hi!
>
> I am looking for info and help on the libunwind API.
>
> What I am trying to achieve is to allow the callchain feature on perf
> for ARM (v7 to start with, then ARMv8), from the DWARF info found in
> the .debug_frame section.
>
> From the source code in tools/perf I have added the call to
> dwarf_find_debug_frame to load and parse the debug info from
> .debug_frame. This works correctly, all IP ranges are found from the
> debug code (test program and libraries). Then at some point I get an
> assertion: 'perf: dwarf/Gparser.c:459: fetch_proc_info: Assertion
> `c->pi.unwind_info' failed.' At that point c->pi is NULL. Cf. below
> for more info.
>
> It looks like I am not using the libunwind API as it should, so that
> the perf code apparently builds a list of IP ranges to resolve but
> cannot use it later on to gather statistics on the runtime info.
>
> Any idea on how to progress? I am also looking at the *_proc_info API
> of libunwind.
>
> Here is the patch I am using below.
>
> Cheers,
> Jean
>
> ---
> Debug log:
>
> perf report --sort symbol --call-graph --stdio
>
> _Uarm_step: calling dwarf_step(ip=0x8464, c->dwarf@0xbee150f8,
> c->dwarf.pi@0xb2bc0008)
> unwind: find_proc_info dso /home/linaro/perf-libunwind/
> test_app/stress_bt
> read_unwind_spec_debug_frame: .debug_frame offset=9304
> opened file '/home/linaro/perf-libunwind/test_app/stress_bt'. Section
> header at offset 18152
> read 3160 bytes of .debug_frame from offset 9304
> ...
> _ULarm_step: calling dwarf_step(ip=0xb6e6e764, c->dwarf@0xbee07508,
> c->dwarf.pi@0xb6e955c0)
> _ULarm_find_proc_info: looking for IP=0xb6e6e763
> opened file '/usr/lib/arm-linux-gnueabihf/libunwind.so.8'. Section
> header at offset 513260
> read 17072 bytes of .debug_frame from offset 451836
> _ULarm_dwarf_search_unwind_table: looking for IP=0xb6e6e763
> _ULarm_find_proc_info returns 0
> ...
> perf: dwarf/Gparser.c:459: fetch_proc_info: Assertion
> `c->pi.unwind_info' failed.
>
>
> ---
> Patch to the kernel source:
>
> diff --git a/tools/perf/util/unwind.c b/tools/perf/util/unwind.c
> index 958723b..dd97688 100644
> --- a/tools/perf/util/unwind.c
> +++ b/tools/perf/util/unwind.c
> @@ -39,6 +39,14 @@ UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
>
> #define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
>
> +extern int
> +UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
> + unw_word_t ip, unw_word_t segbase,
> + const char* obj_name, unw_word_t start,
> + unw_word_t end);
> +
> +#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
> +
> #define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
> #define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
>
> @@ -245,8 +253,9 @@ static int unwind_spec_ehframe(struct dso *dso,
> struct machine *machine,
> return 0;
> }
>
> -static int read_unwind_spec(struct dso *dso, struct machine *machine,
> - u64 *table_data, u64 *segbase, u64 *fde_count)
> +static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
> + u64 *table_data, u64 *segbase,
> + u64 *fde_count)
> {
> int ret = -EINVAL, fd;
> u64 offset;
> @@ -255,18 +264,40 @@ static int read_unwind_spec(struct dso *dso,
> struct machine *machine,
> if (fd < 0)
> return -EINVAL;
>
> + /* Check the .eh_frame section for unwinding info */
> offset = elf_section_offset(fd, ".eh_frame_hdr");
> close(fd);
>
> - if (offset)
> + if (offset) {
> + fprintf(stderr, "%s: .eh_frame offset=%llu\n", __func__, offset);
> ret = unwind_spec_ehframe(dso, machine, offset,
> table_data, segbase,
> fde_count);
> + }
>
> - /* TODO .debug_frame check if eh_frame_hdr fails */
> return ret;
> }
>
> +static int read_unwind_spec_debug_frame(struct dso *dso,
> + struct machine *machine,
> + u64 *segbase)
> +{
> + int fd = dso__data_fd(dso, machine);
> + if (fd < 0)
> + return -EINVAL;
> +
> + /* Check the .debug_frame section for unwinding info */
> + *segbase = elf_section_offset(fd, ".debug_frame");
> + close(fd);
> +
> + fprintf(stderr, "%s: .debug_frame offset=%llu\n", __func__, *segbase);
> +
> + if (!segbase)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
> {
> struct addr_location al;
> @@ -289,22 +320,32 @@ find_proc_info(unw_addr_space_t as, unw_word_t
> ip, unw_proc_info_t *pi,
> if (!map || !map->dso)
> return -EINVAL;
>
> - pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
> + fprintf(stderr, "unwind: find_proc_info dso %s\n", map->dso->name);
> +
> + /* Check the .eh_frame section for unwinding info */
> + if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
> + &table_data, &segbase, &fde_count)) {
> + memset(&di, 0, sizeof(di));
> + di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
> + di.start_ip = map->start;
> + di.end_ip = map->end;
> + di.u.rti.segbase = map->start + segbase;
> + di.u.rti.table_data = map->start + table_data;
> + di.u.rti.table_len = fde_count * sizeof(struct table_entry)
> + / sizeof(unw_word_t);
> + return dwarf_search_unwind_table(as, ip, &di, pi,
> + need_unwind_info, arg);
> + }
>
> - if (read_unwind_spec(map->dso, ui->machine,
> - &table_data, &segbase, &fde_count))
> - return -EINVAL;
> + /* Check the .debug_frame section for unwinding info */
> + if (!read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
> + memset(&di, 0, sizeof(di));
> + if (dwarf_find_debug_frame(0, &di, ip, segbase, map->dso->name,
> + map->start, map->end))
> + return 0;
> + }
>
> - memset(&di, 0, sizeof(di));
> - di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
> - di.start_ip = map->start;
> - di.end_ip = map->end;
> - di.u.rti.segbase = map->start + segbase;
> - di.u.rti.table_data = map->start + table_data;
> - di.u.rti.table_len = fde_count * sizeof(struct table_entry)
> - / sizeof(unw_word_t);
> - return dwarf_search_unwind_table(as, ip, &di, pi,
> - need_unwind_info, arg);
> + return -EINVAL;
> }
>
> static int access_fpreg(unw_addr_space_t __maybe_unused as,
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
>
next prev parent reply other threads:[~2013-08-27 16:12 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <CAFrcx1n5eA4zz+nUhraE_fi_Usc=PCZTC=RCT=S285K4=jqHSg@mail.gmail.com>
2013-08-27 11:58 ` Fwd: perf: callchain feature on ARM - question about libunwind API Jean Pihet
2013-08-27 16:12 ` David Ahern [this message]
2013-08-29 13:52 ` Jiri Olsa
2013-08-29 17:15 ` Jean Pihet
2013-08-30 11:49 ` Jiri Olsa
2013-08-30 11:56 ` Jiri Olsa
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=521CCFD8.90201@gmail.com \
--to=dsahern@gmail.com \
--cc=jean.pihet@linaro.org \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.