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