public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Andrew Burgess <aburgess@redhat.com>
To: gdb-patches@sourceware.org
Cc: Andrew Burgess <aburgess@redhat.com>
Subject: [PATCHv2 3/5] gdb/testsuite: make some of the core file / build-id tests harder
Date: Mon, 28 Oct 2024 18:53:36 +0000	[thread overview]
Message-ID: <4aa82991a3fc95d3b1ff00c896cd5cfcd23fb237.1730141493.git.aburgess@redhat.com> (raw)
In-Reply-To: <cover.1730141493.git.aburgess@redhat.com>

We have a few tests that load core files, which depend on GDB not
auto-loading the executable that matches the core file.  One of these
tests (corefile-buildid.exp) exercises GDB's ability to load the
executable via the build-id links in the debug directory, while the
other two tests are just written assuming that GDB hasn't auto-loaded
the executable.

In the next commit, GDB is going to get better at finding the
executable for a core file, and as a consequence these tests could
start to fail if the testsuite is being run using a compiler that adds
build-ids by default, and is on a target (currently only Linux) with
the improved executable auto-loading.

To avoid these test failures, this commit updates some of the tests.

coredump-filter.exp and corefile.exp are updated to unload the
executable should it be auto-loaded.  This means that the following
output from GDB will match the expected patterns.  If the executable
wasn't auto-loaded then the new step to unload is harmless.

The corefile-buildid.exp test needed some more significant changes.
For this test it is important that the executable be moved aside so
that GDB can't locate it, but we do still need the executable around
somewhere, so that the debug directory can link to it.  The point of
the test is that the executable _should_ be auto-loaded, but using the
debug directory, not using GDB's context parsing logic.

While looking at this test I noticed two additional problems, first we
were creating the core file more times than we needed.  We only need
to create one core file for each test binary (total two), while we
previously created one core file for each style of debug info
directory (total four).  The extra core files should be identical, and
were just overwriting each other, harmless, but still pointless work.

The other problem is that after running an earlier test we modified
the test binary in order to run a later test.  This means it's not
possible to manually re-run the first test as the binary for that test
is destroyed.

As part of the rewrite in this commit I've addressed these issues.

This test does change many of the test names, but there should be no
real changes in what is being tested after this commit.  However, when
the next commit is added, and GDB gets better at auto-loading the
executable for a core file, these tests should still be testing what
is expected.
---
 gdb/testsuite/gdb.base/coredump-filter.exp  |  17 +-
 gdb/testsuite/gdb.base/corefile-buildid.exp | 252 +++++++++-----------
 gdb/testsuite/gdb.base/corefile.exp         |   9 +
 3 files changed, 130 insertions(+), 148 deletions(-)

diff --git a/gdb/testsuite/gdb.base/coredump-filter.exp b/gdb/testsuite/gdb.base/coredump-filter.exp
index 0c1fc7c2dd6..18c3505172b 100644
--- a/gdb/testsuite/gdb.base/coredump-filter.exp
+++ b/gdb/testsuite/gdb.base/coredump-filter.exp
@@ -105,14 +105,23 @@ proc test_disasm { core address should_fail } {
 	    return
 	}
 
+	# If GDB managed to auto-load an executable based on the core
+	# file, then unload it now.
+	gdb_test "with confirm off -- file" \
+	    [multi_line \
+		 "^No executable file now\\." \
+		 "No symbol file now\\."] \
+	    "ensure no executable is loaded"
+
 	if { $should_fail == 1 } {
 	    remote_exec host "mv -f $hide_binfile $binfile"
-	    gdb_test "x/i \$pc" "=> $hex:\tCannot access memory at address $hex" \
-		"disassemble function with corefile and without a binary"
+	    set re "Cannot access memory at address $hex"
 	} else {
-	    gdb_test "x/i \$pc" "=> $hex:\t\[^C\].*" \
-		"disassemble function with corefile and without a binary"
+	    set re "\[^C\].*"
 	}
