[PATCH v4 2/4] include: libsframe: Add API to get FRE offset count

Indu Bhagat indu.bhagat@oracle.com
Tue Jul 29 07:09:49 GMT 2025


On 7/25/25 9:23 AM, Jens Remus wrote:
> This API will be later used by libsframe when dumping SFrame stack trace
> information (e.g. in objdump and readelf) to handle the special case of
> a SFrame FRE without any offsets.  Such FREs without any offsets will be
> used to represent RA undefined.  Other users of libsframe might need the
> same capability.
> 
> Rename the existing static function of same name to re-use its name for
> the global one.  The rename aligns the static function name to the
> likes.
> 
> While at it pass SFrame FRE as pointer to const to sanity check helper.
> 
> include/
> 	* sframe-api.h (sframe_fre_get_offset_count): New declaration.
> 
> libsframe/
> 	* libsframe.ver (sframe_fre_get_offset_count): List new API.
> 	* sframe.c (sframe_fre_get_offset_count): Rename to ...
> 	(sframe_get_fre_offset_count): ... this.
> 	(sframe_fre_sanity_check_p, sframe_fre_offset_bytes_size,
> 	flip_fre, sframe_get_fre_offset): Likewise.
> 	(sframe_fre_get_offset_count): New definition.
> 	(sframe_fre_sanity_check_p): Make frep pointer to const.
> 
> Signed-off-by: Jens Remus <jremus@linux.ibm.com>
> ---
> 
> Notes (jremus):
>      Changes in V4:
>      - New patch.
>      
>      Technically it would not be necessary to make sframe_fre_get_offset_count
>      global (i.e. list it in the version file), as libsframe could use it
>      in dumping SFrame. But other users of libsframe need the capability to
>      differentiate between a failure to get the CFA offset and a FRE without
>      any offsets.
>      

I think ideally we should now adapt the various sframe_fre_get_*_offset 
APIs too..

At the minimum, I think in sframe_fre_get_cfa_offset, we should check 
for errp:

   /* For s390x undo adjustment of CFA offset (to enable 8-bit offsets).  */
   if (!errp && sframe_decoder_get_abi_arch (dctx) == 
SFRAME_ABI_S390X_ENDIAN_BIG)
     offset = SFRAME_V2_S390X_CFA_OFFSET_DECODE (offset);

Next, IIUC currently sframe_get_fre_offset will return 
SFRAME_ERR_FREOFFSET_NOPRESENT when num FRE offsets is 0.

For sframe_fre_get_ra_offset and sframe_fre_get_fp_offset, returning the 
fixed RA offset or fixed FP offset respectively when 
sframe_fre_get_ra_undefined_p (fre) is true looks wierd.  So what do you 
think about:

  - adding a new enum in include/sframe-api.h (Not entirely sure if 
SFRAME_ERR_ZERO_FREOFFSETS is apt name / error in this context)
   _SFRAME_ITEM (SFRAME_ERR_ZERO_FREOFFSETS, "No FRE offsets present.")
   and return it in sframe_fre_get_offset...

  - In sframe_fre_get_ra_offset:
   /* If the RA offset was not being tracked, return the fixed RA offset
      from the SFrame header.  */
   if (ra_offset != SFRAME_CFA_FIXED_RA_INVALID
       && !sframe_fre_get_ra_undefined_p (fre))
     {
       if (errp)
         *errp = 0;
       return ra_offset;
     }
  - Similarly in sframe_fre_get_fp_offset...

What do you think ?

>      An alternative would be to add an API to test for RA undefined.  See
>      a following patch.
> 

I find the RA undefined API to be more direct.  But I am happy to go 
with your best judgement on this.  I do agree either one will suffice 
and that we do not need both.

