From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11361 invoked by alias); 3 Oct 2012 17:03:21 -0000 Received: (qmail 11341 invoked by uid 22791); 3 Oct 2012 17:03:19 -0000 X-SWARE-Spam-Status: No, hits=-3.8 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,KHOP_RCVD_TRUST,KHOP_THREADED,RCVD_IN_DNSWL_LOW,RCVD_IN_HOSTKARMA_YE,TW_XF X-Spam-Check-By: sourceware.org Received: from mail-vb0-f41.google.com (HELO mail-vb0-f41.google.com) (209.85.212.41) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 03 Oct 2012 17:03:13 +0000 Received: by vbkv13 with SMTP id v13so9224931vbk.0 for ; Wed, 03 Oct 2012 10:03:12 -0700 (PDT) MIME-Version: 1.0 Received: by 10.52.31.101 with SMTP id z5mr1211906vdh.57.1349283792375; Wed, 03 Oct 2012 10:03:12 -0700 (PDT) Received: by 10.58.146.138 with HTTP; Wed, 3 Oct 2012 10:03:12 -0700 (PDT) In-Reply-To: References: <201210031543.q93FhTPo021324@glazunov.sibelius.xs4all.nl> Date: Wed, 03 Oct 2012 17:03:00 -0000 Message-ID: Subject: Re: PING: PATCH: PR backtrace/14646: [x32] backtrace doesn't work From: "H.J. Lu" To: Mark Kettenis Cc: gdb-patches@sourceware.org Content-Type: text/plain; charset=ISO-8859-1 X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-10/txt/msg00041.txt.bz2 On Wed, Oct 3, 2012 at 8:59 AM, H.J. Lu wrote: > On Wed, Oct 3, 2012 at 8:43 AM, Mark Kettenis wrote: >>> Date: Wed, 3 Oct 2012 08:26:34 -0700 >>> From: "H.J. Lu" >>> >>> On Sun, Sep 30, 2012 at 2:40 PM, H.J. Lu 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 >>> > >>> > 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 * 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")); }