From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 32011 invoked by alias); 23 Nov 2004 05:35:59 -0000 Mailing-List: contact gdb-patches-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sources.redhat.com Received: (qmail 31991 invoked from network); 23 Nov 2004 05:35:51 -0000 Received: from unknown (HELO priv-edtnes40.telusplanet.net) (199.185.220.224) by sourceware.org with SMTP; 23 Nov 2004 05:35:51 -0000 Received: from takamaka.act-europe.fr ([142.179.108.108]) by priv-edtnes40.telusplanet.net (InterMail vM.6.01.03.02 201-2131-111-104-20040324) with ESMTP id <20041123053544.UWJW29567.priv-edtnes40.telusplanet.net@takamaka.act-europe.fr> for ; Mon, 22 Nov 2004 22:35:44 -0700 Received: by takamaka.act-europe.fr (Postfix, from userid 507) id 1CF8647DA0; Mon, 22 Nov 2004 21:35:44 -0800 (PST) Date: Tue, 23 Nov 2004 05:35:00 -0000 From: Joel Brobecker To: gdb-patches@sources.redhat.com Subject: [RFA/sparc] pb doing next over struct-return function Message-ID: <20041123053544.GM1141@adacore.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="ew6BAiZeqk4r7MaW" Content-Disposition: inline User-Agent: Mutt/1.4i X-SW-Source: 2004-11/txt/msg00443.txt.bz2 --ew6BAiZeqk4r7MaW Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 2857 Hello, This is on sparc - solaris 2.8: Consider the following code: with Ada.Text_IO; use Ada.Text_IO; procedure Small is I : Integer := 123; begin Put_Line (Integer'Image(I)); -- line 6 I := I + 1; end Small; Compile it with: % gnatmake -g small And then try to to a next over line 6: % gdb small (gdb) b small.adb:6 (gdb) run Starting program: /[...]/small Breakpoint 1, small () at small.adb:6 6 Put_Line (Integer'Image(I)); (gdb) n 123 Program exited normally. Ooops, the debugger doesn't stop at line 7! Here is why: First of all, Integer'Image is a call to a function which transforms the Integer variable I into a string. The actually name of the function is: system__img_int__image_integer. When GDB does the stepping, it eventually lands inside that function. Finds out that it has stepped inside it by comparing the frame ID of the previous frame against the step_frame_id, and therefore puts a breakpoint at the return address and resumes the execution. Unfortunately, the breakpoint breakpoint location chosen is not correct, it's one instruction too early, and that causes the breakpoint to never be hit. Hence the "Program exited normally". The reason for the incorrect breakpoint location is that GDB does not see that system__img_int__image_integer is a struct-return function. So the address pointed by "saved_pc + 8" is a "unimp" instruction, which of course is never executed unless something is badly wrong. Digging deeper, I found that this address is incorrectly computed because cache->struct_return_p in sparc32_frame_cache() is not set. And the reason for it not being set is that there is no debugging information available for system__img_int__image_integer, because it is part of the GNAT runtime, which is compiled without debugging information. So I made a small change to sparc32_frame_cache() to fallback to a small heuristic that should help determine whether the function is a struct-return or not based on the instruction found at "saved_pc + 8". If it is a "unimp", then for chances are the function won't return there, but one instruction later. And hence, we must have a struct-return function. This fixes the problem above, and does not introduce any regression in the testsuite. 2004-11-22 Joel Brobecker * sparc-tdep.c (is_unimp_insn): New function. (sparc32_frame_cache): For functions where there is no debugging information to help us determine whether it's a struct-return function or not, fallback on checking whether the instruction at the return address is a "unimp" instruction or not. Tested on sparc-solaris. Ok to commit? Thanks, -- Joel --ew6BAiZeqk4r7MaW Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="sparc-tdep.c.diff" Content-length: 1460 Index: sparc-tdep.c =================================================================== RCS file: /cvs/src/src/gdb/sparc-tdep.c,v retrieving revision 1.156 diff -u -p -r1.156 sparc-tdep.c --- sparc-tdep.c 21 Nov 2004 20:11:09 -0000 1.156 +++ sparc-tdep.c 23 Nov 2004 05:01:15 -0000 @@ -640,6 +640,17 @@ sparc_frame_cache (struct frame_info *ne return cache; } +/* Return True if the instruction corresponding to PC is a "unimp" + instruction. */ + +static int +is_unimp_insn (CORE_ADDR pc) +{ + const unsigned long insn = sparc_fetch_instruction (pc); + + return ((insn & 0xc1c00000) == 0); +} + struct sparc_frame_cache * sparc32_frame_cache (struct frame_info *next_frame, void **this_cache) { @@ -665,6 +676,21 @@ sparc32_frame_cache (struct frame_info * cache->struct_return_p = 1; } } + else + { + /* There is no debugging information for this function to + help us determine whether this function returns a struct + or not. So we rely on another heuristic which is to check + the instruction at the return address and see if this is + a "unimp" instruction. If it is, then it is struct-return + function. */ + CORE_ADDR pc; + int regnum = cache->frameless_p ? SPARC_O7_REGNUM : SPARC_I7_REGNUM; + + pc = frame_unwind_register_unsigned (next_frame, regnum) + 8; + if (is_unimp_insn (pc)) + cache->struct_return_p = 1; + } return cache; } --ew6BAiZeqk4r7MaW--