target/aarch64: a64 disassembler 04/5004/5
authorMete Balci <metebalci@gmail.com>
Sat, 30 Mar 2019 11:27:57 +0000 (12:27 +0100)
committerAntonio Borneo <borneo.antonio@gmail.com>
Sat, 3 Oct 2020 10:21:15 +0000 (11:21 +0100)
Add A64 (AArch64) Disassembler using Capstone framework.

Change-Id: Ia92b57001843b11a818af940a468b131e42a03fd
Signed-off-by: Mete Balci <metebalci@gmail.com>
[Antonio Borneo: Rebased on current HEAD]
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/5004
Tested-by: jenkins
doc/openocd.texi
src/target/Makefile.am
src/target/a64_disassembler.c [new file with mode: 0644]
src/target/a64_disassembler.h [new file with mode: 0644]
src/target/aarch64.c

index 8c99228c3f990595893942bf0d00a92862ce6e4f..317f188d2dc0b7fd816d14623a4645b3156928fb 100644 (file)
@@ -9349,6 +9349,12 @@ target code relies on. In a configuration file, the command would typically be c
 However, normally it is not necessary to use the command at all.
 @end deffn
 
+@deffn Command {aarch64 disassemble} address [count]
+@cindex disassemble
+Disassembles @var{count} instructions starting at @var{address}.
+If @var{count} is not specified, a single instruction is disassembled.
+@end deffn
+
 @deffn Command {aarch64 smp} [on|off]
 Display, enable or disable SMP handling mode. The state of SMP handling influences the way targets in an SMP group
 are handled by the run control. With SMP handling enabled, issuing halt or resume to one core will trigger
index 724f38c24415c8c49a41d145f7b71ba1dd353d0e..19ba7714e1555a1320c7daad18724e74be4b4062 100644 (file)
@@ -89,6 +89,7 @@ ARMV8_SRC = \
        %D%/armv8_dpm.c \
        %D%/armv8_opcodes.c \
        %D%/aarch64.c \
+       %D%/a64_disassembler.c \
        %D%/armv8.c \
        %D%/armv8_cache.c
 
@@ -176,6 +177,7 @@ ARC_SRC = \
        %D%/armv7a_cache_l2x.h \
        %D%/armv7a_mmu.h \
        %D%/arm_disassembler.h \
+       %D%/a64_disassembler.h \
        %D%/arm_opcodes.h \
        %D%/arm_simulator.h \
        %D%/arm_semihosting.h \
