[PATCH v4 5/7] Write SEH records to pdata/xdata
Jan Beulich
jbeulich@suse.com
Mon Feb 2 16:39:36 GMT 2026
On 02.02.2026 16:55, Evgeny Karpov wrote:
> On Fri, Oct 17, 2025, Jan Beulich wrote:
>> On 15.08.2025 00:50, Evgeny Karpov wrote:
>>> + fragS *start_frag, *end_frag;
>>> + addressT start_value, end_value;
>>> + start_frag = symbol_get_frag_and_value (seh_ctx->start_addr, &start_value);
>>> + end_frag = symbol_get_frag_and_value (seh_ctx->end_addr, &end_value);
>>> + offsetT offset;
>>> + frag_offset_ignore_align_p (end_frag, start_frag, &offset);
>>> + start_value += offset / OCTETS_PER_BYTE;
>>> + offset = end_value - start_value;
>>> +
>>> + if (offset < 0)
>>> + {
>>> + as_bad (_("the function size expression for %s "
>>> + "does not evaluate to a non-negative value"),
>>> + S_GET_NAME (seh_ctx->start_addr));
>>> + return;
>>> + }
>>> +
>>> + uintptr_t func_size = offset;
>>> +
>>> + const uint32_t max_frag_size = ((1 << 18) - 1) << 2;
>>
>> Where does this boundary come from?
>
> https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170#large-functions
> The large functions should be split into fragments smaller than 1MB.
Please either introduce a #define (where the name would suitably clarify
the purpose) or add a comment.
>>> + {
>>> + prolog_insruction_count = i + 1;
>>> + break;
>>> + }
>>> + }
>>> +
>>> + if (seh_ctx->aarch64_ctx.epilogue_scopes_count)
>>> + prolog_size = seh_ctx->aarch64_ctx.epilogue_scopes[0].epilogue_start_index;
>>> + else
>>> + prolog_size = seh_ctx->aarch64_ctx.unwind_codes_byte_count;
>>> +
>>> + seh_aarch64_func_fragment *fragment;
>>> + fragment = &seh_ctx->aarch64_ctx.func_fragment;
>>
>> Why not right as initializer of the variable? (Apparently I overlooked
>> similar anomalies already further up.)
>
> The reason is the 80 characters limit per line. Any other preferable style?
seh_aarch64_func_fragment *fragment
= &seh_ctx->aarch64_ctx.func_fragment;
However,
seh_aarch64_func_fragment *fragment = &seh_ctx->aarch64_ctx.func_fragment;
still stays under 80 cols anyway.
>>> + while (true)
>>> + {
>>> + fragment->xdata_addr = symbol_temp_new_now ();
>>> + fragment->offset = fragment_offset;
>>> + fragment->next = NULL;
>>> +
>>> + uintptr_t frag_size = func_size - fragment_offset;
>>> + if (frag_size > max_frag_size)
>>> + frag_size = max_frag_size;
>>> +
>>> + bool is_first_frag = fragment_offset == 0;
>>> + bool is_last_frag = (fragment_offset + frag_size) == func_size;
>>> +
>>> + if (!is_fragmented_function)
>>> + last_fragment_scope = seh_ctx->aarch64_ctx.epilogue_scopes_count;
>>> + else
>>> + {
>>> + first_fragment_scope = last_fragment_scope;
>>> + for (unsigned int i = first_fragment_scope;
>>> + i < seh_ctx->aarch64_ctx.epilogue_scopes_count; ++i)
>>> + {
>>> + const seh_aarch64_epilogue_scope *scope;
>>> + scope = seh_ctx->aarch64_ctx.epilogue_scopes;
>>> + scope += i;
>>> + if (scope->epilogue_start_offset >= (fragment_offset + frag_size))
>>> + break;
>>> +
>>> + if (scope->epilogue_end_offset >= (fragment_offset + frag_size))
>>> + {
>>> + frag_size = scope->epilogue_start_offset - fragment_offset;
>>> + break;
>>> + }
>>> +
>>> + if (scope->epilogue_start_offset >= fragment_offset)
>>> + last_fragment_scope = i + 1;
>>> + }
>>> + }
>>> +
>>> + seh_aarch64_xdata_header *header = &seh_ctx->aarch64_ctx.xdata_header;
>>> + const
>>> + seh_aarch64_epilogue_scope *scopes =
>>> seh_ctx->aarch64_ctx.epilogue_scopes;
>>> +
>>> + header->func_length = frag_size >> 2;
>>
>> Another such magic number.
>
> This is how the function length is encoded.
> https://learn.microsoft.com/en-us/cpp/build/arm64-exception-handling?view=msvc-170#xdata-records
In which case, like above, use a suitably named #define or add a comment,
please. Especially in case constants are used more than once, a #define is
pretty clearly preferred.
Jan
More information about the Binutils
mailing list