aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite
diff options
context:
space:
mode:
authorAndrew Burgess <aburgess@redhat.com>2024-04-25 09:36:43 +0100
committerAndrew Burgess <aburgess@redhat.com>2024-12-24 14:15:24 +0000
commitd3d13bf876aae425ae0eff2ab0f1af9f7da0264a (patch)
tree96b4683cb2a1974d84650f798c58552e0996bb91 /gdb/testsuite
parent1eb397a6d20b312df11e787533f32d2312ced215 (diff)
downloadgdb-d3d13bf876aae425ae0eff2ab0f1af9f7da0264a.zip
gdb-d3d13bf876aae425ae0eff2ab0f1af9f7da0264a.tar.gz
gdb-d3d13bf876aae425ae0eff2ab0f1af9f7da0264a.tar.bz2
gdb: add gdbarch method to get execution context from core file
Add a new gdbarch method which can read the execution context from a core file. An execution context, for this commit, means the filename of the executable used to generate the core file and the arguments passed to the executable. In later commits this will be extended further to include the environment in which the executable was run, but this commit is already pretty big, so I've split that part out into a later commit. Initially this new gdbarch method is only implemented for Linux targets, but a later commit will add FreeBSD support too. Currently when GDB opens a core file, GDB reports the command and arguments used to generate the core file. For example: (gdb) core-file ./core.521524 [New LWP 521524] Core was generated by `./gen-core abc def'. However, this information comes from the psinfo structure in the core file, and this struct only allows 80 characters for the command and arguments combined. If the command and arguments exceed this then they are truncated. Additionally, neither the executable nor the arguments are quoted in the psinfo structure, so if, for example, the executable was named 'aaa bbb' (i.e. contains white space) and was run with the arguments 'ccc' and 'ddd', then when this core file was opened by GDB we'd see: (gdb) core-file ./core.521524 [New LWP 521524] Core was generated by `./aaa bbb ccc ddd'. It is impossible to know if 'bbb' is part of the executable filename, or another argument. However, the kernel places the executable command onto the user stack, this is pointed to by the AT_EXECFN entry in the auxv vector. Additionally, the inferior arguments are all available on the user stack. The new gdbarch method added in this commit extracts this information from the user stack and allows GDB to access it. The information on the stack is writable by the user, so a user application can start up, edit the arguments, override the AT_EXECFN string, and then dump core. In this case GDB will report incorrect information, however, it is worth noting that the psinfo structure is also filled (by the kernel) by just copying information from the user stack, so, if the user edits the on stack arguments, the values reported in psinfo will change, so the new approach is no worse than what we currently have. The benefit of this approach is that GDB gets to report the full executable name and all the arguments without the 80 character limit, and GDB is aware which parts are the executable name, and which parts are arguments, so we can, for example, style the executable name. Another benefit is that, now we know all the arguments, we can poke these into the inferior object. This means that after loading a core file a user can 'show args' to see the arguments used. A user could even transition from core file debugging to live inferior debugging using, e.g. 'run', and GDB would restart the inferior with the correct arguments. Now the downside: finding the AT_EXECFN string is easy, the auxv entry points directly too it. However, finding the arguments is a little trickier. There's currently no easy way to get a direct pointer to the arguments. Instead, I've got a heuristic which I believe should find the arguments in most cases. The algorithm is laid out in linux-tdep.c, I'll not repeat it here, but it's basically a search of the user stack, starting from AT_EXECFN. If the new heuristic fails then GDB just falls back to the old approach, asking bfd to read the psinfo structure for us, which gives the old 80 character limited answer. For testing, I've run this series on (all GNU/Linux) x86-64. s390, ppc64le, and the new test passes in each case. I've done some very basic testing on ARM which does things a little different than the other architectures mentioned, see ARM specific notes in linux_corefile_parse_exec_context_1 for details.
Diffstat (limited to 'gdb/testsuite')
-rw-r--r--gdb/testsuite/gdb.base/corefile-exec-context.c25
-rw-r--r--gdb/testsuite/gdb.base/corefile-exec-context.exp102
2 files changed, 127 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.base/corefile-exec-context.c b/gdb/testsuite/gdb.base/corefile-exec-context.c
new file mode 100644
index 0000000..ed4df60
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile-exec-context.c
@@ -0,0 +1,25 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 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/>. */
+
+#include <stdlib.h>
+
+int
+main (int argc, char **argv)
+{
+ abort ();
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/corefile-exec-context.exp b/gdb/testsuite/gdb.base/corefile-exec-context.exp
new file mode 100644
index 0000000..b18a810
--- /dev/null
+++ b/gdb/testsuite/gdb.base/corefile-exec-context.exp
@@ -0,0 +1,102 @@
+# Copyright 2024 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/>.
+
+# Check GDB can handle reading the full executable name and argument
+# list from a core file.
+#
+# Currently, only Linux supports reading full executable and arguments
+# from a core file.
+require {istarget *-linux*}
+
+standard_testfile
+
+if {[build_executable $testfile.exp $testfile $srcfile] == -1} {
+ untested "failed to compile"
+ return -1
+}
+
+# Linux core files can encore upto 80 characters for the command and
+# arguments in the psinfo. If BINFILE is less than 80 characters in
+# length then lets try to make it longer.
+set binfile_len [string length $binfile]
+if { $binfile_len <= 80 } {
+ set extra_len [expr 80 - $binfile_len + 1]
+ set extra_str [string repeat "x" $extra_len]
+ set new_binfile $binfile$extra_str
+ remote_exec build "mv $binfile $new_binfile"
+ set binfile $new_binfile
+}
+
+# Generate a core file, this time the inferior has no additional
+# arguments.
+set corefile [core_find $binfile {}]
+if {$corefile == ""} {
+ untested "unable to create corefile"
+ return 0
+}
+set corefile_1 "$binfile.1.core"
+remote_exec build "mv $corefile $corefile_1"
+
+# Load the core file and confirm that the full executable name is
+# seen.
+clean_restart $binfile
+set saw_generated_line false
+gdb_test_multiple "core-file $corefile_1" "load core file no args" {
+ -re "^Core was generated by `[string_to_regexp $binfile]'\\.\r\n" {
+ set saw_generated_line true
+ exp_continue
+ }
+
+ -re "^$gdb_prompt $" {
+ gdb_assert { $saw_generated_line } $gdb_test_name
+ }
+
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
+
+# Generate a core file, this time pass some arguments to the inferior.
+set args "aaaaa bbbbb ccccc ddddd eeeee"
+set corefile [core_find $binfile {} $args]
+if {$corefile == ""} {
+ untested "unable to create corefile"
+ return 0
+}
+set corefile_2 "$binfile.2.core"
+remote_exec build "mv $corefile $corefile_2"
+
+# Load the core file and confirm that the full executable name and
+# argument list are seen.
+clean_restart $binfile
+set saw_generated_line false
+gdb_test_multiple "core-file $corefile_2" "load core file with args" {
+ -re "^Core was generated by `[string_to_regexp $binfile] $args'\\.\r\n" {
+ set saw_generated_line true
+ exp_continue
+ }
+
+ -re "^$gdb_prompt $" {
+ gdb_assert { $saw_generated_line } $gdb_test_name
+ }
+
+ -re "^\[^\r\n\]*\r\n" {
+ exp_continue
+ }
+}
+
+# Also, the argument list should be available through 'show args'.
+gdb_test "show args" \
+ "Argument list to give program being debugged when it is started is \"$args\"\\."