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  { "arm64", CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN },
33  { "arm64be", CS_ARCH_ARM64, CS_MODE_BIG_ENDIAN },
34  { "cortexm", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB | CS_MODE_MCLASS },
35  { "thumb", CS_ARCH_ARM, CS_MODE_ARM | CS_MODE_THUMB },
36 
37 #if CS_API_MAJOR >= 5
38  { "riscv32", CS_ARCH_RISCV, CS_MODE_RISCV32 | CS_MODE_RISCVC },
39  { "riscv64", CS_ARCH_RISCV, CS_MODE_RISCV64 | CS_MODE_RISCVC },
40 #endif /* CS_API_MAJOR >= 5 */
41 };
42 
44 {
45  for (size_t i = 0; i < ARRAY_SIZE(all_archs); i++)
46  command_print_sameline(cmd, (i == 0) ? "%s" : " %s",
47  all_archs[i].name);
48 
49  return ERROR_OK;
50 }
51 
52 static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
53 {
54  char opcode[3 * ARRAY_SIZE(insn->bytes) + 1];
55 
56  for (uint16_t i = 0; i < insn->size; i++)
57  sprintf(&opcode[3 * i], " %02" PRIx8, insn->bytes[i]);
58 
59  command_print(cmd, "0x%08" PRIx64 " %s\t%s%s%s",
60  insn->address, opcode, insn->mnemonic,
61  insn->op_str[0] ? "\t" : "", insn->op_str);
62 }
63 
65  uint64_t address, unsigned int count, const char *insn_set)
66 {
67  size_t i;
68 
69  for (i = 0; i < ARRAY_SIZE(all_archs); i++)
70  if (!strcmp(insn_set, all_archs[i].name))
71  break;
72 
73  if (i == ARRAY_SIZE(all_archs)) {
74  command_print(cmd, "Instruction set \"%s\" not supported by Capstone", insn_set);
75  return ERROR_FAIL;
76  }
77 
78  csh handle;
79  cs_err csret = cs_open(all_archs[i].arch, all_archs[i].mode, &handle);
80  if (csret != CS_ERR_OK) {
81  command_print(cmd, "Capstone cs_open() failed: %s", cs_strerror(csret));
82  return ERROR_FAIL;
83  }
84 
85  csret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
86  if (csret != CS_ERR_OK) {
87  command_print(cmd, "Capstone cs_option() failed: %s", cs_strerror(csret));
88  cs_close(&handle);
89  return ERROR_FAIL;
90  }
91 
92  cs_insn *insn = cs_malloc(handle);
93  if (!insn) {
94  command_print(cmd, "Capstone cs_malloc() failed: %s", cs_strerror(csret));
95  cs_close(&handle);
96  return ERROR_FAIL;
97  }
98 
99  while (count > 0) {
100  uint8_t buf[4];
101 
102  int retval = target_read_buffer(target, address, sizeof(buf), buf);
103  if (retval != ERROR_OK) {
104  cs_free(insn, 1);
105  cs_close(&handle);
106  return retval;
107  }
108 
109  size_t size = sizeof(buf);
110  const uint8_t *tmp = buf;
111  bool csbool = cs_disasm_iter(handle, &tmp, &size, &address, insn);
112  if (!csbool) {
113  command_print(cmd, "Capstone cs_disasm_iter() failed: %s", cs_strerror(csret));
114  cs_free(insn, 1);
115  cs_close(&handle);
116  return ERROR_FAIL;
117  }
118 
119  print_opcode(cmd, insn);
120  count--;
121  }
122 
123  cs_free(insn, 1);
124  cs_close(&handle);
125 
126  return ERROR_OK;
127 }
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:64
int oocd_cs_list_insn_types(struct command_invocation *cmd)
Definition: oocd_capstone.c:43
static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
Definition: oocd_capstone.c:52
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