[PATCH v4 2/5] elf: Add SFrame stack tracing
Jens Remus
jremus@linux.ibm.com
Tue Apr 22 12:32:11 GMT 2025
On 22.04.2025 10:55, Claudiu Zissulescu-Ianculescu wrote:
> On 4/18/25 6:09 PM, Florian Weimer wrote:
>> * claudiu zissulescu-ianculescu:
>>
>>> +/* 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. */
>>> +
>>> +#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)
>>
>> Shouldn't this switch to DWARF backtracing to avoid a truncated
>> backtrace? Otherwise std::stacktrace::current() will not work anymore
>> once glibc and libstdc++ are upgraded, I think.
>
> The above macro should avoid truncating the backtrace when sframe
> information is not present, or only present in glibc library.
> When SFrame info is not present in the last frame, then the
> stacktarce_sframe returns 0, thus rolling back to DWARF unwinding.
> When SFrame info is only present in the last frame (i.e., glibc
> backtrace) but not in the backtrace caller, then stacktrace_sframe
> should return 1, thus forcing again the DWARF unwinding procedure to
> kick in.
Maybe it would be good to force a fallback to the DWARF backtracer,
if an object without SFrame information is met. Except form the
initial patch:
> diff --git a/sysdeps/generic/sframe.c b/sysdeps/generic/sframe.c
> +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)
> + return i;
/* Force fallback to DWARF stacktracer. */
return 0;
> +
> + 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
> + return i;
/* Force fallback to DWARF stacktracer. */
return 0;
> + }
> +
> + /* Decode the specified SFrame buffer populate sframe's decoder
> + context. */
> + if (sframe_decode (dctx, (char *) data.dlfo_sframe) == _URC_END_OF_STACK)
> + return i;
> +
> + pc = frame->pc - sframe_vma;
> + /* Find the SFrame Row Entry which contains the PC. */
> + if (sframe_find_fre (dctx, pc, frep) == _URC_END_OF_STACK)
> + {
> +#ifdef MD_DECODE_SIGNAL_FRAME
> + /* I cannot find any FREs, try to see if it is a signal
> + frame, and if so decode it. */
> + if (MD_DECODE_SIGNAL_FRAME (frame) == _URC_NO_REASON)
> + {
> + ra_lst[i] = (void *) frame->pc;
> + continue;
> + }
> +#endif
> + return i;
/* Force fallback to DWARF stacktracer. */
return 0;
> + }
> ...
Regards,
Jens
--
Jens Remus
Linux on Z Development (D3303)
+49-7031-16-1128 Office
jremus@de.ibm.com
IBM
IBM Deutschland Research & Development GmbH; Vorsitzender des Aufsichtsrats: Wolfgang Wendt; Geschäftsführung: David Faller; Sitz der Gesellschaft: Böblingen; Registergericht: Amtsgericht Stuttgart, HRB 243294
IBM Data Privacy Statement: https://www.ibm.com/privacy/
More information about the Libc-alpha
mailing list