[PATCH v10 05/28] Object Attributes v2: new abstractions for subsections and attributes

Matthieu Longo matthieu.longo@arm.com
Fri Nov 28 17:30:28 GMT 2025


On 28/11/2025 13:30, Jan Beulich wrote:
> On 20.11.2025 18:58, Matthieu Longo wrote:
>> From: Richard Ball <richard.ball@arm.com>
>>
>> This patch lays the groundwork for the support of Object Attributes v2 (OAv2).
>> OAv2 is an enhancement of OAv1. They retain successful aspects of OAv1, define
>> the relationship between object attributes and existing GNU properties, separate
>> architectural requirements from software ABI requirements, and simplify the
>> format to make it easier for OAv2 consumers to parse, and skip subsections and
>> attributes. Interestingly, OAv2 have only one scope: the whole relocatable file
>> where they were specified. For the reason behind this choice, see [1], "Build
>> attributes at file scope only". This document also provides more insights into
>> the design rationale for OAv2.
>>
>> Even if OAv2 was designed primarily for AArch64, this implementation splits the
>> generic core logic from the backend-specific one, and aims at facilitating OAv2
>> adoption by others backend. This logic will apply for any subsequent OAv2 patch.
>>
>> New abstractions for attributes and subsections are introduced in bfd/elf-attrs.h
>> Those align with the format of OAv2 proposed in [2].
>>
>> An object attribute obj_attr_v2 is a tag-value pair:
>>   - tag: a key, i.e. a unique identifier for the attribute in the
>>     subsection.
>>   - value: a variant for which the interpretation depends on the encoding
>>     set in the subsection it was stored in. 2 types of values are possible:
>>     ULEB128 (Unsigned Little Endian Base 128) or a string encoded as NTBS
>>     (Null-Terminated Byte String).
>>
>> A subsection obj_attr_subsection_v2 has the following members:
>>   - name: the name of this subsection.
>>   - scope: the prefix in the subsection name determines whether the
>>     subsection is public or private.
>>   - optionality: is this subsection optional or required ? Depending on
>>     whether the subsection is public or private, it can be ignored by the
>>     consumer.
>>   - encoding: see previous note regarding the value of an attribute. This
>>     encoding applies to all the attributes in this subsection.
>>   - list of object attributes.
>>
>> Even if OAv1 and OAv2 data structures are similar, their processing is
>> different. Thus refactoring the code of OAv1 and OAv2 to share it does not
>> seem the right approach for clarity and maintainability, and minimalization
>> of the risk of introducing regressions.
>> Consequently, utility functions to initialize, copy, swap, free, compare,
>> mutate, and sort those structures won't be shared between OAv1 and OAv2.
>>
>> Finally, the version ID used to identify the storage format of the object
>> attributes is object and backend dependent. This approach allows mixing
>> OAv1 and OAv2 in input objects. Then the deserializer translates the input
>> data to the internal model (currently OAv2, but it could be a more generic
>> one in the future) to perform the merge. In the end, the output format is
>> set by the backend: OAv2 for AArch64, OAv1 for others. The only exception
>> for this is objcopy, which won't change the format of the object attributes,
>> and will preserve the format of the data during the copy.
>> Hopefully, this mechanism will make easy the migration from OAv1 to OAv2 if
>> anyone is interested.
>>
>> [1]: [Design Rationale for Build Attributes for the Arm 64-bit Architecture (AARCH64)]
>>       (https://github.com/ARM-software/abi-aa/blob/eec881270d5e3b23e58a6250640d06ff545ec1fc
>>        /design-documents/buildattr64-rationale.rst)
>> [2]: [Build Attributes for the Arm® 64-bit Architecture (AArch64)](https://github.com
>>        /ARM-software/abi-aa/blob/eec881270d5e3b23e58a6250640d06ff545ec1fc/buildattr64
>>        /buildattr64.rst)
>>
>> Co-Authored-By: Matthieu Longo <matthieu.longo@arm.com>
> 
> Okay with a few small adjustments (see below), and provided you also got
> Arm64 side approval.
> 
>> @@ -683,6 +719,12 @@ bool
>>   _bfd_elf_merge_object_attributes (bfd *ibfd, struct bfd_link_info *info)
>>   {
>>     bfd *obfd = info->output_bfd;
>> +
>> +  /* Set the object attribute version for the output object to the recommended
>> +     value by the backend.  */
>> +  elf_obj_attr_version (obfd)
>> +    = get_elf_backend_data (obfd)->default_obj_attr_version;
>> +
>>     obj_attribute *in_attr;
>>     obj_attribute *out_attr;
>>     int vendor;
> 
> Mixing declarations and statements is now allowed, but I think we shouldn't
> needlessly mix them when functions clearly have the two things separated.
> 

Fixed.

>> @@ -3105,6 +3126,10 @@ extern bfd *_bfd_elf64_bfd_from_remote_memory
>>      int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type))
>>     ATTRIBUTE_HIDDEN;
>>   
>> +extern obj_attr_version_t _bfd_obj_attrs_version_dec (uint8_t)
>> +  ATTRIBUTE_HIDDEN;
>> +extern uint8_t _bfd_obj_attrs_version_enc (obj_attr_version_t)
>> +  ATTRIBUTE_HIDDEN;
>>   extern bfd_vma bfd_elf_obj_attr_size (bfd *);
>>   extern void bfd_elf_set_obj_attr_contents (bfd *, bfd_byte *, bfd_vma);
>>   extern int bfd_elf_get_obj_attr_int (bfd *, obj_attr_vendor_t, obj_attr_tag_t);
>> @@ -3143,6 +3168,36 @@ extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr
>>   extern bool _bfd_elf_read_notes
>>     (bfd *, file_ptr, bfd_size_type, size_t) ATTRIBUTE_HIDDEN;
>>   
>> +extern obj_attr_v2_t *bfd_elf_obj_attr_v2_init (obj_attr_tag_t,
>> +  union obj_attr_value_v2);
> 
> Except for this, ...
> 
>> +extern void _bfd_elf_obj_attr_v2_free (obj_attr_v2_t *, obj_attr_encoding_v2_t);
>> +extern obj_attr_v2_t *_bfd_elf_obj_attr_v2_copy (const obj_attr_v2_t *,
>> +  obj_attr_encoding_v2_t);
>> +extern int _bfd_elf_obj_attr_v2_cmp (const obj_attr_v2_t *,
>> +  const obj_attr_v2_t *);
>> +extern obj_attr_v2_t *
>> +obj_attr_v2_find_by_tag (const obj_attr_subsection_v2_t *, obj_attr_tag_t,
>> +  bool);
> 
> ... by their names these are libbfd-internal functions. In which case they want
> to gain ATTRIBUTE_HIDDEN, just like you have it in the earlier hunk.
> 

