/src/capstonenext/utils.c
Line  | Count  | Source  | 
1  |  | /* Capstone Disassembly Engine */  | 
2  |  | /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */  | 
3  |  |  | 
4  |  | #if defined(CAPSTONE_HAS_OSXKERNEL)  | 
5  |  | #include <Availability.h>  | 
6  |  | #include <libkern/libkern.h>  | 
7  |  | #else  | 
8  |  | #include <stdlib.h>  | 
9  |  | #endif  | 
10  |  | #include <string.h>  | 
11  |  | #include <ctype.h>  | 
12  |  |  | 
13  |  | #include "utils.h"  | 
14  |  |  | 
15  |  | // count number of positive members in a list.  | 
16  |  | // NOTE: list must be guaranteed to end in 0  | 
17  |  | unsigned int count_positive(const uint16_t *list)  | 
18  | 6.51M  | { | 
19  | 6.51M  |   unsigned int c;  | 
20  |  |  | 
21  | 8.50M  |   for (c = 0; list[c] > 0; c++)  | 
22  | 1.99M  |     ;  | 
23  |  |  | 
24  | 6.51M  |   return c;  | 
25  | 6.51M  | }  | 
26  |  |  | 
27  |  | // count number of positive members in a list.  | 
28  |  | // NOTE: list must be guaranteed to end in 0  | 
29  |  | unsigned int count_positive8(const unsigned char *list)  | 
30  | 3.25M  | { | 
31  | 3.25M  |   unsigned int c;  | 
32  |  |  | 
33  | 5.59M  |   for (c = 0; list[c] > 0; c++)  | 
34  | 2.33M  |     ;  | 
35  |  |  | 
36  | 3.25M  |   return c;  | 
37  | 3.25M  | }  | 
38  |  |  | 
39  |  | char *cs_strdup(const char *str)  | 
40  | 221k  | { | 
41  | 221k  |   size_t len = strlen(str) + 1;  | 
42  | 221k  |   void *new = cs_mem_malloc(len);  | 
43  |  |  | 
44  | 221k  |   if (new == NULL)  | 
45  | 0  |     return NULL;  | 
46  |  |  | 
47  | 221k  |   return (char *)memmove(new, str, len);  | 
48  | 221k  | }  | 
49  |  |  | 
50  |  | // we need this since Windows doesn't have snprintf()  | 
51  |  | int cs_snprintf(char *buffer, size_t size, const char *fmt, ...)  | 
52  | 238k  | { | 
53  | 238k  |   int ret;  | 
54  |  |  | 
55  | 238k  |   va_list ap;  | 
56  | 238k  |   va_start(ap, fmt);  | 
57  | 238k  |   ret = cs_vsnprintf(buffer, size, fmt, ap);  | 
58  | 238k  |   va_end(ap);  | 
59  |  |  | 
60  | 238k  |   return ret;  | 
61  | 238k  | }  | 
62  |  |  | 
63  |  | bool arr_exist8(unsigned char *arr, unsigned char max, unsigned int id)  | 
64  | 0  | { | 
65  | 0  |   int i;  | 
66  |  | 
  | 
67  | 0  |   for (i = 0; i < max; i++) { | 
68  | 0  |     if (arr[i] == id)  | 
69  | 0  |       return true;  | 
70  | 0  |   }  | 
71  |  |  | 
72  | 0  |   return false;  | 
73  | 0  | }  | 
74  |  |  | 
75  |  | bool arr_exist(uint16_t *arr, unsigned char max, unsigned int id)  | 
76  | 1.31M  | { | 
77  | 1.31M  |   int i;  | 
78  |  |  | 
79  | 1.38M  |   for (i = 0; i < max; i++) { | 
80  | 152k  |     if (arr[i] == id)  | 
81  | 81.5k  |       return true;  | 
82  | 152k  |   }  | 
83  |  |  | 
84  | 1.23M  |   return false;  | 
85  | 1.31M  | }  | 
86  |  |  | 
87  |  | /// @brief Checks if the @id is in the @table. @table has @table_size elements.  | 
88  |  | /// @param table The table with the values to compare to.  | 
89  |  | /// @param table_size The number elements in the table.  | 
90  |  | /// @param id The identifier to search for in the table.  | 
91  |  | /// @return True if @id is part of the @table, false otherwise.  | 
92  |  | bool arr_exist_int(int *table, size_t table_size, int id)  | 
93  | 0  | { | 
94  | 0  |   int i;  | 
95  | 0  |   for (i = 0; i < table_size; i++) { | 
96  | 0  |     if (table[i] == id)  | 
97  | 0  |       return true;  | 
98  | 0  |   }  | 
99  |  |  | 
100  | 0  |   return false;  | 
101  | 0  | }  | 
102  |  |  | 
103  |  | /// Reads 8 bytes in the endian order specified in MI->cs->mode.  | 
104  |  | uint64_t readBytes64(MCInst *MI, const uint8_t *Bytes)  | 
105  | 0  | { | 
106  | 0  |   assert(MI && Bytes);  | 
107  | 0  |   uint64_t Insn;  | 
108  | 0  |   if (MODE_IS_BIG_ENDIAN(MI->csh->mode))  | 
109  | 0  |     Insn = ((uint64_t)Bytes[7] << 0) | ((uint64_t)Bytes[6] << 8) |  | 
110  | 0  |            ((uint64_t)Bytes[5] << 16) | ((uint64_t)Bytes[4] << 24) |  | 
111  | 0  |            ((uint64_t)Bytes[3] << 32) | ((uint64_t)Bytes[2] << 40) |  | 
112  | 0  |            ((uint64_t)Bytes[1] << 48) | ((uint64_t)Bytes[0] << 56);  | 
113  | 0  |   else  | 
114  | 0  |     Insn = ((uint64_t)Bytes[7] << 56) | ((uint64_t)Bytes[6] << 48) |  | 
115  | 0  |            ((uint64_t)Bytes[5] << 40) | ((uint64_t)Bytes[4] << 32) |  | 
116  | 0  |            ((uint64_t)Bytes[3] << 24) | ((uint64_t)Bytes[2] << 16) |  | 
117  | 0  |            ((uint64_t)Bytes[1] << 8) | ((uint64_t)Bytes[0] << 0);  | 
118  | 0  |   return Insn;  | 
119  | 0  | }  | 
120  |  |  | 
121  |  | /// Reads 6 bytes in the endian order specified in MI->cs->mode.  | 
122  |  | uint64_t readBytes48(MCInst *MI, const uint8_t *Bytes)  | 
123  | 74.4k  | { | 
124  | 74.4k  |   assert(MI && Bytes);  | 
125  | 74.4k  |   uint64_t Insn;  | 
126  | 74.4k  |   if (MODE_IS_BIG_ENDIAN(MI->csh->mode))  | 
127  | 74.4k  |     Insn = ((uint64_t)Bytes[5] << 0) | ((uint64_t)Bytes[4] << 8) |  | 
128  | 74.4k  |            ((uint64_t)Bytes[3] << 16) | ((uint64_t)Bytes[2] << 24) |  | 
129  | 74.4k  |            ((uint64_t)Bytes[1] << 32) | ((uint64_t)Bytes[0] << 40);  | 
130  | 0  |   else  | 
131  | 0  |     Insn = ((uint64_t)Bytes[5] << 40) | ((uint64_t)Bytes[4] << 32) |  | 
132  | 0  |            ((uint64_t)Bytes[3] << 24) | ((uint64_t)Bytes[2] << 16) |  | 
133  | 0  |            ((uint64_t)Bytes[1] << 8) | ((uint64_t)Bytes[0] << 0);  | 
134  | 74.4k  |   return Insn;  | 
135  | 74.4k  | }  | 
136  |  |  | 
137  |  | /// Reads 4 bytes in the endian order specified in MI->cs->mode.  | 
138  |  | uint32_t readBytes32(MCInst *MI, const uint8_t *Bytes)  | 
139  | 981k  | { | 
140  | 981k  |   assert(MI && Bytes);  | 
141  | 981k  |   uint32_t Insn;  | 
142  | 981k  |   if (MODE_IS_BIG_ENDIAN(MI->csh->mode))  | 
143  | 434k  |     Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) |  | 
144  | 434k  |            ((uint32_t)Bytes[0] << 24);  | 
145  | 547k  |   else  | 
146  | 547k  |     Insn = ((uint32_t)Bytes[3] << 24) | (Bytes[2] << 16) |  | 
147  | 547k  |            (Bytes[1] << 8) | (Bytes[0] << 0);  | 
148  | 981k  |   return Insn;  | 
149  | 981k  | }  | 
150  |  |  | 
151  |  | /// Reads 3 bytes in the endian order specified in MI->cs->mode.  | 
152  |  | uint32_t readBytes24(MCInst *MI, const uint8_t *Bytes)  | 
153  | 74.1k  | { | 
154  | 74.1k  |   assert(MI && Bytes);  | 
155  | 74.1k  |   uint32_t Insn;  | 
156  | 74.1k  |   if (MODE_IS_BIG_ENDIAN(MI->csh->mode))  | 
157  | 0  |     Insn = (Bytes[2]) | (Bytes[1] << 8) |  | 
158  | 0  |            ((uint32_t)Bytes[0] << 16);  | 
159  | 74.1k  |   else  | 
160  | 74.1k  |     Insn = (Bytes[2] << 16) | (Bytes[1] << 8) |  | 
161  | 74.1k  |            ((uint32_t)Bytes[0]);  | 
162  | 74.1k  |   return Insn;  | 
163  | 74.1k  | }  | 
164  |  |  | 
165  |  | /// Reads 2 bytes in the endian order specified in MI->cs->mode.  | 
166  |  | uint16_t readBytes16(MCInst *MI, const uint8_t *Bytes)  | 
167  | 1.34M  | { | 
168  | 1.34M  |   assert(MI && Bytes);  | 
169  | 1.34M  |   uint16_t Insn;  | 
170  | 1.34M  |   if (MODE_IS_BIG_ENDIAN(MI->csh->mode))  | 
171  | 57.8k  |     Insn = (Bytes[0] << 8) | Bytes[1];  | 
172  | 1.28M  |   else  | 
173  | 1.28M  |     Insn = (Bytes[1] << 8) | Bytes[0];  | 
174  |  |  | 
175  | 1.34M  |   return Insn;  | 
176  | 1.34M  | }  | 
177  |  |  | 
178  |  | /// @brief Appends the string @p src to the string @p str. @p src is put to lower case.  | 
179  |  | /// @param str The string to append to.  | 
180  |  | /// @param str_size The length of @p str  | 
181  |  | /// @param src The string to append.  | 
182  |  | /// Does nothing if any of the given strings is NULL.  | 
183  |  | void append_to_str_lower(char *str, size_t str_size, const char *src)  | 
184  | 11.0k  | { | 
185  | 11.0k  |   if (!str || !src) { | 
186  | 0  |     return;  | 
187  | 0  |   }  | 
188  | 11.0k  |   char *dest = strchr(str, '\0');  | 
189  | 11.0k  |   if (dest - str >= str_size) { | 
190  | 0  |     assert("str_size does not match actual string length." && 0); | 
191  | 0  |     return;  | 
192  | 0  |   }  | 
193  |  |  | 
194  | 11.0k  |   int i = dest - str;  | 
195  | 71.2k  |   for (int j = 0; (i < str_size) && (j < strlen(src)); ++i, ++j) { | 
196  | 60.1k  |     str[i] = tolower(src[j]);  | 
197  | 60.1k  |   }  | 
198  | 11.0k  |   str[i] = '\0';  | 
199  | 11.0k  | }  | 
200  |  |  | 
201  |  | /// @brief Appends the string @p src to the string @p dest.  | 
202  |  | /// @p dest is can be a stack allocated buffer.  | 
203  |  | ///  | 
204  |  | /// @param dest The string to append to.  | 
205  |  | /// @param dest_buf_size Size of buffer @p str.  | 
206  |  | /// @param src The string to append.  | 
207  |  | /// Does nothing if any of the given strings is NULL.  | 
208  |  | void str_append_no_realloc(char *dest, size_t dest_buf_size, const char *src)  | 
209  | 0  | { | 
210  | 0  |   if (!dest || !src) { | 
211  | 0  |     return;  | 
212  | 0  |   }  | 
213  | 0  |   if (strlen(dest) + strlen(src) + 1 > dest_buf_size) { | 
214  | 0  |     printf("str_size does not match actual string length.\n"); | 
215  | 0  |     return;  | 
216  | 0  |   }  | 
217  | 0  |   strncat(dest, src, dest_buf_size - strlen(dest));  | 
218  | 0  | }  | 
219  |  |  | 
220  |  | /// Allocates memory of strlen(str_a) + strlen(str_b) + 1 chars  | 
221  |  | /// and copies all strings into it as str_a + str_b  | 
222  |  | /// str_a is passed to realloc and should not be used afterwards.  | 
223  |  | /// Returns the concatenated string.  | 
224  |  | /// Returns NULL in case of failure.  | 
225  |  | char *str_append(char *str_a, const char *str_b)  | 
226  | 0  | { | 
227  | 0  |   if (!str_a || !str_b) { | 
228  | 0  |     return NULL;  | 
229  | 0  |   }  | 
230  | 0  |   size_t asize = strlen(str_a) + strlen(str_b) + 1;  | 
231  | 0  |   str_a = realloc(str_a, asize);  | 
232  | 0  |   strncat(str_a, str_b, asize - strlen(str_a));  | 
233  | 0  |   return str_a;  | 
234  | 0  | }  | 
235  |  |  | 
236  |  | /// Returns the given byte sequence @bytes as a string of the  | 
237  |  | /// form: 0xXX,0xXX...  | 
238  |  | /// Returns NULL in case of failure.  | 
239  |  | char *byte_seq_to_str(uint8_t *bytes, size_t len)  | 
240  | 0  | { | 
241  | 0  |   if (!bytes) { | 
242  | 0  |     return NULL;  | 
243  | 0  |   }  | 
244  | 0  |   if (len == 0) { | 
245  | 0  |     return NULL;  | 
246  | 0  |   }  | 
247  | 0  |   char single_byte[8] = { 0 }; | 
248  | 0  |   char *s = calloc(sizeof(char), 32);  | 
249  | 0  |   for (size_t i = 0; i < len; ++i) { | 
250  | 0  |     cs_snprintf(single_byte, sizeof(single_byte),  | 
251  | 0  |           "0x%02" PRIx8 "%s", bytes[i],  | 
252  | 0  |           i == len - 1 ? "" : ", ");  | 
253  | 0  |     s = str_append(s, single_byte);  | 
254  | 0  |     if (!s) { | 
255  | 0  |       return NULL;  | 
256  | 0  |     }  | 
257  | 0  |   }  | 
258  | 0  |   return s;  | 
259  | 0  | }  |