This is the mail archive of the gdb-cvs@sourceware.org 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]
Other format: [Raw text]

[binutils-gdb] Fix calling prototyped functions via function pointers


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=54990598c4c74b6af113baf801064d3b1837973f

commit 54990598c4c74b6af113baf801064d3b1837973f
Author: Pedro Alves <palves@redhat.com>
Date:   Mon Sep 4 20:21:13 2017 +0100

    Fix calling prototyped functions via function pointers
    
    Calling a prototyped function via a function pointer with the right
    prototype doesn't work correctly, if the called function requires
    argument coercion...  Like, e.g., with:
    
      float mult (float f1, float f2) { return f1 * f2; }
    
      (gdb) p mult (2, 3.5)
      $1 = 7
      (gdb) p ((float (*) (float, float)) mult) (2, 3.5)
      $2 = 0
    
    both calls should have returned the same, of course.  The problem is
    that GDB misses marking the type of the function pointer target as
    prototyped...
    
    Without the fix, the new test fails like this:
    
     (gdb) p ((int (*) (float, float)) t_float_values2)(3.14159,float_val2)
     $30 = 0
     (gdb) FAIL: gdb.base/callfuncs.exp: p ((int (*) (float, float)) t_float_values2)(3.14159,float_val2)
    
    gdb/ChangeLog:
    2017-09-04  Pedro Alves  <palves@redhat.com>
    
    	* gdbtypes.c (lookup_function_type_with_arguments): Mark function
    	types with more than one parameter as prototyped.
    
    gdb/testsuite/ChangeLog:
    2017-09-04  Pedro Alves  <palves@redhat.com>
    
    	* gdb.base/callfuncs.exp (do_function_calls): New parameter
    	"prototypes".  Test calling float functions via prototyped and
    	unprototyped function pointers.
    	(perform_all_tests): New parameter "prototypes".  Pass it down.
    	(top level): Pass down "prototypes" parameter to
    	perform_all_tests.

Diff:
---
 gdb/ChangeLog                        |  5 +++++
 gdb/gdbtypes.c                       |  2 ++
 gdb/testsuite/ChangeLog              |  9 +++++++++
 gdb/testsuite/gdb.base/callfuncs.exp | 26 +++++++++++++++++++++-----
 4 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9c9c6b1..d1fe7ca 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,10 @@
 2017-09-04  Pedro Alves  <palves@redhat.com>
 
+	* gdbtypes.c (lookup_function_type_with_arguments): Mark function
+	types with more than one parameter as prototyped.
+
+2017-09-04  Pedro Alves  <palves@redhat.com>
+
 	* cli/cli-cmds.c (print_disassembly, disassemble_current_function)
 	(disassemble_command): Use gdb_disassembly_flags instead of bare
 	int.
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index a686923..ceb4f0c 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -547,6 +547,8 @@ lookup_function_type_with_arguments (struct type *type,
 	  gdb_assert (nparams == 0);
 	  TYPE_PROTOTYPED (fn) = 1;
 	}
+      else
+	TYPE_PROTOTYPED (fn) = 1;
     }
 
   TYPE_NFIELDS (fn) = nparams;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 24ad99b..35c5928 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,12 @@
+2017-09-04  Pedro Alves  <palves@redhat.com>
+
+	* gdb.base/callfuncs.exp (do_function_calls): New parameter
+	"prototypes".  Test calling float functions via prototyped and
+	unprototyped function pointers.
+	(perform_all_tests): New parameter "prototypes".  Pass it down.
+	(top level): Pass down "prototypes" parameter to
+	perform_all_tests.
+
 2017-09-04  Simon Marchi  <simon.marchi@ericsson.com>
 
 	* gdb.base/commands.exp (loop_break_test, loop_continue_test):
diff --git a/gdb/testsuite/gdb.base/callfuncs.exp b/gdb/testsuite/gdb.base/callfuncs.exp
index 3651963..a537ebd 100644
--- a/gdb/testsuite/gdb.base/callfuncs.exp
+++ b/gdb/testsuite/gdb.base/callfuncs.exp
@@ -39,7 +39,7 @@ set skip_float_test [gdb_skip_float_test]
 # specifies that the numeric value of a relational or logical expression
 # (computed in the inferior) is 1 for true and 0 for false.
 
-proc do_function_calls {} {
+proc do_function_calls {prototypes} {
     global gdb_prompt skip_float_test
 
     # We need to up this because this can be really slow on some boards.
@@ -95,11 +95,25 @@ proc do_function_calls {} {
 	setup_xfail "mn10300-*-*"
 	if { [test_compiler_info "armcc-*"] } { setup_xfail "*-*-*" }
 	gdb_test "p t_float_values(float_val1,-2.3765)" " = 1"
+	# Same, via unprototyped function pointer (t_float_values is
+	# always unprototyped).
+	gdb_test "p ((int (*) ()) t_float_values)(float_val1,-2.3765)" " = 1"
 
 	# Test passing of arguments which might not be widened.
 	gdb_test "p t_float_values2(0.0,0.0)" " = 0"
+	# Same, via function pointer.
+	if {$prototypes} {
+	    gdb_test "p ((int (*) (float, float)) t_float_values2)(0.0,0.0)" " = 0"
+	} else {
+	    gdb_test "p ((int (*) ()) t_float_values2)(0.0,0.0)" " = 0"
+	}
 
 	gdb_test "p t_float_values2(3.14159,float_val2)" " = 1"
+	if {$prototypes} {
+	    gdb_test "p ((int (*) (float, float)) t_float_values2)(3.14159,float_val2)" " = 1"
+	} else {
+	    gdb_test "p ((int (*) ()) t_float_values2)(3.14159,float_val2)" " = 1"
+	}
 
 	gdb_test "p t_float_many_args (float_val1, float_val2, float_val3, float_val4, float_val5, float_val6, float_val7, float_val8, float_val9, float_val10, float_val11, float_val12, float_val13, float_val14, float_val15)" " = 1" "call function with many float arguments."
 
@@ -315,7 +329,7 @@ proc rerun_and_prepare {} {
 	"next to t_structs_c"
 }
 
-proc perform_all_tests {} {
+proc perform_all_tests {prototypes} {
     gdb_test_no_output "set print sevenbit-strings"
     gdb_test_no_output "set print address off"
     gdb_test_no_output "set width 0"
@@ -326,7 +340,7 @@ proc perform_all_tests {} {
     set old_reg_content [fetch_all_registers "retrieve original register contents"]
 
     # Perform function calls.
-    do_function_calls
+    do_function_calls $prototypes
 
     # Check if all registers still have the same value.
     set new_reg_content [fetch_all_registers \
@@ -500,9 +514,11 @@ proc perform_all_tests {} {
 # Perform all tests with and without function prototypes.
 
 if { ![prepare_for_testing "failed to prepare" $testfile $srcfile "$compile_flags additional_flags=-DPROTOTYPES"] } {
-    perform_all_tests
+    perform_all_tests 1
 }
 
 if { ![prepare_for_testing "failed to prepare" $testfile $srcfile "$compile_flags additional_flags=-DNO_PROTOTYPES"] } {
-    with_test_prefix "noproto" perform_all_tests
+    with_test_prefix "noproto" {
+	perform_all_tests 0
+    }
 }


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