1 /* radare - LGPL - Copyright 2007-2020 - pancake & Skia */
2
3 #include "r_cons.h"
4 #include "r_util.h"
5 #include "r_util/r_print.h"
6 #include "r_reg.h"
7 #define NOPTR 0
8 #define PTRSEEK 1
9 #define PTRBACK 2
10 #define NULLPTR 3
11 #define STRUCTPTR 100
12 #define NESTEDSTRUCT 1
13 #define STRUCTFLAG 10000
14 #define NESTDEPTH 14
15 #define ARRAYINDEX_COEF 10000
16
17 #define MUSTSEE (mode & R_PRINT_MUSTSEE && mode & R_PRINT_ISFIELD && !(mode & R_PRINT_JSON))
18 #define ISQUIET (mode & R_PRINT_QUIET)
19 #define MUSTSET (mode & R_PRINT_MUSTSET && mode & R_PRINT_ISFIELD && setval)
20 #define SEEVALUE (mode & R_PRINT_VALUE)
21 #define MUSTSEEJSON (mode & R_PRINT_JSON && mode & R_PRINT_ISFIELD)
22 #define MUSTSEESTRUCT (mode & R_PRINT_STRUCT)
23
24 //this define is used as a way to acknowledge when updateAddr should take len
25 //as real len of the buffer
26 #define THRESHOLD (-4444)
27
28 //TODO REWRITE THIS IS BECOMING A NIGHTMARE
29
updateAddr(const ut8 * buf,int len,int endian,ut64 * addr,ut64 * addr64)30 static float updateAddr(const ut8 *buf, int len, int endian, ut64 *addr, ut64 *addr64) {
31 float f = 0.0;
32 // assert sizeof (float) == sizeof (ut32))
33 // XXX 999 is used as an implicit buffer size, we should pass the buffer size to every function too, otherwise this code will give us some problems
34 if (len >= THRESHOLD - 7 && len < THRESHOLD) {
35 len = len + THRESHOLD; // get the real len to avoid oob
36 } else {
37 len = 999;
38 }
39 if (len < 1) {
40 return 0;
41 }
42 if (len >= sizeof (float)) {
43 r_mem_swaporcopy ((ut8*)&f, buf, sizeof (float), endian);
44 }
45 if (addr && len > 3) {
46 ut32 tmpaddr = r_read_ble32 (buf, endian);
47 *addr = (ut64)tmpaddr;
48 }
49 if (addr64 && len > 7) {
50 *addr64 = r_read_ble64 (buf, endian);
51 }
52 return f;
53 }
54
r_get_size(RNum * num,ut8 * buf,int endian,const char * s)55 static int r_get_size(RNum *num, ut8 *buf, int endian, const char *s) {
56 size_t len = strlen (s);
57 if (s[0] == '*' && len >= 4) { // value pointed by the address
58 ut64 addr;
59 int offset = (int)r_num_math (num, s + 1);
60 (void)updateAddr (buf + offset, 999, endian, &addr, NULL);
61 return addr;
62 }
63 // flag handling doesnt seems to work here
64 return r_num_math (num, s);
65 }
66
r_print_format_u128(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)67 static void r_print_format_u128(const RPrint* p, int endian, int mode,
68 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
69 ut64 low = r_read_ble64 (buf, endian);
70 ut64 hig = r_read_ble64 (buf + 8, endian);
71 if (MUSTSEEJSON) {
72 p->cb_printf ("\"");
73 } else if (!SEEVALUE && !ISQUIET) {
74 p->cb_printf ("0x%08"PFMT64x" = (uint128_t)", seeki);
75 }
76 if (endian) {
77 p->cb_printf ("0x%016"PFMT64x"", low);
78 p->cb_printf ("%016"PFMT64x, hig);
79 } else {
80 p->cb_printf ("0x%016"PFMT64x"", hig);
81 p->cb_printf ("%016"PFMT64x, low);
82 }
83 if (MUSTSEEJSON) {
84 const char *end = endian? "big": "little";
85 p->cb_printf ("\",\"endian\":\"%s\",\"ctype\":\"uint128_t\"}", end);
86 }
87 }
88
r_print_format_quadword(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)89 static void r_print_format_quadword(const RPrint* p, int endian, int mode,
90 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
91 ut64 addr64;
92 int elem = -1;
93 if (size >= ARRAYINDEX_COEF) {
94 elem = size / ARRAYINDEX_COEF - 1;
95 size %= ARRAYINDEX_COEF;
96 }
97 updateAddr (buf + i, size - i, endian, NULL, &addr64);
98 if (MUSTSET) {
99 p->cb_printf ("wv8 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*8:0));
100 } else if (MUSTSEE) {
101 if (!SEEVALUE && !ISQUIET) {
102 p->cb_printf ("0x%08"PFMT64x" = (qword)",
103 seeki + ((elem >= 0)? elem * 8: 0));
104 }
105 if (size == -1) {
106 if (addr64 == UT32_MAX || ((st64)addr64 < 0 && (st64)addr64 > -4096)) {
107 p->cb_printf ("%d", (int)(addr64));
108 } else {
109 p->cb_printf ("0x%016"PFMT64x, addr64);
110 }
111 } else {
112 if (!SEEVALUE) {
113 p->cb_printf ("[ ");
114 }
115 while (size--) {
116 updateAddr (buf + i, size - i, endian, NULL, &addr64);
117 if (elem == -1 || elem == 0) {
118 p->cb_printf ("0x%016"PFMT64x, addr64);
119 if (elem == 0) {
120 elem = -2;
121 }
122 }
123 if (size != 0 && elem == -1) {
124 p->cb_printf (", ");
125 }
126 if (elem > -1) {
127 elem--;
128 }
129 i += 8;
130 }
131 if (!SEEVALUE) {
132 p->cb_printf (" ]");
133 }
134 }
135 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
136 if (size == -1) {
137 p->cb_printf ("%"PFMT64d, addr64);
138 } else {
139 p->cb_printf ("[ ");
140 while (size--) {
141 updateAddr (buf + i, size - i, endian, NULL, &addr64);
142 if (elem == -1 || elem == 0) {
143 p->cb_printf ("%"PFMT64d, addr64);
144 if (elem == 0) {
145 elem = -2;
146 }
147 }
148 if (size != 0 && elem == -1) {
149 p->cb_printf (", ");
150 }
151 if (elem > -1) {
152 elem--;
153 }
154 i += 8;
155 }
156 p->cb_printf (" ]");
157 }
158 if (MUSTSEEJSON) {
159 p->cb_printf ("}");
160 }
161 }
162 }
163
r_print_format_byte(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)164 static void r_print_format_byte(const RPrint* p, int endian, int mode,
165 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
166 int elem = -1;
167 if (size >= ARRAYINDEX_COEF) {
168 elem = size / ARRAYINDEX_COEF - 1;
169 size %= ARRAYINDEX_COEF;
170 }
171 if (MUSTSET) {
172 p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki + ((elem >= 0) ? elem : 0));
173 } else if (MUSTSEE) {
174 if (!SEEVALUE && !ISQUIET) {
175 p->cb_printf ("0x%08"PFMT64x" = ", seeki + ((elem >= 0) ? elem : 0));
176 }
177 if (size == -1) {
178 p->cb_printf ("0x%02x", buf[i]);
179 } else {
180 if (!SEEVALUE) {
181 p->cb_printf ("[ ");
182 }
183 while (size--) {
184 if (elem == -1 || elem == 0) {
185 p->cb_printf ("0x%02x", buf[i]);
186 if (elem == 0) {
187 elem = -2;
188 }
189 }
190 if (size != 0 && elem == -1) {
191 p->cb_printf (", ");
192 }
193 if (elem > -1) {
194 elem--;
195 }
196 i++;
197 }
198 if (!SEEVALUE) {
199 p->cb_printf (" ]");
200 }
201 }
202 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
203 if (size == -1) {
204 p->cb_printf ("%d", buf[i]);
205 } else {
206 p->cb_printf ("[ ");
207 const char *comma = "";
208 while (size--) {
209 if (elem == -1 || elem == 0) {
210 p->cb_printf ("%s%d", comma, buf[i]);
211 comma = ",";
212 if (elem == 0) {
213 elem = -2;
214 }
215 }
216 if (elem > -1) {
217 elem--;
218 }
219 i++;
220 }
221 p->cb_printf (" ]");
222 }
223 if (MUSTSEEJSON) {
224 p->cb_printf ("}");
225 }
226 }
227 }
228
229 // Return number of consumed bytes
r_print_format_uleb(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)230 static int r_print_format_uleb(const RPrint* p, int endian, int mode,
231 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
232 int elem = -1;
233 int s = 0, offset = 0;
234 ut64 value = 0;
235 if (size >= ARRAYINDEX_COEF) {
236 elem = size / ARRAYINDEX_COEF - 1;
237 size %= ARRAYINDEX_COEF;
238 }
239 if (MUSTSET) {
240 ut8 *tmp;
241 char *nbr;
242 do {
243 r_uleb128_decode (buf+i, &s, &value);
244 i += s;
245 offset += s;
246 } while (elem--);
247 tmp = (ut8*) r_uleb128_encode (r_num_math (NULL, setval), &s);
248 nbr = r_hex_bin2strdup (tmp, s);
249 p->cb_printf ("\"wx %s\" @ 0x%08"PFMT64x"\n", nbr, seeki+offset-s);
250 free (tmp);
251 free (nbr);
252 } else if (MUSTSEE) {
253 if (!SEEVALUE && !ISQUIET) {
254 p->cb_printf ("0x%08" PFMT64x " = ", seeki);
255 }
256 if (size==-1) {
257 r_uleb128_decode (buf+i, &offset, &value);
258 p->cb_printf ("%"PFMT64d, value);
259 } else {
260 if (!SEEVALUE) {
261 p->cb_printf ("[ ");
262 }
263 while (size--) {
264 if (elem == -1 || elem == 0) {
265 r_uleb128_decode (buf+i, &s, &value);
266 i += s;
267 offset += s;
268 p->cb_printf ("%"PFMT64d, value);
269 if (elem == 0) {
270 elem = -2;
271 }
272 }
273 if (size != 0 && elem == -1) {
274 p->cb_printf (", ");
275 }
276 if (elem > -1) {
277 elem--;
278 }
279 }
280 if (!SEEVALUE) {
281 p->cb_printf (" ]");
282 }
283 }
284 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
285 if (size==-1) {
286 r_uleb128_decode (buf+i, &offset, &value);
287 p->cb_printf ("\"%"PFMT64d"\"", value);
288 } else {
289 p->cb_printf ("[ ");
290 while (size--) {
291 if (elem == -1 || elem == 0) {
292 r_uleb128_decode (buf+i, &s, &value);
293 i += s;
294 offset += s;
295 p->cb_printf ("\"%"PFMT64d"\"", value);
296 if (elem == 0) {
297 elem = -2;
298 }
299 }
300 if (size != 0 && elem == -1) {
301 p->cb_printf (", ");
302 }
303 if (elem > -1) {
304 elem--;
305 }
306 }
307 p->cb_printf (" ]");
308 }
309 if (MUSTSEEJSON) {
310 p->cb_printf ("}");
311 }
312 }
313 return offset;
314 }
315
r_print_format_char(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)316 static void r_print_format_char(const RPrint* p, int endian, int mode,
317 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
318 int elem = -1;
319 if (size >= ARRAYINDEX_COEF) {
320 elem = size/ARRAYINDEX_COEF-1;
321 size %= ARRAYINDEX_COEF;
322 }
323 if (MUSTSET) {
324 p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
325 } else if (MUSTSEE) {
326 if (!SEEVALUE && !ISQUIET) {
327 p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 2 : 0)); //XXX:: shouldn't it be elem*1??
328 }
329 if (size == -1) {
330 p->cb_printf ("'%c'", IS_PRINTABLE (buf[i])?buf[i]:'.');
331 } else {
332 if (!SEEVALUE) {
333 p->cb_printf ("[ ");
334 }
335 while (size--) {
336 if (elem == -1 || elem == 0) {
337 p->cb_printf ("'%c'", IS_PRINTABLE (buf[i])?buf[i]:'.');
338 if (elem == 0) {
339 elem = -2;
340 }
341 }
342 if (size != 0 && elem == -1) {
343 p->cb_printf (", ");
344 }
345 if (elem > -1) {
346 elem--;
347 }
348 i++;
349 }
350 if (!SEEVALUE) {
351 p->cb_printf (" ]");
352 }
353 }
354 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
355 if (size == -1) {
356 p->cb_printf ("\"%c\"", IS_PRINTABLE (buf[i])?buf[i]:'.');
357 } else {
358 p->cb_printf ("[ ");
359 while (size--) {
360 if (elem == -1 || elem == 0) {
361 p->cb_printf ("\"%c\"", IS_PRINTABLE (buf[i])?buf[i]:'.');
362 if (elem == 0) {
363 elem = -2;
364 }
365 }
366 if (size != 0 && elem == -1) {
367 p->cb_printf (", ");
368 }
369 if (elem > -1) {
370 elem--;
371 }
372 i++;
373 }
374 p->cb_printf (" ]");
375 }
376 if (MUSTSEEJSON) {
377 p->cb_printf ("}");
378 }
379 }
380 }
381
r_print_format_decchar(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)382 static void r_print_format_decchar(const RPrint* p, int endian, int mode,
383 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
384 int elem = -1;
385 if (size >= ARRAYINDEX_COEF) {
386 elem = size/ARRAYINDEX_COEF-1;
387 size %= ARRAYINDEX_COEF;
388 }
389 if (MUSTSET) {
390 p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
391 } else if (MUSTSEE) {
392 if (!SEEVALUE && !ISQUIET) {
393 p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem : 0));
394 }
395 if (size == -1) {
396 p->cb_printf ("%d", buf[i]);
397 } else {
398 if (!SEEVALUE) {
399 p->cb_printf ("[ ");
400 }
401 while (size--) {
402 if (elem == -1 || elem == 0) {
403 p->cb_printf ("%d", buf[i]);
404 if (elem == 0) {
405 elem = -2;
406 }
407 }
408 if (size != 0 && elem == -1) {
409 p->cb_printf (", ");
410 }
411 if (elem > -1) {
412 elem--;
413 }
414 i++;
415 }
416 if (!SEEVALUE) {
417 p->cb_printf (" ]");
418 }
419 }
420 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
421 if (size == -1) {
422 p->cb_printf ("\"%d\"", buf[i]);
423 } else {
424 p->cb_printf ("[ ");
425 while (size--) {
426 if (elem == -1 || elem == 0) {
427 p->cb_printf ("\"%d\"", buf[i]);
428 if (elem == 0) {
429 elem = -2;
430 }
431 }
432 if (size != 0 && elem == -1) {
433 p->cb_printf (", ");
434 }
435 if (elem > -1) {
436 elem--;
437 }
438 i++;
439 }
440 p->cb_printf (" ]");
441 }
442 if (MUSTSEEJSON) {
443 p->cb_printf ("}");
444 }
445 }
446 }
447
r_print_format_string(const RPrint * p,ut64 seeki,ut64 addr64,ut64 addr,int is64,int mode)448 static int r_print_format_string(const RPrint* p, ut64 seeki, ut64 addr64, ut64 addr, int is64, int mode) {
449 ut8 buffer[255];
450 buffer[0] = 0;
451 if (!p->iob.read_at) {
452 eprintf ("(cannot read memory)\n");
453 return -1;
454 }
455 const ut64 at = (is64 == 1)? addr64: (ut64)addr;
456 int res = p->iob.read_at (p->iob.io, at, buffer, sizeof (buffer) - 8);
457 if (MUSTSEEJSON) {
458 char *encstr = r_str_utf16_encode ((const char *)buffer, -1);
459 if (encstr) {
460 p->cb_printf ("%"PFMT64d",\"string\":\"%s\"}", seeki, encstr);
461 free (encstr);
462 }
463 } else if (MUSTSEESTRUCT) {
464 char *encstr = r_str_utf16_encode ((const char *)buffer, -1);
465 if (encstr) {
466 p->cb_printf ("\"%s\"", encstr);
467 free (encstr);
468 }
469 } else if (MUSTSEE) {
470 if (!SEEVALUE && !ISQUIET) {
471 p->cb_printf ("0x%08" PFMT64x " = ", seeki);
472 }
473 if (!SEEVALUE) {
474 if (ISQUIET) {
475 if (addr == 0LL) {
476 p->cb_printf ("NULL");
477 } else if (addr == UT32_MAX || addr == UT64_MAX) {
478 p->cb_printf ("-1");
479 } else {
480 p->cb_printf ("0x%08" PFMT64x " ", addr);
481 }
482 } else {
483 p->cb_printf ("0x%08" PFMT64x " -> 0x%08" PFMT64x " ", seeki, addr);
484 }
485 }
486 if (res > 0 && buffer[0] != 0xff && buffer[1] != 0xff) {
487 p->cb_printf ("\"%s\"", buffer);
488 }
489 }
490 return 0;
491 }
492
r_print_format_time(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)493 static void r_print_format_time(const RPrint* p, int endian, int mode,
494 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
495 ut64 addr;
496 struct tm timestruct;
497 int elem = -1;
498 if (size >= ARRAYINDEX_COEF) {
499 elem = size/ARRAYINDEX_COEF-1;
500 size %= ARRAYINDEX_COEF;
501 }
502 updateAddr (buf + i, size - i, endian, &addr, NULL);
503 if (MUSTSET) {
504 p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
505 } else if (MUSTSEE) {
506 char *timestr = malloc (ASCTIME_BUF_MINLEN);
507 if (!timestr) {
508 return;
509 }
510 r_asctime_r (gmtime_r ((time_t*)&addr, ×truct), timestr);
511 *(timestr+24) = '\0';
512 if (!SEEVALUE && !ISQUIET) {
513 p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
514 }
515 if (size==-1) {
516 p->cb_printf ("%s", timestr);
517 } else {
518 if (!SEEVALUE) {
519 p->cb_printf ("[ ");
520 }
521 while (size--) {
522 updateAddr (buf + i, size - i, endian, &addr, NULL);
523 r_asctime_r (gmtime_r ((time_t*)&addr, ×truct), timestr);
524 *(timestr+24) = '\0';
525 if (elem == -1 || elem == 0) {
526 p->cb_printf ("%s", timestr);
527 if (elem == 0) {
528 elem = -2;
529 }
530 }
531 if (size != 0 && elem == -1) {
532 p->cb_printf (", ");
533 }
534 if (elem > -1) {
535 elem--;
536 }
537 i += 4;
538 }
539 if (!SEEVALUE) {
540 p->cb_printf (" ]");
541 }
542 }
543 free (timestr);
544 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
545 char *timestr = malloc (ASCTIME_BUF_MINLEN);
546 if (!timestr) {
547 return;
548 }
549 r_asctime_r (gmtime_r ((time_t*)&addr, ×truct), timestr);
550 *(timestr+24) = '\0';
551 if (size==-1) {
552 p->cb_printf ("\"%s\"", timestr);
553 } else {
554 p->cb_printf ("[ ");
555 while (size--) {
556 updateAddr (buf + i, size - i, endian, &addr, NULL);
557 r_asctime_r (gmtime_r ((time_t*)&addr, ×truct), timestr);
558 *(timestr+24) = '\0';
559 if (elem == -1 || elem == 0) {
560 p->cb_printf ("\"%s\"", timestr);
561 if (elem == 0) {
562 elem = -2;
563 }
564 }
565 if (size != 0 && elem == -1) {
566 p->cb_printf (", ");
567 }
568 if (elem > -1) {
569 elem--;
570 }
571 i += 4;
572 }
573 p->cb_printf (" ]");
574 }
575 free (timestr);
576 if (MUSTSEEJSON) {
577 p->cb_printf ("}");
578 }
579 }
580 }
581
582 // TODO: support unsigned int?
r_print_format_hex(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)583 static void r_print_format_hex(const RPrint* p, int endian, int mode,
584 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
585 ut64 addr;
586 int elem = -1;
587 if (size >= ARRAYINDEX_COEF) {
588 elem = size/ARRAYINDEX_COEF-1;
589 size %= ARRAYINDEX_COEF;
590 }
591 updateAddr (buf + i, size - i, endian, &addr, NULL);
592 if (MUSTSET) {
593 p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
594 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
595 p->cb_printf ("%"PFMT64d, addr);
596 } else if (MUSTSEE) {
597 if (!SEEVALUE && !ISQUIET) {
598 p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
599 }
600 if (size == -1) {
601 if (addr == UT64_MAX || addr == UT32_MAX) {
602 p->cb_printf ("-1");
603 } else {
604 p->cb_printf ("%"PFMT64d, addr);
605 }
606 } else {
607 if (!SEEVALUE) {
608 p->cb_printf ("[ ");
609 }
610 while (size--) {
611 updateAddr (buf + i, size - i, endian, &addr, NULL);
612 if (elem == -1 || elem == 0) {
613 if (ISQUIET) {
614 if (addr == UT64_MAX || addr == UT32_MAX) {
615 p->cb_printf ("-1");
616 } else {
617 p->cb_printf ("%"PFMT64d, addr);
618 }
619 } else {
620 p->cb_printf ("%"PFMT64d, addr);
621 }
622 if (elem == 0) {
623 elem = -2;
624 }
625 }
626 if (size != 0 && elem == -1) {
627 p->cb_printf (", ");
628 }
629 if (elem > -1) {
630 elem--;
631 }
632 i += 4;
633 }
634 if (!SEEVALUE) {
635 p->cb_printf (" ]");
636 }
637 }
638 } else if (MUSTSEEJSON) {
639 if (size == -1) {
640 p->cb_printf ("%"PFMT64d, addr);
641 } else {
642 p->cb_printf ("[ ");
643 while (size--) {
644 updateAddr (buf + i, size - i, endian, &addr, NULL);
645 if (elem == -1 || elem == 0) {
646 p->cb_printf ("%"PFMT64d, addr);
647 if (elem == 0) {
648 elem = -2;
649 }
650 }
651 if (size != 0 && elem == -1) {
652 p->cb_printf (", ");
653 }
654 if (elem > -1) {
655 elem--;
656 }
657 i+=4;
658 }
659 p->cb_printf (" ]");
660 }
661 p->cb_printf ("}");
662 }
663 }
664
r_print_format_int(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)665 static void r_print_format_int(const RPrint* p, int endian, int mode,
666 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
667 ut64 addr;
668 int elem = -1;
669 if (size >= ARRAYINDEX_COEF) {
670 elem = size/ARRAYINDEX_COEF-1;
671 size %= ARRAYINDEX_COEF;
672 }
673 updateAddr (buf + i, size - i, endian, &addr, NULL);
674 if (MUSTSET) {
675 p->cb_printf ("wv4 %s @ %"PFMT64d"\n", setval, seeki+((elem>=0)?elem*4:0));
676 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
677 p->cb_printf ("0x%08"PFMT64x, addr);
678 } else if (MUSTSEE) {
679 if (!SEEVALUE && !ISQUIET) {
680 p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
681 }
682 if (size == -1) {
683 p->cb_printf ("%"PFMT64d, (st64)(st32)addr);
684 } else {
685 if (!SEEVALUE) {
686 p->cb_printf ("[ ");
687 }
688 while (size--) {
689 updateAddr (buf + i, size - i, endian, &addr, NULL);
690 if (elem == -1 || elem == 0) {
691 p->cb_printf ("%"PFMT64d, (st64)(st32)addr);
692 if (elem == 0) {
693 elem = -2;
694 }
695 }
696 if (size != 0 && elem == -1) {
697 p->cb_printf (", ");
698 }
699 if (elem > -1) {
700 elem--;
701 }
702 i += 4;
703 }
704 if (!SEEVALUE) {
705 p->cb_printf (" ]");
706 }
707 }
708 } else if (MUSTSEEJSON) {
709 if (size == -1) {
710 p->cb_printf ("%"PFMT64d, addr);
711 } else {
712 p->cb_printf ("[ ");
713 while (size--) {
714 updateAddr (buf + i, size - i, endian, &addr, NULL);
715 if (elem == -1 || elem == 0) {
716 p->cb_printf ("%"PFMT64d, addr);
717 if (elem == 0) {
718 elem = -2;
719 }
720 }
721 if (size != 0 && elem == -1) {
722 p->cb_printf (", ");
723 }
724 if (elem > -1) {
725 elem--;
726 }
727 i+=4;
728 }
729 p->cb_printf (" ]");
730 }
731 p->cb_printf ("}");
732 }
733 }
734
r_print_format_disasm(const RPrint * p,ut64 seeki,int size)735 static int r_print_format_disasm(const RPrint* p, ut64 seeki, int size) {
736 ut64 prevseeki = seeki;
737
738 if (!p->disasm || !p->user) {
739 return 0;
740 }
741
742 size = R_MAX (1, size);
743
744 while (size-- > 0) {
745 seeki += p->disasm (p->user, seeki);
746 }
747
748 return seeki - prevseeki;
749 }
750
r_print_format_octal(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)751 static void r_print_format_octal(const RPrint* p, int endian, int mode,
752 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
753 ut64 addr;
754 int elem = -1;
755 if (size >= ARRAYINDEX_COEF) {
756 elem = size/ARRAYINDEX_COEF-1;
757 size %= ARRAYINDEX_COEF;
758 }
759 updateAddr (buf + i, size - i, endian, &addr, NULL);
760 if (MUSTSET) {
761 p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
762 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
763 p->cb_printf ("0%"PFMT64o, addr);
764 } else if (MUSTSEE) {
765 if (!SEEVALUE && !ISQUIET) {
766 p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
767 }
768 if (!SEEVALUE) {
769 p->cb_printf ("(octal) ");
770 }
771 if (size == -1) {
772 p->cb_printf (" 0%08"PFMT64o, addr);
773 } else {
774 if (!SEEVALUE) {
775 p->cb_printf ("[ ");
776 }
777 while (size--) {
778 updateAddr (buf + i, size - i, endian, &addr, NULL);
779 if (elem == -1 || elem == 0) {
780 p->cb_printf ("0%08"PFMT64o, addr);
781 if (elem == 0) {
782 elem = -2;
783 }
784 }
785 if (size != 0 && elem == -1) {
786 p->cb_printf (", ");
787 }
788 if (elem > -1) {
789 elem--;
790 }
791 i+=4;
792 }
793 if (!SEEVALUE) {
794 p->cb_printf (" ]");
795 }
796 }
797 } else if (MUSTSEEJSON) {
798 if (size == -1) {
799 p->cb_printf ("%"PFMT64d, addr);
800 } else {
801 p->cb_printf ("[ ");
802 while (size--) {
803 updateAddr (buf, i, endian, &addr, NULL);
804 if (elem == -1 || elem == 0) {
805 p->cb_printf ("%"PFMT64d, addr);
806 if (elem == 0) {
807 elem = -2;
808 }
809 }
810 if (size != 0 && elem == -1) {
811 p->cb_printf (", ");
812 }
813 if (elem > -1) {
814 elem--;
815 }
816 i+=4;
817 }
818 p->cb_printf (" ]");
819 }
820 p->cb_printf ("}");
821 }
822 }
823
r_print_format_hexflag(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)824 static void r_print_format_hexflag(const RPrint* p, int endian, int mode,
825 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
826 ut64 addr = 0;
827 int elem = -1;
828 if (size >= ARRAYINDEX_COEF) {
829 elem = size/ARRAYINDEX_COEF-1;
830 size %= ARRAYINDEX_COEF;
831 }
832 updateAddr (buf + i, size - i, endian, &addr, NULL);
833 if (MUSTSET) {
834 p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
835 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
836 p->cb_printf ("0x%08"PFMT64x, addr & UT32_MAX);
837 } else if (MUSTSEE) {
838 ut32 addr32 = (ut32)addr;
839 if (!SEEVALUE && !ISQUIET) {
840 p->cb_printf ("0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
841 }
842 if (size==-1) {
843 if (ISQUIET && (addr32 == UT32_MAX)) {
844 p->cb_printf ("-1");
845 } else {
846 p->cb_printf ("0x%08"PFMT64x, (ut64)addr32);
847 }
848 } else {
849 if (!SEEVALUE) {
850 p->cb_printf ("[ ");
851 }
852 while (size--) {
853 updateAddr (buf + i, size - i, endian, &addr, NULL);
854 if (elem == -1 || elem == 0) {
855 p->cb_printf ("0x%08"PFMT64x, addr);
856 if (elem == 0) {
857 elem = -2;
858 }
859 }
860 if (size != 0 && elem == -1) {
861 p->cb_printf (", ");
862 }
863 if (elem > -1) {
864 elem--;
865 }
866 i+=4;
867 }
868 if (!SEEVALUE) {
869 p->cb_printf (" ]");
870 }
871 }
872 } else if (MUSTSEEJSON) {
873 if (size == -1) {
874 p->cb_printf ("%"PFMT64d, addr);
875 } else {
876 p->cb_printf ("[ ");
877 while (size--) {
878 updateAddr (buf + i, size - i, endian, &addr, NULL);
879 if (elem == -1 || elem == 0) {
880 p->cb_printf ("%"PFMT64d, addr);
881 if (elem == 0) {
882 elem = -2;
883 }
884 }
885 if (size != 0 && elem == -1) {
886 p->cb_printf (",");
887 }
888 if (elem > -1) {
889 elem--;
890 }
891 i += 4;
892 }
893 p->cb_printf (" ]");
894 }
895 p->cb_printf ("}");
896 }
897 }
898
r_print_format_10bytes(const RPrint * p,int mode,const char * setval,ut64 seeki,ut64 addr,ut8 * buf)899 static int r_print_format_10bytes(const RPrint* p, int mode, const char *setval,
900 ut64 seeki, ut64 addr, ut8* buf) {
901 ut8 buffer[255];
902 int j;
903 if (MUSTSET) {
904 p->cb_printf ("?e pf B not yet implemented\n");
905 } else if (mode & R_PRINT_DOT) {
906 for (j = 0; j<10; j++) {
907 p->cb_printf ("%02x ", buf[j]);
908 }
909 } else if (MUSTSEE) {
910 if (!p->iob.read_at) {
911 printf ("(cannot read memory)\n");
912 return -1;
913 }
914 p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
915 if (!SEEVALUE && !ISQUIET) {
916 p->cb_printf ("0x%08" PFMT64x " = ", seeki);
917 }
918 for (j=0; j<10; j++) {
919 p->cb_printf ("%02x ", buf[j]);
920 }
921 if (!SEEVALUE) {
922 p->cb_printf (" ... (");
923 }
924 for (j = 0; j < 10; j++) {
925 if (!SEEVALUE) {
926 if (IS_PRINTABLE (buf[j])) {
927 p->cb_printf ("%c", buf[j]);
928 } else {
929 p->cb_printf (".");
930 }
931 }
932 }
933 if (!SEEVALUE) {
934 p->cb_printf (")");
935 }
936 } else if (MUSTSEEJSON) {
937 if (!p->iob.read_at) {
938 printf ("(cannot read memory)\n");
939 return -1;
940 } else {
941 p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
942 }
943 p->cb_printf ("[ %d", buf[0]);
944 j = 1;
945 for (; j < 10; j++) {
946 p->cb_printf (", %d", buf[j]);
947 }
948 p->cb_printf ("]");
949 return 0;
950 }
951 return 0;
952 }
953
r_print_format_hexpairs(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)954 static int r_print_format_hexpairs(const RPrint* p, int endian, int mode,
955 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
956 int j;
957 size = (size == -1) ? 1 : size;
958 if (MUSTSET) {
959 p->cb_printf ("?e pf X not yet implemented\n");
960 } else if (mode & R_PRINT_DOT) {
961 for (j = 0; j < size; j++) {
962 p->cb_printf ("%02x", buf[i + j]);
963 }
964 } else if (MUSTSEE) {
965 size = (size < 1) ? 1 : size;
966 if (!SEEVALUE && !ISQUIET) {
967 p->cb_printf ("0x%08" PFMT64x " = ", seeki);
968 }
969 for (j = 0; j < size; j++) {
970 p->cb_printf ("%02x ", buf[i + j]);
971 }
972 if (!SEEVALUE) {
973 p->cb_printf (" ... (");
974 }
975 for (j=0; j<size; j++) {
976 if (!SEEVALUE) {
977 if (IS_PRINTABLE (buf[j])) {
978 p->cb_printf ("%c", buf[i+j]);
979 } else {
980 p->cb_printf (".");
981 }
982 }
983 }
984 p->cb_printf (")");
985 } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
986 size = (size < 1) ? 1 : size;
987 p->cb_printf ("[ %d", buf[0]);
988 j = 1;
989 for (; j < 10; j++) {
990 p->cb_printf (", %d", buf[j]);
991 }
992 p->cb_printf ("]");
993 if (MUSTSEEJSON) {
994 p->cb_printf ("}");
995 }
996 return size;
997 }
998 return size;
999 }
1000
r_print_format_float(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1001 static void r_print_format_float(const RPrint* p, int endian, int mode,
1002 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1003 float val_f = 0.0f;
1004 ut64 addr = 0;
1005 int elem = -1;
1006 if (size >= ARRAYINDEX_COEF) {
1007 elem = size/ARRAYINDEX_COEF - 1;
1008 size %= ARRAYINDEX_COEF;
1009 }
1010 val_f = updateAddr (buf + i, 999, endian, &addr, NULL);
1011 if (MUSTSET) {
1012 p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval,
1013 seeki + ((elem >= 0) ? elem * 4 : 0));
1014 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1015 p->cb_printf ("%.9g", val_f);
1016 } else {
1017 if (MUSTSEE) {
1018 if (!SEEVALUE && !ISQUIET) {
1019 p->cb_printf ("0x%08"PFMT64x" = ",
1020 seeki + ((elem >= 0) ? elem * 4 : 0));
1021 }
1022 }
1023 if (size == -1) {
1024 p->cb_printf ("%.9g", val_f);
1025 } else {
1026 if (!SEEVALUE) {
1027 p->cb_printf ("[ ");
1028 }
1029 while (size--) {
1030 val_f = updateAddr (buf + i, 9999, endian, &addr, NULL);
1031 if (elem == -1 || elem == 0) {
1032 p->cb_printf ("%.9g", val_f);
1033 if (elem == 0) {
1034 elem = -2;
1035 }
1036 }
1037 if (size != 0 && elem == -1) {
1038 p->cb_printf (", ");
1039 }
1040 if (elem > -1) {
1041 elem--;
1042 }
1043 i += 4;
1044 }
1045 if (!SEEVALUE) {
1046 p->cb_printf (" ]");
1047 }
1048 }
1049 if (MUSTSEEJSON) {
1050 p->cb_printf ("}");
1051 }
1052 }
1053 }
1054
1055
r_print_format_double(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1056 static void r_print_format_double(const RPrint* p, int endian, int mode,
1057 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1058 double val_f = 0.0;
1059 ut64 addr = 0;
1060 int elem = -1;
1061 if (size >= ARRAYINDEX_COEF) {
1062 elem = size/ARRAYINDEX_COEF - 1;
1063 size %= ARRAYINDEX_COEF;
1064 }
1065 updateAddr (buf + i, 999, endian, &addr, NULL);
1066 r_mem_swaporcopy ((ut8*)&val_f, buf + i, sizeof (double), endian);
1067 if (MUSTSET) {
1068 p->cb_printf ("wv8 %s @ 0x%08"PFMT64x"\n", setval,
1069 seeki + ((elem >= 0) ? elem * 8 : 0));
1070 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1071 p->cb_printf ("%.17g", val_f);
1072 } else {
1073 if (MUSTSEE) {
1074 if (!SEEVALUE && !ISQUIET) {
1075 p->cb_printf ("0x%08"PFMT64x" = ",
1076 seeki + ((elem >= 0) ? elem * 8 : 0));
1077 }
1078 }
1079 if (size == -1) {
1080 p->cb_printf ("%.17g", val_f);
1081 } else {
1082 if (!SEEVALUE) {
1083 p->cb_printf ("[ ");
1084 }
1085 while (size--) {
1086 // XXX this 999 is scary
1087 updateAddr (buf + i, 9999, endian, &addr, NULL);
1088 r_mem_swaporcopy ((ut8*)&val_f, buf + i, sizeof (double), endian);
1089 if (elem == -1 || elem == 0) {
1090 p->cb_printf ("%.17g", val_f);
1091 if (elem == 0) {
1092 elem = -2;
1093 }
1094 }
1095 if (size != 0 && elem == -1) {
1096 p->cb_printf (", ");
1097 }
1098 if (elem > -1) {
1099 elem--;
1100 }
1101 i += 8;
1102 }
1103 if (!SEEVALUE) {
1104 p->cb_printf (" ]");
1105 }
1106 }
1107 if (MUSTSEEJSON) {
1108 p->cb_printf ("}");
1109 }
1110 }
1111 }
1112
r_print_format_word(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1113 static void r_print_format_word(const RPrint* p, int endian, int mode,
1114 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1115 ut64 addr;
1116 int elem = -1;
1117 if (size >= ARRAYINDEX_COEF) {
1118 elem = size/ARRAYINDEX_COEF-1;
1119 size %= ARRAYINDEX_COEF;
1120 }
1121 addr = endian
1122 ? (*(buf + i)) << 8 | (*(buf + i + 1))
1123 : (*(buf + i + 1)) << 8 | (*(buf + i));
1124 if (MUSTSET) {
1125 p->cb_printf ("wv2 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*2:0));
1126 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1127 if (size == -1) {
1128 p->cb_printf ("0x%04"PFMT64x, addr);
1129 }
1130 while ((size -= 2) > 0) {
1131 addr = endian
1132 ? (*(buf+i))<<8 | (*(buf+i+1))
1133 : (*(buf+i+1))<<8 | (*(buf+i));
1134 if (elem == -1 || elem == 0) {
1135 p->cb_printf ("%"PFMT64d, addr);
1136 if (elem == 0) {
1137 elem = -2;
1138 }
1139 }
1140 if (size != 0 && elem == -1) {
1141 p->cb_printf (",");
1142 }
1143 if (elem > -1) {
1144 elem--;
1145 }
1146 i += 2;
1147 }
1148 } else if (MUSTSEE) {
1149 if (!SEEVALUE && !ISQUIET) {
1150 p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*2:0));
1151 }
1152 if (size==-1) {
1153 p->cb_printf ("0x%04"PFMT64x, addr);
1154 } else {
1155 if (!SEEVALUE) {
1156 p->cb_printf ("[ ");
1157 }
1158 while (size--) {
1159 addr = endian
1160 ? (*(buf+i))<<8 | (*(buf+i+1))
1161 : (*(buf+i+1))<<8 | (*(buf+i));
1162 if (elem == -1 || elem == 0) {
1163 p->cb_printf ("0x%04"PFMT64x, addr);
1164 if (elem == 0) {
1165 elem = -2;
1166 }
1167 }
1168 if (size != 0 && elem == -1) {
1169 p->cb_printf (", ");
1170 }
1171 if (elem > -1) {
1172 elem--;
1173 }
1174 i += 2;
1175 }
1176 if (!SEEVALUE) {
1177 p->cb_printf (" ]");
1178 }
1179 }
1180 } else if (MUSTSEEJSON) {
1181 if (size==-1) {
1182 p->cb_printf ("%"PFMT64d, addr);
1183 } else {
1184 p->cb_printf ("[ ");
1185 while ( (size -= 2) >0) {
1186 addr = endian
1187 ? (*(buf+i))<<8 | (*(buf+i+1))
1188 : (*(buf+i+1))<<8 | (*(buf+i));
1189 if (elem == -1 || elem == 0) {
1190 p->cb_printf ("%"PFMT64d, addr);
1191 if (elem == 0) {
1192 elem = -2;
1193 }
1194 }
1195 if (size != 0 && elem == -1) {
1196 p->cb_printf (",");
1197 }
1198 if (elem > -1) {
1199 elem--;
1200 }
1201 i += 2;
1202 }
1203 p->cb_printf (" ]");
1204 }
1205 p->cb_printf ("}");
1206 }
1207 }
1208
r_print_byte_escape(const RPrint * p,const char * src,char ** dst,int dot_nl)1209 static void r_print_byte_escape(const RPrint* p, const char *src, char **dst, int dot_nl) {
1210 r_return_if_fail (p->strconv_mode);
1211 r_str_byte_escape (src, dst, dot_nl, !strcmp (p->strconv_mode, "asciidot"), p->esc_bslash);
1212 }
1213
r_print_format_nulltermstring(const RPrint * p,int len,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1214 static void r_print_format_nulltermstring(const RPrint* p, int len, int endian, int mode,
1215 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1216 if (!p->iob.is_valid_offset (p->iob.io, seeki, 1)) {
1217 ut8 ch = 0xff;
1218 // XXX there are some cases where the memory is there but is_valid_offset fails wtf
1219 if (p->iob.read_at (p->iob.io, seeki, &ch, 1) != 1 && ch != 0xff) {
1220 p->cb_printf ("-1");
1221 return;
1222 }
1223 }
1224 if (p->flags & R_PRINT_FLAGS_UNALLOC && !(p->iob.io->cached & R_PERM_R)) {
1225 ut64 total_map_left = 0;
1226 ut64 addr = seeki;
1227 RIOMap *map;
1228 while (total_map_left < len
1229 && (map = p->iob.io->va
1230 ? p->iob.map_get (p->iob.io, addr)
1231 : p->iob.map_get_paddr (p->iob.io, addr))
1232 && map->perm & R_PERM_R) {
1233 if (!r_io_map_size(map)) {
1234 total_map_left = addr == 0 ? UT64_MAX : UT64_MAX - addr + 1;
1235 break;
1236 }
1237 total_map_left += r_io_map_size (map) - (addr - (p->iob.io->va ? r_io_map_begin (map) : map->delta));
1238 addr += total_map_left;
1239 }
1240 if (total_map_left < len) {
1241 len = total_map_left;
1242 }
1243 }
1244 int str_len = r_str_nlen ((char *)buf + i, len - i);
1245 bool overflow = (size == -1 || size > len - i) && str_len == len - i;
1246 if (MUSTSET) {
1247 int buflen = strlen ((const char *)buf + seeki);
1248 int vallen = strlen (setval);
1249 char *ons, *newstring = ons = strdup (setval);
1250 if ((newstring[0] == '\"' && newstring[vallen - 1] == '\"')
1251 || (newstring[0] == '\'' && newstring[vallen - 1] == '\'')) {
1252 newstring[vallen - 1] = '\0';
1253 newstring++;
1254 vallen -= 2;
1255 }
1256 if (vallen > buflen) {
1257 eprintf ("Warning: new string is longer than previous one\n");
1258 }
1259 p->cb_printf ("wx ");
1260 for (i = 0; i < vallen; i++) {
1261 if (i < vallen - 3 && newstring[i] == '\\' && newstring[i + 1] == 'x') {
1262 p->cb_printf ("%c%c", newstring[i + 2], newstring[i + 3]);
1263 i += 3;
1264 } else {
1265 p->cb_printf ("%2x", newstring[i]);
1266 }
1267 }
1268 p->cb_printf (" @ 0x%08"PFMT64x"\n", seeki);
1269 free (ons);
1270 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1271 int j = i;
1272 (MUSTSEESTRUCT) ?
1273 p->cb_printf ("\"") :
1274 p->cb_printf ("\\\"");
1275 for (; j<len && ((size==-1 || size-- >0) && buf[j]) ; j++) {
1276 char ch = buf[j];
1277 if (ch == '"') {
1278 p->cb_printf ("\\\"");
1279 } else if (IS_PRINTABLE (ch)) {
1280 p->cb_printf ("%c", ch);
1281 } else {
1282 p->cb_printf (".");
1283 }
1284 }
1285 (MUSTSEESTRUCT) ?
1286 p->cb_printf ("\"") :
1287 p->cb_printf ("\\\"");
1288 } else if (MUSTSEE) {
1289 int j = i;
1290 if (!SEEVALUE && !ISQUIET) {
1291 p->cb_printf ("0x%08" PFMT64x " = %s", seeki, overflow ? "ovf " : "");
1292 }
1293 p->cb_printf ("\"");
1294 for (; j < len && ((size == -1 || size-- > 0) && buf[j]) ; j++) {
1295 char esc_str[5] = { 0 };
1296 char *ptr = esc_str;
1297 r_print_byte_escape (p, (char *)&buf[j], &ptr, false);
1298 p->cb_printf ("%s", esc_str);
1299 }
1300 p->cb_printf ("\"");
1301 } else if (MUSTSEEJSON) {
1302 char *utf_encoded_buf = NULL;
1303 p->cb_printf ("\"");
1304 utf_encoded_buf = r_str_escape_utf8_for_json (
1305 (char *)buf + i, size == -1 ? str_len : R_MIN (size, str_len));
1306 if (utf_encoded_buf){
1307 p->cb_printf ("%s", utf_encoded_buf);
1308 free (utf_encoded_buf);
1309 }
1310 p->cb_printf ("\"");
1311 if (overflow) {
1312 p->cb_printf (",\"overflow\":true");
1313 }
1314 p->cb_printf ("}");
1315 }
1316 }
1317
r_print_format_nulltermwidestring(const RPrint * p,const int len,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int size)1318 static void r_print_format_nulltermwidestring(const RPrint* p, const int len, int endian, int mode,
1319 const char *setval, ut64 seeki, ut8* buf, int i, int size) {
1320 if (MUSTSET) {
1321 int vallen = strlen(setval);
1322 char *newstring, *ons;
1323 newstring = ons = strdup(setval);
1324 if ((newstring[0] == '\"' && newstring[vallen-1] == '\"')
1325 || (newstring[0] == '\'' && newstring[vallen-1] == '\'')) {
1326 newstring[vallen - 1] = '\0';
1327 newstring++;
1328 vallen -= 2;
1329 }
1330 if ((size = vallen) > r_wstr_clen((char*)(buf+seeki))) {
1331 eprintf ("Warning: new string is longer than previous one\n");
1332 }
1333 p->cb_printf ("ww %s @ 0x%08"PFMT64x"\n", newstring, seeki);
1334 free(ons);
1335 } else if (MUSTSEE) {
1336 int j = i;
1337 if (!SEEVALUE && !ISQUIET) {
1338 p->cb_printf ("0x%08"PFMT64x" = ", seeki);
1339 }
1340 for (; j<len && ((size==-1 || size-->0) && buf[j]) ; j+=2) {
1341 if (IS_PRINTABLE (buf[j])) {
1342 p->cb_printf ("%c", buf[j]);
1343 } else {
1344 p->cb_printf (".");
1345 }
1346 }
1347 } else if (MUSTSEEJSON) {
1348 int j = i;
1349 p->cb_printf ("%"PFMT64d",\"string\":\"", seeki);
1350 for (; j < len && ((size == -1 || size-- > 0) && buf[j]); j += 2) {
1351 if (IS_PRINTABLE (buf[j])) {
1352 p->cb_printf ("%c", buf[j]);
1353 } else {
1354 p->cb_printf (".");
1355 }
1356 }
1357 p->cb_printf ("\"}");
1358 }
1359 }
1360
r_print_format_bitfield(const RPrint * p,ut64 seeki,char * fmtname,char * fieldname,ut64 addr,int mode,int size)1361 static void r_print_format_bitfield(const RPrint* p, ut64 seeki, char *fmtname,
1362 char *fieldname, ut64 addr, int mode, int size) {
1363 char *bitfield = NULL;
1364 addr &= (1ULL << (size * 8)) - 1;
1365 if (MUSTSEE && !SEEVALUE) {
1366 p->cb_printf ("0x%08"PFMT64x" = ", seeki);
1367 }
1368 bitfield = r_type_enum_getbitfield (p->sdb_types, fmtname, addr);
1369 if (bitfield && *bitfield) {
1370 if (MUSTSEEJSON) {
1371 p->cb_printf ("\"%s\"}", bitfield);
1372 } else if (MUSTSEE) {
1373 p->cb_printf ("%s (bitfield) = %s\n", fieldname, bitfield);
1374 }
1375 } else {
1376 if (MUSTSEEJSON) {
1377 p->cb_printf ("\"`tb %s 0x%"PFMT64x"`\"}", fmtname, addr);
1378 } else if (MUSTSEE) {
1379 p->cb_printf ("%s (bitfield) = `tb %s 0x%"PFMT64x"`\n",
1380 fieldname, fmtname, addr);
1381 }
1382 }
1383 free (bitfield);
1384 }
1385
r_print_format_enum(const RPrint * p,ut64 seeki,char * fmtname,char * fieldname,ut64 addr,int mode,int size)1386 static void r_print_format_enum(const RPrint* p, ut64 seeki, char *fmtname,
1387 char *fieldname, ut64 addr, int mode, int size) {
1388 char *enumvalue = NULL;
1389 addr &= (1ULL << (size * 8)) - 1;
1390 if (MUSTSEE && !SEEVALUE) {
1391 p->cb_printf ("0x%08"PFMT64x" = ", seeki);
1392 }
1393 enumvalue = r_type_enum_member (p->sdb_types, fmtname, NULL, addr);
1394 if (enumvalue && *enumvalue) {
1395 if (mode & R_PRINT_DOT) {
1396 p->cb_printf ("%s.%s", fmtname, enumvalue);
1397 } else if (MUSTSEEJSON) {
1398 p->cb_printf ("%"PFMT64d",\"label\":\"%s\",\"enum\":\"%s\"}",
1399 addr, enumvalue, fmtname);
1400 } else if (MUSTSEE) {
1401 p->cb_printf ("%s (enum %s) = 0x%"PFMT64x" ; %s\n",
1402 fieldname, fmtname, addr, enumvalue);
1403 } else if (MUSTSEESTRUCT) {
1404 p->cb_printf ("%s", enumvalue);
1405 }
1406 } else {
1407 if (MUSTSEEJSON) {
1408 p->cb_printf ("%"PFMT64d",\"enum\":\"%s\"}", addr, fmtname);
1409 } else if (MUSTSEE) {
1410 p->cb_printf ("%s (enum %s) = 0x%"PFMT64x"\n",//`te %s 0x%x`\n",
1411 fieldname, fmtname, addr); //enumvalue); //fmtname, addr);
1412 }
1413 }
1414 free (enumvalue);
1415 }
1416
r_print_format_register(const RPrint * p,int mode,const char * name,const char * setval)1417 static void r_print_format_register(const RPrint* p, int mode,
1418 const char *name, const char *setval) {
1419 if (!p || !p->get_register || !p->reg) {
1420 return;
1421 }
1422 RRegItem *ri = p->get_register (p->reg, name, R_REG_TYPE_ALL);
1423 if (ri) {
1424 if (MUSTSET) {
1425 p->cb_printf ("dr %s=%s\n", name, setval);
1426 } else if (MUSTSEE) {
1427 if (!SEEVALUE) {
1428 p->cb_printf ("%s : 0x%08" PFMT64x "\n", ri->name, p->get_register_value (p->reg, ri));
1429 } else {
1430 p->cb_printf ("0x%08" PFMT64x "\n", p->get_register_value (p->reg, ri));
1431 }
1432 } else if (MUSTSEEJSON) {
1433 p->cb_printf ("%"PFMT64d"}", p->get_register_value (p->reg, ri));
1434 }
1435 } else {
1436 p->cb_printf ("Register %s does not exists\n", name);
1437 }
1438 }
1439
r_print_format_num_specifier(const RPrint * p,ut64 addr,int bytes,int sign)1440 static void r_print_format_num_specifier(const RPrint *p, ut64 addr, int bytes, int sign) {
1441 #define EXT(T) (sign ? (signed T)(addr) : (unsigned T)(addr) )
1442 const char *fs64 = sign ? "%"PFMT64d : "%"PFMT64u;
1443 const char *fs = sign ? "%d" : "%u";
1444 if (bytes == 1) {
1445 p->cb_printf (fs, EXT(char));
1446 } else if (bytes == 2) {
1447 p->cb_printf (fs, EXT(short));
1448 } else if (bytes == 4) {
1449 p->cb_printf (fs, EXT(int)); //XXX: int is not necessarily 4 bytes I guess.
1450 } else if (bytes == 8) {
1451 p->cb_printf (fs64, addr);
1452 }
1453 #undef EXT
1454 }
1455
r_print_format_num(const RPrint * p,int endian,int mode,const char * setval,ut64 seeki,ut8 * buf,int i,int bytes,int sign,int size)1456 static void r_print_format_num(const RPrint *p, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int bytes, int sign, int size) {
1457 ut64 addr = 0LL;
1458 int elem = -1;
1459 if (size >= ARRAYINDEX_COEF) {
1460 elem = size / ARRAYINDEX_COEF - 1;
1461 size %= ARRAYINDEX_COEF;
1462 }
1463 if (bytes == 8) {
1464 updateAddr (buf + i, size - i, endian, NULL, &addr);
1465 } else {
1466 updateAddr (buf + i, size - i, endian, &addr, NULL);
1467 }
1468 if (MUSTSET) {
1469 p->cb_printf ("wv%d %s @ 0x%08"PFMT64x"\n", bytes, setval, seeki+((elem>=0)?elem*(bytes):0));
1470 } else if ((mode & R_PRINT_DOT) || MUSTSEESTRUCT) {
1471 r_print_format_num_specifier (p, addr, bytes, sign);
1472 } else if (MUSTSEE) {
1473 if (!SEEVALUE && !ISQUIET) {
1474 p->cb_printf ("0x%08"PFMT64x" = ", seeki + ((elem >= 0)? elem * bytes: 0));
1475 }
1476 if (size == -1) {
1477 r_print_format_num_specifier (p, addr, bytes, sign);
1478 } else {
1479 if (!SEEVALUE) {
1480 p->cb_printf ("[ ");
1481 }
1482 while (size--) {
1483 if (bytes == 8) {
1484 updateAddr (buf + i, size - i, endian, NULL, &addr);
1485 } else {
1486 updateAddr (buf + i, size - i, endian, &addr, NULL);
1487 }
1488 if (elem == -1 || elem == 0) {
1489 r_print_format_num_specifier (p, addr, bytes, sign);
1490 if (elem == 0) {
1491 elem = -2;
1492 }
1493 }
1494 if (size != 0 && elem == -1) {
1495 p->cb_printf (", ");
1496 }
1497 if (elem > -1) {
1498 elem--;
1499 }
1500 i += bytes;
1501 }
1502 if (!SEEVALUE) {
1503 p->cb_printf (" ]");
1504 }
1505 }
1506 } else if (MUSTSEEJSON) {
1507 if (size == -1) {
1508 r_print_format_num_specifier (p, addr, bytes, sign);
1509 } else {
1510 p->cb_printf ("[ ");
1511 while (size--) {
1512 if (bytes == 8) {
1513 updateAddr (buf + i, size, endian, NULL, &addr);
1514 } else {
1515 updateAddr (buf + i, size, endian, &addr, NULL);
1516 }
1517 if (elem == -1 || elem == 0) {
1518 r_print_format_num_specifier (p, addr, bytes, sign);
1519 if (elem == 0) {
1520 elem = -2;
1521 }
1522 }
1523 if (size != 0 && elem == -1) {
1524 p->cb_printf (", ");
1525 }
1526 if (elem > -1) {
1527 elem--;
1528 }
1529 i += bytes;
1530 }
1531 p->cb_printf (" ]");
1532 }
1533 p->cb_printf ("}");
1534 }
1535 }
1536
r_print_format_byname(RPrint * p,const char * name)1537 R_API const char *r_print_format_byname(RPrint *p, const char *name) {
1538 return sdb_const_get (p->formats, name, NULL);
1539 }
1540
1541 // XXX: this is somewhat incomplete. must be updated to handle all format chars
r_print_format_struct_size(RPrint * p,const char * f,int mode,int n)1542 R_API int r_print_format_struct_size(RPrint *p, const char *f, int mode, int n) {
1543 char *end, *args, *fmt;
1544 int size = 0, tabsize = 0, i, idx = 0, biggest = 0, fmt_len = 0, times = 1;
1545 bool tabsize_set = false;
1546 if (!f) {
1547 return -1;
1548 }
1549 if (n >= 5) { // This is the nesting level, is this not a bit arbitrary?!
1550 return 0;
1551 }
1552 const char *fmt2 = sdb_get (p->formats, f, NULL);
1553 if (!fmt2) {
1554 fmt2 = f;
1555 }
1556 char *o = strdup (fmt2);
1557 if (!o) {
1558 return -1;
1559 }
1560 end = strchr (o, ' ');
1561 fmt = o;
1562 if (!end && !(end = strchr (o, '\0'))) {
1563 free (o);
1564 return -1;
1565 }
1566 if (*end) {
1567 *end = 0;
1568 args = strdup (end + 1);
1569 } else {
1570 args = strdup ("");
1571 }
1572
1573 i = 0;
1574 if (fmt[i] == '{') {
1575 char *end = strchr (fmt + i + 1, '}');
1576 if (!end) {
1577 eprintf ("No end curly bracket.\n");
1578 free (o);
1579 free (args);
1580 return -1;
1581 }
1582 *end = '\0';
1583 times = r_num_math (NULL, fmt + i + 1);
1584 fmt = end + 1;
1585 }
1586 if (fmt[0] == '0') {
1587 mode |= R_PRINT_UNIONMODE;
1588 fmt++;
1589 } else {
1590 mode &= ~R_PRINT_UNIONMODE;
1591 }
1592
1593 int words = r_str_word_set0_stack (args);
1594 fmt_len = strlen (fmt);
1595 for (; i < fmt_len; i++) {
1596 if (fmt[i] == '[') {
1597 char *end = strchr (fmt + i,']');
1598 if (!end) {
1599 eprintf ("No end bracket.\n");
1600 continue;
1601 }
1602 *end = '\0';
1603 tabsize_set = true;
1604 tabsize = r_num_math (NULL, fmt + i + 1);
1605 *end = ']';
1606 while (fmt[i++] != ']') {
1607 ;
1608 }
1609 } else {
1610 tabsize = 1;
1611 }
1612
1613 switch (fmt[i]) {
1614 case '.':
1615 idx--;
1616 case 'c':
1617 case 'b':
1618 case 'X':
1619 size += tabsize * 1;
1620 break;
1621 case 'w':
1622 size += tabsize * 2;
1623 break;
1624 case ':':
1625 idx--;
1626 case 'd':
1627 case 'o':
1628 case 'i':
1629 case 'x':
1630 case 'f':
1631 case 's':
1632 case 't':
1633 size += tabsize * 4;
1634 break;
1635 case 'S':
1636 case 'q':
1637 case 'F':
1638 size += tabsize * 8;
1639 break;
1640 case 'Q': // uint128
1641 size += tabsize * 16;
1642 break;
1643 case 'z':
1644 case 'Z':
1645 size += tabsize;
1646 break;
1647 case '*':
1648 size += tabsize * (p->bits / 8);
1649 i++;
1650 idx--; //no need to go ahead for args
1651 break;
1652 case 'B':
1653 case 'E':
1654 if (tabsize_set) {
1655 if (tabsize < 1 || tabsize > 8) {
1656 eprintf ("Unknown enum format size: %d\n", tabsize);
1657 break;
1658 }
1659 size += tabsize;
1660 } else {
1661 size += 4; // Assuming by default enum as int
1662 }
1663 break;
1664 case '?':
1665 {
1666 const char *wordAtIndex = NULL;
1667 const char *format = NULL;
1668 char *endname = NULL, *structname = NULL;
1669 char tmp = 0;
1670 if (words < idx) {
1671 eprintf ("Index out of bounds\n");
1672 } else {
1673 wordAtIndex = r_str_word_get0 (args, idx);
1674 }
1675 if (!wordAtIndex) {
1676 break;
1677 }
1678 structname = strdup (wordAtIndex);
1679 if (*structname == '(') {
1680 endname = (char*)r_str_rchr (structname, NULL, ')');
1681 } else {
1682 free (structname);
1683 break;
1684 }
1685 if (endname) {
1686 *endname = '\0';
1687 }
1688 format = strchr (structname, ' ');
1689 if (format) {
1690 tmp = *format;
1691 while (tmp == ' ') {
1692 format++;
1693 tmp = *format;
1694 }
1695 } else {
1696 format = sdb_get (p->formats, structname + 1, NULL);
1697 if (format && !strncmp (format, f, strlen (format) - 1)) { // Avoid recursion here
1698 free (o);
1699 free (structname);
1700 return -1;
1701 }
1702 if (!format) { // Fetch format from types db
1703 format = r_type_format (p->sdb_types, structname + 1);
1704 }
1705 }
1706 if (!format) {
1707 eprintf ("Cannot find format for struct `%s'\n", structname + 1);
1708 free (structname);
1709 free (o);
1710 return 0;
1711 }
1712 int newsize = r_print_format_struct_size (p, format, mode, n + 1);
1713 if (newsize < 1) {
1714 eprintf ("Cannot find size for `%s'\n", format);
1715 free (structname);
1716 free (o);
1717 return 0;
1718 }
1719 if (format) {
1720 size += tabsize * newsize;
1721 }
1722 free (structname);
1723 }
1724 break;
1725 case '{':
1726 while (fmt[i] != '}') {
1727 if (!fmt[i]) {
1728 free (o);
1729 free (args);
1730 return -1;
1731 }
1732 i++;
1733 }
1734 i++;
1735 idx--;
1736 break;
1737 case '}':
1738 free (o);
1739 free (args);
1740 return -1;
1741 case '+':
1742 case 'e':
1743 idx--;
1744 break;
1745 case 'p':
1746 if (fmt[i+1] == '2') {
1747 size += tabsize * 2;
1748 } else if (fmt[i+1] == '4') {
1749 size += tabsize * 4;
1750 } else if (fmt[i+1] == '8') {
1751 size += tabsize * 8;
1752 } else {
1753 size += tabsize * (p->bits / 8);
1754 break;
1755 }
1756 i++;
1757 break;
1758 case 'r':
1759 break;
1760 case 'n':
1761 case 'N':
1762 if (fmt[i+1] == '1') {
1763 size += tabsize * 1;
1764 } else if (fmt[i+1] == '2') {
1765 size += tabsize * 2;
1766 } else if (fmt[i+1] == '4') {
1767 size += tabsize * 4;
1768 } else if (fmt[i+1] == '8') {
1769 size += tabsize * 8;
1770 } else {
1771 eprintf ("Invalid n format in (%s)\n", fmt);
1772 free (o);
1773 free (args);
1774 return -2;
1775 }
1776 i++;
1777 break;
1778 case 'u':
1779 case 'D':
1780 case 'T':
1781 //TODO complete this.
1782 default:
1783 //idx--; //Does this makes sense?
1784 break;
1785 }
1786 idx++;
1787 if (mode & R_PRINT_UNIONMODE) {
1788 if (size > biggest) {
1789 biggest = size;
1790 }
1791 size = 0;
1792 }
1793 }
1794 size *= times;
1795 free (o);
1796 free (args);
1797 return (mode & R_PRINT_UNIONMODE)? biggest : size;
1798 }
1799
r_print_format_struct(RPrint * p,ut64 seek,const ut8 * b,int len,const char * name,int slide,int mode,const char * setval,char * field,int anon)1800 static int r_print_format_struct(RPrint* p, ut64 seek, const ut8* b, int len, const char *name,
1801 int slide, int mode, const char *setval, char *field, int anon) {
1802 const char *fmt;
1803 char namefmt[128];
1804 slide++;
1805 if ((slide % STRUCTPTR) > NESTDEPTH || (slide % STRUCTFLAG)/STRUCTPTR > NESTDEPTH) {
1806 eprintf ("Too much nested struct, recursion too deep...\n");
1807 return 0;
1808 }
1809 if (anon) {
1810 fmt = name;
1811 } else {
1812 fmt = sdb_get (p->formats, name, NULL);
1813 if (!fmt) { // Fetch struct info from types DB
1814 fmt = r_type_format (p->sdb_types, name);
1815 }
1816 }
1817 if (!fmt || !*fmt) {
1818 eprintf ("Undefined struct '%s'.\n", name);
1819 return 0;
1820 }
1821 if (MUSTSEE && !SEEVALUE) {
1822 snprintf (namefmt, sizeof (namefmt), "%%%ds", 10+6*slide%STRUCTPTR);
1823 if (fmt[0] == '0') {
1824 p->cb_printf (namefmt, "union");
1825 } else {
1826 p->cb_printf (namefmt, "struct");
1827 }
1828 p->cb_printf ("<%s>\n", name);
1829 }
1830 r_print_format (p, seek, b, len, fmt, mode, setval, field);
1831 return r_print_format_struct_size (p, fmt, mode, 0);
1832 }
1833
get_args_offset(const char * arg)1834 static char *get_args_offset(const char *arg) {
1835 char *args = strchr (arg, ' ');
1836 char *sq_bracket = strchr (arg, '[');
1837 int max = 30;
1838 if (args && sq_bracket) {
1839 char *csq_bracket = strchr (arg, ']');
1840 while (args && csq_bracket && csq_bracket > args && max--) {
1841 args = strchr (csq_bracket, ' ');
1842 }
1843 }
1844 return args;
1845 }
1846
get_format_type(const char fmt,const char arg)1847 static char *get_format_type(const char fmt, const char arg) {
1848 char *type = NULL;
1849 switch (fmt) {
1850 case 'b':
1851 case 'C':
1852 type = strdup ("uint8_t");
1853 break;
1854 case 'c':
1855 type = strdup ("int8_t");
1856 break;
1857 case 'd':
1858 case 'i':
1859 case 'o':
1860 case 'x':
1861 type = strdup ("int32_t");
1862 break;
1863 case 'E':
1864 type = strdup ("enum");
1865 break;
1866 case 'f':
1867 type = strdup ("float");
1868 break;
1869 case 'F':
1870 type = strdup ("double");
1871 break;
1872 case 'q':
1873 type = strdup ("uint64_t");
1874 break;
1875 case 'u':
1876 type = strdup ("uleb128_t");
1877 break;
1878 case 'Q':
1879 type = strdup ("uint128_t");
1880 break;
1881 case 'w':
1882 type = strdup ("uint16_t");
1883 break;
1884 case 'X':
1885 type = strdup ("uint8_t[]");
1886 break;
1887 case 'D':
1888 case 's':
1889 case 'S':
1890 case 't':
1891 case 'z':
1892 case 'Z':
1893 type = strdup ("char*");
1894 break;
1895 case 'n':
1896 case 'N':
1897 switch (arg) {
1898 case '1':
1899 type = strdup (fmt == 'n' ? "int8_t" : "uint8_t");
1900 break;
1901 case '2':
1902 type = strdup (fmt == 'n' ? "int16_t" : "uint16_t");
1903 break;
1904 case '4':
1905 type = strdup (fmt == 'n' ? "int32_t" : "uint32_t");
1906 break;
1907 case '8':
1908 type = strdup (fmt == 'n' ? "int64_t" : "uint64_t");
1909 break;
1910 }
1911 break;
1912 }
1913 return type;
1914 }
1915
1916 //TODO PJ
1917 #define MINUSONE ((void*)(size_t)-1)
1918 #define ISSTRUCT (tmp == '?' || (tmp == '*' && *(arg+1) == '?'))
r_print_format(RPrint * p,ut64 seek,const ut8 * b,const int len,const char * formatname,int mode,const char * setval,char * ofield)1919 R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len,
1920 const char *formatname, int mode, const char *setval, char *ofield) {
1921 int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0;
1922 const int old_bits = p->bits;
1923 char *args = NULL, *bracket, tmp, last = 0;
1924 ut64 addr = 0, addr64 = 0, seeki = 0;
1925 static int slide = 0, oldslide = 0, ident = 4;
1926 char namefmt[32], *field = NULL;
1927 const char *arg = NULL;
1928 const char *fmt = NULL;
1929 const char *argend;
1930 int viewflags = 0;
1931 char *oarg = NULL;
1932 char *internal_format = NULL;
1933
1934 /* Load format from name into fmt */
1935 if (!formatname) {
1936 return 0;
1937 }
1938 fmt = sdb_get (p->formats, formatname, NULL);
1939 if (!fmt) {
1940 fmt = formatname;
1941 }
1942 internal_format = strdup (fmt);
1943 fmt = internal_format;
1944 while (*fmt && IS_WHITECHAR (*fmt)) {
1945 fmt++;
1946 }
1947 argend = fmt + strlen (fmt);
1948 arg = fmt;
1949
1950 nexti = nargs = i = j = 0;
1951
1952 if (len < 1) {
1953 free (internal_format);
1954 return 0;
1955 }
1956 // len+2 to save space for the null termination in wide strings
1957 ut8 *buf = calloc (1, len + 2);
1958 if (!buf) {
1959 free (internal_format);
1960 return 0;
1961 }
1962 memcpy (buf, b, len);
1963 endian = p->big_endian;
1964
1965 if (ofield && ofield != MINUSONE) {
1966 field = strdup (ofield);
1967 }
1968 /* get times */
1969 otimes = times = atoi (arg);
1970 if (times > 0) {
1971 while (IS_DIGIT(*arg)) {
1972 arg++;
1973 }
1974 }
1975
1976 bracket = strchr (arg,'{');
1977 if (bracket) {
1978 char *end = strchr (arg, '}');
1979 if (!end) {
1980 eprintf ("No end bracket. Try pf {ecx}b @ esi\n");
1981 goto beach;
1982 }
1983 *end = '\0';
1984 times = r_num_math (NULL, bracket + 1);
1985 arg = end + 1;
1986 }
1987
1988 if (*arg == '\0') {
1989 goto beach;
1990 }
1991
1992 /* get args */
1993 args = get_args_offset (arg);
1994 if (args) {
1995 int l = 0, maxl = 0;
1996 argend = args;
1997 tmp = *args;
1998 while (tmp == ' ') {
1999 args++;
2000 tmp = *args;
2001 }
2002 args = strdup (args);
2003 nargs = r_str_word_set0_stack (args);
2004 if (nargs == 0) {
2005 R_FREE (args);
2006 }
2007 for (i = 0; i < nargs; i++) {
2008 const char *tmp = r_str_word_get0 (args, i);
2009 const char *nm = r_str_rchr (tmp, NULL, ')');
2010 int len = strlen (nm ? nm + 1 : tmp);
2011 if (len > maxl) {
2012 maxl = len;
2013 }
2014 }
2015 l++;
2016 const char *ends = " "; // XXX trailing space warning
2017 snprintf (namefmt, sizeof (namefmt), "%%%ds :%s",
2018 ((maxl + 1) * (1 + slide)) % STRUCTPTR, ends);
2019 }
2020 #define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR)
2021 #define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR))
2022 if (mode == R_PRINT_JSON && slide == 0) {
2023 p->cb_printf ("[");
2024 }
2025 if (mode == R_PRINT_STRUCT) {
2026 if (formatname && *formatname) {
2027 if (strchr (formatname, ' ')) {
2028 p->cb_printf ("struct {\n");
2029 } else {
2030 p->cb_printf ("struct %s {\n", formatname);
2031 }
2032 } else {
2033 p->cb_printf ("struct {\n");
2034 }
2035 }
2036 if (mode && arg[0] == '0') {
2037 mode |= R_PRINT_UNIONMODE;
2038 arg++;
2039 } else {
2040 mode &= ~R_PRINT_UNIONMODE;
2041 }
2042 if (mode & R_PRINT_DOT) {
2043 char *fmtname;
2044 if (formatname && *formatname) {
2045 if (strchr (formatname, ' ')) {
2046 fmtname = r_str_newf ("0x%"PFMT64x, seek);
2047 } else {
2048 fmtname = strdup (formatname);
2049 }
2050 } else {
2051 fmtname = r_str_newf ("0x%"PFMT64x, seek);
2052 }
2053 p->cb_printf ("digraph g { graph [ rank=same; rankdir=LR; ];\n");
2054 p->cb_printf ("root [ rank=1; shape=record\nlabel=\"%s", fmtname);
2055 }
2056
2057 /* go format */
2058 i = 0;
2059 if (!times) {
2060 otimes = times = 1;
2061 }
2062 for (; times; times--) { // repeat N times
2063 const char *orig = arg;
2064 int first = 1;
2065 if (otimes > 1) {
2066 if (mode & R_PRINT_JSON) {
2067 if (otimes > times) {
2068 p->cb_printf (",");
2069 }
2070 p->cb_printf ("[{\"index\":%d,\"offset\":%"PFMT64d"},", otimes-times, seek+i);
2071 } else if (mode) {
2072 p->cb_printf ("0x%08"PFMT64x" [%d] {\n", seek + i, otimes-times);
2073 }
2074 }
2075 arg = orig;
2076 for (idx = 0; i < len && arg < argend && *arg; arg++) {
2077 int size = 0, elem = 0; /* size of the array, element of the array */
2078 char *fieldname = NULL, *fmtname = NULL;
2079 if (mode & R_PRINT_UNIONMODE) {
2080 i = 0;
2081 }
2082 seeki = seek + i;
2083 addr = 0LL;
2084 invalid = 0;
2085 p->bits = old_bits;
2086 if (arg[0] == '[') {
2087 char *end = strchr (arg,']');
2088 if (!end) {
2089 eprintf ("No end bracket.\n");
2090 goto beach;
2091 }
2092 *end = '\0';
2093 size = r_get_size (p->num, buf, endian, arg + 1);
2094 arg = end + 1;
2095 *end = ']';
2096 } else {
2097 size = -1;
2098 }
2099 int fs = r_print_format_struct_size (p, arg, 0, idx);
2100 if (fs == -2) {
2101 i = -1;
2102 goto beach;
2103 }
2104 if (fs < 1) {
2105 fs = 4;
2106 }
2107 if (i + fs - 1 < len) { // should be +7 to avoid oobread on 'q'
2108 // Max byte number where updateAddr will look into
2109 if (len - i < 7) {
2110 updateAddr (buf + i, THRESHOLD - (len - i), endian, &addr, &addr64);
2111 } else {
2112 updateAddr (buf + i, len - i, endian, &addr, &addr64);
2113 }
2114 if (p->bits == 64) {
2115 addr = addr64;
2116 }
2117 } else {
2118 // eprintf ("Format strings is too big for this buffer\n");
2119 goto beach;
2120 }
2121
2122 tmp = *arg;
2123
2124 if (mode && !args) {
2125 mode |= R_PRINT_ISFIELD;
2126 }
2127 if (!(mode & R_PRINT_QUIET)) {
2128 if (mode & R_PRINT_MUSTSEE && otimes > 1) {
2129 p->cb_printf (" ");
2130 }
2131 }
2132 if (idx < nargs && tmp != 'e' && isptr == 0) {
2133 char *dot = NULL, *bracket = NULL;
2134 if (field) {
2135 dot = strchr (field, '.');
2136 }
2137 if (dot) {
2138 *dot = '\0';
2139 }
2140 free (oarg);
2141 oarg = fieldname = strdup (r_str_word_get0 (args, idx));
2142 if (ISSTRUCT || tmp=='E' || tmp=='B' || tmp=='r') {
2143 if (*fieldname == '(') {
2144 fmtname = fieldname + 1;
2145 fieldname = (char*)r_str_rchr (fieldname, NULL, ')');
2146 if (fieldname) {
2147 *fieldname++ = '\0';
2148 } else {
2149 eprintf ("Missing closing parenthesis in format ')'\n");
2150 goto beach;
2151 }
2152 } else {
2153 eprintf ("Missing name (%s)\n", fieldname);
2154 goto beach;
2155 }
2156 }
2157 if (mode && (!args || (!field && ofield != MINUSONE)
2158 || (field && !strncmp (field, fieldname, \
2159 strchr (field, '[')
2160 ? strchr (field, '[') - field
2161 : strlen (field) + 1)))) {
2162 mode |= R_PRINT_ISFIELD;
2163 } else {
2164 mode &= ~R_PRINT_ISFIELD;
2165 }
2166
2167 /* There we handle specific element in array */
2168 if (field && (bracket = strchr (field, '[')) && mode & R_PRINT_ISFIELD) {
2169 char *end = strchr (field, ']');
2170 if (!end) {
2171 eprintf ("Missing closing bracket\n");
2172 goto beach;
2173 }
2174 *end = '\0';
2175 elem = r_num_math (NULL, bracket + 1) + 1; // +1 to handle 0 index easily
2176 for ( ; bracket < end; bracket++) {
2177 *bracket = '\0';
2178 }
2179 size += elem * ARRAYINDEX_COEF;
2180 } else {
2181 elem = -1;
2182 }
2183 if (tmp != '.' && tmp != ':') {
2184 idx++;
2185 if (MUSTSEE && !SEEVALUE) {
2186 if (!ISQUIET) {
2187 p->cb_printf (namefmt, fieldname);
2188 }
2189 }
2190 }
2191 }
2192 feed_me_again:
2193 switch (isptr) {
2194 case PTRSEEK:
2195 {
2196 nexti = i + (p->bits / 8);
2197 i = 0;
2198 if (tmp == '?') {
2199 seeki = addr;
2200 }
2201 memset (buf, '\0', len);
2202 if (MUSTSEE && !ISQUIET) {
2203 p->cb_printf ("(*0x%"PFMT64x")", addr);
2204 }
2205 isptr = (addr)? PTRBACK: NULLPTR;
2206 if (p->iob.read_at) {
2207 p->iob.read_at (p->iob.io, (ut64)addr, buf, len - 4);
2208 if (((i + 3) < len) || ((i + 7) < len)) {
2209 // XXX this breaks pf *D
2210 if (tmp != 'D') {
2211 updateAddr (buf + i, len - i, endian, &addr, &addr64);
2212 }
2213 } else {
2214 eprintf ("Likely a heap buffer overflow.\n");
2215 goto beach;
2216 }
2217 } else {
2218 eprintf ("(cannot read at 0x%08"PFMT64x", block: %s, blocksize: 0x%x)\n",
2219 addr, b, len);
2220 p->cb_printf ("\n");
2221 goto beach;
2222 }
2223 }
2224 break;
2225 case PTRBACK:
2226 // restore state after pointer seek
2227 i = nexti;
2228 memcpy (buf, b, len);
2229 isptr = NOPTR;
2230 arg--;
2231 continue;
2232 }
2233 if (tmp == 0 && last != '*') {
2234 break;
2235 }
2236
2237 /* skip chars */
2238 switch (tmp) {
2239 case '*': // next char is a pointer
2240 isptr = PTRSEEK;
2241 arg++;
2242 tmp = *arg; //last;
2243 goto feed_me_again;
2244 case '+': // toggle view flags
2245 viewflags = !viewflags;
2246 continue;
2247 case 'e': // tmp swap endian
2248 endian ^= 1;
2249 continue;
2250 case ':': // skip 4 bytes
2251 if (size == -1) {
2252 i += 4;
2253 } else {
2254 while (size--) {
2255 i += 4;
2256 }
2257 }
2258 continue;
2259 case '.': // skip 1 byte
2260 i += (size == -1)? 1: size;
2261 continue;
2262 case 'p': // pointer reference
2263 if (*(arg + 1) == '2') {
2264 tmp = 'w';
2265 arg++;
2266 } else if (*(arg + 1) == '4') {
2267 tmp = 'x';
2268 arg++;
2269 } else if (*(arg + 1) == '8') {
2270 tmp = 'q';
2271 arg++;
2272 } else { //If pointer reference is not mentioned explicitly
2273 switch (p->bits) {
2274 case 16: tmp = 'w'; break;
2275 case 32: tmp = 'x'; break;
2276 default: tmp = 'q'; break;
2277 }
2278 }
2279 break;
2280 }
2281
2282 /* flags */
2283 if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
2284 char *newname = NULL;
2285 if (!fieldname) {
2286 newname = fieldname = r_str_newf ("pf.%"PFMT64u, seeki);
2287 }
2288 if (mode & R_PRINT_UNIONMODE) {
2289 p->cb_printf ("f %s=0x%08"PFMT64x"\n", formatname, seeki);
2290 goto beach;
2291 } else if (tmp == '?') {
2292 p->cb_printf ("f %s.%s_", fmtname, fieldname);
2293 } else if (tmp == 'E') {
2294 p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki);
2295 } else if (slide/STRUCTFLAG>0 && idx==1) {
2296 p->cb_printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki);
2297 } else {
2298 p->cb_printf ("f %s=0x%08" PFMT64x "\n", fieldname, seeki);
2299 }
2300 if (newname) {
2301 R_FREE (newname);
2302 fieldname = NULL;
2303 }
2304 }
2305
2306 /* dot */
2307 if (mode & R_PRINT_DOT) {
2308 if (fieldname) {
2309 p->cb_printf ("|{0x%"PFMT64x"|%c|%s|<%s>",
2310 seeki, tmp, fieldname, fieldname);
2311 } else {
2312 p->cb_printf ("|{0x%"PFMT64x"|%c|",
2313 seeki, tmp);
2314 }
2315 }
2316
2317 /* json */
2318 if (MUSTSEEJSON && mode & R_PRINT_JSON) {
2319 if (oldslide <= slide) {
2320 if (first) {
2321 first = 0;
2322 } else {
2323 p->cb_printf (",");
2324 }
2325 } else if (oldslide) {
2326 p->cb_printf ("]},");
2327 oldslide -= NESTEDSTRUCT;
2328 }
2329 if (fieldname) {
2330 p->cb_printf ("{\"name\":\"%s\",\"type\":\"", fieldname);
2331 } else {
2332 p->cb_printf ("{\"type\":\"");
2333 }
2334 if (ISSTRUCT) {
2335 p->cb_printf ("%s", fmtname);
2336 } else {
2337 if (tmp == 'n' || tmp == 'N') {
2338 p->cb_printf ("%c%c", tmp, *(arg+1));
2339 } else {
2340 p->cb_printf ("%c", tmp);
2341 }
2342 }
2343 if (isptr) {
2344 p->cb_printf ("*");
2345 }
2346 p->cb_printf ("\",\"offset\":%"PFMT64d",\"value\":",
2347 isptr? (seek + nexti - (p->bits / 8)) : seek + i);
2348 }
2349
2350 /* c struct */
2351 if (MUSTSEESTRUCT) {
2352 char *type = get_format_type (tmp, (tmp == 'n' || tmp == 'N') ? arg[1] : 0);
2353 if (type) {
2354 p->cb_printf ("%*c%s %s; // ", ident, ' ', type, fieldname);
2355 } else {
2356 p->cb_printf ("%*cstruct %s {", ident, ' ', fieldname);
2357 }
2358 free (type);
2359 }
2360 bool noline = false;
2361
2362 int oi = i;
2363 if (isptr == NULLPTR) {
2364 if (MUSTSEEJSON) {
2365 p->cb_printf ("\"NULL\"}");
2366 } else if (MUSTSEE) {
2367 p->cb_printf (" NULL\n");
2368 }
2369 isptr = PTRBACK;
2370 } else {
2371 /* format chars */
2372 // before to enter in the switch statement check buf boundaries due to updateAddr
2373 // might go beyond its len and it's usually called in each of the following functions
2374 switch (tmp) {
2375 case 'u':
2376 i += r_print_format_uleb (p, endian, mode, setval, seeki, buf, i, size);
2377 break;
2378 case 't':
2379 r_print_format_time (p, endian, mode, setval, seeki, buf, i, size);
2380 i += (size==-1)? 4: 4 * size;
2381 break;
2382 case 'q':
2383 r_print_format_quadword (p, endian, mode, setval, seeki, buf, i, size);
2384 i += (size == -1)? 8: 8 * size;
2385 break;
2386 case 'Q':
2387 r_print_format_u128 (p, endian, mode, setval, seeki, buf, i, size);
2388 i += (size == -1)? 16: 16 * size;
2389 break;
2390 case 'b':
2391 r_print_format_byte (p, endian, mode, setval, seeki, buf, i, size);
2392 i += (size==-1)? 1: size;
2393 break;
2394 case 'C':
2395 r_print_format_decchar (p, endian, mode, setval, seeki, buf, i, size);
2396 i += (size==-1)? 1: size;
2397 break;
2398 case 'c':
2399 r_print_format_char (p, endian, mode, setval, seeki, buf, i, size);
2400 i += (size==-1)? 1: size;
2401 break;
2402 case 'X':
2403 size = r_print_format_hexpairs (p, endian, mode, setval, seeki, buf, i, size);
2404 i += size;
2405 break;
2406 case 'T':
2407 if (r_print_format_10bytes (p, mode,
2408 setval, seeki, addr, buf) == 0) {
2409 i += (size == -1)? 4: 4 * size;
2410 }
2411 break;
2412 case 'f':
2413 r_print_format_float (p, endian, mode, setval, seeki, buf, i, size);
2414 i += (size == -1)? 4: 4 * size;
2415 break;
2416 case 'F':
2417 r_print_format_double (p, endian, mode, setval, seeki, buf, i, size);
2418 i += (size == -1)? 8: 8 * size;
2419 break;
2420 case 'i':
2421 r_print_format_int (p, endian, mode, setval, seeki, buf, i, size);
2422 i+= (size == -1)? 4: 4 * size;
2423 break;
2424 case 'd': //WHY?? help says: 0x%%08x hexadecimal value (4 bytes)
2425 r_print_format_hex (p, endian, mode, setval, seeki, buf, i, size);
2426 i+= (size == -1)? 4: 4 * size;
2427 break;
2428 case 'D':
2429 if (MUSTSET) {
2430 eprintf ("Set val not implemented yet for disassembler!\n");
2431 }
2432 if (isptr) {
2433 if (p->bits == 64) {
2434 i += r_print_format_disasm (p, addr64, size);
2435 } else {
2436 i += r_print_format_disasm (p, addr, size);
2437 }
2438 } else {
2439 i += r_print_format_disasm (p, seeki, size);
2440 }
2441 break;
2442 case 'o':
2443 r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size);
2444 i += (size == -1)? 4: 4 * size;
2445 break;
2446 case ';':
2447 noline = true;
2448 i -= (size == -1)? 4: 4 * size;
2449 if (i < 0) {
2450 i = 0;
2451 }
2452 break;
2453 case ',':
2454 noline = true;
2455 i -= (size == -1)? 1: size;
2456 if (i < 0) {
2457 i = 0;
2458 }
2459 break;
2460 case 'x':
2461 r_print_format_hexflag (p, endian, mode, setval, seeki, buf, i, size);
2462 i += (size == -1)? 4: 4*size;
2463 break;
2464 case 'w':
2465 r_print_format_word (p, endian, mode, setval, seeki, buf, i, size);
2466 i += (size == -1)? 2: 2 * size;
2467 break;
2468 case 'z': // zero terminated string
2469 r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size);
2470 if (size == -1) {
2471 i += strlen ((char*)buf + i) + 1;
2472 } else {
2473 while (size--) {
2474 i++;
2475 }
2476 }
2477 break;
2478 case 'Z': // zero terminated wide string
2479 r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size);
2480 if (size == -1) {
2481 i += r_wstr_clen((char*)(buf+i))*2+2;
2482 } else {
2483 while (size--) {
2484 i += 2;
2485 }
2486 }
2487 break;
2488 case 's':
2489 if (MUSTSET) {
2490 eprintf ("Set val not implemented yet for strings!\n");
2491 }
2492 if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0) {
2493 i += (size==-1) ? 4 : 4*size;
2494 }
2495 break;
2496 case 'S':
2497 if (MUSTSET) {
2498 eprintf ("Set val not implemented yet for strings!\n");
2499 }
2500 if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0) {
2501 i += (size == -1) ? 8 : 8 * size;
2502 }
2503 break;
2504 case 'B': // resolve bitfield
2505 if (size >= ARRAYINDEX_COEF) {
2506 size %= ARRAYINDEX_COEF;
2507 }
2508 if (MUSTSET) {
2509 eprintf ("Set val not implemented yet for bitfields!\n");
2510 }
2511 r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size);
2512 i+=(size == -1)? 1: size;
2513 break;
2514 case 'E': // resolve enum
2515 if (MUSTSET) {
2516 eprintf ("Set val not implemented yet for enums!\n");
2517 }
2518 if (size >= ARRAYINDEX_COEF) {
2519 size %= ARRAYINDEX_COEF;
2520 }
2521 r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size);
2522 i += (size == -1)? 1: size;
2523 break;
2524 case 'r':
2525 if (fmtname) {
2526 r_print_format_register (p, mode, fmtname, setval);
2527 } else {
2528 eprintf ("Unknown register\n");
2529 }
2530 break;
2531 case '?':
2532 {
2533 int s = 0;
2534 char *nxtfield = NULL;
2535 char *format = NULL;
2536 int anon = 0;
2537 if (size >= ARRAYINDEX_COEF) {
2538 elem = size / ARRAYINDEX_COEF - 1;
2539 size %= ARRAYINDEX_COEF;
2540 }
2541 if (!(mode & R_PRINT_ISFIELD)) {
2542 nxtfield = MINUSONE;
2543 } else if (field) {
2544 nxtfield = strchr (ofield, '.');
2545 }
2546 if (nxtfield != MINUSONE && nxtfield) {
2547 nxtfield++;
2548 }
2549
2550 if (MUSTSEE) {
2551 if (!SEEVALUE) {
2552 p->cb_printf ("\n");
2553 }
2554 }
2555 if (MUSTSEEJSON) {
2556 if (isptr) {
2557 p->cb_printf ("%"PFMT64d"},", seeki);
2558 } else {
2559 p->cb_printf ("[");
2560 }
2561 }
2562 if (MUSTSEESTRUCT) {
2563 if (isptr) {
2564 p->cb_printf ("%"PFMT64d, seeki);
2565 } else {
2566 ident += 4;
2567 p->cb_printf ("\n");
2568 }
2569 }
2570 if (mode & R_PRINT_SEEFLAGS) {
2571 slide += STRUCTFLAG;
2572 }
2573 if (!fmtname) {
2574 break;
2575 }
2576 format = strchr (fmtname, ' ');
2577 if (format) {
2578 anon = 1;
2579 fmtname = format;
2580 while (*fmtname == ' ') {
2581 fmtname++;
2582 }
2583 }
2584 oldslide = slide;
2585 //slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
2586 slide += NESTEDSTRUCT;
2587 if (size == -1) {
2588 s = r_print_format_struct (p, seeki,
2589 buf + i, len - i, fmtname, slide,
2590 mode, setval, nxtfield, anon);
2591 i += (isptr) ? (p->bits / 8) : s;
2592 if (MUSTSEEJSON) {
2593 if (!isptr && (!arg[1] || arg[1] == ' ')) {
2594 p->cb_printf ("]}");
2595 }
2596 }
2597 } else {
2598 if (mode & R_PRINT_ISFIELD) {
2599 if (!SEEVALUE) {
2600 p->cb_printf ("[\n");
2601 }
2602 }
2603 while (size--) {
2604 if (mode && (elem == -1 || elem == 0)) {
2605 mode |= R_PRINT_MUSTSEE;
2606 if (elem == 0) {
2607 elem = -2;
2608 }
2609 } else {
2610 mode &= ~R_PRINT_MUSTSEE;
2611 }
2612 s = r_print_format_struct (p, seek+i,
2613 buf+i, len-i, fmtname, slide, mode, setval, nxtfield, anon);
2614 if ((MUSTSEE || MUSTSEEJSON || MUSTSEESTRUCT) && size != 0 && elem == -1) {
2615 if (MUSTSEEJSON) {
2616 p->cb_printf (",");
2617 } else if (MUSTSEE || MUSTSEESTRUCT) {
2618 p->cb_printf ("\n");
2619 }
2620 }
2621 if (elem > -1) {
2622 elem--;
2623 }
2624 i += (isptr) ? (p->bits / 8) : s;
2625 }
2626 if (mode & R_PRINT_ISFIELD) {
2627 if (!SEEVALUE) {
2628 p->cb_printf ("]\n");
2629 }
2630 }
2631 if (MUSTSEEJSON) {
2632 p->cb_printf ("]}");
2633 }
2634 }
2635 oldslide = slide;
2636 //slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
2637 slide -= NESTEDSTRUCT;
2638 if (mode & R_PRINT_SEEFLAGS) {
2639 oldslide = slide;
2640 slide -= STRUCTFLAG;
2641 }
2642 break;
2643 }
2644 case 'n':
2645 case 'N':
2646 {
2647 int bytes = 0;
2648 int sign = (tmp == 'n') ? 1 : 0;
2649 if (arg[1] == '1') {
2650 bytes = 1;
2651 } else if (arg[1] == '2') {
2652 bytes = 2;
2653 } else if (arg[1] == '4') {
2654 bytes = 4;
2655 } else if (arg[1] == '8') {
2656 bytes = 8;
2657 } else {
2658 invalid = 1;
2659 break;
2660 //or goto beach;???
2661 }
2662 r_print_format_num (p, endian, mode, setval, seeki, buf, i, bytes, sign, size);
2663 i += (size == -1)? bytes: size * bytes;
2664 arg++;
2665 break;
2666 }
2667 default:
2668 /* ignore unknown chars */
2669 invalid = 1;
2670 break;
2671 } //switch
2672 }
2673 if (MUSTSEESTRUCT) {
2674 if (oldslide) {
2675 ident -= 4;
2676 p->cb_printf ("%*c}", ident, ' ');
2677 oldslide -= NESTEDSTRUCT;
2678 }
2679 p->cb_printf ("\n");
2680 }
2681 if (mode & R_PRINT_DOT) {
2682 p->cb_printf ("}");
2683 }
2684 if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
2685 int sz = i - oi;
2686 if (sz > 1) {
2687 p->cb_printf ("fl %d @ 0x%08"PFMT64x"\n", sz, seeki);
2688 p->cb_printf ("Cd %d @ 0x%08"PFMT64x"\n", sz, seeki);
2689 }
2690 }
2691 if (viewflags && p->offname) {
2692 const char *s = p->offname (p->user, seeki);
2693 if (s) {
2694 p->cb_printf ("@(%s)", s);
2695 }
2696 s = p->offname (p->user, addr);
2697 if (s) {
2698 p->cb_printf ("*(%s)", s);
2699 }
2700 }
2701 if (!noline && tmp != 'D' && !invalid && !fmtname && MUSTSEE) {
2702 p->cb_printf ("\n");
2703 }
2704 last = tmp;
2705
2706 // XXX: Due to the already noted issues with the above, we need to strip
2707 // args from fmt:args the same way we strip fmt BUT only for enums as
2708 // nested structs seem to be handled correctly above!
2709 if (arg[0] == 'E') {
2710 char *end_fmt = strchr (arg, ' ');
2711 if (!end_fmt) {
2712 goto beach;
2713 }
2714 char *next_args = strchr (end_fmt + 1, ' ');
2715 if (next_args) {
2716 while (*next_args != '\0') {
2717 *end_fmt++ = *next_args++;
2718 }
2719 }
2720 *end_fmt = '\0';
2721 }
2722 }
2723 if (otimes > 1) {
2724 if (MUSTSEEJSON) {
2725 p->cb_printf ("]");
2726 } else if (mode) {
2727 p->cb_printf ("}\n");
2728 }
2729 }
2730 arg = orig;
2731 oldslide = 0;
2732 }
2733 if (mode & R_PRINT_JSON && slide == 0) {
2734 p->cb_printf("]\n");
2735 }
2736 if (MUSTSEESTRUCT && slide == 0) {
2737 p->cb_printf ("}\n");
2738 }
2739 if (mode & R_PRINT_DOT) {
2740 p->cb_printf ("\"];\n}\n");
2741 // TODO: show nested structs and field reference lines
2742 }
2743 beach:
2744 if (slide == 0) {
2745 oldslide = 0;
2746 }
2747 free (internal_format);
2748 free (oarg);
2749 free (buf);
2750 free (field);
2751 free (args);
2752 return i;
2753 }
2754