From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9800 invoked by alias); 7 Nov 2005 04:49:10 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 9789 invoked by uid 22791); 7 Nov 2005 04:49:07 -0000 Received: from ausmtp02.au.ibm.com (HELO ausmtp02.au.ibm.com) (202.81.18.187) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Mon, 07 Nov 2005 04:49:07 +0000 Received: from sd0208e0.au.ibm.com (d23rh904.au.ibm.com [202.81.18.202]) by ausmtp02.au.ibm.com (8.12.10/8.12.10) with ESMTP id jA74h7xa236896 for ; Mon, 7 Nov 2005 15:43:07 +1100 Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.250.243]) by sd0208e0.au.ibm.com (8.12.10/NCO/VERS6.7) with ESMTP id jA74q0rL128420 for ; Mon, 7 Nov 2005 15:52:00 +1100 Received: from d23av02.au.ibm.com (loopback [127.0.0.1]) by d23av02.au.ibm.com (8.12.11/8.13.3) with ESMTP id jA74mwZ6006489 for ; Mon, 7 Nov 2005 15:48:58 +1100 Received: from [9.181.133.252] ([9.181.133.252]) by d23av02.au.ibm.com (8.12.11/8.12.11) with ESMTP id jA74mtZU006442; Mon, 7 Nov 2005 15:48:56 +1100 Date: Mon, 07 Nov 2005 04:49:00 -0000 From: Wu Zhou To: Daniel Jacobowitz cc: Mark Kettenis , gdb@sources.redhat.com Subject: Re: The root cause for SEGV in evaluating fortran function call, any solution or suggestion? In-Reply-To: <20051107000949.GD19200@nevyn.them.org> Message-ID: References: <20051102145258.GA28372@nevyn.them.org> <200511032134.jA3LYDsT017248@elgar.sibelius.xs4all.nl> <20051107000949.GD19200@nevyn.them.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-SW-Source: 2005-11/txt/msg00135.txt.bz2 Hi Daniel, On Sun, 6 Nov 2005, Daniel Jacobowitz wrote: > On Fri, Nov 04, 2005 at 11:18:00AM +0800, Wu Zhou wrote: > > > 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! > > It's not quite as simple as Mark makes it out to be - in concept, sure, > but not in execution. You have to _allocate_ the space on the stack; > not just find empty space off the side of the stack and write the > argument there. > > By the type that we're calling value_arg_coerce, we've already > allocated some space on the stack, and saved the old stack pointer. > But we'll allocate more space on the stack below, when we push > arguments. And you have to be careful to keep the stack aligned > properly through all of this. Read through the surrounding bits of > infcall.c to see how this works for struct returns; that is the closest > analogue we have today. > > Maybe if you pass the sp value by reference to value_arg_coerce and > adjust it there... You are quite right. Following your pointer, I made another patch and it now passed with both g77 (3.4.4) and gfortran (4.0.1) on a x86 box. I didn't consider the red zone in AMD64 architecture, so maybe it won't work on it. I will try to find a chance to test it on other platform, such as ppc64 or any other platform I can get access to. Appended is the patch. Any comments and suggestion are highly appreciated! 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 7 Nov 2005 04:36:39 -0000 *************** Unwinding of stack if a signal is receiv *** 100,106 **** static struct value * value_arg_coerce (struct value *arg, struct type *param_type, ! int is_prototyped) { struct type *arg_type = check_typedef (value_type (arg)); struct type *type --- 100,106 ---- static struct value * value_arg_coerce (struct value *arg, struct type *param_type, ! int is_prototyped, CORE_ADDR *sp) { struct type *arg_type = check_typedef (value_type (arg)); struct type *type *************** value_arg_coerce (struct value *arg, str *** 109,118 **** switch (TYPE_CODE (type)) { case TYPE_CODE_REF: if (TYPE_CODE (arg_type) != TYPE_CODE_REF && TYPE_CODE (arg_type) != TYPE_CODE_PTR) { ! arg = value_addr (arg); deprecated_set_value_type (arg, param_type); return arg; } --- 109,119 ---- 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) { ! arg = value_addr_stack (arg, sp); deprecated_set_value_type (arg, param_type); return arg; } *************** 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 ---- *************** call_function_by_hand (struct value *fun *** 528,534 **** else param_type = NULL; ! args[i] = value_arg_coerce (args[i], param_type, prototyped); /* elz: this code is to handle the case in which the function to be called has a pointer to function as parameter and the --- 528,534 ---- else param_type = NULL; ! args[i] = value_arg_coerce (args[i], param_type, prototyped, &sp); /* elz: this code is to handle the case in which the function to be called has a pointer to function as parameter and the 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 7 Nov 2005 04:36:47 -0000 *************** value_addr (struct value *arg1) *** 886,891 **** --- 886,963 ---- return arg2; } + /* Mostly the same as value_addr. But when the argument passed is a constant + and the value is not a lval, we allocate a block of memory for that value + on the stack and return the value which contains that address. This is + only used for value_arg_coerce at this time. */ + + struct value * + value_addr_stack (struct value *arg1, CORE_ADDR *sp) + { + struct value *arg2; + + struct type *type = check_typedef (value_type (arg1)); + if (TYPE_CODE (type) == TYPE_CODE_REF) + { + /* Copy the value, but change the type from (T&) to (T*). + We keep the same location information, which is efficient, + and allows &(&X) to get the location containing the reference. */ + arg2 = value_copy (arg1); + deprecated_set_value_type (arg2, lookup_pointer_type (TYPE_TARGET_TYPE (type))); + return arg2; + } + if (TYPE_CODE (type) == TYPE_CODE_FUNC) + return value_coerce_function (arg1); + + if (TYPE_CODE (type) == TYPE_CODE_INT && VALUE_LVAL (arg1) == not_lval) + { + int len = TYPE_LENGTH (type); + CORE_ADDR addr; + + if (gdbarch_frame_align_p (current_gdbarch)) + *sp = gdbarch_frame_align (current_gdbarch, *sp); + if (INNER_THAN (1, 2)) + { + /* stack grows downward */ + if (gdbarch_frame_align_p (current_gdbarch)) + *sp = gdbarch_frame_align (current_gdbarch, *sp - len); + else + *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; + if (gdbarch_frame_align_p (current_gdbarch)) + *sp = gdbarch_frame_align (current_gdbarch, *sp + len); + else + *sp += 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) + + value_offset (arg1) + + value_embedded_offset (arg1))); + + /* This may be a pointer to a base subobject; so remember the + full derived object's type ... */ + arg2 = value_change_enclosing_type (arg2, lookup_pointer_type (value_enclosing_type (arg1))); + /* ... and also the relative position of the subobject in the full object */ + set_value_pointed_to_offset (arg2, value_embedded_offset (arg1)); + return arg2; + } + /* Given a value of a pointer type, apply the C unary * operator to it. */ struct value * Regards - Wu Zhou