Rizin
unix-like reverse engineering framework and cli tools
test_arm_regression.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <capstone/platform.h>
#include <capstone/capstone.h>

Go to the source code of this file.

Classes

struct  platform
 
struct  invalid_code
 
struct  invalid_instructions
 
struct  valid_code
 
struct  valid_instructions
 

Macros

#define _this_printf(...)
 
#define MAX_INVALID_CODES   16
 
#define MAX_VALID_CODES   16
 
#define _this_printf(...)
 

Functions

static char * hex_string (unsigned char *str, size_t len)
 
static void snprint_insn_detail (char *buf, size_t *cur, size_t *left, cs_insn *ins)
 
static void print_insn_detail (cs_insn *ins)
 
static void test_invalids ()
 
static void test_valids ()
 
int main ()
 

Variables

static csh handle
 

Macro Definition Documentation

◆ _this_printf [1/2]

#define _this_printf (   ...)
Value:
{ \
size_t used = 0; \
used = snprintf(buf + *cur, *left, __VA_ARGS__); \
*left -= used; \
*cur += used; \
}
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364

◆ _this_printf [2/2]

#define _this_printf (   ...)
Value:
{ \
size_t used = 0; \
used = snprintf(tmp_buf + cur, left, __VA_ARGS__); \
left -= used; \
cur += used; \
}

◆ MAX_INVALID_CODES

#define MAX_INVALID_CODES   16

Definition at line 148 of file test_arm_regression.c.

◆ MAX_VALID_CODES

#define MAX_VALID_CODES   16

Definition at line 242 of file test_arm_regression.c.

Function Documentation

◆ hex_string()

static char* hex_string ( unsigned char *  str,
size_t  len 
)
static

Definition at line 27 of file test_arm_regression.c.

28 {
29  // returns a malloced string that has the hex version of the string in it
30  // null if failed to malloc
31  char *hex_out;
32  size_t i;
33 
34  hex_out = (char *) malloc(len*2 + 1); // two ascii characters per input character, plus trailing null
35  if (!hex_out) { goto Exit; }
36 
37  for (i = 0; i < len; ++i) {
38  snprintf(hex_out + (i*2), 2, "%02x", str[i]);
39  }
40 
41  hex_out[len*2] = 0; // trailing null
42 
43 Exit:
44  return hex_out;
45 }
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
void * malloc(size_t size)
Definition: malloc.c:123

References i, len, malloc(), snprintf, and cmd_descs_generate::str.

Referenced by test_invalids(), and test_valids().

◆ main()

int main ( void  )

Definition at line 388 of file test_arm_regression.c.

389 {
390  test_invalids();
391  test_valids();
392  return 0;
393 }
static void test_invalids()
static void test_valids()

References test_invalids(), and test_valids().

◆ print_insn_detail()

static void print_insn_detail ( cs_insn *  ins)
static

Definition at line 134 of file test_arm_regression.c.

135 {
136  char a_buf[2048];
137  size_t cur=0, left=2048;
138  snprint_insn_detail(a_buf, &cur, &left, ins);
139  printf("%s\n", a_buf);
140 }
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
static void snprint_insn_detail(char *buf, size_t *cur, size_t *left, cs_insn *ins)

References printf(), and snprint_insn_detail().

Referenced by test_invalids().

◆ snprint_insn_detail()

static void snprint_insn_detail ( char *  buf,
size_t cur,
size_t left,
cs_insn *  ins 
)
static

Definition at line 47 of file test_arm_regression.c.

