On 10.03.2025 18:51, Matthieu Longo wrote:
> --- a/bfd/elf-attrs.c
> +++ b/bfd/elf-attrs.c
> @@ -118,7 +118,51 @@ bfd_elf_obj_attrs_v1_size (bfd *abfd)
> size = vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_PROC);
> size += vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_GNU);
> if (size > 0)
> - size += sizeof(uint8_t); /* <format-version: ‘A’> */
> + size += sizeof(uint8_t); /* <format-version: 'A'> */
> + return size;
> +}
> +
> +/* Return the size of a single attribute. */
> +static bfd_vma
> +obj_attr_v2_size (obj_attr_v2 *attr, obj_attr_encoding_v2 type)
> +{
> + bfd_vma size;
> +
> + size = uleb128_size (attr->tag);
> + if (type == ULEB128)
> + size += uleb128_size (attr->vals.uint_val);
> + if (type == NTBS)
> + size += strlen (attr->vals.string_val) + 1; // +1 for '\0'
> + return size;
> +}
> +
> +/* Return the size of a subsection. */
> +static bfd_vma
> +obj_attr_subsection_v2_size (obj_attr_subsection_v2 *subsec)
> +{
> + bfd_vma size = sizeof(uint32_t); // <uint32: subsection-length>
> + size += strlen (subsec->name) + 1; // NTBS: vendor-name so +1 for '\0'
> + size += 2 * sizeof(uint8_t); // <uint8: optional> <uint8: parameter type>
> + // <attribute>*
Style nit (again here and elsewhere): Style-conforming comments please.
Jan
On 2025-03-11 08:10, Jan Beulich wrote:
> On 10.03.2025 18:51, Matthieu Longo wrote:
>> --- a/bfd/elf-attrs.c
>> +++ b/bfd/elf-attrs.c
>> @@ -118,7 +118,51 @@ bfd_elf_obj_attrs_v1_size (bfd *abfd)
>> size = vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_PROC);
>> size += vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_GNU);
>> if (size > 0)
>> - size += sizeof(uint8_t); /* <format-version: ‘A’> */
>> + size += sizeof(uint8_t); /* <format-version: 'A'> */
>> + return size;
>> +}
>> +
>> +/* Return the size of a single attribute. */
>> +static bfd_vma
>> +obj_attr_v2_size (obj_attr_v2 *attr, obj_attr_encoding_v2 type)
>> +{
>> + bfd_vma size;
>> +
>> + size = uleb128_size (attr->tag);
>> + if (type == ULEB128)
>> + size += uleb128_size (attr->vals.uint_val);
>> + if (type == NTBS)
>> + size += strlen (attr->vals.string_val) + 1; // +1 for '\0'
>> + return size;
>> +}
>> +
>> +/* Return the size of a subsection. */
>> +static bfd_vma
>> +obj_attr_subsection_v2_size (obj_attr_subsection_v2 *subsec)
>> +{
>> + bfd_vma size = sizeof(uint32_t); // <uint32: subsection-length>
>> + size += strlen (subsec->name) + 1; // NTBS: vendor-name so +1 for '\0'
>> + size += 2 * sizeof(uint8_t); // <uint8: optional> <uint8: parameter type>
>> + // <attribute>*
>
> Style nit (again here and elsewhere): Style-conforming comments please.
>
> Jan
Fixed.
@@ -118,7 +118,51 @@ bfd_elf_obj_attrs_v1_size (bfd *abfd)
size = vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_PROC);
size += vendor_obj_attrs_v1_size (abfd, OBJ_ATTR_GNU);
if (size > 0)
- size += sizeof(uint8_t); /* <format-version: ‘A’> */
+ size += sizeof(uint8_t); /* <format-version: 'A'> */
+ return size;
+}
+
+/* Return the size of a single attribute. */
+static bfd_vma
+obj_attr_v2_size (obj_attr_v2 *attr, obj_attr_encoding_v2 type)
+{
+ bfd_vma size;
+
+ size = uleb128_size (attr->tag);
+ if (type == ULEB128)
+ size += uleb128_size (attr->vals.uint_val);
+ if (type == NTBS)
+ size += strlen (attr->vals.string_val) + 1; // +1 for '\0'
+ return size;
+}
+
+/* Return the size of a subsection. */
+static bfd_vma
+obj_attr_subsection_v2_size (obj_attr_subsection_v2 *subsec)
+{
+ bfd_vma size = sizeof(uint32_t); // <uint32: subsection-length>
+ size += strlen (subsec->name) + 1; // NTBS: vendor-name so +1 for '\0'
+ size += 2 * sizeof(uint8_t); // <uint8: optional> <uint8: parameter type>
+ // <attribute>*
+ for (obj_attr_v2 *attr = subsec->first_;
+ attr != NULL;
+ attr = attr->next)
+ size += obj_attr_v2_size (attr, subsec->encoding);
+ return size;
+}
+
+/* Return the size of an build attributes section. */
+static bfd_vma
+vendor_section_obj_attr_v2_size (bfd *abfd)
+{
+ obj_attr_subsection_v2 *subsec = elf_obj_attr_subsections (abfd).first_;
+ if (subsec == NULL)
+ return 0;
+
+ bfd_vma size = sizeof(uint8_t); // <format-version: 'A'>
+ // [ <uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data> ]*
+ for (; subsec != NULL; subsec = subsec->next)
+ size += obj_attr_subsection_v2_size (subsec);
return size;
}
@@ -126,7 +170,9 @@ bfd_elf_obj_attrs_v1_size (bfd *abfd)
bfd_vma
bfd_elf_obj_attr_size (bfd *abfd)
{
- return bfd_elf_obj_attrs_v1_size (abfd);
+ return (get_elf_backend_data (abfd)->obj_attrs_version == 2)
+ ? vendor_section_obj_attr_v2_size (abfd)
+ : bfd_elf_obj_attrs_v1_size (abfd);
}
/* Write VAL in uleb128 format to P, returning a pointer to the
@@ -213,7 +259,7 @@ write_obj_attr_section_v1 (bfd *abfd, bfd_byte *buffer, bfd_vma size)
{
bfd_byte *p = buffer;
- /* <format-version: ‘A’> */
+ /* <format-version: 'A'> */
*(p++) = 'A';
for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor)
@@ -228,11 +274,112 @@ write_obj_attr_section_v1 (bfd *abfd, bfd_byte *buffer, bfd_vma size)
BFD_ASSERT (p <= buffer + size);
}
+static bfd_byte *
+write_obj_attr_v2 (bfd_byte *p, obj_attr_v2* attr, obj_attr_encoding_v2 type)
+{
+ p = write_uleb128 (p, attr->tag);
+ switch (type)
+ {
+ case ULEB128:
+ {
+ p = write_uleb128 (p, attr->vals.uint_val);
+ }
+ break;
+ case NTBS:
+ {
+ size_t len = strlen (attr->vals.string_val) + 1; // +1 for '\0'
+ memcpy (p, attr->vals.string_val, len);
+ p += len;
+ }
+ break;
+ }
+ return p;
+}
+
+static bfd_byte *
+write_obj_attr_subsection_v2 (bfd *abfd,
+ obj_attr_subsection_v2* subsec,
+ bfd_byte *p)
+{
+ // <uint32: subsection-length>
+ bfd_vma subsec_size = obj_attr_subsection_v2_size (subsec);
+ bfd_put_32 (abfd, subsec_size, p);
+ p += sizeof (uint32_t);
+
+ // NTBS: vendor-name
+ size_t vendor_name_size = strlen (subsec->name) + 1; // +1 for '\0'
+ memcpy (p, subsec->name, vendor_name_size);
+ p += vendor_name_size;
+
+ // -- <bytes: vendor-data> --
+ // <uint8: optional>
+ p = write_uleb128 (p, subsec->optional);
+ // <uint8: parameter type>
+ p = write_uleb128 (p, subsec->encoding);
+ // <attribute>*
+ for (obj_attr_v2 *attr = subsec->first_; attr != NULL; attr = attr->next)
+ p = write_obj_attr_v2 (p, attr, subsec->encoding);
+ return p;
+}
+
+static void
+obj_attr_subsection_v2_sort (obj_attr_subsection_list *plist)
+{
+ for (obj_attr_subsection_v2 *subsec = plist->first_;
+ subsec != NULL;
+ subsec = subsec->next)
+ LINKED_LIST_MERGE_SORT(obj_attr_v2) (subsec, _bfd_elf_obj_attr_v2_cmp);
+
+ LINKED_LIST_MERGE_SORT(obj_attr_subsection_v2)
+ (plist, _bfd_elf_obj_attr_subsection_v2_cmp);
+}
+
+static void
+write_obj_attr_section_v2 (bfd *abfd, bfd_byte *buffer, bfd_vma size)
+{
+ bfd_vma section_size = vendor_section_obj_attr_v2_size (abfd);
+ if (section_size == 0)
+ return;
+
+ bfd_byte *p = buffer;
+
+ // <format-version: 'A'>
+ *(p++) = 'A';
+
+ // [ <uint32: subsection-length> NTBS: vendor-name <bytes: vendor-data> ]*
+ for (obj_attr_subsection_v2* subsec = elf_obj_attr_subsections (abfd).first_;
+ subsec != NULL;
+ subsec = subsec->next)
+ p = write_obj_attr_subsection_v2 (abfd, subsec, p);
+
+ /* We didn't overrun the buffer. */
+ BFD_ASSERT (p <= buffer + size);
+ /* We wrote as many data as it was computed by
+ vendor_section_obj_attr_using_subsections_size(). */
+ BFD_ASSERT (section_size == (long unsigned int)(p - buffer));
+}
+
+/* Finalize the content of object attributes before writing. */
+void
+bfd_elf_obj_attr_finalize_content (bfd *abfd)
+{
+ if (get_elf_backend_data (abfd)->obj_attrs_version == 2)
+ /* Before dumping the data, sort subsections in alphabetical order, and
+ attributes according to their tag in numerical order. This is useful
+ for diagnostic tools so that they dump the same output even if the
+ subsections or their attributes were not declared in the same order in
+ different files. */
+ obj_attr_subsection_v2_sort (&elf_obj_attr_subsections (abfd));
+}
+
/* Write the contents of the object attributes section to CONTENTS. */
void
bfd_elf_set_obj_attr_contents (bfd *abfd, bfd_byte *buffer, bfd_vma size)
{
- write_obj_attr_section_v1 (abfd, buffer, size);
+ if (get_elf_backend_data (abfd)->obj_attrs_version == 2)
+ write_obj_attr_section_v2 (abfd, buffer, size);
+ else
+ write_obj_attr_section_v1 (abfd, buffer, size);
}
/* Allocate/find an object attribute. */
@@ -3064,6 +3064,7 @@ extern bfd *_bfd_elf64_bfd_from_remote_memory
int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type));
extern bfd_vma bfd_elf_obj_attr_size (bfd *);
+extern void bfd_elf_obj_attr_finalize_content (bfd *);
extern void bfd_elf_set_obj_attr_contents (bfd *, bfd_byte *, bfd_vma);
extern int bfd_elf_get_obj_attr_int (bfd *, int, unsigned int);
extern obj_attribute *bfd_elf_add_obj_attr_int
@@ -1939,6 +1939,8 @@ create_obj_attrs_section (void)
bfd_set_section_flags (s, SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA);
frag_now_fix ();
char *p = frag_more (size);
+
+ bfd_elf_obj_attr_finalize_content (stdoutput);
bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size);
subsegs_finish_section (s);