2017-01-01 07:50:51 +01:00
|
|
|
# Copyright 2005-2017 Free Software Foundation, Inc.
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
# 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
|
2007-08-23 20:14:19 +02:00
|
|
|
# the Free Software Foundation; either version 3 of the License, or
|
2006-01-04 20:29:26 +01:00
|
|
|
# (at your option) any later version.
|
2007-08-23 20:14:19 +02:00
|
|
|
#
|
2006-01-04 20:29:26 +01:00
|
|
|
# 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.
|
2007-08-23 20:14:19 +02:00
|
|
|
#
|
2006-01-04 20:29:26 +01:00
|
|
|
# You should have received a copy of the GNU General Public License
|
2007-08-23 20:14:19 +02:00
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
# Until "set follow-fork-mode" and "catch fork" are implemented on
|
|
|
|
# other targets...
|
|
|
|
#
|
|
|
|
if {![istarget "*-*-linux*"]} then {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2017-10-12 20:54:34 +02:00
|
|
|
# Checkpoint support is currently implemented in the Linux native
|
|
|
|
# target, so only works with "target native".
|
|
|
|
if { [target_info gdb_protocol] != "" } {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
Fix and test "checkpoint" in non-stop mode
Letting a "checkpoint" run to exit with "set non-stop on" behaves
differently compared to the default all-stop mode ("set non-stop
off").
Currently, in non-stop mode:
(gdb) start
Temporary breakpoint 1 at 0x40086b: file src/gdb/testsuite/gdb.base/checkpoint.c, line 28.
Starting program: build/gdb/testsuite/gdb.base/checkpoint
Temporary breakpoint 1, main () at src/gdb/testsuite/gdb.base/checkpoint.c:28
28 char *tmp = &linebuf[0];
(gdb) checkpoint
checkpoint 1: fork returned pid 24948.
(gdb) c
Continuing.
Copy complete.
Deleting copy.
[Inferior 1 (process 24944) exited normally]
[Switching to process 24948]
(gdb) info threads
Id Target Id Frame
1 process 24948 "checkpoint" (running)
No selected thread. See `help thread'.
(gdb) c
The program is not being run.
(gdb)
Two issues above:
1. Thread 1 got stuck in "(running)" state (it isn't really running)
2. While checkpoints try to preserve the illusion that the thread is
still the same when the process exits, GDB switched to "No thread
selected." instead of staying with thread 1 selected.
Problem #1 is caused by handle_inferior_event and normal_stop not
considering that when a
TARGET_WAITKIND_SIGNALLED/TARGET_WAITKIND_EXITED event is reported,
and the inferior is mourned, the target may still have execution.
Problem #2 is caused by the make_cleanup_restore_current_thread
cleanup installed by fetch_inferior_event not being able to find the
original thread 1's ptid in the thread list, thus not being able to
restore thread 1 as selected thread. The fix is to make the cleanup
installed by make_cleanup_restore_current_thread aware of thread ptid
changes, by installing a thread_ptid_changed observer that adjusts the
cleanup's data.
After the patch, we get the same in all-stop and non-stop modes:
(gdb) c
Continuing.
Copy complete.
Deleting copy.
[Inferior 1 (process 25109) exited normally]
[Switching to process 25113]
(gdb) info threads
Id Target Id Frame
* 1 process 25113 "checkpoint" main () at src/gdb/testsuite/gdb.base/checkpoint.c:28
(gdb)
Turns out the whole checkpoints.exp file can run in non-stop mode
unmodified. I thought of moving most of the test file's contents to a
procedure that can be called twice, once in non-stop mode and another
in all-stop mode. But then, the test already takes close to 30
seconds to run on my machine, so I thought it'd be nicer to run
all-stop and non-stop mode in parallel. Thus I added a new
checkpoint-ns.exp file that just appends "set non-stop on" to GDBFLAGS
and sources checkpoint.exp.
gdb/ChangeLog:
2015-08-07 Pedro Alves <palves@redhat.com>
* infrun.c (handle_inferior_event): If we get
TARGET_WAITKIND_SIGNALLED or TARGET_WAITKIND_EXITED in non-stop
mode, mark all threads of the exiting process as not-executing.
(normal_stop): If we get TARGET_WAITKIND_SIGNALLED or
TARGET_WAITKIND_EXITED in non-stop mode, finish all threads of the
exiting process, if inferior_ptid still points at a process.
* thread.c (struct current_thread_cleanup) <next>: New field.
(current_thread_cleanup_chain): New global.
(restore_current_thread_ptid_changed): New function.
(restore_current_thread_cleanup_dtor): Remove the cleanup from the
current_thread_cleanup_chain list.
(make_cleanup_restore_current_thread): Add the cleanup data to the
current_thread_cleanup_chain list.
(_initialize_thread): Install restore_current_thread_ptid_changed
as thread_ptid_changed observer.
gdb/testsuite/ChangeLog:
2015-08-07 Pedro Alves <palves@redhat.com>
* gdb.base/checkpoint-ns.exp: New file.
* gdb.base/checkpoint.exp: Pass explicit "checkpoint.c" to
standard_testfile.
2015-08-07 18:23:55 +02:00
|
|
|
# Must name the source file explicitly, otherwise when driven by
|
|
|
|
# checkpoints-ns.exp, we'd try compiling checkpoints-ns.c, which
|
|
|
|
# doesn't exist.
|
|
|
|
standard_testfile checkpoint.c
|
2006-01-04 20:29:26 +01:00
|
|
|
|
2013-08-23 20:18:27 +02:00
|
|
|
set pi_txt [gdb_remote_download host ${srcdir}/${subdir}/pi.txt]
|
|
|
|
if {[is_remote host]} {
|
|
|
|
set copy1_txt copy1.txt
|
|
|
|
} else {
|
|
|
|
set copy1_txt [standard_output_file copy1.txt]
|
|
|
|
}
|
|
|
|
|
2016-12-23 17:52:18 +01:00
|
|
|
if {[prepare_for_testing "failed to prepare" $testfile $srcfile \
|
2013-08-23 20:18:27 +02:00
|
|
|
[list debug "additional_flags=-DPI_TXT=\"$pi_txt\" -DCOPY1_TXT=\"$copy1_txt\""]]} {
|
2006-08-10 07:27:22 +02:00
|
|
|
return -1
|
2006-01-04 20:29:26 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
global gdb_prompt
|
|
|
|
|
|
|
|
#
|
|
|
|
# This tests gdb checkpoint and restart.
|
|
|
|
#
|
|
|
|
|
|
|
|
runto_main
|
|
|
|
set break1_loc [gdb_get_line_number "breakpoint 1"]
|
|
|
|
set break2_loc [gdb_get_line_number "breakpoint 2"]
|
|
|
|
set break3_loc [gdb_get_line_number "breakpoint 3"]
|
|
|
|
set break4_loc [gdb_get_line_number "breakpoint 4"]
|
|
|
|
|
|
|
|
gdb_breakpoint $break1_loc
|
|
|
|
gdb_test "continue" "breakpoint 1.*" "break1 start"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 two"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 three"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 four"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 five"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 six"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 seven"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 eight"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 nine"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 10" "breakpoint 1.*" "break1 ten"
|
|
|
|
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "checkpoint" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
gdb_test "info checkpoints" \
|
List checkpoints in ascending order
Before:
(gdb) info checkpoints
3 process 29132 at 0x4008ad, file foo.c, line 81
2 process 29131 at 0x4008ad, file foo.c, line 81
1 process 29130 at 0x4008ad, file foo.c, line 81
* 0 Thread 0x7ffff7fc5740 (LWP 29128) (main process) at 0x4008ad, file foo.c, line 81
After:
(gdb) info checkpoints
* 0 Thread 0x7ffff7fc5740 (LWP 29128) (main process) at 0x4008ad, file foo.c, line 81
1 process 29130 at 0x4008ad, file foo.c, line 81
2 process 29131 at 0x4008ad, file foo.c, line 81
3 process 29132 at 0x4008ad, file foo.c, line 81
gdb/ChangeLog:
2015-11-24 Pedro Alves <palves@redhat.com>
PR 17539
* printcmd.c (display_command): Append new display at the end of
the list.
gdb/testsuite/ChangeLog:
2015-11-24 Pedro Alves <palves@redhat.com>
PR 17539
* gdb.base/display.exp: Expect displays to be sorted in ascending
order. Use multi_line.
* gdb.base/solib-display.exp: Likewise.
2015-11-24 19:11:22 +01:00
|
|
|
" 1 .* 2 .* 3 .* 4 .* 5 .* 6 .* 7 .* 8 .* 9 .* 10 .*" \
|
2006-01-04 20:29:26 +01:00
|
|
|
"info checkpoints one"
|
|
|
|
|
|
|
|
delete_breakpoints
|
|
|
|
gdb_breakpoint $break2_loc
|
|
|
|
gdb_test "continue" "breakpoint 2.*" "break2 one"
|
|
|
|
|
|
|
|
gdb_test "restart 1" "Switching to .*breakpoint 1.*" "restart 1 one"
|
|
|
|
gdb_test "print i" " = 78" "verify i 1 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 1 one"
|
|
|
|
gdb_test "print lines" " = 1.*" "verify lines 1 one"
|
|
|
|
|
|
|
|
gdb_test "restart 2" "Switching to .*breakpoint 1.*" "restart 2 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 2 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 2 one"
|
|
|
|
gdb_test "print lines" " = 11.*" "verify lines 2 one"
|
|
|
|
|
|
|
|
gdb_test "restart 3" "Switching to .*breakpoint 1.*" "restart 3 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 3 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 3 one"
|
|
|
|
gdb_test "print lines" " = 21.*" "verify lines 3 one"
|
|
|
|
|
|
|
|
gdb_test "restart 4" "Switching to .*breakpoint 1.*" "restart 4 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 4 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 4 one"
|
|
|
|
gdb_test "print lines" " = 31.*" "verify lines 4 one"
|
|
|
|
|
|
|
|
gdb_test "restart 5" "Switching to .*breakpoint 1.*" "restart 5 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 5 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 5 one"
|
|
|
|
gdb_test "print lines" " = 41.*" "verify lines 5 one"
|
|
|
|
|
|
|
|
gdb_test "restart 6" "Switching to .*breakpoint 1.*" "restart 6 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 6 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 6 one"
|
|
|
|
gdb_test "print lines" " = 51.*" "verify lines 6 one"
|
|
|
|
|
|
|
|
gdb_test "restart 7" "Switching to .*breakpoint 1.*" "restart 7 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 7 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 7 one"
|
|
|
|
gdb_test "print lines" " = 61.*" "verify lines 7 one"
|
|
|
|
|
|
|
|
gdb_test "restart 8" "Switching to .*breakpoint 1.*" "restart 8 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 8 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 8 one"
|
|
|
|
gdb_test "print lines" " = 71.*" "verify lines 8 one"
|
|
|
|
|
|
|
|
gdb_test "restart 9" "Switching to .*breakpoint 1.*" "restart 9 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 9 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 9 one"
|
|
|
|
gdb_test "print lines" " = 81.*" "verify lines 9 one"
|
|
|
|
|
|
|
|
gdb_test "restart 10" "Switching to .*breakpoint 1.*" "restart 10 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 10 one"
|
|
|
|
gdb_test "print i + 1 == lines * 79" " = 1" "verify i 10 one"
|
|
|
|
gdb_test "print lines" " = 91.*" "verify lines 10 one"
|
|
|
|
|
|
|
|
#
|
|
|
|
# Now let the files be closed by the original process,
|
|
|
|
# and diff them.
|
|
|
|
|
|
|
|
gdb_test "restart 0" "Switching to .*breakpoint 2.*" "restart 0 one"
|
|
|
|
gdb_breakpoint $break3_loc
|
|
|
|
gdb_test "continue" "breakpoint 3.*" "break3 one"
|
|
|
|
|
2013-08-23 20:18:27 +02:00
|
|
|
gdb_test "shell diff -s $pi_txt $copy1_txt" \
|
|
|
|
"Files .*pi.txt and .*copy1.txt are identical.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"diff input and output one"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# And now run from various checkpoints, allowing
|
|
|
|
# various amounts of input and output.
|
|
|
|
#
|
|
|
|
|
|
|
|
gdb_breakpoint $break1_loc
|
|
|
|
|
|
|
|
gdb_test "restart 1" "Switching to .*c == EOF.*" "restart 1 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 100" "breakpoint 1.*" "breakpoint 1 1 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 1 two"
|
|
|
|
gdb_test "print lines" " = 102.*" "verify lines 1 two"
|
|
|
|
|
|
|
|
gdb_test "restart 2" "Switching to .*c == EOF.*" "restart 2 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 100" "breakpoint 1.*" "breakpoint 1 2 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 2 two"
|
|
|
|
gdb_test "print lines" " = 112.*" "verify lines 2 two"
|
|
|
|
|
|
|
|
gdb_test "restart 3" "Switching to .*c == EOF.*" "restart 3 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 500" "breakpoint 1.*" "breakpoint 1 3 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 3 two"
|
|
|
|
gdb_test "print lines" " = 522.*" "verify lines 3 two"
|
|
|
|
|
|
|
|
gdb_test "restart 4" "Switching to .*c == EOF.*" "restart 4 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 500" "breakpoint 1.*" "breakpoint 1 4 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 4 two"
|
|
|
|
gdb_test "print lines" " = 532.*" "verify lines 4 two"
|
|
|
|
|
|
|
|
gdb_test "restart 5" "Switching to .*c == EOF.*" "restart 5 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 1000" "breakpoint 1.*" "breakpoint 1 5 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 5 two"
|
|
|
|
gdb_test "print lines" " = 1042.*" "verify lines 5 two"
|
|
|
|
|
|
|
|
gdb_test "restart 6" "Switching to .*c == EOF.*" "restart 6 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 1000" "breakpoint 1.*" "breakpoint 1 6 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 6 two"
|
|
|
|
gdb_test "print lines" " = 1052.*" "verify lines 5 two"
|
|
|
|
|
|
|
|
gdb_test "restart 7" "Switching to .*c == EOF.*" "restart 7 two"
|
2010-06-09 00:58:03 +02:00
|
|
|
gdb_test "continue" ".*" ""
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_test "continue 1100" "breakpoint 1.*" "breakpoint 1 7 one"
|
|
|
|
gdb_test "step" "if .c == EOF.*" "step in 7 two"
|
|
|
|
gdb_test "print lines" " = 1162.*" "verify lines 7 two"
|
|
|
|
|
2013-08-23 20:18:27 +02:00
|
|
|
gdb_test "shell diff -s $pi_txt $copy1_txt" \
|
|
|
|
"Files .*pi.txt and .*copy1.txt are identical.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"diff input and output two"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# OK, now allow the original program to delete the output file,
|
|
|
|
# and verify that the checkpoints can still write to it.
|
|
|
|
#
|
|
|
|
|
|
|
|
gdb_test "restart 0" "Switching to .*breakpoint 3.*" "restart 0 one"
|
|
|
|
gdb_breakpoint $break4_loc
|
|
|
|
gdb_test "continue" "breakpoint 4.*" "break4 one"
|
|
|
|
|
2013-08-23 20:18:27 +02:00
|
|
|
gdb_test "shell diff $pi_txt $copy1_txt" \
|
|
|
|
"diff: .*copy1.txt: No such file or directory" \
|
2006-01-04 20:29:26 +01:00
|
|
|
"delete copy1"
|
|
|
|
|
|
|
|
delete_breakpoints
|
|
|
|
gdb_breakpoint $break2_loc
|
|
|
|
|
Stop assuming no-debug-info functions return int
The fact that GDB defaults to assuming that functions return int, when
it has no debug info for the function has been a recurring source of
user confusion. Recently this came up on the errno pretty printer
discussions. Shortly after, it came up again on IRC, with someone
wondering why does getenv() in GDB return a negative int:
(gdb) p getenv("PATH")
$1 = -6185
This question (with s/getenv/random-other-C-runtime-function) is a FAQ
on IRC.
The reason for the above is:
(gdb) p getenv
$2 = {<text variable, no debug info>} 0x7ffff7751d80 <getenv>
(gdb) ptype getenv
type = int ()
... which means that GDB truncated the 64-bit pointer that is actually
returned from getent to 32-bit, and then sign-extended it:
(gdb) p /x -6185
$6 = 0xffffe7d7
The workaround is to cast the function to the right type, like:
(gdb) p ((char *(*) (const char *)) getenv) ("PATH")
$3 = 0x7fffffffe7d7 "/usr/local/bin:/"...
IMO, we should do better than this.
I see the "assume-int" issue the same way I see printing bogus values
for optimized-out variables instead of "<optimized out>" -- I'd much
rather that the debugger tells me "I don't know" and tells me how to
fix it than showing me bogus misleading results, making me go around
tilting at windmills.
If GDB prints a signed integer when you're expecting a pointer or
aggregate, you at least have some sense that something is off, but
consider the case of the function actually returning a 64-bit integer.
For example, compile this without debug info:
unsigned long long
function ()
{
return 0x7fffffffffffffff;
}
Currently, with pristine GDB, you get:
(gdb) p function ()
$1 = -1 # incorrect
(gdb) p /x function ()
$2 = 0xffffffff # incorrect
maybe after spending a few hours debugging you suspect something is
wrong with that -1, and do:
(gdb) ptype function
type = int ()
and maybe, just maybe, you realize that the function actually returns
unsigned long long. And you try to fix it with:
(gdb) p /x (unsigned long long) function ()
$3 = 0xffffffffffffffff # incorrect
... which still produces the wrong result, because GDB simply applied
int to unsigned long long conversion. Meaning, it sign-extended the
integer that it extracted from the return of the function, to 64-bits.
and then maybe, after asking around on IRC, you realize you have to
cast the function to a pointer of the right type, and call that. It
won't be easy, but after a few missteps, you'll get to it:
..... (gdb) p /x ((unsigned long long(*) ()) function) ()
$666 = 0x7fffffffffffffff # finally! :-)
So to improve on the user experience, this patch does the following
(interrelated) things:
- makes no-debug-info functions no longer default to "int" as return
type. Instead, they're left with NULL/"<unknown return type>"
return type.
(gdb) ptype getenv
type = <unknown return type> ()
- makes calling a function with unknown return type an error.
(gdb) p getenv ("PATH")
'getenv' has unknown return type; cast the call to its declared return type
- and then to make it easier to call the function, makes it possible
to _only_ cast the return of the function to the right type,
instead of having to cast the function to a function pointer:
(gdb) p (char *) getenv ("PATH") # now Just Works
$3 = 0x7fffffffe7d7 "/usr/local/bin:/"...
(gdb) p ((char *(*) (const char *)) getenv) ("PATH") # continues working
$4 = 0x7fffffffe7d7 "/usr/local/bin:/"...
I.e., it makes GDB default the function's return type to the type
of the cast, and the function's parameters to the type of the
arguments passed down.
After this patch, here's what you'll get for the "unsigned long long"
example above:
(gdb) p function ()
'function' has unknown return type; cast the call to its declared return type
(gdb) p /x (unsigned long long) function ()
$4 = 0x7fffffffffffffff # correct!
Note that while with "print" GDB shows the name of the function that
has the problem:
(gdb) p getenv ("PATH")
'getenv' has unknown return type; cast the call to its declared return type
which can by handy in more complicated expressions, "ptype" does not:
(gdb) ptype getenv ("PATH")
function has unknown return type; cast the call to its declared return type
This will be fixed in the next patch.
gdb/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* ada-lang.c (ada_evaluate_subexp) <TYPE_CODE_FUNC>: Don't handle
TYPE_GNU_IFUNC specially here. Throw error if return type is
unknown.
* ada-typeprint.c (print_func_type): Handle functions with unknown
return type.
* c-typeprint.c (c_type_print_base): Handle functions and methods
with unknown return type.
* compile/compile-c-symbols.c (convert_symbol_bmsym)
<mst_text_gnu_ifunc>: Use nodebug_text_gnu_ifunc_symbol.
* compile/compile-c-types.c: Include "objfiles.h".
(convert_func): For functions with unknown return type, warn and
default to int.
* compile/compile-object-run.c (compile_object_run): Adjust call
to call_function_by_hand_dummy.
* elfread.c (elf_gnu_ifunc_resolve_addr): Adjust call to
call_function_by_hand.
* eval.c (evaluate_subexp_standard): Adjust calls to
call_function_by_hand. Handle functions and methods with unknown
return type. Pass expect_type to call_function_by_hand.
* f-typeprint.c (f_type_print_base): Handle functions with unknown
return type.
* gcore.c (call_target_sbrk): Adjust call to
call_function_by_hand.
* gdbtypes.c (objfile_type): Leave nodebug text symbol with NULL
return type instead of int. Make nodebug_text_gnu_ifunc_symbol be
an integer address type instead of nodebug.
* guile/scm-value.c (gdbscm_value_call): Adjust call to
call_function_by_hand.
* infcall.c (error_call_unknown_return_type): New function.
(call_function_by_hand): New "default_return_type" parameter.
Pass it down.
(call_function_by_hand_dummy): New "default_return_type"
parameter. Use it instead of defaulting to int. If there's no
default and the return type is unknown, throw an error. If
there's a default return type, and the called function has no
debug info, then assume the function is prototyped.
* infcall.h (call_function_by_hand, call_function_by_hand_dummy):
New "default_return_type" parameter.
(error_call_unknown_return_type): New declaration.
* linux-fork.c (call_lseek): Cast return type of lseek.
(inferior_call_waitpid, checkpoint_command): Adjust calls to
call_function_by_hand.
* linux-tdep.c (linux_infcall_mmap, linux_infcall_munmap): Adjust
calls to call_function_by_hand.
* m2-typeprint.c (m2_procedure): Handle functions with unknown
return type.
* objc-lang.c (lookup_objc_class, lookup_child_selector)
(value_nsstring, print_object_command): Adjust calls to
call_function_by_hand.
* p-typeprint.c (pascal_type_print_varspec_prefix): Handle
functions with unknown return type.
(pascal_type_print_func_varspec_suffix): New function.
(pascal_type_print_varspec_suffix) <TYPE_CODE_FUNC,
TYPE_CODE_METHOD>: Use it.
* python/py-value.c (valpy_call): Adjust call to
call_function_by_hand.
* rust-lang.c (rust_evaluate_funcall): Adjust call to
call_function_by_hand.
* valarith.c (value_x_binop, value_x_unop): Adjust calls to
call_function_by_hand.
* valops.c (value_allocate_space_in_inferior): Adjust call to
call_function_by_hand.
* typeprint.c (type_print_unknown_return_type): New function.
* typeprint.h (type_print_unknown_return_type): New declaration.
gdb/testsuite/ChangeLog:
2017-09-04 Pedro Alves <palves@redhat.com>
* gdb.base/break-main-file-remove-fail.exp (test_remove_bp): Cast
return type of munmap in infcall.
* gdb.base/break-probes.exp: Cast return type of foo in infcall.
* gdb.base/checkpoint.exp: Simplify using for loop. Cast return
type of ftell in infcall.
* gdb.base/dprintf-detach.exp (dprintf_detach_test): Cast return
type of getpid in infcall.
* gdb.base/infcall-exec.exp: Cast return type of execlp in
infcall.
* gdb.base/info-os.exp: Cast return type of getpid in infcall.
Bail on failure to extract the pid.
* gdb.base/nodebug.c: #include <stdint.h>.
(multf, multf_noproto, mult, mult_noproto, add8, add8_noproto):
New functions.
* gdb.base/nodebug.exp (test_call_promotion): New procedure.
Change expected output of print/whatis/ptype with functions with
no debug info. Test all supported languages. Call
test_call_promotion.
* gdb.compile/compile.exp: Adjust expected output to expect
warning.
* gdb.threads/siginfo-threads.exp: Likewise.
2017-09-04 21:21:13 +02:00
|
|
|
for {set num 1} {$num <= 10} {incr num} {
|
|
|
|
gdb_test "restart $num" "if .c == EOF.*" "restart $num three"
|
|
|
|
gdb_test "continue" "breakpoint 2.*" "break2 $num one"
|
|
|
|
gdb_test "print (long) ftell (out) > 100000" " = 1.*" "outfile still open $num"
|
|
|
|
}
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# Now confirm that if one fork exits, we automatically switch to another one.
|
|
|
|
#
|
|
|
|
|
|
|
|
delete_breakpoints
|
|
|
|
gdb_test "continue" \
|
2011-03-07 17:03:04 +01:00
|
|
|
"Deleting copy.*$inferior_exited_re normally.*Switching to.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"exit, dropped into next fork one"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
gdb_test "continue" \
|
2011-03-07 17:03:04 +01:00
|
|
|
"Deleting copy.*$inferior_exited_re normally.*Switching to.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"exit, dropped into next fork two"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
gdb_test "continue" \
|
2011-03-07 17:03:04 +01:00
|
|
|
"Deleting copy.*$inferior_exited_re normally.*Switching to.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"exit, dropped into next fork three"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
gdb_test "continue" \
|
2011-03-07 17:03:04 +01:00
|
|
|
"Deleting copy.*$inferior_exited_re normally.*Switching to.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"exit, dropped into next fork four"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
gdb_test "continue" \
|
2011-03-07 17:03:04 +01:00
|
|
|
"Deleting copy.*$inferior_exited_re normally.*Switching to.*" \
|
2016-12-01 21:44:38 +01:00
|
|
|
"exit, dropped into next fork five"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# There should be still at least five forks left
|
|
|
|
#
|
|
|
|
|
List checkpoints in ascending order
Before:
(gdb) info checkpoints
3 process 29132 at 0x4008ad, file foo.c, line 81
2 process 29131 at 0x4008ad, file foo.c, line 81
1 process 29130 at 0x4008ad, file foo.c, line 81
* 0 Thread 0x7ffff7fc5740 (LWP 29128) (main process) at 0x4008ad, file foo.c, line 81
After:
(gdb) info checkpoints
* 0 Thread 0x7ffff7fc5740 (LWP 29128) (main process) at 0x4008ad, file foo.c, line 81
1 process 29130 at 0x4008ad, file foo.c, line 81
2 process 29131 at 0x4008ad, file foo.c, line 81
3 process 29132 at 0x4008ad, file foo.c, line 81
gdb/ChangeLog:
2015-11-24 Pedro Alves <palves@redhat.com>
PR 17539
* printcmd.c (display_command): Append new display at the end of
the list.
gdb/testsuite/ChangeLog:
2015-11-24 Pedro Alves <palves@redhat.com>
PR 17539
* gdb.base/display.exp: Expect displays to be sorted in ascending
order. Use multi_line.
* gdb.base/solib-display.exp: Likewise.
2015-11-24 19:11:22 +01:00
|
|
|
gdb_test "info checkpoints" " 1 .* 2 .* 3 .* 4 .* 5 .*" \
|
2006-01-04 20:29:26 +01:00
|
|
|
"info checkpoints two"
|
|
|
|
|
|
|
|
#
|
|
|
|
# Kill should now terminate all of them.
|
|
|
|
#
|
|
|
|
|
|
|
|
gdb_test "kill" "" "kill all one" \
|
|
|
|
"Kill the program being debugged.*y or n. $" "y"
|
|
|
|
|
|
|
|
#
|
|
|
|
# and confirm that all are gone
|
|
|
|
#
|
|
|
|
|
|
|
|
gdb_test "restart 0" "Not found.*" "no more checkpoint 0"
|
|
|
|
gdb_test "restart 1" "Not found.*" "no more checkpoint 1"
|
|
|
|
gdb_test "restart 2" "Not found.*" "no more checkpoint 2"
|
|
|
|
gdb_test "restart 3" "Not found.*" "no more checkpoint 3"
|
|
|
|
gdb_test "restart 4" "Not found.*" "no more checkpoint 4"
|
|
|
|
gdb_test "restart 5" "Not found.*" "no more checkpoint 5"
|
|
|
|
gdb_test "restart 6" "Not found.*" "no more checkpoint 6"
|
|
|
|
gdb_test "restart 7" "Not found.*" "no more checkpoint 7"
|
|
|
|
gdb_test "restart 8" "Not found.*" "no more checkpoint 8"
|
|
|
|
gdb_test "restart 9" "Not found.*" "no more checkpoint 9"
|
|
|
|
gdb_test "restart 10" "Not found.*" "no more checkpoint 10"
|
|
|
|
|
|
|
|
#
|
2010-03-11 01:20:29 +01:00
|
|
|
# Now let's try setting a large number of checkpoints (>600)
|
2006-01-04 20:29:26 +01:00
|
|
|
#
|
|
|
|
|
|
|
|
gdb_exit
|
|
|
|
gdb_start
|
|
|
|
gdb_reinitialize_dir $srcdir/$subdir
|
|
|
|
gdb_load ${binfile}
|
|
|
|
|
|
|
|
runto_main
|
|
|
|
gdb_breakpoint $break1_loc
|
|
|
|
|
2010-05-25 00:03:59 +02:00
|
|
|
gdb_test "commands\nsilent\nif (lines % 2)\ncheckpoint\nend\n continue\nend" \
|
|
|
|
"" \
|
|
|
|
"set checkpoint breakpoint"
|
2006-01-04 20:29:26 +01:00
|
|
|
|
2010-03-11 01:20:29 +01:00
|
|
|
set prev_timeout $timeout
|
|
|
|
set timeout [expr $timeout + 120]
|
|
|
|
verbose "Timeout now $timeout sec."
|
|
|
|
|
2006-01-04 20:29:26 +01:00
|
|
|
gdb_breakpoint $break2_loc
|
|
|
|
gdb_test "continue" "breakpoint 2.*" "break2 with many checkpoints"
|
|
|
|
|
2007-03-09 16:20:16 +01:00
|
|
|
set count 0
|
|
|
|
set msg "info checkpoints with at least 600 checkpoints"
|
|
|
|
gdb_test_multiple "info checkpoints" $msg {
|
|
|
|
-re " $decimal process \[^\r\]*\r\n" {
|
|
|
|
incr count
|
|
|
|
exp_continue
|
|
|
|
}
|
|
|
|
-re "$gdb_prompt $" {
|
|
|
|
if { $count >= 600 } {
|
|
|
|
pass $msg
|
|
|
|
} else {
|
|
|
|
fail $msg
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-01-04 20:29:26 +01:00
|
|
|
|
|
|
|
#
|
|
|
|
# OK, kill 'em all...
|
|
|
|
#
|
|
|
|
|
2010-03-11 01:20:29 +01:00
|
|
|
gdb_test "kill" "" "kill all one with many checkpoints" \
|
2006-01-04 20:29:26 +01:00
|
|
|
"Kill the program being debugged.*y or n. $" "y"
|
|
|
|
|
2010-03-11 01:20:29 +01:00
|
|
|
# Restore old timeout
|
|
|
|
set timeout $prev_timeout
|
|
|
|
verbose "Timeout now $timeout sec."
|
|
|
|
|
2006-01-04 20:29:26 +01:00
|
|
|
#
|
|
|
|
# Finished: cleanup
|
|
|
|
#
|