Rizin
unix-like reverse engineering framework and cli tools
format.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2007-2020 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2007-2020 Skia <skia@libskia.so>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_util.h>
6 #include <rz_util/rz_print.h>
7 #include <rz_reg.h>
8 #include <rz_type.h>
9 
10 #define NOPTR 0
11 #define PTRSEEK 1
12 #define PTRBACK 2
13 #define NULLPTR 3
14 #define STRUCTPTR 100
15 #define NESTEDSTRUCT 1
16 #define STRUCTFLAG 10000
17 #define NESTDEPTH 14
18 #define ARRAYINDEX_COEF 10000
19 
20 #define MUSTSEE (mode & RZ_PRINT_MUSTSEE && mode & RZ_PRINT_ISFIELD && !(mode & RZ_PRINT_JSON))
21 #define ISQUIET (mode & RZ_PRINT_QUIET)
22 #define MUSTSET (mode & RZ_PRINT_MUSTSET && mode & RZ_PRINT_ISFIELD && setval)
23 #define SEEVALUE (mode & RZ_PRINT_VALUE)
24 #define MUSTSEEJSON (mode & RZ_PRINT_JSON && mode & RZ_PRINT_ISFIELD)
25 #define MUSTSEESTRUCT (mode & RZ_PRINT_STRUCT)
26 
27 // this define is used as a way to acknowledge when updateAddr should take len
28 // as real len of the buffer
29 #define THRESHOLD (-4444)
30 
31 // TODO REWRITE THIS IS BECOMING A NIGHTMARE
32 
33 static float updateAddr(const ut8 *buf, int len, int endian, ut64 *addr, ut64 *addr64) {
34  float f = 0.0;
35  // assert sizeof (float) == sizeof (ut32))
36  // 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
37  if (len >= THRESHOLD - 7 && len < THRESHOLD) {
38  len = len + THRESHOLD; // get the real len to avoid oob
39  } else {
40  len = 999;
41  }
42  if (len < 1) {
43  return 0;
44  }
45  if (len >= sizeof(float)) {
46  rz_mem_swaporcopy((ut8 *)&f, buf, sizeof(float), endian);
47  }
48  if (addr && len > 3) {
49  ut32 tmpaddr = rz_read_ble32(buf, endian);
50  *addr = (ut64)tmpaddr;
51  }
52  if (addr64 && len > 7) {
53  *addr64 = rz_read_ble64(buf, endian);
54  }
55  return f;
56 }
57 
58 static int rz_get_size(RzNum *num, ut8 *buf, int endian, const char *s) {
59  int len = strlen(s);
60  if (s[0] == '*' && len >= 4) { // value pointed by the address
61  ut64 addr;
62  int offset = (int)rz_num_math(num, s + 1);
63  (void)updateAddr(buf + offset, 999, endian, &addr, NULL);
64  return addr;
65  }
66  // flag handling doesnt seems to work here
67  return rz_num_math(num, s);
68 }
69 
70 static void rz_type_format_u128(RzStrBuf *outbuf, int endian, int mode,
71  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
72  ut64 low = rz_read_ble64(buf, endian);
73  ut64 hig = rz_read_ble64(buf + 8, endian);
74  if (MUSTSEEJSON) {
75  rz_strbuf_append(outbuf, "\"");
76  } else if (!SEEVALUE && !ISQUIET) {
77  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = (uint128_t)", seeki);
78  }
79  if (endian) {
80  rz_strbuf_appendf(outbuf, "0x%016" PFMT64x "", low);
81  rz_strbuf_appendf(outbuf, "%016" PFMT64x, hig);
82  } else {
83  rz_strbuf_appendf(outbuf, "0x%016" PFMT64x "", hig);
84  rz_strbuf_appendf(outbuf, "%016" PFMT64x, low);
85  }
86  if (MUSTSEEJSON) {
87  const char *end = endian ? "big" : "little";
88  rz_strbuf_appendf(outbuf, "\",\"endian\":\"%s\",\"ctype\":\"uint128_t\"}", end);
89  }
90 }
91 
92 static void rz_type_format_quadword(RzStrBuf *outbuf, int endian, int mode,
93  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
94  ut64 addr64;
95  int elem = -1;
96  if (size >= ARRAYINDEX_COEF) {
97  elem = size / ARRAYINDEX_COEF - 1;
99  }
100  updateAddr(buf + i, size - i, endian, NULL, &addr64);
101  if (MUSTSET) {
102  rz_strbuf_appendf(outbuf, "wv8 %s @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem * 8 : 0));
103  } else if (MUSTSEE) {
104  if (!SEEVALUE && !ISQUIET) {
105  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = (qword)",
106  seeki + ((elem >= 0) ? elem * 8 : 0));
107  }
108  if (size == -1) {
109  if (addr64 == UT32_MAX || ((st64)addr64 < 0 && (st64)addr64 > -4096)) {
110  rz_strbuf_appendf(outbuf, "%d", (int)(addr64));
111  } else {
112  rz_strbuf_appendf(outbuf, "0x%016" PFMT64x, addr64);
113  }
114  } else {
115  if (!SEEVALUE) {
116  rz_strbuf_append(outbuf, "[ ");
117  }
118  while (size--) {
119  updateAddr(buf + i, size - i, endian, NULL, &addr64);
120  if (elem == -1 || elem == 0) {
121  rz_strbuf_appendf(outbuf, "0x%016" PFMT64x, addr64);
122  if (elem == 0) {
123  elem = -2;
124  }
125  }
126  if (size != 0 && elem == -1) {
127  rz_strbuf_append(outbuf, ", ");
128  }
129  if (elem > -1) {
130  elem--;
131  }
132  i += 8;
133  }
134  if (!SEEVALUE) {
135  rz_strbuf_append(outbuf, " ]");
136  }
137  }
138  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
139  if (size == -1) {
140  rz_strbuf_appendf(outbuf, "%" PFMT64d, addr64);
141  } else {
142  rz_strbuf_append(outbuf, "[ ");
143  while (size--) {
144  updateAddr(buf + i, size - i, endian, NULL, &addr64);
145  if (elem == -1 || elem == 0) {
146  rz_strbuf_appendf(outbuf, "%" PFMT64d, addr64);
147  if (elem == 0) {
148  elem = -2;
149  }
150  }
151  if (size != 0 && elem == -1) {
152  rz_strbuf_append(outbuf, ", ");
153  }
154  if (elem > -1) {
155  elem--;
156  }
157  i += 8;
158  }
159  rz_strbuf_append(outbuf, " ]");
160  }
161  if (MUSTSEEJSON) {
162  rz_strbuf_append(outbuf, "}");
163  }
164  }
165 }
166 
167 static void rz_type_format_byte(RzStrBuf *outbuf, int endian, int mode,
168  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
169  int elem = -1;
170  if (size >= ARRAYINDEX_COEF) {
171  elem = size / ARRAYINDEX_COEF - 1;
173  }
174  if (MUSTSET) {
175  rz_strbuf_appendf(outbuf, "\"w %s\" @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem : 0));
176  } else if (MUSTSEE) {
177  if (!SEEVALUE && !ISQUIET) {
178  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem : 0));
179  }
180  if (size == -1) {
181  rz_strbuf_appendf(outbuf, "0x%02x", buf[i]);
182  } else {
183  if (!SEEVALUE) {
184  rz_strbuf_append(outbuf, "[ ");
185  }
186  while (size--) {
187  if (elem == -1 || elem == 0) {
188  rz_strbuf_appendf(outbuf, "0x%02x", buf[i]);
189  if (elem == 0) {
190  elem = -2;
191  }
192  }
193  if (size != 0 && elem == -1) {
194  rz_strbuf_append(outbuf, ", ");
195  }
196  if (elem > -1) {
197  elem--;
198  }
199  i++;
200  }
201  if (!SEEVALUE) {
202  rz_strbuf_append(outbuf, " ]");
203  }
204  }
205  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
206  if (size == -1) {
207  rz_strbuf_appendf(outbuf, "%d", buf[i]);
208  } else {
209  rz_strbuf_append(outbuf, "[ ");
210  const char *comma = "";
211  while (size--) {
212  if (elem == -1 || elem == 0) {
213  rz_strbuf_appendf(outbuf, "%s%d", comma, buf[i]);
214  comma = ",";
215  if (elem == 0) {
216  elem = -2;
217  }
218  }
219  if (elem > -1) {
220  elem--;
221  }
222  i++;
223  }
224  rz_strbuf_append(outbuf, " ]");
225  }
226  if (MUSTSEEJSON) {
227  rz_strbuf_append(outbuf, "}");
228  }
229  }
230 }
231 
232 // FIXME: Port to the PJ API
233 // Return number of consumed bytes
234 static int rz_type_format_uleb(RzStrBuf *outbuf, int endian, int mode,
235  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
236  int elem = -1;
237  int s = 0, offset = 0;
238  ut64 value = 0;
239  if (size >= ARRAYINDEX_COEF) {
240  elem = size / ARRAYINDEX_COEF - 1;
242  }
243  if (MUSTSET) {
244  ut8 *tmp;
245  char *nbr;
246  do {
247  rz_uleb128_decode(buf + i, &s, &value);
248  i += s;
249  offset += s;
250  } while (elem--);
251  tmp = (ut8 *)rz_uleb128_encode(rz_num_math(NULL, setval), &s);
252  nbr = rz_hex_bin2strdup(tmp, s);
253  rz_strbuf_appendf(outbuf, "wx %s @ 0x%08" PFMT64x "\n", nbr, seeki + offset - s);
254  free(tmp);
255  free(nbr);
256  } else if (MUSTSEE) {
257  if (!SEEVALUE && !ISQUIET) {
258  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
259  }
260  if (size == -1) {
263  } else {
264  if (!SEEVALUE) {
265  rz_strbuf_append(outbuf, "[ ");
266  }
267  while (size--) {
268  if (elem == -1 || elem == 0) {
269  rz_uleb128_decode(buf + i, &s, &value);
270  i += s;
271  offset += s;
273  if (elem == 0) {
274  elem = -2;
275  }
276  }
277  if (size != 0 && elem == -1) {
278  rz_strbuf_append(outbuf, ", ");
279  }
280  if (elem > -1) {
281  elem--;
282  }
283  }
284  if (!SEEVALUE) {
285  rz_strbuf_append(outbuf, " ]");
286  }
287  }
288  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
289  if (size == -1) {
291  rz_strbuf_appendf(outbuf, "\"%" PFMT64d "\"", value);
292  } else {
293  rz_strbuf_append(outbuf, "[ ");
294  while (size--) {
295  if (elem == -1 || elem == 0) {
296  rz_uleb128_decode(buf + i, &s, &value);
297  i += s;
298  offset += s;
299  rz_strbuf_appendf(outbuf, "\"%" PFMT64d "\"", value);
300  if (elem == 0) {
301  elem = -2;
302  }
303  }
304  if (size != 0 && elem == -1) {
305  rz_strbuf_append(outbuf, ", ");
306  }
307  if (elem > -1) {
308  elem--;
309  }
310  }
311  rz_strbuf_append(outbuf, " ]");
312  }
313  if (MUSTSEEJSON) {
314  rz_strbuf_append(outbuf, "}");
315  }
316  }
317  return offset;
318 }
319 
320 static void rz_type_format_char(RzStrBuf *outbuf, int endian, int mode,
321  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
322  int elem = -1;
323  if (size >= ARRAYINDEX_COEF) {
324  elem = size / ARRAYINDEX_COEF - 1;
326  }
327  if (MUSTSET) {
328  rz_strbuf_appendf(outbuf, "\"w %s\" @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem : 0));
329  } else if (MUSTSEE) {
330  if (!SEEVALUE && !ISQUIET) {
331  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 2 : 0)); // XXX:: shouldn't it be elem*1??
332  }
333  if (size == -1) {
334  rz_strbuf_appendf(outbuf, "'%c'", IS_PRINTABLE(buf[i]) ? buf[i] : '.');
335  } else {
336  if (!SEEVALUE) {
337  rz_strbuf_append(outbuf, "[ ");
338  }
339  while (size--) {
340  if (elem == -1 || elem == 0) {
341  rz_strbuf_appendf(outbuf, "'%c'", IS_PRINTABLE(buf[i]) ? buf[i] : '.');
342  if (elem == 0) {
343  elem = -2;
344  }
345  }
346  if (size != 0 && elem == -1) {
347  rz_strbuf_append(outbuf, ", ");
348  }
349  if (elem > -1) {
350  elem--;
351  }
352  i++;
353  }
354  if (!SEEVALUE) {
355  rz_strbuf_append(outbuf, " ]");
356  }
357  }
358  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
359  if (size == -1) {
360  rz_strbuf_appendf(outbuf, "\"%c\"", IS_PRINTABLE(buf[i]) ? buf[i] : '.');
361  } else {
362  rz_strbuf_append(outbuf, "[ ");
363  while (size--) {
364  if (elem == -1 || elem == 0) {
365  rz_strbuf_appendf(outbuf, "\"%c\"", IS_PRINTABLE(buf[i]) ? buf[i] : '.');
366  if (elem == 0) {
367  elem = -2;
368  }
369  }
370  if (size != 0 && elem == -1) {
371  rz_strbuf_append(outbuf, ", ");
372  }
373  if (elem > -1) {
374  elem--;
375  }
376  i++;
377  }
378  rz_strbuf_append(outbuf, " ]");
379  }
380  if (MUSTSEEJSON) {
381  rz_strbuf_append(outbuf, "}");
382  }
383  }
384 }
385 
386 static void rz_type_format_decchar(RzStrBuf *outbuf, int endian, int mode,
387  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
388  int elem = -1;
389  if (size >= ARRAYINDEX_COEF) {
390  elem = size / ARRAYINDEX_COEF - 1;
392  }
393  if (MUSTSET) {
394  rz_strbuf_appendf(outbuf, "\"w %s\" @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem : 0));
395  } else if (MUSTSEE) {
396  if (!SEEVALUE && !ISQUIET) {
397  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem : 0));
398  }
399  if (size == -1) {
400  rz_strbuf_appendf(outbuf, "%d", buf[i]);
401  } else {
402  if (!SEEVALUE) {
403  rz_strbuf_append(outbuf, "[ ");
404  }
405  while (size--) {
406  if (elem == -1 || elem == 0) {
407  rz_strbuf_appendf(outbuf, "%d", buf[i]);
408  if (elem == 0) {
409  elem = -2;
410  }
411  }
412  if (size != 0 && elem == -1) {
413  rz_strbuf_appendf(outbuf, ", ");
414  }
415  if (elem > -1) {
416  elem--;
417  }
418  i++;
419  }
420  if (!SEEVALUE) {
421  rz_strbuf_append(outbuf, " ]");
422  }
423  }
424  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
425  if (size == -1) {
426  rz_strbuf_appendf(outbuf, "\"%d\"", buf[i]);
427  } else {
428  rz_strbuf_append(outbuf, "[ ");
429  while (size--) {
430  if (elem == -1 || elem == 0) {
431  rz_strbuf_appendf(outbuf, "\"%d\"", buf[i]);
432  if (elem == 0) {
433  elem = -2;
434  }
435  }
436  if (size != 0 && elem == -1) {
437  rz_strbuf_appendf(outbuf, ", ");
438  }
439  if (elem > -1) {
440  elem--;
441  }
442  i++;
443  }
444  rz_strbuf_append(outbuf, " ]");
445  }
446  if (MUSTSEEJSON) {
447  rz_strbuf_append(outbuf, "}");
448  }
449  }
450 }
451 
452 static int rz_type_format_string(const RzTypeDB *typedb, RzStrBuf *outbuf, ut64 seeki, ut64 addr64, ut64 addr, int is64, int mode) {
453  ut8 buffer[255];
454  buffer[0] = 0;
455  const ut64 at = (is64 == 1) ? addr64 : (ut64)addr;
456  int res = typedb->iob.read_at(typedb->iob.io, at, buffer, sizeof(buffer) - 8);
457  if (MUSTSEEJSON) {
458  char *encstr = rz_str_utf16_encode((const char *)buffer, -1);
459  if (encstr) {
460  rz_strbuf_appendf(outbuf, "%" PFMT64d ",\"string\":\"%s\"}", seeki, encstr);
461  free(encstr);
462  }
463  } else if (MUSTSEESTRUCT) {
464  char *encstr = rz_str_utf16_encode((const char *)buffer, -1);
465  if (encstr) {
466  rz_strbuf_appendf(outbuf, "\"%s\"", encstr);
467  free(encstr);
468  }
469  } else if (MUSTSEE) {
470  if (!SEEVALUE && !ISQUIET) {
471  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
472  }
473  if (!SEEVALUE) {
474  if (ISQUIET) {
475  if (addr == 0LL) {
476  rz_strbuf_append(outbuf, "NULL");
477  } else if (addr == UT32_MAX || addr == UT64_MAX) {
478  rz_strbuf_append(outbuf, "-1");
479  } else {
480  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " ", addr);
481  }
482  } else {
483  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " -> 0x%08" PFMT64x " ", seeki, addr);
484  }
485  }
486  if (res > 0 && buffer[0] != 0xff && buffer[1] != 0xff) {
487  rz_strbuf_appendf(outbuf, "\"%s\"", buffer);
488  }
489  }
490  return 0;
491 }
492 
493 static void rz_type_format_time(RzStrBuf *outbuf, 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;
501  }
502  updateAddr(buf + i, size - i, endian, &addr, NULL);
503  if (MUSTSET) {
504  rz_strbuf_appendf(outbuf, "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  rz_asctime_r(rz_gmtime_r((time_t *)&addr, &timestruct), timestr);
511  *(timestr + 24) = '\0';
512  if (!SEEVALUE && !ISQUIET) {
513  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
514  }
515  if (size == -1) {
516  rz_strbuf_appendf(outbuf, "%s", timestr);
517  } else {
518  if (!SEEVALUE) {
519  rz_strbuf_appendf(outbuf, "[ ");
520  }
521  while (size--) {
522  updateAddr(buf + i, size - i, endian, &addr, NULL);
523  rz_asctime_r(rz_gmtime_r((time_t *)&addr, &timestruct), timestr);
524  *(timestr + 24) = '\0';
525  if (elem == -1 || elem == 0) {
526  rz_strbuf_appendf(outbuf, "%s", timestr);
527  if (elem == 0) {
528  elem = -2;
529  }
530  }
531  if (size != 0 && elem == -1) {
532  rz_strbuf_appendf(outbuf, ", ");
533  }
534  if (elem > -1) {
535  elem--;
536  }
537  i += 4;
538  }
539  if (!SEEVALUE) {
540  rz_strbuf_appendf(outbuf, " ]");
541  }
542  }
543  free(timestr);
544  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
545  char *timestr = malloc(ASCTIME_BUF_MINLEN);
546  if (!timestr) {
547  return;
548  }
549  rz_asctime_r(rz_gmtime_r((time_t *)&addr, &timestruct), timestr);
550  *(timestr + 24) = '\0';
551  if (size == -1) {
552  rz_strbuf_appendf(outbuf, "\"%s\"", timestr);
553  } else {
554  rz_strbuf_append(outbuf, "[ ");
555  while (size--) {
556  updateAddr(buf + i, size - i, endian, &addr, NULL);
557  rz_asctime_r(rz_gmtime_r((time_t *)&addr, &timestruct), timestr);
558  *(timestr + 24) = '\0';
559  if (elem == -1 || elem == 0) {
560  rz_strbuf_appendf(outbuf, "\"%s\"", timestr);
561  if (elem == 0) {
562  elem = -2;
563  }
564  }
565  if (size != 0 && elem == -1) {
566  rz_strbuf_append(outbuf, ", ");
567  }
568  if (elem > -1) {
569  elem--;
570  }
571  i += 4;
572  }
573  rz_strbuf_append(outbuf, " ]");
574  }
575  free(timestr);
576  if (MUSTSEEJSON) {
577  rz_strbuf_append(outbuf, "}");
578  }
579  }
580 }
581 
582 // TODO: support unsigned int?
583 static void rz_type_format_hex(RzStrBuf *outbuf, 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;
590  }
591  updateAddr(buf + i, size - i, endian, &addr, NULL);
592  if (MUSTSET) {
593  rz_strbuf_appendf(outbuf, "wv4 %s @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem * 4 : 0));
594  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
596  } else if (MUSTSEE) {
597  if (!SEEVALUE && !ISQUIET) {
598  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
599  }
600  if (size == -1) {
601  if (addr == UT64_MAX || addr == UT32_MAX) {
602  rz_strbuf_append(outbuf, "-1");
603  } else {
605  }
606  } else {
607  if (!SEEVALUE) {
608  rz_strbuf_append(outbuf, "[ ");
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  rz_strbuf_append(outbuf, "-1");
616  } else {
618  }
619  } else {
621  }
622  if (elem == 0) {
623  elem = -2;
624  }
625  }
626  if (size != 0 && elem == -1) {
627  rz_strbuf_append(outbuf, ", ");
628  }
629  if (elem > -1) {
630  elem--;
631  }
632  i += 4;
633  }
634  if (!SEEVALUE) {
635  rz_strbuf_append(outbuf, " ]");
636  }
637  }
638  } else if (MUSTSEEJSON) {
639  if (size == -1) {
641  } else {
642  rz_strbuf_append(outbuf, "[ ");
643  while (size--) {
644  updateAddr(buf + i, size - i, endian, &addr, NULL);
645  if (elem == -1 || elem == 0) {
647  if (elem == 0) {
648  elem = -2;
649  }
650  }
651  if (size != 0 && elem == -1) {
652  rz_strbuf_append(outbuf, ", ");
653  }
654  if (elem > -1) {
655  elem--;
656  }
657  i += 4;
658  }
659  rz_strbuf_append(outbuf, " ]");
660  }
661  rz_strbuf_append(outbuf, "}");
662  }
663 }
664 
665 static void rz_type_format_int(RzStrBuf *outbuf, 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;
672  }
673  updateAddr(buf + i, size - i, endian, &addr, NULL);
674  if (MUSTSET) {
675  rz_strbuf_appendf(outbuf, "wv4 %s @ %" PFMT64d "\n", setval, seeki + ((elem >= 0) ? elem * 4 : 0));
676  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
678  } else if (MUSTSEE) {
679  if (!SEEVALUE && !ISQUIET) {
680  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
681  }
682  if (size == -1) {
684  } else {
685  if (!SEEVALUE) {
686  rz_strbuf_append(outbuf, "[ ");
687  }
688  while (size--) {
689  updateAddr(buf + i, size - i, endian, &addr, NULL);
690  if (elem == -1 || elem == 0) {
692  if (elem == 0) {
693  elem = -2;
694  }
695  }
696  if (size != 0 && elem == -1) {
697  rz_strbuf_append(outbuf, ", ");
698  }
699  if (elem > -1) {
700  elem--;
701  }
702  i += 4;
703  }
704  if (!SEEVALUE) {
705  rz_strbuf_append(outbuf, " ]");
706  }
707  }
708  } else if (MUSTSEEJSON) {
709  if (size == -1) {
711  } else {
712  rz_strbuf_append(outbuf, "[ ");
713  while (size--) {
714  updateAddr(buf + i, size - i, endian, &addr, NULL);
715  if (elem == -1 || elem == 0) {
717  if (elem == 0) {
718  elem = -2;
719  }
720  }
721  if (size != 0 && elem == -1) {
722  rz_strbuf_append(outbuf, ", ");
723  }
724  if (elem > -1) {
725  elem--;
726  }
727  i += 4;
728  }
729  rz_strbuf_append(outbuf, " ]");
730  }
731  rz_strbuf_append(outbuf, "}");
732  }
733 }
734 
735 /*
736 static int rz_type_format_disasm(const RzPrint *p, ut64 seeki, int size) {
737  ut64 prevseeki = seeki;
738 
739  if (!p->disasm || !p->user) {
740  return 0;
741  }
742 
743  size = RZ_MAX(1, size);
744 
745  while (size-- > 0) {
746  seeki += p->disasm(p->user, seeki);
747  }
748 
749  return seeki - prevseeki;
750 }
751 */
752 
753 static void rz_type_format_octal(RzStrBuf *outbuf, int endian, int mode,
754  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
755  ut64 addr;
756  int elem = -1;
757  if (size >= ARRAYINDEX_COEF) {
758  elem = size / ARRAYINDEX_COEF - 1;
760  }
761  updateAddr(buf + i, size - i, endian, &addr, NULL);
762  if (MUSTSET) {
763  rz_strbuf_appendf(outbuf, "wv4 %s @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem * 4 : 0));
764  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
766  } else if (MUSTSEE) {
767  if (!SEEVALUE && !ISQUIET) {
768  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
769  }
770  if (!SEEVALUE) {
771  rz_strbuf_append(outbuf, "(octal) ");
772  }
773  if (size == -1) {
775  } else {
776  if (!SEEVALUE) {
777  rz_strbuf_append(outbuf, "[ ");
778  }
779  while (size--) {
780  updateAddr(buf + i, size - i, endian, &addr, NULL);
781  if (elem == -1 || elem == 0) {
783  if (elem == 0) {
784  elem = -2;
785  }
786  }
787  if (size != 0 && elem == -1) {
788  rz_strbuf_append(outbuf, ", ");
789  }
790  if (elem > -1) {
791  elem--;
792  }
793  i += 4;
794  }
795  if (!SEEVALUE) {
796  rz_strbuf_append(outbuf, " ]");
797  }
798  }
799  } else if (MUSTSEEJSON) {
800  if (size == -1) {
802  } else {
803  rz_strbuf_append(outbuf, "[ ");
804  while (size--) {
805  updateAddr(buf, i, endian, &addr, NULL);
806  if (elem == -1 || elem == 0) {
808  if (elem == 0) {
809  elem = -2;
810  }
811  }
812  if (size != 0 && elem == -1) {
813  rz_strbuf_append(outbuf, ", ");
814  }
815  if (elem > -1) {
816  elem--;
817  }
818  i += 4;
819  }
820  rz_strbuf_append(outbuf, " ]");
821  }
822  rz_strbuf_append(outbuf, "}");
823  }
824 }
825 
826 static void rz_type_format_hexflag(RzStrBuf *outbuf, int endian, int mode,
827  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
828  ut64 addr = 0;
829  int elem = -1;
830  if (size >= ARRAYINDEX_COEF) {
831  elem = size / ARRAYINDEX_COEF - 1;
833  }
834  updateAddr(buf + i, size - i, endian, &addr, NULL);
835  if (MUSTSET) {
836  rz_strbuf_appendf(outbuf, "wv4 %s @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem * 4 : 0));
837  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
839  } else if (MUSTSEE) {
840  ut32 addr32 = (ut32)addr;
841  if (!SEEVALUE && !ISQUIET) {
842  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 4 : 0));
843  }
844  if (size == -1) {
845  if (ISQUIET && (addr32 == UT32_MAX)) {
846  rz_strbuf_append(outbuf, "-1");
847  } else {
848  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x, (ut64)addr32);
849  }
850  } else {
851  if (!SEEVALUE) {
852  rz_strbuf_append(outbuf, "[ ");
853  }
854  while (size--) {
855  updateAddr(buf + i, size - i, endian, &addr, NULL);
856  if (elem == -1 || elem == 0) {
858  if (elem == 0) {
859  elem = -2;
860  }
861  }
862  if (size != 0 && elem == -1) {
863  rz_strbuf_append(outbuf, ", ");
864  }
865  if (elem > -1) {
866  elem--;
867  }
868  i += 4;
869  }
870  if (!SEEVALUE) {
871  rz_strbuf_append(outbuf, " ]");
872  }
873  }
874  } else if (MUSTSEEJSON) {
875  if (size == -1) {
877  } else {
878  rz_strbuf_append(outbuf, "[ ");
879  while (size--) {
880  updateAddr(buf + i, size - i, endian, &addr, NULL);
881  if (elem == -1 || elem == 0) {
883  if (elem == 0) {
884  elem = -2;
885  }
886  }
887  if (size != 0 && elem == -1) {
888  rz_strbuf_append(outbuf, ",");
889  }
890  if (elem > -1) {
891  elem--;
892  }
893  i += 4;
894  }
895  rz_strbuf_append(outbuf, " ]");
896  }
897  rz_strbuf_append(outbuf, "}");
898  }
899 }
900 
901 static int rz_type_format_10bytes(const RzTypeDB *typedb, RzStrBuf *outbuf, int mode, const char *setval,
902  ut64 seeki, ut64 addr, ut8 *buf) {
903  ut8 buffer[255];
904  int j;
905  if (MUSTSET) {
906  rz_strbuf_append(outbuf, "?e pf B not yet implemented\n");
907  } else if (mode & RZ_PRINT_DOT) {
908  for (j = 0; j < 10; j++) {
909  rz_strbuf_appendf(outbuf, "%02x ", buf[j]);
910  }
911  } else if (MUSTSEE) {
912  typedb->iob.read_at(typedb->iob.io, (ut64)addr, buffer, 248);
913  if (!SEEVALUE && !ISQUIET) {
914  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
915  }
916  for (j = 0; j < 10; j++) {
917  rz_strbuf_appendf(outbuf, "%02x ", buf[j]);
918  }
919  if (!SEEVALUE) {
920  rz_strbuf_append(outbuf, " ... (");
921  }
922  for (j = 0; j < 10; j++) {
923  if (!SEEVALUE) {
924  if (IS_PRINTABLE(buf[j])) {
925  rz_strbuf_appendf(outbuf, "%c", buf[j]);
926  } else {
927  rz_strbuf_append(outbuf, ".");
928  }
929  }
930  }
931  if (!SEEVALUE) {
932  rz_strbuf_append(outbuf, ")");
933  }
934  } else if (MUSTSEEJSON) {
935  typedb->iob.read_at(typedb->iob.io, (ut64)addr, buffer, 248);
936  rz_strbuf_appendf(outbuf, "[ %d", buf[0]);
937  j = 1;
938  for (; j < 10; j++) {
939  rz_strbuf_appendf(outbuf, ", %d", buf[j]);
940  }
941  rz_strbuf_append(outbuf, "]");
942  return 0;
943  }
944  return 0;
945 }
946 
947 static int rz_type_format_hexpairs(RzStrBuf *outbuf, int endian, int mode,
948  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
949  int j;
950  size = (size == -1) ? 1 : size;
951  if (MUSTSET) {
952  rz_strbuf_append(outbuf, "?e pf X not yet implemented\n");
953  } else if (mode & RZ_PRINT_DOT) {
954  for (j = 0; j < size; j++) {
955  rz_strbuf_appendf(outbuf, "%02x", buf[i + j]);
956  }
957  } else if (MUSTSEE) {
958  size = (size < 1) ? 1 : size;
959  if (!SEEVALUE && !ISQUIET) {
960  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
961  }
962  for (j = 0; j < size; j++) {
963  rz_strbuf_appendf(outbuf, "%02x ", buf[i + j]);
964  }
965  if (!SEEVALUE) {
966  rz_strbuf_append(outbuf, " ... (");
967  }
968  for (j = 0; j < size; j++) {
969  if (!SEEVALUE) {
970  if (IS_PRINTABLE(buf[j])) {
971  rz_strbuf_appendf(outbuf, "%c", buf[i + j]);
972  } else {
973  rz_strbuf_append(outbuf, ".");
974  }
975  }
976  }
977  rz_strbuf_append(outbuf, ")");
978  } else if (MUSTSEEJSON || MUSTSEESTRUCT) {
979  size = (size < 1) ? 1 : size;
980  rz_strbuf_appendf(outbuf, "[ %d", buf[0]);
981  j = 1;
982  for (; j < 10; j++) {
983  rz_strbuf_appendf(outbuf, ", %d", buf[j]);
984  }
985  rz_strbuf_append(outbuf, "]");
986  if (MUSTSEEJSON) {
987  rz_strbuf_append(outbuf, "}");
988  }
989  return size;
990  }
991  return size;
992 }
993 
994 static void rz_type_format_float(RzStrBuf *outbuf, int endian, int mode,
995  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
996  float val_f = 0.0f;
997  ut64 addr = 0;
998  int elem = -1;
999  if (size >= ARRAYINDEX_COEF) {
1000  elem = size / ARRAYINDEX_COEF - 1;
1001  size %= ARRAYINDEX_COEF;
1002  }
1003  val_f = updateAddr(buf + i, 999, endian, &addr, NULL);
1004  if (MUSTSET) {
1005  rz_strbuf_appendf(outbuf, "wv4 %s @ 0x%08" PFMT64x "\n", setval,
1006  seeki + ((elem >= 0) ? elem * 4 : 0));
1007  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
1008  rz_strbuf_appendf(outbuf, "%.9g", val_f);
1009  } else {
1010  if (MUSTSEE) {
1011  if (!SEEVALUE && !ISQUIET) {
1012  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ",
1013  seeki + ((elem >= 0) ? elem * 4 : 0));
1014  }
1015  }
1016  if (size == -1) {
1017  rz_strbuf_appendf(outbuf, "%.9g", val_f);
1018  } else {
1019  if (!SEEVALUE) {
1020  rz_strbuf_append(outbuf, "[ ");
1021  }
1022  while (size--) {
1023  val_f = updateAddr(buf + i, 9999, endian, &addr, NULL);
1024  if (elem == -1 || elem == 0) {
1025  rz_strbuf_appendf(outbuf, "%.9g", val_f);
1026  if (elem == 0) {
1027  elem = -2;
1028  }
1029  }
1030  if (size != 0 && elem == -1) {
1031  rz_strbuf_append(outbuf, ", ");
1032  }
1033  if (elem > -1) {
1034  elem--;
1035  }
1036  i += 4;
1037  }
1038  if (!SEEVALUE) {
1039  rz_strbuf_append(outbuf, " ]");
1040  }
1041  }
1042  if (MUSTSEEJSON) {
1043  rz_strbuf_append(outbuf, "}");
1044  }
1045  }
1046 }
1047 
1048 static void rz_type_format_double(RzStrBuf *outbuf, int endian, int mode,
1049  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
1050  double val_f = 0.0;
1051  ut64 addr = 0;
1052  int elem = -1;
1053  if (size >= ARRAYINDEX_COEF) {
1054  elem = size / ARRAYINDEX_COEF - 1;
1055  size %= ARRAYINDEX_COEF;
1056  }
1057  updateAddr(buf + i, 999, endian, &addr, NULL);
1058  rz_mem_swaporcopy((ut8 *)&val_f, buf + i, sizeof(double), endian);
1059  if (MUSTSET) {
1060  rz_strbuf_appendf(outbuf, "wv8 %s @ 0x%08" PFMT64x "\n", setval,
1061  seeki + ((elem >= 0) ? elem * 8 : 0));
1062  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
1063  rz_strbuf_appendf(outbuf, "%.17g", val_f);
1064  } else {
1065  if (MUSTSEE) {
1066  if (!SEEVALUE && !ISQUIET) {
1067  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ",
1068  seeki + ((elem >= 0) ? elem * 8 : 0));
1069  }
1070  }
1071  if (size == -1) {
1072  rz_strbuf_appendf(outbuf, "%.17g", val_f);
1073  } else {
1074  if (!SEEVALUE) {
1075  rz_strbuf_append(outbuf, "[ ");
1076  }
1077  while (size--) {
1078  // XXX this 999 is scary
1079  updateAddr(buf + i, 9999, endian, &addr, NULL);
1080  rz_mem_swaporcopy((ut8 *)&val_f, buf + i, sizeof(double), endian);
1081  if (elem == -1 || elem == 0) {
1082  rz_strbuf_appendf(outbuf, "%.17g", val_f);
1083  if (elem == 0) {
1084  elem = -2;
1085  }
1086  }
1087  if (size != 0 && elem == -1) {
1088  rz_strbuf_append(outbuf, ", ");
1089  }
1090  if (elem > -1) {
1091  elem--;
1092  }
1093  i += 8;
1094  }
1095  if (!SEEVALUE) {
1096  rz_strbuf_append(outbuf, " ]");
1097  }
1098  }
1099  if (MUSTSEEJSON) {
1100  rz_strbuf_appendf(outbuf, "}");
1101  }
1102  }
1103 }
1104 
1105 static void rz_type_format_word(RzStrBuf *outbuf, int endian, int mode,
1106  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
1107  ut64 addr;
1108  int elem = -1;
1109  if (size >= ARRAYINDEX_COEF) {
1110  elem = size / ARRAYINDEX_COEF - 1;
1111  size %= ARRAYINDEX_COEF;
1112  }
1113  addr = rz_read_ble16(buf + i, endian);
1114  if (MUSTSET) {
1115  rz_strbuf_appendf(outbuf, "wv2 %s @ 0x%08" PFMT64x "\n", setval, seeki + ((elem >= 0) ? elem * 2 : 0));
1116  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
1117  if (size == -1) {
1118  rz_strbuf_appendf(outbuf, "0x%04" PFMT64x, addr);
1119  }
1120  while ((size -= 2) > 0) {
1121  addr = rz_read_ble16(buf + i, endian);
1122  if (elem == -1 || elem == 0) {
1124  if (elem == 0) {
1125  elem = -2;
1126  }
1127  }
1128  if (size != 0 && elem == -1) {
1129  rz_strbuf_append(outbuf, ",");
1130  }
1131  if (elem > -1) {
1132  elem--;
1133  }
1134  i += 2;
1135  }
1136  } else if (MUSTSEE) {
1137  if (!SEEVALUE && !ISQUIET) {
1138  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * 2 : 0));
1139  }
1140  if (size == -1) {
1141  rz_strbuf_appendf(outbuf, "0x%04" PFMT64x, addr);
1142  } else {
1143  if (!SEEVALUE) {
1144  rz_strbuf_append(outbuf, "[ ");
1145  }
1146  while (size--) {
1147  addr = rz_read_ble16(buf + i, endian);
1148  if (elem == -1 || elem == 0) {
1149  rz_strbuf_appendf(outbuf, "0x%04" PFMT64x, addr);
1150  if (elem == 0) {
1151  elem = -2;
1152  }
1153  }
1154  if (size != 0 && elem == -1) {
1155  rz_strbuf_append(outbuf, ", ");
1156  }
1157  if (elem > -1) {
1158  elem--;
1159  }
1160  i += 2;
1161  }
1162  if (!SEEVALUE) {
1163  rz_strbuf_append(outbuf, " ]");
1164  }
1165  }
1166  } else if (MUSTSEEJSON) {
1167  if (size == -1) {
1169  } else {
1170  rz_strbuf_append(outbuf, "[ ");
1171  while ((size -= 2) > 0) {
1172  addr = rz_read_ble16(buf + i, endian);
1173  if (elem == -1 || elem == 0) {
1175  if (elem == 0) {
1176  elem = -2;
1177  }
1178  }
1179  if (size != 0 && elem == -1) {
1180  rz_strbuf_append(outbuf, ",");
1181  }
1182  if (elem > -1) {
1183  elem--;
1184  }
1185  i += 2;
1186  }
1187  rz_strbuf_append(outbuf, " ]");
1188  }
1189  rz_strbuf_append(outbuf, "}");
1190  }
1191 }
1192 
1193 static void rz_type_byte_escape(const RzPrint *p, const char *src, char **dst, int dot_nl) {
1194  rz_return_if_fail(p->strconv_mode);
1195  RzStrEscOptions opt = { 0 };
1196  opt.dot_nl = dot_nl;
1197  opt.show_asciidot = !strcmp(p->strconv_mode, "asciidot");
1198  opt.esc_bslash = p->esc_bslash;
1199  rz_str_byte_escape(src, dst, &opt);
1200 }
1201 
1202 static void rz_type_format_nulltermstring(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, int len, int endian, int mode,
1203  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
1204  if (!typedb->iob.is_valid_offset(typedb->iob.io, seeki, 1)) {
1205  ut8 ch = 0xff;
1206  // XXX there are some cases where the memory is there but is_valid_offset fails
1207  if (typedb->iob.read_at(typedb->iob.io, seeki, &ch, 1) != 1 && ch != 0xff) {
1208  rz_strbuf_append(outbuf, "-1");
1209  return;
1210  }
1211  }
1212  if (p->flags & RZ_PRINT_FLAGS_UNALLOC && !(typedb->iob.io->cached & RZ_PERM_R)) {
1213  ut64 total_map_left = 0;
1214  ut64 addr = seeki;
1215  RzIOMap *map;
1216  while (total_map_left < len && (map = typedb->iob.io->va ? typedb->iob.map_get(typedb->iob.io, addr) : typedb->iob.map_get_paddr(typedb->iob.io, addr)) && map->perm & RZ_PERM_R) {
1217  if (!map->itv.size) {
1218  total_map_left = addr == 0 ? UT64_MAX : UT64_MAX - addr + 1;
1219  break;
1220  }
1221  total_map_left += map->itv.size - (addr - (typedb->iob.io->va ? map->itv.addr : map->delta));
1222  addr += total_map_left;
1223  }
1224  if (total_map_left < len) {
1225  len = total_map_left;
1226  }
1227  }
1228  int str_len = rz_str_nlen((char *)buf + i, len - i);
1229  bool overflow = (size == -1 || size > len - i) && str_len == len - i;
1230  if (MUSTSET) {
1231  int buflen = strlen((const char *)buf + seeki);
1232  int vallen = strlen(setval);
1233  char *ons, *newstring = ons = strdup(setval);
1234  if ((newstring[0] == '\"' && newstring[vallen - 1] == '\"') || (newstring[0] == '\'' && newstring[vallen - 1] == '\'')) {
1235  newstring[vallen - 1] = '\0';
1236  newstring++;
1237  vallen -= 2;
1238  }
1239  if (vallen > buflen) {
1240  eprintf("Warning: new string is longer than previous one\n");
1241  }
1242  rz_strbuf_append(outbuf, "wx ");
1243  for (i = 0; i < vallen; i++) {
1244  if (i < vallen - 3 && newstring[i] == '\\' && newstring[i + 1] == 'x') {
1245  rz_strbuf_appendf(outbuf, "%c%c", newstring[i + 2], newstring[i + 3]);
1246  i += 3;
1247  } else {
1248  rz_strbuf_appendf(outbuf, "%2x", newstring[i]);
1249  }
1250  }
1251  rz_strbuf_appendf(outbuf, " @ 0x%08" PFMT64x "\n", seeki);
1252  free(ons);
1253  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
1254  int j = i;
1256  for (; j < len && ((size == -1 || size-- > 0) && buf[j]); j++) {
1257  char ch = buf[j];
1258  if (ch == '"') {
1259  rz_strbuf_append(outbuf, "\\\"");
1260  } else if (IS_PRINTABLE(ch)) {
1261  rz_strbuf_appendf(outbuf, "%c", ch);
1262  } else {
1263  rz_strbuf_append(outbuf, ".");
1264  }
1265  }
1267  } else if (MUSTSEE) {
1268  int j = i;
1269  if (!SEEVALUE && !ISQUIET) {
1270  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = %s", seeki, overflow ? "ovf " : "");
1271  }
1272  rz_strbuf_append(outbuf, "\"");
1273  for (; j < len && ((size == -1 || size-- > 0) && buf[j]); j++) {
1274  char esc_str[5] = { 0 };
1275  char *ptr = esc_str;
1276  rz_type_byte_escape(p, (char *)&buf[j], &ptr, false);
1277  rz_strbuf_appendf(outbuf, "%s", esc_str);
1278  }
1279  rz_strbuf_append(outbuf, "\"");
1280  } else if (MUSTSEEJSON) {
1281  char *utf_encoded_buf = NULL;
1282  rz_strbuf_append(outbuf, "\"");
1283  utf_encoded_buf = rz_str_escape_utf8_for_json(
1284  (char *)buf + i, size == -1 ? str_len : RZ_MIN(size, str_len));
1285  if (utf_encoded_buf) {
1286  rz_strbuf_appendf(outbuf, "%s", utf_encoded_buf);
1287  free(utf_encoded_buf);
1288  }
1289  rz_strbuf_append(outbuf, "\"");
1290  if (overflow) {
1291  rz_strbuf_append(outbuf, ",\"overflow\":true");
1292  }
1293  rz_strbuf_append(outbuf, "}");
1294  }
1295 }
1296 
1297 static void rz_type_format_nulltermwidestring(RzPrint *p, RzStrBuf *outbuf, const int len, int endian, int mode,
1298  const char *setval, ut64 seeki, ut8 *buf, int i, int size) {
1299  if (MUSTSET) {
1300  int vallen = strlen(setval);
1301  char *newstring, *ons;
1302  newstring = ons = strdup(setval);
1303  if ((newstring[0] == '\"' && newstring[vallen - 1] == '\"') || (newstring[0] == '\'' && newstring[vallen - 1] == '\'')) {
1304  newstring[vallen - 1] = '\0';
1305  newstring++;
1306  vallen -= 2;
1307  }
1308  if (vallen > rz_wstr_clen((char *)(buf + seeki))) {
1309  eprintf("Warning: new string is longer than previous one\n");
1310  }
1311  rz_strbuf_appendf(outbuf, "ww %s @ 0x%08" PFMT64x "\n", newstring, seeki);
1312  free(ons);
1313  } else if (MUSTSEE) {
1314  int j = i;
1315  if (!SEEVALUE && !ISQUIET) {
1316  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
1317  }
1318  for (; j < len && ((size == -1 || size-- > 0) && buf[j]); j += 2) {
1319  if (IS_PRINTABLE(buf[j])) {
1320  rz_strbuf_appendf(outbuf, "%c", buf[j]);
1321  } else {
1322  rz_strbuf_append(outbuf, ".");
1323  }
1324  }
1325  } else if (MUSTSEEJSON) {
1326  int j = i;
1327  rz_strbuf_appendf(outbuf, "%" PFMT64d ",\"string\":\"", seeki);
1328  for (; j < len && ((size == -1 || size-- > 0) && buf[j]); j += 2) {
1329  if (IS_PRINTABLE(buf[j])) {
1330  rz_strbuf_appendf(outbuf, "%c", buf[j]);
1331  } else {
1332  rz_strbuf_append(outbuf, ".");
1333  }
1334  }
1335  rz_strbuf_append(outbuf, "\"}");
1336  }
1337 }
1338 
1339 static void rz_type_format_bitfield(const RzTypeDB *typedb, RzStrBuf *outbuf, ut64 seeki, char *fmtname,
1340  char *fieldname, ut64 addr, int mode, int size) {
1341  char *bitfield = NULL;
1342  addr &= (1ULL << (size * 8)) - 1;
1343  if (MUSTSEE && !SEEVALUE) {
1344  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
1345  }
1346  bitfield = rz_type_db_enum_get_bitfield(typedb, fmtname, addr);
1347  if (bitfield && *bitfield) {
1348  if (MUSTSEEJSON) {
1349  rz_strbuf_appendf(outbuf, "\"%s\"}", bitfield);
1350  } else if (MUSTSEE) {
1351  rz_strbuf_appendf(outbuf, "%s (bitfield) = %s\n", fieldname, bitfield);
1352  }
1353  } else {
1354  if (MUSTSEEJSON) {
1355  rz_strbuf_appendf(outbuf, "\"`tb %s 0x%" PFMT64x "`\"}", fmtname, addr);
1356  } else if (MUSTSEE) {
1357  rz_strbuf_appendf(outbuf, "%s (bitfield) = `tb %s 0x%" PFMT64x "`\n",
1358  fieldname, fmtname, addr);
1359  }
1360  }
1361  free(bitfield);
1362 }
1363 
1364 static void rz_type_format_enum(const RzTypeDB *typedb, RzStrBuf *outbuf, ut64 seeki, char *fmtname,
1365  char *fieldname, ut64 addr, int mode, int size) {
1366  const char *enumvalue = NULL;
1367  addr &= (1ULL << (size * 8)) - 1;
1368  if (MUSTSEE && !SEEVALUE) {
1369  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki);
1370  }
1371  enumvalue = rz_type_db_enum_member_by_val(typedb, fmtname, addr);
1372  if (enumvalue && *enumvalue) {
1373  if (mode & RZ_PRINT_DOT) {
1374  rz_strbuf_appendf(outbuf, "%s.%s", fmtname, enumvalue);
1375  } else if (MUSTSEEJSON) {
1376  rz_strbuf_appendf(outbuf, "%" PFMT64d ",\"label\":\"%s\",\"enum\":\"%s\"}",
1377  addr, enumvalue, fmtname);
1378  } else if (MUSTSEE) {
1379  rz_strbuf_appendf(outbuf, "%s (enum %s) = 0x%" PFMT64x " ; %s\n",
1380  fieldname, fmtname, addr, enumvalue);
1381  } else if (MUSTSEESTRUCT) {
1382  rz_strbuf_appendf(outbuf, "%s", enumvalue);
1383  }
1384  } else {
1385  if (MUSTSEEJSON) {
1386  rz_strbuf_appendf(outbuf, "%" PFMT64d ",\"enum\":\"%s\"}", addr, fmtname);
1387  } else if (MUSTSEE) {
1388  rz_strbuf_appendf(outbuf, "%s (enum %s) = 0x%" PFMT64x "\n", //`te %s 0x%x`\n",
1389  fieldname, fmtname, addr); // enumvalue); //fmtname, addr);
1390  }
1391  }
1392 }
1393 
1395  const char *name, const char *setval) {
1396  if (!p || !p->get_register || !p->reg) {
1397  return;
1398  }
1399  RzRegItem *ri = p->get_register(p->reg, name, RZ_REG_TYPE_ANY);
1400  if (ri) {
1401  if (MUSTSET) {
1402  rz_strbuf_appendf(outbuf, "dr %s=%s\n", name, setval);
1403  } else if (MUSTSEE) {
1404  if (!SEEVALUE) {
1405  rz_strbuf_appendf(outbuf, "%s : 0x%08" PFMT64x "\n", ri->name, p->get_register_value(p->reg, ri));
1406  } else {
1407  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x "\n", p->get_register_value(p->reg, ri));
1408  }
1409  } else if (MUSTSEEJSON) {
1410  rz_strbuf_appendf(outbuf, "%" PFMT64d "}", p->get_register_value(p->reg, ri));
1411  }
1412  } else {
1413  rz_strbuf_appendf(outbuf, "Register %s does not exists\n", name);
1414  }
1415 }
1416 
1418 #define EXT(T) (sign ? (signed T)(addr) : (unsigned T)(addr))
1419  const char *fs64 = sign ? "%" PFMT64d : "%" PFMT64u;
1420  const char *fs = sign ? "%d" : "%u";
1421  if (bytes == 1) {
1422  rz_strbuf_appendf(outbuf, fs, EXT(char));
1423  } else if (bytes == 2) {
1424  rz_strbuf_appendf(outbuf, fs, EXT(short));
1425  } else if (bytes == 4) {
1426  rz_strbuf_appendf(outbuf, fs, EXT(int)); // XXX: int is not necessarily 4 bytes I guess.
1427  } else if (bytes == 8) {
1428  rz_strbuf_appendf(outbuf, fs64, addr);
1429  }
1430 #undef EXT
1431 }
1432 
1433 static void rz_type_format_num(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int bytes, int sign, int size) {
1434  ut64 addr = 0LL;
1435  int elem = -1;
1436  if (size >= ARRAYINDEX_COEF) {
1437  elem = size / ARRAYINDEX_COEF - 1;
1438  size %= ARRAYINDEX_COEF;
1439  }
1440  if (bytes == 8) {
1441  updateAddr(buf + i, size - i, endian, NULL, &addr);
1442  } else {
1443  updateAddr(buf + i, size - i, endian, &addr, NULL);
1444  }
1445  if (MUSTSET) {
1446  rz_strbuf_appendf(outbuf, "wv%d %s @ 0x%08" PFMT64x "\n", bytes, setval, seeki + ((elem >= 0) ? elem * (bytes) : 0));
1447  } else if ((mode & RZ_PRINT_DOT) || MUSTSEESTRUCT) {
1449  } else if (MUSTSEE) {
1450  if (!SEEVALUE && !ISQUIET) {
1451  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " = ", seeki + ((elem >= 0) ? elem * bytes : 0));
1452  }
1453  if (size == -1) {
1455  } else {
1456  if (!SEEVALUE) {
1457  rz_strbuf_append(outbuf, "[ ");
1458  }
1459  while (size--) {
1460  if (bytes == 8) {
1461  updateAddr(buf + i, size - i, endian, NULL, &addr);
1462  } else {
1463  updateAddr(buf + i, size - i, endian, &addr, NULL);
1464  }
1465  if (elem == -1 || elem == 0) {
1467  if (elem == 0) {
1468  elem = -2;
1469  }
1470  }
1471  if (size != 0 && elem == -1) {
1472  rz_strbuf_append(outbuf, ", ");
1473  }
1474  if (elem > -1) {
1475  elem--;
1476  }
1477  i += bytes;
1478  }
1479  if (!SEEVALUE) {
1480  rz_strbuf_append(outbuf, " ]");
1481  }
1482  }
1483  } else if (MUSTSEEJSON) {
1484  if (size == -1) {
1486  } else {
1487  rz_strbuf_append(outbuf, "[ ");
1488  while (size--) {
1489  if (bytes == 8) {
1490  updateAddr(buf + i, size, endian, NULL, &addr);
1491  } else {
1492  updateAddr(buf + i, size, endian, &addr, NULL);
1493  }
1494  if (elem == -1 || elem == 0) {
1496  if (elem == 0) {
1497  elem = -2;
1498  }
1499  }
1500  if (size != 0 && elem == -1) {
1501  rz_strbuf_append(outbuf, ", ");
1502  }
1503  if (elem > -1) {
1504  elem--;
1505  }
1506  i += bytes;
1507  }
1508  rz_strbuf_append(outbuf, " ]");
1509  }
1510  rz_strbuf_append(outbuf, "}");
1511  }
1512 }
1513 
1514 // XXX: this is somewhat incomplete. must be updated to handle all format chars
1515 RZ_API int rz_type_format_struct_size(const RzTypeDB *typedb, const char *f, int mode, int n) {
1516  char *end, *args, *fmt;
1517  int size = 0, tabsize = 0, i, idx = 0, biggest = 0, fmt_len = 0, times = 1;
1518  bool tabsize_set = false;
1519  if (!f) {
1520  return -1;
1521  }
1522  if (n >= 5) { // This is the nesting level, is this not a bit arbitrary?!
1523  return 0;
1524  }
1525  const char *fmt2 = rz_type_db_format_get(typedb, f);
1526  if (!fmt2) {
1527  fmt2 = f;
1528  }
1529  char *o = strdup(fmt2);
1530  if (!o) {
1531  return -1;
1532  }
1533  end = strchr(o, ' ');
1534  fmt = o;
1535  if (!end && !(end = strchr(o, '\0'))) {
1536  free(o);
1537  return -1;
1538  }
1539  if (*end) {
1540  *end = 0;
1541  args = strdup(end + 1);
1542  } else {
1543  args = strdup("");
1544  }
1545 
1546  if (fmt[0] == '{') {
1547  char *end = strchr(fmt + 1, '}');
1548  if (!end) {
1549  RZ_LOG_ERROR("No end curly bracket.\n");
1550  free(o);
1551  free(args);
1552  return -1;
1553  }
1554  *end = '\0';
1555  times = rz_num_math(NULL, fmt + 1);
1556  fmt = end + 1;
1557  }
1558  if (fmt[0] == '0') {
1559  mode |= RZ_PRINT_UNIONMODE;
1560  fmt++;
1561  } else {
1562  mode &= ~RZ_PRINT_UNIONMODE;
1563  }
1564 
1565  int words = rz_str_word_set0_stack(args);
1566  fmt_len = strlen(fmt);
1567  for (i = 0; i < fmt_len; i++) {
1568  if (fmt[i] == '[') {
1569  char *end = strchr(fmt + i, ']');
1570  if (!end) {
1571  RZ_LOG_ERROR("No end bracket.\n");
1572  continue;
1573  }
1574  *end = '\0';
1575  tabsize_set = true;
1576  tabsize = rz_num_math(NULL, fmt + i + 1);
1577  *end = ']';
1578  while (fmt[i++] != ']') {
1579  ;
1580  }
1581  } else {
1582  tabsize = 1;
1583  }
1584 
1585  switch (fmt[i]) {
1586  case '.':
1587  idx--;
1588  // fallthrough
1589  case 'c':
1590  case 'b':
1591  case 'X':
1592  size += tabsize * 1;
1593  break;
1594  case 'w':
1595  size += tabsize * 2;
1596  break;
1597  case ':':
1598  idx--;
1599  // fallthrough
1600  case 'd':
1601  case 'o':
1602  case 'i':
1603  case 'x':
1604  case 'f':
1605  case 's':
1606  case 't':
1607  size += tabsize * 4;
1608  break;
1609  case 'S':
1610  case 'q':
1611  case 'F':
1612  size += tabsize * 8;
1613  break;
1614  case 'Q': // uint128
1615  size += tabsize * 16;
1616  break;
1617  case 'z':
1618  case 'Z':
1619  size += tabsize;
1620  break;
1621  case '*':
1622  size += tabsize * (typedb->target->bits / 8);
1623  i++;
1624  idx--; // no need to go ahead for args
1625  break;
1626  case 'B':
1627  case 'E':
1628  if (tabsize_set) {
1629  if (tabsize < 1 || tabsize > 8) {
1630  RZ_LOG_ERROR("Unknown enum format size: %d\n", tabsize);
1631  break;
1632  }
1633  size += tabsize;
1634  } else {
1635  size += 4; // Assuming by default enum as int
1636  }
1637  break;
1638  case '?': {
1639  const char *wordAtIndex = NULL;
1640  const char *format = NULL;
1641  char *endname = NULL, *structname = NULL;
1642  char tmp = 0;
1643  if (words < idx) {
1644  RZ_LOG_ERROR("Index out of bounds\n");
1645  } else {
1646  wordAtIndex = rz_str_word_get0(args, idx);
1647  }
1648  if (!wordAtIndex) {
1649  break;
1650  }
1651  structname = strdup(wordAtIndex);
1652  if (*structname == '(') {
1653  endname = (char *)rz_str_rchr(structname, NULL, ')');
1654  } else {
1655  free(structname);
1656  break;
1657  }
1658  if (endname) {
1659  *endname = '\0';
1660  }
1661  format = strchr(structname, ' ');
1662  if (format) {
1663  tmp = *format;
1664  while (tmp == ' ') {
1665  format++;
1666  tmp = *format;
1667  }
1668  } else {
1669  format = rz_type_db_format_get(typedb, structname + 1);
1670  if (format && !strncmp(format, f, strlen(format) - 1)) { // Avoid recursion here
1671  free(o);
1672  free(structname);
1673  return -1;
1674  }
1675  if (!format) { // Fetch format from types db
1676  format = rz_type_format(typedb, structname + 1);
1677  }
1678  }
1679  if (!format) {
1680  RZ_LOG_ERROR("Cannot find format for struct `%s'\n", structname + 1);
1681  free(structname);
1682  free(o);
1683  return 0;
1684  }
1685  int newsize = rz_type_format_struct_size(typedb, format, mode, n + 1);
1686  if (newsize < 1) {
1687  RZ_LOG_ERROR("Cannot find size for `%s'\n", format);
1688  free(structname);
1689  free(o);
1690  return 0;
1691  }
1692  if (format) {
1693  size += tabsize * newsize;
1694  }
1695  free(structname);
1696  } break;
1697  case '{':
1698  while (fmt[i] != '}') {
1699  if (!fmt[i]) {
1700  free(o);
1701  free(args);
1702  return -1;
1703  }
1704  i++;
1705  }
1706  i++;
1707  idx--;
1708  break;
1709  case '}':
1710  free(o);
1711  free(args);
1712  return -1;
1713  case '+':
1714  case 'e':
1715  idx--;
1716  break;
1717  case 'p':
1718  if (fmt[i + 1] == '2') {
1719  size += tabsize * 2;
1720  } else if (fmt[i + 1] == '4') {
1721  size += tabsize * 4;
1722  } else if (fmt[i + 1] == '8') {
1723  size += tabsize * 8;
1724  } else {
1725  size += tabsize * (typedb->target->bits / 8);
1726  break;
1727  }
1728  i++;
1729  break;
1730  case 'r':
1731  break;
1732  case 'n':
1733  case 'N':
1734  if (fmt[i + 1] == '1') {
1735  size += tabsize * 1;
1736  } else if (fmt[i + 1] == '2') {
1737  size += tabsize * 2;
1738  } else if (fmt[i + 1] == '4') {
1739  size += tabsize * 4;
1740  } else if (fmt[i + 1] == '8') {
1741  size += tabsize * 8;
1742  } else {
1743  RZ_LOG_ERROR("Invalid '%c' format in (%s)\n", fmt[i + 1], fmt);
1744  free(o);
1745  free(args);
1746  return -2;
1747  }
1748  i++;
1749  break;
1750  case 'u':
1751  case 'D':
1752  case 'T':
1753  // TODO complete this.
1754  default:
1755  // idx--; //Does this makes sense?
1756  break;
1757  }
1758  idx++;
1759  if (mode & RZ_PRINT_UNIONMODE) {
1760  if (size > biggest) {
1761  biggest = size;
1762  }
1763  size = 0;
1764  }
1765  }
1766  size *= times;
1767  free(o);
1768  free(args);
1769  return (mode & RZ_PRINT_UNIONMODE) ? biggest : size;
1770 }
1771 
1772 static int rz_type_format_data_internal(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, ut64 seek, const ut8 *b, const int len,
1773  const char *formatname, int mode, const char *setval, char *ofield);
1774 
1775 static int rz_type_format_struct(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, ut64 seek, const ut8 *b, int len, const char *name,
1776  int slide, int mode, const char *setval, char *field, int anon) {
1777  char *fmt;
1778  int ret = 0;
1779  char namefmt[128];
1780  slide++;
1781  if ((slide % STRUCTPTR) > NESTDEPTH || (slide % STRUCTFLAG) / STRUCTPTR > NESTDEPTH) {
1782  eprintf("Too much nested struct, recursion too deep...\n");
1783  return 0;
1784  }
1785  if (anon) {
1786  fmt = strdup(name);
1787  } else {
1788  const char *dbfmt = rz_type_db_format_get(typedb, name);
1789  if (!dbfmt) { // Fetch struct info from types DB
1790  fmt = rz_type_format(typedb, name);
1791  } else {
1792  fmt = strdup(dbfmt);
1793  }
1794  }
1795  if (RZ_STR_ISEMPTY(fmt)) {
1796  eprintf("Undefined struct '%s'.\n", name);
1797  goto beach;
1798  }
1799  if (MUSTSEE && !SEEVALUE) {
1800  snprintf(namefmt, sizeof(namefmt), "%%%ds", 10 + 6 * slide % STRUCTPTR);
1801  if (fmt[0] == '0') {
1802  rz_strbuf_appendf(outbuf, namefmt, "union");
1803  } else {
1804  rz_strbuf_appendf(outbuf, namefmt, "struct");
1805  }
1806  rz_strbuf_appendf(outbuf, "<%s>\n", name);
1807  }
1808  rz_type_format_data_internal(typedb, p, outbuf, seek, b, len, fmt, mode, setval, field);
1809  ret = rz_type_format_struct_size(typedb, fmt, mode, 0);
1810 
1811 beach:
1812  free(fmt);
1813  return ret;
1814 }
1815 
1816 static char *get_args_offset(const char *arg) {
1817  char *args = strchr(arg, ' ');
1818  char *sq_bracket = strchr(arg, '[');
1819  int max = 30;
1820  if (args && sq_bracket) {
1821  char *csq_bracket = strchr(arg, ']');
1822  while (args && csq_bracket && csq_bracket > args && max--) {
1823  args = strchr(csq_bracket, ' ');
1824  }
1825  }
1826  return args;
1827 }
1828 
1829 static char *get_format_type(const char fmt, const char arg) {
1830  char *type = NULL;
1831  switch (fmt) {
1832  case 'b':
1833  case 'C':
1834  type = strdup("uint8_t");
1835  break;
1836  case 'c':
1837  type = strdup("int8_t");
1838  break;
1839  case 'd':
1840  case 'i':
1841  case 'o':
1842  case 'x':
1843  type = strdup("int32_t");
1844  break;
1845  case 'E':
1846  type = strdup("enum");
1847  break;
1848  case 'f':
1849  type = strdup("float");
1850  break;
1851  case 'F':
1852  type = strdup("double");
1853  break;
1854  case 'q':
1855  type = strdup("uint64_t");
1856  break;
1857  case 'u':
1858  type = strdup("uleb128_t");
1859  break;
1860  case 'Q':
1861  type = strdup("uint128_t");
1862  break;
1863  case 'w':
1864  type = strdup("uint16_t");
1865  break;
1866  case 'X':
1867  type = strdup("uint8_t[]");
1868  break;
1869  case 'D':
1870  case 's':
1871  case 'S':
1872  case 't':
1873  case 'z':
1874  case 'Z':
1875  type = strdup("char*");
1876  break;
1877  case 'n':
1878  case 'N':
1879  switch (arg) {
1880  case '1':
1881  type = strdup(fmt == 'n' ? "int8_t" : "uint8_t");
1882  break;
1883  case '2':
1884  type = strdup(fmt == 'n' ? "int16_t" : "uint16_t");
1885  break;
1886  case '4':
1887  type = strdup(fmt == 'n' ? "int32_t" : "uint32_t");
1888  break;
1889  case '8':
1890  type = strdup(fmt == 'n' ? "int64_t" : "uint64_t");
1891  break;
1892  }
1893  break;
1894  }
1895  return type;
1896 }
1897 
1898 #define MINUSONE ((void *)(size_t)-1)
1899 #define ISSTRUCT (tmp == '?' || (tmp == '*' && *(arg + 1) == '?'))
1900 
1901 RZ_API const char *rz_type_db_format_get(const RzTypeDB *typedb, const char *name) {
1902  rz_return_val_if_fail(typedb && name, NULL);
1903  bool found = false;
1904  const char *result = ht_pp_find(typedb->formats, name, &found);
1905  if (!found || !result) {
1906  // eprintf("Cannot find format \"%s\"\n", name);
1907  return NULL;
1908  }
1909  return result;
1910 }
1911 
1912 RZ_API void rz_type_db_format_set(RzTypeDB *typedb, const char *name, const char *fmt) {
1913  rz_return_if_fail(typedb && name && fmt);
1914  ht_pp_insert(typedb->formats, name, strdup(fmt));
1915 }
1916 
1917 static bool format_collect_cb(void *user, const void *k, const void *v) {
1918  rz_return_val_if_fail(user && k && v, false);
1919  RzList *l = user;
1920  char *fmt = rz_str_newf("%s %s", (const char *)k, (const char *)v);
1921  rz_list_append(l, fmt);
1922  return true;
1923 }
1924 
1926  rz_return_val_if_fail(typedb, NULL);
1928  ht_pp_foreach(typedb->formats, format_collect_cb, formats);
1929  return formats;
1930 }
1931 
1932 RZ_API void rz_type_db_format_delete(RzTypeDB *typedb, const char *name) {
1933  rz_return_if_fail(typedb && name);
1934  ht_pp_delete(typedb->formats, name);
1935 }
1936 
1937 static int rz_type_format_data_internal(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, ut64 seek, const ut8 *b, const int len,
1938  const char *formatname, int mode, const char *setval, char *ofield) {
1939  int nargs, i, invalid, nexti, idx, times, otimes, endian, isptr = 0;
1940  const int old_bits = typedb->target->bits;
1941  char *args = NULL, *bracket, tmp, last = 0;
1942  ut64 addr = 0, addr64 = 0, seeki = 0;
1943  static int slide = 0, oldslide = 0, ident = 4;
1944  char namefmt[32], *field = NULL;
1945  const char *arg = NULL;
1946  const char *fmt = NULL;
1947  const char *argend;
1948  int viewflags = 0;
1949  char *oarg = NULL;
1950  char *internal_format = NULL;
1951 
1952  /* Load format from name into fmt */
1953  if (!formatname) {
1954  return 0;
1955  }
1956  fmt = rz_type_db_format_get(typedb, formatname);
1957  if (!fmt) {
1958  fmt = formatname;
1959  }
1960  internal_format = strdup(fmt);
1961  fmt = internal_format;
1962  while (*fmt && IS_WHITECHAR(*fmt)) {
1963  fmt++;
1964  }
1965  argend = fmt + strlen(fmt);
1966  arg = fmt;
1967 
1968  nexti = nargs = i = 0;
1969 
1970  if (len < 1) {
1971  free(internal_format);
1972  return 0;
1973  }
1974 
1975  // len+2 to save space for the null termination in wide strings
1976  ut8 *buf = calloc(1, len + 2);
1977  if (!buf) {
1978  free(internal_format);
1979  return 0;
1980  }
1981  memcpy(buf, b, len);
1982  endian = typedb->target->big_endian;
1983 
1984  if (ofield && ofield != MINUSONE) {
1985  field = strdup(ofield);
1986  }
1987  /* get times */
1988  otimes = times = atoi(arg);
1989  if (times > 0) {
1990  while (IS_DIGIT(*arg)) {
1991  arg++;
1992  }
1993  }
1994 
1995  bracket = strchr(arg, '{');
1996  if (bracket) {
1997  char *end = strchr(arg, '}');
1998  if (!end) {
1999  eprintf("No end bracket. Try pf {ecx}b @ esi\n");
2000  goto beach;
2001  }
2002  *end = '\0';
2003  times = rz_num_math(NULL, bracket + 1);
2004  arg = end + 1;
2005  }
2006 
2007  if (*arg == '\0') {
2008  goto beach;
2009  }
2010 
2011  /* get args */
2013  if (args) {
2014  int l = 0, maxl = 0;
2015  argend = args;
2016  tmp = *args;
2017  while (tmp == ' ') {
2018  args++;
2019  tmp = *args;
2020  }
2021  args = strdup(args);
2023  if (nargs == 0) {
2024  RZ_FREE(args);
2025  }
2026  for (i = 0; i < nargs; i++) {
2027  const char *tmp = rz_str_word_get0(args, i);
2028  const char *nm = rz_str_rchr(tmp, NULL, ')');
2029  int len = strlen(nm ? nm + 1 : tmp);
2030  if (len > maxl) {
2031  maxl = len;
2032  }
2033  }
2034  l++;
2035  const char *ends = " "; // XXX trailing space warning
2036  snprintf(namefmt, sizeof(namefmt), "%%%ds :%s",
2037  ((maxl + 1) * (1 + slide)) % STRUCTPTR, ends);
2038  }
2039 #define ISPOINTED ((slide % STRUCTFLAG) / STRUCTPTR <= (oldslide % STRUCTFLAG) / STRUCTPTR)
2040 #define ISNESTED ((slide % STRUCTPTR) <= (oldslide % STRUCTPTR))
2041  if (mode == RZ_PRINT_JSON && slide == 0) {
2042  rz_strbuf_append(outbuf, "[");
2043  }
2044  if (mode == RZ_PRINT_STRUCT) {
2045  if (formatname && *formatname) {
2046  if (strchr(formatname, ' ')) {
2047  rz_strbuf_append(outbuf, "struct {\n");
2048  } else {
2049  rz_strbuf_appendf(outbuf, "struct %s {\n", formatname);
2050  }
2051  } else {
2052  rz_strbuf_append(outbuf, "struct {\n");
2053  }
2054  }
2055  if (mode && arg[0] == '0') {
2056  mode |= RZ_PRINT_UNIONMODE;
2057  arg++;
2058  } else {
2059  mode &= ~RZ_PRINT_UNIONMODE;
2060  }
2061  if (mode & RZ_PRINT_DOT) {
2062  char *fmtname;
2063  if (formatname && *formatname) {
2064  if (strchr(formatname, ' ')) {
2065  fmtname = rz_str_newf("0x%" PFMT64x, seek);
2066  } else {
2067  fmtname = strdup(formatname);
2068  }
2069  } else {
2070  fmtname = rz_str_newf("0x%" PFMT64x, seek);
2071  }
2072  rz_strbuf_append(outbuf, "digraph g { graph [ rank=same; rankdir=LR; ];\n");
2073  rz_strbuf_appendf(outbuf, "root [ rank=1; shape=record\nlabel=\"%s", fmtname);
2074  }
2075 
2076  /* go format */
2077  i = 0;
2078  if (!times) {
2079  otimes = times = 1;
2080  }
2081  for (; times; times--) { // repeat N times
2082  const char *orig = arg;
2083  int first = 1;
2084  if (otimes > 1) {
2085  if (mode & RZ_PRINT_JSON) {
2086  if (otimes > times) {
2087  rz_strbuf_append(outbuf, ",");
2088  }
2089  rz_strbuf_appendf(outbuf, "[{\"index\":%d,\"offset\":%" PFMT64d "},", otimes - times, seek + i);
2090  } else if (mode) {
2091  rz_strbuf_appendf(outbuf, "0x%08" PFMT64x " [%d] {\n", seek + i, otimes - times);
2092  }
2093  }
2094  arg = orig;
2095  for (idx = 0; i < len && arg < argend && *arg; arg++) {
2096  int size = 0, elem = 0; /* size of the array, element of the array */
2097  char *fieldname = NULL, *fmtname = NULL;
2098  if (mode & RZ_PRINT_UNIONMODE) {
2099  i = 0;
2100  }
2101  seeki = seek + i;
2102  addr = 0LL;
2103  invalid = 0;
2104  typedb->target->bits = old_bits;
2105  if (arg[0] == '[') {
2106  char *end = strchr(arg, ']');
2107  if (!end) {
2108  eprintf("No end bracket.\n");
2109  goto beach;
2110  }
2111  *end = '\0';
2112  size = rz_get_size(typedb->num, buf, endian, arg + 1);
2113  arg = end + 1;
2114  *end = ']';
2115  } else {
2116  size = -1;
2117  }
2118  int fs = rz_type_format_struct_size(typedb, arg, 0, idx);
2119  if (fs == -2) {
2120  i = -1;
2121  goto beach;
2122  }
2123  if (fs < 1) {
2124  fs = 4;
2125  }
2126  if (i + fs - 1 < len) { // should be +7 to avoid oobread on 'q'
2127  // Max byte number where updateAddr will look into
2128  if (len - i < 7) {
2129  updateAddr(buf + i, THRESHOLD - (len - i), endian, &addr, &addr64);
2130  } else {
2131  updateAddr(buf + i, len - i, endian, &addr, &addr64);
2132  }
2133  if (typedb->target->bits == 64) {
2134  addr = addr64;
2135  }
2136  } else {
2137  // eprintf ("Format strings is too big for this buffer\n");
2138  goto beach;
2139  }
2140 
2141  tmp = *arg;
2142 
2143  if (mode && !args) {
2144  mode |= RZ_PRINT_ISFIELD;
2145  }
2146  if (!(mode & RZ_PRINT_QUIET)) {
2147  if (mode & RZ_PRINT_MUSTSEE && otimes > 1) {
2148  rz_strbuf_append(outbuf, " ");
2149  }
2150  }
2151  if (idx < nargs && tmp != 'e' && isptr == 0) {
2152  char *dot = NULL, *bracket = NULL;
2153  if (field) {
2154  dot = strchr(field, '.');
2155  }
2156  if (dot) {
2157  *dot = '\0';
2158  }
2159  free(oarg);
2160  oarg = fieldname = strdup(rz_str_word_get0(args, idx));
2161  if (ISSTRUCT || tmp == 'E' || tmp == 'B' || tmp == 'r') {
2162  if (*fieldname == '(') {
2163  fmtname = fieldname + 1;
2164  fieldname = (char *)rz_str_rchr(fieldname, NULL, ')');
2165  if (fieldname) {
2166  *fieldname++ = '\0';
2167  } else {
2168  eprintf("Missing closing parenthesis in format ')'\n");
2169  goto beach;
2170  }
2171  } else {
2172  eprintf("Missing name (%s)\n", fieldname);
2173  goto beach;
2174  }
2175  }
2176  if (mode && (!args || (!field && ofield != MINUSONE) || (field && !strncmp(field, fieldname, strchr(field, '[') ? strchr(field, '[') - field : strlen(field) + 1)))) {
2177  mode |= RZ_PRINT_ISFIELD;
2178  } else {
2179  mode &= ~RZ_PRINT_ISFIELD;
2180  }
2181 
2182  /* There we handle specific element in array */
2183  if (field && (bracket = strchr(field, '[')) && mode & RZ_PRINT_ISFIELD) {
2184  char *end = strchr(field, ']');
2185  if (!end) {
2186  eprintf("Missing closing bracket\n");
2187  goto beach;
2188  }
2189  *end = '\0';
2190  elem = rz_num_math(NULL, bracket + 1) + 1; // +1 to handle 0 index easily
2191  for (; bracket < end; bracket++) {
2192  *bracket = '\0';
2193  }
2194  size += elem * ARRAYINDEX_COEF;
2195  } else {
2196  elem = -1;
2197  }
2198  if (tmp != '.' && tmp != ':') {
2199  idx++;
2200  if (MUSTSEE && !SEEVALUE) {
2201  if (!ISQUIET) {
2202  rz_strbuf_appendf(outbuf, namefmt, fieldname);
2203  }
2204  }
2205  }
2206  }
2207  feed_me_again:
2208  switch (isptr) {
2209  case PTRSEEK: {
2210  nexti = i + (typedb->target->bits / 8);
2211  i = 0;
2212  if (tmp == '?') {
2213  seeki = addr;
2214  }
2215  memset(buf, '\0', len);
2216  if (MUSTSEE && !ISQUIET) {
2217  rz_strbuf_appendf(outbuf, "(*0x%" PFMT64x ")", addr);
2218  }
2219  isptr = (addr) ? PTRBACK : NULLPTR;
2220  typedb->iob.read_at(typedb->iob.io, (ut64)addr, buf, len - 4);
2221  if (((i + 3) < len) || ((i + 7) < len)) {
2222  // XXX this breaks pf *D
2223  if (tmp != 'D') {
2224  updateAddr(buf + i, len - i, endian, &addr, &addr64);
2225  }
2226  } else {
2227  eprintf("(cannot read at 0x%08" PFMT64x ", block: %s, blocksize: 0x%x)\n",
2228  addr, b, len);
2229  rz_strbuf_append(outbuf, "\n");
2230  goto beach;
2231  }
2232  } break;
2233  case PTRBACK:
2234  // restore state after pointer seek
2235  i = nexti;
2236  memcpy(buf, b, len);
2237  isptr = NOPTR;
2238  arg--;
2239  continue;
2240  }
2241  if (tmp == 0 && last != '*') {
2242  break;
2243  }
2244 
2245  /* skip chars */
2246  switch (tmp) {
2247  case '*': // next char is a pointer
2248  isptr = PTRSEEK;
2249  arg++;
2250  tmp = *arg; // last;
2251  goto feed_me_again;
2252  case '+': // toggle view flags
2253  viewflags = !viewflags;
2254  continue;
2255  case 'e': // tmp swap endian
2256  endian ^= 1;
2257  continue;
2258  case ':': // skip 4 bytes
2259  if (size == -1) {
2260  i += 4;
2261  } else {
2262  while (size--) {
2263  i += 4;
2264  }
2265  }
2266  continue;
2267  case '.': // skip 1 byte
2268  i += (size == -1) ? 1 : size;
2269  continue;
2270  case 'p': // pointer reference
2271  if (*(arg + 1) == '2') {
2272  tmp = 'w';
2273  arg++;
2274  } else if (*(arg + 1) == '4') {
2275  tmp = 'x';
2276  arg++;
2277  } else if (*(arg + 1) == '8') {
2278  tmp = 'q';
2279  arg++;
2280  } else { // If pointer reference is not mentioned explicitly
2281  switch (typedb->target->bits) {
2282  case 16: tmp = 'w'; break;
2283  case 32: tmp = 'x'; break;
2284  default: tmp = 'q'; break;
2285  }
2286  }
2287  break;
2288  }
2289 
2290  /* flags */
2291  if (mode & RZ_PRINT_SEEFLAGS && isptr != NULLPTR) {
2292  char *newname = NULL;
2293  if (!fieldname) {
2294  newname = fieldname = rz_str_newf("pf.%" PFMT64u, seeki);
2295  }
2296  if (mode & RZ_PRINT_UNIONMODE) {
2297  rz_strbuf_appendf(outbuf, "f %s @ 0x%08" PFMT64x "\n", formatname, seeki);
2298  free(newname);
2299  goto beach;
2300  } else if (tmp == '?') {
2301  rz_strbuf_appendf(outbuf, "f %s.%s_", fmtname, fieldname);
2302  } else if (tmp == 'E') {
2303  rz_strbuf_appendf(outbuf, "f %s @ 0x%08" PFMT64x "\n", fieldname, seeki);
2304  } else if (slide / STRUCTFLAG > 0 && idx == 1) {
2305  rz_strbuf_appendf(outbuf, "%s @ 0x%08" PFMT64x "\n", fieldname, seeki);
2306  } else {
2307  rz_strbuf_appendf(outbuf, "f %s @ 0x%08" PFMT64x "\n", fieldname, seeki);
2308  }
2309  if (newname) {
2310  RZ_FREE(newname);
2311  fieldname = NULL;
2312  }
2313  }
2314 
2315  /* dot */
2316  if (mode & RZ_PRINT_DOT) {
2317  if (fieldname) {
2318  rz_strbuf_appendf(outbuf, "|{0x%" PFMT64x "|%c|%s|<%s>",
2319  seeki, tmp, fieldname, fieldname);
2320  } else {
2321  rz_strbuf_appendf(outbuf, "|{0x%" PFMT64x "|%c|",
2322  seeki, tmp);
2323  }
2324  }
2325 
2326  /* json */
2327  if (MUSTSEEJSON && mode & RZ_PRINT_JSON) {
2328  if (oldslide <= slide) {
2329  if (first) {
2330  first = 0;
2331  } else {
2332  rz_strbuf_append(outbuf, ",");
2333  }
2334  } else if (oldslide) {
2335  rz_strbuf_append(outbuf, "]},");
2336  oldslide -= NESTEDSTRUCT;
2337  }
2338  if (fieldname) {
2339  rz_strbuf_appendf(outbuf, "{\"name\":\"%s\",\"type\":\"", fieldname);
2340  } else {
2341  rz_strbuf_append(outbuf, "{\"type\":\"");
2342  }
2343  if (ISSTRUCT) {
2344  rz_strbuf_appendf(outbuf, "%s", fmtname);
2345  } else {
2346  if (tmp == 'n' || tmp == 'N') {
2347  rz_strbuf_appendf(outbuf, "%c%c", tmp, *(arg + 1));
2348  } else {
2349  rz_strbuf_appendf(outbuf, "%c", tmp);
2350  }
2351  }
2352  if (isptr) {
2353  rz_strbuf_append(outbuf, "*");
2354  }
2355  rz_strbuf_appendf(outbuf, "\",\"offset\":%" PFMT64d ",\"value\":",
2356  isptr ? (seek + nexti - (typedb->target->bits / 8)) : seek + i);
2357  }
2358 
2359  /* c struct */
2360  if (MUSTSEESTRUCT) {
2361  char *type = get_format_type(tmp, (tmp == 'n' || tmp == 'N') ? arg[1] : 0);
2362  if (type) {
2363  rz_strbuf_appendf(outbuf, "%*c%s %s; // ", ident, ' ', type, fieldname);
2364  } else {
2365  rz_strbuf_appendf(outbuf, "%*cstruct %s {", ident, ' ', fieldname);
2366  }
2367  free(type);
2368  }
2369  bool noline = false;
2370 
2371  int oi = i;
2372  if (isptr == NULLPTR) {
2373  if (MUSTSEEJSON) {
2374  rz_strbuf_append(outbuf, "\"NULL\"}");
2375  } else if (MUSTSEE) {
2376  rz_strbuf_append(outbuf, " NULL\n");
2377  }
2378  isptr = PTRBACK;
2379  } else {
2380  /* format chars */
2381  // before to enter in the switch statement check buf boundaries due to updateAddr
2382  // might go beyond its len and it's usually called in each of the following functions
2383  switch (tmp) {
2384  case 'u':
2385  i += rz_type_format_uleb(outbuf, endian, mode, setval, seeki, buf, i, size);
2386  break;
2387  case 't':
2388  rz_type_format_time(outbuf, endian, mode, setval, seeki, buf, i, size);
2389  i += (size == -1) ? 4 : 4 * size;
2390  break;
2391  case 'q':
2392  rz_type_format_quadword(outbuf, endian, mode, setval, seeki, buf, i, size);
2393  i += (size == -1) ? 8 : 8 * size;
2394  break;
2395  case 'Q':
2396  rz_type_format_u128(outbuf, endian, mode, setval, seeki, buf, i, size);
2397  i += (size == -1) ? 16 : 16 * size;
2398  break;
2399  case 'b':
2400  rz_type_format_byte(outbuf, endian, mode, setval, seeki, buf, i, size);
2401  i += (size == -1) ? 1 : size;
2402  break;
2403  case 'C':
2404  rz_type_format_decchar(outbuf, endian, mode, setval, seeki, buf, i, size);
2405  i += (size == -1) ? 1 : size;
2406  break;
2407  case 'c':
2408  rz_type_format_char(outbuf, endian, mode, setval, seeki, buf, i, size);
2409  i += (size == -1) ? 1 : size;
2410  break;
2411  case 'X':
2412  size = rz_type_format_hexpairs(outbuf, endian, mode, setval, seeki, buf, i, size);
2413  i += size;
2414  break;
2415  case 'T':
2416  if (rz_type_format_10bytes(typedb, outbuf, mode,
2417  setval, seeki, addr, buf) == 0) {
2418  i += (size == -1) ? 4 : 4 * size;
2419  }
2420  break;
2421  case 'f':
2422  rz_type_format_float(outbuf, endian, mode, setval, seeki, buf, i, size);
2423  i += (size == -1) ? 4 : 4 * size;
2424  break;
2425  case 'F':
2426  rz_type_format_double(outbuf, endian, mode, setval, seeki, buf, i, size);
2427  i += (size == -1) ? 8 : 8 * size;
2428  break;
2429  case 'i':
2430  rz_type_format_int(outbuf, endian, mode, setval, seeki, buf, i, size);
2431  i += (size == -1) ? 4 : 4 * size;
2432  break;
2433  case 'd': // WHY?? help says: 0x%%08x hexadecimal value (4 bytes)
2434  rz_type_format_hex(outbuf, endian, mode, setval, seeki, buf, i, size);
2435  i += (size == -1) ? 4 : 4 * size;
2436  break;
2437  /*
2438  case 'D':
2439  if (isptr) {
2440  if (typedb->target->bits == 64) {
2441  i += rz_print_format_disasm(p, addr64, size);
2442  } else {
2443  i += rz_print_format_disasm(p, addr, size);
2444  }
2445  } else {
2446  i += rz_print_format_disasm(p, seeki, size);
2447  }
2448  break;
2449  */
2450  case 'o':
2451  rz_type_format_octal(outbuf, endian, mode, setval, seeki, buf, i, size);
2452  i += (size == -1) ? 4 : 4 * size;
2453  break;
2454  case ';':
2455  noline = true;
2456  i -= (size == -1) ? 4 : 4 * size;
2457  if (i < 0) {
2458  i = 0;
2459  }
2460  break;
2461  case ',':
2462  noline = true;
2463  i -= (size == -1) ? 1 : size;
2464  if (i < 0) {
2465  i = 0;
2466  }
2467  break;
2468  case 'x':
2469  rz_type_format_hexflag(outbuf, endian, mode, setval, seeki, buf, i, size);
2470  i += (size == -1) ? 4 : 4 * size;
2471  break;
2472  case 'w':
2473  rz_type_format_word(outbuf, endian, mode, setval, seeki, buf, i, size);
2474  i += (size == -1) ? 2 : 2 * size;
2475  break;
2476  case 'z': // zero terminated string
2477  rz_type_format_nulltermstring(typedb, p, outbuf, len, endian, mode, setval, seeki, buf, i, size);
2478  if (size == -1) {
2479  i += strlen((char *)buf + i) + 1;
2480  } else {
2481  while (size--) {
2482  i++;
2483  }
2484  }
2485  break;
2486  case 'Z': // zero terminated wide string
2487  rz_type_format_nulltermwidestring(p, outbuf, len, endian, mode, setval, seeki, buf, i, size);
2488  if (size == -1) {
2489  i += rz_wstr_clen((char *)(buf + i)) * 2 + 2;
2490  } else {
2491  while (size--) {
2492  i += 2;
2493  }
2494  }
2495  break;
2496  case 's':
2497  if (rz_type_format_string(typedb, outbuf, seeki, addr64, addr, 0, mode) == 0) {
2498  i += (size == -1) ? 4 : 4 * size;
2499  }
2500  break;
2501  case 'S':
2502  if (rz_type_format_string(typedb, outbuf, seeki, addr64, addr, 1, mode) == 0) {
2503  i += (size == -1) ? 8 : 8 * size;
2504  }
2505  break;
2506  case 'B': // resolve bitfield
2507  if (size >= ARRAYINDEX_COEF) {
2508  size %= ARRAYINDEX_COEF;
2509  }
2510  rz_type_format_bitfield(typedb, outbuf, seeki, fmtname, fieldname, addr, mode, size);
2511  i += (size == -1) ? 1 : size;
2512  break;
2513  case 'E': // resolve enum
2514  if (size >= ARRAYINDEX_COEF) {
2515  size %= ARRAYINDEX_COEF;
2516  }
2517  rz_type_format_enum(typedb, outbuf, seeki, fmtname, fieldname, addr, mode, size);
2518  i += (size == -1) ? 1 : size;
2519  break;
2520  case 'r':
2521  if (fmtname) {
2522  rz_print_format_register(outbuf, p, mode, fmtname, setval);
2523  } else {
2524  eprintf("Unknown register\n");
2525  }
2526  break;
2527  case '?': {
2528  int s = 0;
2529  char *nxtfield = NULL;
2530  char *format = NULL;
2531  int anon = 0;
2532  if (size >= ARRAYINDEX_COEF) {
2533  elem = size / ARRAYINDEX_COEF - 1;
2534  size %= ARRAYINDEX_COEF;
2535  }
2536  if (!(mode & RZ_PRINT_ISFIELD)) {
2537  nxtfield = MINUSONE;
2538  } else if (field) {
2539  nxtfield = strchr(ofield, '.');
2540  }
2541  if (nxtfield != MINUSONE && nxtfield) {
2542  nxtfield++;
2543  }
2544 
2545  if (MUSTSEE) {
2546  if (!SEEVALUE) {
2547  rz_strbuf_append(outbuf, "\n");
2548  }
2549  }
2550  if (MUSTSEEJSON) {
2551  if (isptr) {
2552  rz_strbuf_appendf(outbuf, "%" PFMT64d "},", seeki);
2553  } else {
2554  rz_strbuf_append(outbuf, "[");
2555  }
2556  }
2557  if (MUSTSEESTRUCT) {
2558  if (isptr) {
2559  rz_strbuf_appendf(outbuf, "%" PFMT64d, seeki);
2560  } else {
2561  ident += 4;
2562  rz_strbuf_append(outbuf, "\n");
2563  }
2564  }
2565  if (mode & RZ_PRINT_SEEFLAGS) {
2566  slide += STRUCTFLAG;
2567  }
2568  if (!fmtname) {
2569  break;
2570  }
2571  format = strchr(fmtname, ' ');
2572  if (format) {
2573  anon = 1;
2574  fmtname = format;
2575  while (*fmtname == ' ') {
2576  fmtname++;
2577  }
2578  }
2579  oldslide = slide;
2580  // slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
2581  slide += NESTEDSTRUCT;
2582  if (size == -1) {
2583  s = rz_type_format_struct(typedb, p, outbuf, seeki,
2584  buf + i, len - i, fmtname, slide,
2585  mode, setval, nxtfield, anon);
2586  i += (isptr) ? (typedb->target->bits / 8) : s;
2587  if (MUSTSEEJSON) {
2588  if (!isptr && (!arg[1] || arg[1] == ' ')) {
2589  rz_strbuf_append(outbuf, "]}");
2590  }
2591  }
2592  } else {
2593  if (mode & RZ_PRINT_ISFIELD) {
2594  if (!SEEVALUE) {
2595  rz_strbuf_append(outbuf, "[\n");
2596  }
2597  }
2598  while (size--) {
2599  if (mode && (elem == -1 || elem == 0)) {
2600  mode |= RZ_PRINT_MUSTSEE;
2601  if (elem == 0) {
2602  elem = -2;
2603  }
2604  } else {
2605  mode &= ~RZ_PRINT_MUSTSEE;
2606  }
2607  s = rz_type_format_struct(typedb, p, outbuf, seek + i,
2608  buf + i, len - i, fmtname, slide, mode, setval, nxtfield, anon);
2609  if ((MUSTSEE || MUSTSEEJSON || MUSTSEESTRUCT) && size != 0 && elem == -1) {
2610  if (MUSTSEEJSON) {
2611  rz_strbuf_append(outbuf, ",");
2612  } else if (MUSTSEE || MUSTSEESTRUCT) {
2613  rz_strbuf_append(outbuf, "\n");
2614  }
2615  }
2616  if (elem > -1) {
2617  elem--;
2618  }
2619  i += (isptr) ? (typedb->target->bits / 8) : s;
2620  }
2621  if (mode & RZ_PRINT_ISFIELD) {
2622  if (!SEEVALUE) {
2623  rz_strbuf_append(outbuf, "]\n");
2624  }
2625  }
2626  if (MUSTSEEJSON) {
2627  rz_strbuf_append(outbuf, "]}");
2628  }
2629  }
2630  oldslide = slide;
2631  // slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
2632  slide -= NESTEDSTRUCT;
2633  if (mode & RZ_PRINT_SEEFLAGS) {
2634  oldslide = slide;
2635  slide -= STRUCTFLAG;
2636  }
2637  break;
2638  }
2639  case 'n':
2640  case 'N': {
2641  int bytes = 0;
2642  int sign = (tmp == 'n') ? 1 : 0;
2643  if (arg[1] == '1') {
2644  bytes = 1;
2645  } else if (arg[1] == '2') {
2646  bytes = 2;
2647  } else if (arg[1] == '4') {
2648  bytes = 4;
2649  } else if (arg[1] == '8') {
2650  bytes = 8;
2651  } else {
2652  invalid = 1;
2653  break;
2654  // or goto beach;???
2655  }
2656  rz_type_format_num(outbuf, endian, mode, setval, seeki, buf, i, bytes, sign, size);
2657  i += (size == -1) ? bytes : size * bytes;
2658  arg++;
2659  break;
2660  }
2661  default:
2662  /* ignore unknown chars */
2663  invalid = 1;
2664  break;
2665  } // switch
2666  }
2667  if (MUSTSEESTRUCT) {
2668  if (oldslide) {
2669  ident -= 4;
2670  rz_strbuf_appendf(outbuf, "%*c}", ident, ' ');
2671  oldslide -= NESTEDSTRUCT;
2672  }
2673  rz_strbuf_append(outbuf, "\n");
2674  }
2675  if (mode & RZ_PRINT_DOT) {
2676  rz_strbuf_append(outbuf, "}");
2677  }
2678  if (mode & RZ_PRINT_SEEFLAGS && isptr != NULLPTR) {
2679  int sz = i - oi;
2680  if (sz > 1) {
2681  rz_strbuf_appendf(outbuf, "fL %d @ 0x%08" PFMT64x "\n", sz, seeki);
2682  rz_strbuf_appendf(outbuf, "Cd %d @ 0x%08" PFMT64x "\n", sz, seeki);
2683  }
2684  }
2685  if (viewflags && p->offname) {
2686  const char *s = p->offname(p->user, seeki);
2687  if (s) {
2688  rz_strbuf_appendf(outbuf, "@(%s)", s);
2689  }
2690  s = p->offname(p->user, addr);
2691  if (s) {
2692  rz_strbuf_appendf(outbuf, "*(%s)", s);
2693  }
2694  }
2695  if (!noline && tmp != 'D' && !invalid && !fmtname && MUSTSEE) {
2696  rz_strbuf_append(outbuf, "\n");
2697  }
2698  last = tmp;
2699 
2700  // XXX: Due to the already noted issues with the above, we need to strip
2701  // args from fmt:args the same way we strip fmt BUT only for enums as
2702  // nested structs seem to be handled correctly above!
2703  if (arg[0] == 'E') {
2704  char *end_fmt = strchr(arg, ' ');
2705  if (!end_fmt) {
2706  goto beach;
2707  }
2708  char *next_args = strchr(end_fmt + 1, ' ');
2709  if (next_args) {
2710  while (*next_args != '\0') {
2711  *end_fmt++ = *next_args++;
2712  }
2713  }
2714  *end_fmt = '\0';
2715  }
2716  }
2717  if (otimes > 1) {
2718  if (MUSTSEEJSON) {
2719  rz_strbuf_append(outbuf, "]");
2720  } else if (mode) {
2721  rz_strbuf_append(outbuf, "}\n");
2722  }
2723  }
2724  arg = orig;
2725  oldslide = 0;
2726  }
2727  if (mode & RZ_PRINT_JSON && slide == 0) {
2728  rz_strbuf_append(outbuf, "]\n");
2729  }
2730  if (MUSTSEESTRUCT && slide == 0) {
2731  rz_strbuf_append(outbuf, "}\n");
2732  }
2733  if (mode & RZ_PRINT_DOT) {
2734  rz_strbuf_append(outbuf, "\"];\n}\n");
2735  // TODO: show nested structs and field reference lines
2736  }
2737 beach:
2738  if (slide == 0) {
2739  oldslide = 0;
2740  }
2741  free(internal_format);
2742  free(oarg);
2743  free(buf);
2744  free(field);
2745  free(args);
2746  return i;
2747 }
2748 
2749 RZ_API RZ_OWN char *rz_type_format_data(const RzTypeDB *typedb, RzPrint *p, ut64 seek, const ut8 *b, const int len,
2750  const char *formatname, int mode, const char *setval, char *ofield) {
2751  RzStrBuf *outbuf = rz_strbuf_new("");
2752  rz_type_format_data_internal(typedb, p, outbuf, seek, b, len, formatname, mode, setval, ofield);
2753  char *outstr = rz_strbuf_drain(outbuf);
2754  return outstr;
2755 }
2756 
2757 /* Every format string essentially contains two parts:
2758  * 1. The format (`pf` string) itself
2759  * 2. The field name and types, "(field_type)field_name"
2760  * Both parts are separated from each other by space
2761  *
2762  * Example:
2763  * "[2]Ewtxxw[2]B (pe_machine)machine NumberOfSections TimeDateStamp PointerToSymbolTable NumberOfSymbols SizeOfOptionalHeader (pe_characteristics)Characteristics"
2764  * Here "[2]Ewtxxw[2]B" is the `pf` string while the rest are field names and types.
2765  * E.g. "(pe_machine)" is the field type, previously defined enum called "pe_machine"
2766  * "machine" here is the field name. The corresponding construction in C is:
2767  * struct {
2768  * pe_machine machine;
2769  * uint16_t NumberOfSections;
2770  * datetime_t TimeDateStamp;
2771  * uint32_t PointerToSymbolTable;
2772  * uint32_t NumberOfSymbols;
2773  * uint16_t SizeOfOptionalHeader;
2774  * pe_characteristics characteristics; // (bitfield enum)
2775  * };
2776  */
2777 
2778 static const char *type_to_identifier(const RzTypeDB *typedb, RzType *type) {
2779  if (type->kind == RZ_TYPE_KIND_IDENTIFIER) {
2780  return type->identifier.name;
2781  } else if (type->kind == RZ_TYPE_KIND_ARRAY) {
2782  return type_to_identifier(typedb, type->array.type);
2783  } else if (type->kind == RZ_TYPE_KIND_POINTER) {
2784  return type_to_identifier(typedb, type->pointer.type);
2785  } else if (type->kind == RZ_TYPE_KIND_CALLABLE) {
2786  return type->callable->name;
2787  }
2789  return NULL;
2790 }
2791 
2792 static bool type_to_format_pair(const RzTypeDB *typedb, RzStrBuf *format, RzStrBuf *fields, RZ_NULLABLE const char *identifier, RZ_NONNULL RzType *type);
2793 
2794 // This logic applies only to the structure/union members, not the toplevel types
2795 static void base_type_to_format_no_unfold(const RzTypeDB *typedb, RZ_NONNULL RzBaseType *type, RZ_NONNULL const char *identifier, RzStrBuf *format, RzStrBuf *fields) {
2796  rz_return_if_fail(typedb && type && identifier && format && fields);
2797  switch (type->kind) {
2798  case RZ_BASE_TYPE_KIND_STRUCT: {
2799  rz_strbuf_append(format, "?");
2800  rz_strbuf_appendf(fields, "(%s)%s ", type->name, identifier);
2801  break;
2802  }
2803  case RZ_BASE_TYPE_KIND_UNION: {
2804  // In `pf` unions defined like structs but all have 0 offset,
2805  // which is why it uses `0` character as a marker
2806  rz_strbuf_append(format, "0");
2807  rz_strbuf_appendf(fields, "(%s)%s ", type->name, identifier);
2808  break;
2809  }
2810  case RZ_BASE_TYPE_KIND_ENUM: {
2811  // Some enums defined as bitfields in the database, so we search if
2812  // it's stored as the `pf` format in the database
2813  const char *fmt = rz_type_db_format_get(typedb, type->name);
2814  if (fmt) {
2815  rz_strbuf_append(format, "B");
2816  } else {
2817  rz_strbuf_append(format, "E");
2818  }
2819  rz_strbuf_appendf(fields, "(%s)%s ", type->name, identifier);
2820  break;
2821  }
2823  // It might go recursively to find all types behind the alias
2824  char *fmt = rz_type_as_format(typedb, type->type);
2825  if (fmt) {
2826  rz_strbuf_append(format, fmt);
2827  rz_strbuf_appendf(fields, "%s ", identifier);
2828  } else {
2829  type_to_format_pair(typedb, format, fields, identifier, type->type);
2830  }
2831  free(fmt);
2832  break;
2833  }
2834  case RZ_BASE_TYPE_KIND_ATOMIC: {
2835  // We simply skip fields that don't have a format
2836  const char *fmt = rz_type_db_format_get(typedb, type->name);
2837  if (fmt) {
2838  rz_strbuf_append(format, fmt);
2839  rz_strbuf_appendf(fields, "%s ", identifier);
2840  }
2841  break;
2842  }
2843  default:
2845  break;
2846  }
2847 }
2848 
2849 // This logic applies to the toplevel types and unfolds the structure/union types
2850 static void base_type_to_format_unfold(const RzTypeDB *typedb, RZ_NONNULL RzBaseType *type, RzStrBuf *format, RzStrBuf *fields, RZ_NULLABLE const char *identifier) {
2851  rz_return_if_fail(typedb && type && format && fields);
2852  switch (type->kind) {
2853  case RZ_BASE_TYPE_KIND_STRUCT: {
2854  RzTypeStructMember *memb;
2855  rz_vector_foreach(&type->struct_data.members, memb) {
2856  const char *membtype = type_to_identifier(typedb, memb->type);
2857  // Avoid infinite recursion in case of self-referential structures
2858  if (!strcmp(membtype, type->name)) {
2859  continue;
2860  }
2861  if (rz_type_is_identifier(memb->type)) {
2862  // Search the base type of the same name and generate the format from it
2863  RzBaseType *btyp = rz_type_get_base_type(typedb, memb->type);
2864  if (btyp) {
2865  base_type_to_format_no_unfold(typedb, btyp, memb->name, format, fields);
2866  }
2867  } else {
2868  char *membfmt = rz_type_as_format(typedb, memb->type);
2869  rz_strbuf_append(format, membfmt);
2870  if (!rz_type_is_atomic(typedb, memb->type)) {
2871  rz_strbuf_appendf(fields, "(%s)%s ", membtype, memb->name);
2872  } else {
2873  rz_strbuf_appendf(fields, "%s ", memb->name);
2874  }
2875  free(membfmt);
2876  }
2877  }
2878  break;
2879  }
2880  case RZ_BASE_TYPE_KIND_UNION: {
2881  // In `pf` unions defined like structs but all have 0 offset,
2882  // which is why it uses `0` character as a marker
2883  RzTypeUnionMember *memb;
2884  rz_vector_foreach(&type->union_data.members, memb) {
2885  const char *membtype = type_to_identifier(typedb, memb->type);
2886  // Avoid infinite recursion in case of self-referential unions
2887  if (!strcmp(membtype, type->name)) {
2888  continue;
2889  }
2890  if (rz_type_is_identifier(memb->type)) {
2891  // Search the base type of the same name and generate the format from it
2892  RzBaseType *btyp = rz_type_get_base_type(typedb, memb->type);
2893  if (btyp) {
2894  base_type_to_format_no_unfold(typedb, btyp, memb->name, format, fields);
2895  }
2896  } else {
2897  char *membfmt = rz_type_as_format(typedb, memb->type);
2898  rz_strbuf_append(format, membfmt);
2899  if (!rz_type_is_atomic(typedb, memb->type)) {
2900  rz_strbuf_appendf(fields, "(%s)%s ", membtype, memb->name);
2901  } else {
2902  rz_strbuf_appendf(fields, "%s ", memb->name);
2903  }
2904  free(membfmt);
2905  }
2906  }
2907  break;
2908  }
2910  case RZ_BASE_TYPE_KIND_ATOMIC: {
2911  base_type_to_format_no_unfold(typedb, type, type->name, format, fields);
2912  break;
2913  }
2915  // Avoid infinite recursion in case of self-referential typedefs
2916  if (rz_type_is_identifier(type->type)) {
2917  const char *ttype = type_to_identifier(typedb, type->type);
2918  if (!strcmp(ttype, type->name)) {
2919  break;
2920  }
2921  }
2922  type_to_format_pair(typedb, format, fields, identifier, type->type);
2923  break;
2924  }
2925  default:
2927  break;
2928  }
2929 }
2930 
2942  rz_return_val_if_fail(typedb && type && type->name, NULL);
2943 
2944  RzStrBuf *format = rz_strbuf_new("");
2945  RzStrBuf *fields = rz_strbuf_new("");
2946  base_type_to_format_unfold(typedb, type, format, fields, NULL);
2947  char *fieldstr = rz_strbuf_drain(fields);
2948  rz_strbuf_appendf(format, " %s", fieldstr);
2949  free(fieldstr);
2950  char *bufstr = rz_strbuf_drain(format);
2951  rz_str_trim_tail(bufstr);
2952  return bufstr;
2953 }
2954 
2965 RZ_API RZ_OWN char *rz_type_format(RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const char *name) {
2966  rz_return_val_if_fail(typedb && name, NULL);
2967  RzBaseType *btype = rz_type_db_get_base_type(typedb, name);
2968  if (!btype) {
2969  return NULL;
2970  }
2971  return rz_base_type_as_format(typedb, btype);
2972 }
2973 
2974 static void type_to_format(const RzTypeDB *typedb, RzStrBuf *buf, RzType *type) {
2975  if (type->kind == RZ_TYPE_KIND_IDENTIFIER) {
2976  const char *format = rz_type_db_format_get(typedb, type->identifier.name);
2977  if (format) {
2978  rz_strbuf_append(buf, format);
2979  } else {
2980  if (type->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_STRUCT) {
2981  rz_strbuf_append(buf, "?");
2982  } else if (type->identifier.kind == RZ_TYPE_IDENTIFIER_KIND_ENUM) {
2983  rz_strbuf_append(buf, "E");
2984  }
2985  }
2986  } else if (type->kind == RZ_TYPE_KIND_ARRAY) {
2987  rz_strbuf_appendf(buf, "[%" PFMT64d "]", type->array.count);
2988  type_to_format(typedb, buf, type->array.type);
2989  } else if (type->kind == RZ_TYPE_KIND_POINTER) {
2990  rz_strbuf_append(buf, "*");
2991  type_to_format(typedb, buf, type->pointer.type);
2992  }
2993 }
2994 
3006  rz_return_val_if_fail(typedb && type, NULL);
3007  if (type->kind == RZ_TYPE_KIND_CALLABLE) {
3008  // We can't print anything useful for function type
3009  // Thus we consider this is just a `void *` pointer
3010  return strdup("p");
3011  }
3012  // Special case of callable ptr or `void *`
3014  return strdup("p");
3015  }
3016  // Special case of `char *`
3017  if (rz_type_is_char_ptr(type)) {
3018  return strdup("z");
3019  }
3021  type_to_format(typedb, buf, type);
3022  return rz_strbuf_drain(buf);
3023 }
3024 
3025 static bool type_to_format_pair(const RzTypeDB *typedb, RzStrBuf *format, RzStrBuf *fields, RZ_NULLABLE const char *identifier, RZ_NONNULL RzType *type) {
3026  rz_return_val_if_fail(typedb && format && fields && type, false);
3027  if (type->kind == RZ_TYPE_KIND_IDENTIFIER) {
3028  if (!type->identifier.name) {
3029  return false;
3030  }
3031  RzBaseType *btype = rz_type_db_get_base_type(typedb, type->identifier.name);
3032  if (!btype) {
3033  return false;
3034  }
3035  base_type_to_format_unfold(typedb, btype, format, fields, identifier);
3036  } else if (type->kind == RZ_TYPE_KIND_ARRAY) {
3037  rz_strbuf_appendf(format, "[%" PFMT64d "]", type->array.count);
3038  return type_to_format_pair(typedb, format, fields, identifier, type->array.type);
3039  } else if (type->kind == RZ_TYPE_KIND_POINTER) {
3040  // We can't print anything useful for function type pointer
3042  // Thus we consider this is just a `void *` pointer
3043  rz_strbuf_append(format, "p");
3044  const char *name = rz_type_identifier(type);
3045  // Callables are allowed to have empty names
3046  if (name) {
3047  rz_strbuf_appendf(fields, "%s ", name);
3048  }
3049  } else {
3050  rz_strbuf_append(format, "*");
3051  return type_to_format_pair(typedb, format, fields, identifier, type->pointer.type);
3052  }
3053  } else if (type->kind == RZ_TYPE_KIND_CALLABLE) {
3054  // We can't print anything useful for function type
3055  // Thus we consider this is just a `void *` pointer
3056  rz_strbuf_append(format, "p");
3057  // Callables are allowed to have empty names
3058  if (type->callable->name) {
3059  rz_strbuf_appendf(fields, "%s ", type->callable->name);
3060  }
3061  }
3062  return true;
3063 }
3064 
3076  rz_return_val_if_fail(typedb && type, NULL);
3077  RzStrBuf *format = rz_strbuf_new("");
3078  RzStrBuf *fields = rz_strbuf_new("");
3079  if (!type_to_format_pair(typedb, format, fields, NULL, type)) {
3080  rz_strbuf_free(format);
3082  return NULL;
3083  }
3084  char *fieldstr = rz_strbuf_drain(fields);
3085  rz_strbuf_appendf(format, " %s", fieldstr);
3086  free(fieldstr);
3087  char *bufstr = rz_strbuf_drain(format);
3088  rz_str_trim_tail(bufstr);
3089  return bufstr;
3090 }
size_t len
Definition: 6502dis.c:15
const aarch64_field fields[]
Definition: aarch64-opc.c:205
@ bitfield
Definition: aarch64.h:481
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
static const char * arg(RzAnalysis *a, csh *handle, cs_insn *insn, char *buf, int n)
Definition: arm_esil32.c:136
static ut8 bytes[32]
Definition: asm_arc.c:23
RZ_API RZ_BORROW RzBaseType * rz_type_db_get_base_type(const RzTypeDB *typedb, RZ_NONNULL const char *name)
Searches for the RzBaseType in the types database given the name.
Definition: base.c:57
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
const char * k
Definition: dsignal.c:11
const char * v
Definition: dsignal.c:12
int max
Definition: enough.c:225
size_t map(int syms, int left, int len)
Definition: enough.c:237
RZ_API RZ_OWN char * rz_base_type_as_format(const RzTypeDB *typedb, RZ_NONNULL RzBaseType *type)
Represents the RzBaseType as a pf format string.
Definition: format.c:2941
static void rz_type_format_bitfield(const RzTypeDB *typedb, RzStrBuf *outbuf, ut64 seeki, char *fmtname, char *fieldname, ut64 addr, int mode, int size)
Definition: format.c:1339
RZ_API RZ_OWN char * rz_type_as_format(const RzTypeDB *typedb, RZ_NONNULL RzType *type)
Represents the RzType as a pf format string.
Definition: format.c:3005
static void rz_type_format_word(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:1105
static int rz_type_format_10bytes(const RzTypeDB *typedb, RzStrBuf *outbuf, int mode, const char *setval, ut64 seeki, ut64 addr, ut8 *buf)
Definition: format.c:901
#define STRUCTPTR
Definition: format.c:14
static float updateAddr(const ut8 *buf, int len, int endian, ut64 *addr, ut64 *addr64)
Definition: format.c:33
#define PTRSEEK
Definition: format.c:11
#define MUSTSEESTRUCT
Definition: format.c:25
#define PTRBACK
Definition: format.c:12
static void base_type_to_format_no_unfold(const RzTypeDB *typedb, RZ_NONNULL RzBaseType *type, RZ_NONNULL const char *identifier, RzStrBuf *format, RzStrBuf *fields)
Definition: format.c:2795
static void rz_type_format_double(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:1048
#define ISSTRUCT
Definition: format.c:1899
RZ_API void rz_type_db_format_set(RzTypeDB *typedb, const char *name, const char *fmt)
Definition: format.c:1912
RZ_API RZ_OWN char * rz_type_format(RZ_NONNULL const RzTypeDB *typedb, RZ_NONNULL const char *name)
Represents the RzBaseType as a pf format string.
Definition: format.c:2965
static void rz_type_format_octal(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:753
static void rz_print_format_register(RzStrBuf *outbuf, const RzPrint *p, int mode, const char *name, const char *setval)
Definition: format.c:1394
static void rz_type_format_num_specifier(RzStrBuf *outbuf, ut64 addr, int bytes, int sign)
Definition: format.c:1417
static void type_to_format(const RzTypeDB *typedb, RzStrBuf *buf, RzType *type)
Definition: format.c:2974
RZ_API void rz_type_db_format_delete(RzTypeDB *typedb, const char *name)
Definition: format.c:1932
static void rz_type_format_num(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int bytes, int sign, int size)
Definition: format.c:1433
static void rz_type_format_u128(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:70
RZ_API int rz_type_format_struct_size(const RzTypeDB *typedb, const char *f, int mode, int n)
Definition: format.c:1515
#define NULLPTR
Definition: format.c:13
static bool format_collect_cb(void *user, const void *k, const void *v)
Definition: format.c:1917
#define ARRAYINDEX_COEF
Definition: format.c:18
#define THRESHOLD
Definition: format.c:29
#define MUSTSEEJSON
Definition: format.c:24
RZ_API const char * rz_type_db_format_get(const RzTypeDB *typedb, const char *name)
Definition: format.c:1901
static void base_type_to_format_unfold(const RzTypeDB *typedb, RZ_NONNULL RzBaseType *type, RzStrBuf *format, RzStrBuf *fields, RZ_NULLABLE const char *identifier)
Definition: format.c:2850
static int rz_type_format_hexpairs(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:947
RZ_API RZ_OWN char * rz_type_as_format_pair(const RzTypeDB *typedb, RZ_NONNULL RzType *type)
Represents the RzType as a pf format string pair.
Definition: format.c:3075
static void rz_type_format_int(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:665
static void rz_type_format_char(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:320
static int rz_type_format_data_internal(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, ut64 seek, const ut8 *b, const int len, const char *formatname, int mode, const char *setval, char *ofield)
Definition: format.c:1937
static void rz_type_format_hexflag(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:826
#define MUSTSET
Definition: format.c:22
static int rz_type_format_struct(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, ut64 seek, const ut8 *b, int len, const char *name, int slide, int mode, const char *setval, char *field, int anon)
Definition: format.c:1775
#define NESTEDSTRUCT
Definition: format.c:15
static int rz_type_format_string(const RzTypeDB *typedb, RzStrBuf *outbuf, ut64 seeki, ut64 addr64, ut64 addr, int is64, int mode)
Definition: format.c:452
static int rz_type_format_uleb(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:234
#define MINUSONE
Definition: format.c:1898
static void rz_type_format_decchar(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:386
#define MUSTSEE
Definition: format.c:20
static void rz_type_format_quadword(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:92
static const char * type_to_identifier(const RzTypeDB *typedb, RzType *type)
Definition: format.c:2778
static void rz_type_format_byte(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:167
#define EXT(T)
#define NOPTR
Definition: format.c:10
#define NESTDEPTH
Definition: format.c:17
#define STRUCTFLAG
Definition: format.c:16
static void rz_type_byte_escape(const RzPrint *p, const char *src, char **dst, int dot_nl)
Definition: format.c:1193
static void rz_type_format_hex(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:583
RZ_API RZ_OWN RzList * rz_type_db_format_all(RzTypeDB *typedb)
Definition: format.c:1925
static void rz_type_format_nulltermstring(const RzTypeDB *typedb, RzPrint *p, RzStrBuf *outbuf, int len, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:1202
static void rz_type_format_enum(const RzTypeDB *typedb, RzStrBuf *outbuf, ut64 seeki, char *fmtname, char *fieldname, ut64 addr, int mode, int size)
Definition: format.c:1364
static void rz_type_format_nulltermwidestring(RzPrint *p, RzStrBuf *outbuf, const int len, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:1297
#define SEEVALUE
Definition: format.c:23
RZ_API RZ_OWN char * rz_type_format_data(const RzTypeDB *typedb, RzPrint *p, ut64 seek, const ut8 *b, const int len, const char *formatname, int mode, const char *setval, char *ofield)
Definition: format.c:2749
static void rz_type_format_time(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:493
static char * get_format_type(const char fmt, const char arg)
Definition: format.c:1829
static int rz_get_size(RzNum *num, ut8 *buf, int endian, const char *s)
Definition: format.c:58
static char * get_args_offset(const char *arg)
Definition: format.c:1816
static void rz_type_format_float(RzStrBuf *outbuf, int endian, int mode, const char *setval, ut64 seeki, ut8 *buf, int i, int size)
Definition: format.c:994
static bool type_to_format_pair(const RzTypeDB *typedb, RzStrBuf *format, RzStrBuf *fields, RZ_NULLABLE const char *identifier, RZ_NONNULL RzType *type)
Definition: format.c:3025
#define ISQUIET
Definition: format.c:21
unsigned char outbuf[SIZE]
Definition: gun.c:162
RZ_API bool rz_type_is_identifier(RZ_NONNULL const RzType *type)
Checks if the RzType is identifier.
Definition: helpers.c:338
RZ_API bool rz_type_is_atomic(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Checks if the RzType is atomic or derivative of it.
Definition: helpers.c:371
RZ_API bool rz_type_is_void_ptr(RZ_NONNULL const RzType *type)
Checks if the pointer RzType is abstract pointer ("void *")
Definition: helpers.c:298
RZ_API bool rz_type_is_char_ptr(RZ_NONNULL const RzType *type)
Checks if the pointer RzType is a string ("char *" or "const char *")
Definition: helpers.c:318
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
RZ_API const KEY_TYPE bool * found
Definition: ht_inc.h:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
const char int mode
Definition: ioapi.h:137
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd times
Definition: sflib.h:70
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
char * dst
Definition: lz4.h:724
int args
Definition: mipsasm.c:18
int n
Definition: mipsasm.c:19
int type
Definition: mipsasm.c:17
int idx
Definition: setup.py:197
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
static ut64 rz_read_ble64(const void *src, bool big_endian)
Definition: rz_endian.h:501
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
static ut16 rz_read_ble16(const void *src, bool big_endian)
Definition: rz_endian.h:493
RZ_API char * rz_hex_bin2strdup(const ut8 *in, int len)
Definition: hex.c:415
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API void rz_mem_swaporcopy(ut8 *dest, const ut8 *src, int len, bool big_endian)
Definition: mem.c:192
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
#define RZ_PRINT_FLAGS_UNALLOC
Definition: rz_print.h:34
@ RZ_REG_TYPE_ANY
Definition: rz_reg.h:35
RZ_API void rz_str_byte_escape(const char *p, char **dst, RzStrEscOptions *opt)
Converts unprintable characters to C-like backslash representation.
Definition: str.c:1436
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API int rz_str_word_set0_stack(char *str)
Definition: str.c:471
RZ_API RZ_BORROW char * rz_str_trim_tail(RZ_NONNULL char *str)
Removes whitespace characters (space, tab, newline etc.) from the end of a string and replaces them w...
Definition: str_trim.c:125
RZ_API const char * rz_str_rchr(const char *base, const char *p, int ch)
Definition: str.c:829
RZ_API char * rz_str_utf16_encode(const char *s, int len)
Definition: str.c:2993
#define RZ_STR_ISEMPTY(x)
Definition: rz_str.h:67
RZ_API size_t rz_str_nlen(const char *s, size_t n)
Definition: str.c:1949
RZ_API char * rz_str_escape_utf8_for_json(const char *s, int len)
Definition: str.c:1834
RZ_API size_t rz_wstr_clen(const char *s)
Definition: str.c:2087
RZ_API const char * rz_str_word_get0(const char *str, int idx)
Definition: str.c:598
#define IS_DIGIT(x)
Definition: rz_str_util.h:11
#define IS_PRINTABLE(x)
Definition: rz_str_util.h:10
#define IS_WHITECHAR(x)
Definition: rz_str_util.h:5
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API void rz_strbuf_free(RzStrBuf *sb)
Definition: strbuf.c:358
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API struct tm * rz_gmtime_r(RZ_NONNULL const time_t *time, RZ_NONNULL struct tm *res)
Definition: time.c:294
RZ_API char * rz_asctime_r(RZ_NONNULL const struct tm *tm, RZ_NONNULL char *buf)
Definition: time.c:304
#define ASCTIME_BUF_MINLEN
Definition: rz_time.h:13
@ RZ_BASE_TYPE_KIND_TYPEDEF
Definition: rz_type.h:76
@ RZ_BASE_TYPE_KIND_ATOMIC
Definition: rz_type.h:77
@ RZ_BASE_TYPE_KIND_UNION
Definition: rz_type.h:74
@ RZ_BASE_TYPE_KIND_STRUCT
Definition: rz_type.h:73
@ RZ_BASE_TYPE_KIND_ENUM
Definition: rz_type.h:75
@ RZ_TYPE_IDENTIFIER_KIND_STRUCT
Definition: rz_type.h:136
@ RZ_TYPE_IDENTIFIER_KIND_ENUM
Definition: rz_type.h:138
@ RZ_TYPE_KIND_ARRAY
Definition: rz_type.h:130
@ RZ_TYPE_KIND_CALLABLE
Definition: rz_type.h:131
@ RZ_TYPE_KIND_IDENTIFIER
Definition: rz_type.h:128
@ RZ_TYPE_KIND_POINTER
Definition: rz_type.h:129
#define PFMT64d
Definition: rz_types.h:394
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NONNULL
Definition: rz_types.h:64
#define PFMT64u
Definition: rz_types.h:395
#define PFMT64o
Definition: rz_types.h:396
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_MIN(x, y)
#define st64
Definition: rz_types_base.h:10
#define UT32_MAX
Definition: rz_types_base.h:99
#define UT64_MAX
Definition: rz_types_base.h:86
#define st32
Definition: rz_types_base.h:12
RZ_API const ut8 * rz_uleb128_decode(const ut8 *data, int *datalen, ut64 *v)
Definition: uleb128.c:71
RZ_API ut8 * rz_uleb128_encode(const ut64 s, int *len)
Definition: uleb128.c:89
#define rz_vector_foreach(vec, it)
Definition: rz_vector.h:169
static int
Definition: sfsocketcall.h:114
int time_t
Definition: sftypes.h:66
#define b(i)
Definition: sha256.c:42
#define f(i)
Definition: sha256.c:46
Group together some common options used by string escaping functions.
Definition: rz_str.h:39
bool esc_bslash
When true, backslashes \ are quoted with \\
Definition: rz_str.h:41
bool show_asciidot
When true, dots . are placed instead of unprintable characters.
Definition: rz_str.h:40
bool dot_nl
When true, is converted into the graphiz-compatible newline \l.
Definition: rz_str.h:43
Definition: buffer.h:15
Definition: z80asm.h:102
RzIOReadAt read_at
Definition: rz_io.h:240
RzIOIsValidOff is_valid_offset
Definition: rz_io.h:257
RzIOMapGet map_get
Definition: rz_io.h:259
RzIO * io
Definition: rz_io.h:232
RzIOMapGetPaddr map_get_paddr
Definition: rz_io.h:260
int cached
Definition: rz_io.h:69
int va
Definition: rz_io.h:63
char * name
Definition: rz_reg.h:118
RzNum * num
Definition: rz_type.h:38
HtPP * formats
Definition: rz_type.h:34
RzIOBind iob
Definition: rz_type.h:39
RzTypeTarget * target
Definition: rz_type.h:36
bool big_endian
Definition: rz_type.h:25
ut64 buflen
Definition: core.c:76
RZ_API bool rz_type_is_callable_ptr(RZ_NONNULL const RzType *type)
Checks if the RzType is the pointer to the RzCallable.
Definition: function.c:375
RZ_API bool rz_type_is_callable_ptr_nested(RZ_NONNULL const RzType *type)
Checks if the RzType is the nested pointer to the RzCallable.
Definition: function.c:399
RZ_API RZ_BORROW const char * rz_type_identifier(RZ_NONNULL const RzType *type)
Returns the type C identifier.
Definition: type.c:1155
RZ_API RZ_BORROW const char * rz_type_db_enum_member_by_val(const RzTypeDB *typedb, RZ_NONNULL const char *name, ut64 val)
Returns the enum case name matching the cpecified value.
Definition: type.c:508
RZ_API RZ_BORROW RzBaseType * rz_type_get_base_type(const RzTypeDB *typedb, RZ_NONNULL const RzType *type)
Returns the RzBaseType for the chosen RzType.
Definition: type.c:1251
RZ_API RZ_OWN char * rz_type_db_enum_get_bitfield(const RzTypeDB *typedb, RZ_NONNULL const char *name, ut64 val)
Returns all matching bitfields as an OR mask given the resulting value.
Definition: type.c:584
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static xtensa_format_internal formats[]
static int comma
Definition: z80asm.c:76
static int addr
Definition: z80asm.c:58
static int seek(char *argv[])