[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