mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-30 12:44:10 +08:00
gdb/
* infcall.c (call_function_by_hand): Move BP_ADDR comment to AT_ENTRY_POINT. (call_function_by_hand) <ON_STACK>: Call write_memory with gdbarch_breakpoint_from_pc, if possible. (call_function_by_hand) <AT_ENTRY_POINT>: The BP_ADDR comment is moved here. gdb/testsuite/ * gdb.base/valgrind-infcall.c: New file. * gdb.base/valgrind-infcall.exp: New file.
This commit is contained in:
parent
1467929f3f
commit
a14dd77ea7
@ -1,3 +1,12 @@
|
||||
2012-07-31 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* infcall.c (call_function_by_hand): Move BP_ADDR comment to
|
||||
AT_ENTRY_POINT.
|
||||
(call_function_by_hand) <ON_STACK>: Call write_memory with
|
||||
gdbarch_breakpoint_from_pc, if possible.
|
||||
(call_function_by_hand) <AT_ENTRY_POINT>: The BP_ADDR comment is moved
|
||||
here.
|
||||
|
||||
2012-07-31 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* tracepoint.c: Add 'static' for some variables.
|
||||
|
@ -618,15 +618,38 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
|
||||
not just the breakpoint but also an extra word containing the
|
||||
size (?) of the structure being passed. */
|
||||
|
||||
/* The actual breakpoint (at BP_ADDR) is inserted separatly so there
|
||||
is no need to write that out. */
|
||||
|
||||
switch (gdbarch_call_dummy_location (gdbarch))
|
||||
{
|
||||
case ON_STACK:
|
||||
sp = push_dummy_code (gdbarch, sp, funaddr,
|
||||
args, nargs, target_values_type,
|
||||
&real_pc, &bp_addr, get_current_regcache ());
|
||||
{
|
||||
const gdb_byte *bp_bytes;
|
||||
CORE_ADDR bp_addr_as_address;
|
||||
int bp_size;
|
||||
|
||||
/* Be careful BP_ADDR is in inferior PC encoding while
|
||||
BP_ADDR_AS_ADDRESS is a plain memory address. */
|
||||
|
||||
sp = push_dummy_code (gdbarch, sp, funaddr, args, nargs,
|
||||
target_values_type, &real_pc, &bp_addr,
|
||||
get_current_regcache ());
|
||||
|
||||
/* Write a legitimate instruction at the point where the infcall
|
||||
breakpoint is going to be inserted. While this instruction
|
||||
is never going to be executed, a user investigating the
|
||||
memory from GDB would see this instruction instead of random
|
||||
uninitialized bytes. We chose the breakpoint instruction
|
||||
as it may look as the most logical one to the user and also
|
||||
valgrind 3.7.0 needs it for proper vgdb inferior calls.
|
||||
|
||||
If software breakpoints are unsupported for this target we
|
||||
leave the user visible memory content uninitialized. */
|
||||
|
||||
bp_addr_as_address = bp_addr;
|
||||
bp_bytes = gdbarch_breakpoint_from_pc (gdbarch, &bp_addr_as_address,
|
||||
&bp_size);
|
||||
if (bp_bytes != NULL)
|
||||
write_memory (bp_addr_as_address, bp_bytes, bp_size);
|
||||
}
|
||||
break;
|
||||
case AT_ENTRY_POINT:
|
||||
{
|
||||
@ -634,8 +657,12 @@ call_function_by_hand (struct value *function, int nargs, struct value **args)
|
||||
|
||||
real_pc = funaddr;
|
||||
dummy_addr = entry_point_address ();
|
||||
|
||||
/* A call dummy always consists of just a single breakpoint, so
|
||||
its address is the same as the address of the dummy. */
|
||||
its address is the same as the address of the dummy.
|
||||
|
||||
The actual breakpoint is inserted separatly so there is no need to
|
||||
write that out. */
|
||||
bp_addr = dummy_addr;
|
||||
break;
|
||||
}
|
||||
|
@ -1,3 +1,8 @@
|
||||
2012-07-27 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.base/valgrind-infcall.c: New file.
|
||||
* gdb.base/valgrind-infcall.exp: New file.
|
||||
|
||||
2012-07-30 Doug Evans <dje@google.com>
|
||||
|
||||
* gdb.dwarf2/fission-reread.S: Use .data instead of .bss.
|
||||
|
40
gdb/testsuite/gdb.base/valgrind-infcall.c
Normal file
40
gdb/testsuite/gdb.base/valgrind-infcall.c
Normal file
@ -0,0 +1,40 @@
|
||||
/* This testcase is part of GDB, the GNU debugger.
|
||||
|
||||
Copyright 2012 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>
|
||||
|
||||
static volatile int infcall_var;
|
||||
|
||||
static int
|
||||
gdb_test_infcall (void)
|
||||
{
|
||||
return ++infcall_var;
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
void *p;
|
||||
|
||||
gdb_test_infcall ();
|
||||
p = malloc (1);
|
||||
if (p == NULL)
|
||||
return 1;
|
||||
free (p);
|
||||
free (p); /* double-free */
|
||||
return 0;
|
||||
}
|
115
gdb/testsuite/gdb.base/valgrind-infcall.exp
Normal file
115
gdb/testsuite/gdb.base/valgrind-infcall.exp
Normal file
@ -0,0 +1,115 @@
|
||||
# Copyright 2012 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/>.
|
||||
|
||||
if [is_remote target] {
|
||||
# The test always runs locally.
|
||||
return 0
|
||||
}
|
||||
|
||||
set test valgrind-infcall
|
||||
set srcfile $test.c
|
||||
set executable $test
|
||||
set binfile ${objdir}/${subdir}/${executable}
|
||||
if {[build_executable $test.exp $executable $srcfile {debug}] == -1} {
|
||||
return -1
|
||||
}
|
||||
|
||||
set test "spawn valgrind"
|
||||
set cmd "valgrind --vgdb-error=0 $binfile"
|
||||
set res [remote_spawn host $cmd];
|
||||
if { $res < 0 || $res == "" } {
|
||||
verbose -log "Spawning $cmd failed."
|
||||
unsupported $test
|
||||
return -1
|
||||
}
|
||||
pass $test
|
||||
# Declare GDB now as running.
|
||||
set gdb_spawn_id -1
|
||||
|
||||
# GDB started by vgdb stops already after the startup is executed, like with
|
||||
# non-extended gdbserver. It is also not correct to run/attach the inferior.
|
||||
set use_gdb_stub 1
|
||||
|
||||
set test "valgrind started"
|
||||
# The trailing '.' differs for different memcheck versions.
|
||||
gdb_test_multiple "" $test {
|
||||
-re "Memcheck, a memory error detector\\.?\r\n" {
|
||||
pass $test
|
||||
}
|
||||
-re "valgrind: failed to start tool 'memcheck' for platform '.*': No such file or directory" {
|
||||
unsupported $test
|
||||
return -1
|
||||
}
|
||||
-re "valgrind: wrong ELF executable class" {
|
||||
unsupported $test
|
||||
return -1
|
||||
}
|
||||
-re "command not found" {
|
||||
# The spawn succeeded, but then valgrind was not found - e.g. if
|
||||
# we spawned SSH to a remote system.
|
||||
unsupported $test
|
||||
return -1
|
||||
}
|
||||
-re "valgrind: Bad option '--vgdb-error=0'" {
|
||||
# valgrind is not >= 3.7.0.
|
||||
unsupported $test
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
set test "vgdb prompt"
|
||||
# The trailing '.' differs for different memcheck versions.
|
||||
gdb_test_multiple "" $test {
|
||||
-re " (target remote | \[^\r\n\]*/vgdb \[^\r\n\]*)\r\n" {
|
||||
set vgdbcmd $expect_out(1,string)
|
||||
pass $test
|
||||
}
|
||||
}
|
||||
|
||||
# Do not kill valgrind.
|
||||
unset gdb_spawn_id
|
||||
set board [host_info name]
|
||||
unset_board_info fileid
|
||||
|
||||
clean_restart $executable
|
||||
|
||||
gdb_test "$vgdbcmd" " in _start .*" "target remote for vgdb"
|
||||
|
||||
gdb_test "monitor v.set gdb_output" "valgrind output will go to gdb.*"
|
||||
|
||||
set continue_count 1
|
||||
while 1 {
|
||||
set test "continue #$continue_count"
|
||||
gdb_test_multiple "continue" "" {
|
||||
-re "Invalid free\\(\\).*: main .*\r\n$gdb_prompt $" {
|
||||
pass $test
|
||||
break
|
||||
}
|
||||
-re "\r\n$gdb_prompt $" {
|
||||
pass "$test (false warning)"
|
||||
}
|
||||
}
|
||||
set continue_count [expr $continue_count + 1]
|
||||
}
|
||||
|
||||
set test "p gdb_test_infcall ()"
|
||||
gdb_test_multiple $test $test {
|
||||
-re "unhandled instruction bytes.*\r\n$gdb_prompt $" {
|
||||
fail $test
|
||||
}
|
||||
-re "Continuing \\.\\.\\..*\r\n\\\$1 = 2\r\n$gdb_prompt $" {
|
||||
pass $test
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user