This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
RFD: Testsuite cases for inferior function calls
- To: gdb-patches at sourceware dot cygnus dot com
- Subject: RFD: Testsuite cases for inferior function calls
- From: "Peter.Schauer" <Peter dot Schauer at regent dot e-technik dot tu-muenchen dot de>
- Date: Sun, 17 Sep 2000 13:03:19 MET DST
Fernando Nasser wrote:
> Probably because there is no testcase for this... (hint hint hint)
I have spent some time to come up with testsuite cases for this,
and fixing all the GDB bugs that turned up in the targets I have access to
(Solaris sparc, Solaris x86, AIX 4.3, Linux x86).
I suspect that many more targets might fail on these testcases, so before I
go to all the trouble for submitting proper RFAs for the changes (adding
more comments and ChangeLog entries), is there any chance that the new
testsuite cases get accepted ?
I'd also be interested in the test results on other targets for the new
testcases.
Here are my current diffs versus CVS GDB from Sep 15:
*** ./testsuite/gdb.base/callfuncs.c.orig Mon Jun 28 18:02:51 1999
--- ./testsuite/gdb.base/callfuncs.c Fri Sep 15 21:36:51 2000
***************
*** 172,192 ****
(i5 == 5) && (i6 == 6) && (i7 == 7) && (i8 == 8) && (i9 == 9);
}
-
- /* Gotta have a main to be able to generate a linked, runnable
- executable, and also provide a useful place to set a breakpoint. */
- extern void * malloc() ;
- int main ()
- {
- #ifdef usestubs
- set_debug_traps();
- breakpoint();
- #endif
- malloc(1);
- t_structs_c(struct_val1);
- return 0 ;
- }
-
/* Functions that expect specific values to be passed and return
either 0 or 1, depending upon whether the values were
passed incorrectly or correctly, respectively. */
--- 172,177 ----
***************
*** 356,359 ****
--- 341,360 ----
#endif
{
return ((*func_arg1)(a, b));
+ }
+
+
+ /* Gotta have a main to be able to generate a linked, runnable
+ executable, and also provide a useful place to set a breakpoint. */
+ extern void * malloc() ;
+ int main ()
+ {
+ #ifdef usestubs
+ set_debug_traps();
+ breakpoint();
+ #endif
+ malloc(1);
+ t_double_values(double_val1, double_val2);
+ t_structs_c(struct_val1);
+ return 0 ;
}
*** ./testsuite/gdb.base/callfuncs.exp.orig Thu Jan 6 04:06:51 2000
--- ./testsuite/gdb.base/callfuncs.exp Fri Sep 15 21:36:51 2000
***************
*** 237,242 ****
--- 237,260 ----
"call inferior func with struct - returns char *"
}
+ # Procedure to get current content of all registers.
+ global all_registers_content
+ set all_registers_content ""
+ proc do_get_all_registers { } {
+ global gdb_prompt
+ global expect_out
+ global all_registers_content
+
+ set all_registers_content ""
+ send_gdb "info all-registers\n"
+ gdb_expect {
+ -re "info all-registers\r\n(.*)$gdb_prompt $" {
+ set all_registers_content $expect_out(1,string)
+ }
+ default {}
+ }
+ }
+
# Start with a fresh gdb.
gdb_exit
***************
*** 271,277 ****
--- 289,368 ----
}
}
+ # Make sure that malloc gets called and that the floating point unit
+ # is initialized via a call to t_double_values.
+ gdb_test "next" "t_double_values\\(double_val1, double_val2\\);.*"
gdb_test "next" "t_structs_c\\(struct_val1\\);.*"
+
+ # Save all register contents.
+ do_get_all_registers
+ set old_reg_content $all_registers_content
+
+ # Perform function calls.
do_function_calls
+ # Check if all registers still have the same value.
+ do_get_all_registers
+ set new_reg_content $all_registers_content
+ if [string match $old_reg_content $new_reg_content] then {
+ pass "gdb function calls preserve register contents"
+ } else {
+ set old_reg_content $all_registers_content
+ fail "gdb function calls preserve register contents"
+ }
+
+ # Set breakpoint at a function we will call from gdb.
+ gdb_breakpoint add
+
+ # Call function (causing a breakpoint hit in the call dummy) and do a continue,
+ # make sure we are back at main and still have the same register contents.
+ gdb_test "print add(4,5)" "The program being debugged stopped while.*" ""
+ gdb_test "continue" "Continuing.*" "continue from call dummy breakpoint"
+ if ![gdb_test "bt 2" \
+ "#0 main.*" \
+ "bt after continuing from call dummy breakpoint"] then {
+ do_get_all_registers
+ set new_reg_content $all_registers_content
+ if [string match $old_reg_content $new_reg_content] then {
+ pass "continue after stop in call dummy preserves register contents"
+ } else {
+ fail "continue after stop in call dummy preserves register contents"
+ }
+ }
+
+ # Call function (causing a breakpoint hit in the call dummy) and do a finish,
+ # make sure we are back at main and still have the same register contents.
+ gdb_test "print add(4,5)" "The program being debugged stopped while.*" ""
+ gdb_test "finish" \
+ "Value returned is.* = 9" \
+ "finish from call dummy breakpoint returns correct value"
+ if ![gdb_test "bt 2" \
+ "#0 main.*" \
+ "bt after finishing from call dummy breakpoint"] then {
+ do_get_all_registers
+ set new_reg_content $all_registers_content
+ if [string match $old_reg_content $new_reg_content] then {
+ pass "finish after stop in call dummy preserves register contents"
+ } else {
+ fail "finish after stop in call dummy preserves register contents"
+ }
+ }
+
+ # Call function (causing a breakpoint hit in the call dummy) and do a return
+ # with a value, make sure we are back at main with the same register contents.
+ gdb_test "print add(4,5)" "The program being debugged stopped while.*" ""
+ if ![gdb_test "return 7" \
+ "#0 main.*" \
+ "back at main after return from call dummy breakpoint" \
+ "Make add return now. .y or n.*" \
+ "y"] then {
+ do_get_all_registers
+ set new_reg_content $all_registers_content
+ if [string match $old_reg_content $new_reg_content] then {
+ pass "return after stop in call dummy preserves register contents"
+ } else {
+ fail "return after stop in call dummy preserves register contents"
+ }
+ }
+
return 0
*** ./config/i386/nm-linux.h.orig Fri Sep 15 21:27:38 2000
--- ./config/i386/nm-linux.h Sun Sep 17 12:24:45 2000
***************
*** 65,76 ****
/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
#define FETCH_INFERIOR_REGISTERS
! /* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we fall
back on the code `infptrace.c' (well a copy of that code in
`i386-linux-nat.c' for now) and we can access only the
general-purpose registers in that way. */
! #define CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS)
! #define CANNOT_STORE_REGISTER(regno) CANNOT_FETCH_REGISTER (regno)
/* Override child_resume in `infptrace.c'. */
#define CHILD_RESUME
--- 65,78 ----
/* Override copies of {fetch,store}_inferior_registers in `infptrace.c'. */
#define FETCH_INFERIOR_REGISTERS
! /* Nevertheless, define CANNOT_{FETCH,STORE}_REGISTER, because we might fall
back on the code `infptrace.c' (well a copy of that code in
`i386-linux-nat.c' for now) and we can access only the
general-purpose registers in that way. */
! extern int cannot_fetch_register (int regno);
! extern int cannot_store_register (int regno);
! #define CANNOT_FETCH_REGISTER(regno) cannot_store_register (regno)
! #define CANNOT_STORE_REGISTER(regno) cannot_fetch_register (regno)
/* Override child_resume in `infptrace.c'. */
#define CHILD_RESUME
*** ./i386-linux-nat.c.orig Fri Sep 15 21:27:11 2000
--- ./i386-linux-nat.c Sun Sep 17 12:20:48 2000
***************
*** 133,141 ****
#endif
/* Registers we shouldn't try to fetch. */
! #if !defined (CANNOT_FETCH_REGISTER)
! #define CANNOT_FETCH_REGISTER(regno) 0
! #endif
/* Fetch one register. */
--- 133,139 ----
#endif
/* Registers we shouldn't try to fetch. */
! #define OLD_CANNOT_FETCH_REGISTER(regno) ((regno) >= NUM_GREGS)
/* Fetch one register. */
***************
*** 150,156 ****
char buf[MAX_REGISTER_RAW_SIZE];
int tid;
! if (CANNOT_FETCH_REGISTER (regno))
{
memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
supply_register (regno, buf);
--- 148,154 ----
char buf[MAX_REGISTER_RAW_SIZE];
int tid;
! if (OLD_CANNOT_FETCH_REGISTER (regno))
{
memset (buf, '\0', REGISTER_RAW_SIZE (regno)); /* Supply zeroes */
supply_register (regno, buf);
***************
*** 201,209 ****
}
/* Registers we shouldn't try to store. */
! #if !defined (CANNOT_STORE_REGISTER)
! #define CANNOT_STORE_REGISTER(regno) 0
! #endif
/* Store one register. */
--- 199,205 ----
}
/* Registers we shouldn't try to store. */
! #define OLD_CANNOT_STORE_REGISTER(regno) ((regno) >= NUM_GREGS)
/* Store one register. */
***************
*** 217,223 ****
unsigned int offset; /* Offset of registers within the u area. */
int tid;
! if (CANNOT_STORE_REGISTER (regno))
{
return;
}
--- 213,219 ----
unsigned int offset; /* Offset of registers within the u area. */
int tid;
! if (OLD_CANNOT_STORE_REGISTER (regno))
{
return;
}
***************
*** 513,518 ****
--- 509,529 ----
/* Transferring arbitrary registers between GDB and inferior. */
+ int
+ cannot_fetch_register (int regno)
+ {
+ if (! have_ptrace_getregs)
+ return OLD_CANNOT_FETCH_REGISTER (regno);
+ return 0;
+ }
+ int
+ cannot_store_register (int regno)
+ {
+ if (! have_ptrace_getregs)
+ return OLD_CANNOT_STORE_REGISTER (regno);
+ return 0;
+ }
+
/* Fetch register REGNO from the child process. If REGNO is -1, do
this for all registers (including the floating point and SSE
registers). */
*** ./rs6000-tdep.c.orig Sat Aug 5 11:37:42 2000
--- ./rs6000-tdep.c Fri Sep 15 21:36:51 2000
***************
*** 671,679 ****
frames, etc.
*************************************************************************/
- extern int stop_stack_dummy;
-
/* Pop the innermost frame, go back to the caller. */
static void
--- 671,677 ----
***************
*** 687,693 ****
pc = read_pc ();
sp = FRAME_FP (frame);
! if (stop_stack_dummy)
{
generic_pop_dummy_frame ();
flush_cached_frames ();
--- 685,691 ----
pc = read_pc ();
sp = FRAME_FP (frame);
! if (PC_IN_CALL_DUMMY (frame->pc, frame->frame, frame->frame))
{
generic_pop_dummy_frame ();
flush_cached_frames ();
***************
*** 2140,2145 ****
--- 2138,2144 ----
set_gdbarch_get_saved_register (gdbarch, generic_get_saved_register);
set_gdbarch_fix_call_dummy (gdbarch, rs6000_fix_call_dummy);
set_gdbarch_push_dummy_frame (gdbarch, generic_push_dummy_frame);
+ set_gdbarch_save_dummy_frame_tos (gdbarch, generic_save_dummy_frame_tos);
set_gdbarch_push_return_address (gdbarch, ppc_push_return_address);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_coerce_float_to_double (gdbarch, rs6000_coerce_float_to_double);
*** ./sparc-tdep.c.orig Fri Sep 15 21:27:31 2000
--- ./sparc-tdep.c Fri Sep 15 21:36:51 2000
***************
*** 2138,2148 ****
/* Comply with strange Sun cc calling convention for struct-returning
functions. */
! if (!using_gcc
! && (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
! || TYPE_CODE (value_type) == TYPE_CODE_UNION))
! store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
! TYPE_LENGTH (value_type) & 0x1fff);
if (!(GDB_TARGET_IS_SPARC64))
{
--- 2138,2152 ----
/* Comply with strange Sun cc calling convention for struct-returning
functions. */
! if (TYPE_CODE (value_type) == TYPE_CODE_STRUCT
! || TYPE_CODE (value_type) == TYPE_CODE_UNION)
! {
! store_unsigned_integer (dummy + CALL_DUMMY_CALL_OFFSET + 8, 4,
! TYPE_LENGTH (value_type) & 0x1fff);
! set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 0x30);
! }
! else
! set_gdbarch_call_dummy_breakpoint_offset (current_gdbarch, 0x2c);
if (!(GDB_TARGET_IS_SPARC64))
{
***************
*** 2961,2971 ****
set_gdbarch_long_long_bit (gdbarch, 8 * TARGET_CHAR_BIT);
set_gdbarch_max_register_raw_size (gdbarch, 8);
set_gdbarch_max_register_virtual_size (gdbarch, 8);
- #ifdef DO_CALL_DUMMY_ON_STACK
- set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
- #else
- set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
- #endif
set_gdbarch_pop_frame (gdbarch, sparc_pop_frame);
set_gdbarch_push_return_address (gdbarch, sparc_push_return_address);
set_gdbarch_push_dummy_frame (gdbarch, sparc_push_dummy_frame);
--- 2965,2970 ----
***************
*** 2999,3004 ****
--- 2998,3004 ----
/* 32-bit machine types: */
#ifdef SPARC32_CALL_DUMMY_ON_STACK
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
set_gdbarch_call_dummy_address (gdbarch, sparc_call_dummy_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0x30);
set_gdbarch_call_dummy_length (gdbarch, 0x38);
***************
*** 3005,3010 ****
--- 3005,3011 ----
set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_32);
#else
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
***************
*** 3053,3058 ****
--- 3054,3060 ----
default: /* Any new machine type is likely to be 64-bit. */
#ifdef SPARC64_CALL_DUMMY_ON_STACK
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_on_stack);
set_gdbarch_call_dummy_address (gdbarch, sparc_call_dummy_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 8 * 4);
set_gdbarch_call_dummy_length (gdbarch, 192);
***************
*** 3060,3065 ****
--- 3062,3068 ----
set_gdbarch_call_dummy_start_offset (gdbarch, 148);
set_gdbarch_call_dummy_words (gdbarch, call_dummy_64);
#else
+ set_gdbarch_pc_in_call_dummy (gdbarch, pc_in_call_dummy_at_entry_point);
set_gdbarch_call_dummy_address (gdbarch, entry_point_address);
set_gdbarch_call_dummy_breakpoint_offset (gdbarch, 0);
set_gdbarch_call_dummy_length (gdbarch, 0);
*** ./stack.c.orig Sat Aug 5 11:37:49 2000
--- ./stack.c Fri Sep 15 21:36:51 2000
***************
*** 1892,1897 ****
--- 1892,1903 ----
if (retval_exp)
set_return_value (return_value);
+ /* If we are at the end of a call dummy now, pop the dummy frame too. */
+
+ if (CALL_DUMMY_HAS_COMPLETED (read_pc(), read_sp (),
+ FRAME_FP (get_current_frame ())))
+ POP_FRAME;
+
/* If interactive, print the frame that is now current. */
if (from_tty)
--
Peter Schauer pes@regent.e-technik.tu-muenchen.de