Hi Tom!

On Fri, 8 Feb 2019 10:41:47 +0100, Tom de Vries <tdevr...@suse.de> wrote:
> The backtrace functions backtrace_full, backtrace_print and backtrace_simple
> walk the call stack, but make sure to skip the first entry, in order to skip
> over the functions themselves, and start the backtrace at the caller of the
> functions.
> 
> When compiling with -flto, the functions may be inlined, causing them to skip
> over the caller instead.

So, when recently working on the OpenACC Profiling Interface
implementation in libgomp, where I'm using libbacktrace to figure out the
caller of certain libgomp functions, I recently wondered about the very
same issue, that we reliably have to skip a few initial frames.

So, "noinline" is how to do that reliably...  ;-/ That might be
non-obvious for the casual reader, so they might not understand...

> Fix this by declaring the functions with __attribute__((noinline)).

... this alone.

I'd suggest to have a common "#define LIBBACKTRACE_NOINLINE [...]" (or
similar), together with the explanatory comment given above, and use that
at the respective definition (or declaration?) sites.  Can that go into
the public libbacktrace "*.h" file, so that it can also be used
elsewhere, as described above?

If you agree, want me to prepare a patch?


Grüße
 Thomas


> [libbacktrace] Declare external backtrace fns noinline
> 
> 2019-02-08  Tom de Vries  <tdevr...@suse.de>
> 
>       * backtrace.c (backtrace_full): Declare with __attribute__((noinline)).
>       * print.c (backtrace_print): Same.
>       * simple.c (backtrace_simple): Same.
> 
> ---
>  libbacktrace/backtrace.c | 2 +-
>  libbacktrace/print.c     | 2 +-
>  libbacktrace/simple.c    | 2 +-
>  3 files changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/libbacktrace/backtrace.c b/libbacktrace/backtrace.c
> index 29204c63313..c579e803825 100644
> --- a/libbacktrace/backtrace.c
> +++ b/libbacktrace/backtrace.c
> @@ -98,7 +98,7 @@ unwind (struct _Unwind_Context *context, void *vdata)
>  
>  /* Get a stack backtrace.  */
>  
> -int
> +int __attribute__((noinline))
>  backtrace_full (struct backtrace_state *state, int skip,
>               backtrace_full_callback callback,
>               backtrace_error_callback error_callback, void *data)
> diff --git a/libbacktrace/print.c b/libbacktrace/print.c
> index b2f45446443..0767facecae 100644
> --- a/libbacktrace/print.c
> +++ b/libbacktrace/print.c
> @@ -80,7 +80,7 @@ error_callback (void *data, const char *msg, int errnum)
>  
>  /* Print a backtrace.  */
>  
> -void
> +void __attribute__((noinline))
>  backtrace_print (struct backtrace_state *state, int skip, FILE *f)
>  {
>    struct print_data data;
> diff --git a/libbacktrace/simple.c b/libbacktrace/simple.c
> index d439fcee8e2..118936397da 100644
> --- a/libbacktrace/simple.c
> +++ b/libbacktrace/simple.c
> @@ -90,7 +90,7 @@ simple_unwind (struct _Unwind_Context *context, void *vdata)
>  
>  /* Get a simple stack backtrace.  */
>  
> -int
> +int __attribute__((noinline))
>  backtrace_simple (struct backtrace_state *state, int skip,
>                 backtrace_simple_callback callback,
>                 backtrace_error_callback error_callback, void *data)

Reply via email to