[4/7] Implements aarch64 process record and reverse debugging support
Commit Message
2014-09-18 Omair Javaid <omair.javaid@linaro.org>
* aarch64-linux-tdep.c (aarch64_linux_init_abi): Install AArch64
process record handler.
* aarch64-tdep.c (record.h): Include.
(record-full.h): Include.
(submask): New macro.
(bit): New macro.
(bits): New macro.
(REG_ALLOC): New macro.
(MEM_ALLOC): New macro.
(struct aarch64_mem_r): Define.
(aarch64_record_result): New enum.
(struct insn_decode_record): Define.
(insn_decode_record): New typedef.
(aarch64_record_data_proc_reg): Add record handler for data processing
register insns.
(aarch64_record_data_proc_imm): Add record handler for data processing
immediate insns.
(aarch64_record_branch_except_sys): Add record handler for branch,
exception and system insns.
(aarch64_record_load_store): Add record handler for load/store insns.
(aarch64_record_decode_insn_handler): Add record insn decoding function.
(deallocate_reg_mem): Add memory cleanup function for record data.
(aarch64_process_record): Add gdbarch handler for AArch64 process
record.
* aarch64-tdep.h (aarch64_process_record): New extern declaration.
---
gdb/aarch64-linux-tdep.c | 3 +
gdb/aarch64-tdep.c | 578 +++++++++++++++++++++++++++++++++++++++++++++++
gdb/aarch64-tdep.h | 3 +
3 files changed, 584 insertions(+)
Comments
On 18 September 2014 05:09, Omair Javaid <omair.javaid@linaro.org> wrote:
> 2014-09-18 Omair Javaid <omair.javaid@linaro.org>
>
> * aarch64-linux-tdep.c (aarch64_linux_init_abi): Install AArch64
> process record handler.
> * aarch64-tdep.c (record.h): Include.
> (record-full.h): Include.
> (submask): New macro.
> (bit): New macro.
> (bits): New macro.
> (REG_ALLOC): New macro.
> (MEM_ALLOC): New macro.
> (struct aarch64_mem_r): Define.
> (aarch64_record_result): New enum.
> (struct insn_decode_record): Define.
> (insn_decode_record): New typedef.
> (aarch64_record_data_proc_reg): Add record handler for data processing
> register insns.
> (aarch64_record_data_proc_imm): Add record handler for data processing
> immediate insns.
> (aarch64_record_branch_except_sys): Add record handler for branch,
> exception and system insns.
> (aarch64_record_load_store): Add record handler for load/store insns.
> (aarch64_record_decode_insn_handler): Add record insn decoding function.
> (deallocate_reg_mem): Add memory cleanup function for record data.
> (aarch64_process_record): Add gdbarch handler for AArch64 process
> record.
> * aarch64-tdep.h (aarch64_process_record): New extern declaration.
> ---
> gdb/aarch64-linux-tdep.c | 3 +
> gdb/aarch64-tdep.c | 578 +++++++++++++++++++++++++++++++++++++++++++++++
> gdb/aarch64-tdep.h | 3 +
> 3 files changed, 584 insertions(+)
>
> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
> index e5565a8..5ab7b37 100644
> --- a/gdb/aarch64-linux-tdep.c
> +++ b/gdb/aarch64-linux-tdep.c
> @@ -401,6 +401,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
> set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
> set_gdbarch_stap_parse_special_token (gdbarch,
> aarch64_stap_parse_special_token);
> +
> + /* Reversible debugging, process record. */
> + set_gdbarch_process_record (gdbarch, aarch64_process_record);
> }
>
> /* Provide a prototype to silence -Wmissing-prototypes. */
> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
> index 1898f6b..ed28f68 100644
> --- a/gdb/aarch64-tdep.c
> +++ b/gdb/aarch64-tdep.c
> @@ -50,6 +50,9 @@
>
> #include "vec.h"
>
> +#include "record.h"
> +#include "record-full.h"
> +
> #include "features/aarch64.c"
>
> /* Pseudo register base numbers. */
> @@ -2804,3 +2807,578 @@ When on, AArch64 specific debugging is enabled."),
> show_aarch64_debug,
> &setdebuglist, &showdebuglist);
> }
> +
> +/* AArch64 process record-replay related structures, defines etc. */
> +
> +#define submask(x) ((1L << ((x) + 1)) - 1)
> +#define bit(obj,st) (((obj) >> (st)) & 1)
> +#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
> +
> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
> + do \
> + { \
> + unsigned int reg_len = LENGTH; \
> + if (reg_len) \
> + { \
> + REGS = XNEWVEC (uint32_t, reg_len); \
> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
> + } \
> + } \
> + while (0)
> +
> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
> + do \
> + { \
> + unsigned int mem_len = LENGTH; \
> + if (mem_len) \
> + { \
> + MEMS = XNEWVEC (struct aarch64_mem_r, mem_len); \
> + memcpy(&MEMS->len, &RECORD_BUF[0], \
> + sizeof(struct aarch64_mem_r) * LENGTH); \
> + } \
> + } \
> + while (0)
> +
> +/* AArch64 memory record structure. */
> +struct aarch64_mem_r
> +{
> + uint64_t len; /* Record length. */
> + uint64_t addr; /* Memory address. */
> +};
> +
> +enum aarch64_record_result
> +{
> + AARCH64_RECORD_SUCCESS,
> + AARCH64_RECORD_FAILURE,
> + AARCH64_RECORD_UNSUPPORTED
> +};
> +
> +/* AArch64 instruction record contains opcode of current insn and execution
> + state (before entry to decode_insn()), contains list of to-be-modified
> + registers and memory blocks (on return from decode_insn()). */
> +
> +typedef struct insn_decode_record_t
> +{
> + struct gdbarch *gdbarch;
> + struct regcache *regcache;
> + CORE_ADDR this_addr;
> + uint32_t aarch64_insn;
> + uint32_t mem_rec_count;
> + uint32_t reg_rec_count;
> + uint32_t *aarch64_regs;
> + struct aarch64_mem_r *aarch64_mems;
> +} insn_decode_record;
> +
> +/* Record handler for data processing - register instructions. */
> +static unsigned int
> +aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
> +{
> + uint8_t reg_rd, insn_bits24_27, insn_bits21_23, setflags;
> + uint32_t record_buf[4];
> +
> + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
> + insn_bits21_23 = bits (aarch64_insn_r->aarch64_insn, 21, 23);
> +
> + if (!bit (aarch64_insn_r->aarch64_insn, 28))
> + {
> + /* Logical (shifted register). */
> + if (insn_bits24_27 == 0x0a)
> + setflags = (bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03);
> + /* Add/subtract. */
> + else if (insn_bits24_27 == 0x0b)
> + setflags = bit (aarch64_insn_r->aarch64_insn, 29);
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + if (setflags)
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
> + }
> + else
> + {
> + if (insn_bits24_27 == 0x0b)
> + {
> + /* Data-processing (3 source). */
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + else if (insn_bits24_27 == 0x0a)
> + {
> + if (insn_bits21_23 == 0x00)
> + {
> + /* Add/subtract (with carry). */
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + if (bit (aarch64_insn_r->aarch64_insn, 29))
> + {
> + record_buf[1] = AARCH64_CPSR_REGNUM;
> + aarch64_insn_r->reg_rec_count = 2;
> + }
> + }
> + else if (insn_bits21_23 == 0x02)
> + {
> + /* Conditional compare (register) / Conditional compare (immediate). */
> + record_buf[0] = AARCH64_CPSR_REGNUM;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + else if (insn_bits21_23 == 0x04 || insn_bits21_23 == 0x06)
> + {
> + /* CConditional select. */
> + /* Data-processing (2 source). */
> + /* Data-processing (1 source). */
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> + }
> + }
> +
> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
> + record_buf);
> + return AARCH64_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for data processing - immediate instructions. */
> +static unsigned int
> +aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
> +{
> + uint8_t reg_rd, insn_bit28, insn_bit23, insn_bits24_27, setflags;
> + uint32_t record_buf[4];
> +
> + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
> + insn_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
> + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
> +
> + /* PC rel addressing / Move wide immediate / BitField / Extract. */
> + if (insn_bits24_27 == 0x00 || insn_bits24_27 == 0x03 ||
> + (insn_bits24_27 == 0x02 && insn_bit23))
> + {
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + else if (insn_bits24_27 == 0x01)
> + {
> + /* Add/Subtract (immediate). */
> + setflags = bit (aarch64_insn_r->aarch64_insn, 29);
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + if (setflags)
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
> + }
> + else if (insn_bits24_27 == 0x02 && !insn_bit23)
> + {
> + /* Logical (immediate). */
> + setflags = bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03;
> + record_buf[0] = reg_rd;
> + aarch64_insn_r->reg_rec_count = 1;
> + if (setflags)
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
> + }
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
> + record_buf);
> + return AARCH64_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for branch, exception generation and system instructions. */
> +static unsigned int
> +aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
> +{
> + struct gdbarch_tdep *tdep = gdbarch_tdep (aarch64_insn_r->gdbarch);
> + uint8_t insn_bits24_27, insn_bits28_31, insn_bits22_23;
> + uint32_t record_buf[4];
> +
> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
> + insn_bits28_31 = bits (aarch64_insn_r->aarch64_insn, 28, 31);
> + insn_bits22_23 = bits (aarch64_insn_r->aarch64_insn, 22, 23);
> +
> + if (insn_bits28_31 == 0x0d)
> + {
> + /* Exception generation instructions. */
> + if (insn_bits24_27 == 0x04)
> + return AARCH64_RECORD_UNSUPPORTED;
> + /* System instructions. */
> + else if (insn_bits24_27 == 0x05 && insn_bits22_23 == 0x00)
> + {
> + record_buf[0] = AARCH64_CPSR_REGNUM;
> + record_buf[1] = bits (aarch64_insn_r->aarch64_insn, 0, 4);
> + aarch64_insn_r->reg_rec_count = 2;
> + }
> + else if((insn_bits24_27 & 0x0e) == 0x06)
> + {
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
> + if (bits (aarch64_insn_r->aarch64_insn, 21, 22) == 0x01)
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
> + }
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> + }
> + else if ((insn_bits28_31 & 0x07) == 0x01 && (insn_bits24_27 & 0x0c) == 0x04)
> + {
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
> + if (bit (aarch64_insn_r->aarch64_insn, 31))
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
> + }
> + else
> + /* All other types of branch instructions. */
> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
> +
> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
> + record_buf);
> + return AARCH64_RECORD_SUCCESS;
> +}
> +
> +/* Record handler for load and store instructions. */
> +static unsigned int
> +aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
> +{
> + uint8_t insn_bits24_27, insn_bits28_29, insn_bits10_11;
> + uint8_t insn_bit23, insn_bit21;
> + uint8_t opc, size_bits, ld_flag, vector_flag;
> + uint32_t reg_rn, reg_rt, reg_rt2;
> + uint64_t datasize, offset;
> + uint32_t record_buf[8];
> + uint64_t record_buf_mem[8];
> + CORE_ADDR address;
> +
> + insn_bits10_11 = bits (aarch64_insn_r->aarch64_insn, 10, 11);
> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
> + insn_bits28_29 = bits (aarch64_insn_r->aarch64_insn, 28, 29);
> + insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21);
> + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
> + ld_flag = bit (aarch64_insn_r->aarch64_insn, 22);
> + vector_flag = bit (aarch64_insn_r->aarch64_insn, 26);
> + reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4);
> + reg_rn = bits (aarch64_insn_r->aarch64_insn, 5, 9);
> + reg_rt2 = bits (aarch64_insn_r->aarch64_insn, 10, 14);
> + size_bits = bits (aarch64_insn_r->aarch64_insn, 30, 31);
> +
> + /* Load/store exclusive instructions decoding. */
> + if (insn_bits24_27 == 0x08 && insn_bits28_29 == 0x00)
> + {
> + if (ld_flag)
> + {
> + record_buf[0] = reg_rt;
> + aarch64_insn_r->reg_rec_count = 1;
> + if (insn_bit21)
> + {
> + record_buf[1] = reg_rt2;
> + aarch64_insn_r->reg_rec_count = 2;
> + }
> + }
> + else
> + {
> + if (insn_bit21)
> + datasize = (8 << size_bits) * 2;
> + else
> + datasize = (8 << size_bits);
> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
> + &address);
> + record_buf_mem[0] = datasize / 8;
> + record_buf_mem[1] = address;
> + aarch64_insn_r->mem_rec_count = 1;
> + if (!insn_bit23)
> + {
> + /* Save register rs. */
> + record_buf[0] = bits (aarch64_insn_r->aarch64_insn, 16, 20);
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + }
> + }
> + /* Load register (literal) instructions decoding. */
> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x01)
> + {
> + if (vector_flag)
> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
> + else
> + record_buf[0] = reg_rt;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + /* All types of load/store pair instructions decoding. */
> + else if ((insn_bits24_27 & 0x0a) == 0x08 && insn_bits28_29 == 0x02)
> + {
> + if (ld_flag)
> + {
> + if (vector_flag)
> + {
> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
> + record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM;
> + }
> + else
> + {
> + record_buf[0] = reg_rt;
> + record_buf[1] = reg_rt2;
> + }
> + aarch64_insn_r->reg_rec_count = 2;
> + }
> + else
> + {
> + uint16_t imm7_off;
> + imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21);
> + if (!vector_flag)
> + size_bits = size_bits >> 1;
> + datasize = 8 << (2 + size_bits);
> + offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off;
> + offset = offset << (2 + size_bits);
> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
> + &address);
> + if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23))
> + {
> + if (imm7_off & 0x40)
> + address = address - offset;
> + else
> + address = address + offset;
> + }
> +
> + record_buf_mem[0] = datasize / 8;
> + record_buf_mem[1] = address;
> + record_buf_mem[2] = datasize / 8;
> + record_buf_mem[3] = address + (datasize / 8);
> + aarch64_insn_r->mem_rec_count = 2;
> + }
> + if (bit (aarch64_insn_r->aarch64_insn, 23))
> + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
> + }
> + /* Load/store register (unsigned immediate) instructions. */
> + else if ((insn_bits24_27 & 0x0b) == 0x09 && insn_bits28_29 == 0x03)
> + {
> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
> + if (!(opc >> 1))
> + if (opc & 0x01)
> + ld_flag = 0x01;
> + else
> + ld_flag = 0x0;
> + else
> + if (size_bits != 0x03)
> + ld_flag = 0x01;
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + if (!ld_flag)
> + {
> + offset = bits (aarch64_insn_r->aarch64_insn, 10, 21);
> + datasize = 8 << size_bits;
> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
> + &address);
> + offset = offset << size_bits;
> + address = address + offset;
> +
> + record_buf_mem[0] = datasize >> 3;
> + record_buf_mem[1] = address;
> + aarch64_insn_r->mem_rec_count = 1;
> + }
> + else
> + {
> + if (vector_flag)
> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
> + else
> + record_buf[0] = reg_rt;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + }
> + /* Load/store register (register offset) instructions. */
> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
> + insn_bits10_11 == 0x02 && insn_bit21)
> + {
> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
> + if (!(opc >> 1))
> + if (opc & 0x01)
> + ld_flag = 0x01;
> + else
> + ld_flag = 0x0;
> + else
> + if (size_bits != 0x03)
> + ld_flag = 0x01;
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + if (!ld_flag)
> + {
> + uint64_t reg_rm_val;
> + regcache_raw_read_unsigned (aarch64_insn_r->regcache,
> + bits (aarch64_insn_r->aarch64_insn, 16, 20), ®_rm_val);
> + if (bit (aarch64_insn_r->aarch64_insn, 12))
> + offset = reg_rm_val << size_bits;
> + else
> + offset = reg_rm_val;
> + datasize = 8 << size_bits;
> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
> + &address);
> + address = address + offset;
> + record_buf_mem[0] = datasize >> 3;
> + record_buf_mem[1] = address;
> + aarch64_insn_r->mem_rec_count = 1;
> + }
> + else
> + {
> + if (vector_flag)
> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
> + else
> + record_buf[0] = reg_rt;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + }
> + /* Load/store register (immediate) instructions. */
> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
> + !insn_bit21)
> + {
> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
> + if (!(opc >> 1))
> + if (opc & 0x01)
> + ld_flag = 0x01;
> + else
> + ld_flag = 0x0;
> + else
> + if (size_bits != 0x03)
> + ld_flag = 0x01;
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + if (!ld_flag)
> + {
> + uint16_t imm9_off;
> + imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20);
> + offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off;
> + datasize = 8 << size_bits;
> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
> + &address);
> + if (insn_bits10_11 != 0x01)
> + {
> + if (imm9_off & 0x0100)
> + address = address - offset;
> + else
> + address = address + offset;
> + }
> + record_buf_mem[0] = datasize >> 3;
> + record_buf_mem[1] = address;
> + aarch64_insn_r->mem_rec_count = 1;
> + }
> + else
> + {
> + if (vector_flag)
> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
> + else
> + record_buf[0] = reg_rt;
> + aarch64_insn_r->reg_rec_count = 1;
> + }
> + if (insn_bits10_11 == 0x01 || insn_bits10_11 == 0x03)
> + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
> + }
> + /* Advanced SIMD load/store instructions. */
> + else
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
> + record_buf_mem);
> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
> + record_buf);
> + return AARCH64_RECORD_SUCCESS;
> +}
> +/* Decodes insns type and invokes its record handler. */
> +
> +static unsigned int
> +aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r)
> +{
> + uint32_t ins_bit25, ins_bit26, ins_bit27, ins_bit28;
> +
> + ins_bit25 = bit (aarch64_insn_r->aarch64_insn, 25);
> + ins_bit26 = bit (aarch64_insn_r->aarch64_insn, 26);
> + ins_bit27 = bit (aarch64_insn_r->aarch64_insn, 27);
> + ins_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
> +
> + /* Data processing - immediate instructions. */
> + if (!ins_bit26 && !ins_bit27 && ins_bit28)
> + return aarch64_record_data_proc_imm (aarch64_insn_r);
> +
> + /* Branch, exception generation and system instructions. */
> + if (ins_bit26 && !ins_bit27 && ins_bit28)
> + return aarch64_record_branch_except_sys (aarch64_insn_r);
> +
> + /* Load and store instructions. */
> + if (!ins_bit25 && ins_bit27)
> + return aarch64_record_load_store (aarch64_insn_r);
> +
> + /* Data processing - register instructions. */
> + if (ins_bit25 && !ins_bit26 && ins_bit27)
> + return aarch64_record_data_proc_reg (aarch64_insn_r);
> +
> + /* Data processing - SIMD and floating point instructions. */
> + if (ins_bit25 && ins_bit26 && ins_bit27)
> + return AARCH64_RECORD_UNSUPPORTED;
> +
> + return AARCH64_RECORD_UNSUPPORTED;
> +}
> +
> +/* Cleans up local record registers and memory allocations. */
> +
> +static void
> +deallocate_reg_mem (insn_decode_record *record)
> +{
> + xfree (record->aarch64_regs);
> + xfree (record->aarch64_mems);
> +}
> +
> +/* Parse the current instruction and record the values of the registers and
> + memory that will be changed in current instruction to record_arch_list
> + return -1 if something is wrong. */
> +
> +int
> +aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
> + CORE_ADDR insn_addr)
> +{
> + uint32_t rec_no = 0;
> + uint8_t insn_size = 4;
> + uint32_t ret = 0;
> + ULONGEST t_bit = 0, insn_id = 0;
> + gdb_byte buf[insn_size];
> + insn_decode_record aarch64_record;
> +
> + memset (&buf[0], 0, insn_size);
> + memset (&aarch64_record, 0, sizeof (insn_decode_record));
> + target_read_memory (insn_addr, &buf[0], insn_size);
> + aarch64_record.aarch64_insn = (uint32_t) extract_unsigned_integer (&buf[0],
> + insn_size, gdbarch_byte_order (gdbarch));
> + aarch64_record.regcache = regcache;
> + aarch64_record.this_addr = insn_addr;
> + aarch64_record.gdbarch = gdbarch;
> +
> + ret = aarch64_record_decode_insn_handler (&aarch64_record);
> + if (ret == AARCH64_RECORD_UNSUPPORTED)
> + {
> + printf_unfiltered (_("Process record does not support instruction "
> + "0x%0x at address %s.\n"),aarch64_record.aarch64_insn,
> + paddress (gdbarch, insn_addr));
> + ret = -1;
> + }
> +
> + if (0 == ret)
> + {
> + /* Record registers. */
> + record_full_arch_list_add_reg (aarch64_record.regcache, AARCH64_PC_REGNUM);
> + if (aarch64_record.aarch64_regs)
> + for (rec_no = 0; rec_no < aarch64_record.reg_rec_count; rec_no++)
> + if (record_full_arch_list_add_reg (aarch64_record.regcache,
> + aarch64_record.aarch64_regs[rec_no]))
> + ret = -1;
> +
> + /* Record memories. */
> + if (aarch64_record.aarch64_mems)
> + for (rec_no = 0; rec_no < aarch64_record.mem_rec_count; rec_no++)
> + if (record_full_arch_list_add_mem
> + ((CORE_ADDR)aarch64_record.aarch64_mems[rec_no].addr,
> + aarch64_record.aarch64_mems[rec_no].len))
> + ret = -1;
> +
> + if (record_full_arch_list_add_end ())
> + ret = -1;
> + }
> +
> + deallocate_reg_mem (&aarch64_record);
> + return ret;
> +}
> diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
> index 78fb779..3dd3dcc 100644
> --- a/gdb/aarch64-tdep.h
> +++ b/gdb/aarch64-tdep.h
> @@ -90,4 +90,7 @@ struct gdbarch_tdep
> struct type *vnb_type;
> };
>
> +extern int aarch64_process_record (struct gdbarch *gdbarch,
> + struct regcache *regcache, CORE_ADDR addr);
> +
> #endif /* aarch64-tdep.h */
> --
> 1.9.1
>
Ping! Kindly help me approve this patch series.
On 19 September 2014 03:28, Omair Javaid <omair.javaid@linaro.org> wrote:
> On 18 September 2014 05:09, Omair Javaid <omair.javaid@linaro.org> wrote:
>> 2014-09-18 Omair Javaid <omair.javaid@linaro.org>
>>
>> * aarch64-linux-tdep.c (aarch64_linux_init_abi): Install AArch64
>> process record handler.
>> * aarch64-tdep.c (record.h): Include.
>> (record-full.h): Include.
>> (submask): New macro.
>> (bit): New macro.
>> (bits): New macro.
>> (REG_ALLOC): New macro.
>> (MEM_ALLOC): New macro.
>> (struct aarch64_mem_r): Define.
>> (aarch64_record_result): New enum.
>> (struct insn_decode_record): Define.
>> (insn_decode_record): New typedef.
>> (aarch64_record_data_proc_reg): Add record handler for data processing
>> register insns.
>> (aarch64_record_data_proc_imm): Add record handler for data processing
>> immediate insns.
>> (aarch64_record_branch_except_sys): Add record handler for branch,
>> exception and system insns.
>> (aarch64_record_load_store): Add record handler for load/store insns.
>> (aarch64_record_decode_insn_handler): Add record insn decoding function.
>> (deallocate_reg_mem): Add memory cleanup function for record data.
>> (aarch64_process_record): Add gdbarch handler for AArch64 process
>> record.
>> * aarch64-tdep.h (aarch64_process_record): New extern declaration.
>> ---
>> gdb/aarch64-linux-tdep.c | 3 +
>> gdb/aarch64-tdep.c | 578 +++++++++++++++++++++++++++++++++++++++++++++++
>> gdb/aarch64-tdep.h | 3 +
>> 3 files changed, 584 insertions(+)
>>
>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
>> index e5565a8..5ab7b37 100644
>> --- a/gdb/aarch64-linux-tdep.c
>> +++ b/gdb/aarch64-linux-tdep.c
>> @@ -401,6 +401,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>> set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
>> set_gdbarch_stap_parse_special_token (gdbarch,
>> aarch64_stap_parse_special_token);
>> +
>> + /* Reversible debugging, process record. */
>> + set_gdbarch_process_record (gdbarch, aarch64_process_record);
>> }
>>
>> /* Provide a prototype to silence -Wmissing-prototypes. */
>> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
>> index 1898f6b..ed28f68 100644
>> --- a/gdb/aarch64-tdep.c
>> +++ b/gdb/aarch64-tdep.c
>> @@ -50,6 +50,9 @@
>>
>> #include "vec.h"
>>
>> +#include "record.h"
>> +#include "record-full.h"
>> +
>> #include "features/aarch64.c"
>>
>> /* Pseudo register base numbers. */
>> @@ -2804,3 +2807,578 @@ When on, AArch64 specific debugging is enabled."),
>> show_aarch64_debug,
>> &setdebuglist, &showdebuglist);
>> }
>> +
>> +/* AArch64 process record-replay related structures, defines etc. */
>> +
>> +#define submask(x) ((1L << ((x) + 1)) - 1)
>> +#define bit(obj,st) (((obj) >> (st)) & 1)
>> +#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
>> +
>> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
>> + do \
>> + { \
>> + unsigned int reg_len = LENGTH; \
>> + if (reg_len) \
>> + { \
>> + REGS = XNEWVEC (uint32_t, reg_len); \
>> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
>> + } \
>> + } \
>> + while (0)
>> +
>> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
>> + do \
>> + { \
>> + unsigned int mem_len = LENGTH; \
>> + if (mem_len) \
>> + { \
>> + MEMS = XNEWVEC (struct aarch64_mem_r, mem_len); \
>> + memcpy(&MEMS->len, &RECORD_BUF[0], \
>> + sizeof(struct aarch64_mem_r) * LENGTH); \
>> + } \
>> + } \
>> + while (0)
>> +
>> +/* AArch64 memory record structure. */
>> +struct aarch64_mem_r
>> +{
>> + uint64_t len; /* Record length. */
>> + uint64_t addr; /* Memory address. */
>> +};
>> +
>> +enum aarch64_record_result
>> +{
>> + AARCH64_RECORD_SUCCESS,
>> + AARCH64_RECORD_FAILURE,
>> + AARCH64_RECORD_UNSUPPORTED
>> +};
>> +
>> +/* AArch64 instruction record contains opcode of current insn and execution
>> + state (before entry to decode_insn()), contains list of to-be-modified
>> + registers and memory blocks (on return from decode_insn()). */
>> +
>> +typedef struct insn_decode_record_t
>> +{
>> + struct gdbarch *gdbarch;
>> + struct regcache *regcache;
>> + CORE_ADDR this_addr;
>> + uint32_t aarch64_insn;
>> + uint32_t mem_rec_count;
>> + uint32_t reg_rec_count;
>> + uint32_t *aarch64_regs;
>> + struct aarch64_mem_r *aarch64_mems;
>> +} insn_decode_record;
>> +
>> +/* Record handler for data processing - register instructions. */
>> +static unsigned int
>> +aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
>> +{
>> + uint8_t reg_rd, insn_bits24_27, insn_bits21_23, setflags;
>> + uint32_t record_buf[4];
>> +
>> + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>> + insn_bits21_23 = bits (aarch64_insn_r->aarch64_insn, 21, 23);
>> +
>> + if (!bit (aarch64_insn_r->aarch64_insn, 28))
>> + {
>> + /* Logical (shifted register). */
>> + if (insn_bits24_27 == 0x0a)
>> + setflags = (bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03);
>> + /* Add/subtract. */
>> + else if (insn_bits24_27 == 0x0b)
>> + setflags = bit (aarch64_insn_r->aarch64_insn, 29);
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + if (setflags)
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
>> + }
>> + else
>> + {
>> + if (insn_bits24_27 == 0x0b)
>> + {
>> + /* Data-processing (3 source). */
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + else if (insn_bits24_27 == 0x0a)
>> + {
>> + if (insn_bits21_23 == 0x00)
>> + {
>> + /* Add/subtract (with carry). */
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + if (bit (aarch64_insn_r->aarch64_insn, 29))
>> + {
>> + record_buf[1] = AARCH64_CPSR_REGNUM;
>> + aarch64_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else if (insn_bits21_23 == 0x02)
>> + {
>> + /* Conditional compare (register) / Conditional compare (immediate). */
>> + record_buf[0] = AARCH64_CPSR_REGNUM;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + else if (insn_bits21_23 == 0x04 || insn_bits21_23 == 0x06)
>> + {
>> + /* CConditional select. */
>> + /* Data-processing (2 source). */
>> + /* Data-processing (1 source). */
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> + }
>> + }
>> +
>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>> + record_buf);
>> + return AARCH64_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for data processing - immediate instructions. */
>> +static unsigned int
>> +aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
>> +{
>> + uint8_t reg_rd, insn_bit28, insn_bit23, insn_bits24_27, setflags;
>> + uint32_t record_buf[4];
>> +
>> + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>> + insn_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
>> + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>> +
>> + /* PC rel addressing / Move wide immediate / BitField / Extract. */
>> + if (insn_bits24_27 == 0x00 || insn_bits24_27 == 0x03 ||
>> + (insn_bits24_27 == 0x02 && insn_bit23))
>> + {
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + else if (insn_bits24_27 == 0x01)
>> + {
>> + /* Add/Subtract (immediate). */
>> + setflags = bit (aarch64_insn_r->aarch64_insn, 29);
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + if (setflags)
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
>> + }
>> + else if (insn_bits24_27 == 0x02 && !insn_bit23)
>> + {
>> + /* Logical (immediate). */
>> + setflags = bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03;
>> + record_buf[0] = reg_rd;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + if (setflags)
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
>> + }
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>> + record_buf);
>> + return AARCH64_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for branch, exception generation and system instructions. */
>> +static unsigned int
>> +aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
>> +{
>> + struct gdbarch_tdep *tdep = gdbarch_tdep (aarch64_insn_r->gdbarch);
>> + uint8_t insn_bits24_27, insn_bits28_31, insn_bits22_23;
>> + uint32_t record_buf[4];
>> +
>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>> + insn_bits28_31 = bits (aarch64_insn_r->aarch64_insn, 28, 31);
>> + insn_bits22_23 = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>> +
>> + if (insn_bits28_31 == 0x0d)
>> + {
>> + /* Exception generation instructions. */
>> + if (insn_bits24_27 == 0x04)
>> + return AARCH64_RECORD_UNSUPPORTED;
>> + /* System instructions. */
>> + else if (insn_bits24_27 == 0x05 && insn_bits22_23 == 0x00)
>> + {
>> + record_buf[0] = AARCH64_CPSR_REGNUM;
>> + record_buf[1] = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>> + aarch64_insn_r->reg_rec_count = 2;
>> + }
>> + else if((insn_bits24_27 & 0x0e) == 0x06)
>> + {
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
>> + if (bits (aarch64_insn_r->aarch64_insn, 21, 22) == 0x01)
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
>> + }
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> + }
>> + else if ((insn_bits28_31 & 0x07) == 0x01 && (insn_bits24_27 & 0x0c) == 0x04)
>> + {
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
>> + if (bit (aarch64_insn_r->aarch64_insn, 31))
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
>> + }
>> + else
>> + /* All other types of branch instructions. */
>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
>> +
>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>> + record_buf);
>> + return AARCH64_RECORD_SUCCESS;
>> +}
>> +
>> +/* Record handler for load and store instructions. */
>> +static unsigned int
>> +aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
>> +{
>> + uint8_t insn_bits24_27, insn_bits28_29, insn_bits10_11;
>> + uint8_t insn_bit23, insn_bit21;
>> + uint8_t opc, size_bits, ld_flag, vector_flag;
>> + uint32_t reg_rn, reg_rt, reg_rt2;
>> + uint64_t datasize, offset;
>> + uint32_t record_buf[8];
>> + uint64_t record_buf_mem[8];
>> + CORE_ADDR address;
>> +
>> + insn_bits10_11 = bits (aarch64_insn_r->aarch64_insn, 10, 11);
>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>> + insn_bits28_29 = bits (aarch64_insn_r->aarch64_insn, 28, 29);
>> + insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21);
>> + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
>> + ld_flag = bit (aarch64_insn_r->aarch64_insn, 22);
>> + vector_flag = bit (aarch64_insn_r->aarch64_insn, 26);
>> + reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>> + reg_rn = bits (aarch64_insn_r->aarch64_insn, 5, 9);
>> + reg_rt2 = bits (aarch64_insn_r->aarch64_insn, 10, 14);
>> + size_bits = bits (aarch64_insn_r->aarch64_insn, 30, 31);
>> +
>> + /* Load/store exclusive instructions decoding. */
>> + if (insn_bits24_27 == 0x08 && insn_bits28_29 == 0x00)
>> + {
>> + if (ld_flag)
>> + {
>> + record_buf[0] = reg_rt;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + if (insn_bit21)
>> + {
>> + record_buf[1] = reg_rt2;
>> + aarch64_insn_r->reg_rec_count = 2;
>> + }
>> + }
>> + else
>> + {
>> + if (insn_bit21)
>> + datasize = (8 << size_bits) * 2;
>> + else
>> + datasize = (8 << size_bits);
>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>> + &address);
>> + record_buf_mem[0] = datasize / 8;
>> + record_buf_mem[1] = address;
>> + aarch64_insn_r->mem_rec_count = 1;
>> + if (!insn_bit23)
>> + {
>> + /* Save register rs. */
>> + record_buf[0] = bits (aarch64_insn_r->aarch64_insn, 16, 20);
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + }
>> + /* Load register (literal) instructions decoding. */
>> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x01)
>> + {
>> + if (vector_flag)
>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>> + else
>> + record_buf[0] = reg_rt;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + /* All types of load/store pair instructions decoding. */
>> + else if ((insn_bits24_27 & 0x0a) == 0x08 && insn_bits28_29 == 0x02)
>> + {
>> + if (ld_flag)
>> + {
>> + if (vector_flag)
>> + {
>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>> + record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM;
>> + }
>> + else
>> + {
>> + record_buf[0] = reg_rt;
>> + record_buf[1] = reg_rt2;
>> + }
>> + aarch64_insn_r->reg_rec_count = 2;
>> + }
>> + else
>> + {
>> + uint16_t imm7_off;
>> + imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21);
>> + if (!vector_flag)
>> + size_bits = size_bits >> 1;
>> + datasize = 8 << (2 + size_bits);
>> + offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off;
>> + offset = offset << (2 + size_bits);
>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>> + &address);
>> + if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23))
>> + {
>> + if (imm7_off & 0x40)
>> + address = address - offset;
>> + else
>> + address = address + offset;
>> + }
>> +
>> + record_buf_mem[0] = datasize / 8;
>> + record_buf_mem[1] = address;
>> + record_buf_mem[2] = datasize / 8;
>> + record_buf_mem[3] = address + (datasize / 8);
>> + aarch64_insn_r->mem_rec_count = 2;
>> + }
>> + if (bit (aarch64_insn_r->aarch64_insn, 23))
>> + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
>> + }
>> + /* Load/store register (unsigned immediate) instructions. */
>> + else if ((insn_bits24_27 & 0x0b) == 0x09 && insn_bits28_29 == 0x03)
>> + {
>> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>> + if (!(opc >> 1))
>> + if (opc & 0x01)
>> + ld_flag = 0x01;
>> + else
>> + ld_flag = 0x0;
>> + else
>> + if (size_bits != 0x03)
>> + ld_flag = 0x01;
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + if (!ld_flag)
>> + {
>> + offset = bits (aarch64_insn_r->aarch64_insn, 10, 21);
>> + datasize = 8 << size_bits;
>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>> + &address);
>> + offset = offset << size_bits;
>> + address = address + offset;
>> +
>> + record_buf_mem[0] = datasize >> 3;
>> + record_buf_mem[1] = address;
>> + aarch64_insn_r->mem_rec_count = 1;
>> + }
>> + else
>> + {
>> + if (vector_flag)
>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>> + else
>> + record_buf[0] = reg_rt;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + /* Load/store register (register offset) instructions. */
>> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
>> + insn_bits10_11 == 0x02 && insn_bit21)
>> + {
>> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>> + if (!(opc >> 1))
>> + if (opc & 0x01)
>> + ld_flag = 0x01;
>> + else
>> + ld_flag = 0x0;
>> + else
>> + if (size_bits != 0x03)
>> + ld_flag = 0x01;
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + if (!ld_flag)
>> + {
>> + uint64_t reg_rm_val;
>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache,
>> + bits (aarch64_insn_r->aarch64_insn, 16, 20), ®_rm_val);
>> + if (bit (aarch64_insn_r->aarch64_insn, 12))
>> + offset = reg_rm_val << size_bits;
>> + else
>> + offset = reg_rm_val;
>> + datasize = 8 << size_bits;
>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>> + &address);
>> + address = address + offset;
>> + record_buf_mem[0] = datasize >> 3;
>> + record_buf_mem[1] = address;
>> + aarch64_insn_r->mem_rec_count = 1;
>> + }
>> + else
>> + {
>> + if (vector_flag)
>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>> + else
>> + record_buf[0] = reg_rt;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + }
>> + /* Load/store register (immediate) instructions. */
>> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
>> + !insn_bit21)
>> + {
>> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>> + if (!(opc >> 1))
>> + if (opc & 0x01)
>> + ld_flag = 0x01;
>> + else
>> + ld_flag = 0x0;
>> + else
>> + if (size_bits != 0x03)
>> + ld_flag = 0x01;
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + if (!ld_flag)
>> + {
>> + uint16_t imm9_off;
>> + imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20);
>> + offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off;
>> + datasize = 8 << size_bits;
>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>> + &address);
>> + if (insn_bits10_11 != 0x01)
>> + {
>> + if (imm9_off & 0x0100)
>> + address = address - offset;
>> + else
>> + address = address + offset;
>> + }
>> + record_buf_mem[0] = datasize >> 3;
>> + record_buf_mem[1] = address;
>> + aarch64_insn_r->mem_rec_count = 1;
>> + }
>> + else
>> + {
>> + if (vector_flag)
>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>> + else
>> + record_buf[0] = reg_rt;
>> + aarch64_insn_r->reg_rec_count = 1;
>> + }
>> + if (insn_bits10_11 == 0x01 || insn_bits10_11 == 0x03)
>> + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
>> + }
>> + /* Advanced SIMD load/store instructions. */
>> + else
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
>> + record_buf_mem);
>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>> + record_buf);
>> + return AARCH64_RECORD_SUCCESS;
>> +}
>> +/* Decodes insns type and invokes its record handler. */
>> +
>> +static unsigned int
>> +aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r)
>> +{
>> + uint32_t ins_bit25, ins_bit26, ins_bit27, ins_bit28;
>> +
>> + ins_bit25 = bit (aarch64_insn_r->aarch64_insn, 25);
>> + ins_bit26 = bit (aarch64_insn_r->aarch64_insn, 26);
>> + ins_bit27 = bit (aarch64_insn_r->aarch64_insn, 27);
>> + ins_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
>> +
>> + /* Data processing - immediate instructions. */
>> + if (!ins_bit26 && !ins_bit27 && ins_bit28)
>> + return aarch64_record_data_proc_imm (aarch64_insn_r);
>> +
>> + /* Branch, exception generation and system instructions. */
>> + if (ins_bit26 && !ins_bit27 && ins_bit28)
>> + return aarch64_record_branch_except_sys (aarch64_insn_r);
>> +
>> + /* Load and store instructions. */
>> + if (!ins_bit25 && ins_bit27)
>> + return aarch64_record_load_store (aarch64_insn_r);
>> +
>> + /* Data processing - register instructions. */
>> + if (ins_bit25 && !ins_bit26 && ins_bit27)
>> + return aarch64_record_data_proc_reg (aarch64_insn_r);
>> +
>> + /* Data processing - SIMD and floating point instructions. */
>> + if (ins_bit25 && ins_bit26 && ins_bit27)
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +
>> + return AARCH64_RECORD_UNSUPPORTED;
>> +}
>> +
>> +/* Cleans up local record registers and memory allocations. */
>> +
>> +static void
>> +deallocate_reg_mem (insn_decode_record *record)
>> +{
>> + xfree (record->aarch64_regs);
>> + xfree (record->aarch64_mems);
>> +}
>> +
>> +/* Parse the current instruction and record the values of the registers and
>> + memory that will be changed in current instruction to record_arch_list
>> + return -1 if something is wrong. */
>> +
>> +int
>> +aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
>> + CORE_ADDR insn_addr)
>> +{
>> + uint32_t rec_no = 0;
>> + uint8_t insn_size = 4;
>> + uint32_t ret = 0;
>> + ULONGEST t_bit = 0, insn_id = 0;
>> + gdb_byte buf[insn_size];
>> + insn_decode_record aarch64_record;
>> +
>> + memset (&buf[0], 0, insn_size);
>> + memset (&aarch64_record, 0, sizeof (insn_decode_record));
>> + target_read_memory (insn_addr, &buf[0], insn_size);
>> + aarch64_record.aarch64_insn = (uint32_t) extract_unsigned_integer (&buf[0],
>> + insn_size, gdbarch_byte_order (gdbarch));
>> + aarch64_record.regcache = regcache;
>> + aarch64_record.this_addr = insn_addr;
>> + aarch64_record.gdbarch = gdbarch;
>> +
>> + ret = aarch64_record_decode_insn_handler (&aarch64_record);
>> + if (ret == AARCH64_RECORD_UNSUPPORTED)
>> + {
>> + printf_unfiltered (_("Process record does not support instruction "
>> + "0x%0x at address %s.\n"),aarch64_record.aarch64_insn,
>> + paddress (gdbarch, insn_addr));
>> + ret = -1;
>> + }
>> +
>> + if (0 == ret)
>> + {
>> + /* Record registers. */
>> + record_full_arch_list_add_reg (aarch64_record.regcache, AARCH64_PC_REGNUM);
>> + if (aarch64_record.aarch64_regs)
>> + for (rec_no = 0; rec_no < aarch64_record.reg_rec_count; rec_no++)
>> + if (record_full_arch_list_add_reg (aarch64_record.regcache,
>> + aarch64_record.aarch64_regs[rec_no]))
>> + ret = -1;
>> +
>> + /* Record memories. */
>> + if (aarch64_record.aarch64_mems)
>> + for (rec_no = 0; rec_no < aarch64_record.mem_rec_count; rec_no++)
>> + if (record_full_arch_list_add_mem
>> + ((CORE_ADDR)aarch64_record.aarch64_mems[rec_no].addr,
>> + aarch64_record.aarch64_mems[rec_no].len))
>> + ret = -1;
>> +
>> + if (record_full_arch_list_add_end ())
>> + ret = -1;
>> + }
>> +
>> + deallocate_reg_mem (&aarch64_record);
>> + return ret;
>> +}
>> diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
>> index 78fb779..3dd3dcc 100644
>> --- a/gdb/aarch64-tdep.h
>> +++ b/gdb/aarch64-tdep.h
>> @@ -90,4 +90,7 @@ struct gdbarch_tdep
>> struct type *vnb_type;
>> };
>>
>> +extern int aarch64_process_record (struct gdbarch *gdbarch,
>> + struct regcache *regcache, CORE_ADDR addr);
>> +
>> #endif /* aarch64-tdep.h */
>> --
>> 1.9.1
>>
>
> Ping! Kindly help me approve this patch series.
ping!
On 14/10/2014 17:47, Omair Javaid wrote:
> On 19 September 2014 03:28, Omair Javaid <omair.javaid@linaro.org> wrote:
>> On 18 September 2014 05:09, Omair Javaid <omair.javaid@linaro.org> wrote:
>>> 2014-09-18 Omair Javaid <omair.javaid@linaro.org>
>>>
>>> * aarch64-linux-tdep.c (aarch64_linux_init_abi): Install AArch64
>>> process record handler.
>>> * aarch64-tdep.c (record.h): Include.
>>> (record-full.h): Include.
>>> (submask): New macro.
>>> (bit): New macro.
>>> (bits): New macro.
>>> (REG_ALLOC): New macro.
>>> (MEM_ALLOC): New macro.
>>> (struct aarch64_mem_r): Define.
>>> (aarch64_record_result): New enum.
>>> (struct insn_decode_record): Define.
>>> (insn_decode_record): New typedef.
>>> (aarch64_record_data_proc_reg): Add record handler for data processing
>>> register insns.
>>> (aarch64_record_data_proc_imm): Add record handler for data processing
>>> immediate insns.
>>> (aarch64_record_branch_except_sys): Add record handler for branch,
>>> exception and system insns.
>>> (aarch64_record_load_store): Add record handler for load/store insns.
>>> (aarch64_record_decode_insn_handler): Add record insn decoding function.
>>> (deallocate_reg_mem): Add memory cleanup function for record data.
>>> (aarch64_process_record): Add gdbarch handler for AArch64 process
>>> record.
>>> * aarch64-tdep.h (aarch64_process_record): New extern declaration.
>>> ---
>>> gdb/aarch64-linux-tdep.c | 3 +
>>> gdb/aarch64-tdep.c | 578 +++++++++++++++++++++++++++++++++++++++++++++++
>>> gdb/aarch64-tdep.h | 3 +
>>> 3 files changed, 584 insertions(+)
>>>
>>> diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
>>> index e5565a8..5ab7b37 100644
>>> --- a/gdb/aarch64-linux-tdep.c
>>> +++ b/gdb/aarch64-linux-tdep.c
>>> @@ -401,6 +401,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>>> set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
>>> set_gdbarch_stap_parse_special_token (gdbarch,
>>> aarch64_stap_parse_special_token);
>>> +
>>> + /* Reversible debugging, process record. */
>>> + set_gdbarch_process_record (gdbarch, aarch64_process_record);
>>> }
>>>
>>> /* Provide a prototype to silence -Wmissing-prototypes. */
>>> diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
>>> index 1898f6b..ed28f68 100644
>>> --- a/gdb/aarch64-tdep.c
>>> +++ b/gdb/aarch64-tdep.c
>>> @@ -50,6 +50,9 @@
>>>
>>> #include "vec.h"
>>>
>>> +#include "record.h"
>>> +#include "record-full.h"
>>> +
>>> #include "features/aarch64.c"
>>>
>>> /* Pseudo register base numbers. */
>>> @@ -2804,3 +2807,578 @@ When on, AArch64 specific debugging is enabled."),
>>> show_aarch64_debug,
>>> &setdebuglist, &showdebuglist);
>>> }
>>> +
>>> +/* AArch64 process record-replay related structures, defines etc. */
>>> +
>>> +#define submask(x) ((1L << ((x) + 1)) - 1)
>>> +#define bit(obj,st) (((obj) >> (st)) & 1)
>>> +#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
>>> +
>>> +#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
>>> + do \
>>> + { \
>>> + unsigned int reg_len = LENGTH; \
>>> + if (reg_len) \
>>> + { \
>>> + REGS = XNEWVEC (uint32_t, reg_len); \
>>> + memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
>>> + } \
>>> + } \
>>> + while (0)
>>> +
>>> +#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
>>> + do \
>>> + { \
>>> + unsigned int mem_len = LENGTH; \
>>> + if (mem_len) \
>>> + { \
>>> + MEMS = XNEWVEC (struct aarch64_mem_r, mem_len); \
>>> + memcpy(&MEMS->len, &RECORD_BUF[0], \
>>> + sizeof(struct aarch64_mem_r) * LENGTH); \
>>> + } \
>>> + } \
>>> + while (0)
>>> +
>>> +/* AArch64 memory record structure. */
>>> +struct aarch64_mem_r
>>> +{
>>> + uint64_t len; /* Record length. */
>>> + uint64_t addr; /* Memory address. */
>>> +};
>>> +
>>> +enum aarch64_record_result
>>> +{
>>> + AARCH64_RECORD_SUCCESS,
>>> + AARCH64_RECORD_FAILURE,
>>> + AARCH64_RECORD_UNSUPPORTED
>>> +};
>>> +
>>> +/* AArch64 instruction record contains opcode of current insn and execution
>>> + state (before entry to decode_insn()), contains list of to-be-modified
>>> + registers and memory blocks (on return from decode_insn()). */
>>> +
>>> +typedef struct insn_decode_record_t
>>> +{
>>> + struct gdbarch *gdbarch;
>>> + struct regcache *regcache;
>>> + CORE_ADDR this_addr;
>>> + uint32_t aarch64_insn;
>>> + uint32_t mem_rec_count;
>>> + uint32_t reg_rec_count;
>>> + uint32_t *aarch64_regs;
>>> + struct aarch64_mem_r *aarch64_mems;
>>> +} insn_decode_record;
>>> +
>>> +/* Record handler for data processing - register instructions. */
>>> +static unsigned int
>>> +aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
>>> +{
>>> + uint8_t reg_rd, insn_bits24_27, insn_bits21_23, setflags;
>>> + uint32_t record_buf[4];
>>> +
>>> + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>>> + insn_bits21_23 = bits (aarch64_insn_r->aarch64_insn, 21, 23);
>>> +
>>> + if (!bit (aarch64_insn_r->aarch64_insn, 28))
>>> + {
>>> + /* Logical (shifted register). */
>>> + if (insn_bits24_27 == 0x0a)
>>> + setflags = (bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03);
>>> + /* Add/subtract. */
>>> + else if (insn_bits24_27 == 0x0b)
>>> + setflags = bit (aarch64_insn_r->aarch64_insn, 29);
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + if (setflags)
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
>>> + }
>>> + else
>>> + {
>>> + if (insn_bits24_27 == 0x0b)
>>> + {
>>> + /* Data-processing (3 source). */
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (insn_bits24_27 == 0x0a)
>>> + {
>>> + if (insn_bits21_23 == 0x00)
>>> + {
>>> + /* Add/subtract (with carry). */
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + if (bit (aarch64_insn_r->aarch64_insn, 29))
>>> + {
>>> + record_buf[1] = AARCH64_CPSR_REGNUM;
>>> + aarch64_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else if (insn_bits21_23 == 0x02)
>>> + {
>>> + /* Conditional compare (register) / Conditional compare (immediate). */
>>> + record_buf[0] = AARCH64_CPSR_REGNUM;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (insn_bits21_23 == 0x04 || insn_bits21_23 == 0x06)
>>> + {
>>> + /* CConditional select. */
>>> + /* Data-processing (2 source). */
>>> + /* Data-processing (1 source). */
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> + }
>>> + }
>>> +
>>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>>> + record_buf);
>>> + return AARCH64_RECORD_SUCCESS;
>>> +}
>>> +
>>> +/* Record handler for data processing - immediate instructions. */
>>> +static unsigned int
>>> +aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
>>> +{
>>> + uint8_t reg_rd, insn_bit28, insn_bit23, insn_bits24_27, setflags;
>>> + uint32_t record_buf[4];
>>> +
>>> + reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>>> + insn_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
>>> + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
>>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>>> +
>>> + /* PC rel addressing / Move wide immediate / BitField / Extract. */
>>> + if (insn_bits24_27 == 0x00 || insn_bits24_27 == 0x03 ||
>>> + (insn_bits24_27 == 0x02 && insn_bit23))
>>> + {
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + else if (insn_bits24_27 == 0x01)
>>> + {
>>> + /* Add/Subtract (immediate). */
>>> + setflags = bit (aarch64_insn_r->aarch64_insn, 29);
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + if (setflags)
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
>>> + }
>>> + else if (insn_bits24_27 == 0x02 && !insn_bit23)
>>> + {
>>> + /* Logical (immediate). */
>>> + setflags = bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03;
>>> + record_buf[0] = reg_rd;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + if (setflags)
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
>>> + }
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>>> + record_buf);
>>> + return AARCH64_RECORD_SUCCESS;
>>> +}
>>> +
>>> +/* Record handler for branch, exception generation and system instructions. */
>>> +static unsigned int
>>> +aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
>>> +{
>>> + struct gdbarch_tdep *tdep = gdbarch_tdep (aarch64_insn_r->gdbarch);
>>> + uint8_t insn_bits24_27, insn_bits28_31, insn_bits22_23;
>>> + uint32_t record_buf[4];
>>> +
>>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>>> + insn_bits28_31 = bits (aarch64_insn_r->aarch64_insn, 28, 31);
>>> + insn_bits22_23 = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>>> +
>>> + if (insn_bits28_31 == 0x0d)
>>> + {
>>> + /* Exception generation instructions. */
>>> + if (insn_bits24_27 == 0x04)
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> + /* System instructions. */
>>> + else if (insn_bits24_27 == 0x05 && insn_bits22_23 == 0x00)
>>> + {
>>> + record_buf[0] = AARCH64_CPSR_REGNUM;
>>> + record_buf[1] = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>>> + aarch64_insn_r->reg_rec_count = 2;
>>> + }
>>> + else if((insn_bits24_27 & 0x0e) == 0x06)
>>> + {
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
>>> + if (bits (aarch64_insn_r->aarch64_insn, 21, 22) == 0x01)
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
>>> + }
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> + }
>>> + else if ((insn_bits28_31 & 0x07) == 0x01 && (insn_bits24_27 & 0x0c) == 0x04)
>>> + {
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
>>> + if (bit (aarch64_insn_r->aarch64_insn, 31))
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
>>> + }
>>> + else
>>> + /* All other types of branch instructions. */
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
>>> +
>>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>>> + record_buf);
>>> + return AARCH64_RECORD_SUCCESS;
>>> +}
>>> +
>>> +/* Record handler for load and store instructions. */
>>> +static unsigned int
>>> +aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
>>> +{
>>> + uint8_t insn_bits24_27, insn_bits28_29, insn_bits10_11;
>>> + uint8_t insn_bit23, insn_bit21;
>>> + uint8_t opc, size_bits, ld_flag, vector_flag;
>>> + uint32_t reg_rn, reg_rt, reg_rt2;
>>> + uint64_t datasize, offset;
>>> + uint32_t record_buf[8];
>>> + uint64_t record_buf_mem[8];
>>> + CORE_ADDR address;
>>> +
>>> + insn_bits10_11 = bits (aarch64_insn_r->aarch64_insn, 10, 11);
>>> + insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
>>> + insn_bits28_29 = bits (aarch64_insn_r->aarch64_insn, 28, 29);
>>> + insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21);
>>> + insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
>>> + ld_flag = bit (aarch64_insn_r->aarch64_insn, 22);
>>> + vector_flag = bit (aarch64_insn_r->aarch64_insn, 26);
>>> + reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4);
>>> + reg_rn = bits (aarch64_insn_r->aarch64_insn, 5, 9);
>>> + reg_rt2 = bits (aarch64_insn_r->aarch64_insn, 10, 14);
>>> + size_bits = bits (aarch64_insn_r->aarch64_insn, 30, 31);
>>> +
>>> + /* Load/store exclusive instructions decoding. */
>>> + if (insn_bits24_27 == 0x08 && insn_bits28_29 == 0x00)
>>> + {
>>> + if (ld_flag)
>>> + {
>>> + record_buf[0] = reg_rt;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + if (insn_bit21)
>>> + {
>>> + record_buf[1] = reg_rt2;
>>> + aarch64_insn_r->reg_rec_count = 2;
>>> + }
>>> + }
>>> + else
>>> + {
>>> + if (insn_bit21)
>>> + datasize = (8 << size_bits) * 2;
>>> + else
>>> + datasize = (8 << size_bits);
>>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>>> + &address);
>>> + record_buf_mem[0] = datasize / 8;
>>> + record_buf_mem[1] = address;
>>> + aarch64_insn_r->mem_rec_count = 1;
>>> + if (!insn_bit23)
>>> + {
>>> + /* Save register rs. */
>>> + record_buf[0] = bits (aarch64_insn_r->aarch64_insn, 16, 20);
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + }
>>> + }
>>> + /* Load register (literal) instructions decoding. */
>>> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x01)
>>> + {
>>> + if (vector_flag)
>>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>>> + else
>>> + record_buf[0] = reg_rt;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + /* All types of load/store pair instructions decoding. */
>>> + else if ((insn_bits24_27 & 0x0a) == 0x08 && insn_bits28_29 == 0x02)
>>> + {
>>> + if (ld_flag)
>>> + {
>>> + if (vector_flag)
>>> + {
>>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>>> + record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM;
>>> + }
>>> + else
>>> + {
>>> + record_buf[0] = reg_rt;
>>> + record_buf[1] = reg_rt2;
>>> + }
>>> + aarch64_insn_r->reg_rec_count = 2;
>>> + }
>>> + else
>>> + {
>>> + uint16_t imm7_off;
>>> + imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21);
>>> + if (!vector_flag)
>>> + size_bits = size_bits >> 1;
>>> + datasize = 8 << (2 + size_bits);
>>> + offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off;
>>> + offset = offset << (2 + size_bits);
>>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>>> + &address);
>>> + if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23))
>>> + {
>>> + if (imm7_off & 0x40)
>>> + address = address - offset;
>>> + else
>>> + address = address + offset;
>>> + }
>>> +
>>> + record_buf_mem[0] = datasize / 8;
>>> + record_buf_mem[1] = address;
>>> + record_buf_mem[2] = datasize / 8;
>>> + record_buf_mem[3] = address + (datasize / 8);
>>> + aarch64_insn_r->mem_rec_count = 2;
>>> + }
>>> + if (bit (aarch64_insn_r->aarch64_insn, 23))
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
>>> + }
>>> + /* Load/store register (unsigned immediate) instructions. */
>>> + else if ((insn_bits24_27 & 0x0b) == 0x09 && insn_bits28_29 == 0x03)
>>> + {
>>> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>>> + if (!(opc >> 1))
>>> + if (opc & 0x01)
>>> + ld_flag = 0x01;
>>> + else
>>> + ld_flag = 0x0;
>>> + else
>>> + if (size_bits != 0x03)
>>> + ld_flag = 0x01;
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + if (!ld_flag)
>>> + {
>>> + offset = bits (aarch64_insn_r->aarch64_insn, 10, 21);
>>> + datasize = 8 << size_bits;
>>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>>> + &address);
>>> + offset = offset << size_bits;
>>> + address = address + offset;
>>> +
>>> + record_buf_mem[0] = datasize >> 3;
>>> + record_buf_mem[1] = address;
>>> + aarch64_insn_r->mem_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + if (vector_flag)
>>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>>> + else
>>> + record_buf[0] = reg_rt;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + }
>>> + /* Load/store register (register offset) instructions. */
>>> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
>>> + insn_bits10_11 == 0x02 && insn_bit21)
>>> + {
>>> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>>> + if (!(opc >> 1))
>>> + if (opc & 0x01)
>>> + ld_flag = 0x01;
>>> + else
>>> + ld_flag = 0x0;
>>> + else
>>> + if (size_bits != 0x03)
>>> + ld_flag = 0x01;
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + if (!ld_flag)
>>> + {
>>> + uint64_t reg_rm_val;
>>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache,
>>> + bits (aarch64_insn_r->aarch64_insn, 16, 20), ®_rm_val);
>>> + if (bit (aarch64_insn_r->aarch64_insn, 12))
>>> + offset = reg_rm_val << size_bits;
>>> + else
>>> + offset = reg_rm_val;
>>> + datasize = 8 << size_bits;
>>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>>> + &address);
>>> + address = address + offset;
>>> + record_buf_mem[0] = datasize >> 3;
>>> + record_buf_mem[1] = address;
>>> + aarch64_insn_r->mem_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + if (vector_flag)
>>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>>> + else
>>> + record_buf[0] = reg_rt;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + }
>>> + /* Load/store register (immediate) instructions. */
>>> + else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
>>> + !insn_bit21)
>>> + {
>>> + opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
>>> + if (!(opc >> 1))
>>> + if (opc & 0x01)
>>> + ld_flag = 0x01;
>>> + else
>>> + ld_flag = 0x0;
>>> + else
>>> + if (size_bits != 0x03)
>>> + ld_flag = 0x01;
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + if (!ld_flag)
>>> + {
>>> + uint16_t imm9_off;
>>> + imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20);
>>> + offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off;
>>> + datasize = 8 << size_bits;
>>> + regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
>>> + &address);
>>> + if (insn_bits10_11 != 0x01)
>>> + {
>>> + if (imm9_off & 0x0100)
>>> + address = address - offset;
>>> + else
>>> + address = address + offset;
>>> + }
>>> + record_buf_mem[0] = datasize >> 3;
>>> + record_buf_mem[1] = address;
>>> + aarch64_insn_r->mem_rec_count = 1;
>>> + }
>>> + else
>>> + {
>>> + if (vector_flag)
>>> + record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
>>> + else
>>> + record_buf[0] = reg_rt;
>>> + aarch64_insn_r->reg_rec_count = 1;
>>> + }
>>> + if (insn_bits10_11 == 0x01 || insn_bits10_11 == 0x03)
>>> + record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
>>> + }
>>> + /* Advanced SIMD load/store instructions. */
>>> + else
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
>>> + record_buf_mem);
>>> + REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
>>> + record_buf);
>>> + return AARCH64_RECORD_SUCCESS;
>>> +}
>>> +/* Decodes insns type and invokes its record handler. */
>>> +
>>> +static unsigned int
>>> +aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r)
>>> +{
>>> + uint32_t ins_bit25, ins_bit26, ins_bit27, ins_bit28;
>>> +
>>> + ins_bit25 = bit (aarch64_insn_r->aarch64_insn, 25);
>>> + ins_bit26 = bit (aarch64_insn_r->aarch64_insn, 26);
>>> + ins_bit27 = bit (aarch64_insn_r->aarch64_insn, 27);
>>> + ins_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
>>> +
>>> + /* Data processing - immediate instructions. */
>>> + if (!ins_bit26 && !ins_bit27 && ins_bit28)
>>> + return aarch64_record_data_proc_imm (aarch64_insn_r);
>>> +
>>> + /* Branch, exception generation and system instructions. */
>>> + if (ins_bit26 && !ins_bit27 && ins_bit28)
>>> + return aarch64_record_branch_except_sys (aarch64_insn_r);
>>> +
>>> + /* Load and store instructions. */
>>> + if (!ins_bit25 && ins_bit27)
>>> + return aarch64_record_load_store (aarch64_insn_r);
>>> +
>>> + /* Data processing - register instructions. */
>>> + if (ins_bit25 && !ins_bit26 && ins_bit27)
>>> + return aarch64_record_data_proc_reg (aarch64_insn_r);
>>> +
>>> + /* Data processing - SIMD and floating point instructions. */
>>> + if (ins_bit25 && ins_bit26 && ins_bit27)
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +
>>> + return AARCH64_RECORD_UNSUPPORTED;
>>> +}
>>> +
>>> +/* Cleans up local record registers and memory allocations. */
>>> +
>>> +static void
>>> +deallocate_reg_mem (insn_decode_record *record)
>>> +{
>>> + xfree (record->aarch64_regs);
>>> + xfree (record->aarch64_mems);
>>> +}
>>> +
>>> +/* Parse the current instruction and record the values of the registers and
>>> + memory that will be changed in current instruction to record_arch_list
>>> + return -1 if something is wrong. */
>>> +
>>> +int
>>> +aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
>>> + CORE_ADDR insn_addr)
>>> +{
>>> + uint32_t rec_no = 0;
>>> + uint8_t insn_size = 4;
>>> + uint32_t ret = 0;
>>> + ULONGEST t_bit = 0, insn_id = 0;
>>> + gdb_byte buf[insn_size];
>>> + insn_decode_record aarch64_record;
>>> +
>>> + memset (&buf[0], 0, insn_size);
>>> + memset (&aarch64_record, 0, sizeof (insn_decode_record));
>>> + target_read_memory (insn_addr, &buf[0], insn_size);
>>> + aarch64_record.aarch64_insn = (uint32_t) extract_unsigned_integer (&buf[0],
>>> + insn_size, gdbarch_byte_order (gdbarch));
>>> + aarch64_record.regcache = regcache;
>>> + aarch64_record.this_addr = insn_addr;
>>> + aarch64_record.gdbarch = gdbarch;
>>> +
>>> + ret = aarch64_record_decode_insn_handler (&aarch64_record);
>>> + if (ret == AARCH64_RECORD_UNSUPPORTED)
>>> + {
>>> + printf_unfiltered (_("Process record does not support instruction "
>>> + "0x%0x at address %s.\n"),aarch64_record.aarch64_insn,
>>> + paddress (gdbarch, insn_addr));
>>> + ret = -1;
>>> + }
>>> +
>>> + if (0 == ret)
>>> + {
>>> + /* Record registers. */
>>> + record_full_arch_list_add_reg (aarch64_record.regcache, AARCH64_PC_REGNUM);
>>> + if (aarch64_record.aarch64_regs)
>>> + for (rec_no = 0; rec_no < aarch64_record.reg_rec_count; rec_no++)
>>> + if (record_full_arch_list_add_reg (aarch64_record.regcache,
>>> + aarch64_record.aarch64_regs[rec_no]))
>>> + ret = -1;
>>> +
>>> + /* Record memories. */
>>> + if (aarch64_record.aarch64_mems)
>>> + for (rec_no = 0; rec_no < aarch64_record.mem_rec_count; rec_no++)
>>> + if (record_full_arch_list_add_mem
>>> + ((CORE_ADDR)aarch64_record.aarch64_mems[rec_no].addr,
>>> + aarch64_record.aarch64_mems[rec_no].len))
>>> + ret = -1;
>>> +
>>> + if (record_full_arch_list_add_end ())
>>> + ret = -1;
>>> + }
>>> +
>>> + deallocate_reg_mem (&aarch64_record);
>>> + return ret;
>>> +}
>>> diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
>>> index 78fb779..3dd3dcc 100644
>>> --- a/gdb/aarch64-tdep.h
>>> +++ b/gdb/aarch64-tdep.h
>>> @@ -90,4 +90,7 @@ struct gdbarch_tdep
>>> struct type *vnb_type;
>>> };
>>>
>>> +extern int aarch64_process_record (struct gdbarch *gdbarch,
>>> + struct regcache *regcache, CORE_ADDR addr);
>>> +
>>> #endif /* aarch64-tdep.h */
>>> --
>>> 1.9.1
>>>
>>
>> Ping! Kindly help me approve this patch series.
>
> ping!
>
ping!
@@ -401,6 +401,9 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand);
set_gdbarch_stap_parse_special_token (gdbarch,
aarch64_stap_parse_special_token);
+
+ /* Reversible debugging, process record. */
+ set_gdbarch_process_record (gdbarch, aarch64_process_record);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
@@ -50,6 +50,9 @@
#include "vec.h"
+#include "record.h"
+#include "record-full.h"
+
#include "features/aarch64.c"
/* Pseudo register base numbers. */
@@ -2804,3 +2807,578 @@ When on, AArch64 specific debugging is enabled."),
show_aarch64_debug,
&setdebuglist, &showdebuglist);
}
+
+/* AArch64 process record-replay related structures, defines etc. */
+
+#define submask(x) ((1L << ((x) + 1)) - 1)
+#define bit(obj,st) (((obj) >> (st)) & 1)
+#define bits(obj,st,fn) (((obj) >> (st)) & submask ((fn) - (st)))
+
+#define REG_ALLOC(REGS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int reg_len = LENGTH; \
+ if (reg_len) \
+ { \
+ REGS = XNEWVEC (uint32_t, reg_len); \
+ memcpy(®S[0], &RECORD_BUF[0], sizeof(uint32_t)*LENGTH); \
+ } \
+ } \
+ while (0)
+
+#define MEM_ALLOC(MEMS, LENGTH, RECORD_BUF) \
+ do \
+ { \
+ unsigned int mem_len = LENGTH; \
+ if (mem_len) \
+ { \
+ MEMS = XNEWVEC (struct aarch64_mem_r, mem_len); \
+ memcpy(&MEMS->len, &RECORD_BUF[0], \
+ sizeof(struct aarch64_mem_r) * LENGTH); \
+ } \
+ } \
+ while (0)
+
+/* AArch64 memory record structure. */
+struct aarch64_mem_r
+{
+ uint64_t len; /* Record length. */
+ uint64_t addr; /* Memory address. */
+};
+
+enum aarch64_record_result
+{
+ AARCH64_RECORD_SUCCESS,
+ AARCH64_RECORD_FAILURE,
+ AARCH64_RECORD_UNSUPPORTED
+};
+
+/* AArch64 instruction record contains opcode of current insn and execution
+ state (before entry to decode_insn()), contains list of to-be-modified
+ registers and memory blocks (on return from decode_insn()). */
+
+typedef struct insn_decode_record_t
+{
+ struct gdbarch *gdbarch;
+ struct regcache *regcache;
+ CORE_ADDR this_addr;
+ uint32_t aarch64_insn;
+ uint32_t mem_rec_count;
+ uint32_t reg_rec_count;
+ uint32_t *aarch64_regs;
+ struct aarch64_mem_r *aarch64_mems;
+} insn_decode_record;
+
+/* Record handler for data processing - register instructions. */
+static unsigned int
+aarch64_record_data_proc_reg (insn_decode_record *aarch64_insn_r)
+{
+ uint8_t reg_rd, insn_bits24_27, insn_bits21_23, setflags;
+ uint32_t record_buf[4];
+
+ reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
+ insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
+ insn_bits21_23 = bits (aarch64_insn_r->aarch64_insn, 21, 23);
+
+ if (!bit (aarch64_insn_r->aarch64_insn, 28))
+ {
+ /* Logical (shifted register). */
+ if (insn_bits24_27 == 0x0a)
+ setflags = (bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03);
+ /* Add/subtract. */
+ else if (insn_bits24_27 == 0x0b)
+ setflags = bit (aarch64_insn_r->aarch64_insn, 29);
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ if (setflags)
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
+ }
+ else
+ {
+ if (insn_bits24_27 == 0x0b)
+ {
+ /* Data-processing (3 source). */
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ else if (insn_bits24_27 == 0x0a)
+ {
+ if (insn_bits21_23 == 0x00)
+ {
+ /* Add/subtract (with carry). */
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ if (bit (aarch64_insn_r->aarch64_insn, 29))
+ {
+ record_buf[1] = AARCH64_CPSR_REGNUM;
+ aarch64_insn_r->reg_rec_count = 2;
+ }
+ }
+ else if (insn_bits21_23 == 0x02)
+ {
+ /* Conditional compare (register) / Conditional compare (immediate). */
+ record_buf[0] = AARCH64_CPSR_REGNUM;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ else if (insn_bits21_23 == 0x04 || insn_bits21_23 == 0x06)
+ {
+ /* CConditional select. */
+ /* Data-processing (2 source). */
+ /* Data-processing (1 source). */
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+ }
+ }
+
+ REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
+ record_buf);
+ return AARCH64_RECORD_SUCCESS;
+}
+
+/* Record handler for data processing - immediate instructions. */
+static unsigned int
+aarch64_record_data_proc_imm (insn_decode_record *aarch64_insn_r)
+{
+ uint8_t reg_rd, insn_bit28, insn_bit23, insn_bits24_27, setflags;
+ uint32_t record_buf[4];
+
+ reg_rd = bits (aarch64_insn_r->aarch64_insn, 0, 4);
+ insn_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
+ insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
+ insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
+
+ /* PC rel addressing / Move wide immediate / BitField / Extract. */
+ if (insn_bits24_27 == 0x00 || insn_bits24_27 == 0x03 ||
+ (insn_bits24_27 == 0x02 && insn_bit23))
+ {
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ else if (insn_bits24_27 == 0x01)
+ {
+ /* Add/Subtract (immediate). */
+ setflags = bit (aarch64_insn_r->aarch64_insn, 29);
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ if (setflags)
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
+ }
+ else if (insn_bits24_27 == 0x02 && !insn_bit23)
+ {
+ /* Logical (immediate). */
+ setflags = bits (aarch64_insn_r->aarch64_insn, 29, 30) == 0x03;
+ record_buf[0] = reg_rd;
+ aarch64_insn_r->reg_rec_count = 1;
+ if (setflags)
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_CPSR_REGNUM;
+ }
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
+ record_buf);
+ return AARCH64_RECORD_SUCCESS;
+}
+
+/* Record handler for branch, exception generation and system instructions. */
+static unsigned int
+aarch64_record_branch_except_sys (insn_decode_record *aarch64_insn_r)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (aarch64_insn_r->gdbarch);
+ uint8_t insn_bits24_27, insn_bits28_31, insn_bits22_23;
+ uint32_t record_buf[4];
+
+ insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
+ insn_bits28_31 = bits (aarch64_insn_r->aarch64_insn, 28, 31);
+ insn_bits22_23 = bits (aarch64_insn_r->aarch64_insn, 22, 23);
+
+ if (insn_bits28_31 == 0x0d)
+ {
+ /* Exception generation instructions. */
+ if (insn_bits24_27 == 0x04)
+ return AARCH64_RECORD_UNSUPPORTED;
+ /* System instructions. */
+ else if (insn_bits24_27 == 0x05 && insn_bits22_23 == 0x00)
+ {
+ record_buf[0] = AARCH64_CPSR_REGNUM;
+ record_buf[1] = bits (aarch64_insn_r->aarch64_insn, 0, 4);
+ aarch64_insn_r->reg_rec_count = 2;
+ }
+ else if((insn_bits24_27 & 0x0e) == 0x06)
+ {
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
+ if (bits (aarch64_insn_r->aarch64_insn, 21, 22) == 0x01)
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
+ }
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+ }
+ else if ((insn_bits28_31 & 0x07) == 0x01 && (insn_bits24_27 & 0x0c) == 0x04)
+ {
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
+ if (bit (aarch64_insn_r->aarch64_insn, 31))
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_LR_REGNUM;
+ }
+ else
+ /* All other types of branch instructions. */
+ record_buf[aarch64_insn_r->reg_rec_count++] = AARCH64_PC_REGNUM;
+
+ REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
+ record_buf);
+ return AARCH64_RECORD_SUCCESS;
+}
+
+/* Record handler for load and store instructions. */
+static unsigned int
+aarch64_record_load_store (insn_decode_record *aarch64_insn_r)
+{
+ uint8_t insn_bits24_27, insn_bits28_29, insn_bits10_11;
+ uint8_t insn_bit23, insn_bit21;
+ uint8_t opc, size_bits, ld_flag, vector_flag;
+ uint32_t reg_rn, reg_rt, reg_rt2;
+ uint64_t datasize, offset;
+ uint32_t record_buf[8];
+ uint64_t record_buf_mem[8];
+ CORE_ADDR address;
+
+ insn_bits10_11 = bits (aarch64_insn_r->aarch64_insn, 10, 11);
+ insn_bits24_27 = bits (aarch64_insn_r->aarch64_insn, 24, 27);
+ insn_bits28_29 = bits (aarch64_insn_r->aarch64_insn, 28, 29);
+ insn_bit21 = bit (aarch64_insn_r->aarch64_insn, 21);
+ insn_bit23 = bit (aarch64_insn_r->aarch64_insn, 23);
+ ld_flag = bit (aarch64_insn_r->aarch64_insn, 22);
+ vector_flag = bit (aarch64_insn_r->aarch64_insn, 26);
+ reg_rt = bits (aarch64_insn_r->aarch64_insn, 0, 4);
+ reg_rn = bits (aarch64_insn_r->aarch64_insn, 5, 9);
+ reg_rt2 = bits (aarch64_insn_r->aarch64_insn, 10, 14);
+ size_bits = bits (aarch64_insn_r->aarch64_insn, 30, 31);
+
+ /* Load/store exclusive instructions decoding. */
+ if (insn_bits24_27 == 0x08 && insn_bits28_29 == 0x00)
+ {
+ if (ld_flag)
+ {
+ record_buf[0] = reg_rt;
+ aarch64_insn_r->reg_rec_count = 1;
+ if (insn_bit21)
+ {
+ record_buf[1] = reg_rt2;
+ aarch64_insn_r->reg_rec_count = 2;
+ }
+ }
+ else
+ {
+ if (insn_bit21)
+ datasize = (8 << size_bits) * 2;
+ else
+ datasize = (8 << size_bits);
+ regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+ &address);
+ record_buf_mem[0] = datasize / 8;
+ record_buf_mem[1] = address;
+ aarch64_insn_r->mem_rec_count = 1;
+ if (!insn_bit23)
+ {
+ /* Save register rs. */
+ record_buf[0] = bits (aarch64_insn_r->aarch64_insn, 16, 20);
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ }
+ }
+ /* Load register (literal) instructions decoding. */
+ else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x01)
+ {
+ if (vector_flag)
+ record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+ else
+ record_buf[0] = reg_rt;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ /* All types of load/store pair instructions decoding. */
+ else if ((insn_bits24_27 & 0x0a) == 0x08 && insn_bits28_29 == 0x02)
+ {
+ if (ld_flag)
+ {
+ if (vector_flag)
+ {
+ record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+ record_buf[1] = reg_rt2 + AARCH64_V0_REGNUM;
+ }
+ else
+ {
+ record_buf[0] = reg_rt;
+ record_buf[1] = reg_rt2;
+ }
+ aarch64_insn_r->reg_rec_count = 2;
+ }
+ else
+ {
+ uint16_t imm7_off;
+ imm7_off = bits (aarch64_insn_r->aarch64_insn, 15, 21);
+ if (!vector_flag)
+ size_bits = size_bits >> 1;
+ datasize = 8 << (2 + size_bits);
+ offset = (imm7_off & 0x40) ? (~imm7_off & 0x007f) + 1 : imm7_off;
+ offset = offset << (2 + size_bits);
+ regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+ &address);
+ if (!((insn_bits24_27 & 0x0b) == 0x08 && insn_bit23))
+ {
+ if (imm7_off & 0x40)
+ address = address - offset;
+ else
+ address = address + offset;
+ }
+
+ record_buf_mem[0] = datasize / 8;
+ record_buf_mem[1] = address;
+ record_buf_mem[2] = datasize / 8;
+ record_buf_mem[3] = address + (datasize / 8);
+ aarch64_insn_r->mem_rec_count = 2;
+ }
+ if (bit (aarch64_insn_r->aarch64_insn, 23))
+ record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
+ }
+ /* Load/store register (unsigned immediate) instructions. */
+ else if ((insn_bits24_27 & 0x0b) == 0x09 && insn_bits28_29 == 0x03)
+ {
+ opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
+ if (!(opc >> 1))
+ if (opc & 0x01)
+ ld_flag = 0x01;
+ else
+ ld_flag = 0x0;
+ else
+ if (size_bits != 0x03)
+ ld_flag = 0x01;
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ if (!ld_flag)
+ {
+ offset = bits (aarch64_insn_r->aarch64_insn, 10, 21);
+ datasize = 8 << size_bits;
+ regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+ &address);
+ offset = offset << size_bits;
+ address = address + offset;
+
+ record_buf_mem[0] = datasize >> 3;
+ record_buf_mem[1] = address;
+ aarch64_insn_r->mem_rec_count = 1;
+ }
+ else
+ {
+ if (vector_flag)
+ record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+ else
+ record_buf[0] = reg_rt;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ }
+ /* Load/store register (register offset) instructions. */
+ else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
+ insn_bits10_11 == 0x02 && insn_bit21)
+ {
+ opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
+ if (!(opc >> 1))
+ if (opc & 0x01)
+ ld_flag = 0x01;
+ else
+ ld_flag = 0x0;
+ else
+ if (size_bits != 0x03)
+ ld_flag = 0x01;
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ if (!ld_flag)
+ {
+ uint64_t reg_rm_val;
+ regcache_raw_read_unsigned (aarch64_insn_r->regcache,
+ bits (aarch64_insn_r->aarch64_insn, 16, 20), ®_rm_val);
+ if (bit (aarch64_insn_r->aarch64_insn, 12))
+ offset = reg_rm_val << size_bits;
+ else
+ offset = reg_rm_val;
+ datasize = 8 << size_bits;
+ regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+ &address);
+ address = address + offset;
+ record_buf_mem[0] = datasize >> 3;
+ record_buf_mem[1] = address;
+ aarch64_insn_r->mem_rec_count = 1;
+ }
+ else
+ {
+ if (vector_flag)
+ record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+ else
+ record_buf[0] = reg_rt;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ }
+ /* Load/store register (immediate) instructions. */
+ else if ((insn_bits24_27 & 0x0b) == 0x08 && insn_bits28_29 == 0x03 &&
+ !insn_bit21)
+ {
+ opc = bits (aarch64_insn_r->aarch64_insn, 22, 23);
+ if (!(opc >> 1))
+ if (opc & 0x01)
+ ld_flag = 0x01;
+ else
+ ld_flag = 0x0;
+ else
+ if (size_bits != 0x03)
+ ld_flag = 0x01;
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ if (!ld_flag)
+ {
+ uint16_t imm9_off;
+ imm9_off = bits (aarch64_insn_r->aarch64_insn, 12, 20);
+ offset = (imm9_off & 0x0100) ? (((~imm9_off) & 0x01ff) + 1) : imm9_off;
+ datasize = 8 << size_bits;
+ regcache_raw_read_unsigned (aarch64_insn_r->regcache, reg_rn,
+ &address);
+ if (insn_bits10_11 != 0x01)
+ {
+ if (imm9_off & 0x0100)
+ address = address - offset;
+ else
+ address = address + offset;
+ }
+ record_buf_mem[0] = datasize >> 3;
+ record_buf_mem[1] = address;
+ aarch64_insn_r->mem_rec_count = 1;
+ }
+ else
+ {
+ if (vector_flag)
+ record_buf[0] = reg_rt + AARCH64_V0_REGNUM;
+ else
+ record_buf[0] = reg_rt;
+ aarch64_insn_r->reg_rec_count = 1;
+ }
+ if (insn_bits10_11 == 0x01 || insn_bits10_11 == 0x03)
+ record_buf[aarch64_insn_r->reg_rec_count++] = reg_rn;
+ }
+ /* Advanced SIMD load/store instructions. */
+ else
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ MEM_ALLOC (aarch64_insn_r->aarch64_mems, aarch64_insn_r->mem_rec_count,
+ record_buf_mem);
+ REG_ALLOC (aarch64_insn_r->aarch64_regs, aarch64_insn_r->reg_rec_count,
+ record_buf);
+ return AARCH64_RECORD_SUCCESS;
+}
+/* Decodes insns type and invokes its record handler. */
+
+static unsigned int
+aarch64_record_decode_insn_handler (insn_decode_record *aarch64_insn_r)
+{
+ uint32_t ins_bit25, ins_bit26, ins_bit27, ins_bit28;
+
+ ins_bit25 = bit (aarch64_insn_r->aarch64_insn, 25);
+ ins_bit26 = bit (aarch64_insn_r->aarch64_insn, 26);
+ ins_bit27 = bit (aarch64_insn_r->aarch64_insn, 27);
+ ins_bit28 = bit (aarch64_insn_r->aarch64_insn, 28);
+
+ /* Data processing - immediate instructions. */
+ if (!ins_bit26 && !ins_bit27 && ins_bit28)
+ return aarch64_record_data_proc_imm (aarch64_insn_r);
+
+ /* Branch, exception generation and system instructions. */
+ if (ins_bit26 && !ins_bit27 && ins_bit28)
+ return aarch64_record_branch_except_sys (aarch64_insn_r);
+
+ /* Load and store instructions. */
+ if (!ins_bit25 && ins_bit27)
+ return aarch64_record_load_store (aarch64_insn_r);
+
+ /* Data processing - register instructions. */
+ if (ins_bit25 && !ins_bit26 && ins_bit27)
+ return aarch64_record_data_proc_reg (aarch64_insn_r);
+
+ /* Data processing - SIMD and floating point instructions. */
+ if (ins_bit25 && ins_bit26 && ins_bit27)
+ return AARCH64_RECORD_UNSUPPORTED;
+
+ return AARCH64_RECORD_UNSUPPORTED;
+}
+
+/* Cleans up local record registers and memory allocations. */
+
+static void
+deallocate_reg_mem (insn_decode_record *record)
+{
+ xfree (record->aarch64_regs);
+ xfree (record->aarch64_mems);
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to record_arch_list
+ return -1 if something is wrong. */
+
+int
+aarch64_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR insn_addr)
+{
+ uint32_t rec_no = 0;
+ uint8_t insn_size = 4;
+ uint32_t ret = 0;
+ ULONGEST t_bit = 0, insn_id = 0;
+ gdb_byte buf[insn_size];
+ insn_decode_record aarch64_record;
+
+ memset (&buf[0], 0, insn_size);
+ memset (&aarch64_record, 0, sizeof (insn_decode_record));
+ target_read_memory (insn_addr, &buf[0], insn_size);
+ aarch64_record.aarch64_insn = (uint32_t) extract_unsigned_integer (&buf[0],
+ insn_size, gdbarch_byte_order (gdbarch));
+ aarch64_record.regcache = regcache;
+ aarch64_record.this_addr = insn_addr;
+ aarch64_record.gdbarch = gdbarch;
+
+ ret = aarch64_record_decode_insn_handler (&aarch64_record);
+ if (ret == AARCH64_RECORD_UNSUPPORTED)
+ {
+ printf_unfiltered (_("Process record does not support instruction "
+ "0x%0x at address %s.\n"),aarch64_record.aarch64_insn,
+ paddress (gdbarch, insn_addr));
+ ret = -1;
+ }
+
+ if (0 == ret)
+ {
+ /* Record registers. */
+ record_full_arch_list_add_reg (aarch64_record.regcache, AARCH64_PC_REGNUM);
+ if (aarch64_record.aarch64_regs)
+ for (rec_no = 0; rec_no < aarch64_record.reg_rec_count; rec_no++)
+ if (record_full_arch_list_add_reg (aarch64_record.regcache,
+ aarch64_record.aarch64_regs[rec_no]))
+ ret = -1;
+
+ /* Record memories. */
+ if (aarch64_record.aarch64_mems)
+ for (rec_no = 0; rec_no < aarch64_record.mem_rec_count; rec_no++)
+ if (record_full_arch_list_add_mem
+ ((CORE_ADDR)aarch64_record.aarch64_mems[rec_no].addr,
+ aarch64_record.aarch64_mems[rec_no].len))
+ ret = -1;
+
+ if (record_full_arch_list_add_end ())
+ ret = -1;
+ }
+
+ deallocate_reg_mem (&aarch64_record);
+ return ret;
+}
@@ -90,4 +90,7 @@ struct gdbarch_tdep
struct type *vnb_type;
};
+extern int aarch64_process_record (struct gdbarch *gdbarch,
+ struct regcache *regcache, CORE_ADDR addr);
+
#endif /* aarch64-tdep.h */