Rizin
unix-like reverse engineering framework and cli tools
test_arm.c
Go to the documentation of this file.
1 /* Capstone Disassembler Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3 
4 #include <stdio.h>
5 #include <stdlib.h>
6 
7 #include <capstone/platform.h>
8 #include <capstone/capstone.h>
9 
10 static csh handle;
11 
12 struct platform {
13  cs_arch arch;
14  cs_mode mode;
15  unsigned char *code;
16  size_t size;
17  const char *comment;
18  int syntax;
19 };
20 
21 static void print_string_hex(const char *comment, unsigned char *str, size_t len)
22 {
23  unsigned char *c;
24 
25  printf("%s", comment);
26  for (c = str; c < str + len; c++) {
27  printf("0x%02x ", *c & 0xff);
28  }
29 
30  printf("\n");
31 }
32 
33 static void print_insn_detail(csh cs_handle, cs_insn *ins)
34 {
35  cs_arm *arm;
36  int i;
37  cs_regs regs_read, regs_write;
38  uint8_t regs_read_count, regs_write_count;
39 
40  // detail can be NULL on "data" instruction if SKIPDATA option is turned ON
41  if (ins->detail == NULL)
42  return;
43 
44  arm = &(ins->detail->arm);
45 
46  if (arm->op_count)
47  printf("\top_count: %u\n", arm->op_count);
48 
49  for (i = 0; i < arm->op_count; i++) {
50  cs_arm_op *op = &(arm->operands[i]);
51  switch((int)op->type) {
52  default:
53  break;
54  case ARM_OP_REG:
55  printf("\t\toperands[%u].type: REG = %s\n", i, cs_reg_name(cs_handle, op->reg));
56  break;
57  case ARM_OP_IMM:
58  printf("\t\toperands[%u].type: IMM = 0x%x\n", i, op->imm);
59  break;
60  case ARM_OP_FP:
61 #if defined(_KERNEL_MODE)
62  // Issue #681: Windows kernel does not support formatting float point
63  printf("\t\toperands[%u].type: FP = <float_point_unsupported>\n", i);
64 #else
65  printf("\t\toperands[%u].type: FP = %f\n", i, op->fp);
66 #endif
67  break;
68  case ARM_OP_MEM:
69  printf("\t\toperands[%u].type: MEM\n", i);
70  if (op->mem.base != ARM_REG_INVALID)
71  printf("\t\t\toperands[%u].mem.base: REG = %s\n",
72  i, cs_reg_name(cs_handle, op->mem.base));
73  if (op->mem.index != ARM_REG_INVALID)
74  printf("\t\t\toperands[%u].mem.index: REG = %s\n",
75  i, cs_reg_name(cs_handle, op->mem.index));
76  if (op->mem.scale != 1)
77  printf("\t\t\toperands[%u].mem.scale: %u\n", i, op->mem.scale);
78  if (op->mem.disp != 0)
79  printf("\t\t\toperands[%u].mem.disp: 0x%x\n", i, op->mem.disp);
80  if (op->mem.lshift != 0)
81  printf("\t\t\toperands[%u].mem.lshift: 0x%x\n", i, op->mem.lshift);
82 
83  break;
84  case ARM_OP_PIMM:
85  printf("\t\toperands[%u].type: P-IMM = %u\n", i, op->imm);
86  break;
87  case ARM_OP_CIMM:
88  printf("\t\toperands[%u].type: C-IMM = %u\n", i, op->imm);
89  break;
90  case ARM_OP_SETEND:
91  printf("\t\toperands[%u].type: SETEND = %s\n", i, op->setend == ARM_SETEND_BE? "be" : "le");
92  break;
93  case ARM_OP_SYSREG:
94  printf("\t\toperands[%u].type: SYSREG = %u\n", i, op->reg);
95  break;
96  }
97 
98  if (op->neon_lane != -1) {
99  printf("\t\toperands[%u].neon_lane = %u\n", i, op->neon_lane);
100  }
101 
102  switch(op->access) {
103  default:
104  break;
105  case CS_AC_READ:
106  printf("\t\toperands[%u].access: READ\n", i);
107  break;
108  case CS_AC_WRITE:
109  printf("\t\toperands[%u].access: WRITE\n", i);
110  break;
111  case CS_AC_READ | CS_AC_WRITE:
112  printf("\t\toperands[%u].access: READ | WRITE\n", i);
113  break;
114  }
115 
116  if (op->shift.type != ARM_SFT_INVALID && op->shift.value) {
117  if (op->shift.type < ARM_SFT_ASR_REG)
118  // shift with constant value
119  printf("\t\t\tShift: %u = %u\n", op->shift.type, op->shift.value);
120  else
121  // shift with register
122  printf("\t\t\tShift: %u = %s\n", op->shift.type,
123  cs_reg_name(cs_handle, op->shift.value));
124  }
125 
126  if (op->vector_index != -1) {
127  printf("\t\toperands[%u].vector_index = %u\n", i, op->vector_index);
128  }
129 
130  if (op->subtracted)
131  printf("\t\tSubtracted: True\n");
132  }
133 
134  if (arm->cc != ARM_CC_AL && arm->cc != ARM_CC_INVALID)
135  printf("\tCode condition: %u\n", arm->cc);
136 
137  if (arm->update_flags)
138  printf("\tUpdate-flags: True\n");
139 
140  if (arm->writeback)
141  printf("\tWrite-back: True\n");
142 
143  if (arm->cps_mode)
144  printf("\tCPSI-mode: %u\n", arm->cps_mode);
145 
146  if (arm->cps_flag)
147  printf("\tCPSI-flag: %u\n", arm->cps_flag);
148 
149  if (arm->vector_data)
150  printf("\tVector-data: %u\n", arm->vector_data);
151 
152  if (arm->vector_size)
153  printf("\tVector-size: %u\n", arm->vector_size);
154 
155  if (arm->usermode)
156  printf("\tUser-mode: True\n");
157 
158  if (arm->mem_barrier)
159  printf("\tMemory-barrier: %u\n", arm->mem_barrier);
160 
161  // Print out all registers accessed by this instruction (either implicit or explicit)
162  if (!cs_regs_access(cs_handle, ins,
163  regs_read, &regs_read_count,
164  regs_write, &regs_write_count)) {
165  if (regs_read_count) {
166  printf("\tRegisters read:");
167  for(i = 0; i < regs_read_count; i++) {
168  printf(" %s", cs_reg_name(cs_handle, regs_read[i]));
169  }
170  printf("\n");
171  }
172 
173  if (regs_write_count) {
174  printf("\tRegisters modified:");
175  for(i = 0; i < regs_write_count; i++) {
176  printf(" %s", cs_reg_name(cs_handle, regs_write[i]));
177  }
178  printf("\n");
179  }
180  }
181 
182  printf("\n");
183 }
184 
185 static void test()
186 {
187 #define ARM_CODE "\x86\x48\x60\xf4\x4d\x0f\xe2\xf4\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8\xf4\x80\x00\x00"
188 #define ARM_CODE2 "\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c"
189 #define THUMB_CODE "\x60\xf9\x1f\x04\xe0\xf9\x4f\x07\x70\x47\x00\xf0\x10\xe8\xeb\x46\x83\xb0\xc9\x68\x1f\xb1\x30\xbf\xaf\xf3\x20\x84\x52\xf8\x23\xf0"
190 #define THUMB_CODE2 "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0\x18\xbf\xad\xbf\xf3\xff\x0b\x0c\x86\xf3\x00\x89\x80\xf3\x00\x8c\x4f\xfa\x99\xf6\xd0\xff\xa2\x01"
191 #define THUMB_MCLASS "\xef\xf3\x02\x80"
192 #define ARMV8 "\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5"
193 
194  struct platform platforms[] = {
195  {
196  CS_ARCH_ARM,
197  CS_MODE_ARM,
198  (unsigned char *)ARM_CODE,
199  sizeof(ARM_CODE) - 1,
200  "ARM"
201  },
202  {
203  CS_ARCH_ARM,
205  (unsigned char *)THUMB_CODE,
206  sizeof(THUMB_CODE) - 1,
207  "Thumb"
208  },
209  {
210  CS_ARCH_ARM,
212  (unsigned char *)ARM_CODE2,
213  sizeof(ARM_CODE2) - 1,
214  "Thumb-mixed"
215  },
216  {
217  CS_ARCH_ARM,
219  (unsigned char *)THUMB_CODE2,
220  sizeof(THUMB_CODE2) - 1,
221  "Thumb-2 & register named with numbers",
223  },
224  {
225  CS_ARCH_ARM,
227  (unsigned char*)THUMB_MCLASS,
228  sizeof(THUMB_MCLASS) - 1,
229  "Thumb-MClass"
230  },
231  {
232  CS_ARCH_ARM,
234  (unsigned char*)ARMV8,
235  sizeof(ARMV8) - 1,
236  "Arm-V8"
237  },
238  };
239 
240  uint64_t address = 0x80001000;
241  cs_insn *insn;
242  int i;
243  size_t count;
244 
245  for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) {
246  cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle);
247  if (err) {
248  printf("Failed on cs_open() with error returned: %u\n", err);
249  abort();
250  }
251 
253 
254  if (platforms[i].syntax)
256 
257  count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn);
258  if (count) {
259  size_t j;
260  printf("****************\n");
261  printf("Platform: %s\n", platforms[i].comment);
263  printf("Disasm:\n");
264 
265  for (j = 0; j < count; j++) {
266  printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str);
267  print_insn_detail(handle, &insn[j]);
268  }
269  printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size);
270 
271  // free memory allocated by cs_disasm()
272  cs_free(insn, count);
273  } else {
274  printf("****************\n");
275  printf("Platform: %s\n", platforms[i].comment);
277  printf("ERROR: Failed to disasm given code!\n");
278  abort();
279  }
280 
281  printf("\n");
282 
283  cs_close(&handle);
284  }
285 }
286 
287 int main()
288 {
289  test();
290 
291  return 0;
292 }
293 
size_t len
Definition: 6502dis.c:15
lzma_index ** i
Definition: index.h:629
static bool err
Definition: armass.c:435
@ ARM_SFT_INVALID
Definition: arm.h:19
@ ARM_SFT_ASR_REG
shift with register
Definition: arm.h:25
@ ARM_SETEND_BE
BE operand.
Definition: arm.h:176
@ 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_SETEND
operand for SETEND instruction
Definition: arm.h:169
@ 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_OP_SYSREG
MSR/MRS special register operand.
Definition: arm.h:170
@ ARM_CC_AL
Always (unconditional) Always (unconditional)
Definition: arm.h:49
@ ARM_CC_INVALID
Definition: arm.h:34
@ ARM_REG_INVALID
Definition: arm.h:253
cs_arch
Architecture type.
Definition: capstone.h:74
@ CS_ARCH_ARM
ARM architecture (including Thumb, Thumb-2)
Definition: capstone.h:75
cs_mode
Mode type.
Definition: capstone.h:102
@ CS_MODE_MCLASS
ARM's Cortex-M series.
Definition: capstone.h:109
@ CS_MODE_ARM
32-bit ARM
Definition: capstone.h:104
@ CS_MODE_V8
ARMv8 A32 encodings for ARM.
Definition: capstone.h:110
@ 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
size_t csh
Definition: capstone.h:71
@ 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
@ CS_AC_READ
Operand read from memory or register.
Definition: capstone.h:204
@ CS_AC_WRITE
Operand write to memory or register.
Definition: capstone.h:205
#define NULL
Definition: cris-opc.c:27
CAPSTONE_EXPORT cs_err CAPSTONE_API cs_regs_access(csh ud, const cs_insn *insn, cs_regs regs_read, uint8_t *regs_read_count, cs_regs regs_write, uint8_t *regs_write_count)
Definition: cs.c:1504
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 const char *CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
Definition: cs.c:1154
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
_Use_decl_annotations_ int __cdecl printf(const char *const _Format,...)
Definition: cs_driver.c:93
cs_arch arch
Definition: cstool.c:13
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
struct platform platforms[]
Definition: fuzz_diff.c:18
voidpf void uLong size
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
unsigned long uint64_t
Definition: sftypes.h:28
unsigned char uint8_t
Definition: sftypes.h:31
#define c(i)
Definition: sha256.c:43
Definition: inftree9.h:24
Instruction operand.
Definition: arm.h:391
Instruction structure.
Definition: arm.h:424
unsigned char * code
#define PRIx64
Definition: sysdefs.h:94
static csh handle
Definition: test_arm.c:10
static void print_string_hex(const char *comment, unsigned char *str, size_t len)
Definition: test_arm.c:21
#define THUMB_CODE
#define THUMB_MCLASS
#define ARM_CODE2
static void test()
Definition: test_arm.c:185
#define ARMV8
static void print_insn_detail(csh cs_handle, cs_insn *ins)
Definition: test_arm.c:33
int main()
Definition: test_arm.c:287
#define ARM_CODE
#define THUMB_CODE2
Definition: dis.c:32
mnemonic
Definition: z80asm.h:48