[PATCH v6 4/5] elf: Add SFrame stack tracing
Florian Weimer
fweimer@redhat.com
Tue Jun 24 08:32:50 GMT 2025
* claudiu zissulescu-ianculescu:
> From: Claudiu Zissulescu <claudiu.zissulescu-ianculescu@oracle.com>
>
> This patch adds the necessary bits to enable stack tracing using
> SFrame. In the case the new SFrame stack tracing procedure doesn't
> find SFrame related info, the stack tracing falls back on default
> Dwarf implementation.
>
> The new SFrame stack tracing procedure is added to bebug/backtrace.c
> file, the support functions are added in sysdeps folder, namely
> sframe.h, read-sframe.c and read-sfame.h.
Typo: [d]ebug/backtrace.c
Why do you place the support routines into sysdeps/generic/? I don't see
any sysdeps overrides.
Global, non-installed include files can go into include/.
> diff --git a/debug/backtrace.c b/debug/backtrace.c
> index 05cdc84e8d..aca0b5ade9 100644
> --- a/debug/backtrace.c
> +++ b/debug/backtrace.c
> @@ -20,6 +20,7 @@
> #include <stdlib.h>
> #include <unwind.h>
> #include <unwind-link.h>
> +#include <sframe.h>
>
> struct trace_arg
> {
> @@ -30,6 +31,29 @@ struct trace_arg
> int size;
> };
>
> +/* Initialize the SFrame backtrace routine, and try to backtrace the
> + current stack using SFrame info. The return value of SFrame stack
> + tracer must be larger than one to consider the SFrame backtrace
> + valid. Otherwise, there may be the case that glibc is compiled
> + using SFrame but the application not. The SFrame backtracer can
> + fallback on Dwarf unwinder also when it is a posibility to return a
> + truncated trace. This happens when a stack frame is detected
> + missing SFrame information. */
> +
> +#define DO_SFRAME_BACKTRACE(ARRAY, SIZE) \
> + do \
> + { \
> + int cnt; \
> + frame frame; \
> + frame.pc = getPC(); \
> + frame.sp = getSP(); \
> + frame.fp = (_Unwind_Ptr) __builtin_frame_address (0); \
> + cnt = stacktrace_sframe (ARRAY, SIZE, &frame); \
> + if (cnt > 1) \
> + return cnt; \
> + } \
> + while(0)
> +
> static _Unwind_Reason_Code
> backtrace_helper (struct _Unwind_Context *ctx, void *a)
> {
> @@ -72,7 +96,14 @@ __backtrace (void **array, int size)
> .cnt = -1
> };
>
> - if (size <= 0 || arg.unwind_link == NULL)
> + if (size <= 0)
> + return 0;
> +
> + /* Try first the SFrame backtracer. */
> + DO_SFRAME_BACKTRACE (array, size);
> +
> + /* Try the dwarf unwinder. */
> + if (arg.unwind_link == NULL)
> return 0;
I dislike the macro with the control flow. As far as I can see, there
is just a single result value (cnt), so you could easily use an inline
function. But it addresses my concern regarding truncated backtraces in
a mix DWARF/SFrame environment. Still this would benefit from a test
that shows this works.
The internal functions should use __ prefixes (at least if they are
declared with external linkage), so that they do not conflict with
application definitions when linking statically.
> +int
> +stacktrace_sframe (void **ra_lst, int count, frame *frame)
> +{
> + _Unwind_Ptr sframe_vma, cfa, return_addr, ra_stack_loc, fp_stack_loc, pc,
> + frame_ptr;
> + int cfa_offset, fp_offset, ra_offset, i;
> + sframe_frame_row_entry fred, *frep = &fred;
> +
> + if (!ra_lst || !count)
> + return 0;
> +
> + for (i = 0; i < count; i++)
> + {
> + _Unwind_Reason_Code err;
> + struct dl_find_object data;
> + sframe_decoder_ctx decoder_context, *dctx = &decoder_context;
> +
> + /* Clean decoder context. */
> + memset (dctx, 0, sizeof (sframe_decoder_ctx));
> +
> + /* Load and set up the SFrame stack trace info for pc. */
> + if (_dl_find_object_helper ((void *) frame->pc, &data) < 0)
> + /* Force fallback to DWARF stacktracer. */
> + return 0;
Inconsistent tabs vs whitespace.
> +
> + sframe_vma = (_Unwind_Ptr) data.dlfo_sframe;
> + if (!sframe_vma)
> + {
> +#ifdef MD_DECODE_SIGNAL_FRAME
> + /* I cannot find a valid SFrame section. Check if it is a
> + signal frame. */
> + if (MD_DECODE_SIGNAL_FRAME (frame) == _URC_NO_REASON)
> + {
> + ra_lst[i] = (void *) frame->pc;
> + continue;
> + }
> +#endif
> + /* Force fallback to DWARF stacktracer. */
> + return 0;
> + }
I don't quite understand how this approach is valid. Wouldn't we have
to check MD_DECODE_SIGNAL_FRAME (frame) first? Otherwise we might get
incorrect results if _dl_find_object encounters a valid-looking code
address.
(Not a complete review, sorry.)
Thanks,
Florian
More information about the Libc-alpha
mailing list