From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18121 invoked by alias); 7 Mar 2007 04:16:30 -0000 Received: (qmail 18109 invoked by uid 22791); 7 Mar 2007 04:16:29 -0000 X-Spam-Check-By: sourceware.org Received: from nile.gnat.com (HELO nile.gnat.com) (205.232.38.5) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 07 Mar 2007 04:16:24 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-nile.gnat.com (Postfix) with ESMTP id 0605748CBFC for ; Tue, 6 Mar 2007 23:16:23 -0500 (EST) Received: from nile.gnat.com ([127.0.0.1]) by localhost (nile.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id 25184-01-5 for ; Tue, 6 Mar 2007 23:16:22 -0500 (EST) Received: from takamaka.act-europe.fr (unknown [70.71.0.212]) by nile.gnat.com (Postfix) with ESMTP id 88A5F48CE64 for ; Tue, 6 Mar 2007 23:16:22 -0500 (EST) Received: by takamaka.act-europe.fr (Postfix, from userid 1000) id DFEE5E7B38; Tue, 6 Mar 2007 20:16:43 -0800 (PST) Date: Wed, 07 Mar 2007 04:16:00 -0000 From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [RFA/mips(commit?)] Unwinding from noreturn function Message-ID: <20070307041643.GJ25742@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="/9DWx/yDrRhgMJTb" Content-Disposition: inline User-Agent: Mutt/1.4.2.2i Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-03/txt/msg00066.txt.bz2 --/9DWx/yDrRhgMJTb Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 3916 Hello, I'm starting to work on bringing mips-irix back to life. One of the issues I've noticed is that unwinding is generally broken, particularly from noreturn functions. I normally have commit priviledges for mips, but in this case I wouldn't mind an extra opinion on the first issue I found. Since I don't have access to a mips16 machine, I can't test the change there... Consider the following example: procedure A is begin raise Constraint_Error; end A; Compile it with the following command: % gnatmake -g a Then try the following: % gdb a (gdb) start (gdb) b __gnat_debug_raise_exception Breakpoint 2 at 0x9947160: file s-except.adb, line 44. (gdb) cont Continuing. Breakpoint 2, <__gnat_debug_raise_exception> (e=0x9a33168) [...] (gdb) bt #0 <__gnat_debug_raise_exception> (e=0x9a33168) at s-except.adb:44 #1 0x097b82e8 in <__gnat_raise_nodefer_with_msg> (e=0x9a33168) at a-except.adb:830 #2 0x097b82e8 in <__gnat_raise_nodefer_with_msg> (e=0x9a33168) at a-except.adb:830 Backtrace stopped: previous frame identical to this frame (corrupt stack?) I actually found two issues: 1. One major: mips_pc_is_mips16 that returns non-zero if bit 0 of the address it is given is set. /* If bit 0 of the address is set, assume this is a MIPS16 address. */ if (is_mips16_addr (memaddr)) return 1; However, this doesn't work very well in our case, especially in this situation: static const struct frame_unwind * mips_insn16_frame_sniffer (struct frame_info *next_frame) { CORE_ADDR pc = frame_unwind_address_in_block (next_frame, NORMAL_FRAME); if (mips_pc_is_mips16 (pc)) return &mips_insn16_frame_unwind; return NULL; } In this case, frame_unwind_address_in_block will return the frame return address *minus one*, thus accidently triggering the check above. As a consequence, we ended up using the mips16 unwinder instead of the mips32 one. It seems to me that the above check is only an optimization, and I've spotted at least one instance where I cannot see an obvious guaranty that the address has not been decremented by one of the _in_block functions... So the decision I made was to remove that check. 2. One minor: There was a confusion in the unwinder between the return address and the address of the instruction calling us. So I replaced frame_pc_unwind calls by their associated frame_unwind_address_in_block. With the two fixes above, I managed to get the full backtrace: (gdb) bt #0 <__gnat_debug_raise_exception> (e=0x9a33168) at s-except.adb:44 #1 0x097b82e8 in <__gnat_raise_nodefer_with_msg> (e=0x9a33168) at a-except.adb:830 #2 0x097b8990 in ada.exceptions.raise_with_location_and_msg ( e=0x9a33168, f=(system.address) 0xf, l=1717986919, m=(system.address) 0x31) at a-except.adb:995 #3 0x097b82a0 in <__gnat_raise_constraint_error_msg> ( file=(system.address) 0x9a33168, line=161761434, msg=(system.address) 0x31) at a-except.adb:795 #4 0x097b8b58 in <__gnat_rcheck_04> ( file=(system.address) 0x9a3b240, line=15) at a-except.adb:1043 #5 0x100027f0 in a () at a.adb:3 2007-03-07 Joel Brobecker * mips-tdep.c (mips_pc_is_mips16): Remove check for bit zero of the given address. (mips_insn16_frame_cache): Use the proper function to get the address of the caller instruction. (mips_insn32_frame_cache): Likewise. Tested on mips-irix. Fixes many many many tests (about 500 or so). OK to apply? Thanks, -- Joel --/9DWx/yDrRhgMJTb Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="mips16.diff" Content-length: 1382 Index: mips-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/mips-tdep.c,v retrieving revision 1.404 diff -u -p -r1.404 mips-tdep.c --- mips-tdep.c 27 Feb 2007 20:17:19 -0000 1.404 +++ mips-tdep.c 7 Mar 2007 04:02:06 -0000 @@ -808,10 +808,6 @@ mips_pc_is_mips16 (CORE_ADDR memaddr) { struct minimal_symbol *sym; - /* If bit 0 of the address is set, assume this is a MIPS16 address. */ - if (is_mips16_addr (memaddr)) - return 1; - /* A flag indicating that this is a MIPS16 function is stored by elfread.c in the high bit of the info field. Use this to decide if the function is MIPS16 or normal MIPS. */ @@ -1640,7 +1636,8 @@ mips_insn16_frame_cache (struct frame_in /* Analyze the function prologue. */ { - const CORE_ADDR pc = frame_pc_unwind (next_frame); + const CORE_ADDR pc = + frame_unwind_address_in_block (next_frame, NORMAL_FRAME); CORE_ADDR start_addr; find_pc_partial_function (pc, NULL, &start_addr, NULL); @@ -1961,7 +1958,8 @@ mips_insn32_frame_cache (struct frame_in /* Analyze the function prologue. */ { - const CORE_ADDR pc = frame_pc_unwind (next_frame); + const CORE_ADDR pc = + frame_unwind_address_in_block (next_frame, NORMAL_FRAME); CORE_ADDR start_addr; find_pc_partial_function (pc, NULL, &start_addr, NULL); --/9DWx/yDrRhgMJTb--