From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 16409 invoked by alias); 25 Dec 2010 14:22:07 -0000 Received: (qmail 16399 invoked by uid 22791); 25 Dec 2010 14:22:03 -0000 X-SWARE-Spam-Status: No, hits=-0.8 required=5.0 tests=AWL,BAYES_20,TW_BL,TW_CB,TW_EG,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 25 Dec 2010 14:21:55 +0000 Received: (qmail 21091 invoked from network); 25 Dec 2010 14:21:49 -0000 Received: from unknown (HELO ?192.168.0.101?) (yao@127.0.0.2) by mail.codesourcery.com with ESMTPA; 25 Dec 2010 14:21:49 -0000 Message-ID: <4D15FDF6.4070606@codesourcery.com> Date: Sat, 25 Dec 2010 17:54:00 -0000 From: Yao Qi User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.13) Gecko/20101208 Thunderbird/3.1.7 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: Re: [patch 3/3] Displaced stepping for 16-bit Thumb instructions References: <4D15F9B8.5070705@codesourcery.com> In-Reply-To: <4D15F9B8.5070705@codesourcery.com> Content-Type: multipart/mixed; boundary="------------030908000004030309050709" 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: 2010-12/txt/msg00462.txt.bz2 This is a multi-part message in MIME format. --------------030908000004030309050709 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Content-length: 290 Patch 3 is about supporting 16-bit Thumb displaced stepping. In this patch, we decode 16-bit instruction, and process them. We also leave a slot for 32-bit Thumb instructions, and put an error there. Test cases are updated accordingly for some PC-related instructions. -- Yao (齐尧) --------------030908000004030309050709 Content-Type: text/x-patch; name="arm_disp_step_thumb_16bit.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="arm_disp_step_thumb_16bit.patch" Content-length: 28664 gdb/ 2010-12-25 Yao Qi Displaced stepping support for 16-bit Thumb insns. * gdb/arm-tdep.c (THUMB_NOP): New macro. (displaced_read_reg): Support Thumb mode. (thumb_copy_unmodified_16bit): New. (cleanup_branch): Move some code to ... (cleanup_branch_1): ... here. New. Support Thumb mode. (cleanup_cbz_cbnz): New. (copy_b_bl_blx): Move some code to ... (arm_copy_b_bl_blx): ... here. New. (thumb_copy_b): New. (copy_bx_blx_reg): Move some code to ... (arm_copy_bx_blx_reg): ... here. New. (thumb_copy_bx_blx_reg): New. (decode_unconditional): Update caller. (decode_miscellaneous): Likewise. (decode_b_bl_ldmstm): Likewise. (copy_ldr_str_ldrb_strb): Replace magic number with macro. (thumb_decode_dp): New. (thumb_decode_pc_relative): New. (thumb_copy_16bit_ldr_literal): New. (thumb_copy_cbnz_cbz): New. (thumb_process_displaced_16bit_insn): New. (thumb_process_displaced_32bit_insn): New. gdb/testsuite/ 2010-12-25 Yao Qi * gdb.arch/arm-disp-step.S: Test cbnz/cbz, adr and ldr. * gdb.arch/arm-disp-step.exp: Likewise. diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 93c4e50..4d766c9 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -4326,6 +4326,9 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) /* NOP instruction (mov r0, r0). */ #define ARM_NOP 0xe1a00000 +#define THUMB_NOP 0x4600 + +static int displaced_in_arm_mode (struct regcache *regs); /* Helper for register reads for displaced stepping. In particular, this returns the PC as it would be seen by the instruction at its original @@ -4338,10 +4341,15 @@ displaced_read_reg (struct regcache *regs, CORE_ADDR from, int regno) if (regno == 15) { + if (displaced_in_arm_mode (regs)) + from += 8; + else + from += 6; + if (debug_displaced) fprintf_unfiltered (gdb_stdlog, "displaced: read pc value %.8lx\n", - (unsigned long) from + 8); - return (ULONGEST) from + 8; /* Pipeline offset. */ + (unsigned long) from); + return (ULONGEST) from; /* Pipeline offset. */ } else { @@ -4530,6 +4538,21 @@ copy_unmodified (struct gdbarch *gdbarch, uint32_t insn, return 0; } +static int +thumb_copy_unmodified_16bit (struct gdbarch *gdbarch, unsigned int insn, + const char *iname, + struct displaced_step_closure *dsc) +{ + if (debug_displaced) + fprintf_unfiltered (gdb_stdlog, "displaced: copying insn %.4x, " + "opcode/class '%s' unmodified\n", insn, + iname); + + RECORD_MOD_16BIT_INSN (0, insn); + + return 0; +} + /* Preload instructions with immediate offset. */ static void @@ -4668,16 +4691,11 @@ copy_copro_load_store (struct gdbarch *gdbarch, uint32_t insn, return 0; } -/* Clean up branch instructions (actually perform the branch, by setting - PC). */ - static void -cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs, - struct displaced_step_closure *dsc) +cleanup_branch_1 (struct gdbarch *gdbarch, struct regcache *regs, + struct displaced_step_closure *dsc, unsigned int branch_taken) { ULONGEST from = dsc->insn_addr; - uint32_t status = displaced_read_reg (regs, from, ARM_PS_REGNUM); - int branch_taken = condition_true (dsc->u.branch.cond, status); enum pc_write_style write_pc = dsc->u.branch.exchange ? BX_WRITE_PC : BRANCH_WRITE_PC; @@ -4687,29 +4705,45 @@ cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs, if (dsc->u.branch.link) { ULONGEST pc = displaced_read_reg (regs, from, ARM_PC_REGNUM); - displaced_write_reg (regs, dsc, ARM_LR_REGNUM, pc - 4, CANNOT_WRITE_PC); + + if (displaced_in_arm_mode (regs)) + displaced_write_reg (regs, dsc, ARM_LR_REGNUM, pc - 4, CANNOT_WRITE_PC); + else + displaced_write_reg (regs, dsc, ARM_LR_REGNUM, (pc - 2) | 1u, + CANNOT_WRITE_PC); } displaced_write_reg (regs, dsc, ARM_PC_REGNUM, dsc->u.branch.dest, write_pc); } +/* Clean up branch instructions (actually perform the branch, by setting + PC). */ +static void +cleanup_branch(struct gdbarch *gdbarch, struct regcache *regs, + struct displaced_step_closure *dsc) +{ + ULONGEST from = dsc->insn_addr; + uint32_t status = displaced_read_reg (regs, from, ARM_PS_REGNUM); + int branch_taken = condition_true (dsc->u.branch.cond, status); + + cleanup_branch_1 (gdbarch, regs, dsc, branch_taken); +} + +static void +cleanup_cbz_cbnz(struct gdbarch *gdbarch, struct regcache *regs, + struct displaced_step_closure *dsc) +{ + cleanup_branch_1 (gdbarch, regs, dsc, dsc->u.branch.cond); +} + /* Copy B/BL/BLX instructions with immediate destinations. */ static int -copy_b_bl_blx (struct gdbarch *gdbarch, uint32_t insn, - struct regcache *regs, struct displaced_step_closure *dsc) +copy_b_bl_blx (struct gdbarch *gdbarch, unsigned int cond, int exchange, + int link, long offset, struct regcache *regs, + struct displaced_step_closure *dsc) { - unsigned int cond = bits (insn, 28, 31); - int exchange = (cond == 0xf); - int link = exchange || bit (insn, 24); CORE_ADDR from = dsc->insn_addr; - long offset; - - if (debug_displaced) - fprintf_unfiltered (gdb_stdlog, "displaced: copying %s immediate insn " - "%.8lx\n", (exchange) ? "blx" : (link) ? "bl" : "b", - (unsigned long) insn); - /* Implement "BL