target/aarch64: a64 disassembler

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
This commit is contained in:
Mete Balci
2019-03-30 12:27:57 +01:00
committed by Antonio Borneo
parent a31e579e87
commit d7d70c2719
5 changed files with 224 additions and 1 deletions

View 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 \

View File

@@ -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

View File

@@ -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 */

View 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,