+
+	gdb_test "x/i \$pc" "=> $hex:\t${re}" \
+	    "disassemble function with corefile and without a binary"
     }
 
     with_test_prefix "with binary" {
diff --git a/gdb/testsuite/gdb.base/corefile-buildid.exp b/gdb/testsuite/gdb.base/corefile-buildid.exp
index fc54cf201d9..377ae802239 100644
--- a/gdb/testsuite/gdb.base/corefile-buildid.exp
+++ b/gdb/testsuite/gdb.base/corefile-buildid.exp
@@ -19,71 +19,72 @@
 
 # Build-id-related tests for core files.
 
-standard_testfile
+standard_testfile .c -shlib-shr.c -shlib.c
 
-# Build a non-shared executable.
+# Create a corefile from PROGNAME.  Return the name of the generated
+# corefile, or the empty string if anything goes wrong.
+#
+# The generated corefile must contain a buildid for PROGNAME.  If it
+# doesn't then an empty string will be returned.
+proc create_core_file { progname } {
+    # Generate a corefile.
+    set corefile [core_find $progname]
+    if {$corefile == ""} {
+	untested "could not generate core file"
+	return ""
+    }
+    verbose -log "corefile is $corefile"
+
+    # Check the corefile has a build-id for the executable.
+    if { [catch "exec [gdb_find_eu-unstrip] -n --core $corefile" output] == 0 } {
+	set line [lindex [split $output "\n"] 0]
+	set binfile_re (?:[string_to_regexp $progname]|\\\[(?:exe|pie)\\\])
+	if { ![regexp "^${::hex}\\+${::hex} \[a-f0-9\]+@${::hex}.*$binfile_re$" $line] } {
+	    unsupported "no build-id for executable in corefile"
+	    return ""
+	}
+    } else {
+	unsupported "eu-unstrip tool failed"
+	return ""
+    }
 
-proc build_corefile_buildid_exec {} {
-    global testfile srcfile binfile execdir
+    return $corefile
+}
 
-    if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
-	untested "failed to compile"
-	return false
-    }
 
-    # Move executable to non-default path.
-    set builddir [standard_output_file $execdir]
-    remote_exec build "rm -rf $builddir"
-    remote_exec build "mkdir $builddir"
-    remote_exec build "mv $binfile [file join $builddir [file tail $binfile]]"
+# Build a non-shared executable.
 
-    return true
+proc build_corefile_buildid_exec { progname } {
+    return [expr {[build_executable "build non-shared exec" $progname $::srcfile] != -1}]
 }
 
 # Build a shared executable.
 
-proc build_corefile_buildid_shared {} {
-    global srcdir subdir testfile binfile srcfile sharedir
-
-    set builddir [standard_output_file $sharedir]
-
+proc build_corefile_buildid_shared { progname } {
     # Compile DSO.
-    set srcdso [file join $srcdir $subdir $testfile-shlib-shr.c]
-    set objdso [standard_output_file $testfile-shlib-shr.so]
-    if {[gdb_compile_shlib $srcdso $objdso {debug}] != ""} {
-	untested "failed to compile dso"
+    set objdso [standard_output_file $::testfile-shlib-shr.so]
+    if {[build_executable "build dso" $objdso $::srcfile2 {debug shlib}] == -1} {
 	return false
     }
 
+
     # Compile shared library.
-    set srclib [file join $srcdir $subdir $testfile-shlib.c]
-    set libname lib$testfile.so
+    set srclib $::srcfile3
+    set libname lib$::testfile.so
     set objlib [standard_output_file $libname]
-    set dlopen_lib [shlib_target_file \
-			[file join $builddir [file tail $objdso]]]
-    set opts [list debug shlib_load \
+    set dlopen_lib [shlib_target_file $objdso]
+    set opts [list debug shlib_load shlib \
 		  additional_flags=-DSHLIB_NAME=\"$dlopen_lib\"]
-    if {[gdb_compile_shlib $srclib $objlib $opts] != ""} {
-	untested "failed to compile shared library"
+    if {[build_executable "build solib" $objlib $::srcfile3 $opts] == -1} {
 	return false
     }
 
     # Compile main program.
-    set srcexec [file join $srcdir $subdir $srcfile]
-    set binfile [standard_output_file $testfile-shared]
     set opts [list debug shlib=$objlib additional_flags=-DTEST_SHARED]
-    if {[gdb_compile $srcexec $binfile executable $opts] != ""} {
-	untested "failed to compile shared executable"
+    if {[build_executable "build shared exec" $progname $::srcfile $opts] == -1} {
 	return false
     }
 
-    # Move objects to non-default path.
-    remote_exec build "rm -rf $builddir"
-    remote_exec build "mkdir $builddir"
-    remote_exec build "mv $binfile $builddir"
-    remote_exec build "mv $objdso  $builddir"
-    remote_exec build "mv $objlib $builddir"
-
     return true
 }
 
@@ -154,37 +155,43 @@ proc check_exec_file {file} {
 # SHARED is a boolean indicating whether we are testing the shared
 # library core dump test case.
 
-proc locate_exec_from_core_build_id {corefile buildid suffix \
+proc locate_exec_from_core_build_id {corefile buildid \
+					 dirname progname \
 					 sepdebug symlink shared} {
-    global testfile binfile srcfile
-
     clean_restart
 
     # Set up the build-id directory and symlink the binary there.
+    set d "debugdir"
+    if {$shared} {
+	set d "${d}_shared"
+    } else {
+	set d "${d}_not-shared"
+    }
     if {$symlink} {
-	set d "symlinkdir"
+	set d "${d}_symlink"
     } else {
-	set d "debugdir"
+	set d "${d}_copy"
     }
-    set debugdir [standard_output_file $d-$suffix]
-    remote_exec build "rm -rf $debugdir"
+    if {$sepdebug} {
+	set d "${d}_stripped"
+    } else {
+	set d "${d}_not-stripped"
+    }
+
+    set debugdir [standard_output_file $d]
     remote_exec build \
 	"mkdir -p [file join $debugdir [file dirname $buildid]]"
 
     set files_list {}
-    lappend files_list $binfile $buildid
+    lappend files_list [file join $dirname [file tail $progname]] \
+	$buildid
     if {$sepdebug} {
-	lappend files_list "$binfile.debug" "$buildid.debug"
-    }
-    if {$shared} {
-	global sharedir
-	set builddir [standard_output_file $sharedir]
-    } else {
-	global execdir
-	set builddir [standard_output_file $execdir]
+	lappend files_list [file join $dirname [file tail $progname]].debug \
+	    "$buildid.debug"
     }
+
     foreach {target name} $files_list {
-	set t [file join $builddir [file tail $target]]
+	set t [file join $dirname [file tail $target]]
 	if {$symlink} {
 	    remote_exec build "ln -s $t [file join $debugdir $name]"
 	} else {
@@ -198,109 +205,66 @@ proc locate_exec_from_core_build_id {corefile buildid suffix \
     gdb_test "core-file $corefile" "Program terminated with .*" \
 	"load core file"
     if {$symlink} {
-	set expected_file [file join $builddir [file tail $binfile]]
+	set expected_file [file join $dirname [file tail $progname]]
     } else {
 	set expected_file $buildid
     }
     check_exec_file [file join $debugdir $expected_file]
 }
 
-# Run a build-id tests on a core file.
-# Supported options: "-shared" and "-sepdebug" for running tests
-# of shared and/or stripped/.debug executables.
-
-proc do_corefile_buildid_tests {args} {
-    global binfile testfile srcfile execdir sharedir hex
-
-    # Parse options.
-    parse_args [list {sepdebug} {shared}]
+foreach_with_prefix mode { exec shared } {
+    # Build the executable.
+    set progname ${binfile}-$mode
+    set build_proc build_corefile_buildid_${mode}
+    if { ![$build_proc $progname] } {
+	return -1
+    }
 
-    # PROGRAM to run to generate core file.  This could be different
-    # than the program that was originally built, e.g., for a stripped
-    # executable.
-    if {$shared} {
-	set builddir [standard_output_file $sharedir]
-    } else {
-	set builddir [standard_output_file $execdir]
+    # Generate a corefile.
+    set corefile [create_core_file $progname]
+    if { $corefile eq "" } {
+	return -1
     }
-    set program_to_run [file join $builddir [file tail $binfile]]
 
-    # A list of suffixes to use to describe the test and the .build-id
-    # directory for the test.  The suffix will be used, joined with spaces,
-    # to prefix all tests for the given run.  It will be used, joined with
-    # dashes, to create a unique build-id directory.
-    set suffix {}
-    if {$shared} {
-	lappend suffix "shared"
-    } else {
-	lappend suffix "exec"
+    # Get the build-id filename without ".debug" on the end.  This
+    # will have the format: '.build-id/xx/xxxxx'
+    set buildid [build_id_debug_filename_get $progname ""]
+    if {$buildid == ""} {
+	untested "binary has no build-id"
+	return
     }
+    verbose -log "build-id is $buildid"
 
-    if {$sepdebug} {
-	# Strip debuginfo into its own file.
-	if {[gdb_gnu_strip_debug [standard_output_file $program_to_run] \
-		 no-debuglink] != 0} {
-	    untested "could not strip executable  for [join $suffix \ ]"
-	    return
-	}
+    # Create a directory for the non-stripped test.
+    set combined_dirname [standard_output_file ${mode}_non-stripped]
+    remote_exec build "mkdir -p $combined_dirname"
+    remote_exec build "cp $progname $combined_dirname"
 
-	lappend suffix "sepdebug"
+    # Create a directory for the stripped test.
+    if {[gdb_gnu_strip_debug [standard_output_file $progname] no-debuglink] != 0} {
+	untested "could not strip executable  for [join $suffix \ ]"
+	return
     }
-
-    with_test_prefix "[join $suffix \ ]" {
-	# Find the core file.
-	set corefile [core_find $program_to_run]
-	if {$corefile == ""} {
-	    untested "could not generate core file"
-	    return
-	}
-	verbose -log "corefile is $corefile"
-
-	if { [catch "exec [gdb_find_eu-unstrip] -n --core $corefile" output] == 0 } {
-	    set line [lindex [split $output "\n"] 0]
-	    set binfile_re (?:[string_to_regexp $program_to_run]|\\\[(?:exe|pie)\\\])
-	    if { ![regexp "^${hex}\\+${hex} \[a-f0-9\]+@${hex}.*$binfile_re$" $line] } {
-		unsupported "build id for exec"
-		return
-	    }
+    set sepdebug_dirname [standard_output_file ${mode}_stripped]
+    remote_exec build "mkdir -p $sepdebug_dirname"
+    remote_exec build "mv $progname $sepdebug_dirname"
+    remote_exec build "mv ${progname}.debug $sepdebug_dirname"
+
+    # Now do the actual testing part.  Fill out a debug directory with
+    # build-id related files (copies or symlinks) and then load the
+    # corefile.  Check GDB finds the executable and debug information
+    # via the build-id related debug directory contents.
+    foreach_with_prefix sepdebug { false true } {
+	if { $sepdebug } {
+	    set dirname $sepdebug_dirname
 	} else {
-	    unsupported "eu-unstrip execution"
-	    return
-	}
-
-	# Get the build-id filename without ".debug" on the end.  This
-	# will have the format: '.build-id/xx/xxxxx'
-	set buildid [build_id_debug_filename_get $program_to_run ""]
-	if {$buildid == ""} {
-	    untested "binary has no build-id"
-	    return
+	    set dirname $combined_dirname
 	}
-	verbose -log "build-id is $buildid"
-
-	locate_exec_from_core_build_id $corefile $buildid \
-	    [join $suffix -] $sepdebug false $shared
 
-	with_test_prefix "symlink" {
+	foreach_with_prefix symlink { false true } {
 	    locate_exec_from_core_build_id $corefile $buildid \
-		[join $suffix -] $sepdebug true $shared
+		$dirname $progname \
+		$sepdebug $symlink [expr {$mode eq "shared"}]
 	}
     }
 }
-
-# Directories where executables will be moved before testing.
-set execdir "build-exec"
-set sharedir "build-shared"
-
-#
-# Do tests
-#
-
-build_corefile_buildid_exec
-do_corefile_buildid_tests
-do_corefile_buildid_tests -sepdebug
-
-if {[allow_shlib_tests]} {
-    build_corefile_buildid_shared
-    do_corefile_buildid_tests -shared
-    do_corefile_buildid_tests -shared -sepdebug
-}
diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
index dc3c8b1dfc8..2111aa66d7d 100644
--- a/gdb/testsuite/gdb.base/corefile.exp
+++ b/gdb/testsuite/gdb.base/corefile.exp
@@ -348,6 +348,15 @@ proc corefile_test_attach {} {
 	gdb_start
 
 	gdb_test "core-file $corefile" "Core was generated by .*" "attach: load core again"
+
+	# If GDB managed to auto-load an executable based on the core
+	# file, then unload it now.
+	gdb_test "with confirm off -- file" \
+	    [multi_line \
+		 "^No executable file now\\." \
+		 "No symbol file now\\."] \
+	    "ensure no executable is loaded"
+
 	gdb_test "info files" "\r\nLocal core dump file:\r\n.*" "attach: sanity check we see the core file"
 
 	gdb_test "attach $pid" "Attaching to process $pid\r\n.*" "attach: with core"
-- 
2.25.4


  parent reply	other threads:[~2024-10-28 18:53 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-26 11:11 [PATCH 0/5] Better executable auto-loading when opening a core file Andrew Burgess
2024-10-26 11:11 ` [PATCH 1/5] gdb: add gdbarch method to get execution context from " Andrew Burgess
2024-10-26 11:11 ` [PATCH 2/5] gdb: parse and set the inferior environment from core files Andrew Burgess
2024-10-26 11:11 ` [PATCH 3/5] gdb/testsuite: make some of the core file / build-id tests harder Andrew Burgess
2024-10-26 11:11 ` [PATCH 4/5] gdb: improve GDB's ability to auto-load the exec for a core file Andrew Burgess
2024-10-26 11:11 ` [PATCH 5/5] gdb/freebsd: port core file context parsing to FreeBSD Andrew Burgess
2024-10-28 18:53 ` [PATCHv2 0/5] Better executable auto-loading when opening a core file Andrew Burgess
2024-10-28 18:53   ` [PATCHv2 1/5] gdb: add gdbarch method to get execution context from " Andrew Burgess
2024-10-28 18:53   ` [PATCHv2 2/5] gdb: parse and set the inferior environment from core files Andrew Burgess
2024-10-28 18:53   ` Andrew Burgess [this message]
2024-10-28 18:53   ` [PATCHv2 4/5] gdb: improve GDB's ability to auto-load the exec for a core file Andrew Burgess
2024-10-28 18:53   ` [PATCHv2 5/5] gdb/freebsd: port core file context parsing to FreeBSD Andrew Burgess
2024-10-29 14:08   ` [PATCHv3 0/5] Better executable auto-loading when opening a core file Andrew Burgess
2024-10-29 14:08     ` [PATCHv3 1/5] gdb: add gdbarch method to get execution context from " Andrew Burgess
2024-10-29 14:08     ` [PATCHv3 2/5] gdb: parse and set the inferior environment from core files Andrew Burgess
2024-10-29 14:08     ` [PATCHv3 3/5] gdb/testsuite: make some of the core file / build-id tests harder Andrew Burgess
2024-10-29 14:08     ` [PATCHv3 4/5] gdb: improve GDB's ability to auto-load the exec for a core file Andrew Burgess
2024-10-29 14:08     ` [PATCHv3 5/5] gdb/freebsd: port core file context parsing to FreeBSD Andrew Burgess

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4aa82991a3fc95d3b1ff00c896cd5cfcd23fb237.1730141493.git.aburgess@redhat.com \
    --to=aburgess@redhat.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).