This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH]: Handle sparc skipping unimp instruction with dwarf2


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  <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;
     }
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]