[1/2] GDB test suite: Add helper for locating core files

Message ID 1505760152-28775-2-git-send-email-arnez@linux.vnet.ibm.com
State New, archived
Headers

Commit Message

Andreas Arnez Sept. 18, 2017, 6:41 p.m. UTC
  The test suite contains a convenience proc `core_find' that basically
performs two tasks:

1. Run a given command (expecting it to dump core).
2. Locate the core dump generated by the command, and return it.

However, some test cases just need the second part, because they run the
command in a different way.  Hence they implement their own logic for
locating the core dump.

This change replaces the instances of core dump retrieval logic by
invocations of a new separate proc.  And it renames `core_find' to
`run_and_get_core', to reduce confusion.

gdb/testsuite/ChangeLog:

	* lib/gdb.exp (exec_in_dir): New helper proc.
	(core_find): Rename to...
	(run_and_get_core): ...this.  Remove the deletefiles argument.
	Split out the logic for locating the dump into...
	(find_core): ...this new proc.
	* gdb.arch/s390-multiarch.exp: Adjust invocations of core_find.
	* gdb.base/break-interp.exp: Likewise.
	* gdb.base/corefile.exp: Likewise.
	* gdb.threads/corethreads.exp: Likewise.
	* gdb.arch/s390-vregs.exp: Exploit find_core.
	* gdb.base/bigcore.exp: Likewise.
---
 gdb/testsuite/gdb.arch/s390-multiarch.exp |   2 +-
 gdb/testsuite/gdb.arch/s390-vregs.exp     |   6 +-
 gdb/testsuite/gdb.base/bigcore.exp        |  11 +--
 gdb/testsuite/gdb.base/break-interp.exp   |   2 +-
 gdb/testsuite/gdb.base/corefile.exp       |   2 +-
 gdb/testsuite/gdb.threads/corethreads.exp |   2 +-
 gdb/testsuite/lib/gdb.exp                 | 127 +++++++++++++++++-------------
 7 files changed, 80 insertions(+), 72 deletions(-)
  

Comments

Kevin Buettner Oct. 7, 2017, 4:45 p.m. UTC | #1
On Mon, 18 Sep 2017 20:41:51 +0200
Andreas Arnez <arnez@linux.vnet.ibm.com> wrote:

> The test suite contains a convenience proc `core_find' that basically
> performs two tasks:
> 
> 1. Run a given command (expecting it to dump core).
> 2. Locate the core dump generated by the command, and return it.
> 
> However, some test cases just need the second part, because they run the
> command in a different way.  Hence they implement their own logic for
> locating the core dump.
> 
> This change replaces the instances of core dump retrieval logic by
> invocations of a new separate proc.  And it renames `core_find' to
> `run_and_get_core', to reduce confusion.
> 
> gdb/testsuite/ChangeLog:
> 
> 	* lib/gdb.exp (exec_in_dir): New helper proc.
> 	(core_find): Rename to...
> 	(run_and_get_core): ...this.  Remove the deletefiles argument.
> 	Split out the logic for locating the dump into...
> 	(find_core): ...this new proc.
> 	* gdb.arch/s390-multiarch.exp: Adjust invocations of core_find.
> 	* gdb.base/break-interp.exp: Likewise.
> 	* gdb.base/corefile.exp: Likewise.
> 	* gdb.threads/corethreads.exp: Likewise.
> 	* gdb.arch/s390-vregs.exp: Exploit find_core.
> 	* gdb.base/bigcore.exp: Likewise.

Hi Andreas,

I've looked your patches over and for the most part, I like them.
They better consolidate the logic for finding core files to
lib/gdb.exp.

However, one serious problem is that your rewrite of code in
lib/gdb.exp removes support for the handling of remote core files.

E.g. when I test your patch on my x86-64 linux box using the
following command...

    make check RUNTESTFLAGS="--target_board=native-gdbserver"

...I see 32 fewer passes than before and also one more known failure.

