From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 30637 invoked by alias); 7 Mar 2005 21:03:52 -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 30591 invoked from network); 7 Mar 2005 21:03:46 -0000 Received: from unknown (HELO sibelius.xs4all.nl) (82.92.89.47) by sourceware.org with SMTP; 7 Mar 2005 21:03:46 -0000 Received: from elgar.sibelius.xs4all.nl (elgar.sibelius.xs4all.nl [192.168.0.2]) by sibelius.xs4all.nl (8.13.0/8.13.0) with ESMTP id j27L3jeS003788 for ; Mon, 7 Mar 2005 22:03:45 +0100 (CET) Received: from elgar.sibelius.xs4all.nl (localhost [127.0.0.1]) by elgar.sibelius.xs4all.nl (8.12.6p3/8.12.6) with ESMTP id j27L3i7H004354 for ; Mon, 7 Mar 2005 22:03:44 +0100 (CET) (envelope-from kettenis@elgar.sibelius.xs4all.nl) Received: (from kettenis@localhost) by elgar.sibelius.xs4all.nl (8.12.6p3/8.12.6/Submit) id j27L3i4x004351; Mon, 7 Mar 2005 22:03:44 +0100 (CET) Date: Mon, 07 Mar 2005 21:03:00 -0000 Message-Id: <200503072103.j27L3i4x004351@elgar.sibelius.xs4all.nl> From: Mark Kettenis To: gdb-patches@sources.redhat.com Subject: [RFC] DWARF2 unwinder on SPARC X-SW-Source: 2005-03/txt/msg00095.txt.bz2 I'm working on enabling the DWARF2 unwinder on 32-bit and 64-bit SPARC. It's basically working for me on FreeBSD/sparc64, but there are two issues that I'd like some opinions about. 1. I'll need to handle DW_CFA_GNU_window_save. I suppose its interpretation will be really machine specific, but it really only makes sense for register window architectures. And I can only think of a single example of such an architecture that's still around. Now the problem I'm facing is the choice between two evils: a. Contaminate dwarf2-frame.c with a bit of target-specific code. b. Contaminate dwarf2-frame.c with another architecture-specific operation that will only be used for SPARC. Can someone make a choice for me ;-) 2. We need a mechanism for return addresses that are not quite the contents of a register or memory slot. On SPARC, the address of the call instruction is stored in a register instead of the address where we should return to. So the proper way to unwind the pc is to take this register and add 8 to it. There's also npc, which should be calculated in a similar way by adding 12. We'll need something similar for PA-RISC and m88k will need it too if it ever gains a dwarf2 unwinder. There might be more architectures out there that need this. My proposal is to change the definition of DWARF2_FRAME_REG_RA such that the offset member of `struct dwarf2_frame_state_reg' can be used to specify the amount to add to the value yielded by the return address column. This is compatible with the existing use since currently that offset member is initialized to zero. As an alternative, we can add a new constant DWARF2_FRAME_REG_RA_OFFSET for this usage. Attached is my preliminary patch that implements this stuff. Mark Index: dwarf2-frame.c =================================================================== RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v retrieving revision 1.48 diff -u -p -r1.48 dwarf2-frame.c --- dwarf2-frame.c 11 Feb 2005 18:13:49 -0000 1.48 +++ dwarf2-frame.c 7 Mar 2005 21:03:14 -0000 @@ -445,6 +445,20 @@ bad CFI data; mismatched DW_CFA_restore_ /* cfa_how deliberately not set. */ break; + case DW_CFA_GNU_window_save: + dwarf2_frame_state_alloc_regs (&fs->regs, 32); + for (reg = 8; reg < 16; reg++) + { + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_REG; + fs->regs.reg[reg].loc.reg = reg + 16; + } + for (reg = 16; reg < 32; reg++) + { + fs->regs.reg[reg].how = DWARF2_FRAME_REG_SAVED_OFFSET; + fs->regs.reg[reg].loc.offset = (reg - 16) * 8; + } + break; + case DW_CFA_GNU_args_size: /* Ignored. */ insn_ptr = read_uleb128 (insn_ptr, insn_end, &utmp); @@ -588,6 +602,9 @@ struct dwarf2_frame_cache /* Saved registers, indexed by GDB register number, not by DWARF register number. */ struct dwarf2_frame_state_reg *reg; + + /* Return address register. */ + struct dwarf2_frame_state_reg retaddr_reg; }; static struct dwarf2_frame_cache * @@ -733,16 +750,29 @@ incomplete CFI data; unspecified registe what GCC does on some targets. It turns out that GCC assumes that the return address can be found in the register corresponding to the return address column. - Incidentally, that's how should treat a return address - column specifying "same value" too. */ + Incidentally, that's how we should treat a return + address column specifying "same value" too. */ if (fs->retaddr_column < fs->regs.num_regs && retaddr_reg->how != DWARF2_FRAME_REG_UNSPECIFIED && retaddr_reg->how != DWARF2_FRAME_REG_SAME_VALUE) - cache->reg[regnum] = *retaddr_reg; + { + if (cache->reg[regnum].loc.offset == 0) + cache->reg[regnum] = *retaddr_reg; + else + cache->retaddr_reg = *retaddr_reg; + } else { - cache->reg[regnum].loc.reg = fs->retaddr_column; - cache->reg[regnum].how = DWARF2_FRAME_REG_SAVED_REG; + if (cache->reg[regnum].loc.offset == 0) + { + cache->reg[regnum].loc.reg = fs->retaddr_column; + cache->reg[regnum].how = DWARF2_FRAME_REG_SAVED_REG; + } + else + { + cache->retaddr_reg.loc.reg = fs->retaddr_column; + cache->retaddr_reg.how = DWARF2_FRAME_REG_SAVED_REG; + } } } } @@ -864,6 +894,21 @@ dwarf2_frame_prev_register (struct frame } break; + case DWARF2_FRAME_REG_RA: + *optimizedp = 0; + *lvalp = not_lval; + *addrp = 0; + *realnump = -1; + if (valuep) + { + CORE_ADDR pc = cache->reg[regnum].loc.offset; + + regnum = DWARF2_REG_TO_REGNUM (cache->retaddr_reg.loc.reg); + pc += frame_unwind_register_unsigned (next_frame, regnum); + store_typed_address (valuep, builtin_type_void_func_ptr, pc); + } + break; + default: internal_error (__FILE__, __LINE__, _("Unknown register rule.")); }