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 10:03 AM, H.J. Lu <hjl.tools@gmail.com> wrote:
> 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.
>

Pseudo registers, like esp, aren't updated during stack unwind:

http://sourceware.org/bugzilla/show_bug.cgi?id=14673


-- 
H.J.


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