[PATCH v2 10/28] Object Attributes v2: new abstractions for subsections and attributes
Matthieu Longo
matthieu.longo@arm.com
Fri May 2 10:32:42 GMT 2025
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 key-value pair:
- key: a tag id, 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>
---
bfd/Makefile.am | 2 +-
bfd/Makefile.in | 2 +-
bfd/elf-attrs.c | 205 +++++++++++++++++++++++++++++++++++++++--
bfd/elf-attrs.h | 117 +++++++++++++++++++++++
bfd/elf-bfd.h | 53 ++++++++++-
bfd/elfnn-aarch64.c | 21 +++++
bfd/elfxx-aarch64.c | 16 ++++
bfd/elfxx-aarch64.h | 6 ++
bfd/elfxx-target.h | 16 +++-
bfd/po/SRC-POTFILES.in | 1 +
gas/output-file.c | 2 +
11 files changed, 426 insertions(+), 15 deletions(-)
create mode 100644 bfd/elf-attrs.h
diff --git a/bfd/Makefile.am b/bfd/Makefile.am
index 4987ac9cccc..0339db6b2b6 100644
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -707,7 +707,7 @@ SOURCE_HFILES = \
elf32-metag.h elf32-nds32.h elf32-ppc.h \
elf32-rx.h elf32-score.h elf32-sh-relocs.h elf32-spu.h \
elf32-tic6x.h elf32-tilegx.h elf32-tilepro.h elf32-v850.h \
- elf64-hppa.h elf64-ppc.h elf64-tilegx.h \
+ elf64-hppa.h elf64-ppc.h elf64-tilegx.h elf-attrs.h \
elf-bfd.h elfcode.h elfcore.h elf-hppa.h elf-linker-x86.h \
elf-linux-core.h elf-nacl.h elf-s390.h elf-vxworks.h \
elfxx-aarch64.h elfxx-ia64.h elfxx-mips.h elfxx-riscv.h \
diff --git a/bfd/Makefile.in b/bfd/Makefile.in
index 8a670ad1d05..61f6b205bb6 100644
--- a/bfd/Makefile.in
+++ b/bfd/Makefile.in
@@ -1170,7 +1170,7 @@ SOURCE_HFILES = \
elf32-metag.h elf32-nds32.h elf32-ppc.h \
elf32-rx.h elf32-score.h elf32-sh-relocs.h elf32-spu.h \
elf32-tic6x.h elf32-tilegx.h elf32-tilepro.h elf32-v850.h \
- elf64-hppa.h elf64-ppc.h elf64-tilegx.h \
+ elf64-hppa.h elf64-ppc.h elf64-tilegx.h elf-attrs.h \
elf-bfd.h elfcode.h elfcore.h elf-hppa.h elf-linker-x86.h \
elf-linux-core.h elf-nacl.h elf-s390.h elf-vxworks.h \
elfxx-aarch64.h elfxx-ia64.h elfxx-mips.h elfxx-riscv.h \
diff --git a/bfd/elf-attrs.c b/bfd/elf-attrs.c
index 0f9b2c4d1b5..7622070ff03 100644
--- a/bfd/elf-attrs.c
+++ b/bfd/elf-attrs.c
@@ -20,10 +20,27 @@
#include "sysdep.h"
#include "bfd.h"
+#include "doubly-linked-list.h"
#include "libiberty.h"
#include "libbfd.h"
#include "elf-bfd.h"
+obj_attr_version_t
+_bfd_obj_attrs_version_dec (uint8_t encoded_version)
+{
+ if (encoded_version == 'A')
+ return OBJ_ATTR_V1;
+ return OBJ_ATTR_VERSION_UNSUPPORTED;
+}
+
+uint8_t
+_bfd_obj_attrs_version_enc (obj_attr_version_t version)
+{
+ if (version == OBJ_ATTR_V1)
+ return 'A';
+ abort ();
+}
+
/* Return the number of bytes needed by I in uleb128 format. */
static uint32_t
uleb128_size (uint32_t i)
@@ -212,8 +229,9 @@ write_obj_attr_section_v1 (bfd *abfd, bfd_byte *buffer, bfd_vma size)
{
bfd_byte *p = buffer;
- /* <format-version: 'A'> */
- *(p++) = 'A';
+ const struct elf_backend_data *be = get_elf_backend_data (abfd);
+ /* <uint8: format-version> */
+ *(p++) = be->obj_attrs_version_enc (elf_obj_attr_version (abfd));
for (int vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; ++vendor)
{
@@ -407,6 +425,12 @@ _bfd_elf_copy_obj_attributes (bfd *ibfd, bfd *obfd)
|| bfd_get_flavour (obfd) != bfd_target_elf_flavour)
return;
+ obj_attr_version_t version = elf_obj_attr_version (ibfd);
+ elf_obj_attr_version (obfd) = version;
+
+ if (version == OBJ_ATTR_VERSION_NONE)
+ return;
+
for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++)
{
in_attr
@@ -476,6 +500,7 @@ gnu_obj_attrs_arg_type (unsigned int tag)
int
_bfd_elf_obj_attrs_arg_type (bfd *abfd, obj_attr_vendor vendor, uint32_t tag)
{
+ /* This function should only be called for object attributes version 1. */
switch (vendor)
{
case OBJ_ATTR_PROC:
@@ -613,6 +638,8 @@ bfd_elf_parse_attr_section_v1 (bfd *abfd, bfd_byte *p, bfd_byte *p_end)
void
_bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
{
+ elf_obj_attr_version (abfd) = OBJ_ATTR_VERSION_NONE;
+
/* PR 17512: file: 2844a11d. */
if (hdr->sh_size == 0)
return;
@@ -635,18 +662,20 @@ _bfd_elf_parse_attributes (bfd *abfd, Elf_Internal_Shdr * hdr)
unsigned char *cursor = data;
- /* The first character is the version of the attributes.
- Currently only version 'A' is recognised here. */
- if (*cursor != 'A')
+ /* The first character is the version of the attributes. */
+ obj_attr_version_t version
+ = get_elf_backend_data (abfd)->obj_attrs_version_dec (*cursor);
+ if (version == OBJ_ATTR_VERSION_UNSUPPORTED || version > OBJ_ATTR_MAX_V)
{
- _bfd_error_handler (_("%pB: error: unknown attributes version '%c'(%d) "
- "- expecting 'A'\n"), abfd, *cursor, *cursor);
+ _bfd_error_handler (_("%pB: error: unknown attributes version '%c'(%d)\n"),
+ abfd, *cursor, *cursor);
bfd_set_error (bfd_error_wrong_format);
goto free_data;
}
++cursor;
+ elf_obj_attr_version (abfd) = version;
bfd_elf_parse_attr_section_v1 (abfd, cursor, data + hdr->sh_size);
free_data:
@@ -818,8 +847,166 @@ _bfd_elf_merge_unknown_attribute_list (bfd *ibfd, bfd *obfd)
return result;
}
-bool _bfd_elf_write_section_build_attributes (bfd *abfd,
- struct bfd_link_info *info ATTRIBUTE_UNUSED)
+obj_attr_v2 *
+_bfd_elf_obj_attr_v2_init (uint32_t tag,
+ union obj_attr_value_v2 vals)
+{
+ obj_attr_v2 *attr = (obj_attr_v2 *) malloc (sizeof (*attr));
+ memset (attr, 0, sizeof (*attr));
+ attr->tag = tag;
+ attr->vals = vals;
+ return attr;
+}
+
+void
+_bfd_elf_obj_attr_v2_free (obj_attr_v2 *attr, obj_attr_encoding_v2 encoding)
+{
+ if (encoding == OA_ENC_NTBS)
+ free ((char *) attr->vals.string_val);
+ free (attr);
+}
+
+obj_attr_v2 *
+_bfd_elf_obj_attr_v2_copy (obj_attr_v2 *other,
+ obj_attr_encoding_v2 encoding)
+{
+ union obj_attr_value_v2 vals;
+ if (encoding == OA_ENC_NTBS)
+ vals.string_val =
+ (other->vals.string_val != NULL)
+ ? strdup (other->vals.string_val)
+ : NULL;
+ else
+ vals.uint_val = other->vals.uint_val;
+
+ return _bfd_elf_obj_attr_v2_init (other->tag, vals);
+}
+
+int
+_bfd_elf_obj_attr_v2_cmp (const obj_attr_v2 *a1, const obj_attr_v2 *a2)
+{
+ if (a1->tag < a2->tag)
+ return -1;
+ else if (a1->tag > a2->tag)
+ return 1;
+ else
+ return 0;
+}
+
+/* Find the object attribute matching the given tag (object attributes v2 only).
+ Note: The parameter 'sorted' specifies whether the given list is sorted or
+ not. If the list of attributes is sorted, the linear search stops as soon as
+ it finds an attribute with a greater tag. */
+obj_attr_v2 *
+obj_attr_v2_find_by_tag (const obj_attr_subsection_v2 *subsec,
+ uint32_t tag,
+ bool sorted)
+{
+ for (obj_attr_v2 *attr = subsec->first_;
+ attr != NULL;
+ attr = attr->next)
+ if (attr->tag == tag)
+ return attr;
+ else if (sorted && attr->tag > tag)
+ break;
+ return NULL;
+}
+
+LINKED_LIST_MUTATIVE_OPS_DECL(obj_attr_subsection_v2, obj_attr_v2, /* public */)
+LINKED_LIST_MERGE_SORT_DECL(obj_attr_subsection_v2, obj_attr_v2, /* public */)
+
+obj_attr_subsection_v2 *
+_bfd_elf_obj_attr_subsection_v2_init (const char *name,
+ obj_attr_subsection_scope_v2 scope,
+ bool optional,
+ obj_attr_encoding_v2 encoding)
+{
+ obj_attr_subsection_v2 *subsection = (obj_attr_subsection_v2 *)
+ malloc (sizeof (*subsection));
+ memset (subsection, 0, sizeof (*subsection));
+ subsection->name = name;
+ subsection->scope = scope;
+ subsection->optional = optional;
+ subsection->encoding = encoding;
+ return subsection;
+}
+
+void
+_bfd_elf_obj_attr_subsection_v2_free (obj_attr_subsection_v2 *subsec)
+{
+ for (obj_attr_v2 *attr = subsec->first_; attr != NULL; attr = attr->next)
+ _bfd_elf_obj_attr_v2_free (attr, subsec->encoding);
+ free (subsec);
+}
+
+obj_attr_subsection_v2 *
+_bfd_elf_obj_attr_subsection_v2_copy (obj_attr_subsection_v2 const *other)
+{
+ obj_attr_subsection_v2 *new_subsec =
+ _bfd_elf_obj_attr_subsection_v2_init (other->name, other->scope,
+ other->optional, other->encoding);
+ for (obj_attr_v2* attr = other->first_;
+ attr != NULL;
+ attr = attr->next)
+ {
+ obj_attr_v2* new_attr = _bfd_elf_obj_attr_v2_copy (attr, other->encoding);
+ LINKED_LIST_APPEND(obj_attr_v2) (new_subsec, new_attr);
+ }
+ return new_subsec;
+}
+
+int
+_bfd_elf_obj_attr_subsection_v2_cmp (const obj_attr_subsection_v2 *s1,
+ const obj_attr_subsection_v2 *s2)
+{
+ int res = strcmp (s1->name, s2->name);
+ if (res != 0)
+ return res;
+
+ /* Giving to the optionality a higher priority than the encoding is
+ artificial. Its only purpose is to give a strict total order to
+ a collection of subsections. */
+ if (!s1->optional && s2->optional)
+ return -1;
+ else if (s1->optional && !s2->optional)
+ return 1;
+
+ if (s1->encoding < s2->encoding)
+ return -1;
+ else if (s1->encoding > s2->encoding)
+ return 1;
+
+ return 0;
+}
+
+/* Find the subsection matching the given name.
+ Note: The parameter sorted specified whether the given list is sorted or not.
+ If the list of subsections is sorted, the linear search stops as soon as it
+ finds a subsection name with a greater order. */
+obj_attr_subsection_v2 *
+obj_attr_subsection_v2_find_by_name (obj_attr_subsection_v2 *first,
+ const char *name,
+ bool sorted)
+{
+ for (obj_attr_subsection_v2 *s = first;
+ s != NULL;
+ s = s->next)
+ {
+ int cmp = strcmp (s->name, name);
+ if (cmp == 0)
+ return s;
+ else if (sorted && cmp > 0)
+ break;
+ }
+ return NULL;
+}
+
+LINKED_LIST_MUTATIVE_OPS_DECL(obj_attr_subsection_list, obj_attr_subsection_v2, /* public */)
+LINKED_LIST_MERGE_SORT_DECL(obj_attr_subsection_list, obj_attr_subsection_v2, /* public */)
+
+bool
+_bfd_elf_write_section_build_attributes (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
asection *sec = elf_obj_build_attributes (abfd);
diff --git a/bfd/elf-attrs.h b/bfd/elf-attrs.h
new file mode 100644
index 00000000000..ae3a164ae40
--- /dev/null
+++ b/bfd/elf-attrs.h
@@ -0,0 +1,117 @@
+/* ELF attributes support (based on ARM EABI attributes).
+ Copyright (C) 2025 Free Software Foundation, Inc.
+ Written by Cygnus Support.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#pragma once
+
+#include <stdint.h>
+
+typedef enum obj_attr_version_t {
+ OBJ_ATTR_VERSION_NONE = 0,
+ OBJ_ATTR_VERSION_UNSUPPORTED,
+ OBJ_ATTR_V1,
+ OBJ_ATTR_V2,
+ OBJ_ATTR_MAX_V = OBJ_ATTR_V2,
+} obj_attr_version_t;
+
+/* --------------------
+ Object attributes v2
+ -------------------- */
+
+typedef enum obj_attr_encoding_v2
+{
+ OA_ENC_UNSET = 0,
+ OA_ENC_ULEB128 = 1,
+ OA_ENC_NTBS = 2,
+ OA_ENC_MAX = OA_ENC_NTBS,
+} obj_attr_encoding_v2;
+
+#define obj_attr_encoding_v2_from_u8(value) \
+ ((enum obj_attr_encoding_v2) (value + 1))
+#define obj_attr_encoding_v2_to_u8(value) \
+ ((uint8_t) (value - 1))
+
+typedef union obj_attr_value_v2 {
+ uint32_t uint_val;
+ const char* string_val;
+} obj_attr_value_v2;
+
+typedef struct obj_attr_v2 {
+ /* The name/tag of an attribute. */
+ uint32_t tag;
+
+ /* The value assigned to an attribute, can be ULEB128 or NTBS. */
+ union obj_attr_value_v2 vals;
+
+ /* The next attribute in the list or NULL. */
+ struct obj_attr_v2 *next;
+
+ /* The previous attribute in the list or NULL. */
+ struct obj_attr_v2 *prev;
+
+} obj_attr_v2;
+
+typedef enum obj_attr_subsection_scope_v2
+{
+ OA_SUBSEC_PUBLIC = 0,
+ OA_SUBSEC_PRIVATE = 1,
+} obj_attr_subsection_scope_v2;
+
+typedef struct obj_attr_subsection_v2 {
+ /* The name of the subsection. */
+ const char *name;
+
+ /* The scope of the subsection. */
+ obj_attr_subsection_scope_v2 scope;
+
+ /* Is this subsection optional ? Can it be skipped ? */
+ bool optional;
+
+ /* The value encoding of attributes in this subsection. */
+ obj_attr_encoding_v2 encoding;
+
+ /* The size of the list. */
+ uint32_t size;
+
+ /* The next subsection in the list, or NULL. */
+ struct obj_attr_subsection_v2 *next;
+
+ /* The previous subsection in the list, or NULL. */
+ struct obj_attr_subsection_v2 *prev;
+
+ /* A pointer to the first node of the list. */
+ struct obj_attr_v2 *first_;
+
+ /* A pointer to the last node of the list. */
+ struct obj_attr_v2 *last_;
+
+} obj_attr_subsection_v2;
+
+typedef struct obj_attr_subsection_list
+{
+ /* A pointer to the first node of the list. */
+ obj_attr_subsection_v2 *first_;
+
+ /* A pointer to the last node of the list. */
+ obj_attr_subsection_v2 *last_;
+
+ /* The size of the list. */
+ uint32_t size;
+} obj_attr_subsection_list;
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index d528db07a0c..591eed5598f 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -24,9 +24,11 @@
#include <stdlib.h>
+#include "doubly-linked-list.h"
#include "elf/common.h"
#include "elf/external.h"
#include "elf/internal.h"
+#include "elf-attrs.h"
#include "bfdlink.h"
#ifndef ENABLE_CHECKING
@@ -1630,13 +1632,22 @@ struct elf_backend_data
/* The section name to use for a processor-standard attributes section. */
const char *obj_attrs_section;
- /* Return 1, 2 or 3 to indicate what type of arguments a
- processor-specific tag takes. */
+ /* Return 1, 2 or 3 to indicate what type of arguments a tag takes. */
int (*obj_attrs_arg_type) (uint32_t);
/* The section type to use for an attributes section. */
unsigned int obj_attrs_section_type;
+ /* The preferred version of object attributes for the output object. */
+ obj_attr_version_t default_obj_attr_version;
+
+ /* Decode the object attributes version from the version number encoded in
+ the input object. */
+ obj_attr_version_t (*obj_attrs_version_dec) (uint8_t);
+
+ /* Encode the object attributes version into the output object. */
+ uint8_t (*obj_attrs_version_enc) (obj_attr_version_t);
+
/* This function determines the order in which any attributes are
written. It must be defined for input in the range
LEAST_KNOWN_OBJ_ATTRIBUTE..NUM_KNOWN_OBJ_ATTRIBUTES-1 (this range
@@ -2159,9 +2170,19 @@ struct elf_obj_tdata
after all input GNU properties are merged for output. */
elf_property_list *properties;
+ /* The version of object attributes for this object.
+ For an input object, the format version used to store the data.
+ For an output object, the targeted format version. */
+ obj_attr_version_t obj_attr_version;
+
obj_attribute known_obj_attributes[2][NUM_KNOWN_OBJ_ATTRIBUTES];
obj_attribute_list *other_obj_attributes[2];
+ /* Object attributes v2: attributes of the same category are stored inside
+ the same subsection. A subsection can only hold attributes with the same
+ data type. */
+ obj_attr_subsection_list obj_attr_subsections;
+
/* Linked-list containing information about every Systemtap section
found in the object file. Each section corresponds to one entry
in the list. */
@@ -2249,12 +2270,14 @@ struct elf_obj_tdata
#define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
#define elf_flags_init(bfd) (elf_tdata(bfd) -> o->flags_init)
#define elf_use_dt_symtab_p(bfd) (elf_tdata(bfd) -> dt_symtab_count != 0)
+#define elf_obj_attr_version(bfd) (elf_tdata (bfd) -> obj_attr_version)
#define elf_known_obj_attributes(bfd) (elf_tdata (bfd) -> known_obj_attributes)
#define elf_other_obj_attributes(bfd) (elf_tdata (bfd) -> other_obj_attributes)
#define elf_known_obj_attributes_proc(bfd) \
(elf_known_obj_attributes (bfd) [OBJ_ATTR_PROC])
#define elf_other_obj_attributes_proc(bfd) \
(elf_other_obj_attributes (bfd) [OBJ_ATTR_PROC])
+#define elf_obj_attr_subsections(bfd) (elf_tdata (bfd) -> obj_attr_subsections)
#define elf_properties(bfd) (elf_tdata (bfd) -> properties)
#define elf_has_no_copy_on_protected(bfd) \
(elf_tdata(bfd) -> has_no_copy_on_protected)
@@ -3055,6 +3078,8 @@ extern bfd *_bfd_elf64_bfd_from_remote_memory
(bfd *templ, bfd_vma ehdr_vma, bfd_size_type size, bfd_vma *loadbasep,
int (*target_read_memory) (bfd_vma, bfd_byte *, bfd_size_type));
+extern obj_attr_version_t _bfd_obj_attrs_version_dec (uint8_t);
+extern uint8_t _bfd_obj_attrs_version_enc (obj_attr_version_t);
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 *, int, unsigned int);
@@ -3085,6 +3110,30 @@ extern bool _bfd_elf_merge_unknown_attribute_list (bfd *, bfd *);
extern Elf_Internal_Shdr *_bfd_elf_single_rel_hdr (asection *sec);
extern bool elf_read_notes (bfd *, file_ptr, bfd_size_type, size_t);
+extern obj_attr_v2 *_bfd_elf_obj_attr_v2_init (unsigned int,
+ union obj_attr_value_v2);
+extern void _bfd_elf_obj_attr_v2_free (obj_attr_v2 *, obj_attr_encoding_v2);
+extern obj_attr_v2 *_bfd_elf_obj_attr_v2_copy (obj_attr_v2 *,
+ obj_attr_encoding_v2);
+extern int _bfd_elf_obj_attr_v2_cmp (const obj_attr_v2 *, const obj_attr_v2 *);
+extern obj_attr_v2 *
+obj_attr_v2_find_by_tag (const obj_attr_subsection_v2 *, uint32_t, bool);
+LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(obj_attr_subsection_v2, obj_attr_v2, extern);
+_LINKED_LIST_MERGE_SORT_PROTOTYPE(obj_attr_v2, extern);
+LINKED_LIST_MERGE_SORT_PROTOTYPE(obj_attr_subsection_v2, obj_attr_v2, extern);
+extern obj_attr_subsection_v2 *_bfd_elf_obj_attr_subsection_v2_init (const char*,
+ obj_attr_subsection_scope_v2, bool, obj_attr_encoding_v2);
+extern void _bfd_elf_obj_attr_subsection_v2_free (obj_attr_subsection_v2 *);
+extern obj_attr_subsection_v2 *_bfd_elf_obj_attr_subsection_v2_copy
+ (obj_attr_subsection_v2 const*);
+extern int _bfd_elf_obj_attr_subsection_v2_cmp (const obj_attr_subsection_v2 *,
+ const obj_attr_subsection_v2 *s2);
+extern obj_attr_subsection_v2 * obj_attr_subsection_v2_find_by_name
+ (obj_attr_subsection_v2 *, const char *, bool);
+LINKED_LIST_MUTATIVE_OPS_PROTOTYPE(obj_attr_subsection_list, obj_attr_subsection_v2, extern);
+_LINKED_LIST_MERGE_SORT_PROTOTYPE(obj_attr_subsection_v2, extern);
+LINKED_LIST_MERGE_SORT_PROTOTYPE(obj_attr_subsection_list, obj_attr_subsection_v2, extern);
+
extern bool _bfd_elf_parse_gnu_properties
(bfd *, Elf_Internal_Note *);
extern elf_property_list * _bfd_elf_find_property
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 548da1f8b30..ed79e127d07 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -10760,8 +10760,29 @@ const struct elf_size_info elfNN_aarch64_size_info =
#define elf_backend_extern_protected_data 0
#define elf_backend_hash_symbol elf_aarch64_hash_symbol
+/* elf_backend_obj_attrs_vendor is not used in the same way as AArch32 with
+ OAv1. The original use for OAv1 is replaced by the concept of subsections,
+ each one having its own name defined by the assembly directive
+ "aeabi_subsection". In OAv2, obj_attrs_vendor represents the vendor prefix,
+ which if present, makes a subsection public, or private otherwise. */
+#undef elf_backend_obj_attrs_vendor
+#define elf_backend_obj_attrs_vendor "aeabi"
#undef elf_backend_obj_attrs_section
#define elf_backend_obj_attrs_section SEC_AARCH64_ATTRIBUTES
+/* elf_backend_obj_attrs_arg_type is unused as the type of an attribute is
+ determined by looking up at the current subsection, not the value of the
+ tag. */
+#define elf_backend_obj_attrs_arg_type NULL
+#undef elf_backend_obj_attrs_section_type
+#define elf_backend_obj_attrs_section_type SHT_AARCH64_ATTRIBUTES
+#undef elf_backend_default_obj_attr_version
+#define elf_backend_default_obj_attr_version OBJ_ATTR_V2
+#undef elf_backend_obj_attrs_version_dec
+#define elf_backend_obj_attrs_version_dec \
+ _bfd_aarch64_obj_attrs_version_dec
+#undef elf_backend_obj_attrs_version_enc
+#define elf_backend_obj_attrs_version_enc \
+ _bfd_aarch64_obj_attrs_version_enc
#include "elfNN-target.h"
diff --git a/bfd/elfxx-aarch64.c b/bfd/elfxx-aarch64.c
index 551f74e3373..d5f98cac27f 100644
--- a/bfd/elfxx-aarch64.c
+++ b/bfd/elfxx-aarch64.c
@@ -868,6 +868,22 @@ _bfd_aarch64_elf_check_gnu_properties_linked_dynamic_objects (
pbfd);
}
+obj_attr_version_t
+_bfd_aarch64_obj_attrs_version_dec (uint8_t encoded_version)
+{
+ if (encoded_version == 'A')
+ return OBJ_ATTR_V2;
+ return OBJ_ATTR_VERSION_UNSUPPORTED;
+}
+
+uint8_t
+_bfd_aarch64_obj_attrs_version_enc (obj_attr_version_t version)
+{
+ if (version == OBJ_ATTR_V2)
+ return 'A';
+ abort ();
+}
+
/* Find the first input bfd with GNU property and merge it with GPROP. If no
such input is found, add it to a new section at the last input. Update
GPROP accordingly. */
diff --git a/bfd/elfxx-aarch64.h b/bfd/elfxx-aarch64.h
index 506f4a93c9d..a98eef1e66b 100644
--- a/bfd/elfxx-aarch64.h
+++ b/bfd/elfxx-aarch64.h
@@ -209,6 +209,12 @@ _bfd_aarch64_elf_write_core_note (bfd *, char *, int *, int, ...);
#define elf_backend_grok_psinfo _bfd_aarch64_elf_grok_psinfo
#define elf_backend_write_core_note _bfd_aarch64_elf_write_core_note
+extern obj_attr_version_t
+_bfd_aarch64_obj_attrs_version_dec (uint8_t);
+
+extern uint8_t
+_bfd_aarch64_obj_attrs_version_enc (obj_attr_version_t);
+
extern bfd *
_bfd_aarch64_elf_link_setup_gnu_properties (struct bfd_link_info *);
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index 625243cac94..738fd512169 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -554,7 +554,16 @@
#define elf_backend_obj_attrs_arg_type NULL
#endif
#ifndef elf_backend_obj_attrs_section_type
-#define elf_backend_obj_attrs_section_type SHT_GNU_ATTRIBUTES
+#define elf_backend_obj_attrs_section_type SHT_GNU_ATTRIBUTES
+#endif
+#ifndef elf_backend_default_obj_attr_version
+#define elf_backend_default_obj_attr_version OBJ_ATTR_V1
+#endif
+#ifndef elf_backend_obj_attrs_version_dec
+#define elf_backend_obj_attrs_version_dec _bfd_obj_attrs_version_dec
+#endif
+#ifndef elf_backend_obj_attrs_version_enc
+#define elf_backend_obj_attrs_version_enc _bfd_obj_attrs_version_enc
#endif
#ifndef elf_backend_obj_attrs_order
#define elf_backend_obj_attrs_order NULL
@@ -808,7 +817,7 @@
#ifndef elf_backend_symbol_section_index
#define elf_backend_symbol_section_index NULL
#endif
-
+
#ifndef elf_match_priority
#define elf_match_priority \
(ELF_ARCH == bfd_arch_unknown ? 2 : ELF_OSABI == ELFOSABI_NONE ? 1 : 0)
@@ -934,6 +943,9 @@ static const struct elf_backend_data elfNN_bed =
elf_backend_obj_attrs_section,
elf_backend_obj_attrs_arg_type,
elf_backend_obj_attrs_section_type,
+ elf_backend_default_obj_attr_version,
+ elf_backend_obj_attrs_version_dec,
+ elf_backend_obj_attrs_version_enc,
elf_backend_obj_attrs_order,
elf_backend_obj_attrs_handle_unknown,
elf_backend_parse_gnu_properties,
diff --git a/bfd/po/SRC-POTFILES.in b/bfd/po/SRC-POTFILES.in
index 54b078b8295..4b8ccfbe2c8 100644
--- a/bfd/po/SRC-POTFILES.in
+++ b/bfd/po/SRC-POTFILES.in
@@ -132,6 +132,7 @@ ecoff.c
ecofflink.c
ecoffswap.h
elf-attrs.c
+elf-attrs.h
elf-bfd.h
elf-eh-frame.c
elf-hppa.h
diff --git a/gas/output-file.c b/gas/output-file.c
index 5cb37f109d3..60ba7c562a0 100644
--- a/gas/output-file.c
+++ b/gas/output-file.c
@@ -50,6 +50,8 @@ output_file_create (const char *name)
bfd_set_arch_mach (stdoutput, TARGET_ARCH, TARGET_MACH);
if (flag_traditional_format)
stdoutput->flags |= BFD_TRADITIONAL_FORMAT;
+ elf_obj_attr_version (stdoutput)
+ = get_elf_backend_data (stdoutput)->default_obj_attr_version;
}
static void
--
2.49.0
More information about the Binutils
mailing list