From 0b33a45f784dcde7f35911c2ca823e5e6be98337 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:08 -0400 Subject: [PATCH 01/17] opcodes/z80: remove use of sprintf When building on macOS, I get: CC z80-dis.lo /Users/smarchi/src/binutils-gdb/opcodes/z80-dis.c:804:41: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 804 | info->fprintf_func = (fprintf_ftype) &sprintf; | ^ Replace this use of sprintf with the safer snprintf. Add a small structure and wrappers around snprintf in order to glue everything together. When asked to review my patch, Claude Code mentioned that the existing code had a latent bug: while info->fprintf_func and info->stream get set temporarily, info->fprintf_styled_func doesn't. If fprintf_styled_func happened to be called, it would receive a `stream` it doesn't expect. It's probably not a problem today, if the disassembler doesn't emit styling, but it seems like a good moment to fix it. Use the disassemble_set_printf function to set both fprintf functions and the stream argument at the same time. Change-Id: I85dee82f3a0c53f38e52ca1158bc605854ab4896 --- opcodes/z80-dis.c | 53 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/opcodes/z80-dis.c b/opcodes/z80-dis.c index d5b4c4210d0..0269b6f3415 100644 --- a/opcodes/z80-dis.c +++ b/opcodes/z80-dis.c @@ -21,6 +21,7 @@ #include "sysdep.h" #include "disassemble.h" +#include "libiberty.h" #include struct buffer @@ -768,11 +769,55 @@ pref_ind (struct buffer *buf, disassemble_info *info, const char *txt) static int print_insn_z80_buf (struct buffer *buf, disassemble_info *info); +struct sized_buf +{ + char *buf; + size_t size; +}; + +/* An fprintf_ftype implementation writing to STREAM, which must point to a + struct sized_buf. */ + +static int ATTRIBUTE_PRINTF_2 +sized_buf_printf (void *stream, const char *format, ...) +{ + va_list ap; + int ret; + struct sized_buf *sbuf = stream; + + va_start (ap, format); + ret = vsnprintf (sbuf->buf, sbuf->size, format, ap); + va_end (ap); + + return ret; +} + +/* Same as sized_buf_printf, but as an fprintf_styled_ftype implementation. + The style is ignored for now. */ + +static int ATTRIBUTE_PRINTF_3 +sized_buf_styled_printf (void *stream, + enum disassembler_style style ATTRIBUTE_UNUSED, + const char *format, ...) +{ + va_list ap; + int ret; + struct sized_buf *sbuf = stream; + + va_start (ap, format); + ret = vsnprintf (sbuf->buf, sbuf->size, format, ap); + va_end (ap); + + return ret; +} + static int suffix (struct buffer *buf, disassemble_info *info, const char *txt) { char mybuf[TXTSIZ*4]; + struct sized_buf sbuf = { mybuf, ARRAY_SIZE (mybuf) }; fprintf_ftype old_fprintf; + fprintf_styled_ftype old_fprintf_styled; void *old_stream; char *p; @@ -800,15 +845,15 @@ suffix (struct buffer *buf, disassemble_info *info, const char *txt) } old_fprintf = info->fprintf_func; + old_fprintf_styled = info->fprintf_styled_func; old_stream = info->stream; - info->fprintf_func = (fprintf_ftype) &sprintf; - info->stream = mybuf; + disassemble_set_printf (info, &sbuf, sized_buf_printf, + sized_buf_styled_printf); mybuf[0] = 0; buf->base++; if (print_insn_z80_buf (buf, info) >= 0) buf->n_used++; - info->fprintf_func = old_fprintf; - info->stream = old_stream; + disassemble_set_printf (info, old_stream, old_fprintf, old_fprintf_styled); for (p = mybuf; *p; ++p) if (*p == ' ') From 8e0b14a98975d5762117f4d145443ac4df0b0396 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 29 Jul 2026 15:21:42 -0600 Subject: [PATCH 02/17] Update gdb.ada/unchecked_union.exp for gnat-llvm gnat-llvm emits a slightly different encoding for Ada unchecked unions. This encoding lets GDB resolve the discriminant for some branches that appear as "?" when compiled with GCC's GNAT. This patch updates gdb.ada/unchecked_union.exp to allow this. Approved-By: Andrew Burgess --- gdb/testsuite/gdb.ada/unchecked_union.exp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/gdb/testsuite/gdb.ada/unchecked_union.exp b/gdb/testsuite/gdb.ada/unchecked_union.exp index 6a54e606712..ef9da787e65 100644 --- a/gdb/testsuite/gdb.ada/unchecked_union.exp +++ b/gdb/testsuite/gdb.ada/unchecked_union.exp @@ -24,20 +24,23 @@ standard_ada_testfile unchecked_union proc multi_line_string {str} { set result {} foreach line $str { - lappend result [string_to_regexp $line] + lappend result [quotemeta $line] } set res [multi_line {*}$result] verbose -log "RES: '$res'" return $res } +# Note the quotemeta expression here. gnat-llvm emits slightly a +# different encoding here, which lets gdb see the discriminant for a +# branch. set inner_string \ [list \ " case ? is" \ " when 0 =>" \ " small: range 0 .. 255;" \ " second: range 0 .. 255;" \ - " when ? =>" \ + " when @/\[1?\]/ =>" \ " bval: range 0 .. 255;" \ " when others =>" \ " large: range 255 .. 510;" \ @@ -50,12 +53,15 @@ set inner_full \ $inner_string \ [list "end record"]] +# Note the quotemeta expression here. gnat-llvm emits slightly a +# different encoding here, which lets gdb see the discriminant for a +# branch. set pair_string \ [list \ " case ? is" \ - " when ? =>" \ + " when @/\[0?\]/ =>" \ " field_one: range 0 .. 255;" \ - " when ? =>" \ + " when @/(\\?|others)/ =>" \ " field_two: range 255 .. 510;" \ " end case;"] From 3cb73f9a98c41bfa3efa074765c3d22d3c2d98e9 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:06 -0400 Subject: [PATCH 03/17] gdbsupport: remove uses of vsprintf When building on macOS, I get: CXX common-utils.o /Users/smarchi/src/binutils-gdb/gdbsupport/common-utils.cc:106:3: error: 'vsprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use vsnprintf(3) instead. [-Werror,-Wdeprecated-declarations] 106 | vsprintf (&str[0], fmt, vp); | ^ /Users/smarchi/src/binutils-gdb/gdbsupport/common-utils.cc:128:3: error: 'vsprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use vsnprintf(3) instead. [-Werror,-Wdeprecated-declarations] 128 | vsprintf (&str[0], fmt, args); | ^ /Users/smarchi/src/binutils-gdb/gdbsupport/common-utils.cc:166:3: error: 'vsprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use vsnprintf(3) instead. [-Werror,-Wdeprecated-declarations] 166 | vsprintf (&str[curr_size], fmt, args); | ^ We know that those calls should be safe because we computed the size that fmt+args take just before, and allocated that many bytes. But I also don't see a real downside in switching those calls to use vsnprintf and double check that everything went right. Change the type of the existing "size" variable in "string_vprintf" to "int", since that's what vsnprintf returns. Change-Id: I589d9a170fdd15cc31b44b76689c6d8c324e340a Approved-By: Andrew Burgess --- gdbsupport/common-utils.cc | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/gdbsupport/common-utils.cc b/gdbsupport/common-utils.cc index 3ae3afcc380..f31699be13a 100644 --- a/gdbsupport/common-utils.cc +++ b/gdbsupport/common-utils.cc @@ -92,10 +92,9 @@ std::string string_printf (const char* fmt, ...) { va_list vp; - int size; va_start (vp, fmt); - size = vsnprintf (NULL, 0, fmt, vp); + int size = vsnprintf (NULL, 0, fmt, vp); va_end (vp); std::string str (size, '\0'); @@ -103,7 +102,8 @@ string_printf (const char* fmt, ...) /* C++11 and later guarantee std::string uses contiguous memory and always includes the terminating '\0'. */ va_start (vp, fmt); - vsprintf (&str[0], fmt, vp); + int ret = vsnprintf (&str[0], size + 1, fmt, vp); + gdb_assert (ret == size); va_end (vp); return str; @@ -115,17 +115,17 @@ std::string string_vprintf (const char* fmt, va_list args) { va_list vp; - size_t size; va_copy (vp, args); - size = vsnprintf (NULL, 0, fmt, vp); + int size = vsnprintf (NULL, 0, fmt, vp); va_end (vp); std::string str (size, '\0'); /* C++11 and later guarantee std::string uses contiguous memory and always includes the terminating '\0'. */ - vsprintf (&str[0], fmt, args); + int ret = vsnprintf (&str[0], size + 1, fmt, args); + gdb_assert (ret == size); return str; } @@ -152,10 +152,9 @@ std::string & string_vappendf (std::string &str, const char *fmt, va_list args) { va_list vp; - int grow_size; va_copy (vp, args); - grow_size = vsnprintf (NULL, 0, fmt, vp); + int grow_size = vsnprintf (NULL, 0, fmt, vp); va_end (vp); size_t curr_size = str.size (); @@ -163,7 +162,8 @@ string_vappendf (std::string &str, const char *fmt, va_list args) /* C++11 and later guarantee std::string uses contiguous memory and always includes the terminating '\0'. */ - vsprintf (&str[curr_size], fmt, args); + int ret = vsnprintf (&str[curr_size], grow_size + 1, fmt, args); + gdb_assert (ret == grow_size); return str; } From 485a8536190f2f0f622bd58e4eb23da95988a131 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:07 -0400 Subject: [PATCH 04/17] gdbsupport: remove uses of sprintf When building on macOS, I get some errors about the uses of sprintf: CXX xml-utils.o /Users/smarchi/src/binutils-gdb/gdbsupport/xml-utils.cc:91:8: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 91 | sprintf (str, "%d", va_arg (ap, int)); | ^ We know they are safe, because the 32 byte destination buffer is large enough for all conversions. But I also don't think it's a big deal to switch to xsnprintf to avoid these errors, and to catch any future error. Change-Id: If3531e1916e103dfccd0ec033639b14a2b6df3cf Approved-By: Andrew Burgess --- gdbsupport/xml-utils.cc | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/gdbsupport/xml-utils.cc b/gdbsupport/xml-utils.cc index 13dc2749912..cec7281c929 100644 --- a/gdbsupport/xml-utils.cc +++ b/gdbsupport/xml-utils.cc @@ -88,52 +88,55 @@ string_xml_appendf (std::string &buffer, const char *format, ...) str = va_arg (ap, char *); break; case 'd': - sprintf (str, "%d", va_arg (ap, int)); + xsnprintf (buf, sizeof (buf), "%d", va_arg (ap, int)); break; case 'u': - sprintf (str, "%u", va_arg (ap, unsigned int)); + xsnprintf (buf, sizeof (buf), "%u", va_arg (ap, unsigned int)); break; case 'x': - sprintf (str, "%x", va_arg (ap, unsigned int)); + xsnprintf (buf, sizeof (buf), "%x", va_arg (ap, unsigned int)); break; case 'o': - sprintf (str, "%o", va_arg (ap, unsigned int)); + xsnprintf (buf, sizeof (buf), "%o", va_arg (ap, unsigned int)); break; case 'l': f++; switch (*f) { case 'd': - sprintf (str, "%ld", va_arg (ap, long)); + xsnprintf (buf, sizeof (buf), "%ld", va_arg (ap, long)); break; case 'u': - sprintf (str, "%lu", va_arg (ap, unsigned long)); + xsnprintf (buf, sizeof (buf), "%lu", + va_arg (ap, unsigned long)); break; case 'x': - sprintf (str, "%lx", va_arg (ap, unsigned long)); + xsnprintf (buf, sizeof (buf), "%lx", + va_arg (ap, unsigned long)); break; case 'o': - sprintf (str, "%lo", va_arg (ap, unsigned long)); + xsnprintf (buf, sizeof (buf), "%lo", + va_arg (ap, unsigned long)); break; case 'l': f++; switch (*f) { case 'd': - sprintf (str, "%" PRId64, - (int64_t) va_arg (ap, long long)); + xsnprintf (buf, sizeof (buf), "%" PRId64, + (int64_t) va_arg (ap, long long)); break; case 'u': - sprintf (str, "%" PRIu64, - (uint64_t) va_arg (ap, unsigned long long)); + xsnprintf (buf, sizeof (buf), "%" PRIu64, + (uint64_t) va_arg (ap, unsigned long long)); break; case 'x': - sprintf (str, "%" PRIx64, - (uint64_t) va_arg (ap, unsigned long long)); + xsnprintf (buf, sizeof (buf), "%" PRIx64, + (uint64_t) va_arg (ap, unsigned long long)); break; case 'o': - sprintf (str, "%" PRIo64, - (uint64_t) va_arg (ap, unsigned long long)); + xsnprintf (buf, sizeof (buf), "%" PRIo64, + (uint64_t) va_arg (ap, unsigned long long)); break; default: str = 0; From 88629da8ad34c10c7e4cfecbd672a6ad1338e91c Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:09 -0400 Subject: [PATCH 05/17] sim/ppc: make defines.h sed command portable When building on macOS, whose sed is the BSD one, I get: GEN ppc/stamp-defines sed: 1: "/^#define HAVE_.*1$/{ s ...": extra characters at the end of p command make[1]: *** [ppc/stamp-defines] Error 1 BSD sed apparently does not accept a `}' directly after another command, it needs a separating semicolon. Add one after the `p'. GNU sed accepts both forms, and produces the same output either way. Re-generate sim/Makefile.in. Change-Id: I0709ad7b0051e08299f2576113b549aba9fc703f Approved-By: Andrew Burgess --- sim/Makefile.in | 2 +- sim/ppc/local.mk | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sim/Makefile.in b/sim/Makefile.in index 1f9bbfec03f..2a23b5c2eaa 100644 --- a/sim/Makefile.in +++ b/sim/Makefile.in @@ -5722,7 +5722,7 @@ testsuite/common/bits64m63.c: testsuite/common/bits-gen$(EXEEXT) testsuite/commo @SIM_ENABLE_ARCH_ppc_TRUE@ppc/defines.h: ppc/stamp-defines ; @true @SIM_ENABLE_ARCH_ppc_TRUE@ppc/stamp-defines: config.h Makefile -@SIM_ENABLE_ARCH_ppc_TRUE@ $(AM_V_GEN)$(SED) -n -e '/^#define HAVE_.*1$$/{ s/ 1$$/",/; s/.* HAVE_/"HAVE_/; p }' < config.h > ppc/defines.hin +@SIM_ENABLE_ARCH_ppc_TRUE@ $(AM_V_GEN)$(SED) -n -e '/^#define HAVE_.*1$$/{ s/ 1$$/",/; s/.* HAVE_/"HAVE_/; p; }' < config.h > ppc/defines.hin @SIM_ENABLE_ARCH_ppc_TRUE@ $(AM_V_at)$(SHELL) $(srcroot)/move-if-change ppc/defines.hin ppc/defines.h @SIM_ENABLE_ARCH_ppc_TRUE@ $(AM_V_at)touch $@ diff --git a/sim/ppc/local.mk b/sim/ppc/local.mk index f9f134abe3c..9aca96465ac 100644 --- a/sim/ppc/local.mk +++ b/sim/ppc/local.mk @@ -80,7 +80,7 @@ noinst_PROGRAMS += %D%/run %D%/defines.h: %D%/stamp-defines ; @true %D%/stamp-defines: config.h Makefile - $(AM_V_GEN)$(SED) -n -e '/^#define HAVE_.*1$$/{ s/ 1$$/",/; s/.* HAVE_/"HAVE_/; p }' < config.h > %D%/defines.hin + $(AM_V_GEN)$(SED) -n -e '/^#define HAVE_.*1$$/{ s/ 1$$/",/; s/.* HAVE_/"HAVE_/; p; }' < config.h > %D%/defines.hin $(AM_V_at)$(SHELL) $(srcroot)/move-if-change %D%/defines.hin %D%/defines.h $(AM_V_at)touch $@ From 1bf675bdada38c307058897be6f743ebd665fcdb Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:10 -0400 Subject: [PATCH 06/17] sim/m32r: fix unused variable warning on non-Linux hosts When building on macOS, I get: /Users/smarchi/src/binutils-gdb/sim/m32r/traps.c:191:18: error: unused variable 'cb' [-Werror,-Wunused-variable] 191 | host_callback *cb = STATE_CALLBACK (sd); | ^~ All the uses of `cb' in m32r_trap are inside the TRAP_LINUX_SYSCALL case, which is guarded by `#ifdef __linux__'. Move the declaration inside that case, so that it only exists where it is used. Change-Id: I609850daf7fa60d92856988dffe7e314eb1d8a30 Approved-By: Andrew Burgess --- sim/m32r/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sim/m32r/traps.c b/sim/m32r/traps.c index 7b98b245397..bb82ae80e2a 100644 --- a/sim/m32r/traps.c +++ b/sim/m32r/traps.c @@ -188,7 +188,6 @@ USI m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) { SIM_DESC sd = CPU_STATE (current_cpu); - host_callback *cb = STATE_CALLBACK (sd); if (STATE_ENVIRONMENT (sd) == OPERATING_ENVIRONMENT) goto case_default; @@ -217,6 +216,7 @@ m32r_trap (SIM_CPU *current_cpu, PCADDR pc, int num) #ifdef __linux__ case TRAP_LINUX_SYSCALL: { + host_callback *cb = STATE_CALLBACK (sd); CB_SYSCALL s; unsigned int func, arg1, arg2, arg3, arg4, arg5, arg6, arg7; int result, errcode; From 77fb5754bb7f9f38228fa82ef6f466dfcd11052f Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:11 -0400 Subject: [PATCH 07/17] sim/m32r: fix unused function warnings on non-Linux hosts When building on macOS, I get: /Users/smarchi/src/binutils-gdb/sim/m32r/traps.c:141:1: error: unused function 't2h_addr' [-Werror,-Wunused-function] 141 | t2h_addr (host_callback *cb, struct cb_syscall *sc, | ^~~~~~~~ /Users/smarchi/src/binutils-gdb/sim/m32r/traps.c:158:1: error: unused function 'translate_endian_h2t' [-Werror,-Wunused-function] 158 | translate_endian_h2t (void *addr, size_t size) | ^~~~~~~~~~~~~~~~~~~~ /Users/smarchi/src/binutils-gdb/sim/m32r/traps.c:171:1: error: unused function 'translate_endian_t2h' [-Werror,-Wunused-function] 171 | translate_endian_t2h (void *addr, size_t size) | ^~~~~~~~~~~~~~~~~~~~ These three helpers are only called from the TRAP_LINUX_SYSCALL case, which is guarded by `#ifdef __linux__'. Put them behind the same guard. Change-Id: I8c8744727eb27abc08231be2a10f8d0de44d7ea6 Approved-By: Andrew Burgess --- sim/m32r/traps.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sim/m32r/traps.c b/sim/m32r/traps.c index bb82ae80e2a..43a81c915d1 100644 --- a/sim/m32r/traps.c +++ b/sim/m32r/traps.c @@ -134,7 +134,9 @@ m32r_core_signal (SIM_DESC sd, SIM_CPU *current_cpu, sim_cia cia, sim_core_signal (sd, current_cpu, cia, map, nr_bytes, addr, transfer, sig); } - + +#ifdef __linux__ + /* Translate target's address to host's address. */ static void * @@ -180,6 +182,8 @@ translate_endian_t2h (void *addr, size_t size) *((unsigned short *) p) = T2H_2 (*((unsigned short *) p)); } +#endif /* __linux__ */ + /* Trap support. The result is the pc address to continue at. Preprocessing like saving the various registers has already been done. */ From 554068200b304005f072faa2c7868147b3584b34 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:13 -0400 Subject: [PATCH 08/17] gdb/dwarf2: remove uses of sprintf When building on macOS, I get some: /Users/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:3773:4: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 3773 | sprintf (buf, "TU %s at offset %s", hex_string (sig_type->signature), | ^ Replace them with xsnprintf, which takes the destination size and asserts that the output was not truncated. Change-Id: Ie0324f75e5d4aad9b647007848459bf4af5998a6 Approved-By: Andrew Burgess --- gdb/dwarf2/read.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index ca475f53745..a8b99425554 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -3770,15 +3770,16 @@ process_queue (dwarf2_per_objfile *per_objfile) if (signatured_type *sig_type = per_cu->as_signatured_type (); sig_type != nullptr) { - sprintf (buf, "TU %s at offset %s", hex_string (sig_type->signature), - sect_offset_str (per_cu->sect_off ())); + xsnprintf (buf, sizeof (buf), "TU %s at offset %s", + hex_string (sig_type->signature), + sect_offset_str (per_cu->sect_off ())); /* There can be 100s of TUs. Only print them in verbose mode. */ debug_print_threshold = 2; } else { - sprintf (buf, "CU at offset %s", - sect_offset_str (per_cu->sect_off ())); + xsnprintf (buf, sizeof (buf), "CU at offset %s", + sect_offset_str (per_cu->sect_off ())); debug_print_threshold = 1; } From 27e4e8af3ad033edd5f10517346c12db7d2373e1 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:14 -0400 Subject: [PATCH 09/17] gdb/elfread: remove use of sprintf When building on macOS, I get: /Users/smarchi/src/binutils-gdb/gdb/elfread.c:813:3: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 813 | sprintf (name_got_plt, "%s" SYMBOL_GOT_PLT_SUFFIX, name); | ^ Change this use of sprintf with an std::string, which also allows getting rid of a use of alloca. Change-Id: I296e25c863463ef05eca582c8303557570d63cf0 Approved-By: Andrew Burgess --- gdb/elfread.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/gdb/elfread.c b/gdb/elfread.c index e3890ae0270..fcbd0176d08 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -804,20 +804,17 @@ static int elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) { gnu_ifunc_debug_printf ("resolving \"%s\" by GOT", name); - char *name_got_plt; - const size_t got_suffix_len = strlen (SYMBOL_GOT_PLT_SUFFIX); int found = 0; const char *func = __func__; - name_got_plt = (char *) alloca (strlen (name) + got_suffix_len + 1); - sprintf (name_got_plt, "%s" SYMBOL_GOT_PLT_SUFFIX, name); + std::string name_got_plt = std::string (name) + SYMBOL_GOT_PLT_SUFFIX; /* FIXME: we only search the initial namespace. To search other namespaces, we would need to provide context, e.g. in form of an objfile in that namespace. */ current_program_space->iterate_over_objfiles_in_search_order - ([name, name_got_plt, &addr_p, &found, func] (struct objfile *objfile) + ([name, &name_got_plt, &addr_p, &found, func] (struct objfile *objfile) { bfd *obfd = objfile->obfd.get (); struct gdbarch *gdbarch = objfile->arch (); @@ -828,8 +825,8 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) gdb_byte *buf = (gdb_byte *) alloca (ptr_size); bound_minimal_symbol msym - = lookup_minimal_symbol (current_program_space, name_got_plt, - objfile); + = lookup_minimal_symbol (current_program_space, + name_got_plt.c_str (), objfile); if (msym.minsym == NULL) return 0; if (msym.minsym->type () != mst_slot_got_plt) @@ -850,7 +847,8 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p) addr = gdbarch_addr_bits_remove (gdbarch, addr); gnu_ifunc_debug_printf_func (func, "GOT entry \"%s\" points to %s", - name_got_plt, paddress (gdbarch, addr)); + name_got_plt.c_str (), + paddress (gdbarch, addr)); if (elf_gnu_ifunc_record_cache (name, addr)) { From 2452e480ae871587ef4e34ce1da368c71b43b425 Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Mon, 17 Aug 2026 11:16:18 -0400 Subject: [PATCH 10/17] gdb/tracepoint: remove uses of sprintf When building on macOS, I get some: /Users/smarchi/src/binutils-gdb/gdb/tracepoint.c:1196:4: error: 'sprintf' is deprecated: This function is provided for compatibility reasons only. Due to security concerns inherent in the design of sprintf(3), it is highly recommended that you use snprintf(3) instead. [-Werror,-Wdeprecated-declarations] 1196 | sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0), | ^ Replace them with xsnprintf. Change-Id: Id3ec76c47e5c0091fa3a028e36063b2115378e7e Approved-By: Andrew Burgess --- gdb/tracepoint.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 798bb9a552d..932a8f557e4 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -1164,6 +1164,9 @@ collection_list::stringify () gdb_printf ("\n"); if (!m_memranges.empty () && info_verbose) gdb_printf ("Collecting memranges: \n"); + + char *buf_end = temp_buf.data () + temp_buf.size (); + for (i = 0, count = 0, end = temp_buf.data (); i < m_memranges.size (); i++) { @@ -1193,11 +1196,12 @@ collection_list::stringify () "FFFFFFFF" (or more, depending on sizeof (unsigned)). Special-case it. */ if (m_memranges[i].type == memrange_absolute) - sprintf (end, "M-1,%s,%lX", phex_nz (m_memranges[i].start, 0), - (long) length); + xsnprintf (end, buf_end - end, "M-1,%s,%lX", + phex_nz (m_memranges[i].start, 0), (long) length); else - sprintf (end, "M%X,%s,%lX", m_memranges[i].type, - phex_nz (m_memranges[i].start, 0), (long) length); + xsnprintf (end, buf_end - end, "M%X,%s,%lX", + m_memranges[i].type, phex_nz (m_memranges[i].start, 0), + (long) length); } count += strlen (end); @@ -1213,7 +1217,9 @@ collection_list::stringify () count = 0; end = temp_buf.data (); } - sprintf (end, "X%08X,", (int) m_aexprs[i]->buf.size ()); + + xsnprintf (end, buf_end - end, "X%08X,", + (int) m_aexprs[i]->buf.size ()); end += 10; /* 'X' + 8 hex digits + ',' */ count += 10; @@ -2816,11 +2822,14 @@ encode_source_string (int tpnum, ULONGEST addr, { if (80 + strlen (srctype) > buf_size) error (_("Buffer too small for source encoding")); - sprintf (buf, "%x:%s:%s:%x:%x:", - tpnum, phex_nz (addr), - srctype, 0, (int) strlen (src)); + + xsnprintf (buf, buf_size, "%x:%s:%s:%x:%x:", + tpnum, phex_nz (addr), + srctype, 0, (int) strlen (src)); + if (strlen (buf) + strlen (src) * 2 >= buf_size) error (_("Source string too long for buffer")); + bin2hex ((gdb_byte *) src, buf + strlen (buf), strlen (src)); return -1; } From d336a91494769d1f7a9486245c4e88c4a32e2ad3 Mon Sep 17 00:00:00 2001 From: GDB Administrator Date: Wed, 19 Aug 2026 00:00:08 +0000 Subject: [PATCH 11/17] Automatic date update in version.in --- bfd/version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bfd/version.h b/bfd/version.h index 7e8381ad7aa..50af28cf8fd 100644 --- a/bfd/version.h +++ b/bfd/version.h @@ -16,7 +16,7 @@ In releases, the date is not included in either version strings or sonames. */ -#define BFD_VERSION_DATE 20260818 +#define BFD_VERSION_DATE 20260819 #define BFD_VERSION @bfd_version@ #define BFD_VERSION_STRING @bfd_version_package@ @bfd_version_string@ #define REPORT_BUGS_TO @report_bugs_to@ From 09a7362522ef0447210042a4f0309559edae82bb Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 19 Aug 2026 08:20:50 +0200 Subject: [PATCH 12/17] [gdb/testsuite] Fix gdb.python/py-failed-init.exp with python 3.15 On Fedora Rawhide aarch64-linux, I ran into: ... builtin_spawn $build/gdb/gdb -nw -nx -q -iex set height 0 -iex set width 0 \ -data-directory $build/gdb/data-directory -iex set interactive-mode on WARN: Could not find the standard library directory! The Python 'home' directory was set to 'foo', is this correct? Error occurred computing Python error message. $build/gdb/gdb: warning: Could not load the Python gdb module from `$build/gdb/data-directory/python'. Limited Python support is available from the _gdb module. Suggest passing --data-directory=/path/to/gdb/data-directory. (gdb) set height 0 (gdb) set width 0 (gdb) dir Reinitialize source path to empty? (y or n) y Source directories searched: $cdir:$cwd (gdb) dir $src/gdb/testsuite/gdb.python Source directories searched: $src/gdb/testsuite/gdb.python:$cdir:$cwd (gdb) python print (1) 1 (gdb) FAIL: $exp: gdb-command quit Exception ignored on threading shutdown: Traceback (most recent call last): File "", line 2, in ModuleNotFoundError: No module named 'importlib' PASS: gdb.python/py-failed-init.exp: quit ... The ModuleNotFoundError reported after quit originates from gdbpy_initialize_gdb_readline. I've filed a PR about this [1]. The test-case tries to break python: ... save_vars { env(PYTHONHOME) } { setenv PYTHONHOME foo clean_restart } ... enough to get it to this point: ... gdb_test "python print (1)" \ "Python not initialized" ... but apparently, that doesn't work anymore in this python version: ... $ python --version Python 3.15.0b4 ... Update the test-case by simply accepting the output. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=34485 --- gdb/testsuite/gdb.python/py-failed-init.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gdb/testsuite/gdb.python/py-failed-init.exp b/gdb/testsuite/gdb.python/py-failed-init.exp index c2b9c990e29..b2ea8c152fe 100644 --- a/gdb/testsuite/gdb.python/py-failed-init.exp +++ b/gdb/testsuite/gdb.python/py-failed-init.exp @@ -22,7 +22,7 @@ save_vars { env(PYTHONHOME) } { } gdb_test "python print (1)" \ - "Python not initialized" + "(Python not initialized|1)" set output_seen 0 gdb_test_multiple "quit" "" { From ab1830f633107b180b46938003e6f49fb44cb17d Mon Sep 17 00:00:00 2001 From: Cole Munz Date: Mon, 17 Aug 2026 16:59:00 +0000 Subject: [PATCH 13/17] PR 24576: duplicate-script check on hosts without inodes Since 2.47, ld rejects a perfectly ordinary link on native Windows: ld.exe: error: linker script file '../common_arm/ldscript.common (ldscript-flash)' appears multiple times when the only thing on the command line is a single -T, and that script INCLUDEs one other file. The two names in the message are the giveaway: the file being opened and an entry already recorded are different files, so the comparison that matched them is wrong. Two changes stack up to produce it. d048eee29108 ("ld: Use stat to check if linker script appears multiple times") changed the PR 24576 check from a name comparison to stat plus SAME_INODE. Then 47071f8b14a0 ("same-inode.h: don't depend on _GL_WINDOWS_STAT_INODES") dropped the guard in include/same-inode.h that had been expanding SAME_INODE to a literal 0 on native Windows. binutils never defines _GL_WINDOWS_STAT_INODES, so on Windows the check went from dead code to live in one release. The Windows CRT sets st_ino to 0 for every file. The guard that survived only rejects st_ino == 0 && st_dev == 0, and st_dev is the drive number, so on D: it is 3 and the guard passes. Every file on the drive then compares equal to every other file, and the first INCLUDE inside a -T script looks like a repeat of the script itself. The commit message of 47071f8b14a0 anticipates this: "this doesn't really make SAME_INODE usable on windows hosts as a number of the likely filesystems (FAT, HPFS, or NTFS) don't support st_ino." Fall back to comparing file names when stat gives no usable inode, so the duplicate detection keeps working on hosts where inodes are real and stops firing on files that merely share a device. PR 24576's own testcases still pass, including the ././/script spelling that a name comparison alone would miss, because hosts with real inodes still take the inode path. Signed-off-by: Cole Munz --- ld/ldfile.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/ld/ldfile.c b/ld/ldfile.c index 00fe1d90d44..cad1e168af0 100644 --- a/ld/ldfile.c +++ b/ld/ldfile.c @@ -881,15 +881,30 @@ ldfile_find_command_file (const char *name, the same linker script twice. */ if (stat (filename, &sbuf1) == 0) { - struct stat sbuf2; +#if defined _WIN32 && ! defined __CYGWIN__ + /* Native Windows stat reports st_ino as zero on most file + systems. Compare file names there. */ + bool have_inode = sbuf1.st_ino != 0; +#else + bool have_inode = true; +#endif + for (script = processed_scripts; script != NULL; script = script->next) - if ((open_how != script_nonT || script->open_how != script_nonT) - && stat (script->name, &sbuf2) == 0 - && SAME_INODE (sbuf1, sbuf2)) - fatal (_("%P: error: linker script file '%s (%s)'" - " appears multiple times\n"), filename, script->name); + { + struct stat sbuf2; + + if (open_how == script_nonT && script->open_how == script_nonT) + continue; + + if (have_inode + ? (stat (script->name, &sbuf2) == 0 + && SAME_INODE (sbuf1, sbuf2)) + : filename_cmp (filename, script->name) == 0) + fatal (_("%P: error: linker script file '%s (%s)'" + " appears multiple times\n"), filename, script->name); + } } len = strlen (filename); From af9387222dcb66e656807eb331c7f7d61b6b2af6 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 19 Aug 2026 10:29:09 +0200 Subject: [PATCH 14/17] [gdb/testsuite] Simplify regexp in gdb.rocm/watchpoint-at-end-of-shader.exp In gdb.rocm/watchpoint-at-end-of-shader.exp, we have: ... [multi_line "Switching to \[^\r\n\]+(?=\r\n)" \ "" \ ... This expands to "Switching to \[^\r\n\]+(?=\r\n)\r\n". The lookahead '(?=\r\n)' is superfluous (because it's followed by '\r\n'), so drop it. While we're at it, reduce escaping by using {}. --- gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp b/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp index 2ae0e044a53..298b5be9461 100644 --- a/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp +++ b/gdb/testsuite/gdb.rocm/watchpoint-at-end-of-shader.exp @@ -71,7 +71,8 @@ proc do_test {precise_memory has_xfail} { setup_xfail "*-*-*" } gdb_test "continue" \ - [multi_line "Switching to \[^\r\n\]+(?=\r\n)" \ + [multi_line \ + {Switching to [^\r\n]+} \ "" \ "Thread $::decimal \[^\r\n\]*hit Hardware watchpoint $::decimal: -location \\*v" \ "" \ From 5ac46e0aa6f18bb265fb4df3a3c9d1d15f2813d1 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 19 Aug 2026 10:35:20 +0200 Subject: [PATCH 15/17] [gdb/testsuite] Fix gdb.python/py-selected-context.exp regexp On ppc64-linux, with test-case gdb.python/py-selected-context.exp I run into: ... (gdb) info inferiors^M Num Description Connection Executable ^M 1 ^M * 2 ^M (gdb) FAIL: $exp: check inferior 2 was selected ... In contrast, on x86_64-linux, I get: ... (gdb) info inferiors^M Num Description Connection Executable ^M 1 ^M * 2 ^M (gdb) PASS: $exp: check inferior 2 was selected ... The output is identical, so it's surprising that there's a different outcome. The proc doing the check is: ... proc check_inferior { inf testname } { gdb_test "info inferiors" \ "\r\n\\*\\s+[string_to_regexp $inf]\\s+\[^\r\n\]*(?=\r\n)" \ $testname } ... The problem seems to be triggered by the lookahead part '(?=\r\n)': removing it makes the test pass. By switching on some debugging in gdb_test_multiple, we get this info: ... Looking to match ""(?:\r\n\*\s+2\s+[^\r\n]*(?=\r\n))\r\n\(gdb\) $"" ... which shows that the lookahead '(?=\r\n)' is immediately followed by a '\r\n', making the lookahead superfluous. Still, the test should not fail. It fails due to an expect bug [1][2]. But, there's another problem with the regexp. If we use the same proc to try to match inferior 1, we get a FAIL on both setups: ... (gdb) info inferiors^M Num Description Connection Executable ^M * 1 ^M 2 ^M (gdb) FAIL: $exp: check inferior 1 was selected ... The problem is that the regexp doesn't allow a line after the matching line. Fix this this by appending '.*' to the regexp. Doing so also has the effect that we no longer run into the expect problem. While we're at it, rewrite the regexp to a more modern form, and drop the unnecessary string_to_regexp: ... [multi_line \ "" \ [subst_vars {[*]\s+$inf\s+[^\r\n]*(?=\r\n).*}]] ... Tested on x86_64-linux and ppc64-linux. [1] https://sourceware.org/bugzilla/show_bug.cgi?id=34471 [2] https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1143513 --- gdb/testsuite/gdb.python/py-selected-context.exp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gdb/testsuite/gdb.python/py-selected-context.exp b/gdb/testsuite/gdb.python/py-selected-context.exp index 28b9b456003..07ace151f26 100644 --- a/gdb/testsuite/gdb.python/py-selected-context.exp +++ b/gdb/testsuite/gdb.python/py-selected-context.exp @@ -46,7 +46,9 @@ proc event_regexp { inferior {thread "None"} {frame "None"}} { # inferior. INF should be an inferior number, e.g. '1', '2', etc. proc check_inferior { inf testname } { gdb_test "info inferiors" \ - "\r\n\\*\\s+[string_to_regexp $inf]\\s+\[^\r\n\]*(?=\r\n)" \ + [multi_line \ + "" \ + [subst_vars {[*]\s+$inf\s+[^\r\n]*(?=\r\n).*}]] \ $testname } From 62b18dd418d99ff60d14eb2035439951fb9f448b Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 19 Aug 2026 10:47:25 +0200 Subject: [PATCH 16/17] [gdb/testsuite] Fix two test-cases on ppc64-linux Fix two test-cases on ppc64-linux, where the .dot prefix used in the v1 ABI is causing a mismatch. Tested on ppc64-linux and x86_64-linux. --- gdb/testsuite/gdb.ada/bp_c_mixed_case.exp | 6 +++++- gdb/testsuite/gdb.opt/break-on-_exit.exp | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp b/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp index 4dd4106649a..d428825e051 100644 --- a/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp +++ b/gdb/testsuite/gdb.ada/bp_c_mixed_case.exp @@ -60,8 +60,12 @@ gdb_test "p " \ " = void" \ "p , in Ada" +# The optional leading dot is for ppc64 v1 ABI function descriptors. gdb_test "p " \ - " = {} $hex " \ + [quotemeta \ + [string cat \ + {$@DECIMAL = {} @HEX} \ + { <@/[.]?/NoDebugMixedCaseFunc>}]] \ "p , in Ada" # Try inserting a breakpoint inside a C function. Because the function's diff --git a/gdb/testsuite/gdb.opt/break-on-_exit.exp b/gdb/testsuite/gdb.opt/break-on-_exit.exp index fa7cd96d61d..9caa54e4ad8 100644 --- a/gdb/testsuite/gdb.opt/break-on-_exit.exp +++ b/gdb/testsuite/gdb.opt/break-on-_exit.exp @@ -62,4 +62,6 @@ gdb_test "info shared" # If the skip_prologue analysis of _exit is too eager, we may not hit the # breakpoint. -gdb_continue_to_breakpoint "_exit" "_exit \\(\\) .*" +# The optional leading dot is for ppc64 v1 ABI function descriptors. +gdb_continue_to_breakpoint "_exit" \ + [quotemeta {@/[.]?/_exit () @...}] From 4ed310516eb76cbf650523a53f733060d3ae71b9 Mon Sep 17 00:00:00 2001 From: Tom de Vries Date: Wed, 19 Aug 2026 11:21:27 +0200 Subject: [PATCH 17/17] [gdb/testsuite] Fix gdb.tui/tailcall-msym.exp on ppc64-linux On ppc64-linux, with test-case gdb.tui/tailcall-msym.exp I ran into: ... FAIL: $exp: status bar says main ... The test-case: - compiles the source to executable tailcall-msym - gets some information about addresses - recompiles the source to assembly - adds some extra text to the assembly - compiles the updated assembly into tailcall-msym-updated The test-case source contains three functions: main, caller and callee. The idea is that the updated executable has the same instructions, but an additional function dumy_func at the location of the instructions of caller after the call to callee. On x86_64-linux, that looks like this: ... 000000000040111d : 40111d: 55 push %rbp 40111e: 48 89 e5 mov %rsp,%rbp 401121: e8 f0 ff ff ff call 401116 0000000000401126 : 401126: 8b 05 e8 2e 00 00 mov 0x2ee8(%rip),%eax 40112c: 83 c0 01 add $0x1,%eax 40112f: 89 05 df 2e 00 00 mov %eax,0x2edf(%rip) 401135: 8b 05 d9 2e 00 00 mov 0x2ed9(%rip),%eax 40113b: 83 c0 01 add $0x1,%eax 40113e: 89 05 d0 2e 00 00 mov %eax,0x2ed0(%rip) 401144: 90 nop 401145: 5d pop %rbp 401146: c3 ret ... On ppc64-linux using the v1 ABI that doesn't work out (because of the complex way functions are laid out in assembly), and instead caller stays the same, but main is renamed to dummy_func: ... (gdb) p dummy_func $3 = {} 0x9b0 (gdb) p main $4 = {} 0x9b0 (gdb) ... There's a note in the test-case: ... # Emit a new size for function 'caller', the assembler seems happy # enough to just use this new length instead of the original length # the compiler emitted. # # If this is ever a problem then we'll need to parse through the # assembler file and remove the original .size directive. ... and I tried that out manually, but it didn't help either. Fix this by bailing out if not all four functions exist: ... UNSUPPORTED: $exp: couldn't find function main ... Likewise in gdb.base/tailcall-msym.exp. Tested on ppc64-linux and x86_64-linux. --- gdb/testsuite/gdb.base/tailcall-msym.exp | 19 +++++++++++++++++ gdb/testsuite/gdb.tui/tailcall-msym.exp | 27 +++++++++++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-) diff --git a/gdb/testsuite/gdb.base/tailcall-msym.exp b/gdb/testsuite/gdb.base/tailcall-msym.exp index d6cd06f88cd..9ffaa7f17c1 100644 --- a/gdb/testsuite/gdb.base/tailcall-msym.exp +++ b/gdb/testsuite/gdb.base/tailcall-msym.exp @@ -132,6 +132,25 @@ if { [prepare_for_testing "prepare" ${testfile}-updated $asm_file {nodebug}] } { return } +foreach func {caller callee main dummy_func} { + set re_found \ + "^$valnum_re = {} $hex <$func>" + + set found 0 + gdb_test_multiple "p $func" "" { + -re -wrap $re_found { + set found 1 + } + -re -wrap "" { + } + } + + if {!$found} { + unsupported "couldn't find function $func" + return + } +} + if {![runto callee]} { return } diff --git a/gdb/testsuite/gdb.tui/tailcall-msym.exp b/gdb/testsuite/gdb.tui/tailcall-msym.exp index 81b52355c01..1e13414f760 100644 --- a/gdb/testsuite/gdb.tui/tailcall-msym.exp +++ b/gdb/testsuite/gdb.tui/tailcall-msym.exp @@ -136,15 +136,36 @@ if { [build_executable "build" $real_testfile $asm_file {nodebug}] } { Term::clean_restart 24 80 $real_testfile -if {![runto callee]} { +if {![Term::prepare_for_tui]} { + unsupported "TUI not supported" return } -if {![Term::enter_tui]} { - unsupported "TUI not supported" +foreach func {caller callee main dummy_func} { + set re_found \ + "^$valnum_re = {} $hex <$func>" + + set found 0 + gdb_test_multiple "p $func" "" { + -re -wrap $re_found { + set found 1 + } + -re -wrap "" { + } + } + + if {!$found} { + unsupported "couldn't find function $func" + return + } +} + +if {![runto callee]} { return } +Term::command_no_prompt_prefix "tui enable" + # Check the function name on display in the status bar. The interesting # case here is 'caller', which is a tailcall function in an objfile with # no debug information.