From patchwork Wed Jun 4 16:21:08 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Omair Javaid X-Patchwork-Id: 31382 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f70.google.com (mail-oa0-f70.google.com [209.85.219.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 68193203AC for ; Wed, 4 Jun 2014 16:22:01 +0000 (UTC) Received: by mail-oa0-f70.google.com with SMTP id g18sf44558871oah.9 for ; Wed, 04 Jun 2014 09:22:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:mailing-list :precedence:list-id:list-unsubscribe:list-subscribe:list-archive :list-post:list-help:sender:delivered-to:from:to:cc:subject:date :message-id:in-reply-to:references:x-original-sender :x-original-authentication-results; bh=VcGfp51N9erqtsa8BxdXv6jOox5RdnlNQkE4LyOGqLc=; b=QxwePL1ej5rrTwTjxbOXijpenYnnAlMBNC4Badwm93+FIGJCuxSQLB7CJ2bg9wgEC9 m4MGffjKZUx4DGSelul8XvH/k0sfdDP9Y9tEXF7TOsT6OrUMlJkNR2K7mRl7Y5rtnYjo mUNK4MBG4uI9KHa12i+kukWAu8x6/r0o8QEXhIyDBWpgVW6lRMRoRAPeuYrTEmpOfkuP 7IcrAtCMQAWF08DjZOyiozJy2uGjKsaZyYU30yhKHpWn10j6oFz51WHm/fuWHnQ3tHfx KxqJ5sKrZnhtQH+gvqyRq4H3hOABHLJ6DFVFLvTc/NPCgwnZeSFWXt5IBIu0498IQDo/ JHGA== X-Gm-Message-State: ALoCoQmfSfxvsnHKKVUqSDuGpbFTogX+IAcQxKF/1/0AiFPe47AF01/x9FK86568hBj07zi6gzTn X-Received: by 10.182.19.35 with SMTP id b3mr23332149obe.12.1401898920891; Wed, 04 Jun 2014 09:22:00 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.101.247 with SMTP id u110ls3243130qge.79.gmail; Wed, 04 Jun 2014 09:22:00 -0700 (PDT) X-Received: by 10.221.50.70 with SMTP id vd6mr3577967vcb.51.1401898920630; Wed, 04 Jun 2014 09:22:00 -0700 (PDT) Received: from mail-vc0-x235.google.com (mail-vc0-x235.google.com [2607:f8b0:400c:c03::235]) by mx.google.com with ESMTPS id rv2si1989224vdb.88.2014.06.04.09.22.00 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 04 Jun 2014 09:22:00 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c03::235 as permitted sender) client-ip=2607:f8b0:400c:c03::235; Received: by mail-vc0-f181.google.com with SMTP id hq11so6933191vcb.12 for ; Wed, 04 Jun 2014 09:22:00 -0700 (PDT) X-Received: by 10.53.8.162 with SMTP id dl2mr27909470vdd.24.1401898920456; Wed, 04 Jun 2014 09:22:00 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.54.6 with SMTP id vs6csp57844vcb; Wed, 4 Jun 2014 09:22:00 -0700 (PDT) X-Received: by 10.58.30.1 with SMTP id o1mr16907888veh.37.1401898919905; Wed, 04 Jun 2014 09:21:59 -0700 (PDT) Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id gu3si6704595pbb.232.2014.06.04.09.21.59 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 04 Jun 2014 09:21:59 -0700 (PDT) Received-SPF: pass (google.com: domain of gdb-patches-return-113109-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Received: (qmail 3658 invoked by alias); 4 Jun 2014 16:21:46 -0000 Mailing-List: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org Precedence: list List-Id: List-Unsubscribe: , List-Subscribe: List-Archive: List-Post: , List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 3593 invoked by uid 89); 4 Jun 2014 16:21:45 -0000 X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-wi0-f180.google.com Received: from mail-wi0-f180.google.com (HELO mail-wi0-f180.google.com) (209.85.212.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Wed, 04 Jun 2014 16:21:42 +0000 Received: by mail-wi0-f180.google.com with SMTP id hi2so1820842wib.7 for ; Wed, 04 Jun 2014 09:21:38 -0700 (PDT) X-Received: by 10.194.179.9 with SMTP id dc9mr6467623wjc.74.1401898898367; Wed, 04 Jun 2014 09:21:38 -0700 (PDT) Received: from localhost.localdomain ([182.185.152.186]) by mx.google.com with ESMTPSA id um7sm2677062wjc.12.2014.06.04.09.21.35 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 04 Jun 2014 09:21:37 -0700 (PDT) From: Omair Javaid To: gdb-patches@sourceware.org Cc: Omair Javaid Subject: [PATCH 4/7] Implements aarch64 process record and reverse debugging support Date: Wed, 4 Jun 2014 21:21:08 +0500 Message-Id: <1401898871-2270-5-git-send-email-omair.javaid@linaro.org> In-Reply-To: <1401898871-2270-1-git-send-email-omair.javaid@linaro.org> References: <1401898871-2270-1-git-send-email-omair.javaid@linaro.org> X-IsSubscribed: yes X-Original-Sender: omair.javaid@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 2607:f8b0:400c:c03::235 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org; dkim=pass header.i=@sourceware.org X-Google-Group-Id: 836684582541 This patch defines structures, macros and functions required for process record and reverse debugging support on aarch64-linux targets. Also implements support for recording most if not all of instructions from a64 instruction set. gdb: 2014-06-04 Omair Javaid * aarch64-linux-tdep.c (aarch64_linux_init_abi): Updated. * aarch64-tdep.c (record.h): Include. (record-full.h): Include. (aarch64_record_data_proc_reg): New function. (aarch64_record_data_proc_imm): New function. (aarch64_record_branch_except_sys): New function. (aarch64_record_load_store): New function. (aarch64_record_decode_insn_handler): New function. (deallocate_reg_mem): New function. (aarch64_process_record): New function. * aarch64-tdep.h (submask): New macro. (bit): New macro. (bits): New macro. (REG_ALLOC): New macro. (MEM_ALLOC): New macro. (struct aarch64_mem_r): Defined. (aarch64_record_result): New enum. (struct insn_decode_record): Defined. (insn_decode_record): New typedef. (aarch64_process_record): New extern declaration. --- gdb/aarch64-linux-tdep.c | 3 + gdb/aarch64-tdep.c | 517 +++++++++++++++++++++++++++++++++++++++++++++++ gdb/aarch64-tdep.h | 65 ++++++ 3 files changed, 585 insertions(+) diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index b285818..dece0c3 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -468,6 +468,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 4abe36e..bb533b2 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -52,6 +52,9 @@ #include "gdb_assert.h" #include "vec.h" +#include "record.h" +#include "record-full.h" + #include "features/aarch64.c" /* Pseudo register base numbers. */ @@ -2806,3 +2809,517 @@ When on, AArch64 specific debugging is enabled."), show_aarch64_debug, &setdebuglist, &showdebuglist); } + +/* 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_USUPPORTED; + + 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_USUPPORTED; + } + } + + 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_USUPPORTED; + + 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_USUPPORTED; + /* 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_USUPPORTED; + } + 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_USUPPORTED; + + 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_USUPPORTED; + + 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_USUPPORTED; + + 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_USUPPORTED; + + 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 thumb2 instruction 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_USUPPORTED; + + return AARCH64_RECORD_USUPPORTED; +} + +/* 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_USUPPORTED) + { + 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..8a193f4 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -90,4 +90,69 @@ struct gdbarch_tdep struct type *vnb_type; }; +/* 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) + +/* ARM 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_USUPPORTED +}; + +/* ARM 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; + +extern int aarch64_process_record (struct gdbarch *gdbarch, + struct regcache *regcache, CORE_ADDR addr); + #endif /* aarch64-tdep.h */