lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date:   Tue, 16 Feb 2021 10:47:02 +0000
From:   Alexandre Truong <alexandre.truong@....com>
To:     linux-kernel@...r.kernel.org, linux-perf-users@...r.kernel.org
Subject: Re: [PATCH v2 4/4] perf tools: determine if LR is the return address

Hi,

This patch is supposed to be a v3, I did a rebase.

Thanks,

Alexandre

On 2/12/21 5:03 PM, Alexandre Truong wrote:
> On arm64 and frame pointer mode (e.g: perf record --callgraph fp),
> use dwarf unwind info to check if the link register is the return
> address in order to inject it to the frame pointer stack.
>
> Write the following application:
>
>       int a = 10;
>
>       void f2(void)
>       {
>               for (int i = 0; i < 1000000; i++)
>                       a *= a;
>       }
>
>       void f1()
>       {
>               for (int i = 0; i < 10; i++)
>                       f2();
>       }
>
>       int main (void)
>       {
>               f1();
>               return 0;
>       }
>
> with the following compilation flags:
>       gcc -fno-omit-frame-pointer -fno-inline -O2
>
> The compiler omits the frame pointer for f2 on arm. This is a problem
> with any leaf call, for example an application with many different
> calls to malloc() would always omit the calling frame, even if it
> can be determined.
>
>       ./perf record --call-graph fp ./a.out
>       ./perf report
>
> currently gives the following stack:
>
> 0xffffea52f361
> _start
> __libc_start_main
> main
> f2
>
> After this change, perf report correctly shows f1() calling f2(),
> even though it was missing from the frame pointer unwind:
>
>       ./perf report
>
> 0xffffea52f361
> _start
> __libc_start_main
> main
> f1
> f2
>
> Signed-off-by: Alexandre Truong <alexandre.truong@....com>
> ---
>   tools/perf/util/Build                         |  1 +
>   .../util/arm-frame-pointer-unwind-support.c   | 44 +++++++++++++++++++
>   .../util/arm-frame-pointer-unwind-support.h   |  7 +++
>   tools/perf/util/machine.c                     |  9 ++--
>   4 files changed, 58 insertions(+), 3 deletions(-)
>   create mode 100644 tools/perf/util/arm-frame-pointer-unwind-support.c
>   create mode 100644 tools/perf/util/arm-frame-pointer-unwind-support.h
>
> diff --git a/tools/perf/util/Build b/tools/perf/util/Build
> index 188521f34347..3b82cb992bce 100644
> --- a/tools/perf/util/Build
> +++ b/tools/perf/util/Build
> @@ -1,3 +1,4 @@
> +perf-y += arm-frame-pointer-unwind-support.o
>   perf-y += annotate.o
>   perf-y += block-info.o
>   perf-y += block-range.o
> diff --git a/tools/perf/util/arm-frame-pointer-unwind-support.c b/tools/perf/util/arm-frame-pointer-unwind-support.c
> new file mode 100644
> index 000000000000..964efd08e72e
> --- /dev/null
> +++ b/tools/perf/util/arm-frame-pointer-unwind-support.c
> @@ -0,0 +1,44 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include "../arch/arm64/include/uapi/asm/perf_regs.h"
> +#include "arch/arm64/include/perf_regs.h"
> +#include "event.h"
> +#include "arm-frame-pointer-unwind-support.h"
> +#include "callchain.h"
> +#include "unwind.h"
> +
> +struct entries {
> +     u64 stack[2];
> +     size_t length;
> +};
> +
> +static bool get_leaf_frame_caller_enabled(struct perf_sample *sample)
> +{
> +     return callchain_param.record_mode == CALLCHAIN_FP && sample->user_regs.regs
> +             && sample->user_regs.mask == PERF_REGS_MASK;
> +}
> +
> +static int add_entry(struct unwind_entry *entry, void *arg)
> +{
> +     struct entries *entries = arg;
> +
> +     entries->stack[entries->length++] = entry->ip;
> +     return 0;
> +}
> +
> +u64 get_leaf_frame_caller_aarch64(struct perf_sample *sample, struct thread *thread)
> +{
> +     int ret;
> +
> +     struct entries entries = {{0, 0}, 0};
> +
> +     if (!get_leaf_frame_caller_enabled(sample))
> +             return 0;
> +
> +     ret = unwind__get_entries(add_entry, &entries, thread, sample, 2);
> +
> +     if (ret || entries.length != 2)
> +             return ret;
> +
> +     return callchain_param.order == ORDER_CALLER ?
> +             entries.stack[0] : entries.stack[1];
> +}
> diff --git a/tools/perf/util/arm-frame-pointer-unwind-support.h b/tools/perf/util/arm-frame-pointer-unwind-support.h
> new file mode 100644
> index 000000000000..16dc03fa9abe
> --- /dev/null
> +++ b/tools/perf/util/arm-frame-pointer-unwind-support.h
> @@ -0,0 +1,7 @@
> +/* SPDX-License-Identifier: GPL-2.0 */
> +#ifndef __PERF_ARM_FRAME_POINTER_UNWIND_SUPPORT_H
> +#define __PERF_ARM_FRAME_POINTER_UNWIND_SUPPORT_H
> +
> +u64 get_leaf_frame_caller_aarch64(struct perf_sample *sample, struct thread *thread);
> +
> +#endif /* __PERF_ARM_FRAME_POINTER_UNWIND_SUPPORT_H */
> diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
> index 7f03ffa016b0..dfb72dbc0e2d 100644
> --- a/tools/perf/util/machine.c
> +++ b/tools/perf/util/machine.c
> @@ -34,6 +34,7 @@
>   #include "bpf-event.h"
>   #include <internal/lib.h> // page_size
>   #include "cgroup.h"
> +#include "arm-frame-pointer-unwind-support.h"
>
>   #include <linux/ctype.h>
>   #include <symbol/kallsyms.h>
> @@ -2671,10 +2672,12 @@ static int find_prev_cpumode(struct ip_callchain *chain, struct thread *thread,
>       return err;
>   }
>
> -static u64 get_leaf_frame_caller(struct perf_sample *sample __maybe_unused,
> -             struct thread *thread __maybe_unused)
> +static u64 get_leaf_frame_caller(struct perf_sample *sample, struct thread *thread)
>   {
> -     return 0;
> +     if (strncmp(thread->maps->machine->env->arch, "aarch64", 7) == 0)
> +             return get_leaf_frame_caller_aarch64(sample, thread);
> +     else
> +             return 0;
>   }
>
>   static int thread__resolve_callchain_sample(struct thread *thread,
>
IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