From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 2754 invoked by alias); 5 Apr 2006 04:55:43 -0000 Received: (qmail 2744 invoked by uid 22791); 5 Apr 2006 04:55:42 -0000 X-Spam-Check-By: sourceware.org Received: from dsl027-180-168.sfo1.dsl.speakeasy.net (HELO sunset.davemloft.net) (216.27.180.168) by sourceware.org (qpsmtpd/0.31) with ESMTP; Wed, 05 Apr 2006 04:55:40 +0000 Received: from localhost ([127.0.0.1] ident=davem) by sunset.davemloft.net with esmtp (Exim 4.60) (envelope-from ) id 1FR031-0000RA-AV for gdb-patches@sources.redhat.com; Tue, 04 Apr 2006 21:55:15 -0700 Date: Wed, 05 Apr 2006 04:55:00 -0000 Message-Id: <20060404.215502.57443255.davem@davemloft.net> To: gdb-patches@sources.redhat.com Subject: [PATCH]: Handle sparc skipping unimp instruction with dwarf2 From: "David S. Miller" Mime-Version: 1.0 Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes 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/msg00050.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. 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. Sparc64 doesn't have this funny convention so all of this is not relevant there. I tested using the dwarf2 unwinder for sparc32 Linux/Sparc and there are no regressions, and using dwarf2 in fact fixes a few of the remaining threading testcase failures (there are still some more to tackle alas :). Comments? 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; } }