From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 23779 invoked by alias); 5 Apr 2006 09:30:51 -0000 Received: (qmail 23769 invoked by uid 22791); 5 Apr 2006 09:30:50 -0000 X-Spam-Check-By: sourceware.org Received: from smtp-vbr15.xs4all.nl (HELO smtp-vbr15.xs4all.nl) (194.109.24.35) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 05 Apr 2006 09:30:41 +0000 Received: from webmail.xs4all.nl (dovemail5.xs4all.nl [194.109.26.7]) by smtp-vbr15.xs4all.nl (8.13.6/8.13.6) with ESMTP id k359U3Ns092823; Wed, 5 Apr 2006 11:30:07 +0200 (CEST) (envelope-from mark.kettenis@xs4all.nl) Received: from 192.87.1.22 (SquirrelMail authenticated user sibelius) by webmail.xs4all.nl with HTTP; Wed, 5 Apr 2006 11:30:07 +0200 (CEST) Message-ID: <4459.192.87.1.22.1144229407.squirrel@webmail.xs4all.nl> In-Reply-To: <20060404.215502.57443255.davem@davemloft.net> References: <20060404.215502.57443255.davem@davemloft.net> Date: Wed, 05 Apr 2006 09:30:00 -0000 Subject: Re: [PATCH]: Handle sparc skipping unimp instruction with dwarf2 From: "Mark Kettenis" To: "David S. Miller" Cc: gdb-patches@sources.redhat.com User-Agent: SquirrelMail/1.4.5 MIME-Version: 1.0 Content-Type: text/plain;charset=iso-8859-1 Content-Transfer-Encoding: 8bit Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2006-04/txt/msg00053.txt.bz2 > > This is a followon to my previous posting entitled: > > [PATCH]: Setup sparc32 to support dwarf2 unwind sniffer > > and this patch is relative to that one. > > If you actually enable the dwarf2 unwind sniffer on sparc 32-bit > you'll hit a bunch of regressions in gdb.base/struct.exp, and > the reason is simple. The dwarf2 unwinder doesn't know about the > convention where we should skip the caller's unimp instruction > when returning from a function that returns a structure. Oh, it's coming back to me now. That was another reason why I didn't bother with the dwarf2 unwinder on 32-bit sparc yet. Guess you don't want to enable the dwarf2 unwinder for 32-bit Linux just yet ;-). > This is very easy to fix with just a little bit of infrastructure > adjustments. What we do is we pass in the fs->pc to the dwarf2 reg > init function. We use this PC to find out if the function we are > analyzing returns a struct or not. If so, we adjust the PC and NPC > by 4. Rather than passing the PC, I think you should actually pass down NEXT_FRAME. Other targets might have different requirements, and you can unwind the PC from NEXT_FRAME in the sparc code. Oh, and could you rename sparc32_dwarf2_struct_return_p() to sparc32_struct_return_p() and make sparc32_frame_cache() use that function too? The check isn't really dwarf2-specific and duplication of code is bad! Thanks, Mark > 2006-04-04 David S. Miller > > * dwarf2-frame.c (dwarf2_frame_ops init_reg): Add CORE_ADDR "pc" > argument. > (dwarf2_frame_default_init_reg): Likewise. > (dwarf2_frame_set_init_reg): Update init_reg arg. > (dwarf2_frame_init_reg): Take "pc" and pass it to ops->init_reg(). > (dwarf2_frame_cache): Pass fs->pc to dwarf2_frame_init_reg. > * dwarf2-frame.h (dwarf2-frame_set_init_reg): Update declaration. > * cris-tdep.c (cris_dwarf2_frame_init_reg): Add "pc" argument. > * s390-tdep.c (s390_dwarf2_frame_init_reg): Likewise. > * sh-tdep.c (sh_dwarf2_frame_init_reg): Likewise. > * sparc64-tdep.c (sparc64_dwarf2_frame_init_reg): Likewise. > * sparc-tdep.c (sparc_dwarf2_frame_init_reg): Likewise, and use > it to determine if the function returns a structure and thus we > have to indicate the return PC and NPC are 4 bytes later than > usual. > > --- dwarf2-frame.h.~1~ 2006-02-25 15:04:58.000000000 -0800 > +++ dwarf2-frame.h 2006-04-04 21:35:50.000000000 -0700 > @@ -79,7 +79,8 @@ struct dwarf2_frame_state_reg > > extern void dwarf2_frame_set_init_reg (struct gdbarch *gdbarch, > void (*init_reg) (struct gdbarch *, int, > - struct dwarf2_frame_state_reg *)); > + struct dwarf2_frame_state_reg *, > + CORE_ADDR)); > > /* Set the architecture-specific signal trampoline recognition > function for GDBARCH to SIGNAL_FRAME_P. */ > --- dwarf2-frame.c.~1~ 2006-02-25 15:04:58.000000000 -0800 > +++ dwarf2-frame.c 2006-04-04 21:36:40.000000000 -0700 > @@ -506,7 +506,8 @@ static struct gdbarch_data *dwarf2_frame > struct dwarf2_frame_ops > { > /* Pre-initialize the register state REG for register REGNUM. */ > - void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg > *); > + void (*init_reg) (struct gdbarch *, int, struct dwarf2_frame_state_reg > *, > + CORE_ADDR); > > /* Check whether the frame preceding NEXT_FRAME will be a signal > trampoline. */ > @@ -518,7 +519,8 @@ struct dwarf2_frame_ops > > static void > dwarf2_frame_default_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > /* If we have a register that acts as a program counter, mark it as > a destination for the return address. If we have a register that > @@ -570,7 +572,8 @@ dwarf2_frame_init (struct obstack *obsta > void > dwarf2_frame_set_init_reg (struct gdbarch *gdbarch, > void (*init_reg) (struct gdbarch *, int, > - struct dwarf2_frame_state_reg *)) > + struct dwarf2_frame_state_reg *, > + CORE_ADDR)) > { > struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, > dwarf2_frame_data); > > @@ -581,11 +584,12 @@ dwarf2_frame_set_init_reg (struct gdbarc > > static void > dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > struct dwarf2_frame_ops *ops = gdbarch_data (gdbarch, > dwarf2_frame_data); > > - ops->init_reg (gdbarch, regnum, reg); > + ops->init_reg (gdbarch, regnum, reg, pc); > } > > /* Set the architecture-specific signal trampoline recognition > @@ -713,7 +717,7 @@ dwarf2_frame_cache (struct frame_info *n > int regnum; > > for (regnum = 0; regnum < num_regs; regnum++) > - dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[regnum]); > + dwarf2_frame_init_reg (gdbarch, regnum, &cache->reg[regnum], > fs->pc); > } > > /* Go through the DWARF2 CFI generated table and save its register > --- cris-tdep.c.~1~ 2006-02-25 15:04:58.000000000 -0800 > +++ cris-tdep.c 2006-04-04 21:36:50.000000000 -0700 > @@ -1852,7 +1852,8 @@ cris_dwarf2_reg_to_regnum (int reg) > > static void > cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > /* The return address column. */ > if (regnum == PC_REGNUM) > --- s390-tdep.c.~1~ 2006-02-25 15:05:02.000000000 -0800 > +++ s390-tdep.c 2006-04-04 21:36:56.000000000 -0700 > @@ -2279,7 +2279,8 @@ s390_unwind_sp (struct gdbarch *gdbarch, > > static void > s390_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); > > --- sh-tdep.c.~1~ 2006-04-04 14:52:27.000000000 -0700 > +++ sh-tdep.c 2006-04-04 21:37:07.000000000 -0700 > @@ -2123,7 +2123,8 @@ sh_sh2a_register_sim_regno (int nr) > > static void > sh_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > /* Mark the PC as the destination for the return address. */ > if (regnum == PC_REGNUM) > --- sparc64-tdep.c.~1~ 2006-02-25 15:05:03.000000000 -0800 > +++ sparc64-tdep.c 2006-04-04 21:37:16.000000000 -0700 > @@ -1106,7 +1106,8 @@ sparc64_return_value (struct gdbarch *gd > > static void > sparc64_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > switch (regnum) > { > --- sparc-tdep.c.~2~ 2006-04-04 20:19:46.000000000 -0700 > +++ sparc-tdep.c 2006-04-04 21:35:29.000000000 -0700 > @@ -995,9 +995,33 @@ > || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)); > } > > +static int > +sparc32_dwarf2_struct_return_p (CORE_ADDR pc) > +{ > + struct symbol *sym; > + > + sym = find_pc_function (pc); > + if (sym) > + { > + struct type *type = check_typedef (SYMBOL_TYPE (sym)); > + enum type_code code = TYPE_CODE (type); > + > + if (code == TYPE_CODE_FUNC || code == TYPE_CODE_METHOD) > + { > + type = check_typedef (TYPE_TARGET_TYPE (type)); > + if (sparc_structure_or_union_p (type) > + || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) > + return 1; > + } > + } > + > + return 0; > +} > + > static void > sparc32_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum, > - struct dwarf2_frame_state_reg *reg) > + struct dwarf2_frame_state_reg *reg, > + CORE_ADDR pc) > { > switch (regnum) > { > @@ -1012,11 +1036,11 @@ > break; > case SPARC32_PC_REGNUM: > reg->how = DWARF2_FRAME_REG_RA_OFFSET; > - reg->loc.offset = 8; > + reg->loc.offset = (sparc32_dwarf2_struct_return_p (pc) ? 12 : 8); > break; > case SPARC32_NPC_REGNUM: > reg->how = DWARF2_FRAME_REG_RA_OFFSET; > - reg->loc.offset = 12; > + reg->loc.offset = (sparc32_dwarf2_struct_return_p (pc) ? 16 : 12); > break; > } > } >