OpenOCD
oocd_capstone.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /*
4  * This file wraps the functions in capstone library.
5  * It also takes care of API changes across versions.
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include <capstone.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 
16 #include <helper/command.h>
17 #include <helper/log.h>
18 #include <target/oocd_capstone.h>
19 #include <target/target.h>
20 
21 /*
22  * Extracted from Capstone tool 'cstool', file 'cstool/cstool.c'.
23  * Big rework expected for next Capstone v6.
24  */
25 static struct {
26  const char *name;
27  cs_arch arch;
28  cs_mode mode;
29 } all_archs[] = {
30  { "arm", CS_ARCH_ARM, CS_MODE_ARM },
31  { "armbe", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_BIG_ENDIAN },
32  { "cortexm", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS },
33  { "thumb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB },
34 
35 #if CS_API_MAJOR < 6
36  { "arm64", CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN },
37  { "arm64be", CS_ARCH_ARM64, CS_MODE_BIG_ENDIAN },
38 #if CS_API_MAJOR >= 5
39  { "riscv32", CS_ARCH_RISCV, CS_MODE_RISCV32 | CS_MODE_RISCVC },
40  { "riscv64", CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCVC },
41 #endif
42 #endif /* CS_API_MAJOR < 6 */
43 
44 #if CS_API_MAJOR >= 6
45  { "arm64", CS_ARCH_AARCH64, CS_MODE_LITTLE_ENDIAN },
46  { "arm64be", CS_ARCH_AARCH64, CS_MODE_BIG_ENDIAN },
47  { "riscv32", CS_ARCH_RISCV, CS_MODE_RISCV32 | CS_MODE_RISCV_C },
48  { "riscv64", CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCV_C },
49  { "xtensa", CS_ARCH_XTENSA, CS_MODE_XTENSA_ESP32 },
50  { "xtensa_s2", CS_ARCH_XTENSA, CS_MODE_XTENSA_ESP32S2 },
51  { "xtensa_8266", CS_ARCH_XTENSA, CS_MODE_XTENSA_ESP8266 },
52  { "arc", CS_ARCH_ARC, CS_MODE_LITTLE_ENDIAN },
53 #endif /* CS_API_MAJOR >= 6 */
54 };
55 
57 {
58  for (size_t i = 0; i < ARRAY_SIZE(all_archs); i++)
59  command_print_sameline(cmd, (i == 0) ? "%s" : " %s",
60  all_archs[i].name);
61 
62  return ERROR_OK;
63 }
64 
65 static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
66 {
67  char opcode[3 * ARRAY_SIZE(insn->bytes) + 1];
68 
69  for (uint16_t i = 0; i < insn->size; i++)
70  sprintf(&opcode[3 * i], " %02" PRIx8, insn->bytes[i]);
71 
72  command_print(cmd, "0x%08" PRIx64 " %s\t%s%s%s",
73  insn->address, opcode, insn->mnemonic,
74  insn->op_str[0] ? "\t" : "", insn->op_str);
75 }
76 
78  uint64_t address, unsigned int count, const char *insn_set)
79 {
80  size_t i;
81 
82  for (i = 0; i < ARRAY_SIZE(all_archs); i++)
83  if (!strcmp(insn_set, all_archs[i].name))
84  break;
85 
86  if (i == ARRAY_SIZE(all_archs)) {
87  command_print(cmd, "Instruction set \"%s\" not supported by Capstone", insn_set);
88  return ERROR_FAIL;
89  }
90 
91  csh handle;
92  cs_err csret = cs_open(all_archs[i].arch, all_archs[i].mode, &handle);
93  if (csret != CS_ERR_OK) {
94  command_print(cmd, "Capstone cs_open() failed: %s", cs_strerror(csret));
95  return ERROR_FAIL;
96  }
97 
98  csret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
99  if (csret != CS_ERR_OK) {
100  command_print(cmd, "Capstone cs_option() failed: %s", cs_strerror(csret));
101  cs_close(&handle);
102  return ERROR_FAIL;
103  }
104 
105  cs_insn *insn = cs_malloc(handle);
106  if (!insn) {
107  command_print(cmd, "Capstone cs_malloc() failed: %s", cs_strerror(csret));
108  cs_close(&handle);
109  return ERROR_FAIL;
110  }
111 
112  while (count > 0) {
113  uint8_t buf[4];
114 
115  int retval = target_read_buffer(target, address, sizeof(buf), buf);
116  if (retval != ERROR_OK) {
117  cs_free(insn, 1);
118  cs_close(&handle);
119  return retval;
120  }
121 
122  size_t size = sizeof(buf);
123  const uint8_t *tmp = buf;
124  bool csbool = cs_disasm_iter(handle, &tmp, &size, &address, insn);
125  if (!csbool) {
126  command_print(cmd, "Capstone cs_disasm_iter() failed: %s", cs_strerror(csret));
127  cs_free(insn, 1);
128  cs_close(&handle);
129  return ERROR_FAIL;
130  }
131 
132  print_opcode(cmd, insn);
133  count--;
134  }
135 
136  cs_free(insn, 1);
137  cs_close(&handle);
138 
139  return ERROR_OK;
140 }
void command_print_sameline(struct command_invocation *cmd, const char *format,...)
Definition: command.c:378
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:389
uint32_t size
Size of dw_spi_transaction::buffer.
Definition: dw-spi-helper.h:4
uint32_t address
Starting address. Sector aligned.
Definition: dw-spi-helper.h:0
#define ERROR_FAIL
Definition: log.h:188
#define ERROR_OK
Definition: log.h:182
cs_mode mode
Definition: oocd_capstone.c:28
int oocd_cs_disassemble(struct command_invocation *cmd, struct target *target, uint64_t address, unsigned int count, const char *insn_set)
Definition: oocd_capstone.c:77
int oocd_cs_list_insn_types(struct command_invocation *cmd)
Definition: oocd_capstone.c:56
static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
Definition: oocd_capstone.c:65
const char * name
Definition: oocd_capstone.c:26
static struct @119 all_archs[]
cs_arch arch
Definition: oocd_capstone.c:27
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
Definition: target.h:119
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2470
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
uint8_t cmd
Definition: vdebug.c:1
uint8_t count[4]
Definition: vdebug.c:22