This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

RFD: Testsuite cases for inferior function calls


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]