This is the mail archive of the gdb@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]

Re: The root cause for SEGV in evaluating fortran function call,any solution or suggestion?


I also added a testcase for this.  It should be easy to test in the coding 
process.  I tested it with gfortran and mainline gdb, it report 5PASS + 
1FAIL ('p res_(2)' reports "Attempt to take address of value not located 
in memory").  The test with g77 and mainline gdb shows 4 PASS and 2 FAIL 
(SEGV with 'p res_(2)' and 'p res_(b)').  And test with the g77 and the 
latest patched gdb, it showed 5PASS + 1FAIL (error output with 'p res_(2)').

Do you think that it make sense for this goes into the testsuite tree? 

Here is the patch:

Index: gdb.fortran/func-call.f
===================================================================
RCS file: gdb.fortran/func-call.f
diff -N gdb.fortran/func-call.f
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gdb.fortran/func-call.f	4 Nov 2005 03:47:22 -0000
***************
*** 0 ****
--- 1,27 ----
+ c Copyright 2005 Free Software Foundation, Inc.
+ 
+ c This program is free software; you can redistribute it and/or modify
+ c it under the terms of the GNU General Public License as published by
+ c the Free Software Foundation; either version 2 of the License, or
+ c (at your option) any later version.
+ c
+ c This program is distributed in the hope that it will be useful,
+ c but WITHOUT ANY WARRANTY; without even the implied warranty of
+ c MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ c GNU General Public License for more details.
+ c
+ c You should have received a copy of the GNU General Public License
+ c along with this program; if not, write to the Free Software
+ c Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ 
+         PROGRAM funcall 
+           integer a, b
+           b = 2
+           a = res(b) 
+         END PROGRAM 
+ 
+         function res(m)
+           integer m
+           integer res
+           res = m * m
+         end function
Index: gdb.fortran/func-call.exp
===================================================================
RCS file: gdb.fortran/func-call.exp
diff -N gdb.fortran/func-call.exp
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gdb.fortran/func-call.exp	4 Nov 2005 03:47:22 -0000
***************
*** 0 ****
--- 1,79 ----
+ # Copyright 2005 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 2 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, write to the Free Software
+ # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+ 
+ # This file was written by Wu Zhou. (woodzltc@cn.ibm.com)
+ 
+ if $tracelevel then {
+ 	strace $tracelevel
+ }
+ 
+ set testfile "func-call"
+ set srcfile ${testfile}.f
+ set binfile ${objdir}/${subdir}/${testfile}
+ 
+ if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } {
+     untested "Couldn't compile ${srcfile}"
+     return -1
+ }
+ 
+ gdb_exit
+ gdb_start
+ gdb_reinitialize_dir $srcdir/$subdir
+ gdb_load ${binfile}
+ 
+ # To test "print res_(2)"
+ 
+ if ![runto MAIN__] then {
+     perror "couldn't run to breakpoint MAIN__"
+     continue
+ }
+ 
+ gdb_breakpoint [gdb_get_line_number "a = res(b)"]
+ gdb_continue_to_breakpoint "initialize argument b"
+ gdb_test_multiple "print res_(2)" "print res_(2)" {
+     -re ".*\[0-9\]+ = 4.*$gdb_prompt $" {
+         pass "use constant 2 as the argument"
+     }
+     -re "Program received signal SIGSEGV, Segmentation fault.*$gdb_prompt $" {
+         fail "print res_(2) get SEGV"   
+     }
+     -re ".*$gdb_prompt $" {
+         fail "other unexpected error"
+     }
+ }
+ 
+ # To test "print res_(b)"
+ 
+ if ![runto MAIN__] then {
+     perror "couldn't run to breakpoint MAIN__"
+     continue
+ }
+ 
+ gdb_breakpoint [gdb_get_line_number "a = res(b)"]
+ gdb_continue_to_breakpoint "initialize argument b"
+ gdb_test "print res_(b)" ".*\[0-9\]+ = 4.*" "use variable 'b' as the argument"
+ 
+ # To test "print res_(&b)"
+ 
+ if ![runto MAIN__] then {
+     perror "couldn't run to breakpoint MAIN__"
+     continue
+ }
+ 
+ gdb_breakpoint [gdb_get_line_number "a = res(b)"]
+ gdb_continue_to_breakpoint "initialize argument b"
+ gdb_test "print res_(&b)" ".*\[0-9\]+ = 4.*" "use the address of 'b' as the argument"
+ 


On Fri, 4 Nov 2005, Wu Zhou wrote:

> Hi Mark,
> 
> On Thu, 3 Nov 2005, Mark Kettenis wrote:
> 
> > > Date: Thu, 3 Nov 2005 11:14:51 +0800 (CST)
> > > From: Wu Zhou <woodzltc@cn.ibm.com>
> > > 
> > > Maybe we can convert the argument to its pointer before we enter into
> > > call_function_by_hand (evaluate_subexp_standard: case OP_FUNCALL)?  
> > > Normally what function you will use to allocate memory on the stack?  I am 
> > > not very familar with that kind of code.  Thanks!
> > 
> > Allocating memory on the stack is actually quite eazy.  Just
> > substract/add the amount of space you need from/to the stack pointer,
> > and use the new/old stack pointer as the address for the memory.
> > Whether you should substract or add depends on whether the stack grows
> > downward or upward.  Use gdbarch_inner_than(gdbarch, 1, 2) to check.
> > There's quite a bit of code in infcall.c that uses this trick.
> > 
> 
> Thanks.  I did some tests following this way.  But didn't get any success. 
> So I had to post here again to see if anybody can help me out.  
> 
> My basic idea is to create a value which hold the address to the original 
> argument. This is done in valur_addr for these argument which is not lval 
> and whose type is TYPE_CODE_INT.  Then I use the above method to get a new 
> value which hold the address to the original address.  Although it doesn't 
> report SEGV or "can not access memory" message, it didn't ouptut the 
> correct result I expected.  I expect 4 (which is 2 * 2), but it return 
> different number for me every time I run it.
> 
> Following is the changed I made to valur_arg_coerce and value_addr.  Could 
> anyone help me pointed out what is the reason why it fail.  Thanks a lot!
> 
> Index: infcall.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/infcall.c,v
> retrieving revision 1.73
> diff -c -3 -p -r1.73 infcall.c
> *** infcall.c	2 Sep 2005 19:02:44 -0000	1.73
> --- infcall.c	4 Nov 2005 03:11:35 -0000
> *************** value_arg_coerce (struct value *arg, str
> *** 109,114 ****
> --- 109,115 ----
>     switch (TYPE_CODE (type))
>       {
>       case TYPE_CODE_REF:
> +     case TYPE_CODE_PTR:
>         if (TYPE_CODE (arg_type) != TYPE_CODE_REF
>   	  && TYPE_CODE (arg_type) != TYPE_CODE_PTR)
>   	{
> *************** value_arg_coerce (struct value *arg, str
> *** 154,160 ****
>   	  type = lookup_pointer_type (TYPE_TARGET_TYPE (type));
>         break;
>       case TYPE_CODE_UNDEF:
> -     case TYPE_CODE_PTR:
>       case TYPE_CODE_STRUCT:
>       case TYPE_CODE_UNION:
>       case TYPE_CODE_VOID:
> --- 155,160 ----
> Index: valops.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/valops.c,v
> retrieving revision 1.161
> diff -c -3 -p -r1.161 valops.c
> *** valops.c	27 May 2005 04:39:32 -0000	1.161
> --- valops.c	4 Nov 2005 03:11:49 -0000
> *************** value_addr (struct value *arg1)
> *** 868,877 ****
>       }
>     if (TYPE_CODE (type) == TYPE_CODE_FUNC)
>       return value_coerce_function (arg1);
> ! 
>     if (VALUE_LVAL (arg1) != lval_memory)
>       error (_("Attempt to take address of value not located in memory."));
>   
>     /* Get target memory address */
>     arg2 = value_from_pointer (lookup_pointer_type (value_type (arg1)),
>   			     (VALUE_ADDRESS (arg1)
> --- 868,905 ----
>       }
>     if (TYPE_CODE (type) == TYPE_CODE_FUNC)
>       return value_coerce_function (arg1);
> ! /*
>     if (VALUE_LVAL (arg1) != lval_memory)
>       error (_("Attempt to take address of value not located in memory."));
> + */
> + 
> +   if (TYPE_CODE (type) == TYPE_CODE_INT  && VALUE_LVAL (arg1) == not_lval)
> +     {
> +       int len = TYPE_LENGTH (type);
> +       CORE_ADDR addr;
> +       CORE_ADDR sp = read_sp ();
> +       if (INNER_THAN (1, 2))
> + 	{
> + 	  /* stack grows downward */
> + 	  sp -= len;
> + 	  /* ... so the address of the thing we push is the
> + 	     stack pointer after we push it.  */
> + 	  addr = sp;
> + 	}
> +       else
> + 	{
> + 	  /* The stack grows up, so the address of the thing
> + 	     we push is the stack pointer before we push it.  */
> + 	  addr = sp;
> + 	  sp += len;
> + 	}
> + 
> +       addr = (CORE_ADDR) malloc (len);
> +       write_memory (addr, value_contents_all (arg1), len);
> +       arg2 = value_from_pointer (lookup_pointer_type (type), addr);
>   
> +       return arg2;
> +     }
>     /* Get target memory address */
>     arg2 = value_from_pointer (lookup_pointer_type (value_type (arg1)),
>   			     (VALUE_ADDRESS (arg1)
> 

 
 Regards
 - Wu Zhou
 
 


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