This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH]: Handle sparc skipping unimp instruction with dwarf2
- From: "Mark Kettenis" <mark dot kettenis at xs4all dot nl>
- To: "David S. Miller" <davem at davemloft dot net>
- Cc: gdb-patches at sources dot redhat dot com
- Date: Wed, 5 Apr 2006 11:30:07 +0200 (CEST)
- Subject: Re: [PATCH]: Handle sparc skipping unimp instruction with dwarf2
- References: <20060404.215502.57443255.davem@davemloft.net>
>
> 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 <davem@sunset.davemloft.net>
>
> * 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;
> }
> }
>