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]

Re: PING: PATCH: PR backtrace/14646: [x32] backtrace doesn't work


On Wed, Oct 3, 2012 at 8:59 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Wed, Oct 3, 2012 at 8:43 AM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote:
>>> Date: Wed, 3 Oct 2012 08:26:34 -0700
>>> From: "H.J. Lu" <hjl.tools@gmail.com>
>>>
>>> On Sun, Sep 30, 2012 at 2:40 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
>>> > Hi,
>>> >
>>> > amd64_x32_init_abi has
>>> >
>>> >   tdep->sp_regnum_from_eax = AMD64_RSP_REGNUM;
>>> >   tdep->pc_regnum_from_eax = AMD64_RIP_REGNUM;
>>> >
>>> > But unwind frame info is based on the real RSP/RIP
>>> > registers.  Pseudo sp/pc registers don't work with
>>> > frame related codes:
>>> >
>>> > [hjl@gnu-tools-1 gdb]$ egrep "pc_regnum|sp_regnum" *fram*.c
>>> > dwarf2-frame.c:  if (regnum == gdbarch_pc_regnum (gdbarch))
>>> > dwarf2-frame.c:  else if (regnum == gdbarch_sp_regnum (gdbarch))
>>> > dwarf2-frame.c:          == gdbarch_sp_regnum (gdbarch)))
>>> > dwarf2-frame-tailcall.c:  if (regnum == gdbarch_pc_regnum
>>> > (this_gdbarch))
>>> > dwarf2-frame-tailcall.c:  else if (cache->prev_sp_p && regnum ==
>>> > gdbarch_sp_regnum (this_gdbarch))
>>> > dwarf2-frame-tailcall.c:      int sp_regnum;
>>> > dwarf2-frame-tailcall.c:      sp_regnum = gdbarch_sp_regnum
>>> > (prev_gdbarch);
>>> > dwarf2-frame-tailcall.c:      if (sp_regnum == -1)
>>> > dwarf2-frame-tailcall.c:      prev_sp = frame_unwind_register_unsigned
>>> > (this_frame, sp_regnum);
>>> > frame.c:      && gdbarch_pc_regnum (gdbarch) >= 0
>>> > frame.c:                      gdbarch_pc_regnum (gdbarch),
>>> > frame.c:                      gdbarch_pc_regnum (gdbarch),
>>> > frame.c:     the gdbarch_sp_regnum register is meaningful.  */
>>> > frame.c:  if (gdbarch_sp_regnum (gdbarch) >= 0)
>>> > frame.c:                    gdbarch_sp_regnum (gdbarch));
>>> > [hjl@gnu-tools-1 gdb]$
>>> >
>>> > It is nice to print
>>> >
>>> > (gdb) p $sp
>>> > $1 = (void *) 0xffffd028
>>> >
>>> > instead of
>>> >
>>> > (gdb) p $sp
>>> > $1 = 4294955048
>>> >
>>> > But it breaks frame unwind.  This patch removes pseudo sp/pc regnum from
>>> > x32.  "p $sp" and "p $pc" will print 64bit integers.  But "p $esp" and
>>> > "p $esp" work fine.  OK for trunk and 4.5 branch?
>>> >
>>> > Thanks.
>>> >
>>> >
>>> > H.J.
>>> > ---
>>> > 2012-09-30  H.J. Lu  <hongjiu.lu@intel.com>
>>> >
>>> >         PR backtrace/14646
>>> >         PR gdb/14647
>>> >         * i386-tdep.h (gdbarch_tdep): Remove sp_regnum_from_eax and
>>> >         pc_regnum_from_eax.
>>> >         * i386-tdep.c (i386_gdbarch_init): Don't use sp_regnum_from_eax
>>> >         nor pc_regnum_from_eax.
>>> >         * amd64-tdep.c (amd64_x32_init_abi): Don't set sp_regnum_from_eax
>>> >         nor pc_regnum_from_eax.
>>> >
>>
>> There's got to be a better way to handle that.  Did you look into
>> using dwarf2_frame_set_init_reg() to establish mappings to the "raw"
>> rip and rsp registers?
>
> It doesn't work for x32 since gdbarch_sp_regnum and
> gdbarch_pc_regnum are used like:
>
>   if (get_frame_func_if_available (this_frame, &entry_pc))
>     {
>       /* Decode the insns in the FDE up to the entry PC.  */
>       instr = execute_cfa_program (fde, fde->instructions, fde->end, gdbarch,
>                                    entry_pc, fs);
>
>       if (fs->regs.cfa_how == CFA_REG_OFFSET
>           && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg)
>               == gdbarch_sp_regnum (gdbarch)))
>         {
>           entry_cfa_sp_offset = fs->regs.cfa_offset;
>           entry_cfa_sp_offset_p = 1;
>         }
>     }
>
> gdbarch_sp_regnum will return the wrong register number.  If there are
> gdbarch_frame_sp_regnum and gdbarch_frame_pc_regnum,  which
> default to gdbarch_sp_regnum and gdbarch_pc_regnum, respectively,
> and use them everywhere, except for "p $pc/$sp", x32 can set up proper
> gdbarch_frame_sp_regnum and gdbarch_frame_pc_regnum.
>