Here are the passes that no longer occur when using your patch:

    PASS: gdb.base/corefile.exp: args: -core=corefile.core
    PASS: gdb.base/corefile.exp: args: execfile -core=corefile.core
    PASS: gdb.base/corefile.exp: core-file command
    PASS: gdb.base/corefile.exp: print coremaker_data
    PASS: gdb.base/corefile.exp: print coremaker_bss
    PASS: gdb.base/corefile.exp: print coremaker_ro
    PASS: gdb.base/corefile.exp: print func2::coremaker_local
    PASS: gdb.base/corefile.exp: $_exitsignal prints SIGABRT (6)
    PASS: gdb.base/corefile.exp: $_exitcode is void
    PASS: gdb.base/corefile.exp: backtrace in corefile.exp
    PASS: gdb.base/corefile.exp: up in corefile.exp
    PASS: gdb.base/corefile.exp: accessing original mmap data in core file
    PASS: gdb.base/corefile.exp: accessing mmapped data in core file
    PASS: gdb.base/corefile.exp: up in corefile.exp (reinit)
    PASS: gdb.base/corefile.exp: core
    PASS: gdb.base/corefile.exp: run: load core again
    PASS: gdb.base/corefile.exp: run: sanity check we see the core file
    PASS: gdb.base/corefile.exp: run: with core
    PASS: gdb.base/corefile.exp: run: core file is cleared
    PASS: gdb.base/corefile.exp: quit with a process
    PASS: gdb.base/corefile.exp: quit with processes: n
    PASS: gdb.base/corefile.exp: no question: load core
    PASS: gdb.base/corefile.exp: quit with a core file
    PASS: gdb.base/corefile.exp: core-file warning-free
    PASS: gdb.threads/corethreads.exp: load core
    PASS: gdb.threads/corethreads.exp: sanity check we see the core file
    PASS: gdb.threads/corethreads.exp: print pthread_t of thread0
    PASS: gdb.threads/corethreads.exp: print pthread_t of thread1
    PASS: gdb.threads/corethreads.exp: thread0 found
    PASS: gdb.threads/corethreads.exp: thread1 found
    PASS: gdb.threads/corethreads.exp: no other thread found

Instead, several warnings are now printed instead:

    WARNING: Can not generate core dump on remote target.

If you can restore support for handling of remote core files, I'd very
much like to review this patch again.

Thanks,

Kevin
  

Patch

