openocd: src/target: replace the GPL-2.0-or-later license tag
[fw/openocd] / src / target / a64_disassembler.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2019 by Mete Balci                                      *
5  *   metebalci@gmail.com                                                   *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
12 #include <helper/log.h>
13 #include "target.h"
14 #include "a64_disassembler.h"
15
16 #if HAVE_CAPSTONE
17
18 #include <capstone.h>
19
20 static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
21 {
22         uint32_t opcode = 0;
23
24         memcpy(&opcode, insn->bytes, insn->size);
25
26         if (insn->size == 4) {
27
28                 uint16_t opcode_high = opcode >> 16;
29
30                 opcode = opcode & 0xffff;
31
32                 command_print(cmd,
33                                 "0x%08" PRIx64"  %04x %04x\t%s\t%s",
34                                 insn->address,
35                                 opcode,
36                                 opcode_high,
37                                 insn->mnemonic,
38                                 insn->op_str);
39
40         } else {
41
42                 command_print(
43                                 cmd,
44                                 "0x%08" PRIx64"  %04x\t%s\t%s",
45                                 insn->address,
46                                 opcode,
47                                 insn->mnemonic,
48                                 insn->op_str);
49
50         }
51 }
52
53 int a64_disassemble(struct command_invocation *cmd, struct target *target, target_addr_t address, size_t count)
54 {
55         int ret;
56         int csret;
57         csh handle;
58
59         csret = cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, &handle);
60
61         if (csret != CS_ERR_OK) {
62
63                 LOG_ERROR("cs_open() failed: %s", cs_strerror(csret));
64                 return ERROR_FAIL;
65
66         }
67
68         csret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
69
70         if (csret != CS_ERR_OK) {
71
72                 LOG_ERROR("cs_option() failed: %s", cs_strerror(csret));
73                 cs_close(&handle);
74                 return ERROR_FAIL;
75
76         }
77
78         cs_insn *insn = cs_malloc(handle);
79
80         if (csret != CS_ERR_OK) {
81
82                 LOG_ERROR("cs_malloc() failed: %s", cs_strerror(csret));
83                 cs_close(&handle);
84                 return ERROR_FAIL;
85
86         }
87
88         while (count > 0) {
89
90                 uint8_t buffer[4];
91
92                 ret = target_read_buffer(target, address, sizeof(buffer), buffer);
93
94                 if (ret != ERROR_OK) {
95                         cs_free(insn, 1);
96                         cs_close(&handle);
97                         return ret;
98                 }
99
100                 size_t size = sizeof(buffer);
101                 const uint8_t *tmp = buffer;
102
103                 ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
104
105                 if (!ret) {
106
107                         LOG_ERROR("cs_disasm_iter() failed: %s", cs_strerror(cs_errno(handle)));
108                         cs_free(insn, 1);
109                         cs_close(&handle);
110                         return ERROR_FAIL;
111
112                 }
113
114                 print_opcode(cmd, insn);
115                 count--;
116
117         }
118
119         cs_free(insn, 1);
120         cs_close(&handle);
121
122         return ERROR_OK;
123 }
124
125 #else
126
127 int a64_disassemble(struct command_invocation *cmd, struct target *target, target_addr_t address, size_t count)
128 {
129         command_print(cmd, "capstone disassembly framework required");
130
131         return ERROR_FAIL;
132 }
133
134 #endif