Work around gcc-4.9 bug
Matthieu Longo
matthieu.longo@arm.com
Thu Feb 26 14:32:06 GMT 2026
On 26/02/2026 07:47, Alan Modra wrote:
> Commit 893eb49c9b12 exposed a gcc-4.9 build error, with gcc-4.9
> erroneously complaining that F_MIN_SUBSECTION_DATA_LEN has a
> non-constant initialisation.
>
> * readelf.c (F_MIN_SUBSECTION_DATA_LEN): Use #define to work
> around gcc-4.9 bug.
> (F_SUBSECTION_LEN, F_SUBSECTION_COMPREHENSION),
> (F_SUBSECTION_ENCODING): Use #define here too.
> (elf_parse_attrs_subsection_v2): Adjust format string.
>
> diff --git a/binutils/readelf.c b/binutils/readelf.c
> index c9ec085adc4..0c3e24e8bf7 100644
> --- a/binutils/readelf.c
> +++ b/binutils/readelf.c
> @@ -20098,14 +20098,14 @@ typedef struct {
> uint64_t read;
> } BufferReadOp_t;
>
> -const uint32_t F_SUBSECTION_LEN = sizeof (uint32_t);
> -const uint32_t F_SUBSECTION_COMPREHENSION = sizeof(uint8_t);
> -const uint32_t F_SUBSECTION_ENCODING = sizeof(uint8_t);
> /* The minimum subsection length is 7: 4 bytes for the length itself, and 1
> byte for an empty NUL-terminated string, 1 byte for the comprehension,
> 1 byte for the encoding, and no vendor-data. */
> -const uint32_t F_MIN_SUBSECTION_DATA_LEN = F_SUBSECTION_LEN + 1 /* for '\0' */
> - + F_SUBSECTION_COMPREHENSION + F_SUBSECTION_ENCODING;
> +#define F_SUBSECTION_LEN 4
> +#define F_SUBSECTION_COMPREHENSION 1
> +#define F_SUBSECTION_ENCODING 1
> +#define F_MIN_SUBSECTION_DATA_LEN \
> + (F_SUBSECTION_LEN + 1 + F_SUBSECTION_COMPREHENSION + F_SUBSECTION_ENCODING)
>
> static BufferReadOp_t
> elf_parse_attrs_subsection_v2 (const unsigned char *cursor,
> @@ -20128,7 +20128,7 @@ elf_parse_attrs_subsection_v2 (const unsigned char *cursor,
> }
> else if (subsection_len < F_MIN_SUBSECTION_DATA_LEN)
> {
> - error (_("Bad subsection length: too small (%u < min=%"PRIu32")\n"),
> + error (_("Bad subsection length: too small (%u < min=%u)\n"),
> subsection_len, F_MIN_SUBSECTION_DATA_LEN);
> /* Error, but still try to display the content until meeting a more
> serious error. */
>
Hi Alan,
Would it make sense to add a check on the compiler version around the original code instead of replacing it ?
#if defined (__GNUC__) && (__GNUC__ > 4)
/* Keep the new code */
#else
/* Fix for 4.9 which is easy to detect with a grep, and drop when support for GCC 4.9 goes away. */
#endif
This would help to modernize the code as soon as the support for an old compiler is dropped.
I previously worked in a big code base on a migration to C++11, and then C++14, and then C++17 migration. The codebase had to compile with SunCC, GCC, Clang and MSC.
If there was a fix that was easier to implement or more future-proof with newer versions of C++, we opted for it and added #ifdef around it while still implementing the workaround for older versions.
Then, when we were dropping the support for a platform or a compiler, it was easy to detect the pieces that were compiler/platform-specific and the now dead-code could easily be dropped.
As a drawback, it makes some pieces of code more difficult to read, and there are risks of differences in behavior depending on the implementation that was selected at compile time (tests were helping to detect issues in this regard).
Please let me know your thoughts about this approach.
Regards,
Matthieu
More information about the Binutils
mailing list