diff --git a/gdb/testsuite/gdb.arch/s390-multiarch.exp b/gdb/testsuite/gdb.arch/s390-multiarch.exp
index 28545d7..9d45e04 100644
--- a/gdb/testsuite/gdb.arch/s390-multiarch.exp
+++ b/gdb/testsuite/gdb.arch/s390-multiarch.exp
@@ -51,7 +51,7 @@  proc compile_and_dump {variant ccopts binfile} {
     pass $test
 
     set test "create core file ($variant)"
-    set corefile [core_find $binfile]
+    set corefile [run_and_get_core $binfile]
     if {$corefile == ""} {
 	fail $test
 	return {}
diff --git a/gdb/testsuite/gdb.arch/s390-vregs.exp b/gdb/testsuite/gdb.arch/s390-vregs.exp
index d2c31e1..d5ed6f2 100644
--- a/gdb/testsuite/gdb.arch/s390-vregs.exp
+++ b/gdb/testsuite/gdb.arch/s390-vregs.exp
@@ -185,14 +185,12 @@  gdb_exit
 
 # Find the core file and rename it (avoid accumulating core files).
 
-set cores [glob -nocomplain -directory $coredir *core*]
-if {[llength $cores] != 1} {
+set destcore [find_core $binfile $coredir]
+if {$destcore == ""} {
     untested "core file not found"
     remote_exec build "rm -rf $coredir"
     return -1
 }
-set destcore [standard_output_file ${testfile}.core]
-remote_exec build "mv [file join $coredir [lindex $cores 0]] $destcore"
 remote_exec build "rm -rf $coredir"
 
 # Restart gdb and load the core file.  Compare the VRs.
diff --git a/gdb/testsuite/gdb.base/bigcore.exp b/gdb/testsuite/gdb.base/bigcore.exp
index dbd8c00..ba8480a 100644
--- a/gdb/testsuite/gdb.base/bigcore.exp
+++ b/gdb/testsuite/gdb.base/bigcore.exp
@@ -135,16 +135,7 @@  gdb_test "signal SIGABRT" "Program terminated with signal SIGABRT, .*"
 set timeout $oldtimeout
 
 # Find the corefile
-set file ""
-foreach pat [list core.${inferior_pid} ${testfile}.core core] {
-    set names [glob -nocomplain [standard_output_file $pat]]
-    if {[llength $names] == 1} {
-	set file [lindex $names 0]
-	remote_exec build "mv $file $corefile"
-	break
-    }
-}
-
+set file [find_core $binfile [file dirname $corefile] $corefile]
 if { $file == "" } {
     untested "can't generate a core file"
     return 0
diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp
index 3a6d9a9..49967c6 100644
--- a/gdb/testsuite/gdb.base/break-interp.exp
+++ b/gdb/testsuite/gdb.base/break-interp.exp
@@ -201,7 +201,7 @@  proc test_core {file displacement} {
     with_test_prefix "core" {
 	global srcdir subdir gdb_prompt expect_out
 
-	set corefile [core_find $file {} "segv"]
+	set corefile [run_and_get_core $file "segv"]
 	if {$corefile == ""} {
 	    return
 	}
diff --git a/gdb/testsuite/gdb.base/corefile.exp b/gdb/testsuite/gdb.base/corefile.exp
index 21b974f..a9f7115 100644
--- a/gdb/testsuite/gdb.base/corefile.exp
+++ b/gdb/testsuite/gdb.base/corefile.exp
@@ -34,7 +34,7 @@  if {[build_executable $testfile.exp $testfile $srcfile debug] == -1} {
     return -1
 }
 
-set corefile [core_find $binfile {coremmap.data}]
+set corefile [run_and_get_core $binfile]
 if {$corefile == ""} {
     return 0
 }
diff --git a/gdb/testsuite/gdb.threads/corethreads.exp b/gdb/testsuite/gdb.threads/corethreads.exp
index f7d85fb..0f80625 100644
--- a/gdb/testsuite/gdb.threads/corethreads.exp
+++ b/gdb/testsuite/gdb.threads/corethreads.exp
@@ -26,7 +26,7 @@  if { [gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executa
      return -1
 }
 
-set corefile [core_find $binfile]
+set corefile [run_and_get_core $binfile]
 if {$corefile == ""} {
     return 0
 }
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index 8af1b77..1fd0009 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -5795,71 +5795,90 @@  if {[info exists GDB_PARALLEL]} {
     }
 }
 
-proc core_find {binfile {deletefiles {}} {arg ""}} {
-    global objdir subdir
+# Run COMMAND in directory DIR.  Suppress the command's output and ignore
+# its exit code.  Return 0 if the command could be executed, nonzero
+# otherwise.
+
+proc exec_in_dir {dir command} {
+    set err [catch {system "(cd ${dir}; ${command}; true) >/dev/null 2>&1"}]
+    if {$err} {
+	verbose -log "Failed executing \"${command}\"."
+    } else {
+	verbose -log "Executed: \"${command}\"."
+    }
+    return $err
+}
 
-    set destcore "$binfile.core"
-    file delete $destcore
+# Run a program that will dump core, then try to locate the core file.
+# Return the core file's filename, or "", if none was found.
 
-    # Create a core file named "$destcore" rather than just "core", to
-    # avoid problems with sys admin types that like to regularly prune all
-    # files named "core" from the system.
-    #
-    # Arbitrarily try setting the core size limit to "unlimited" since
-    # this does not hurt on systems where the command does not work and
-    # allows us to generate a core on systems where it does.
-    #
-    # Some systems append "core" to the name of the program; others append
-    # the name of the program to "core"; still others (like Linux, as of
-    # May 2003) create cores named "core.PID".  In the latter case, we
-    # could have many core files lying around, and it may be difficult to
-    # tell which one is ours, so let's run the program in a subdirectory.
-    set found 0
+proc run_and_get_core {binfile {arg ""}} {
+    if {[is_remote target]} {
+	warning "Can not generate core dump on remote target."
+	return ""
+    }
+    # Run the program in a subdirectory, to prevent generated files or
+    # core files from clashing, and to simplify clean-up.
     set coredir [standard_output_file coredir.[getpid]]
     file mkdir $coredir
-    catch "system \"(cd ${coredir}; ulimit -c unlimited; ${binfile} ${arg}; true) >/dev/null 2>&1\""
-    #      remote_exec host "${binfile}"
+
+    set err [exec_in_dir $coredir "ulimit -c unlimited; ${binfile} ${arg}"]
+    if {$err} {
+	# Try again without "ulimit -c", for shells that don't understand
+	# this.
+	set err [exec_in_dir $coredir "${binfile} ${arg}"]
+    }
+    if {$err} {
+	set destcore ""
+	warning "Could not invoke ${binfile} for generating a core dump"
+    } else {
+	set destcore [find_core $binfile $coredir]
+    }
+
+    # Clean up after ourselves.
+    file delete -force $coredir
+
+    return $destcore
+}
+
+# Find a core file that should have been created by the executable BINFILE
+# in the directory COREDIR.  Move it to "BINFILE.core", or to DESTCORE, if
+# specified.  Return that path name, or "" if no core file was found.
+
+proc find_core {binfile coredir {destcore ""}} {
+    if {[is_remote target]} {
+	warning "Can not access remote core file."
+	return ""
+    }
+    global objdir subdir
+
+    if {$destcore eq ""} {
+	set destcore "$binfile.core"
+    }
+    file delete $destcore
+
     foreach i "${coredir}/core ${coredir}/core.coremaker.c ${binfile}.core" {
-	if [remote_file build exists $i] {
-	    remote_exec build "mv $i $destcore"
-	    set found 1
+	if [file exists $i] {
+	    file rename $i $destcore
+	    return $destcore
 	}
     }
     # Check for "core.PID".
-    if { $found == 0 } {
-	set names [glob -nocomplain -directory $coredir core.*]
-	if {[llength $names] == 1} {
-	    set corefile [file join $coredir [lindex $names 0]]
-	    remote_exec build "mv $corefile $destcore"
-	    set found 1
-	}
-    }
-    if { $found == 0 } {
-	# The braindamaged HPUX shell quits after the ulimit -c above
-	# without executing ${binfile}.  So we try again without the
-	# ulimit here if we didn't find a core file above.
-	# Oh, I should mention that any "braindamaged" non-Unix system has
-	# the same problem. I like the cd bit too, it's really neat'n stuff.
-	catch "system \"(cd ${objdir}/${subdir}; ${binfile}; true) >/dev/null 2>&1\""
-	foreach i "${objdir}/${subdir}/core ${objdir}/${subdir}/core.coremaker.c ${binfile}.core" {
-	    if [remote_file build exists $i] {
-		remote_exec build "mv $i $destcore"
-		set found 1
-	    }
+    set names [glob -nocomplain -directory $coredir core.*]
+    if {[llength $names] == 1} {
+	set corefile [file join $coredir [lindex $names 0]]
+	file rename $corefile $destcore
+	return $destcore
+    }
+    foreach i "${objdir}/${subdir}/core ${objdir}/${subdir}/core.coremaker.c ${binfile}.core" {
+	if [file exists $i] {
+	    file rename $i $destcore
+	    return $destcore
 	}
     }
 
-    # Try to clean up after ourselves. 
-    foreach deletefile $deletefiles {
-	remote_file build delete [file join $coredir $deletefile]
-    }
-    remote_exec build "rmdir $coredir"
-	
-    if { $found == 0  } {
-	warning "can't generate a core file - core tests suppressed - check ulimit -c"
-	return ""
-    }
-    return $destcore
+    warning "Can not locate core dump generated by \"[file tail $binfile]\"."
+    return ""
 }
 
 # gdb_target_symbol_prefix compiles a test program and then examines