This patch adds frame_sp_regnum and frame_pc_regnum, which
are used for "p $pc"/"p $sp".  I can override them for x32 with

static int
amd64_x32_frame_pc_regnum (struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  return tdep->eax_regnum + AMD64_RIP_REGNUM;
}

static int
amd64_x32_frame_sp_regnum (struct gdbarch *gdbarch)
{
  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  return tdep->eax_regnum + AMD64_RSP_REGNUM;
}

Any comments?

Thanks.

-- 
H.J.
---
2012-10-03  H.J. Lu  <hongjiu.lu@intel.com>

	* frame.h (default_frame_pc_regnum): New prototype.
	(default_frame_sp_regnum): Likewise.
	* gdbarch.sh: Add frame_sp_regnum and frame_pc_regnum.
	* std-regs.c (default_frame_pc_regnum): New function.
	(default_frame_sp_regnum): Likewise.
	(value_of_builtin_frame_pc_reg): Replace gdbarch_pc_regnum
	with gdbarch_frame_pc_regnum.
	(value_of_builtin_frame_sp_reg): Replace gdbarch_sp_regnum
	with gdbarch_frame_sp_regnum.
	* gdbarch.c: Regenerated.
	* gdbarch.h: Likewise.

diff --git a/gdb/frame.h b/gdb/frame.h
index fa80663..750abc9 100644
--- a/gdb/frame.h
+++ b/gdb/frame.h
@@ -787,4 +787,10 @@ extern struct frame_info *create_new_frame
(CORE_ADDR base, CORE_ADDR pc);
 extern int frame_unwinder_is (struct frame_info *fi,
 			      const struct frame_unwind *unwinder);

+/* Return PC regnum for value_of_builtin_frame_pc_reg.  */
+extern int default_frame_pc_regnum (struct gdbarch *gdbarch);
+
+/* Return SP regnum for value_of_builtin_frame_sp_reg.  */
+extern int default_frame_sp_regnum (struct gdbarch *gdbarch);
+
 #endif /* !defined (FRAME_H)  */
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index c20b8ca..6ad6e08 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -449,6 +449,8 @@ M:int:ax_pseudo_register_push_stack:struct
agent_expr *ax, int reg:ax, reg
 # gdbarch_sp_regnum will hopefully be replaced by UNWIND_SP.
 v:int:sp_regnum:::-1:-1::0
 v:int:pc_regnum:::-1:-1::0
+m:int:frame_sp_regnum:void:::default_frame_sp_regnum::0
+m:int:frame_pc_regnum:void:::default_frame_pc_regnum::0
 v:int:ps_regnum:::-1:-1::0
 v:int:fp0_regnum:::0:-1::0
 # Convert stab register number (from \`r\' declaration) to a gdb REGNUM.
diff --git a/gdb/std-regs.c b/gdb/std-regs.c
index c5b97d6..4e47a07 100644
--- a/gdb/std-regs.c
+++ b/gdb/std-regs.c
@@ -26,6 +26,19 @@
 #include "value.h"
 #include "gdb_string.h"

+/* Return PC regnum for value_of_builtin_frame_pc_reg.  */
+int
+default_frame_pc_regnum (struct gdbarch *gdbarch)
+{
+  return gdbarch_pc_regnum (gdbarch);
+}
+
+/* Return SP regnum for value_of_builtin_frame_sp_reg.  */
+int
+default_frame_sp_regnum (struct gdbarch *gdbarch)
+{
+  return gdbarch_sp_regnum (gdbarch);
+}

 static struct value *
 value_of_builtin_frame_fp_reg (struct frame_info *frame, const void *baton)
@@ -58,8 +71,8 @@ value_of_builtin_frame_pc_reg (struct frame_info
*frame, const void *baton)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);

-  if (gdbarch_pc_regnum (gdbarch) >= 0)
-    return value_of_register (gdbarch_pc_regnum (gdbarch), frame);
+  if (gdbarch_frame_pc_regnum (gdbarch) >= 0)
+    return value_of_register (gdbarch_frame_pc_regnum (gdbarch), frame);
   else
     {
       struct type *func_ptr_type = builtin_type (gdbarch)->builtin_func_ptr;
@@ -77,8 +90,8 @@ value_of_builtin_frame_sp_reg (struct frame_info
*frame, const void *baton)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);

-  if (gdbarch_sp_regnum (gdbarch) >= 0)
-    return value_of_register (gdbarch_sp_regnum (gdbarch), frame);
+  if (gdbarch_frame_sp_regnum (gdbarch) >= 0)
+    return value_of_register (gdbarch_frame_sp_regnum (gdbarch), frame);
   error (_("Standard register ``$sp'' is not available for this target"));
 }


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