[1/2] GDB test suite: Add helper for locating core files
Commit Message
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
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
@@ -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 {}
@@ -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.
@@ -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
@@ -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
}
@@ -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
}
@@ -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
}
@@ -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