From patchwork Thu Jul 2 17:27:46 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Georg-Johann Lay X-Patchwork-Id: 138345 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 25F5E4BA23C7 for ; Thu, 2 Jul 2026 17:28:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 25F5E4BA23C7 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1783013310; bh=+VlYy9GnmD5NgxymuVKnxwO2vNNQLRz8D0Gp8SyygSI=; h=Date:To:Cc:Subject:List-Id:List-Unsubscribe:List-Archive: List-Post:List-Help:List-Subscribe:From:Reply-To:From; b=h2jjsYUHEA3+BX54Cr+n61aldbk1uLqnJo5fyWd/9h6AOaMTuWfsCE/d6vH9OWTWV 8k0XJZXerSd0OpgwcI09iCwU7/bDFIcMZTwgPUfHzDNLMMmLPStR4aEKQKdL9Aqp67 ozdEmj+T2NCdQJ76P9TFJQ2npOPEdCn1v/JxSfzE= X-Original-To: binutils@sourceware.org Delivered-To: binutils@sourceware.org Received: from mo4-p00-ob.smtp.rzone.de (mo4-p00-ob.smtp.rzone.de [85.215.255.24]) by sourceware.org (Postfix) with ESMTPS id E31084BA2E07 for ; Thu, 2 Jul 2026 17:27:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E31084BA2E07 ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E31084BA2E07 ARC-Seal: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1783013270; cv=pass; b=pLKQlpGxSn88CjkhAQxiEkLxu4p50Si9Ou70UQwNKXUoV1wLJqsu4ZmvyPCywt30pTkoHmTjK3GvlZTITEgN002GorzOftoZvYXzv5YCe9d6O8A5sHc9SxR84eTiMMPdMWf78nHk2+T3wQR4cIceTO8pNV0VOXFjB8OkLPIY/Gs= ARC-Message-Signature: i=2; a=rsa-sha256; d=sourceware.org; s=key; t=1783013270; c=relaxed/simple; bh=K4RG2bKitmYPP9a35mFu+pPSpR6uRSZcd+ZgJfrMJaY=; h=DKIM-Signature:DKIM-Signature:Message-ID:Date:MIME-Version:From: To:Subject; b=PO3xlVLcIa0Oc9pB/hqw/5gvOh3P++QMazyKa8Q9JcJSZ4UY8qBQg0iiTrUOCT5Dwco1omX3XNoMdgw53N1cQxz00NcsCtzlRVpqK98omBM6LM+DE0k6uuU8laDcpTWpyiyyJBwn0psCBKsH5qwxUOZjXFIT/NQf1awm/FkaGdw= ARC-Authentication-Results: i=2; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=gjlay.de header.i=@gjlay.de header.a=rsa-sha256 header.s=strato-dkim-0002 header.b=VJdE1IF2; dkim=pass header.d=gjlay.de header.i=@gjlay.de header.a=ed25519-sha256 header.s=strato-dkim-0003 header.b=LDzcJzVk DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E31084BA2E07 ARC-Seal: i=1; a=rsa-sha256; t=1783013267; cv=none; d=strato.com; s=strato-dkim-0002; b=KMlTb08ZDdu2Hp+RRgfjY+Cd/GBM+G+nfEt2gLLsPFTgqgIlEosi6OGltdjgjMAXbV Fqs4L1azzrDMXfCi5gX8iaBeZa7lFAk94ng4ovZgKLolWps7cfRJsNlOFcDhuclziW3U YPuluv6YgRE2FChIPdRYOoEb0ZHIvSqlx6cZyMexH9Sle73IkAf/iX8tyeuCDsN3/u4g IDOwTeBR+g49ac4QHnH0aB4q/e1HlDPHPe+Coktm1NNP7DOWCaUBc/n/iNbbXhQJVmk0 mnPB0XePctYEUE96mQskeR5tQV6WKm20Wniv0yHRDnH/UlxNGWAiZPgY4kYwNgLsJJU9 I5Xg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1783013267; s=strato-dkim-0002; d=strato.com; h=Subject:Cc:To:From:Date:Message-ID:Cc:Date:From:Subject:Sender; bh=+VlYy9GnmD5NgxymuVKnxwO2vNNQLRz8D0Gp8SyygSI=; b=GocnOoaROlArqKO6jF+MymjB+jWzH18a1DqxBCtV7KQP3K0iMH8Y81Y91oJ2noLHq+ 2GfHlZoW/sJzMT5TnZ0ULdc2JYgZvJ9zhxEK7uTfPf0qdtPSiAqvFLw4cfWu9QqLbzOR YzCv74vistNYFmkYKYXJuZ+eU1SCY0uxffnbNeHDCkmsRsmqrSLomwIwcJmb9PV4tH90 7JULIC0JSj/Xds1WCa61EFd303DfwcvruppaVtS0wdIdT8FMhuj8FArSuVToCLlEdIST mKrore2XO5zaviNPmoSWWl93ER9IG6K3LtU3HpDj//qIgquVGHjhp0eGpD+PI3AFlqB5 89Mw== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo00 X-RZG-AUTH: ":LXoWVUeid/7A29J/hMvvT3koxZnKXKoq0dKoR0vdoTJLPTbtkmuxs0lUnBw=" Received: from [192.168.2.102] by smtp.strato.de (RZmta 55.5.6 DYNA|AUTH) with ESMTPSA id x5ee59262HRkHXa (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Thu, 2 Jul 2026 19:27:46 +0200 (CEST) Message-ID: <701a37e4-9249-4c5e-abf5-de05c2cc3bec@gjlay.de> Date: Thu, 2 Jul 2026 19:27:46 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Content-Language: en-US To: binutils@sourceware.org Cc: Denis Chertykov Subject: [patch] AVR: Add support for .gnu_attribute 4 (Tag_GNU_AVR_VTABLE_AS) X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS, TXREP shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Georg-Johann Lay via Binutils From: Georg-Johann Lay Reply-To: Georg-Johann Lay Errors-To: binutils-bounces~patchwork=sourceware.org@sourceware.org The upcoming support for ISO/IEC TR 18037 "Embedded C" named address spaces in G++ would allow to put C++ virtual tables into such an address spaces, see https://gcc.gnu.org/PR69549. The current address space used for vtables is the generic one, which means that RAM is wasted on machines where .rodata is located in RAM. The TARGET_ADDR_SPACE_FOR_ARTIFICIAL_RODATA GCC target hook allows to chose a custom vtable address space. However, in contrast to current user-selectable address spaces, placing vtables in a different address space is an ABI change, so that a means to detect ABI violations is highly appreciated. The feature of choice is .gnu_attribute 4 (Tag_GNU_AVR_VTABLE_AS) which would tag an object file with one of the following values: 0 (Val_GNU_AVR_VTABLE_NONE) for files that neither define nor access vtables. 1 (Val_GNU_AVR_VTABLE_RAM) use the generic address space. 2 (Val_GNU_AVR_VTABLE_FLASH) use the 16-bit address space __flash. 3 (Val_GNU_AVR_VTABLE_FLASH1) use the 16-bit address space __flash1. 4 (Val_GNU_AVR_VTABLE_FLASH2) use the 16-bit address space __flash2. 5 (Val_GNU_AVR_VTABLE_FLASH3) use the 16-bit address space __flash3. 6 (Val_GNU_AVR_VTABLE_FLASH4) use the 16-bit address space __flash4. 7 (Val_GNU_AVR_VTABLE_FLASH5) use the 16-bit address space __flash5. 8 (Val_GNU_AVR_VTABLE_FLASHX) use the 24-bit address space __flashx. A tag value of zero is compatible with all other tag values. Two non-zero tag values are compatible iff they are the same. Unknown tag values are silently accepted an treated just like the values above so as to allow for compatibility with future extensions. Ok for trunk? Johann --- PR ld/34305 include/ * elf/avr.h (libiberty.h): Include for ARRAY_SIZE. (Tag_GNU_AVR_VTABLE_AS = 4): New enum. (Val_GNU_AVR_VTABLE_NONE, Val_GNU_AVR_VTABLE_RAM) (Val_GNU_AVR_VTABLE_FLASH, Val_GNU_AVR_VTABLE_FLASH1) (Val_GNU_AVR_VTABLE_FLASH2, Val_GNU_AVR_VTABLE_FLASH3) (Val_GNU_AVR_VTABLE_FLASH4, Val_GNU_AVR_VTABLE_FLASH5) (Val_GNU_AVR_VTABLE_FLASHX, Val_GNU_AVR_VTABLE_Sentinel): New enum values for Tag_GNU_AVR_VTABLE_AS. (avr_tag_vtable_as_name): New static function. bfd/ * elf32-avr.h (bfd_avr_elf_merge_private_bfd_data): New proto. * elf32-avr.c (libiberty.h): Include for ARRAY_SIZE. (avr_elf_merge_obj_attributes): New static function. (bfd_avr_elf_merge_private_bfd_data): New function that calls it. (bfd_elf32_bfd_merge_private_bfd_data): Define to bfd_avr_elf_merge_private_bfd_data. gas/ * doc/as.texi (GNU Object Attributes) [AVR Attributes]: New subsection. ld/ * testsuite/ld-avr/attr-gnu-4-1.s: New source. * testsuite/ld-avr/attr-gnu-4-2.s: New source. * testsuite/ld-avr/attr-gnu-4-1.d: New test. * testsuite/ld-avr/attr-gnu-4-2.d: New test. * testsuite/ld-avr/attr-gnu-4-1_2.d: New test. binutils/ * readelf.c (display_avr_gnu_attribute): New static function. (process_arch_specific) : Call process_attributes with display_avr_gnu_attribute as a callback. diff --git a/bfd/elf32-avr.c b/bfd/elf32-avr.c index 6653e4d72f6..2a0cc339511 100644 --- a/bfd/elf32-avr.c +++ b/bfd/elf32-avr.c @@ -25,6 +25,7 @@ #include "elf-bfd.h" #include "elf/avr.h" #include "elf32-avr.h" +#include "libiberty.h" /* Enable debugging printout at stdout with this variable. */ static bool debug_relax = false; @@ -4246,6 +4247,67 @@ avr_elf32_property_record_name (struct avr_property_record *rec) } +/* Merge object attributes from IBFD into OBFD. Error if there are + conflicting attributes. The follwing attributes are supported: + Tag_GNU_AVR_VTABLE_AS + One plus avr-g++'s named address-space for VTABLEs. +*/ + +static bool +avr_elf_merge_obj_attributes (bfd *ibfd, struct bfd_link_info *info) +{ + static bfd *last_fp; + obj_attribute *in_attr, *in_attrs; + obj_attribute *out_attr, *out_attrs; + bfd *obfd = info->output_bfd; + + in_attrs = elf_known_obj_attributes (ibfd)[OBJ_ATTR_GNU]; + out_attrs = elf_known_obj_attributes (obfd)[OBJ_ATTR_GNU]; + + in_attr = &in_attrs[Tag_GNU_AVR_VTABLE_AS]; + out_attr = &out_attrs[Tag_GNU_AVR_VTABLE_AS]; + + if (in_attr->i == Val_GNU_AVR_VTABLE_NONE + || out_attr->i == Val_GNU_AVR_VTABLE_NONE) + { + if (in_attr->i != Val_GNU_AVR_VTABLE_NONE) + { + out_attr->type = ATTR_TYPE_FLAG_INT_VAL; + out_attr->i = in_attr->i; + last_fp = ibfd; + } + } + else if (in_attr->i != out_attr->i) + { + const char *const tag = "Tag_GNU_AVR_VTABLE_AS"; + const char *const iname = avr_tag_vtable_as_name (in_attr->i); + const char *const oname = avr_tag_vtable_as_name (out_attr->i); + + _bfd_error_handler + /* xgettext:c-format */ + (_("%pB uses %s tag %d (%s), %pB uses %s tag %d (%s)"), + ibfd, tag, in_attr->i, iname, + last_fp, tag, out_attr->i, oname); + + out_attr->type = ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_ERROR; + bfd_set_error (bfd_error_bad_value); + return false; + } + + // Merge any common GNU attributes. + return _bfd_elf_merge_object_attributes (ibfd, info); +} + + +/* Merge backend specific data from an object file to the output + object file when linking. */ + +bool bfd_avr_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) +{ + return avr_elf_merge_obj_attributes (ibfd, info); +} + + #define ELF_ARCH bfd_arch_avr #define ELF_TARGET_ID AVR_ELF_DATA #define ELF_MACHINE_CODE EM_AVR @@ -4270,6 +4332,8 @@ avr_elf32_property_record_name (struct avr_property_record *rec) #define bfd_elf32_bfd_get_relocated_section_contents \ elf32_avr_get_relocated_section_contents #define bfd_elf32_new_section_hook elf_avr_new_section_hook +#define bfd_elf32_bfd_merge_private_bfd_data \ + bfd_avr_elf_merge_private_bfd_data #define elf_backend_special_sections elf_avr_special_sections #include "elf32-target.h" diff --git a/bfd/elf32-avr.h b/bfd/elf32-avr.h index 46e69b8b447..1b822c6adbb 100644 --- a/bfd/elf32-avr.h +++ b/bfd/elf32-avr.h @@ -36,6 +36,9 @@ elf32_avr_size_stubs (bfd *, struct bfd_link_info *, bool); extern bool elf32_avr_build_stubs (struct bfd_link_info *); +extern bool +bfd_avr_elf_merge_private_bfd_data (bfd *, struct bfd_link_info *); + /* The name of the section into which the property records are stored. */ #define AVR_PROPERTY_RECORD_SECTION_NAME ".avr.prop" diff --git a/binutils/readelf.c b/binutils/readelf.c index 686a16c60fc..1ed1ee61e6f 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -18249,6 +18249,30 @@ display_arm_attribute (unsigned char * p, return display_tag_value (tag, p, end); } +static unsigned char * +display_avr_gnu_attribute (unsigned char * p, + unsigned int tag, + const unsigned char * const end) +{ + if (tag == Tag_GNU_AVR_VTABLE_AS) + { + unsigned int val; + + printf (" Tag_GNU_AVR_VTABLE_AS (%u): ", tag); + if (p == end) + { + printf (_("\n")); + return p; + } + + READ_ULEB (val, p, end); + printf ("%d (%s)\n", val, avr_tag_vtable_as_name (val)); + return p; + } + + return display_tag_value (tag & 1, p, end); +} + static unsigned char * display_gnu_attribute (unsigned char * p, unsigned char * (* display_proc_gnu_attribute) @@ -23449,7 +23473,9 @@ process_arch_specific (Filedata * filedata) return process_attributes (filedata, "aeabi", SHT_ARM_ATTRIBUTES, display_arm_attribute, display_generic_attribute); - + case EM_AVR: + return process_attributes (filedata, NULL, SHT_GNU_ATTRIBUTES, NULL, + display_avr_gnu_attribute); case EM_MIPS: case EM_MIPS_RS3_LE: return process_mips_specific (filedata); diff --git a/gas/doc/as.texi b/gas/doc/as.texi index 1cb1fd879a4..8e714d9f2a1 100644 --- a/gas/doc/as.texi +++ b/gas/doc/as.texi @@ -8000,6 +8000,25 @@ than 1, the file can only be processed by other toolchains under some private arrangement indicated by the flag value and the vendor name. @end table +@subsection AVR Attributes + +@table @r +@item Tag_GNU_AVR_VTABLE_AS (4) +The @uref{https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html#AVR-Named-Address-Spaces,,named address space} +for C++ virtual tables used by this object file: +@itemize @bullet +@item 0 for files that neither define nor access virtual tables. +@item 1 for files that use the generic address space. +@item 2 for files that use the 16-bit address space @code{__flash}. +@item 3 for files that use the 16-bit address space @code{__flash1}. +@item 4 for files that use the 16-bit address space @code{__flash2}. +@item 5 for files that use the 16-bit address space @code{__flash3}. +@item 6 for files that use the 16-bit address space @code{__flash4}. +@item 7 for files that use the 16-bit address space @code{__flash5}. +@item 8 for files that use the 24-bit address space @code{__flashx}. +@end itemize +@end table + @subsection M680x0 Attributes @table @r diff --git a/include/elf/avr.h b/include/elf/avr.h index e60ebc7fb24..60f9e97a1dd 100644 --- a/include/elf/avr.h +++ b/include/elf/avr.h @@ -22,6 +22,7 @@ #define _ELF_AVR_H #include "elf/reloc-macros.h" +#include "libiberty.h" // ARRAY_SIZE /* Processor specific flags for the ELF header e_flags field. */ #define EF_AVR_MACH 0x7F @@ -90,4 +91,76 @@ START_RELOC_NUMBERS (elf_avr_reloc_type) RELOC_NUMBER (R_AVR_32_PCREL, 36) END_RELOC_NUMBERS (R_AVR_max) + +// Object attribute tags. +enum +{ + // 0-3 are generic. + + // VTABLE is located in some named address space. + Tag_GNU_AVR_VTABLE_AS = 4, +}; + + +// Object attribute values. +enum +{ + // There's no VTABLE instance or VTABLE access in the ojbect file. + Val_GNU_AVR_VTABLE_NONE = 0, + + // When the module hosts or reads a VTABLE, then Tag_GNU_AVR_VTABLE_AS is + // one plus AVR GCC's address space enum from /gcc/config/avr/avr.h. + + // VTABLE is located in AS0, the generic address space (RAM). + // This includes .rodata. */ + Val_GNU_AVR_VTABLE_RAM = 0 + 1, + + // __flash: 16-bit flash in 0x0 -- 0xffff. + Val_GNU_AVR_VTABLE_FLASH = 1 + 1, + + // __flash1: 16-bit flash in 0x10000 -- 0x1ffff. + Val_GNU_AVR_VTABLE_FLASH1 = 2 + 1, + + // __flash2: 16-bit flash in 0x20000 -- 0x2ffff. + Val_GNU_AVR_VTABLE_FLASH2 = 3 + 1, + + // __flash3: 16-bit flash in 0x30000 -- 0x3ffff. + Val_GNU_AVR_VTABLE_FLASH3 = 4 + 1, + + // __flash4: 16-bit flash in 0x40000 -- 0x4ffff. + Val_GNU_AVR_VTABLE_FLASH4 = 5 + 1, + + // __flash5: 16-bit flash in 0x50000 -- 0x5ffff. + Val_GNU_AVR_VTABLE_FLASH5 = 6 + 1, + + // __flashx: 24-bit flash. + Val_GNU_AVR_VTABLE_FLASHX = 7 + 1, + + Val_GNU_AVR_VTABLE_Sentinel +}; + + +// Map Tag_GNU_AVR_VTABLE_AS to a static string for diagnostics. + +static inline const char * +avr_tag_vtable_as_name (int tag) +{ + switch (tag) + { + default: + break; + case Val_GNU_AVR_VTABLE_NONE: return "no vtables"; + case Val_GNU_AVR_VTABLE_RAM: return "generic address space"; + case Val_GNU_AVR_VTABLE_FLASH: return "__flash"; + case Val_GNU_AVR_VTABLE_FLASH1: return "__flash1"; + case Val_GNU_AVR_VTABLE_FLASH2: return "__flash2"; + case Val_GNU_AVR_VTABLE_FLASH3: return "__flash3"; + case Val_GNU_AVR_VTABLE_FLASH4: return "__flash4"; + case Val_GNU_AVR_VTABLE_FLASH5: return "__flash5"; + case Val_GNU_AVR_VTABLE_FLASHX: return "__flashx"; + } + + return ""; +} + #endif /* _ELF_AVR_H */ diff --git a/ld/testsuite/ld-avr/attr-gnu-4-1.d b/ld/testsuite/ld-avr/attr-gnu-4-1.d new file mode 100644 index 00000000000..461db4f8e92 --- /dev/null +++ b/ld/testsuite/ld-avr/attr-gnu-4-1.d @@ -0,0 +1,8 @@ +#name: AVR Tag_AVR_GNU_VTABLE_AS 1 +#source: attr-gnu-4-1.s +#readelf: -A +#target: avr-*-* + +Attribute Section: gnu +File Attributes + Tag_GNU_AVR_VTABLE_AS \(4\): 1 \(generic address space\) diff --git a/ld/testsuite/ld-avr/attr-gnu-4-1.s b/ld/testsuite/ld-avr/attr-gnu-4-1.s new file mode 100644 index 00000000000..e985a56f6b1 --- /dev/null +++ b/ld/testsuite/ld-avr/attr-gnu-4-1.s @@ -0,0 +1 @@ +.gnu_attribute 4,1 diff --git a/ld/testsuite/ld-avr/attr-gnu-4-1_2.d b/ld/testsuite/ld-avr/attr-gnu-4-1_2.d new file mode 100644 index 00000000000..5e7ea5c667e --- /dev/null +++ b/ld/testsuite/ld-avr/attr-gnu-4-1_2.d @@ -0,0 +1,7 @@ +#name: AVR Tag_AVR_GNU_VTABLE_AS conflict +#source: attr-gnu-4-1.s +#source: attr-gnu-4-2.s +#as: +#ld: +#target: avr-*-* +#error: failed to merge target specific data of file diff --git a/ld/testsuite/ld-avr/attr-gnu-4-2.d b/ld/testsuite/ld-avr/attr-gnu-4-2.d new file mode 100644 index 00000000000..2a823c1b280 --- /dev/null +++ b/ld/testsuite/ld-avr/attr-gnu-4-2.d @@ -0,0 +1,8 @@ +#name: AVR Tag_AVR_GNU_VTABLE_AS 2 +#source: attr-gnu-4-2.s +#readelf: -A +#target: avr-*-* + +Attribute Section: gnu +File Attributes + Tag_GNU_AVR_VTABLE_AS \(4\): 2 \(__flash\) diff --git a/ld/testsuite/ld-avr/attr-gnu-4-2.s b/ld/testsuite/ld-avr/attr-gnu-4-2.s new file mode 100644 index 00000000000..54ebf4ed8dd --- /dev/null +++ b/ld/testsuite/ld-avr/attr-gnu-4-2.s @@ -0,0 +1 @@ +.gnu_attribute 4,2