Read Ada main name from executable, not inferior

An upstream bug report points out this bug: if the user switches from
one Ada executable to another without "kill"ing the inferior, then the
"start" command will fail.

What happens here is that the Ada "main" name is found in a constant
string in the executable.  But, if the inferior is running, then the
process_stratum target reads from the inferior memory.

This patch fixes the problem by changing the main name code to set
trust-readonly-sections, causing the target stack to read from the
executable instead.

I looked briefly at changing GNAT to emit DW_AT_main_subprogram
instead, but this looks to be pretty involved.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25811
This commit is contained in:
Tom Tromey 2023-08-21 09:55:14 -06:00
parent 655e4e52ef
commit 358be6e72d
6 changed files with 132 additions and 3 deletions

View File

@ -814,6 +814,13 @@ ada_main_name ()
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 ();
}

View File

@ -116,10 +116,9 @@ static struct target_ops *the_debug_target;
static struct cmd_list_element *targetlist = NULL;
/* True if we should trust readonly sections from the
executable when reading memory. */
/* See target.h. */
static bool trust_readonly = false;
bool trust_readonly = false;
/* Nonzero if we should show true memory content including
memory breakpoint inserted by gdb. */

View File

@ -2477,6 +2477,10 @@ extern int remote_timeout;
extern scoped_restore_tmpl<int>
make_scoped_restore_show_memory_breakpoints (int show);
/* True if we should trust readonly sections from the
executable when reading memory. */
extern bool trust_readonly;
extern bool may_write_registers;
extern bool may_write_memory;
extern bool may_insert_breakpoints;

View File

@ -0,0 +1,69 @@
# Copyright 2023 Free Software Foundation, Inc.
# 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, see <http://www.gnu.org/licenses/>.
load_lib "ada.exp"
require allow_ada_tests
# This testcase verifies the behavior of the `start' command, which
# does not work when we use the gdb stub...
require !use_gdb_stub
standard_ada_testfile first
if {[gdb_compile_ada "${srcfile}" "${binfile}" executable {debug}] != ""} {
return -1
}
# Build the second test program
set srcfile2 ${srcdir}/${subdir}/${testdir}/second.adb
set binfile2 [standard_output_file second]
if {[gdb_compile_ada "${srcfile2}" "${binfile2}" executable {debug}] != ""} {
return -1
}
foreach_with_prefix scenario {kill no-kill} {
clean_restart $binfile
# Start the program, we should land in the program main procedure
if {[gdb_start_cmd] < 0} {
fail start
return -1
}
gdb_test "" \
"first \\(\\) at .*first.adb.*" \
"start first"
gdb_test_no_output "set confirm off"
if {$scenario == "kill"} {
gdb_test "kill" "Inferior $decimal .*killed.*"
}
gdb_test "file $binfile2" "Reading symbols from .*" \
"switch to second executable"
# Start the program a second time, GDB should land in procedure
# Second this time.
if {[gdb_start_cmd] < 0} {
fail "start second"
} else {
gdb_test "" \
"second \\(\\) at .*second.adb.*" \
"start second"
}
}

View File

@ -0,0 +1,25 @@
-- Copyright 2005-2023 Free Software Foundation, Inc.
--
-- 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, see <http://www.gnu.org/licenses/>.
procedure First is
procedure Break_Me is
begin
null;
end Break_Me;
begin
Break_Me;
end First;

View File

@ -0,0 +1,25 @@
-- Copyright 2005-2023 Free Software Foundation, Inc.
--
-- 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, see <http://www.gnu.org/licenses/>.
procedure Second is
procedure Break_Me is
begin
null;
end Break_Me;
begin
Break_Me;
end Second;