* [PATCH 0/3] Bug fixes in arm reverse debugging @ 2016-02-22 16:53 Yao Qi 2016-02-22 16:53 ` [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn Yao Qi ` (3 more replies) 0 siblings, 4 replies; 11+ messages in thread From: Yao Qi @ 2016-02-22 16:53 UTC (permalink / raw) To: gdb-patches This patch series extends test case gdb.reverse/aarch64.exp for general test (it covers aarch64 and arm, and I plan to merge i386 tests to it too) and fix some bugs on instruction decoding exposed the new tests. *** BLURB HERE *** Yao Qi (3): Generalize gdb.reverse/aarch64.exp Record right reg num of thumb special data instructions Fix various bugs in arm_record_exreg_ld_st_insn gdb/arm-tdep.c | 101 +++++++++++------- gdb/testsuite/gdb.reverse/aarch64.c | 99 ----------------- gdb/testsuite/gdb.reverse/aarch64.exp | 115 -------------------- gdb/testsuite/gdb.reverse/insn-reverse.c | 164 +++++++++++++++++++++++++++++ gdb/testsuite/gdb.reverse/insn-reverse.exp | 130 +++++++++++++++++++++++ 5 files changed, 356 insertions(+), 253 deletions(-) delete mode 100644 gdb/testsuite/gdb.reverse/aarch64.c delete mode 100644 gdb/testsuite/gdb.reverse/aarch64.exp create mode 100644 gdb/testsuite/gdb.reverse/insn-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/insn-reverse.exp -- 1.9.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn 2016-02-22 16:53 [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi @ 2016-02-22 16:53 ` Yao Qi 2016-02-23 19:59 ` Luis Machado 2016-02-22 16:53 ` [PATCH 2/3] Record right reg num of thumb special data instructions Yao Qi ` (2 subsequent siblings) 3 siblings, 1 reply; 11+ messages in thread From: Yao Qi @ 2016-02-22 16:53 UTC (permalink / raw) To: gdb-patches This patch fixes various bugs in arm_record_exreg_ld_st_insn, and use gdb.reverse/insn-reverse.c to test more arm instructions. - Set flag SINGLE_REG correctly. In the arch reference manual, SING_REG is true when the bit 8 of instruction is zero. - Record the right D registers for instructions changing S registers. - Fix the order of length and address in record_buf_mem array. - Shift the offset by 2 instead of by 24. This patch also fixes one internal error, (gdb) PASS: gdb.reverse/finish-precsave.exp: BP at end of main continue^M Continuing.^M ../../binutils-gdb/gdb/utils.c:1072: internal-error: virtual memory exhausted.^M A problem internal to GDB has been detected,FAIL: gdb.reverse/finish-precsave.exp: run to end of main (GDB internal error) gdb: 2016-02-22 Yao Qi <yao.qi@linaro.org> * arm-tdep.c (arm_record_exreg_ld_st_insn): Set 'single_reg' per bit 8. Check bit 20 instead of bit 4 for VMOV instruction. Record D registers for instructions changing S registers. Change of the order of length and address in record_buf_mem array. gdb/testsuite: 2016-02-22 Yao Qi <yao.qi@linaro.org> * gdb.reverse/insn-reverse.c [__arm__] (ext_reg_load): New. [__arm__] (ext_reg_mov, ext_reg_push_pop): New. (testcases): Update. --- gdb/arm-tdep.c | 93 ++++++++++++++++++++------------ gdb/testsuite/gdb.reverse/insn-reverse.c | 43 +++++++++++++++ 2 files changed, 101 insertions(+), 35 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 0c0e1a5..5c5524b 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -10909,13 +10909,13 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); opcode = bits (arm_insn_r->arm_insn, 20, 24); - single_reg = bit (arm_insn_r->arm_insn, 8); + single_reg = !bit (arm_insn_r->arm_insn, 8); op_vldm_vstm = opcode & 0x1b; /* Handle VMOV instructions. */ if ((opcode & 0x1e) == 0x04) { - if (bit (arm_insn_r->arm_insn, 4)) + if (bit (arm_insn_r->arm_insn, 20)) /* to_arm_registers bit 20? */ { record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15); record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19); @@ -10923,18 +10923,29 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) } else { - uint8_t reg_m = ((bits (arm_insn_r->arm_insn, 0, 3) << 1) - | bit (arm_insn_r->arm_insn, 5)); + uint8_t reg_m = bits (arm_insn_r->arm_insn, 0, 3); + uint8_t bit_m = bit (arm_insn_r->arm_insn, 5); - if (!single_reg) + if (single_reg) { - record_buf[0] = num_regs + reg_m; - record_buf[1] = num_regs + reg_m + 1; - arm_insn_r->reg_rec_count = 2; + /* The first S register number m is REG_M:M (M is bit 5), + the corresponding D register number is REG_M:M / 2, which + is REG_M. */ + record_buf[arm_insn_r->reg_rec_count++] = ARM_D0_REGNUM + reg_m; + /* The second S register number is REG_M:M + 1, the + corresponding D register number is (REG_M:M + 1) / 2. + IOW, if bit M is 1, the first and second S registers + are mapped to different D registers, otherwise, they are + in the same D register. */ + if (bit_m) + { + record_buf[arm_insn_r->reg_rec_count++] + = ARM_D0_REGNUM + reg_m + 1; + } } else { - record_buf[0] = reg_m + ARM_D0_REGNUM; + record_buf[0] = ((bit_m << 4) + reg_m + ARM_D0_REGNUM); arm_insn_r->reg_rec_count = 1; } } @@ -10949,7 +10960,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; memory_count = imm_off8; if (bit (arm_insn_r->arm_insn, 23)) @@ -10965,19 +10976,19 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) while (memory_count > 0) { - if (!single_reg) + if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; start_address = start_address + 4; memory_index = memory_index + 2; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; start_address = start_address + 8; memory_index = memory_index + 4; } @@ -10991,25 +11002,36 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) { uint32_t reg_count, reg_vd; uint32_t reg_index = 0; + uint32_t bit_d = bit (arm_insn_r->arm_insn, 22); reg_vd = bits (arm_insn_r->arm_insn, 12, 15); reg_count = bits (arm_insn_r->arm_insn, 0, 7); - if (single_reg) - reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4); - else - reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); + /* REG_VD is the first D register number. If the instruction + loads memory to S registers (SINGLE_REG is TRUE), the register + number is (REG_VD << 1 | bit D), so the corresponding D + register number is (REG_VD << 1 | bit D) / 2 = REG_VD. */ + if (!single_reg) + reg_vd = reg_vd | (bit_d << 4); - if (bit (arm_insn_r->arm_insn, 21)) + if (bit (arm_insn_r->arm_insn, 21) /* write back */) record_buf[reg_index++] = bits (arm_insn_r->arm_insn, 16, 19); - while (reg_count > 0) + /* If the instruction loads memory to D register, REG_COUNT should + divide 2, according to the ARM Architecture Reference Manual. + If the instruction loads memory to S register, divide 2 as well + because two S registers are mapped to D register. */ + reg_count = reg_count / 2; + if (single_reg && bit_d) { - if (single_reg) - record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1; - else - record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; + /* Increase the register count if S register list starts from + odd number (bit d is one). */ + reg_count++; + } + while (reg_count > 0) + { + record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; reg_count--; } arm_insn_r->reg_rec_count = reg_index; @@ -11023,7 +11045,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; if (bit (arm_insn_r->arm_insn, 23)) start_address = u_regval + imm_off32; @@ -11032,16 +11054,16 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; arm_insn_r->mem_rec_count = 1; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; arm_insn_r->mem_rec_count = 2; } } @@ -11058,7 +11080,8 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) else { reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); - record_buf[0] = num_regs + reg_vd; + /* Record register D rather than pseudo register S. */ + record_buf[0] = ARM_D0_REGNUM + reg_vd / 2; } arm_insn_r->reg_rec_count = 1; } diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.c b/gdb/testsuite/gdb.reverse/insn-reverse.c index 1bfb8b0..22cd267 100644 --- a/gdb/testsuite/gdb.reverse/insn-reverse.c +++ b/gdb/testsuite/gdb.reverse/insn-reverse.c @@ -88,6 +88,45 @@ adv_simd_vect_shift (void) { asm ("fcvtzs s0, s0, #1"); } +#elif (defined __arm__) +static void +ext_reg_load (void) +{ + char in[8]; + + asm ("vldr d0, [%0]" : : "r" (in)); + asm ("vldr s3, [%0]" : : "r" (in)); + + asm ("vldm %0, {d3-d4}" : : "r" (in)); + asm ("vldm %0, {s9-s11}" : : "r" (in)); +} + +static void +ext_reg_mov (void) +{ + int i, j; + double d; + + i = 1; + j = 2; + + asm ("vmov s4, s5, %0, %1" : "=r" (i), "=r" (j): ); + asm ("vmov s7, s8, %0, %1" : "=r" (i), "=r" (j): ); + asm ("vmov %0, %1, s10, s11" : : "r" (i), "r" (j)); + asm ("vmov %0, %1, s1, s2" : : "r" (i), "r" (j)); + + asm ("vmov %P2, %0, %1" : "=r" (i), "=r" (j): "w" (d)); + asm ("vmov %1, %2, %P0" : "=w" (d) : "r" (i), "r" (j)); +} + +static void +ext_reg_push_pop (void) +{ + double d; + + asm ("vpush {%P0}" : : "w" (d)); + asm ("vpop {%P0}" : : "w" (d)); +} #endif typedef void (*testcase_ftype) (void); @@ -104,6 +143,10 @@ static testcase_ftype testcases[] = adv_simd_scalar_index, adv_simd_smlal, adv_simd_vect_shift, +#elif (defined __arm__) + ext_reg_load, + ext_reg_mov, + ext_reg_push_pop, #endif }; -- 1.9.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn 2016-02-22 16:53 ` [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn Yao Qi @ 2016-02-23 19:59 ` Luis Machado 2016-02-26 14:54 ` Yao Qi 0 siblings, 1 reply; 11+ messages in thread From: Luis Machado @ 2016-02-23 19:59 UTC (permalink / raw) To: Yao Qi, gdb-patches Just internal comment nits. On 02/22/2016 01:53 PM, Yao Qi wrote: > This patch fixes various bugs in arm_record_exreg_ld_st_insn, and use > gdb.reverse/insn-reverse.c to test more arm instructions. > > - Set flag SINGLE_REG correctly. In the arch reference manual, > SING_REG is true when the bit 8 of instruction is zero. > - Record the right D registers for instructions changing S registers. > - Fix the order of length and address in record_buf_mem array. > - Shift the offset by 2 instead of by 24. > > This patch also fixes one internal error, > > (gdb) PASS: gdb.reverse/finish-precsave.exp: BP at end of main > continue^M > Continuing.^M > ../../binutils-gdb/gdb/utils.c:1072: internal-error: virtual memory exhausted.^M > A problem internal to GDB has been detected,FAIL: gdb.reverse/finish-precsave.exp: run to end of main (GDB internal error) > ... > @@ -10991,25 +11002,36 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) > { > uint32_t reg_count, reg_vd; > uint32_t reg_index = 0; > + uint32_t bit_d = bit (arm_insn_r->arm_insn, 22); > > reg_vd = bits (arm_insn_r->arm_insn, 12, 15); > reg_count = bits (arm_insn_r->arm_insn, 0, 7); > > - if (single_reg) > - reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4); > - else > - reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); > + /* REG_VD is the first D register number. If the instruction > + loads memory to S registers (SINGLE_REG is TRUE), the register > + number is (REG_VD << 1 | bit D), so the corresponding D > + register number is (REG_VD << 1 | bit D) / 2 = REG_VD. */ > + if (!single_reg) > + reg_vd = reg_vd | (bit_d << 4); > > - if (bit (arm_insn_r->arm_insn, 21)) > + if (bit (arm_insn_r->arm_insn, 21) /* write back */) > record_buf[reg_index++] = bits (arm_insn_r->arm_insn, 16, 19); > > - while (reg_count > 0) > + /* If the instruction loads memory to D register, REG_COUNT should > + divide 2, according to the ARM Architecture Reference Manual. "...should be divided by 2..."? > + If the instruction loads memory to S register, divide 2 as well "... divide by 2..." > + because two S registers are mapped to D register. */ > + reg_count = reg_count / 2; > + if (single_reg && bit_d) > { > - if (single_reg) > - record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1; > - else > - record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; > + /* Increase the register count if S register list starts from > + odd number (bit d is one). */ "...from an odd number..."? ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn 2016-02-23 19:59 ` Luis Machado @ 2016-02-26 14:54 ` Yao Qi 0 siblings, 0 replies; 11+ messages in thread From: Yao Qi @ 2016-02-26 14:54 UTC (permalink / raw) To: Luis Machado; +Cc: Yao Qi, gdb-patches Luis Machado <lgustavo@codesourcery.com> writes: >> - while (reg_count > 0) >> + /* If the instruction loads memory to D register, REG_COUNT should >> + divide 2, according to the ARM Architecture Reference Manual. > > "...should be divided by 2..."? > >> + If the instruction loads memory to S register, divide 2 as well > > "... divide by 2..." > >> + because two S registers are mapped to D register. */ >> + reg_count = reg_count / 2; >> + if (single_reg && bit_d) >> { >> - if (single_reg) >> - record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1; >> - else >> - record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; >> + /* Increase the register count if S register list starts from >> + odd number (bit d is one). */ > > "...from an odd number..."? Hi Luis, Thanks for the review. I fixed them. -- Yao (齐尧) From 8600280115853d508d82ae47932b3cbb8d4c22ac Mon Sep 17 00:00:00 2001 From: Yao Qi <yao.qi@linaro.org> Date: Tue, 16 Feb 2016 12:59:03 +0000 Subject: [PATCH] Fix various bugs in arm_record_exreg_ld_st_insn This patch fixes various bugs in arm_record_exreg_ld_st_insn, and use gdb.reverse/insn-reverse.c to test more arm instructions. - Set flag SINGLE_REG correctly. In the arch reference manual, SING_REG is true when the bit 8 of instruction is zero. - Record the right D registers for instructions changing S registers. - Fix the order of length and address in record_buf_mem array. - Shift the offset by 2 instead of by 24. This patch also fixes one internal error, (gdb) PASS: gdb.reverse/finish-precsave.exp: BP at end of main continue^M Continuing.^M ../../binutils-gdb/gdb/utils.c:1072: internal-error: virtual memory exhausted.^M A problem internal to GDB has been detected,FAIL: gdb.reverse/finish-precsave.exp: run to end of main (GDB internal error) gdb: 2016-02-26 Yao Qi <yao.qi@linaro.org> * arm-tdep.c (arm_record_exreg_ld_st_insn): Set 'single_reg' per bit 8. Check bit 20 instead of bit 4 for VMOV instruction. Record D registers for instructions changing S registers. Change of the order of length and address in record_buf_mem array. gdb/testsuite: 2016-02-26 Yao Qi <yao.qi@linaro.org> * gdb.reverse/insn-reverse.c [__arm__] (ext_reg_load): New. [__arm__] (ext_reg_mov, ext_reg_push_pop): New. (testcases): Update. diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index bd0ee97..2eb7bb1 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -10909,13 +10909,13 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) const int num_regs = gdbarch_num_regs (arm_insn_r->gdbarch); opcode = bits (arm_insn_r->arm_insn, 20, 24); - single_reg = bit (arm_insn_r->arm_insn, 8); + single_reg = !bit (arm_insn_r->arm_insn, 8); op_vldm_vstm = opcode & 0x1b; /* Handle VMOV instructions. */ if ((opcode & 0x1e) == 0x04) { - if (bit (arm_insn_r->arm_insn, 4)) + if (bit (arm_insn_r->arm_insn, 20)) /* to_arm_registers bit 20? */ { record_buf[0] = bits (arm_insn_r->arm_insn, 12, 15); record_buf[1] = bits (arm_insn_r->arm_insn, 16, 19); @@ -10923,18 +10923,29 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) } else { - uint8_t reg_m = ((bits (arm_insn_r->arm_insn, 0, 3) << 1) - | bit (arm_insn_r->arm_insn, 5)); + uint8_t reg_m = bits (arm_insn_r->arm_insn, 0, 3); + uint8_t bit_m = bit (arm_insn_r->arm_insn, 5); - if (!single_reg) + if (single_reg) { - record_buf[0] = num_regs + reg_m; - record_buf[1] = num_regs + reg_m + 1; - arm_insn_r->reg_rec_count = 2; + /* The first S register number m is REG_M:M (M is bit 5), + the corresponding D register number is REG_M:M / 2, which + is REG_M. */ + record_buf[arm_insn_r->reg_rec_count++] = ARM_D0_REGNUM + reg_m; + /* The second S register number is REG_M:M + 1, the + corresponding D register number is (REG_M:M + 1) / 2. + IOW, if bit M is 1, the first and second S registers + are mapped to different D registers, otherwise, they are + in the same D register. */ + if (bit_m) + { + record_buf[arm_insn_r->reg_rec_count++] + = ARM_D0_REGNUM + reg_m + 1; + } } else { - record_buf[0] = reg_m + ARM_D0_REGNUM; + record_buf[0] = ((bit_m << 4) + reg_m + ARM_D0_REGNUM); arm_insn_r->reg_rec_count = 1; } } @@ -10949,7 +10960,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; memory_count = imm_off8; if (bit (arm_insn_r->arm_insn, 23)) @@ -10965,19 +10976,19 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) while (memory_count > 0) { - if (!single_reg) + if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; start_address = start_address + 4; memory_index = memory_index + 2; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; start_address = start_address + 8; memory_index = memory_index + 4; } @@ -10991,25 +11002,36 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) { uint32_t reg_count, reg_vd; uint32_t reg_index = 0; + uint32_t bit_d = bit (arm_insn_r->arm_insn, 22); reg_vd = bits (arm_insn_r->arm_insn, 12, 15); reg_count = bits (arm_insn_r->arm_insn, 0, 7); - if (single_reg) - reg_vd = reg_vd | (bit (arm_insn_r->arm_insn, 22) << 4); - else - reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); + /* REG_VD is the first D register number. If the instruction + loads memory to S registers (SINGLE_REG is TRUE), the register + number is (REG_VD << 1 | bit D), so the corresponding D + register number is (REG_VD << 1 | bit D) / 2 = REG_VD. */ + if (!single_reg) + reg_vd = reg_vd | (bit_d << 4); - if (bit (arm_insn_r->arm_insn, 21)) + if (bit (arm_insn_r->arm_insn, 21) /* write back */) record_buf[reg_index++] = bits (arm_insn_r->arm_insn, 16, 19); - while (reg_count > 0) + /* If the instruction loads memory to D register, REG_COUNT should + be divided by 2, according to the ARM Architecture Reference + Manual. If the instruction loads memory to S register, divide by + 2 as well because two S registers are mapped to D register. */ + reg_count = reg_count / 2; + if (single_reg && bit_d) { - if (single_reg) - record_buf[reg_index++] = num_regs + reg_vd + reg_count - 1; - else - record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; + /* Increase the register count if S register list starts from + an odd number (bit d is one). */ + reg_count++; + } + while (reg_count > 0) + { + record_buf[reg_index++] = ARM_D0_REGNUM + reg_vd + reg_count - 1; reg_count--; } arm_insn_r->reg_rec_count = reg_index; @@ -11023,7 +11045,7 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) reg_rn = bits (arm_insn_r->arm_insn, 16, 19); regcache_raw_read_unsigned (reg_cache, reg_rn, &u_regval); imm_off8 = bits (arm_insn_r->arm_insn, 0, 7); - imm_off32 = imm_off8 << 24; + imm_off32 = imm_off8 << 2; if (bit (arm_insn_r->arm_insn, 23)) start_address = u_regval + imm_off32; @@ -11032,16 +11054,16 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) if (single_reg) { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; arm_insn_r->mem_rec_count = 1; } else { - record_buf_mem[memory_index] = start_address; - record_buf_mem[memory_index + 1] = 4; - record_buf_mem[memory_index + 2] = start_address + 4; - record_buf_mem[memory_index + 3] = 4; + record_buf_mem[memory_index] = 4; + record_buf_mem[memory_index + 1] = start_address; + record_buf_mem[memory_index + 2] = 4; + record_buf_mem[memory_index + 3] = start_address + 4; arm_insn_r->mem_rec_count = 2; } } @@ -11058,7 +11080,8 @@ arm_record_exreg_ld_st_insn (insn_decode_record *arm_insn_r) else { reg_vd = (reg_vd << 1) | bit (arm_insn_r->arm_insn, 22); - record_buf[0] = num_regs + reg_vd; + /* Record register D rather than pseudo register S. */ + record_buf[0] = ARM_D0_REGNUM + reg_vd / 2; } arm_insn_r->reg_rec_count = 1; } diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.c b/gdb/testsuite/gdb.reverse/insn-reverse.c index 1bfb8b0..22cd267 100644 --- a/gdb/testsuite/gdb.reverse/insn-reverse.c +++ b/gdb/testsuite/gdb.reverse/insn-reverse.c @@ -88,6 +88,45 @@ adv_simd_vect_shift (void) { asm ("fcvtzs s0, s0, #1"); } +#elif (defined __arm__) +static void +ext_reg_load (void) +{ + char in[8]; + + asm ("vldr d0, [%0]" : : "r" (in)); + asm ("vldr s3, [%0]" : : "r" (in)); + + asm ("vldm %0, {d3-d4}" : : "r" (in)); + asm ("vldm %0, {s9-s11}" : : "r" (in)); +} + +static void +ext_reg_mov (void) +{ + int i, j; + double d; + + i = 1; + j = 2; + + asm ("vmov s4, s5, %0, %1" : "=r" (i), "=r" (j): ); + asm ("vmov s7, s8, %0, %1" : "=r" (i), "=r" (j): ); + asm ("vmov %0, %1, s10, s11" : : "r" (i), "r" (j)); + asm ("vmov %0, %1, s1, s2" : : "r" (i), "r" (j)); + + asm ("vmov %P2, %0, %1" : "=r" (i), "=r" (j): "w" (d)); + asm ("vmov %1, %2, %P0" : "=w" (d) : "r" (i), "r" (j)); +} + +static void +ext_reg_push_pop (void) +{ + double d; + + asm ("vpush {%P0}" : : "w" (d)); + asm ("vpop {%P0}" : : "w" (d)); +} #endif typedef void (*testcase_ftype) (void); @@ -104,6 +143,10 @@ static testcase_ftype testcases[] = adv_simd_scalar_index, adv_simd_smlal, adv_simd_vect_shift, +#elif (defined __arm__) + ext_reg_load, + ext_reg_mov, + ext_reg_push_pop, #endif }; ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/3] Record right reg num of thumb special data instructions 2016-02-22 16:53 [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi 2016-02-22 16:53 ` [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn Yao Qi @ 2016-02-22 16:53 ` Yao Qi 2016-02-22 16:53 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Yao Qi 2016-02-26 15:01 ` [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi 3 siblings, 0 replies; 11+ messages in thread From: Yao Qi @ 2016-02-22 16:53 UTC (permalink / raw) To: gdb-patches When GDB decodes these thumb special data instructions, such as 'mov sp, r7' the Rd is got incorrectly. According to the arch reference manual, the Rd is DN:Rdn, in which DN is bit 7 and Rdn is bits 0 to 2. This patch fixes it. gdb: 2016-02-22 Yao Qi <yao.qi@linaro.org> * arm-tdep.c (thumb_record_ld_st_reg_offset): Fix the register number of Rd. --- gdb/arm-tdep.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 1a3a209..0c0e1a5 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -11512,10 +11512,10 @@ thumb_record_ld_st_reg_offset (insn_decode_record *thumb_insn_r) } else { - /* Format 8; special data processing insns. */ - reg_src1 = bits (thumb_insn_r->arm_insn, 0, 2); - record_buf[0] = ARM_PS_REGNUM; - record_buf[1] = reg_src1; + /* Format 8; special data processing insns. */ + record_buf[0] = ARM_PS_REGNUM; + record_buf[1] = (bit (thumb_insn_r->arm_insn, 7) << 3 + | bits (thumb_insn_r->arm_insn, 0, 2)); thumb_insn_r->reg_rec_count = 2; } } -- 1.9.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/3] Generalize gdb.reverse/aarch64.exp 2016-02-22 16:53 [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi 2016-02-22 16:53 ` [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn Yao Qi 2016-02-22 16:53 ` [PATCH 2/3] Record right reg num of thumb special data instructions Yao Qi @ 2016-02-22 16:53 ` Yao Qi 2016-02-24 11:22 ` Pedro Alves 2016-02-26 15:01 ` [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi 3 siblings, 1 reply; 11+ messages in thread From: Yao Qi @ 2016-02-22 16:53 UTC (permalink / raw) To: gdb-patches I said we can generialize gdb.reverse/aarch64.exp for other architectures https://sourceware.org/ml/gdb-patches/2015-05/msg00482.html and here is the patch to change aarch64.exp to insn-reverse.exp. gdb/testsuite: 2016-02-22 Yao Qi <yao.qi@linaro.org> * gdb.reverse/aarch64.c: Rename it ... * gdb.reverse/insn-reverse.c: to ... [__aarch64__] Include arm_neon.h. (testcase_ftype): New. (testcases): New array. (n_testcases): New. (main): Call each element in testcases. * gdb.reverse/aarch64.exp: Rename it ... * gdb.reverse/insn-reverse.exp: to ... Remove is_aarch64_target check. (read_testcase): New. Do the tests in a loop. --- gdb/testsuite/gdb.reverse/aarch64.c | 99 ---------------------- gdb/testsuite/gdb.reverse/aarch64.exp | 115 ------------------------- gdb/testsuite/gdb.reverse/insn-reverse.c | 121 +++++++++++++++++++++++++++ gdb/testsuite/gdb.reverse/insn-reverse.exp | 130 +++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 214 deletions(-) delete mode 100644 gdb/testsuite/gdb.reverse/aarch64.c delete mode 100644 gdb/testsuite/gdb.reverse/aarch64.exp create mode 100644 gdb/testsuite/gdb.reverse/insn-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/insn-reverse.exp diff --git a/gdb/testsuite/gdb.reverse/aarch64.c b/gdb/testsuite/gdb.reverse/aarch64.c deleted file mode 100644 index ae8509a..0000000 --- a/gdb/testsuite/gdb.reverse/aarch64.c +++ /dev/null @@ -1,99 +0,0 @@ -/* This testcase is part of GDB, the GNU debugger. - - Copyright 2015-2016 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#include <arm_neon.h> - -static void -load (void) -{ - int buf[8]; - - asm ("ld1 { v1.8b }, [%[buf]]\n" - "ld1 { v2.8b, v3.8b }, [%[buf]]\n" - "ld1 { v3.8b, v4.8b, v5.8b }, [%[buf]]\n" - : - : [buf] "r" (buf) - : /* No clobbers */); -} - -static void -move (void) -{ - float32x2_t b1_ = vdup_n_f32(123.0f); - float32_t a1_ = 0; - float64x1_t b2_ = vdup_n_f64(456.0f); - float64_t a2_ = 0; - - asm ("ins %0.s[0], %w1\n" - : "=w"(b1_) - : "r"(a1_), "0"(b1_) - : /* No clobbers */); - - asm ("ins %0.d[1], %x1\n" - : "=w"(b2_) - : "r"(a2_), "0"(b2_) - : /* No clobbers */); -} - -static void -adv_simd_mod_imm (void) -{ - float32x2_t a1 = {2.0, 4.0}; - - asm ("bic %0.2s, #1\n" - "bic %0.2s, #1, lsl #8\n" - : "=w"(a1) - : "0"(a1) - : /* No clobbers */); -} - -static void -adv_simd_scalar_index (void) -{ - float64x2_t b_ = {0.0, 0.0}; - float64_t a_ = 1.0; - float64_t result; - - asm ("fmla %d0,%d1,%2.d[1]" - : "=w"(result) - : "w"(a_), "w"(b_) - : /* No clobbers */); -} - -static void -adv_simd_smlal (void) -{ - asm ("smlal v13.2d, v8.2s, v0.2s"); -} - -static void -adv_simd_vect_shift (void) -{ - asm ("fcvtzs s0, s0, #1"); -} - -int -main () -{ - load (); - move (); - adv_simd_mod_imm (); - adv_simd_scalar_index (); - adv_simd_smlal (); - adv_simd_vect_shift (); - return 0; -} diff --git a/gdb/testsuite/gdb.reverse/aarch64.exp b/gdb/testsuite/gdb.reverse/aarch64.exp deleted file mode 100644 index 2906d4b..0000000 --- a/gdb/testsuite/gdb.reverse/aarch64.exp +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (C) 2015-2016 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -if ![supports_reverse] { - return -} - -# Test aarch64 instruction recording. - -if {![is_aarch64_target]} then { - verbose "Skipping aarch64 instruction recording tests." - return -} - -standard_testfile - -if {[prepare_for_testing $testfile.exp $testfile $srcfile \ - [list debug]]} { - untested ${testfile}.exp - return -1 -} -if { ![runto main] } then { - fail "run to main" - return -} - -# In each function FUNC, GDB turns on process record, and single step -# until program goes to the end of the function. Then, single step -# backward. In each of forward single step and backward single step, -# the contents of registers are saved, and test compares them. If -# there is any differences, a FAIL is emitted. - -proc test { func } { - global hex decimal - global gdb_prompt - - with_test_prefix "$func" { - gdb_breakpoint $func - gdb_test "continue" - - set last_insn "" - set test "disassemble $func" - gdb_test_multiple $test $test { - -re ".*($hex) <\\+$decimal>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" { - set last_insn $expect_out(1,string) - } - } - if { $last_insn == "" } { - fail "find the last instruction of function $func" - } - - # Activate process record/replay - gdb_test_no_output "record" "Turn on process record" - - # Registers contents before each forward single step. - set count 0 - for {} {$count < 500} {incr count} { - gdb_test_multiple "x/i \$pc" "" { - -re ".* ($hex) <.*>:\[ \t\]*(.*)\r\n$gdb_prompt $" { - set insn_addr $expect_out(1,string) - - if [expr {$last_insn == $insn_addr}] { - break - } - - set insn_array($count) $expect_out(2,string) - } - } - - set pre_regs($count) [capture_command_output "info all-registers" ""] - gdb_test "si" "" "" - } - - incr count -1 - # Registers contents after each backward single step. - for {set i $count} {$i >= 0} {incr i -1} { - gdb_test "reverse-stepi" "" "" - set post_regs($i) [capture_command_output "info all-registers" ""] - } - - # Compare the register contents. - for {set i 0} {$i < $count} {incr i} { - if { ![gdb_assert { [string compare $pre_regs($i) $post_regs($i)] == 0 } \ - "compare registers on insn $i:$insn_array($i)"] } { - - foreach pre_line [split $pre_regs($i) \n] post_line [split $post_regs($i) \n] { - if { [string compare $pre_line $post_line] } { - verbose -log " -:$pre_line" - verbose -log " +:$post_line" - } - } - } - } - gdb_test "record stop" - } -} - -test "load" -test "move" -test "adv_simd_mod_imm" -test "adv_simd_scalar_index" -test "adv_simd_smlal" -test "adv_simd_vect_shift" diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.c b/gdb/testsuite/gdb.reverse/insn-reverse.c new file mode 100644 index 0000000..1bfb8b0 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/insn-reverse.c @@ -0,0 +1,121 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015-2016 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if (defined __aarch64__) +#include <arm_neon.h> +#endif + +#if (defined __aarch64__) +static void +load (void) +{ + int buf[8]; + + asm ("ld1 { v1.8b }, [%[buf]]\n" + "ld1 { v2.8b, v3.8b }, [%[buf]]\n" + "ld1 { v3.8b, v4.8b, v5.8b }, [%[buf]]\n" + : + : [buf] "r" (buf) + : /* No clobbers */); +} + +static void +move (void) +{ + float32x2_t b1_ = vdup_n_f32(123.0f); + float32_t a1_ = 0; + float64x1_t b2_ = vdup_n_f64(456.0f); + float64_t a2_ = 0; + + asm ("ins %0.s[0], %w1\n" + : "=w"(b1_) + : "r"(a1_), "0"(b1_) + : /* No clobbers */); + + asm ("ins %0.d[1], %x1\n" + : "=w"(b2_) + : "r"(a2_), "0"(b2_) + : /* No clobbers */); +} + +static void +adv_simd_mod_imm (void) +{ + float32x2_t a1 = {2.0, 4.0}; + + asm ("bic %0.2s, #1\n" + "bic %0.2s, #1, lsl #8\n" + : "=w"(a1) + : "0"(a1) + : /* No clobbers */); +} + +static void +adv_simd_scalar_index (void) +{ + float64x2_t b_ = {0.0, 0.0}; + float64_t a_ = 1.0; + float64_t result; + + asm ("fmla %d0,%d1,%2.d[1]" + : "=w"(result) + : "w"(a_), "w"(b_) + : /* No clobbers */); +} + +static void +adv_simd_smlal (void) +{ + asm ("smlal v13.2d, v8.2s, v0.2s"); +} + +static void +adv_simd_vect_shift (void) +{ + asm ("fcvtzs s0, s0, #1"); +} +#endif + +typedef void (*testcase_ftype) (void); + +/* Functions testing instruction decodings. GDB will read n_testcases + to know how many functions to test. */ + +static testcase_ftype testcases[] = +{ +#if (defined __aarch64__) + load, + move, + adv_simd_mod_imm, + adv_simd_scalar_index, + adv_simd_smlal, + adv_simd_vect_shift, +#endif +}; + +static int n_testcases = (sizeof (testcases) / sizeof (testcase_ftype)); + +int +main () +{ + int i = 0; + + for (i = 0; i < n_testcases; i++) + testcases[i] (); + + return 0; +} diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.exp b/gdb/testsuite/gdb.reverse/insn-reverse.exp new file mode 100644 index 0000000..f52b40c --- /dev/null +++ b/gdb/testsuite/gdb.reverse/insn-reverse.exp @@ -0,0 +1,130 @@ +# Copyright (C) 2015-2016 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if ![supports_reverse] { + return +} + +standard_testfile + +if {[prepare_for_testing $testfile.exp $testfile $srcfile \ + [list debug]]} { + untested ${testfile}.exp + return -1 +} +if { ![runto main] } then { + fail "run to main" + return +} + +# Read function name from testcases[N]. + +proc read_testcase { n } { + global gdb_prompt + + set result -1 + gdb_test_multiple "print testcases\[${n}\]" "read name of test case ${n}" { + -re "\[$\].*= .*<(.*)>.*$gdb_prompt $" { + set result $expect_out(1,string) + } + -re "$gdb_prompt $" { } + } + + return $result +} + +# In each function FUNC, GDB turns on process record, and single step +# until program goes to the end of the function. Then, single step +# backward. In each of forward single step and backward single step, +# the contents of registers are saved, and test compares them. If +# there is any differences, a FAIL is emitted. + +proc test { func } { + global hex decimal + global gdb_prompt + + with_test_prefix "$func" { + gdb_breakpoint $func + gdb_test "continue" + + set last_insn "" + set test "disassemble $func" + gdb_test_multiple $test $test { + -re ".*($hex) <\\+$decimal>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" { + set last_insn $expect_out(1,string) + } + } + if { $last_insn == "" } { + fail "find the last instruction of function $func" + } + + # Activate process record/replay + gdb_test_no_output "record" "Turn on process record" + + # Registers contents before each forward single step. + set count 0 + for {} {$count < 500} {incr count} { + gdb_test_multiple "x/i \$pc" "" { + -re ".* ($hex) <.*>:\[ \t\]*(.*)\r\n$gdb_prompt $" { + set insn_addr $expect_out(1,string) + + if [expr {$last_insn == $insn_addr}] { + break + } + + set insn_array($count) $expect_out(2,string) + } + } + + set pre_regs($count) [capture_command_output "info all-registers" ""] + gdb_test "si" "" "" + } + + incr count -1 + # Registers contents after each backward single step. + for {set i $count} {$i >= 0} {incr i -1} { + gdb_test "reverse-stepi" "" "" + set post_regs($i) [capture_command_output "info all-registers" ""] + } + + # Compare the register contents. + for {set i 0} {$i < $count} {incr i} { + if { ![gdb_assert { [string compare $pre_regs($i) $post_regs($i)] == 0 } \ + "compare registers on insn $i:$insn_array($i)"] } { + + foreach pre_line [split $pre_regs($i) \n] post_line [split $post_regs($i) \n] { + if { [string compare $pre_line $post_line] } { + verbose -log " -:$pre_line" + verbose -log " +:$post_line" + } + } + } + } + gdb_test "record stop" + } +} + +set n_testcases [get_integer_valueof "n_testcases" 0] + +if { ${n_testcases} == 0 } { + untested "No test" + return 1 +} + +for { set i 0 } { ${i} < ${n_testcases} } { incr i } { + set testcase [read_testcase $i] + + test $testcase +} -- 1.9.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/3] Generalize gdb.reverse/aarch64.exp 2016-02-22 16:53 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Yao Qi @ 2016-02-24 11:22 ` Pedro Alves 2016-02-24 14:40 ` Yao Qi 0 siblings, 1 reply; 11+ messages in thread From: Pedro Alves @ 2016-02-24 11:22 UTC (permalink / raw) To: Yao Qi, gdb-patches On 02/22/2016 04:53 PM, Yao Qi wrote: > I said we can generialize gdb.reverse/aarch64.exp for other > architectures https://sourceware.org/ml/gdb-patches/2015-05/msg00482.html > and here is the patch to change aarch64.exp to insn-reverse.exp. > > gdb/testsuite: > > 2016-02-22 Yao Qi <yao.qi@linaro.org> > > * gdb.reverse/aarch64.c: Rename it ... > * gdb.reverse/insn-reverse.c: to ... > [__aarch64__] Include arm_neon.h. > (testcase_ftype): New. > (testcases): New array. > (n_testcases): New. > (main): Call each element in testcases. > * gdb.reverse/aarch64.exp: Rename it ... > * gdb.reverse/insn-reverse.exp: to ... > Remove is_aarch64_target check. > (read_testcase): New. > Do the tests in a loop. > --- > gdb/testsuite/gdb.reverse/aarch64.c | 99 ---------------------- > gdb/testsuite/gdb.reverse/aarch64.exp | 115 ------------------------- > gdb/testsuite/gdb.reverse/insn-reverse.c | 121 +++++++++++++++++++++++++++ > gdb/testsuite/gdb.reverse/insn-reverse.exp | 130 +++++++++++++++++++++++++++++ Can you send a "git diff -M" so we can easily see the actual changes? (You can make that the default with git config.) Though I think even better would be to do the rename in one patch, and the generalization changes in a separate patch. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1/3] Generalize gdb.reverse/aarch64.exp 2016-02-24 11:22 ` Pedro Alves @ 2016-02-24 14:40 ` Yao Qi 2016-02-24 14:40 ` [PATCH 1.5/3] Rename gdb.reverse/aarch64.{exp,c} to gdb.reverse/insn-reverse.{exp,c} Yao Qi 2016-02-24 19:37 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Pedro Alves 0 siblings, 2 replies; 11+ messages in thread From: Yao Qi @ 2016-02-24 14:40 UTC (permalink / raw) To: gdb-patches I said we can generialize gdb.reverse/aarch64.exp for other architectures https://sourceware.org/ml/gdb-patches/2015-05/msg00482.html and here is the patch to change aarch64.exp so that it can be used to test for other architectures as well. gdb/testsuite: 2016-02-24 Yao Qi <yao.qi@linaro.org> * gdb.reverse/aarch64.c: [__aarch64__] Include arm_neon.h. (testcase_ftype): New. (testcases): New array. (n_testcases): New. (main): Call each element in testcases. * gdb.reverse/aarch64.exp: Remove is_aarch64_target check. (read_testcase): New. Do the tests in a loop. --- gdb/testsuite/gdb.reverse/aarch64.c | 34 ++++++++++++++++++++++++----- gdb/testsuite/gdb.reverse/aarch64.exp | 41 ++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/gdb/testsuite/gdb.reverse/aarch64.c b/gdb/testsuite/gdb.reverse/aarch64.c index ae8509a..1bfb8b0 100644 --- a/gdb/testsuite/gdb.reverse/aarch64.c +++ b/gdb/testsuite/gdb.reverse/aarch64.c @@ -15,8 +15,11 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#if (defined __aarch64__) #include <arm_neon.h> +#endif +#if (defined __aarch64__) static void load (void) { @@ -85,15 +88,34 @@ adv_simd_vect_shift (void) { asm ("fcvtzs s0, s0, #1"); } +#endif + +typedef void (*testcase_ftype) (void); + +/* Functions testing instruction decodings. GDB will read n_testcases + to know how many functions to test. */ + +static testcase_ftype testcases[] = +{ +#if (defined __aarch64__) + load, + move, + adv_simd_mod_imm, + adv_simd_scalar_index, + adv_simd_smlal, + adv_simd_vect_shift, +#endif +}; + +static int n_testcases = (sizeof (testcases) / sizeof (testcase_ftype)); int main () { - load (); - move (); - adv_simd_mod_imm (); - adv_simd_scalar_index (); - adv_simd_smlal (); - adv_simd_vect_shift (); + int i = 0; + + for (i = 0; i < n_testcases; i++) + testcases[i] (); + return 0; } diff --git a/gdb/testsuite/gdb.reverse/aarch64.exp b/gdb/testsuite/gdb.reverse/aarch64.exp index 2906d4b..f52b40c 100644 --- a/gdb/testsuite/gdb.reverse/aarch64.exp +++ b/gdb/testsuite/gdb.reverse/aarch64.exp @@ -17,13 +17,6 @@ if ![supports_reverse] { return } -# Test aarch64 instruction recording. - -if {![is_aarch64_target]} then { - verbose "Skipping aarch64 instruction recording tests." - return -} - standard_testfile if {[prepare_for_testing $testfile.exp $testfile $srcfile \ @@ -36,6 +29,22 @@ if { ![runto main] } then { return } +# Read function name from testcases[N]. + +proc read_testcase { n } { + global gdb_prompt + + set result -1 + gdb_test_multiple "print testcases\[${n}\]" "read name of test case ${n}" { + -re "\[$\].*= .*<(.*)>.*$gdb_prompt $" { + set result $expect_out(1,string) + } + -re "$gdb_prompt $" { } + } + + return $result +} + # In each function FUNC, GDB turns on process record, and single step # until program goes to the end of the function. Then, single step # backward. In each of forward single step and backward single step, @@ -107,9 +116,15 @@ proc test { func } { } } -test "load" -test "move" -test "adv_simd_mod_imm" -test "adv_simd_scalar_index" -test "adv_simd_smlal" -test "adv_simd_vect_shift" +set n_testcases [get_integer_valueof "n_testcases" 0] + +if { ${n_testcases} == 0 } { + untested "No test" + return 1 +} + +for { set i 0 } { ${i} < ${n_testcases} } { incr i } { + set testcase [read_testcase $i] + + test $testcase +} -- 1.9.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1.5/3] Rename gdb.reverse/aarch64.{exp,c} to gdb.reverse/insn-reverse.{exp,c} 2016-02-24 14:40 ` Yao Qi @ 2016-02-24 14:40 ` Yao Qi 2016-02-24 19:37 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Pedro Alves 1 sibling, 0 replies; 11+ messages in thread From: Yao Qi @ 2016-02-24 14:40 UTC (permalink / raw) To: gdb-patches gdb/testsuite: 2016-02-24 Yao Qi <yao.qi@linaro.org> * gdb.reverse/aarch64.c: Rename to ... * gdb.reverse/insn-reverse.c: ... it. * gdb.reverse/aarch64.exp: Rename to ... * gdb.reverse/insn-reverse.exp: ... it. --- gdb/testsuite/gdb.reverse/aarch64.c | 121 --------------------------- gdb/testsuite/gdb.reverse/aarch64.exp | 130 ----------------------------- gdb/testsuite/gdb.reverse/insn-reverse.c | 121 +++++++++++++++++++++++++++ gdb/testsuite/gdb.reverse/insn-reverse.exp | 130 +++++++++++++++++++++++++++++ 4 files changed, 251 insertions(+), 251 deletions(-) delete mode 100644 gdb/testsuite/gdb.reverse/aarch64.c delete mode 100644 gdb/testsuite/gdb.reverse/aarch64.exp create mode 100644 gdb/testsuite/gdb.reverse/insn-reverse.c create mode 100644 gdb/testsuite/gdb.reverse/insn-reverse.exp diff --git a/gdb/testsuite/gdb.reverse/aarch64.c b/gdb/testsuite/gdb.reverse/aarch64.c deleted file mode 100644 index 1bfb8b0..0000000 --- a/gdb/testsuite/gdb.reverse/aarch64.c +++ /dev/null @@ -1,121 +0,0 @@ -/* This testcase is part of GDB, the GNU debugger. - - Copyright 2015-2016 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. */ - -#if (defined __aarch64__) -#include <arm_neon.h> -#endif - -#if (defined __aarch64__) -static void -load (void) -{ - int buf[8]; - - asm ("ld1 { v1.8b }, [%[buf]]\n" - "ld1 { v2.8b, v3.8b }, [%[buf]]\n" - "ld1 { v3.8b, v4.8b, v5.8b }, [%[buf]]\n" - : - : [buf] "r" (buf) - : /* No clobbers */); -} - -static void -move (void) -{ - float32x2_t b1_ = vdup_n_f32(123.0f); - float32_t a1_ = 0; - float64x1_t b2_ = vdup_n_f64(456.0f); - float64_t a2_ = 0; - - asm ("ins %0.s[0], %w1\n" - : "=w"(b1_) - : "r"(a1_), "0"(b1_) - : /* No clobbers */); - - asm ("ins %0.d[1], %x1\n" - : "=w"(b2_) - : "r"(a2_), "0"(b2_) - : /* No clobbers */); -} - -static void -adv_simd_mod_imm (void) -{ - float32x2_t a1 = {2.0, 4.0}; - - asm ("bic %0.2s, #1\n" - "bic %0.2s, #1, lsl #8\n" - : "=w"(a1) - : "0"(a1) - : /* No clobbers */); -} - -static void -adv_simd_scalar_index (void) -{ - float64x2_t b_ = {0.0, 0.0}; - float64_t a_ = 1.0; - float64_t result; - - asm ("fmla %d0,%d1,%2.d[1]" - : "=w"(result) - : "w"(a_), "w"(b_) - : /* No clobbers */); -} - -static void -adv_simd_smlal (void) -{ - asm ("smlal v13.2d, v8.2s, v0.2s"); -} - -static void -adv_simd_vect_shift (void) -{ - asm ("fcvtzs s0, s0, #1"); -} -#endif - -typedef void (*testcase_ftype) (void); - -/* Functions testing instruction decodings. GDB will read n_testcases - to know how many functions to test. */ - -static testcase_ftype testcases[] = -{ -#if (defined __aarch64__) - load, - move, - adv_simd_mod_imm, - adv_simd_scalar_index, - adv_simd_smlal, - adv_simd_vect_shift, -#endif -}; - -static int n_testcases = (sizeof (testcases) / sizeof (testcase_ftype)); - -int -main () -{ - int i = 0; - - for (i = 0; i < n_testcases; i++) - testcases[i] (); - - return 0; -} diff --git a/gdb/testsuite/gdb.reverse/aarch64.exp b/gdb/testsuite/gdb.reverse/aarch64.exp deleted file mode 100644 index f52b40c..0000000 --- a/gdb/testsuite/gdb.reverse/aarch64.exp +++ /dev/null @@ -1,130 +0,0 @@ -# Copyright (C) 2015-2016 Free Software Foundation, Inc. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see <http://www.gnu.org/licenses/>. - -if ![supports_reverse] { - return -} - -standard_testfile - -if {[prepare_for_testing $testfile.exp $testfile $srcfile \ - [list debug]]} { - untested ${testfile}.exp - return -1 -} -if { ![runto main] } then { - fail "run to main" - return -} - -# Read function name from testcases[N]. - -proc read_testcase { n } { - global gdb_prompt - - set result -1 - gdb_test_multiple "print testcases\[${n}\]" "read name of test case ${n}" { - -re "\[$\].*= .*<(.*)>.*$gdb_prompt $" { - set result $expect_out(1,string) - } - -re "$gdb_prompt $" { } - } - - return $result -} - -# In each function FUNC, GDB turns on process record, and single step -# until program goes to the end of the function. Then, single step -# backward. In each of forward single step and backward single step, -# the contents of registers are saved, and test compares them. If -# there is any differences, a FAIL is emitted. - -proc test { func } { - global hex decimal - global gdb_prompt - - with_test_prefix "$func" { - gdb_breakpoint $func - gdb_test "continue" - - set last_insn "" - set test "disassemble $func" - gdb_test_multiple $test $test { - -re ".*($hex) <\\+$decimal>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" { - set last_insn $expect_out(1,string) - } - } - if { $last_insn == "" } { - fail "find the last instruction of function $func" - } - - # Activate process record/replay - gdb_test_no_output "record" "Turn on process record" - - # Registers contents before each forward single step. - set count 0 - for {} {$count < 500} {incr count} { - gdb_test_multiple "x/i \$pc" "" { - -re ".* ($hex) <.*>:\[ \t\]*(.*)\r\n$gdb_prompt $" { - set insn_addr $expect_out(1,string) - - if [expr {$last_insn == $insn_addr}] { - break - } - - set insn_array($count) $expect_out(2,string) - } - } - - set pre_regs($count) [capture_command_output "info all-registers" ""] - gdb_test "si" "" "" - } - - incr count -1 - # Registers contents after each backward single step. - for {set i $count} {$i >= 0} {incr i -1} { - gdb_test "reverse-stepi" "" "" - set post_regs($i) [capture_command_output "info all-registers" ""] - } - - # Compare the register contents. - for {set i 0} {$i < $count} {incr i} { - if { ![gdb_assert { [string compare $pre_regs($i) $post_regs($i)] == 0 } \ - "compare registers on insn $i:$insn_array($i)"] } { - - foreach pre_line [split $pre_regs($i) \n] post_line [split $post_regs($i) \n] { - if { [string compare $pre_line $post_line] } { - verbose -log " -:$pre_line" - verbose -log " +:$post_line" - } - } - } - } - gdb_test "record stop" - } -} - -set n_testcases [get_integer_valueof "n_testcases" 0] - -if { ${n_testcases} == 0 } { - untested "No test" - return 1 -} - -for { set i 0 } { ${i} < ${n_testcases} } { incr i } { - set testcase [read_testcase $i] - - test $testcase -} diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.c b/gdb/testsuite/gdb.reverse/insn-reverse.c new file mode 100644 index 0000000..1bfb8b0 --- /dev/null +++ b/gdb/testsuite/gdb.reverse/insn-reverse.c @@ -0,0 +1,121 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015-2016 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#if (defined __aarch64__) +#include <arm_neon.h> +#endif + +#if (defined __aarch64__) +static void +load (void) +{ + int buf[8]; + + asm ("ld1 { v1.8b }, [%[buf]]\n" + "ld1 { v2.8b, v3.8b }, [%[buf]]\n" + "ld1 { v3.8b, v4.8b, v5.8b }, [%[buf]]\n" + : + : [buf] "r" (buf) + : /* No clobbers */); +} + +static void +move (void) +{ + float32x2_t b1_ = vdup_n_f32(123.0f); + float32_t a1_ = 0; + float64x1_t b2_ = vdup_n_f64(456.0f); + float64_t a2_ = 0; + + asm ("ins %0.s[0], %w1\n" + : "=w"(b1_) + : "r"(a1_), "0"(b1_) + : /* No clobbers */); + + asm ("ins %0.d[1], %x1\n" + : "=w"(b2_) + : "r"(a2_), "0"(b2_) + : /* No clobbers */); +} + +static void +adv_simd_mod_imm (void) +{ + float32x2_t a1 = {2.0, 4.0}; + + asm ("bic %0.2s, #1\n" + "bic %0.2s, #1, lsl #8\n" + : "=w"(a1) + : "0"(a1) + : /* No clobbers */); +} + +static void +adv_simd_scalar_index (void) +{ + float64x2_t b_ = {0.0, 0.0}; + float64_t a_ = 1.0; + float64_t result; + + asm ("fmla %d0,%d1,%2.d[1]" + : "=w"(result) + : "w"(a_), "w"(b_) + : /* No clobbers */); +} + +static void +adv_simd_smlal (void) +{ + asm ("smlal v13.2d, v8.2s, v0.2s"); +} + +static void +adv_simd_vect_shift (void) +{ + asm ("fcvtzs s0, s0, #1"); +} +#endif + +typedef void (*testcase_ftype) (void); + +/* Functions testing instruction decodings. GDB will read n_testcases + to know how many functions to test. */ + +static testcase_ftype testcases[] = +{ +#if (defined __aarch64__) + load, + move, + adv_simd_mod_imm, + adv_simd_scalar_index, + adv_simd_smlal, + adv_simd_vect_shift, +#endif +}; + +static int n_testcases = (sizeof (testcases) / sizeof (testcase_ftype)); + +int +main () +{ + int i = 0; + + for (i = 0; i < n_testcases; i++) + testcases[i] (); + + return 0; +} diff --git a/gdb/testsuite/gdb.reverse/insn-reverse.exp b/gdb/testsuite/gdb.reverse/insn-reverse.exp new file mode 100644 index 0000000..f52b40c --- /dev/null +++ b/gdb/testsuite/gdb.reverse/insn-reverse.exp @@ -0,0 +1,130 @@ +# Copyright (C) 2015-2016 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +if ![supports_reverse] { + return +} + +standard_testfile + +if {[prepare_for_testing $testfile.exp $testfile $srcfile \ + [list debug]]} { + untested ${testfile}.exp + return -1 +} +if { ![runto main] } then { + fail "run to main" + return +} + +# Read function name from testcases[N]. + +proc read_testcase { n } { + global gdb_prompt + + set result -1 + gdb_test_multiple "print testcases\[${n}\]" "read name of test case ${n}" { + -re "\[$\].*= .*<(.*)>.*$gdb_prompt $" { + set result $expect_out(1,string) + } + -re "$gdb_prompt $" { } + } + + return $result +} + +# In each function FUNC, GDB turns on process record, and single step +# until program goes to the end of the function. Then, single step +# backward. In each of forward single step and backward single step, +# the contents of registers are saved, and test compares them. If +# there is any differences, a FAIL is emitted. + +proc test { func } { + global hex decimal + global gdb_prompt + + with_test_prefix "$func" { + gdb_breakpoint $func + gdb_test "continue" + + set last_insn "" + set test "disassemble $func" + gdb_test_multiple $test $test { + -re ".*($hex) <\\+$decimal>:\[^\r\n\]+\r\nEnd of assembler dump\.\r\n$gdb_prompt $" { + set last_insn $expect_out(1,string) + } + } + if { $last_insn == "" } { + fail "find the last instruction of function $func" + } + + # Activate process record/replay + gdb_test_no_output "record" "Turn on process record" + + # Registers contents before each forward single step. + set count 0 + for {} {$count < 500} {incr count} { + gdb_test_multiple "x/i \$pc" "" { + -re ".* ($hex) <.*>:\[ \t\]*(.*)\r\n$gdb_prompt $" { + set insn_addr $expect_out(1,string) + + if [expr {$last_insn == $insn_addr}] { + break + } + + set insn_array($count) $expect_out(2,string) + } + } + + set pre_regs($count) [capture_command_output "info all-registers" ""] + gdb_test "si" "" "" + } + + incr count -1 + # Registers contents after each backward single step. + for {set i $count} {$i >= 0} {incr i -1} { + gdb_test "reverse-stepi" "" "" + set post_regs($i) [capture_command_output "info all-registers" ""] + } + + # Compare the register contents. + for {set i 0} {$i < $count} {incr i} { + if { ![gdb_assert { [string compare $pre_regs($i) $post_regs($i)] == 0 } \ + "compare registers on insn $i:$insn_array($i)"] } { + + foreach pre_line [split $pre_regs($i) \n] post_line [split $post_regs($i) \n] { + if { [string compare $pre_line $post_line] } { + verbose -log " -:$pre_line" + verbose -log " +:$post_line" + } + } + } + } + gdb_test "record stop" + } +} + +set n_testcases [get_integer_valueof "n_testcases" 0] + +if { ${n_testcases} == 0 } { + untested "No test" + return 1 +} + +for { set i 0 } { ${i} < ${n_testcases} } { incr i } { + set testcase [read_testcase $i] + + test $testcase +} -- 1.9.1 ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/3] Generalize gdb.reverse/aarch64.exp 2016-02-24 14:40 ` Yao Qi 2016-02-24 14:40 ` [PATCH 1.5/3] Rename gdb.reverse/aarch64.{exp,c} to gdb.reverse/insn-reverse.{exp,c} Yao Qi @ 2016-02-24 19:37 ` Pedro Alves 1 sibling, 0 replies; 11+ messages in thread From: Pedro Alves @ 2016-02-24 19:37 UTC (permalink / raw) To: Yao Qi, gdb-patches On 02/24/2016 02:40 PM, Yao Qi wrote: > I said we can generialize gdb.reverse/aarch64.exp for other > architectures https://sourceware.org/ml/gdb-patches/2015-05/msg00482.html > and here is the patch to change aarch64.exp so that it can be used to > test for other architectures as well. > > gdb/testsuite: > > 2016-02-24 Yao Qi <yao.qi@linaro.org> > > * gdb.reverse/aarch64.c: [__aarch64__] Include arm_neon.h. > (testcase_ftype): New. > (testcases): New array. > (n_testcases): New. > (main): Call each element in testcases. > * gdb.reverse/aarch64.exp: Remove is_aarch64_target check. > (read_testcase): New. > Do the tests in a loop. Thanks for splitting. LGTM. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/3] Bug fixes in arm reverse debugging 2016-02-22 16:53 [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi ` (2 preceding siblings ...) 2016-02-22 16:53 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Yao Qi @ 2016-02-26 15:01 ` Yao Qi 3 siblings, 0 replies; 11+ messages in thread From: Yao Qi @ 2016-02-26 15:01 UTC (permalink / raw) To: Yao Qi; +Cc: gdb-patches Yao Qi <qiyaoltc@gmail.com> writes: > This patch series extends test case gdb.reverse/aarch64.exp for general > test (it covers aarch64 and arm, and I plan to merge i386 tests to it > too) and fix some bugs on instruction decoding exposed the new tests. I pushed them in. -- Yao (齐尧) ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2016-02-26 15:01 UTC | newest] Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-02-22 16:53 [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi 2016-02-22 16:53 ` [PATCH 3/3] Fix various bugs in arm_record_exreg_ld_st_insn Yao Qi 2016-02-23 19:59 ` Luis Machado 2016-02-26 14:54 ` Yao Qi 2016-02-22 16:53 ` [PATCH 2/3] Record right reg num of thumb special data instructions Yao Qi 2016-02-22 16:53 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Yao Qi 2016-02-24 11:22 ` Pedro Alves 2016-02-24 14:40 ` Yao Qi 2016-02-24 14:40 ` [PATCH 1.5/3] Rename gdb.reverse/aarch64.{exp,c} to gdb.reverse/insn-reverse.{exp,c} Yao Qi 2016-02-24 19:37 ` [PATCH 1/3] Generalize gdb.reverse/aarch64.exp Pedro Alves 2016-02-26 15:01 ` [PATCH 0/3] Bug fixes in arm reverse debugging Yao Qi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).