48 {
49  size_t used = 0;
50 
51 #define _this_printf(...) \
52  { \
53  size_t used = 0; \
54  used = snprintf(buf + *cur, *left, __VA_ARGS__); \
55  *left -= used; \
56  *cur += used; \
57  }
58 
59  cs_arm *arm;
60  int i;
61 
62  // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
63  if (ins->detail == NULL)
64  return;
65 
66  arm = &(ins->detail->arm);
67 
68  if (arm->op_count)
69  _this_printf("\top_count: %u\n", arm->op_count);
70 
71  for (i = 0; i < arm->op_count; i++) {
72  cs_arm_op *op = &(arm->operands[i]);
73  switch((int)op->type) {
74  default:
75  break;
76  case ARM_OP_REG:
77  _this_printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(handle, op->reg));
78  break;
79  case ARM_OP_IMM:
80  _this_printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
81  break;
82  case ARM_OP_FP:
83  _this_printf("\t\toperands[%u].type: FP = %f\n", i, op->fp);
84  break;
85  case ARM_OP_MEM:
86  _this_printf("\t\toperands[%u].type: MEM\n", i);
87  if (op->mem.base != X86_REG_INVALID)
88  _this_printf("\t\t\toperands[%u].mem.base: REG = %s\n",
89  i, cs_reg_name(handle, op->mem.base));
90  if (op->mem.index != X86_REG_INVALID)
91  _this_printf("\t\t\toperands[%u].mem.index: REG = %s\n",
92  i, cs_reg_name(handle, op->mem.index));
93  if (op->mem.scale != 1)
94  _this_printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
95  if (op->mem.disp != 0)
96  _this_printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
97 
98  break;
99  case ARM_OP_PIMM:
100  _this_printf("\t\toperands[%u].type: P-IMM = %u\n", i, op->imm);
101  break;
102  case ARM_OP_CIMM:
103  _this_printf("\t\toperands[%u].type: C-IMM = %u\n", i, op->imm);
104  break;
105  }
106 
107  if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
108  if (op->shift.type < ARM_SFT_ASR_REG) {
109  // shift with constant value
110  _this_printf("\t\t\tShift: %u = %u\n", op->shift.type, op->shift.value);
111  } else {
112  // shift with register
113  _this_printf("\t\t\tShift: %u = %s\n", op->shift.type,
114  cs_reg_name(handle, op->shift.value));
115  }
116  }
117  }
118 
119  if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID) {
120  _this_printf("\tCode condition: %u\n", arm->cc);
121  }
122 
123  if (arm->update_flags) {
124  _this_printf("\tUpdate-flags: True\n");
125  }
126 
127  if (arm->writeback) {
128  _this_printf("\tWrite-back: True\n");
129  }
130 
131 #undef _this_printf
132 }
@ ARM_SFT_INVALID
Definition: arm.h:19
@ ARM_SFT_ASR_REG
shift with register
Definition: arm.h:25
@ ARM_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: arm.h:164
@ ARM_OP_REG
= CS_OP_REG (Register operand).
Definition: arm.h:163
@ ARM_OP_CIMM
C-Immediate (coprocessor registers)
Definition: arm.h:167
@ ARM_OP_PIMM
P-Immediate (coprocessor registers)
Definition: arm.h:168
@ ARM_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: arm.h:165
@ ARM_OP_FP
= CS_OP_FP (Floating-Point operand).
Definition: arm.h:166
@ ARM_CC_AL
Always (unconditional) Always (unconditional)
Definition: arm.h:49
@ ARM_CC_INVALID
Definition: arm.h:34
@ X86_REG_INVALID
Definition: x86.h:20
#define NULL
Definition: cris-opc.c:27
CAPSTONE_EXPORT const char *CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
Definition: cs.c:1154
Instruction operand.
Definition: arm.h:391
Instruction structure.
Definition: arm.h:424
static csh handle
#define _this_printf(...)
Definition: dis.c:32

References _this_printf, ARM_CC_AL, ARM_CC_INVALID, ARM_OP_CIMM, ARM_OP_FP, ARM_OP_IMM, ARM_OP_MEM, ARM_OP_PIMM, ARM_OP_REG, ARM_SFT_ASR_REG, ARM_SFT_INVALID, cs_reg_name(), handle, i, NULL, and X86_REG_INVALID.

Referenced by print_insn_detail(), and test_valids().

◆ test_invalids()

static void test_invalids ( )
static

Definition at line 158 of file test_arm_regression.c.

159 {
160  struct invalid_instructions invalids[] = {{
161  CS_ARCH_ARM,
163  "Thumb",
164  1,
165  {{
166  (unsigned char *)"\xbd\xe8\x1e\xff",
167  4,
168  "invalid thumb2 pop because sp used and because both pc and lr are "
169  "present at the same time"
170  }},
171  }};
172 
173  struct invalid_instructions * invalid = NULL;
174 
175  uint64_t address = 0x1000;
176  cs_insn *insn;
177  int i;
178  int j;
179  size_t count;
180 
181  printf("\nShould be invalid\n"
182  "-----------------\n");
183 
184  for (i = 0; i < sizeof(invalids)/sizeof(invalids[0]); i++) {
185  cs_err err;
186 
187  invalid = invalids + i;
188  err = cs_open(invalid->arch, invalid->mode, &handle);
189 
190  if (err) {
191  printf("Failed on cs_open() with error returned: %u\n", err);
192  continue;
193  }
194 
197 
198  for (j = 0; j < invalid->num_invalid_codes; ++j) {
199  struct invalid_code *invalid_code = NULL;
200  char *hex_str = NULL;
201 
202  invalid_code = invalid->invalid_codes + j;
203 
205 
206  printf("%s %s: %s\n", invalid->platform_comment, hex_str, invalid_code->comment);
207 
208  free(hex_str);
209 
211  invalid_code->code, invalid_code->size, address, 0, &insn
212  );
213 
214  if (count) {
215  size_t k;
216  printf(" ERROR:\n");
217 
218  for (k = 0; k < count; k++) {
219  printf(" 0x%"PRIx64":\t%s\t%s\n",
220  insn[k].address, insn[k].mnemonic, insn[k].op_str);
221  print_insn_detail(&insn[k]);
222  }
223  cs_free(insn, count);
224 
225  } else {
226  printf(" SUCCESS: invalid\n");
227  }
228  }
229 
230  cs_close(&handle);
231  }
232 }
static bool err
Definition: armass.c:435
@ CS_ARCH_ARM
ARM architecture (including Thumb, Thumb-2)
Definition: capstone.h:75
@ CS_MODE_THUMB
ARM's Thumb mode, including Thumb-2.
Definition: capstone.h:108
@ CS_OPT_DETAIL
Break down instruction structure into details.
Definition: capstone.h:171
@ CS_OPT_SYNTAX
Assembly output syntax.
Definition: capstone.h:170
@ CS_OPT_SYNTAX_NOREGNAME
Prints register name with only number (CS_OPT_SYNTAX)
Definition: capstone.h:187
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
Definition: capstone.h:183
CAPSTONE_EXPORT size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
Definition: cs.c:798
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
Definition: cs.c:453
CAPSTONE_EXPORT void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
Definition: cs.c:1017
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_close(csh *handle)
Definition: cs.c:501
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
Definition: cs.c:646
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
const char * k
Definition: dsignal.c:11
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static char hex_str[]
Definition: utils.c:9
unsigned long uint64_t
Definition: sftypes.h:28
unsigned char * code
struct invalid_code invalid_codes[MAX_INVALID_CODES]
#define PRIx64
Definition: sysdefs.h:94
static void print_insn_detail(cs_insn *ins)
static char * hex_string(unsigned char *str, size_t len)
mnemonic
Definition: z80asm.h:48

References invalid_instructions::arch, invalid_code::code, invalid_code::comment, count, CS_ARCH_ARM, cs_close(), cs_disasm(), cs_free(), CS_MODE_THUMB, cs_open(), CS_OPT_DETAIL, CS_OPT_ON, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME, cs_option(), err, free(), handle, hex_str, hex_string(), i, invalid_instructions::invalid_codes, k, invalid_instructions::mode, NULL, invalid_instructions::num_invalid_codes, invalid_instructions::platform_comment, print_insn_detail(), printf(), PRIx64, and invalid_code::size.

Referenced by main().

◆ test_valids()

static void test_valids ( )
static

Definition at line 251 of file test_arm_regression.c.

252 {
253  struct valid_instructions valids[] = {{
254  CS_ARCH_ARM,
256  "Thumb",
257  3,
258  {{ (unsigned char *)"\x00\xf0\x26\xe8", 4, 0x352,
259  "0x352:\tblx\t#0x3a0\n"
260  "\top_count: 1\n"
261  "\t\toperands[0].type: IMM = 0x3a0\n",
262 
263  "thumb2 blx with misaligned immediate"
264  }, { (unsigned char *)"\x05\xdd", 2, 0x1f0,
265  "0x1f0:\tble\t#0x1fe\n"
266  "\top_count: 1\n"
267  "\t\toperands[0].type: IMM = 0x1fe\n"
268  "\tCode condition: 14\n",
269 
270  "thumb b cc with thumb-aligned target"
271  }, { (unsigned char *)"\xbd\xe8\xf0\x8f", 4, 0,
272  "0x0:\tpop.w\t{r4, r5, r6, r7, r8, r9, r10, r11, pc}\n"
273  "\top_count: 9\n"
274  "\t\toperands[0].type: REG = r4\n"
275  "\t\toperands[1].type: REG = r5\n"
276  "\t\toperands[2].type: REG = r6\n"
277  "\t\toperands[3].type: REG = r7\n"
278  "\t\toperands[4].type: REG = r8\n"
279  "\t\toperands[5].type: REG = r9\n"
280  "\t\toperands[6].type: REG = r10\n"
281  "\t\toperands[7].type: REG = r11\n"
282  "\t\toperands[8].type: REG = pc\n",
283 
284  "thumb2 pop that should be valid"
285  },
286  }
287  }};
288 
289  struct valid_instructions * valid = NULL;
290 
291  uint64_t address = 0x1000;
292  cs_insn *insn;
293  int i;
294  int j;
295  size_t count;
296 
297 
298  for (i = 0; i < sizeof(valids)/sizeof(valids[0]); i++) {
299  cs_err err;
300 
301  valid = valids + i;
302  err = cs_open(valid->arch, valid->mode, &handle);
303 
304  if (err) {
305  printf("Failed on cs_open() with error returned: %u\n", err);
306  continue;
307  }
308 
311 
312 #define _this_printf(...) \
313  { \
314  size_t used = 0; \
315  used = snprintf(tmp_buf + cur, left, __VA_ARGS__); \
316  left -= used; \
317  cur += used; \
318  }
319  printf("\nShould be valid\n"
320  "---------------\n");
321 
322  for (j = 0; j < valid->num_valid_codes; ++j) {
323  char tmp_buf[2048];
324  size_t left = 2048;
325  size_t cur = 0;
326  size_t used = 0;
327  int success = 0;
328  char * hex_str = NULL;
329 
330  struct valid_code * valid_code = NULL;
331  valid_code = valid->valid_codes + j;
332 
334 
335  printf("%s %s @ 0x%04x: %s\n %s",
336  valid->platform_comment, hex_str, valid_code->start_addr,
338 
341  valid_code->start_addr, 0, &insn
342  );
343 
344  if (count) {
345  size_t k;
346  size_t max_len = 0;
347  size_t tmp_len = 0;
348 
349  for (k = 0; k < count; k++) {
350  _this_printf(
351  "0x%"PRIx64":\t%s\t%s\n",
352  insn[k].address, insn[k].mnemonic,
353  insn[k].op_str
354  );
355 
356  snprint_insn_detail(tmp_buf, &cur, &left, &insn[k]);
357  }
358 
359  max_len = strlen(tmp_buf);
360  tmp_len = strlen(valid_code->expected_out);
361  if (tmp_len > max_len) {
362  max_len = tmp_len;
363  }
364 
365  if (memcmp(tmp_buf, valid_code->expected_out, max_len)) {
366  printf(
367  " ERROR: '''\n%s''' does not match"
368  " expected '''\n%s'''\n",
369  tmp_buf, valid_code->expected_out
370  );
371  } else {
372  printf(" SUCCESS: valid\n");
373  }
374 
375  cs_free(insn, count);
376 
377  } else {
378  printf("ERROR: invalid\n");
379  }
380  }
381 
382  cs_close(&handle);
383  }
384 
385 #undef _this_prinf
386 }
unsigned char * code
bool valid
Definition: core.c:77

References _this_printf, valid_code::code, valid_code::comment, count, CS_ARCH_ARM, cs_close(), cs_disasm(), cs_free(), CS_MODE_THUMB, cs_open(), CS_OPT_DETAIL, CS_OPT_ON, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME, cs_option(), err, valid_code::expected_out, handle, hex_str, hex_string(), i, k, NULL, printf(), PRIx64, valid_code::size, snprint_insn_detail(), valid_code::start_addr, and valid.

Referenced by main().

Variable Documentation

◆ handle

csh handle
static

Definition at line 16 of file test_arm_regression.c.

Referenced by snprint_insn_detail(), test_invalids(), and test_valids().