Fixed.

>> +LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(obj_attr_subsection_v2_t,
>> +				   obj_attr_v2_t, extern);
>> +LINKED_LIST_MERGE_SORT_PROTOTYPE_(obj_attr_v2_t, extern);
>> +LINKED_LIST_MERGE_SORT_PROTOTYPE(obj_attr_subsection_v2_t,
>> +				 obj_attr_v2_t, extern);
>> +extern obj_attr_subsection_v2_t *_bfd_elf_obj_attr_subsection_v2_init
>> +  (const char*, obj_attr_subsection_scope_v2_t, bool, obj_attr_encoding_v2_t);
>> +extern void _bfd_elf_obj_attr_subsection_v2_free (obj_attr_subsection_v2_t *);
>> +extern obj_attr_subsection_v2_t *_bfd_elf_obj_attr_subsection_v2_copy
>> +  (const obj_attr_subsection_v2_t *);
>> +extern int _bfd_elf_obj_attr_subsection_v2_cmp
>> +  (const obj_attr_subsection_v2_t *, const obj_attr_subsection_v2_t *);
>> +extern obj_attr_subsection_v2_t * obj_attr_subsection_v2_find_by_name
>> +  (obj_attr_subsection_v2_t *, const char *, bool);
> 
> Same here.
> 
> Jan

Fixed.

Matthieu


More information about the Binutils mailing list