--- /dev/null
+/***************************************************************************
+ * 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