[PATCH,V5 6/9] bfd: gas: ld: libsframe: adopt new encoding for FDE func start addr field

Jan Beulich jbeulich@suse.com
Fri Jul 4 07:54:52 GMT 2025


On 03.07.2025 16:12, Indu Bhagat wrote:
> This patch convenes a set of changes in bfd, gas, ld, libsframe towards
> moving to the new encoding for the 'sfde_func_start_address' field in
> SFrame FDE.
> 
> First, gas must now mark all SFrame sections with the new flag
> SFRAME_F_FDE_FUNC_START_PCREL.  gas was already emitting the field
> in the said encoding.
> 
> 	* gas/gen-sframe.c (output_sframe_internal): Emit the flag
> 	SFRAME_F_FDE_FUNC_START_PCREL.
> 
> Similarly for ld, adopt the new semantics of sfde_func_start_address
> consistently.  This means:
>   - When merging SFrame sections, check that all input SFrame sections
>     have the SFRAME_F_FDE_FUNC_START_PCREL flag set.  If the check
>     fails, ld errors out.
>   - When merging SFrame sections, keep even the in-memory contents of
>     the FDE function start address (buffer passed to libsframe
>     sframe_encoder_write () for writing out) encoded in the new
>     semantics.  While it is, in theory, possible that instead of doing this
>     change here, we adjust the value of sfde_func_start_address at the final
>     write (sframe_encoder_write) time.  But latter is not favorable for
>     maintenanance and may be generally confusing for developers.
>   - When creating SFrame for PLT entries, emit flag
>     SFRAME_F_FDE_FUNC_START_PCREL.
> 
> include/
>         * sframe-api.h (SFRAME_F_LD_MUSTHAVE_FLAGS): New definition.
> bfd/
> 	* elf-sframe.c (_bfd_elf_merge_section_sframe): Check for flag
> 	combinatation SFRAME_F_LD_MUSTHAVE_FLAGS set for all input and
> 	output SFrame sections.  If not, error out.  Also, adopt the new
>         semantics of function start address encoding.
> 	* bfd/elfxx-x86.c (_bfd_x86_elf_create_sframe_plt): Emit flag
> 	SFRAME_F_FDE_FUNC_START_PCREL.
> 
> Next, for dumping SFrame sections, now that we are emitting the same
> encoding in GAS, non-relocatable and relocatable SFrame links, it is the
> time to set relocate to TRUE in debug_displays[].
> 
> binutils/
> 	* dwarf.c (struct dwarf_section_display): Allow sframe sections
> 	  to now be relocated.
> gas/testsuite/
> 	* gas/cfi-sframe/cfi-sframe-aarch64-pac-ab-key-1.d: Update the
> 	test.  Relocatable SFrame sections now display non-zero value
> 	(appropriate function start address).
> 
> Now, as the SFrame sections on-disk and in-memory use the new semantics of
> sfde_func_start_address encoding (i.e., function start address is the
> offset from the sfde_func_start_address field to the start PC), the
> calculation to make it human readable (i.e., relatable to the addresses
> in .text sections) needs adjustment.
> 
> libsframe/
> 	* sframe-dump.c (dump_sframe_func_with_fres): Adjust the
> 	function start address for dumping.
> 
> Now that both the emission of the new encoding, and the relocation of
> sections before dumping them is in place, it is time to adjust the
> testcases.
> 
> gas/testsuite/
> 	* gas/cfi-sframe/cfi-sframe-aarch64-1.d: Update expected output
> 	to include SFRAME_F_FDE_FUNC_START_PCREL instead of NONE.
> 	* gas/cfi-sframe/cfi-sframe-aarch64-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-aarch64-3.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-aarch64-4.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-1.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-10.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-11.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-3.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-4.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-5.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-6.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-7.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-8.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-common-9.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-x86_64-1.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-x86_64-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-x86_64-empty-1.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-x86_64-empty-2.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-x86_64-empty-3.d: Likewise.
> 	* gas/cfi-sframe/cfi-sframe-x86_64-empty-4.d: Likewise.
> 	* gas/cfi-sframe/common-empty-1.d: Likewise.
> 	* gas/cfi-sframe/common-empty-2.d: Likewise.
> 	* gas/cfi-sframe/common-empty-3.d: Likewise.
> 	* gas/scfi/x86_64/scfi-cfi-sections-1.d: Likewise.
> 	* gas/scfi/x86_64/scfi-dyn-stack-1.d: Likewise.
> ld/testsuite/
> 	* ld-aarch64/sframe-simple-1.d: Update expected output to
> 	include SFRAME_F_FDE_FUNC_START_PCREL.
> 	* ld-x86-64/sframe-ibt-plt-1.d: Likewise.
> 	* ld-x86-64/sframe-plt-1.d: Likewise.
> 	* ld-x86-64/sframe-pltgot-1.d: Likewise.
> 	* ld-x86-64/sframe-pltgot-2.d: Likewise.
> 	* ld-x86-64/sframe-simple-1.d: Likewise.
> 
> Naturally, the change of semantics for 'SFrame FDE function start address'
> has consequences on the implementation in libsframe.  As per the new
> semantics:
>   - Function start address in the SFrame FDE (sfde_func_start_address)
>     is an offset from the FDE function start address field to the start
>     PC of the associated function.
> 
> Note that, the libsframe library brings the SFrame section contents into
> its own memory to create a sframe_decoder_ctx object via sframe_decode
> ().  Many internal and user-interfacing APIs then may use
> sframe_decoder_ctx object to interact and fulfill the work.
> 
> In context of changing semantics for sfde_func_start_address, following
> relevant examples may help understand the impact:
>   - sframe_find_fre () finds a the SFrame stack trace data (SFrame FRE)
>     given a lookup offset (offset of lookup_pc from the start of SFrame
>     section).  Now that the sfde_func_start_address includes the
>     distance from the sfde_func_start_address field to the start of
>     SFrame section itself, the comparison checks of
>     sfde_func_start_address with the incoming lookup offset need
>     adjustment.
>   - Some internal functions (sframe_get_funcdesc_with_addr_internal ()
>     finds SFrame FDE by using binary seach comparing
>     sfde_func_start_address fields, etc.) need adjustments.
>   - sframe_encoder_write () sorts the SFrame FDEs before writing out
>     the SFrame data.  Sorting of SFrame FDE via the internal function
>     sframe_sort_funcdesc() needs adjustments: the new encoding of
>     sfde_func_start_address means the distances are not from the same
>     anchor, so cannot be sorted directly.
> 
> This patch takes the approach of adding a new internal function:
>   - sframe_decoder_get_secrel_func_start_addr (): This function returns
>     the offset of the start PC of the function from the start of SFrame
>     section, i.e., it gives a section-relative offset.
> 
> As the sframe_decoder_get_secrel_func_start_addr () API needs the value
> of the function index in the FDE list, another internal API needs
> sframe_fre_check_range_p () adjustments too.
> 
> Sorting the FDEs (via sframe_sort_funcdesc ()) is done by first bringing
> all offsets in sfde_func_start_address relative to start of SFrame
> section, followed by sorting, and then readjusting the offsets accroding
> to the new position in the FDE list.
> 
> libsframe/
> 	* sframe.c (sframe_decoder_get_secrel_func_start_addr): New
> 	static function.
>         (sframe_fre_check_range_p): Adjust the interface a bit.
> 	(sframe_get_funcdesc_with_addr_internal): Use
> 	sframe_decoder_get_secrel_func_start_addr () when comparing
> 	sfde_func_start_address with user input offset.
>         (sframe_find_fre): Adopt the new semantics.
>         (sframe_sort_funcdesc): Likewise.
> 
> For the libsframe testsuite, use the new encoding for FDE func start
> addr: distance between the FDE sfde_func_start_address field and the
> start PC of the function itself.
> 
> Use SFRAME_F_FDE_FUNC_START_PCREL flag, though the sframe_encode ()
> interface in libsframe applies no sanity checks for the encoding itself.
> 
> libsframe/testsuite/
> 	* libsframe.find/findfre-1.c: Adjust to use the new
> 	SFRAME_F_FDE_FUNC_START_PCREL specific encoding.
> 	* libsframe.find/findfunc-1.c: Likewise.
> 	* libsframe.find/plt-findfre-1.c: Likewise.
> 	* libsframe/testsuite/libsframe.decode/DATA2: Update data file
> 	due to usage of new SFRAME_F_FDE_FUNC_START_PCREL flag.
> 	* libsframe/testsuite/libsframe.encode/encode-1.c: Use flag
> 	SFRAME_F_FDE_FUNC_START_PCREL.