diff --git a/src/target/a64_disassembler.c b/src/target/a64_disassembler.c
new file mode 100644 (file)
index 0000000..bd78129
--- /dev/null
@@ -0,0 +1,145 @@
+/***************************************************************************
+ *   Copyright (C) 2019 by Mete Balci                                      *
+ *   metebalci@gmail.com                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <helper/log.h>
+#include "target.h"
+#include "a64_disassembler.h"
+
+#if HAVE_CAPSTONE
+
+#include <capstone/capstone.h>
+
+static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
+{
+       uint32_t opcode = 0;
+
+       memcpy(&opcode, insn->bytes, insn->size);
+
+       if (insn->size == 4) {
+
+               uint16_t opcode_high = opcode >> 16;
+
+               opcode = opcode & 0xffff;
+
+               command_print(cmd,
+                               "0x%08" PRIx64"  %04x %04x\t%s\t%s",
+                               insn->address,
+                               opcode,
+                               opcode_high,
+                               insn->mnemonic,
+                               insn->op_str);
+
+       } else {
+
+               command_print(
+                               cmd,
+                               "0x%08" PRIx64"  %04x\t%s\t%s",
+                               insn->address,
+                               opcode,
+                               insn->mnemonic,
+                               insn->op_str);
+
+       }
+}
+
+int a64_disassemble(struct command_invocation *cmd, struct target *target, target_addr_t address, size_t count)
+{
+       int ret;
+       int csret;
+       csh handle;
+
+       csret = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &handle);
+
+       if (csret != CS_ERR_OK) {
+
+               LOG_ERROR("cs_open() failed: %s", cs_strerror(csret));
+               return ERROR_FAIL;
+
+       }
+
+       csret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
+
+       if (csret != CS_ERR_OK) {
+
+               LOG_ERROR("cs_option() failed: %s", cs_strerror(csret));
+               cs_close(&handle);
+               return ERROR_FAIL;
+
+       }
+
+       cs_insn *insn = cs_malloc(handle);
+
+       if (csret != CS_ERR_OK) {
+
+               LOG_ERROR("cs_malloc() failed: %s", cs_strerror(csret));
+               cs_close(&handle);
+               return ERROR_FAIL;
+
+       }
+
+       while (count > 0) {
+
+               uint8_t buffer[4];
+
+               ret = target_read_buffer(target, address, sizeof(buffer), buffer);
+
+               if (ret != ERROR_OK) {
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ret;
+               }
+
+               size_t size = sizeof(buffer);
+               const uint8_t *tmp = buffer;
+
+               ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
+
+               if (!ret) {
+
+                       LOG_ERROR("cs_disasm_iter() failed: %s", cs_strerror(cs_errno(handle)));
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ERROR_FAIL;
+
+               }
+
+               print_opcode(cmd, insn);
+               count--;
+
+       }
+
+       cs_free(insn, 1);
+       cs_close(&handle);
+
+       return ERROR_OK;
+}
+
+#else
+
+int a64_disassemble(struct command_invocation *cmd, struct target *target, target_addr_t address, size_t count)
+{
+       command_print(cmd, "capstone disassembly framework required");
+
+       return ERROR_FAIL;
+}
+
+#endif
diff --git a/src/target/a64_disassembler.h b/src/target/a64_disassembler.h
new file mode 100644 (file)
index 0000000..5c58bbf
--- /dev/null
@@ -0,0 +1,30 @@
+/***************************************************************************
+ *   Copyright (C) 2019 by Mete Balci                                      *
+ *   metebalci@gmail.com                                                   *
+ *                                                                         *
+ *   This program is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU General Public License as published by  *
+ *   the Free Software Foundation; either version 2 of the License, or     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
+ ***************************************************************************/
+
+#ifndef OPENOCD_TARGET_AARCH64_DISASSEMBLER_H
+#define OPENOCD_TARGET_AARCH64_DISASSEMBLER_H
+
+#include "target.h"
+
+int a64_disassemble(
+               struct command_invocation *cmd,
+               struct target *target,
+               target_addr_t address,
+               size_t count);
+
+#endif /* OPENOCD_TARGET_AARCH64_DISASSEMBLER_H */
index 4febc8c96c4c221a396367f9fbc2bd933095585a..dee16d116130c90997fe88bcc8bcdfde15ec229b 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "breakpoints.h"
 #include "aarch64.h"
+#include "a64_disassembler.h"
 #include "register.h"
 #include "target_request.h"
 #include "target_type.h"
@@ -2566,7 +2567,6 @@ COMMAND_HANDLER(aarch64_handle_cache_info_command)
                        &armv8->armv8_mmu.armv8_cache);
 }
 
-
 COMMAND_HANDLER(aarch64_handle_dbginit_command)
 {
        struct target *target = get_current_target(CMD_CTX);
@@ -2578,6 +2578,39 @@ COMMAND_HANDLER(aarch64_handle_dbginit_command)
        return aarch64_init_debug_access(target);
 }
 
+COMMAND_HANDLER(aarch64_handle_disassemble_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+
+       if (target == NULL) {
+               LOG_ERROR("No target selected");
+               return ERROR_FAIL;
+       }
+
+       struct aarch64_common *aarch64 = target_to_aarch64(target);
+
+       if (aarch64->common_magic != AARCH64_COMMON_MAGIC) {
+               command_print(CMD, "current target isn't an AArch64");
+               return ERROR_FAIL;
+       }
+
+       int count = 1;
+       target_addr_t address;
+
+       switch (CMD_ARGC) {
+               case 2:
+                       COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count);
+               /* FALL THROUGH */
+               case 1:
+                       COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address);
+                       break;
+               default:
+                       return ERROR_COMMAND_SYNTAX_ERROR;
+       }
+
+       return a64_disassemble(CMD, target, address, count);
+}
+
 COMMAND_HANDLER(aarch64_mask_interrupts_command)
 {
        struct target *target = get_current_target(CMD_CTX);
@@ -2758,6 +2791,13 @@ static const struct command_registration aarch64_exec_command_handlers[] = {
                .help = "Initialize core debug",
                .usage = "",
        },
+       {
+               .name = "disassemble",
+               .handler = aarch64_handle_disassemble_command,
+               .mode = COMMAND_EXEC,
+               .help = "Disassemble instructions",
+               .usage = "address [count]",
+       },
        {
                .name = "maskisr",
                .handler = aarch64_mask_interrupts_command,

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)