[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