[PATCH v2 7/7] Fix the calculation of the function length

Richard Earnshaw (lists) Richard.Earnshaw@arm.com
Thu Jul 24 13:56:51 GMT 2025


On 24/07/2025 11:23, Evgeny Karpov wrote:
> Wednesday, July 23
> Richard Earnshaw (lists) <Richard.Earnshaw@arm.com> wrote:
> 
>>> Repro case:
>>>
>>> .text
>>> .seh_proc	test
>>> .seh_endprologue
>>>     mov x0, xzr
>>>     .align 2 // Once this is removed, the expression for function size can be evaluated correctly
>>>     ret
>>> .seh_endproc
>>>
>>
>> I don't think it's that uncommon to see code with alignment of branch targets.  For example,
>>
>> .text
>>      .p2align 4  // 16-byte alignment so that func is at start of cache line
>> func:
>>      // code
>>      b  Lsomewhere
>>      // no fall-through path
>>      .p2align 4  // 16-byte alignment so that Lsomewhere_else is at start of cache line
>> Lsomewhere_else:
>>      // more code
>>
>> We certainly want to support that.  See, for example, -falign-labels and -falign-loops in the gcc manual.
>>
>> Maybe your problem is that you're trying to calculate the function size for the seh data too early, before the frags have been consolidated: the intra-section alignment data should all be replaced with appropriate padding before the object file is emitted, so all offsets within a function become fixed.
> 
> Thanks. It was exactly this case. This patch is no longer needed, and the issue 
> will be addressed by adding the change below to [Patch] Write SEH records to pdata/xdata
> 
> Regards,
> Evgeny
> 
> diff --git a/gas/config/obj-coff-seh.c b/gas/config/obj-coff-seh.c
> index 75b45b8d4dd..b05153bfe81 100644
> --- a/gas/config/obj-coff-seh.c
> +++ b/gas/config/obj-coff-seh.c
> @@ -559,6 +559,24 @@ do_seh_endproc (void)
>  {
>    seh_ctx_cur->end_addr = symbol_temp_new_now ();
> 
> +#if defined (COFFAARCH64)
> +/* Fragment alignment should be handled before writing unwinding
> +   information to the .pdata/.xdata sections. This is required to
> +   accurately calculate the function size, which is used to split
> +   the function into multiple fragments if it is too large. */
> +
> +  struct frag * current_frag = frchain_now->frch_root;
> +  while(current_frag)
> +    {
> +      if (current_frag->fr_type == rs_align_code)
> +       {
> +         HANDLE_ALIGN (now_seg, current_frag);
> +         current_frag->fr_type = rs_fill;
> +       }
> +      current_frag = current_frag->fr_next;
> +    }
> +#endif
> +

This still feels like it might be a bit early, though I don't know the SEH (or coff for that matter) code well enough to be sure.  The normal way of handling this inside, say, the .text section is to emit an internal relocation.  These will then get processed and eliminated later on to leave the data.  The only time that might get tricky is if the size of the relocated element itself can change (eg with encodings like LEB128.

Perhaps Jan can comment here.

R.


More information about the Binutils mailing list