I have two more remarks below. Please adjust (or not) as you see fit, and
then feel free to put in.

> @@ -411,6 +425,18 @@ _bfd_elf_merge_section_sframe (bfd *abfd,
>        return false;
>      }
>  
> +  /* Check that all SFrame sections being linked have the 'data encoding'
> +     related flags set.  The implementation does not support updating these
> +     data encodings on the fly.  */
> +  ectx_flags = sframe_encoder_get_flags (sfe_ctx);
> +  if ((dctx_flags & ectx_flags & SFRAME_F_LD_MUSTHAVE_FLAGS)
> +      != SFRAME_F_LD_MUSTHAVE_FLAGS)
> +    {
> +      _bfd_error_handler
> +	(_("input SFrame sections with unexpected data encoding prevent"
> +	  " .sframe generation"));
> +      return false;
> +    }

ectx_flags is about the output, though, isn't it? The message talks of only
inputs. Maybe best drop "input" from there?

> --- a/gas/gen-sframe.c
> +++ b/gas/gen-sframe.c
> @@ -663,8 +663,9 @@ output_sframe_internal (void)
>    int fixed_ra_offset = SFRAME_CFA_FIXED_RA_INVALID;
>  
>    /* The function descriptor entries as dumped by the assembler are not
> -     sorted on PCs.  */
> -  unsigned char sframe_flags = 0;
> +     sorted on PCs.  Fix for PR ld/32666 requires setting of an additional
> +     flag in SFrame Version 2.  */
> +  unsigned char sframe_flags = SFRAME_F_FDE_FUNC_START_PCREL;

Question is whether this shouldn't then use SFRAME_F_LD_MUSTHAVE_FLAGS, too.

Jan


More information about the Binutils mailing list