1 /* radare - LGPL - Copyright 2007-2020 - pancake */
2
3 #include <r_util.h>
4 #if __UNIX__
5 #include <sys/mman.h>
6 #endif
7
8 #define SET_BIT(p,n) ((p) |= (1 << (n)))
9 #define CLR_BIT(p,n) ((p) &= (~(1) << (n)))
10
11 // TODO: find better name (r_mem_length()); is this used somewhere?
r_mem_count(const ut8 ** addr)12 R_API int r_mem_count(const ut8 **addr) {
13 int i = 0;
14 while (*addr++) {
15 i++;
16 }
17 return i;
18 }
19
r_mem_eq(ut8 * a,ut8 * b,int len)20 R_API int r_mem_eq(ut8 *a, ut8 *b, int len) {
21 register int i;
22 for (i = 0; i < len; i++) {
23 if (a[i] != b[i]) {
24 return false;
25 }
26 }
27 return true;
28 }
29
r_mem_copyloop(ut8 * dest,const ut8 * orig,int dsize,int osize)30 R_API void r_mem_copyloop(ut8 *dest, const ut8 *orig, int dsize, int osize) {
31 int i = 0, j;
32 while (i < dsize) {
33 for (j = 0; j < osize && i < dsize; j++) {
34 dest[i++] = orig[j];
35 }
36 }
37 }
38
r_mem_cmp_mask(const ut8 * dest,const ut8 * orig,const ut8 * mask,int len)39 R_API int r_mem_cmp_mask(const ut8 *dest, const ut8 *orig, const ut8 *mask, int len) {
40 ut8 *mdest = malloc (len);
41 if (!mdest) {
42 return -1;
43 }
44 ut8 *morig = malloc (len);
45 if (!morig) {
46 free (mdest);
47 return -1;
48 }
49 int i;
50 for (i = 0; i < len; i++) {
51 mdest[i] = dest[i] & mask[i];
52 morig[i] = orig[i] & mask[i];
53 }
54 int ret = memcmp (mdest, morig, len);
55 free (mdest);
56 free (morig);
57 return ret;
58 }
59
r_mem_copybits(ut8 * dst,const ut8 * src,int bits)60 R_API void r_mem_copybits(ut8 *dst, const ut8 *src, int bits) {
61 ut8 srcmask, dstmask;
62 int bytes = (int) (bits / 8);
63 bits = bits % 8;
64 memcpy (dst, src, bytes);
65 if (bits) {
66 srcmask = dstmask = 0;
67 switch (bits) {
68 case 1: srcmask = 0x80; dstmask = 0x7f; break;
69 case 2: srcmask = 0xc0; dstmask = 0x3f; break;
70 case 3: srcmask = 0xe0; dstmask = 0x1f; break;
71 case 4: srcmask = 0xf0; dstmask = 0x0f; break;
72 case 5: srcmask = 0xf8; dstmask = 0x07; break;
73 case 6: srcmask = 0xfc; dstmask = 0x03; break;
74 case 7: srcmask = 0xfe; dstmask = 0x01; break;
75 }
76 dst[bytes] = ((dst[bytes] & dstmask) | (src[bytes] & srcmask));
77 }
78 }
79
readbit(const ut8 * src,int bitoffset)80 static inline char readbit(const ut8 *src, int bitoffset) {
81 const int wholeBytes = bitoffset / 8;
82 const int remainingBits = bitoffset % 8;
83 // return (src[wholeBytes] >> remainingBits) & 1;
84 return (src[wholeBytes] & 1<< remainingBits);
85 }
86
writebit(ut8 * dst,int i,bool c)87 static inline void writebit (ut8 *dst, int i, bool c) {
88 const int byte = i / 8;
89 const int bit = (i % 8);
90 // eprintf ("Write %d %d = %d\n", byte, bit, c);
91 dst += byte;
92 if (c) {
93 //dst[byte] |= (1 << bit);
94 R_BIT_SET (dst , bit);
95 } else {
96 //dst[byte] &= (1 << bit);
97 R_BIT_UNSET (dst , bit);
98 }
99 }
100
r_mem_copybits_delta(ut8 * dst,int doff,const ut8 * src,int soff,int bits)101 R_API void r_mem_copybits_delta(ut8 *dst, int doff, const ut8 *src, int soff, int bits) {
102 int i;
103 if (doff < 0 || soff < 0 || !dst || !src) {
104 return;
105 }
106 for (i = 0; i < bits; i++) {
107 bool c = readbit (src, i + soff);
108 writebit (dst, i + doff, c);
109 }
110 }
111
r_mem_get_num(const ut8 * b,int size)112 R_API ut64 r_mem_get_num(const ut8 *b, int size) {
113 // LITTLE ENDIAN is the default for streams
114 switch (size) {
115 case 1:
116 return r_read_le8 (b);
117 case 2:
118 return r_read_le16 (b);
119 case 4:
120 return r_read_le32 (b);
121 case 8:
122 return r_read_le64 (b);
123 }
124 return 0LL;
125 }
126
127 // TODO: SEE: R_API ut64 r_reg_get_value(RReg *reg, RRegItem *item) { .. dupped code?
r_mem_set_num(ut8 * dest,int dest_size,ut64 num)128 R_API int r_mem_set_num(ut8 *dest, int dest_size, ut64 num) {
129 // LITTLE ENDIAN is the default for streams
130 switch (dest_size) {
131 case 1:
132 r_write_le8 (dest, (ut8) (num & UT8_MAX));
133 break;
134 case 2:
135 r_write_le16 (dest, (ut16) (num & UT16_MAX));
136 break;
137 case 4:
138 r_write_le32 (dest, (ut32) (num & UT32_MAX));
139 break;
140 case 8:
141 r_write_le64 (dest, num);
142 break;
143 default:
144 return false;
145 }
146 return true;
147 }
148
149 // The default endian is LE for streams.
150 // This function either swaps or copies len bytes depending on bool big_endian
151 // TODO: Remove completely
r_mem_swaporcopy(ut8 * dest,const ut8 * src,int len,bool big_endian)152 R_API void r_mem_swaporcopy(ut8 *dest, const ut8 *src, int len, bool big_endian) {
153 if (big_endian) {
154 r_mem_swapendian (dest, src, len);
155 } else {
156 memcpy (dest, src, len);
157 }
158 }
159
160 // This function unconditionally swaps endian of size bytes of orig -> dest
161 // TODO: Remove completely
r_mem_swapendian(ut8 * dest,const ut8 * orig,int size)162 R_API void r_mem_swapendian(ut8 *dest, const ut8 *orig, int size) {
163 ut8 buffer[8];
164 switch (size) {
165 case 1:
166 *dest = *orig;
167 break;
168 case 2:
169 *buffer = *orig;
170 dest[0] = orig[1];
171 dest[1] = buffer[0];
172 break;
173 case 3:
174 *buffer = *orig;
175 dest[0] = orig[2];
176 dest[1] = orig[1];
177 dest[2] = buffer[0];
178 break;
179 case 4:
180 memcpy (buffer, orig, 4);
181 dest[0] = buffer[3];
182 dest[1] = buffer[2];
183 dest[2] = buffer[1];
184 dest[3] = buffer[0];
185 break;
186 case 8:
187 memcpy (buffer, orig, 8);
188 dest[0] = buffer[7];
189 dest[1] = buffer[6];
190 dest[2] = buffer[5];
191 dest[3] = buffer[4];
192 dest[4] = buffer[3];
193 dest[5] = buffer[2];
194 dest[6] = buffer[1];
195 dest[7] = buffer[0];
196 break;
197 default:
198 if (dest != orig) {
199 memmove (dest, orig, size);
200 }
201 }
202 }
203
204 // R_DOC r_mem_mem: Finds the needle of nlen size into the haystack of hlen size
205 // R_UNIT printf("%s\n", r_mem_mem("food is pure lame", 20, "is", 2));
r_mem_mem(const ut8 * haystack,int hlen,const ut8 * needle,int nlen)206 R_API const ut8 *r_mem_mem(const ut8 *haystack, int hlen, const ut8 *needle, int nlen) {
207 int i, until = hlen - nlen + 1;
208 if (hlen < 1 || nlen < 1) {
209 return NULL;
210 }
211 for (i = 0; i < until; i++) {
212 if (!memcmp (haystack + i, needle, nlen)) {
213 return haystack + i;
214 }
215 }
216 return NULL;
217 }
218
219 // TODO: rename to r_mem_mem and refactor all calls to this function
r_mem_mem_aligned(const ut8 * haystack,int hlen,const ut8 * needle,int nlen,int align)220 R_API const ut8 *r_mem_mem_aligned(const ut8 *haystack, int hlen, const ut8 *needle, int nlen, int align) {
221 int i, until = hlen - nlen + 1;
222 if (align < 1) {
223 align = 1;
224 }
225 if (hlen < 1 || nlen < 1) {
226 return NULL;
227 }
228 if (align > 1) {
229 until -= (until % align);
230 }
231 for (i = 0; i < until; i += align) {
232 if (!memcmp (haystack + i, needle, nlen)) {
233 return haystack + i;
234 }
235 }
236 return NULL;
237 }
238
r_mem_protect(void * ptr,int size,const char * prot)239 R_API int r_mem_protect(void *ptr, int size, const char *prot) {
240 #if __UNIX__
241 int p = 0;
242 if (strchr (prot, 'x')) {
243 p |= PROT_EXEC;
244 }
245 if (strchr (prot, 'r')) {
246 p |= PROT_READ;
247 }
248 if (strchr (prot, 'w')) {
249 p |= PROT_WRITE;
250 }
251 if (mprotect (ptr, size, p) == -1) {
252 return false;
253 }
254 #elif __WINDOWS__
255 int r, w, x;
256 DWORD p = PAGE_NOACCESS;
257 r = strchr (prot, 'r')? 1: 0;
258 w = strchr (prot, 'w')? 1: 0;
259 x = strchr (prot, 'x')? 1: 0;
260 if (w && x) {
261 return false;
262 }
263 if (x) {
264 p = PAGE_EXECUTE_READ;
265 } else if (w) {
266 p = PAGE_READWRITE;
267 } else if (r) {
268 p = PAGE_READONLY;
269 }
270 if (!VirtualProtect (ptr, size, p, NULL)) {
271 return false;
272 }
273 #else
274 #warning Unknown platform
275 #endif
276 return true;
277 }
278
r_mem_dup(const void * s,int l)279 R_API void *r_mem_dup(const void *s, int l) {
280 void *d = malloc (l);
281 if (d) {
282 memcpy (d, s, l);
283 }
284 return d;
285 }
286
r_mem_reverse(ut8 * b,int l)287 R_API void r_mem_reverse(ut8 *b, int l) {
288 ut8 tmp;
289 int i, end = l / 2;
290 for (i = 0; i < end; i++) {
291 tmp = b[i];
292 b[i] = b[l - i - 1];
293 b[l - i - 1] = tmp;
294 }
295 }
296
r_mem_is_printable(const ut8 * a,int la)297 R_API bool r_mem_is_printable(const ut8 *a, int la) {
298 int i;
299 for (i = 0; i < la; i++) {
300 if (a[i] != '\n' && a[i] != '\t' && !IS_PRINTABLE (a[i])) {
301 return false;
302 }
303 }
304 return true;
305 }
306
r_mem_is_zero(const ut8 * b,int l)307 R_API bool r_mem_is_zero(const ut8 *b, int l) {
308 int i;
309 for (i = 0; i < l; i++) {
310 if (b[i]) {
311 return false;
312 }
313 }
314 return true;
315 }
316
r_mem_alloc(int sz)317 R_API void *r_mem_alloc(int sz) {
318 return calloc (sz, 1);
319 }
320
r_mem_free(void * p)321 R_API void r_mem_free(void *p) {
322 free (p);
323 }
324
r_mem_memzero(void * dst,size_t l)325 R_API void r_mem_memzero(void *dst, size_t l) {
326 #ifdef _MSC_VER
327 RtlSecureZeroMemory (dst, l);
328 #else
329 #if HAVE_EXPLICIT_BZERO
330 explicit_bzero (dst, l);
331 #elif HAVE_EXPLICIT_MEMSET
332 (void)explicit_memset (dst, 0, l);
333 #else
334 memset (dst, 0, l);
335 __asm__ volatile ("" :: "r"(dst) : "memory");
336 #endif
337 #endif
338 }
339
r_mem_mmap_resize(RMmap * m,ut64 newsize)340 R_API void *r_mem_mmap_resize(RMmap *m, ut64 newsize) {
341 #if __WINDOWS__
342 if (m->fm != INVALID_HANDLE_VALUE) {
343 CloseHandle (m->fm);
344 }
345 if (m->fh != INVALID_HANDLE_VALUE) {
346 CloseHandle (m->fh);
347 }
348 if (m->buf) {
349 UnmapViewOfFile (m->buf);
350 }
351 #elif __UNIX__
352 if (munmap (m->buf, m->len) != 0) {
353 return NULL;
354 }
355 #endif
356 if (!r_sys_truncate (m->filename, newsize)) {
357 return NULL;
358 }
359 m->len = newsize;
360 r_file_mmap_arch (m, m->filename, m->fd);
361 return m->buf;
362 }
363