* [PATCH] Always fetch Ada "main" name from the executable
@ 2026-07-30 17:03 Tom Tromey
2026-07-31 10:48 ` Pedro Alves
2026-08-05 17:07 ` Andrew Burgess
0 siblings, 2 replies; 5+ messages in thread
From: Tom Tromey @ 2026-07-30 17:03 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey
The gdb.ada/file-then-restart.exp test was failing with gnat-llvm. I
tracked this down to the "main" name not being stored in a readonly
section, meaning that the code in ada_main_name using trust_readonly
did not work.
However, it seems to me that gdb should always prefer the data from
the executable in this particular case. So, rather than relying on
trust_readonly, this patch changes gdb to do this directly.
---
gdb/ada-lang.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3c6c9af488f..906c5cd3465 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -775,8 +775,6 @@ ada_get_decoded_type (struct type *type)
const char *
ada_main_name ()
{
- static gdb::unique_xmalloc_ptr<char> main_program_name;
-
/* For Ada, the name of the main procedure is stored in a specific
string constant, generated by the binder. Look for that symbol,
extract its address, and then read that string. If we didn't find
@@ -786,21 +784,31 @@ ada_main_name ()
= lookup_minimal_symbol (current_program_space,
ADA_MAIN_PROGRAM_SYMBOL_NAME);
- if (msym.minsym != NULL)
+ if (msym.minsym != nullptr)
{
+ static gdb_byte main_program_name[1024];
+
CORE_ADDR main_program_name_addr = msym.value_address ();
if (main_program_name_addr == 0)
error (_("Invalid address for Ada main program name."));
- /* Force trust_readonly, because we always want to fetch this
- string from the executable, not from inferior memory. If the
- user changes the exec-file and invokes "start", we want to
- pick the "main" from the new executable, not one that may
- come from the still-live inferior. */
- scoped_restore save_trust_readonly
- = make_scoped_restore (&trust_readonly, true);
- main_program_name = target_read_string (main_program_name_addr, 1024);
- return main_program_name.get ();
+ /* We always want to fetch this string from the executable, not
+ from inferior memory. If the user changes the exec-file and
+ invokes "start", we want to pick the "main" from the new
+ executable, not one that may come from the still-live
+ inferior. */
+ ULONGEST xferred = 0;
+ const auto §ions = current_program_space->target_sections ();
+ if ((section_table_xfer_memory_partial (main_program_name, nullptr,
+ main_program_name_addr,
+ sizeof (main_program_name),
+ &xferred,
+ sections)
+ == TARGET_XFER_OK)
+ && xferred > 0
+ && (strnlen ((char *) main_program_name, sizeof (main_program_name))
+ < sizeof (main_program_name)))
+ return (char *) main_program_name;
}
/* The main procedure doesn't seem to be in Ada. */
base-commit: 6d1be0b90e837e4c82eaaf6f9e8c7da7227902e1
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] Always fetch Ada "main" name from the executable
2026-07-30 17:03 [PATCH] Always fetch Ada "main" name from the executable Tom Tromey
@ 2026-07-31 10:48 ` Pedro Alves
2026-08-05 17:07 ` Andrew Burgess
1 sibling, 0 replies; 5+ messages in thread
From: Pedro Alves @ 2026-07-31 10:48 UTC (permalink / raw)
To: Tom Tromey, gdb-patches
FWIW, I was intrigued by the subject, so I took a look, and ...
On 2026-07-30 18:03, Tom Tromey wrote:
> The gdb.ada/file-then-restart.exp test was failing with gnat-llvm. I
> tracked this down to the "main" name not being stored in a readonly
> section, meaning that the code in ada_main_name using trust_readonly
> did not work.
>
> However, it seems to me that gdb should always prefer the data from
> the executable in this particular case. So, rather than relying on
> trust_readonly, this patch changes gdb to do this directly.
... this LGTM.
Approved-By: Pedro Alves <pedro@palves.net>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] Always fetch Ada "main" name from the executable
2026-07-30 17:03 [PATCH] Always fetch Ada "main" name from the executable Tom Tromey
2026-07-31 10:48 ` Pedro Alves
@ 2026-08-05 17:07 ` Andrew Burgess
2026-08-07 13:55 ` Tom Tromey
1 sibling, 1 reply; 5+ messages in thread
From: Andrew Burgess @ 2026-08-05 17:07 UTC (permalink / raw)
To: Tom Tromey, gdb-patches; +Cc: Tom Tromey
Tom Tromey <tromey@adacore.com> writes:
> The gdb.ada/file-then-restart.exp test was failing with gnat-llvm. I
> tracked this down to the "main" name not being stored in a readonly
> section, meaning that the code in ada_main_name using trust_readonly
> did not work.
>
> However, it seems to me that gdb should always prefer the data from
> the executable in this particular case. So, rather than relying on
> trust_readonly, this patch changes gdb to do this directly.
I was pointed at this:
https://sourceware.org/pipermail/bunsen/2026q3/001484.html
It's an AI/LLM code review of this patch. The review in this case seems
to be totally bogus, everything it is commenting on is either fine, or
is part of the documented API of the function.
However, I asked Claude to review the patch and it did highlight one
issue. It's mostly theoretical, but fixing it is trivial, so we might
as well.
Let me know what you think.
Thanks,
Andrew
---
commit 5990efb77092a3a02330260b88899d5a8b15bca7
Author: Andrew Burgess <aburgess@redhat.com>
Date: Wed Aug 5 17:23:38 2026 +0100
gdb/ada: avoid rereading stale main name data in edge case
The commit:
commit 8eafbbc74748e499ec785f78858687bd7ea79005
Date: Wed Jul 29 12:40:03 2026 -0600
Always fetch Ada "main" name from the executable
changes ada_main_name to use section_table_xfer_memory_partial. This
introduced a highly unlikely, but theoretical bug where stale buffer
data could cause GDB to find an invalid name for "main".
Looking at ada_main_name (in ada-lang.c), the steps to reproduce the
bug are:
1. Debug a program that causes the static buffer main_program_name
to have some content written to it. For the sake of this bug
let's assume the main name is "xxxxxxxxxx", the main_program_name
buffer will contain 10 'x' characters, a null byte, then whatever
happened to be in the section after that.
2. A new executable is loaded into GDB and ada_main_name is called
again.
3. For whatever reason the new executable is maybe not correct. The
ADA_MAIN_PROGRAM_SYMBOL_NAME symbol points to an address 5 bytes
before the end of a section. None of these 5 bytes are a null
bytes. Let's assume these 5 bytes are "aaaaa".
4. The section_table_xfer_memory_partial call will try to read up to
1024 bytes, but as there are only 5 bytes left in the section,
only 5 will be read. This leaves the main_program_name buffer
containing "aaaaaxxxxx" followed by a null character byte.
5. GDB returns this merged string as the result from ada_main_name.
Now given this depends on the second executable being broken, we maybe
don't really care too much, however, fixing this is pretty easy.
The current code already checks:
&& (strnlen ((char *) main_program_name, sizeof (main_program_name))
< sizeof (main_program_name))
This ensures that there's a string with a null byte contained within
the buffer, but makes the assumption that we always read
sizeof (main_program_name) bytes from the section.
But we know how many bytes were read, that's the value in XFERRED.
What we really want to ask is: was there a null terminated string
within the bytes that we just read. This is:
&& (strnlen ((char *) main_program_name, xferred) < xferred)
Given how simple this fix is, let's make it.
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 906c5cd3465..174e04af04c 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -806,8 +806,7 @@ ada_main_name ()
sections)
== TARGET_XFER_OK)
&& xferred > 0
- && (strnlen ((char *) main_program_name, sizeof (main_program_name))
- < sizeof (main_program_name)))
+ && (strnlen ((char *) main_program_name, xferred) < xferred))
return (char *) main_program_name;
}
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] Always fetch Ada "main" name from the executable
2026-08-05 17:07 ` Andrew Burgess
@ 2026-08-07 13:55 ` Tom Tromey
2026-08-07 15:03 ` Andrew Burgess
0 siblings, 1 reply; 5+ messages in thread
From: Tom Tromey @ 2026-08-07 13:55 UTC (permalink / raw)
To: Andrew Burgess; +Cc: Tom Tromey, gdb-patches
>>>>> "Andrew" == Andrew Burgess <aburgess@redhat.com> writes:
Andrew> gdb/ada: avoid rereading stale main name data in edge case
Andrew> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
Andrew> index 906c5cd3465..174e04af04c 100644
Andrew> --- a/gdb/ada-lang.c
Andrew> +++ b/gdb/ada-lang.c
Andrew> @@ -806,8 +806,7 @@ ada_main_name ()
Andrew> sections)
Andrew> == TARGET_XFER_OK)
Andrew> && xferred > 0
Andrew> - && (strnlen ((char *) main_program_name, sizeof (main_program_name))
Andrew> - < sizeof (main_program_name)))
Andrew> + && (strnlen ((char *) main_program_name, xferred) < xferred))
Andrew> return (char *) main_program_name;
Andrew> }
Looks good to me.
I suppose xferred < sizeof (main_program_name) and so the first strnlen
is probably now redundant. However this doesn't really matter, the main
name is not examined very often.
Approved-By: Tom Tromey <tom@tromey.com>
Tom
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH] Always fetch Ada "main" name from the executable
2026-08-07 13:55 ` Tom Tromey
@ 2026-08-07 15:03 ` Andrew Burgess
0 siblings, 0 replies; 5+ messages in thread
From: Andrew Burgess @ 2026-08-07 15:03 UTC (permalink / raw)
To: Tom Tromey; +Cc: Tom Tromey, gdb-patches
Tom Tromey <tromey@adacore.com> writes:
>>>>>> "Andrew" == Andrew Burgess <aburgess@redhat.com> writes:
>
> Andrew> gdb/ada: avoid rereading stale main name data in edge case
>
> Andrew> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> Andrew> index 906c5cd3465..174e04af04c 100644
> Andrew> --- a/gdb/ada-lang.c
> Andrew> +++ b/gdb/ada-lang.c
> Andrew> @@ -806,8 +806,7 @@ ada_main_name ()
> Andrew> sections)
> Andrew> == TARGET_XFER_OK)
> Andrew> && xferred > 0
> Andrew> - && (strnlen ((char *) main_program_name, sizeof (main_program_name))
> Andrew> - < sizeof (main_program_name)))
> Andrew> + && (strnlen ((char *) main_program_name, xferred) < xferred))
> Andrew> return (char *) main_program_name;
> Andrew> }
>
> Looks good to me.
>
> I suppose xferred < sizeof (main_program_name) and so the first strnlen
I did think about this, but the section_table_xfer_memory_partial call
is capped at 'sizeof (main_program_name)' so this check would really be
an assert.
But as the section_table_xfer_memory_partial call is part of this same
`if` condition we'd have to split the code like:
if (section_table_xfer_memory_partial (....) == TARGET_XFER_OK)
{
gdb_assert (xferred < sizeof (main_program_name));
if (xferred > 0
&& strnlen ((char *) main_program_name, xferred) < xferred)
return (char *) main_program_name;
}
And the extra complexity didn't seem worth it.
> is probably now redundant. However this doesn't really matter, the main
> name is not examined very often.
>
> Approved-By: Tom Tromey <tom@tromey.com>
I've pushed the patch now.
Thanks,
Andrew
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-07 15:03 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-30 17:03 [PATCH] Always fetch Ada "main" name from the executable Tom Tromey
2026-07-31 10:48 ` Pedro Alves
2026-08-05 17:07 ` Andrew Burgess
2026-08-07 13:55 ` Tom Tromey
2026-08-07 15:03 ` Andrew Burgess
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox