1 /* Capstone Disassembly Engine */
2 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2014 */
3 #if defined (WIN32) || defined (WIN64) || defined (_WIN32) || defined (_WIN64)
4 #pragma warning(disable:4996)			// disable MSVC's warning on strcpy()
5 #pragma warning(disable:28719)		// disable MSVC's warning on strcpy()
6 #endif
7 #if defined(CAPSTONE_HAS_OSXKERNEL)
8 #include <libkern/libkern.h>
9 #else
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #endif
14 
15 #include <string.h>
16 #include <capstone.h>
17 
18 #include "utils.h"
19 #include "MCRegisterInfo.h"
20 
21 #if defined(_KERNEL_MODE)
22 #include "windows\winkernel_mm.h"
23 #endif
24 
25 // Issue #681: Windows kernel does not support formatting float point
26 #if defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
27 #if defined(CAPSTONE_HAS_ARM) || defined(CAPSTONE_HAS_ARM64)
28 #define CAPSTONE_STR_INTERNAL(x) #x
29 #define CAPSTONE_STR(x) CAPSTONE_STR_INTERNAL(x)
30 #define CAPSTONE_MSVC_WRANING_PREFIX __FILE__ "("CAPSTONE_STR(__LINE__)") : warning message : "
31 
32 #pragma message(CAPSTONE_MSVC_WRANING_PREFIX "Windows driver does not support full features for selected architecture(s). Define CAPSTONE_DIET to compile Capstone with only supported features. See issue #681 for details.")
33 
34 #undef CAPSTONE_MSVC_WRANING_PREFIX
35 #undef CAPSTONE_STR
36 #undef CAPSTONE_STR_INTERNAL
37 #endif
38 #endif	// defined(_KERNEL_MODE) && !defined(CAPSTONE_DIET)
39 
40 #if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(CAPSTONE_DIET) && !defined(_KERNEL_MODE)
41 #define INSN_CACHE_SIZE 32
42 #else
43 // reduce stack variable size for kernel/firmware
44 #define INSN_CACHE_SIZE 8
45 #endif
46 
47 // default SKIPDATA mnemonic
48 #ifndef CAPSTONE_DIET
49 #define SKIPDATA_MNEM ".byte"
50 #else // No printing is available in diet mode
51 #define SKIPDATA_MNEM NULL
52 #endif
53 
54 cs_err (*arch_init[MAX_ARCH])(cs_struct *) = { NULL };
55 cs_err (*arch_option[MAX_ARCH]) (cs_struct *, cs_opt_type, size_t value) = { NULL };
56 void (*arch_destroy[MAX_ARCH]) (cs_struct *) = { NULL };
57 cs_mode arch_disallowed_mode_mask[MAX_ARCH] = { 0 };
58 
59 extern void ARM_enable(void);
60 extern void AArch64_enable(void);
61 extern void Mips_enable(void);
62 extern void X86_enable(void);
63 extern void PPC_enable(void);
64 extern void Sparc_enable(void);
65 extern void SystemZ_enable(void);
66 extern void XCore_enable(void);
67 
archs_enable(void)68 static void archs_enable(void)
69 {
70 	static bool initialized = false;
71 
72 	if (initialized)
73 		return;
74 
75 #ifdef CAPSTONE_HAS_ARM
76 	ARM_enable();
77 #endif
78 #ifdef CAPSTONE_HAS_ARM64
79 	AArch64_enable();
80 #endif
81 #ifdef CAPSTONE_HAS_MIPS
82 	Mips_enable();
83 #endif
84 #ifdef CAPSTONE_HAS_POWERPC
85 	PPC_enable();
86 #endif
87 #ifdef CAPSTONE_HAS_SPARC
88 	Sparc_enable();
89 #endif
90 #ifdef CAPSTONE_HAS_SYSZ
91 	SystemZ_enable();
92 #endif
93 #ifdef CAPSTONE_HAS_X86
94 	X86_enable();
95 #endif
96 #ifdef CAPSTONE_HAS_XCORE
97 	XCore_enable();
98 #endif
99 
100 
101 	initialized = true;
102 }
103 
104 unsigned int all_arch = 0;
105 
106 #if defined(CAPSTONE_USE_SYS_DYN_MEM)
107 #if !defined(CAPSTONE_HAS_OSXKERNEL) && !defined(_KERNEL_MODE)
108 cs_malloc_t cs_mem_malloc = malloc;
109 cs_calloc_t cs_mem_calloc = calloc;
110 cs_realloc_t cs_mem_realloc = realloc;
111 cs_free_t cs_mem_free = free;
112 cs_vsnprintf_t cs_vsnprintf = vsnprintf;
113 #elif defined(_KERNEL_MODE)
114 cs_malloc_t cs_mem_malloc = cs_winkernel_malloc;
115 cs_calloc_t cs_mem_calloc = cs_winkernel_calloc;
116 cs_realloc_t cs_mem_realloc = cs_winkernel_realloc;
117 cs_free_t cs_mem_free = cs_winkernel_free;
118 cs_vsnprintf_t cs_vsnprintf = cs_winkernel_vsnprintf;
119 #else
120 extern void* kern_os_malloc(size_t size);
121 extern void kern_os_free(void* addr);
122 extern void* kern_os_realloc(void* addr, size_t nsize);
123 
cs_kern_os_calloc(size_t num,size_t size)124 static void* cs_kern_os_calloc(size_t num, size_t size)
125 {
126 	return kern_os_malloc(num * size); // malloc bzeroes the buffer
127 }
128 
129 cs_malloc_t cs_mem_malloc = kern_os_malloc;
130 cs_calloc_t cs_mem_calloc = cs_kern_os_calloc;
131 cs_realloc_t cs_mem_realloc = kern_os_realloc;
132 cs_free_t cs_mem_free = kern_os_free;
133 cs_vsnprintf_t cs_vsnprintf = vsnprintf;
134 #endif
135 #else
136 cs_malloc_t cs_mem_malloc = NULL;
137 cs_calloc_t cs_mem_calloc = NULL;
138 cs_realloc_t cs_mem_realloc = NULL;
139 cs_free_t cs_mem_free = NULL;
140 cs_vsnprintf_t cs_vsnprintf = NULL;
141 #endif
142 
143 CAPSTONE_EXPORT
cs_version(int * major,int * minor)144 unsigned int CAPSTONE_API cs_version(int *major, int *minor)
145 {
146 	archs_enable();
147 
148 	if (major != NULL && minor != NULL) {
149 		*major = CS_API_MAJOR;
150 		*minor = CS_API_MINOR;
151 	}
152 
153 	return (CS_API_MAJOR << 8) + CS_API_MINOR;
154 }
155 
156 CAPSTONE_EXPORT
cs_support(int query)157 bool CAPSTONE_API cs_support(int query)
158 {
159 	archs_enable();
160 
161 	if (query == CS_ARCH_ALL)
162 		return all_arch == ((1 << CS_ARCH_ARM) | (1 << CS_ARCH_ARM64) |
163 				(1 << CS_ARCH_MIPS) | (1 << CS_ARCH_X86) |
164 				(1 << CS_ARCH_PPC) | (1 << CS_ARCH_SPARC) |
165 				(1 << CS_ARCH_SYSZ) | (1 << CS_ARCH_XCORE));
166 
167 	if ((unsigned int)query < CS_ARCH_MAX)
168 		return all_arch & (1 << query);
169 
170 	if (query == CS_SUPPORT_DIET) {
171 #ifdef CAPSTONE_DIET
172 		return true;
173 #else
174 		return false;
175 #endif
176 	}
177 
178 	if (query == CS_SUPPORT_X86_REDUCE) {
179 #if defined(CAPSTONE_HAS_X86) && defined(CAPSTONE_X86_REDUCE)
180 		return true;
181 #else
182 		return false;
183 #endif
184 	}
185 
186 	// unsupported query
187 	return false;
188 }
189 
190 CAPSTONE_EXPORT
cs_errno(csh handle)191 cs_err CAPSTONE_API cs_errno(csh handle)
192 {
193 	struct cs_struct *ud;
194 	if (!handle)
195 		return CS_ERR_CSH;
196 
197 	ud = (struct cs_struct *)(uintptr_t)handle;
198 
199 	return ud->errnum;
200 }
201 
202 CAPSTONE_EXPORT
cs_strerror(cs_err code)203 const char * CAPSTONE_API cs_strerror(cs_err code)
204 {
205 	switch(code) {
206 		default:
207 			return "Unknown error code";
208 		case CS_ERR_OK:
209 			return "OK (CS_ERR_OK)";
210 		case CS_ERR_MEM:
211 			return "Out of memory (CS_ERR_MEM)";
212 		case CS_ERR_ARCH:
213 			return "Invalid architecture (CS_ERR_ARCH)";
214 		case CS_ERR_HANDLE:
215 			return "Invalid handle (CS_ERR_HANDLE)";
216 		case CS_ERR_CSH:
217 			return "Invalid csh (CS_ERR_CSH)";
218 		case CS_ERR_MODE:
219 			return "Invalid mode (CS_ERR_MODE)";
220 		case CS_ERR_OPTION:
221 			return "Invalid option (CS_ERR_OPTION)";
222 		case CS_ERR_DETAIL:
223 			return "Details are unavailable (CS_ERR_DETAIL)";
224 		case CS_ERR_MEMSETUP:
225 			return "Dynamic memory management uninitialized (CS_ERR_MEMSETUP)";
226 		case CS_ERR_VERSION:
227 			return "Different API version between core & binding (CS_ERR_VERSION)";
228 		case CS_ERR_DIET:
229 			return "Information irrelevant in diet engine (CS_ERR_DIET)";
230 		case CS_ERR_SKIPDATA:
231 			return "Information irrelevant for 'data' instruction in SKIPDATA mode (CS_ERR_SKIPDATA)";
232 	}
233 }
234 
235 CAPSTONE_EXPORT
cs_open(cs_arch arch,cs_mode mode,csh * handle)236 cs_err CAPSTONE_API cs_open(cs_arch arch, cs_mode mode, csh *handle)
237 {
238 	cs_err err;
239 	struct cs_struct *ud;
240 	if (!cs_mem_malloc || !cs_mem_calloc || !cs_mem_realloc || !cs_mem_free || !cs_vsnprintf)
241 		// Error: before cs_open(), dynamic memory management must be initialized
242 		// with cs_option(CS_OPT_MEM)
243 		return CS_ERR_MEMSETUP;
244 
245 	archs_enable();
246 
247 	if (arch < CS_ARCH_MAX && arch_init[arch]) {
248 		// verify if requested mode is valid
249 		if (mode & arch_disallowed_mode_mask[arch]) {
250 			*handle = 0;
251 			return CS_ERR_MODE;
252 		}
253 
254 		ud = cs_mem_calloc(1, sizeof(*ud));
255 		if (!ud) {
256 			// memory insufficient
257 			return CS_ERR_MEM;
258 		}
259 
260 		ud->errnum = CS_ERR_OK;
261 		ud->arch = arch;
262 		ud->mode = mode;
263 		// by default, do not break instruction into details
264 		ud->detail = CS_OPT_OFF;
265 
266 		// default skipdata setup
267 		ud->skipdata_setup.mnemonic = SKIPDATA_MNEM;
268 
269 		err = arch_init[ud->arch](ud);
270 		if (err) {
271 			cs_mem_free(ud);
272 			*handle = 0;
273 			return err;
274 		}
275 
276 		*handle = (uintptr_t)ud;
277 
278 		return CS_ERR_OK;
279 	} else {
280 		*handle = 0;
281 		return CS_ERR_ARCH;
282 	}
283 }
284 
285 CAPSTONE_EXPORT
cs_close(csh * handle)286 cs_err CAPSTONE_API cs_close(csh *handle)
287 {
288 	struct cs_struct *ud;
289 
290 	if (*handle == 0)
291 		// invalid handle
292 		return CS_ERR_CSH;
293 
294 	ud = (struct cs_struct *)(*handle);
295 
296 	if (ud->printer_info)
297 		cs_mem_free(ud->printer_info);
298 
299 	cs_mem_free(ud->insn_cache);
300 
301 	memset(ud, 0, sizeof(*ud));
302 	cs_mem_free(ud);
303 
304 	// invalidate this handle by ZERO out its value.
305 	// this is to make sure it is unusable after cs_close()
306 	*handle = 0;
307 
308 	return CS_ERR_OK;
309 }
310 
311 // fill insn with mnemonic & operands info
fill_insn(struct cs_struct * handle,cs_insn * insn,char * buffer,MCInst * mci,PostPrinter_t postprinter,const uint8_t * code)312 static void fill_insn(struct cs_struct *handle, cs_insn *insn, char *buffer, MCInst *mci,
313 		PostPrinter_t postprinter, const uint8_t *code)
314 {
315 #ifndef CAPSTONE_DIET
316 	char *sp, *mnem;
317 #endif
318 	uint16_t copy_size = MIN(sizeof(insn->bytes), insn->size);
319 
320 	// fill the instruction bytes.
321 	// we might skip some redundant bytes in front in the case of X86
322 	memcpy(insn->bytes, code + insn->size - copy_size, copy_size);
323 	insn->size = copy_size;
324 
325 	// alias instruction might have ID saved in OpcodePub
326 	if (MCInst_getOpcodePub(mci))
327 		insn->id = MCInst_getOpcodePub(mci);
328 
329 	// post printer handles some corner cases (hacky)
330 	if (postprinter)
331 		postprinter((csh)handle, insn, buffer, mci);
332 
333 #ifndef CAPSTONE_DIET
334 	// fill in mnemonic & operands
335 	// find first space or tab
336 	mnem = insn->mnemonic;
337 	for (sp = buffer; *sp; sp++) {
338 		if (*sp == ' '|| *sp == '\t')
339 			break;
340 		if (*sp == '|')	// lock|rep prefix for x86
341 			*sp = ' ';
342 		// copy to @mnemonic
343 		*mnem = *sp;
344 		mnem++;
345 	}
346 
347 	*mnem = '\0';
348 
349 	// copy @op_str
350 	if (*sp) {
351 		// find the next non-space char
352 		sp++;
353 		for (; ((*sp == ' ') || (*sp == '\t')); sp++);
354 		strncpy(insn->op_str, sp, sizeof(insn->op_str) - 1);
355 		insn->op_str[sizeof(insn->op_str) - 1] = '\0';
356 	} else
357 		insn->op_str[0] = '\0';
358 #endif
359 }
360 
361 // how many bytes will we skip when encountering data (CS_OPT_SKIPDATA)?
362 // this very much depends on instruction alignment requirement of each arch.
skipdata_size(cs_struct * handle)363 static uint8_t skipdata_size(cs_struct *handle)
364 {
365 	switch(handle->arch) {
366 		default:
367 			// should never reach
368 			return (uint8_t)-1;
369 		case CS_ARCH_ARM:
370 			// skip 2 bytes on Thumb mode.
371 			if (handle->mode & CS_MODE_THUMB)
372 				return 2;
373 			// otherwise, skip 4 bytes
374 			return 4;
375 		case CS_ARCH_ARM64:
376 		case CS_ARCH_MIPS:
377 		case CS_ARCH_PPC:
378 		case CS_ARCH_SPARC:
379 			// skip 4 bytes
380 			return 4;
381 		case CS_ARCH_SYSZ:
382 			// SystemZ instruction's length can be 2, 4 or 6 bytes,
383 			// so we just skip 2 bytes
384 			return 2;
385 		case CS_ARCH_X86:
386 			// X86 has no restriction on instruction alignment
387 			return 1;
388 		case CS_ARCH_XCORE:
389 			// XCore instruction's length can be 2 or 4 bytes,
390 			// so we just skip 2 bytes
391 			return 2;
392 	}
393 }
394 
395 CAPSTONE_EXPORT
cs_option(csh ud,cs_opt_type type,size_t value)396 cs_err CAPSTONE_API cs_option(csh ud, cs_opt_type type, size_t value)
397 {
398 	struct cs_struct *handle;
399 	archs_enable();
400 
401 	// cs_option() can be called with NULL handle just for CS_OPT_MEM
402 	// This is supposed to be executed before all other APIs (even cs_open())
403 	if (type == CS_OPT_MEM) {
404 		cs_opt_mem *mem = (cs_opt_mem *)value;
405 
406 		cs_mem_malloc = mem->malloc;
407 		cs_mem_calloc = mem->calloc;
408 		cs_mem_realloc = mem->realloc;
409 		cs_mem_free = mem->free;
410 		cs_vsnprintf = mem->vsnprintf;
411 
412 		return CS_ERR_OK;
413 	}
414 
415 	handle = (struct cs_struct *)(uintptr_t)ud;
416 	if (!handle)
417 		return CS_ERR_CSH;
418 
419 	switch(type) {
420 		default:
421 			break;
422 		case CS_OPT_DETAIL:
423 			handle->detail = (cs_opt_value)value;
424 			return CS_ERR_OK;
425 		case CS_OPT_SKIPDATA:
426 			handle->skipdata = (value == CS_OPT_ON);
427 			if (handle->skipdata) {
428 				if (handle->skipdata_size == 0) {
429 					// set the default skipdata size
430 					handle->skipdata_size = skipdata_size(handle);
431 				}
432 			}
433 			return CS_ERR_OK;
434 		case CS_OPT_SKIPDATA_SETUP:
435 			if (value)
436 				handle->skipdata_setup = *((cs_opt_skipdata *)value);
437 			return CS_ERR_OK;
438 		case CS_OPT_MODE:
439 			// verify if requested mode is valid
440 			if (value & arch_disallowed_mode_mask[handle->arch]) {
441 				return CS_ERR_OPTION;
442 			}
443 			break;
444 	}
445 
446 	return arch_option[handle->arch](handle, type, value);
447 }
448 
449 // generate @op_str for data instruction of SKIPDATA
450 #ifndef CAPSTONE_DIET
skipdata_opstr(char * opstr,const uint8_t * buffer,size_t size)451 static void skipdata_opstr(char *opstr, const uint8_t *buffer, size_t size)
452 {
453 	char *p = opstr;
454 	int len;
455 	size_t i;
456 	size_t available = sizeof(((cs_insn*)NULL)->op_str);
457 
458 	if (!size) {
459 		opstr[0] = '\0';
460 		return;
461 	}
462 
463 	len = cs_snprintf(p, available, "0x%02x", buffer[0]);
464 	p+= len;
465 	available -= len;
466 
467 	for(i = 1; i < size; i++) {
468 		len = cs_snprintf(p, available, ", 0x%02x", buffer[i]);
469 		if (len < 0) {
470 			break;
471 		}
472 		if ((size_t)len > available - 1) {
473 			break;
474 		}
475 		p+= len;
476 		available -= len;
477 	}
478 }
479 #endif
480 
481 // dynamicly allocate memory to contain disasm insn
482 // NOTE: caller must free() the allocated memory itself to avoid memory leaking
483 CAPSTONE_EXPORT
cs_disasm(csh ud,const uint8_t * buffer,size_t size,uint64_t offset,size_t count,cs_insn ** insn)484 size_t CAPSTONE_API cs_disasm(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
485 {
486 	struct cs_struct *handle;
487 	MCInst mci;
488 	uint16_t insn_size;
489 	size_t c = 0, i;
490 	unsigned int f = 0;	// index of the next instruction in the cache
491 	cs_insn *insn_cache;	// cache contains disassembled instructions
492 	void *total = NULL;
493 	size_t total_size = 0;	// total size of output buffer containing all insns
494 	bool r;
495 	void *tmp;
496 	size_t skipdata_bytes;
497 	uint64_t offset_org; // save all the original info of the buffer
498 	size_t size_org;
499 	const uint8_t *buffer_org;
500 	unsigned int cache_size = INSN_CACHE_SIZE;
501 	size_t next_offset;
502 
503 	handle = (struct cs_struct *)(uintptr_t)ud;
504 	if (!handle) {
505 		// FIXME: how to handle this case:
506 		// handle->errnum = CS_ERR_HANDLE;
507 		return 0;
508 	}
509 
510 	handle->errnum = CS_ERR_OK;
511 
512 	// reset IT block of ARM structure
513 	if (handle->arch == CS_ARCH_ARM)
514 		handle->ITBlock.size = 0;
515 
516 #ifdef CAPSTONE_USE_SYS_DYN_MEM
517 	if (count > 0 && count <= INSN_CACHE_SIZE)
518 		cache_size = (unsigned int) count;
519 #endif
520 
521 	// save the original offset for SKIPDATA
522 	buffer_org = buffer;
523 	offset_org = offset;
524 	size_org = size;
525 
526 	total_size = sizeof(cs_insn) * cache_size;
527 	total = cs_mem_malloc(total_size);
528 	if (total == NULL) {
529 		// insufficient memory
530 		handle->errnum = CS_ERR_MEM;
531 		return 0;
532 	}
533 
534 	insn_cache = total;
535 
536 	while (size > 0) {
537 		MCInst_Init(&mci);
538 		mci.csh = handle;
539 
540 		// relative branches need to know the address & size of current insn
541 		mci.address = offset;
542 
543 		if (handle->detail) {
544 			// allocate memory for @detail pointer
545 			insn_cache->detail = cs_mem_malloc(sizeof(cs_detail));
546 		} else {
547 			insn_cache->detail = NULL;
548 		}
549 
550 		// save all the information for non-detailed mode
551 		mci.flat_insn = insn_cache;
552 		mci.flat_insn->address = offset;
553 #ifdef CAPSTONE_DIET
554 		// zero out mnemonic & op_str
555 		mci.flat_insn->mnemonic[0] = '\0';
556 		mci.flat_insn->op_str[0] = '\0';
557 #endif
558 
559 		r = handle->disasm(ud, buffer, size, &mci, &insn_size, offset, handle->getinsn_info);
560 		if (r) {
561 			SStream ss;
562 			SStream_Init(&ss);
563 
564 			mci.flat_insn->size = insn_size;
565 
566 			// map internal instruction opcode to public insn ID
567 
568 			handle->insn_id(handle, insn_cache, mci.Opcode);
569 
570 			handle->printer(&mci, &ss, handle->printer_info);
571 
572 			fill_insn(handle, insn_cache, ss.buffer, &mci, handle->post_printer, buffer);
573 
574 			next_offset = insn_size;
575 		} else	{
576 			// encounter a broken instruction
577 
578 			// free memory of @detail pointer
579 			if (handle->detail) {
580 				cs_mem_free(insn_cache->detail);
581 			}
582 
583 			// if there is no request to skip data, or remaining data is too small,
584 			// then bail out
585 			if (!handle->skipdata || handle->skipdata_size > size)
586 				break;
587 
588 			if (handle->skipdata_setup.callback) {
589 				skipdata_bytes = handle->skipdata_setup.callback(buffer_org, size_org,
590 						(size_t)(offset - offset_org), handle->skipdata_setup.user_data);
591 				if (skipdata_bytes > size)
592 					// remaining data is not enough
593 					break;
594 
595 				if (!skipdata_bytes)
596 					// user requested not to skip data, so bail out
597 					break;
598 			} else
599 				skipdata_bytes = handle->skipdata_size;
600 
601 			// we have to skip some amount of data, depending on arch & mode
602 			insn_cache->id = 0;	// invalid ID for this "data" instruction
603 			insn_cache->address = offset;
604 			insn_cache->size = (uint16_t)skipdata_bytes;
605 			memcpy(insn_cache->bytes, buffer, skipdata_bytes);
606 #ifdef CAPSTONE_DIET
607  			insn_cache->mnemonic[0] = '\0';
608 			insn_cache->op_str[0] = '\0';
609 #else
610 			strncpy(insn_cache->mnemonic, handle->skipdata_setup.mnemonic,
611   					sizeof(insn_cache->mnemonic) - 1);
612   			skipdata_opstr(insn_cache->op_str, buffer, skipdata_bytes);
613 #endif
614 			insn_cache->detail = NULL;
615 
616 			next_offset = skipdata_bytes;
617 		}
618 
619 		// one more instruction entering the cache
620 		f++;
621 
622 		// one more instruction disassembled
623 		c++;
624 		if (count > 0 && c == count)
625 			// already got requested number of instructions
626 			break;
627 
628 		if (f == cache_size) {
629 			// full cache, so expand the cache to contain incoming insns
630 			cache_size = cache_size * 8 / 5; // * 1.6 ~ golden ratio
631 			total_size += (sizeof(cs_insn) * cache_size);
632 			tmp = cs_mem_realloc(total, total_size);
633 			if (tmp == NULL) {	// insufficient memory
634 				if (handle->detail) {
635 					insn_cache = (cs_insn *)total;
636 					for (i = 0; i < c; i++, insn_cache++)
637 						cs_mem_free(insn_cache->detail);
638 				}
639 
640 				cs_mem_free(total);
641 				*insn = NULL;
642 				handle->errnum = CS_ERR_MEM;
643 				return 0;
644 			}
645 
646 			total = tmp;
647 			// continue to fill in the cache after the last instruction
648 			insn_cache = (cs_insn *)((char *)total + sizeof(cs_insn) * c);
649 
650 			// reset f back to 0, so we fill in the cache from begining
651 			f = 0;
652 		} else
653 			insn_cache++;
654 
655 		buffer += next_offset;
656 		size -= next_offset;
657 		offset += next_offset;
658 	}
659 
660 	if (!c) {
661 		// we did not disassemble any instruction
662 		cs_mem_free(total);
663 		total = NULL;
664 	} else if (f != cache_size) {
665 		// total did not fully use the last cache, so downsize it
666 		tmp = cs_mem_realloc(total, total_size - (cache_size - f) * sizeof(*insn_cache));
667 		if (tmp == NULL) {	// insufficient memory
668 			// free all detail pointers
669 			if (handle->detail) {
670 				insn_cache = (cs_insn *)total;
671 				for (i = 0; i < c; i++, insn_cache++)
672 					cs_mem_free(insn_cache->detail);
673 			}
674 
675 			cs_mem_free(total);
676 			*insn = NULL;
677 
678 			handle->errnum = CS_ERR_MEM;
679 			return 0;
680 		}
681 
682 		total = tmp;
683 	}
684 
685 	*insn = total;
686 
687 	return c;
688 }
689 
690 CAPSTONE_EXPORT
691 CAPSTONE_DEPRECATED
cs_disasm_ex(csh ud,const uint8_t * buffer,size_t size,uint64_t offset,size_t count,cs_insn ** insn)692 size_t CAPSTONE_API cs_disasm_ex(csh ud, const uint8_t *buffer, size_t size, uint64_t offset, size_t count, cs_insn **insn)
693 {
694 	return cs_disasm(ud, buffer, size, offset, count, insn);
695 }
696 
697 CAPSTONE_EXPORT
cs_free(cs_insn * insn,size_t count)698 void CAPSTONE_API cs_free(cs_insn *insn, size_t count)
699 {
700 	size_t i;
701 
702 	// free all detail pointers
703 	for (i = 0; i < count; i++)
704 		cs_mem_free(insn[i].detail);
705 
706 	// then free pointer to cs_insn array
707 	cs_mem_free(insn);
708 }
709 
710 CAPSTONE_EXPORT
cs_malloc(csh ud)711 cs_insn * CAPSTONE_API cs_malloc(csh ud)
712 {
713 	cs_insn *insn;
714 	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
715 
716 	insn = cs_mem_malloc(sizeof(cs_insn));
717 	if (!insn) {
718 		// insufficient memory
719 		handle->errnum = CS_ERR_MEM;
720 		return NULL;
721 	} else {
722 		if (handle->detail) {
723 			// allocate memory for @detail pointer
724 			insn->detail = cs_mem_malloc(sizeof(cs_detail));
725 			if (insn->detail == NULL) {	// insufficient memory
726 				cs_mem_free(insn);
727 				handle->errnum = CS_ERR_MEM;
728 				return NULL;
729 			}
730 		} else
731 			insn->detail = NULL;
732 	}
733 
734 	return insn;
735 }
736 
737 // iterator for instruction "single-stepping"
738 CAPSTONE_EXPORT
cs_disasm_iter(csh ud,const uint8_t ** code,size_t * size,uint64_t * address,cs_insn * insn)739 bool CAPSTONE_API cs_disasm_iter(csh ud, const uint8_t **code, size_t *size,
740 		uint64_t *address, cs_insn *insn)
741 {
742 	struct cs_struct *handle;
743 	uint16_t insn_size;
744 	MCInst mci;
745 	bool r;
746 
747 	handle = (struct cs_struct *)(uintptr_t)ud;
748 	if (!handle) {
749 		return false;
750 	}
751 
752 	handle->errnum = CS_ERR_OK;
753 
754 	MCInst_Init(&mci);
755 	mci.csh = handle;
756 
757 	// relative branches need to know the address & size of current insn
758 	mci.address = *address;
759 
760 	// save all the information for non-detailed mode
761 	mci.flat_insn = insn;
762 	mci.flat_insn->address = *address;
763 #ifdef CAPSTONE_DIET
764 	// zero out mnemonic & op_str
765 	mci.flat_insn->mnemonic[0] = '\0';
766 	mci.flat_insn->op_str[0] = '\0';
767 #endif
768 
769 	r = handle->disasm(ud, *code, *size, &mci, &insn_size, *address, handle->getinsn_info);
770 	if (r) {
771 		SStream ss;
772 		SStream_Init(&ss);
773 
774 		mci.flat_insn->size = insn_size;
775 
776 		// map internal instruction opcode to public insn ID
777 		handle->insn_id(handle, insn, mci.Opcode);
778 
779 		handle->printer(&mci, &ss, handle->printer_info);
780 
781 		fill_insn(handle, insn, ss.buffer, &mci, handle->post_printer, *code);
782 
783 		*code += insn_size;
784 		*size -= insn_size;
785 		*address += insn_size;
786 	} else { 	// encounter a broken instruction
787 		size_t skipdata_bytes;
788 
789 		// if there is no request to skip data, or remaining data is too small,
790 		// then bail out
791 		if (!handle->skipdata || handle->skipdata_size > *size)
792 			return false;
793 
794 		if (handle->skipdata_setup.callback) {
795 			skipdata_bytes = handle->skipdata_setup.callback(*code, *size,
796 					0, handle->skipdata_setup.user_data);
797 			if (skipdata_bytes > *size)
798 				// remaining data is not enough
799 				return false;
800 
801 			if (!skipdata_bytes)
802 				// user requested not to skip data, so bail out
803 				return false;
804 		} else
805 			skipdata_bytes = handle->skipdata_size;
806 
807 		// we have to skip some amount of data, depending on arch & mode
808 		insn->id = 0;	// invalid ID for this "data" instruction
809 		insn->address = *address;
810 		insn->size = (uint16_t)skipdata_bytes;
811 		memcpy(insn->bytes, *code, skipdata_bytes);
812 #ifdef CAPSTONE_DIET
813 		insn->mnemonic[0] = '\0';
814 		insn->op_str[0] = '\0';
815 #else
816 		strncpy(insn->mnemonic, handle->skipdata_setup.mnemonic,
817 				sizeof(insn->mnemonic) - 1);
818 		skipdata_opstr(insn->op_str, *code, skipdata_bytes);
819 #endif
820 
821 		*code += skipdata_bytes;
822 		*size -= skipdata_bytes;
823 		*address += skipdata_bytes;
824 	}
825 
826 	return true;
827 }
828 
829 // return friendly name of regiser in a string
830 CAPSTONE_EXPORT
cs_reg_name(csh ud,unsigned int reg)831 const char * CAPSTONE_API cs_reg_name(csh ud, unsigned int reg)
832 {
833 	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
834 
835 	if (!handle || handle->reg_name == NULL) {
836 		return NULL;
837 	}
838 
839 	return handle->reg_name(ud, reg);
840 }
841 
842 CAPSTONE_EXPORT
cs_insn_name(csh ud,unsigned int insn)843 const char * CAPSTONE_API cs_insn_name(csh ud, unsigned int insn)
844 {
845 	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
846 
847 	if (!handle || handle->insn_name == NULL) {
848 		return NULL;
849 	}
850 
851 	return handle->insn_name(ud, insn);
852 }
853 
854 CAPSTONE_EXPORT
cs_group_name(csh ud,unsigned int group)855 const char * CAPSTONE_API cs_group_name(csh ud, unsigned int group)
856 {
857 	struct cs_struct *handle = (struct cs_struct *)(uintptr_t)ud;
858 
859 	if (!handle || handle->group_name == NULL) {
860 		return NULL;
861 	}
862 
863 	return handle->group_name(ud, group);
864 }
865 
arr_exist(unsigned char * arr,unsigned char max,unsigned int id)866 static bool arr_exist(unsigned char *arr, unsigned char max, unsigned int id)
867 {
868 	int i;
869 
870 	for (i = 0; i < max; i++) {
871 		if (arr[i] == id)
872 			return true;
873 	}
874 
875 	return false;
876 }
877 
878 CAPSTONE_EXPORT
cs_insn_group(csh ud,const cs_insn * insn,unsigned int group_id)879 bool CAPSTONE_API cs_insn_group(csh ud, const cs_insn *insn, unsigned int group_id)
880 {
881 	struct cs_struct *handle;
882 	if (!ud)
883 		return false;
884 
885 	handle = (struct cs_struct *)(uintptr_t)ud;
886 
887 	if (!handle->detail) {
888 		handle->errnum = CS_ERR_DETAIL;
889 		return false;
890 	}
891 
892 	if(!insn->id) {
893 		handle->errnum = CS_ERR_SKIPDATA;
894 		return false;
895 	}
896 
897 	if(!insn->detail) {
898 		handle->errnum = CS_ERR_DETAIL;
899 		return false;
900 	}
901 
902 	return arr_exist(insn->detail->groups, insn->detail->groups_count, group_id);
903 }
904 
905 CAPSTONE_EXPORT
cs_reg_read(csh ud,const cs_insn * insn,unsigned int reg_id)906 bool CAPSTONE_API cs_reg_read(csh ud, const cs_insn *insn, unsigned int reg_id)
907 {
908 	struct cs_struct *handle;
909 	if (!ud)
910 		return false;
911 
912 	handle = (struct cs_struct *)(uintptr_t)ud;
913 
914 	if (!handle->detail) {
915 		handle->errnum = CS_ERR_DETAIL;
916 		return false;
917 	}
918 
919 	if(!insn->id) {
920 		handle->errnum = CS_ERR_SKIPDATA;
921 		return false;
922 	}
923 
924 	if(!insn->detail) {
925 		handle->errnum = CS_ERR_DETAIL;
926 		return false;
927 	}
928 
929 	return arr_exist(insn->detail->regs_read, insn->detail->regs_read_count, reg_id);
930 }
931 
932 CAPSTONE_EXPORT
cs_reg_write(csh ud,const cs_insn * insn,unsigned int reg_id)933 bool CAPSTONE_API cs_reg_write(csh ud, const cs_insn *insn, unsigned int reg_id)
934 {
935 	struct cs_struct *handle;
936 	if (!ud)
937 		return false;
938 
939 	handle = (struct cs_struct *)(uintptr_t)ud;
940 
941 	if (!handle->detail) {
942 		handle->errnum = CS_ERR_DETAIL;
943 		return false;
944 	}
945 
946 	if(!insn->id) {
947 		handle->errnum = CS_ERR_SKIPDATA;
948 		return false;
949 	}
950 
951 	if(!insn->detail) {
952 		handle->errnum = CS_ERR_DETAIL;
953 		return false;
954 	}
955 
956 	return arr_exist(insn->detail->regs_write, insn->detail->regs_write_count, reg_id);
957 }
958 
959 CAPSTONE_EXPORT
cs_op_count(csh ud,const cs_insn * insn,unsigned int op_type)960 int CAPSTONE_API cs_op_count(csh ud, const cs_insn *insn, unsigned int op_type)
961 {
962 	struct cs_struct *handle;
963 	unsigned int count = 0, i;
964 	if (!ud)
965 		return -1;
966 
967 	handle = (struct cs_struct *)(uintptr_t)ud;
968 
969 	if (!handle->detail) {
970 		handle->errnum = CS_ERR_DETAIL;
971 		return -1;
972 	}
973 
974 	if(!insn->id) {
975 		handle->errnum = CS_ERR_SKIPDATA;
976 		return -1;
977 	}
978 
979 	if(!insn->detail) {
980 		handle->errnum = CS_ERR_DETAIL;
981 		return -1;
982 	}
983 
984 	handle->errnum = CS_ERR_OK;
985 
986 	switch (handle->arch) {
987 		default:
988 			handle->errnum = CS_ERR_HANDLE;
989 			return -1;
990 		case CS_ARCH_ARM:
991 			for (i = 0; i < insn->detail->arm.op_count; i++)
992 				if (insn->detail->arm.operands[i].type == (arm_op_type)op_type)
993 					count++;
994 			break;
995 		case CS_ARCH_ARM64:
996 			for (i = 0; i < insn->detail->arm64.op_count; i++)
997 				if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type)
998 					count++;
999 			break;
1000 		case CS_ARCH_X86:
1001 			for (i = 0; i < insn->detail->x86.op_count; i++)
1002 				if (insn->detail->x86.operands[i].type == (x86_op_type)op_type)
1003 					count++;
1004 			break;
1005 		case CS_ARCH_MIPS:
1006 			for (i = 0; i < insn->detail->mips.op_count; i++)
1007 				if (insn->detail->mips.operands[i].type == (mips_op_type)op_type)
1008 					count++;
1009 			break;
1010 		case CS_ARCH_PPC:
1011 			for (i = 0; i < insn->detail->ppc.op_count; i++)
1012 				if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type)
1013 					count++;
1014 			break;
1015 		case CS_ARCH_SPARC:
1016 			for (i = 0; i < insn->detail->sparc.op_count; i++)
1017 				if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type)
1018 					count++;
1019 			break;
1020 		case CS_ARCH_SYSZ:
1021 			for (i = 0; i < insn->detail->sysz.op_count; i++)
1022 				if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type)
1023 					count++;
1024 			break;
1025 		case CS_ARCH_XCORE:
1026 			for (i = 0; i < insn->detail->xcore.op_count; i++)
1027 				if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type)
1028 					count++;
1029 			break;
1030 	}
1031 
1032 	return count;
1033 }
1034 
1035 CAPSTONE_EXPORT
cs_op_index(csh ud,const cs_insn * insn,unsigned int op_type,unsigned int post)1036 int CAPSTONE_API cs_op_index(csh ud, const cs_insn *insn, unsigned int op_type,
1037 		unsigned int post)
1038 {
1039 	struct cs_struct *handle;
1040 	unsigned int count = 0, i;
1041 	if (!ud)
1042 		return -1;
1043 
1044 	handle = (struct cs_struct *)(uintptr_t)ud;
1045 
1046 	if (!handle->detail) {
1047 		handle->errnum = CS_ERR_DETAIL;
1048 		return -1;
1049 	}
1050 
1051 	if(!insn->id) {
1052 		handle->errnum = CS_ERR_SKIPDATA;
1053 		return -1;
1054 	}
1055 
1056 	if(!insn->detail) {
1057 		handle->errnum = CS_ERR_DETAIL;
1058 		return -1;
1059 	}
1060 
1061 	handle->errnum = CS_ERR_OK;
1062 
1063 	switch (handle->arch) {
1064 		default:
1065 			handle->errnum = CS_ERR_HANDLE;
1066 			return -1;
1067 		case CS_ARCH_ARM:
1068 			for (i = 0; i < insn->detail->arm.op_count; i++) {
1069 				if (insn->detail->arm.operands[i].type == (arm_op_type)op_type)
1070 					count++;
1071 				if (count == post)
1072 					return i;
1073 			}
1074 			break;
1075 		case CS_ARCH_ARM64:
1076 			for (i = 0; i < insn->detail->arm64.op_count; i++) {
1077 				if (insn->detail->arm64.operands[i].type == (arm64_op_type)op_type)
1078 					count++;
1079 				if (count == post)
1080 					return i;
1081 			}
1082 			break;
1083 		case CS_ARCH_X86:
1084 			for (i = 0; i < insn->detail->x86.op_count; i++) {
1085 				if (insn->detail->x86.operands[i].type == (x86_op_type)op_type)
1086 					count++;
1087 				if (count == post)
1088 					return i;
1089 			}
1090 			break;
1091 		case CS_ARCH_MIPS:
1092 			for (i = 0; i < insn->detail->mips.op_count; i++) {
1093 				if (insn->detail->mips.operands[i].type == (mips_op_type)op_type)
1094 					count++;
1095 				if (count == post)
1096 					return i;
1097 			}
1098 			break;
1099 		case CS_ARCH_PPC:
1100 			for (i = 0; i < insn->detail->ppc.op_count; i++) {
1101 				if (insn->detail->ppc.operands[i].type == (ppc_op_type)op_type)
1102 					count++;
1103 				if (count == post)
1104 					return i;
1105 			}
1106 			break;
1107 		case CS_ARCH_SPARC:
1108 			for (i = 0; i < insn->detail->sparc.op_count; i++) {
1109 				if (insn->detail->sparc.operands[i].type == (sparc_op_type)op_type)
1110 					count++;
1111 				if (count == post)
1112 					return i;
1113 			}
1114 			break;
1115 		case CS_ARCH_SYSZ:
1116 			for (i = 0; i < insn->detail->sysz.op_count; i++) {
1117 				if (insn->detail->sysz.operands[i].type == (sysz_op_type)op_type)
1118 					count++;
1119 				if (count == post)
1120 					return i;
1121 			}
1122 			break;
1123 		case CS_ARCH_XCORE:
1124 			for (i = 0; i < insn->detail->xcore.op_count; i++) {
1125 				if (insn->detail->xcore.operands[i].type == (xcore_op_type)op_type)
1126 					count++;
1127 				if (count == post)
1128 					return i;
1129 			}
1130 			break;
1131 	}
1132 
1133 	return -1;
1134 }
1135