>   include/sframe-api.h    |  6 ++++++
>   libsframe/libsframe.ver |  5 +++++
>   libsframe/sframe.c      | 24 ++++++++++++++++++------
>   3 files changed, 29 insertions(+), 6 deletions(-)
> 
> diff --git a/include/sframe-api.h b/include/sframe-api.h
> index 8c26257fb643..02688e4edca4 100644
> --- a/include/sframe-api.h
> +++ b/include/sframe-api.h
> @@ -201,6 +201,12 @@ dump_sframe (sframe_decoder_ctx *decoder, uint64_t addr);
>   extern uint8_t
>   sframe_fre_get_base_reg_id (sframe_frame_row_entry *fre, int *errp);
>   
> +/* Get the number of offset from the FRE.  Set errp if failure.  */
> +
> +int
> +sframe_fre_get_offset_count (const sframe_decoder_ctx *dctx ATTRIBUTE_UNUSED,
> +			     const sframe_frame_row_entry *fre, int *errp);
> +
>   /* Get the CFA offset from the FRE.  If the offset is invalid, sets errp.  */
>   extern int32_t
>   sframe_fre_get_cfa_offset (sframe_decoder_ctx *dtcx,
> diff --git a/libsframe/libsframe.ver b/libsframe/libsframe.ver
> index 8cc80da2f26a..e02e29ae134f 100644
> --- a/libsframe/libsframe.ver
> +++ b/libsframe/libsframe.ver
> @@ -41,3 +41,8 @@ LIBSFRAME_2.0 {
>     local:
>       *;
>   } LIBSFRAME_0.0;
> +
> +LIBSFRAME_2.1 {
> +  global:
> +    sframe_fre_get_offset_count;
> +} LIBSFRAME_2.0;
> diff --git a/libsframe/sframe.c b/libsframe/sframe.c
> index 9814a3ae4c1f..108c2bf9d2a9 100644
> --- a/libsframe/sframe.c
> +++ b/libsframe/sframe.c
> @@ -114,7 +114,7 @@ sframe_get_hdr_size (sframe_header *sfh)
>   /* Access functions for frame row entry data.  */
>   
>   static uint8_t
> -sframe_fre_get_offset_count (uint8_t fre_info)
> +sframe_get_fre_offset_count (uint8_t fre_info)
>   {
>     return SFRAME_V1_FRE_OFFSET_COUNT (fre_info);
>   }
> @@ -284,7 +284,7 @@ sframe_fre_start_addr_size (uint32_t fre_type)
>   /* Check if the FREP has valid data.  */
>   
>   static bool
> -sframe_fre_sanity_check_p (sframe_frame_row_entry *frep)
> +sframe_fre_sanity_check_p (const sframe_frame_row_entry *frep)
>   {
>     uint8_t offset_size, offset_cnt;
>     uint8_t fre_info;
> @@ -300,7 +300,7 @@ sframe_fre_sanity_check_p (sframe_frame_row_entry *frep)
>         && offset_size != SFRAME_FRE_OFFSET_4B)
>       return false;
>   
> -  offset_cnt = sframe_fre_get_offset_count (fre_info);
> +  offset_cnt = sframe_get_fre_offset_count (fre_info);
>     if (offset_cnt > MAX_NUM_STACK_OFFSETS)
>       return false;
>   
> @@ -318,7 +318,7 @@ sframe_fre_offset_bytes_size (uint8_t fre_info)
>   
>     debug_printf ("offset_size =  %u\n", offset_size);
>   
> -  offset_cnt = sframe_fre_get_offset_count (fre_info);
> +  offset_cnt = sframe_get_fre_offset_count (fre_info);
>   
>     if (offset_size == SFRAME_FRE_OFFSET_2B
>         || offset_size == SFRAME_FRE_OFFSET_4B)	/* 2 or 4 bytes.  */
> @@ -442,7 +442,7 @@ flip_fre (char *fp, uint32_t fre_type, size_t *fre_size)
>     /* FRE info is uint8_t.  No need to flip.  */
>     fre_info = *(uint8_t*)fp;
>     offset_size = sframe_fre_get_offset_size (fre_info);
> -  offset_cnt = sframe_fre_get_offset_count (fre_info);
> +  offset_cnt = sframe_get_fre_offset_count (fre_info);
>   
>     /* Advance the buffer pointer to where the stack offsets are.  */
>     fre_info_size = sizeof (uint8_t);
> @@ -587,7 +587,7 @@ sframe_get_fre_offset (sframe_frame_row_entry *fre, int idx, int *errp)
>     if (fre == NULL || !sframe_fre_sanity_check_p (fre))
>       return sframe_set_errno (errp, SFRAME_ERR_FRE_INVAL);
>   
> -  offset_cnt = sframe_fre_get_offset_count (fre->fre_info);
> +  offset_cnt = sframe_get_fre_offset_count (fre->fre_info);
>     offset_size = sframe_fre_get_offset_size (fre->fre_info);
>   
>     if (offset_cnt < idx + 1)
> @@ -692,6 +692,18 @@ sframe_fre_get_base_reg_id (sframe_frame_row_entry *fre, int *errp)
>     return SFRAME_V1_FRE_CFA_BASE_REG_ID (fre_info);
>   }
>   
> +/* Get the number of offset from the FRE.  Set errp if failure.  */
> +
> +int
> +sframe_fre_get_offset_count (const sframe_decoder_ctx *dctx ATTRIBUTE_UNUSED,
> +			     const sframe_frame_row_entry *fre, int *errp)
> +{
> +  if (fre == NULL || !sframe_fre_sanity_check_p (fre))
> +    return sframe_set_errno (errp, SFRAME_ERR_FRE_INVAL);
> +
> +  return sframe_get_fre_offset_count (fre->fre_info);
> +}
> +
>   /* Get the CFA offset from the FRE.  If the offset is invalid, sets errp.  */
>   
>   int32_t



More information about the Binutils mailing list