radare2/libr/util/p_format.c

1669 lines
44 KiB
C
Raw Normal View History

2016-05-30 15:30:55 +02:00
/* radare - LGPL - Copyright 2007-2016 - pancake & Skia */
#include "r_cons.h"
#include "r_util.h"
#include "r_print.h"
#include "r_reg.h"
#define NOPTR 0
#define PTRSEEK 1
#define PTRBACK 2
#define NULLPTR 3
#define STRUCTPTR 100
#define NESTEDSTRUCT 1
#define STRUCTFLAG 10000
#define NESTDEPTH 14
#define ARRAYINDEX_COEF 10000
#define MUSTSEE (mode & R_PRINT_MUSTSEE && mode & R_PRINT_ISFIELD && !(mode & R_PRINT_JSON))
#define MUSTSET (mode & R_PRINT_MUSTSET && mode & R_PRINT_ISFIELD && setval)
#define SEEVALUE (mode & R_PRINT_VALUE)
#define MUSTSEEJSON (mode & R_PRINT_JSON && mode & R_PRINT_ISFIELD)
2014-08-01 11:46:08 +02:00
static void updateAddr(const ut8 *buf, int i, int endian, ut64 *addr, ut64 *addr64) {
if (addr) {
if (endian)
*addr = ((ut32)(*(buf+i))<<24)
| ((ut32)(*(buf+i+1))<<16)
| ((ut32)(*(buf+i+2))<<8)
| ((ut32)(*(buf+i+3)));
else
*addr = ((ut32)(*(buf+i+3))<<24)
| ((ut32)(*(buf+i+2))<<16)
| ((ut32)(*(buf+i+1))<<8)
| ((ut32)(*(buf+i)));
}
if (addr64) {
if (endian)
*addr64 = ((ut64)(*(buf+i))<<56)
| ((ut64)(*(buf+i+1))<<48)
| ((ut64)(*(buf+i+2))<<40)
| ((ut64)(*(buf+i+3))<<32)
| ((ut64)(*(buf+i+4))<<24)
| ((ut64)(*(buf+i+5))<<16)
| ((ut64)(*(buf+i+6))<<8)
| ((ut64)(*(buf+i+7)));
else
*addr64 = ((ut64)(*(buf+i+7))<<56)
| ((ut64)(*(buf+i+6))<<48)
| ((ut64)(*(buf+i+5))<<40)
| ((ut64)(*(buf+i+4))<<32)
| ((ut64)(*(buf+i+3))<<24)
| ((ut64)(*(buf+i+2))<<16)
| ((ut64)(*(buf+i+1))<<8)
| ((ut64)(*(buf+i)));
}
2014-08-01 00:15:17 +02:00
}
static int r_get_size(RNum *num, ut8 *buf, int endian, const char *s) {
int size=0, len = strlen(s);
ut64 addr;
if (s[0] == '*' && len >= 4) { // value pointed by the address
int offset = r_num_math (num, s+1);
updateAddr (buf, offset, endian, &addr, NULL);
return addr;
} else {
size = r_num_math (num, s); // this should handle also the flags, but doesn't work... :/
// eprintf ("SIZE: %s --> %d\n", s, size);
}
return size;
}
static void r_print_format_quadword(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
ut64 addr64;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
updateAddr (buf, i, endian, NULL, &addr64);
if (MUSTSET) {
p->cb_printf ("wv8 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*8:0));
} else if (MUSTSEE) {
if (!SEEVALUE) {
2016-06-01 12:13:09 +02:00
p->cb_printf ("0x%08"PFMT64x" = (qword)",
seeki + ((elem >= 0)? elem * 2: 0));
}
2016-06-01 12:13:09 +02:00
if (size==-1) {
p->cb_printf ("0x%016"PFMT64x, addr64);
2016-06-01 12:13:09 +02:00
} else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, NULL, &addr64);
if (elem == -1 || elem == 0) {
p->cb_printf ("0x%016"PFMT64x, addr64);
if (elem == 0) elem = -2;
}
2016-06-01 12:13:09 +02:00
if (size != 0 && elem == -1) {
p->cb_printf (", ");
2016-06-01 12:13:09 +02:00
}
if (elem > -1) {
elem--;
}
i += 8;
}
if (!SEEVALUE) p->cb_printf (" ]");
2014-10-26 02:22:58 +02:00
}
} else if (MUSTSEEJSON) {
2016-05-30 15:30:55 +02:00
if (size==-1) {
2016-03-08 11:44:32 +01:00
p->cb_printf ("%"PFMT64d, addr64);
2016-05-30 15:30:55 +02:00
} else {
p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, NULL, &addr64);
if (elem == -1 || elem == 0) {
2016-03-08 11:44:32 +01:00
p->cb_printf ("%"PFMT64d, addr64);
if (elem == 0) elem = -2;
}
2016-05-30 15:30:55 +02:00
if (size != 0 && elem == -1) {
p->cb_printf (", ");
2016-05-30 15:30:55 +02:00
}
if (elem > -1) elem--;
2016-05-30 15:30:55 +02:00
i += 8;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
2014-08-01 19:33:52 +02:00
}
}
static void r_print_format_byte(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
if (MUSTSET) {
p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem:0));
2016-06-01 12:13:09 +02:00
if (size==-1) {
p->cb_printf ("0x%02x", buf[i]);
2016-06-01 12:13:09 +02:00
} else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
if (elem == -1 || elem == 0) {
p->cb_printf ("0x%02x", buf[i]);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i++;
}
if (!SEEVALUE) p->cb_printf (" ]");
}
} else if (MUSTSEEJSON) {
if (size==-1)
p->cb_printf ("%d", buf[i]);
else {
p->cb_printf ("[ ");
while (size--) {
if (elem == -1 || elem == 0) {
p->cb_printf (", %d", buf[i]);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i++;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
2014-08-01 19:33:52 +02:00
}
}
2015-05-02 15:07:08 +02:00
static int r_print_format_uleb(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
int elem = -1;
int s = 0, sum = 0;
ut64 value = 0, offset = 0;
if (size >= ARRAYINDEX_COEF) {
2016-06-01 12:13:09 +02:00
elem = size / ARRAYINDEX_COEF - 1;
2015-05-02 15:07:08 +02:00
size %= ARRAYINDEX_COEF;
}
// offset = seeki+((elem>=0)?16*elem:0);
if (MUSTSET) {
ut8 *tmp;
char *nbr;
do {
offset += s;
r_uleb128_decode (buf+offset, &s, &value);
} while (elem--);
tmp = (ut8*) r_uleb128_encode (r_num_math (NULL, setval), &s);
nbr = r_hex_bin2strdup (tmp, s);
p->cb_printf ("\"wx %s\" @ 0x%08"PFMT64x"\n", nbr, seeki+offset);
2015-05-02 15:07:08 +02:00
free (tmp);
free (nbr);
// sum = size of the converted number
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
2015-05-02 15:07:08 +02:00
if (size==-1) {
2015-07-28 16:39:35 +02:00
r_uleb128_decode (buf+i, &s, &value);
p->cb_printf ("%"PFMT64d, value);
2015-05-02 15:07:08 +02:00
sum = s;
} else {
if (!SEEVALUE) p->cb_printf ("[ ");
2015-05-02 15:07:08 +02:00
while (size--) {
if (elem == -1 || elem == 0) {
r_uleb128_decode (buf+i, &s, &value);
sum += s;
p->cb_printf ("%"PFMT64d, value);
2015-05-02 15:07:08 +02:00
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
2015-05-02 15:07:08 +02:00
if (elem > -1) elem--;
i+=s;
}
if (!SEEVALUE) p->cb_printf (" ]");
2015-05-02 15:07:08 +02:00
}
} else if (MUSTSEEJSON) {
if (size==-1) {
2015-07-28 16:39:35 +02:00
r_uleb128_decode (buf+i, &s, &value);
p->cb_printf ("\"%"PFMT64d"\"", value);
2015-05-02 15:07:08 +02:00
sum = s;
} else {
p->cb_printf ("[ ");
2015-05-02 15:07:08 +02:00
while (size--) {
if (elem == -1 || elem == 0) {
r_uleb128_decode (buf+i, &s, &value);
sum += s;
p->cb_printf ("\"%"PFMT64d"\"", value);
2015-05-02 15:07:08 +02:00
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
2015-05-02 15:07:08 +02:00
if (elem > -1) elem--;
i+=s;
}
p->cb_printf (" ]");
2015-05-02 15:07:08 +02:00
}
p->cb_printf ("}");
2015-05-02 15:07:08 +02:00
}
return sum;
}
static void r_print_format_char(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
if (MUSTSET) {
p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*2:0));
if (size==-1)
p->cb_printf ("'%c'", IS_PRINTABLE (buf[i])?buf[i]:'.');
else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
if (elem == -1 || elem == 0) {
p->cb_printf ("'%c'", IS_PRINTABLE (buf[i])?buf[i]:'.');
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i++;
}
if (!SEEVALUE) p->cb_printf (" ]");
}
} else if (MUSTSEEJSON) {
if (size==-1)
p->cb_printf ("\"%c\"", IS_PRINTABLE (buf[i])?buf[i]:'.');
else {
p->cb_printf ("[ ");
while (size--) {
if (elem == -1 || elem == 0) {
p->cb_printf ("\"%c\"", IS_PRINTABLE (buf[i])?buf[i]:'.');
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i++;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
2014-08-01 19:33:52 +02:00
}
}
2015-03-03 01:03:49 +01:00
static void r_print_format_decchar(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
if (MUSTSET) {
p->cb_printf ("\"w %s\" @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem:0));
2015-03-03 01:03:49 +01:00
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem:0));
2015-03-03 01:03:49 +01:00
if (size==-1)
p->cb_printf ("%d", buf[i]);
2015-03-03 01:03:49 +01:00
else {
if (!SEEVALUE) p->cb_printf ("[ ");
2015-03-03 01:03:49 +01:00
while (size--) {
if (elem == -1 || elem == 0) {
p->cb_printf ("%d", buf[i]);
2015-03-03 01:03:49 +01:00
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
2015-03-03 01:03:49 +01:00
if (elem > -1) elem--;
i++;
}
if (!SEEVALUE) p->cb_printf (" ]");
2015-03-03 01:03:49 +01:00
}
} else if (MUSTSEEJSON) {
if (size==-1)
p->cb_printf ("\"%d\"", buf[i]);
2015-03-03 01:03:49 +01:00
else {
p->cb_printf ("[ ");
2015-03-03 01:03:49 +01:00
while (size--) {
if (elem == -1 || elem == 0) {
p->cb_printf ("\"%d\"", buf[i]);
2015-03-03 01:03:49 +01:00
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
2015-03-03 01:03:49 +01:00
if (elem > -1) elem--;
i++;
}
p->cb_printf (" ]");
2015-03-03 01:03:49 +01:00
}
p->cb_printf ("}");
2015-03-03 01:03:49 +01:00
}
}
static int r_print_format_string(const RPrint* p, ut64 seeki, ut64 addr64, ut64 addr, int is64, int mode) {
2014-08-01 19:33:52 +02:00
ut8 buffer[255];
2014-12-01 23:30:32 +01:00
buffer[0] = 0;
2014-08-01 19:33:52 +02:00
if (p->iob.read_at) {
if (is64 == 1)
p->iob.read_at (p->iob.io, addr64, buffer, sizeof (buffer)-8);
else
p->iob.read_at (p->iob.io, (ut64)addr, buffer, sizeof (buffer)-8);
} else {
eprintf ("(cannot read memory)\n");
2014-08-01 19:33:52 +02:00
return -1;
}
if (MUSTSEEJSON) {
p->cb_printf ("%d,\"string\":\"%s\"}", seeki, buffer);
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ", seeki, addr);
p->cb_printf ("%s", buffer);
2014-10-26 02:22:58 +02:00
}
2014-08-01 19:33:52 +02:00
return 0;
}
static void r_print_format_time(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
2014-10-31 02:09:08 +01:00
ut64 addr;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
2014-10-31 02:09:08 +01:00
updateAddr (buf, i, endian, &addr, NULL);
if (MUSTSET) {
p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
} else if (MUSTSEE) {
char *timestr = strdup(asctime (gmtime ((time_t*)&addr)));
*(timestr+24) = '\0';
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
if (size==-1) {
p->cb_printf ("%s", timestr);
} else {
if (!SEEVALUE) p->cb_printf ("[ ");
2014-10-31 02:09:08 +01:00
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
free (timestr);
timestr = strdup (asctime (gmtime ((time_t*)&addr)));
*(timestr+24) = '\0';
if (elem == -1 || elem == 0) {
p->cb_printf ("%s", timestr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i += 4;
2014-10-31 02:09:08 +01:00
}
if (!SEEVALUE) p->cb_printf (" ]");
2014-10-31 02:09:08 +01:00
}
free (timestr);
} else if (MUSTSEEJSON) {
char *timestr = strdup (asctime (gmtime ((time_t*)&addr)));
*(timestr+24) = '\0';
if (size==-1) {
p->cb_printf ("\"%s\"", timestr);
} else {
p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
free (timestr);
timestr = strdup (asctime (gmtime ((time_t*)&addr)));
*(timestr+24) = '\0';
if (elem == -1 || elem == 0) {
p->cb_printf ("\"%s\"", timestr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i += 4;
}
p->cb_printf (" ]");
}
free (timestr);
p->cb_printf ("}");
2014-10-31 02:09:08 +01:00
}
}
2014-08-01 19:33:52 +02:00
// TODO: support unsigned int?
static void r_print_format_hex(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
ut64 addr;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
updateAddr (buf, i, endian, &addr, NULL);
if (MUSTSET) {
p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
} else if (mode & R_PRINT_DOT) {
p->cb_printf ("%"PFMT64d, addr);
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
if (size==-1)
p->cb_printf ("%"PFMT64d, addr);
else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
if (elem == -1 || elem == 0) {
p->cb_printf ("%"PFMT64d, addr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i+=4;
}
if (!SEEVALUE) p->cb_printf (" ]");
}
} else if (MUSTSEEJSON) {
if (size==-1)
p->cb_printf ("%d", addr);
else {
p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
if (elem == -1 || elem == 0) {
p->cb_printf ("%d", addr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i+=4;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
2014-08-01 19:33:52 +02:00
}
}
2016-06-06 10:36:09 +02:00
static int r_print_format_disasm(const RPrint* p, ut64 seeki, int size) {
ut64 prevseeki = seeki;
if (!p->disasm || !p->user) return 0;
size = R_MAX (1, size);
while (size-- > 0) {
seeki += p->disasm (p->user, seeki);
}
return seeki - prevseeki;
}
static void r_print_format_octal (const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
ut64 addr;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
updateAddr (buf, i, endian, &addr, NULL);
if (MUSTSET) {
p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
2015-10-25 03:28:29 +01:00
} else if (mode & R_PRINT_DOT) {
p->cb_printf ("0%"PFMT64o, addr);
} else if (MUSTSEE) {
ut32 addr32 = (ut32)addr;
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
if (!SEEVALUE) p->cb_printf ("(octal) ");
if (size==-1)
2016-06-01 12:13:09 +02:00
p->cb_printf (" 0%08"PFMT64o, addr32);
else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
addr32 = (ut32)addr;
if (elem == -1 || elem == 0) {
p->cb_printf ("0%08"PFMT64o, addr32);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i+=4;
}
if (!SEEVALUE) p->cb_printf (" ]");
2014-10-26 02:22:58 +02:00
}
} else if (MUSTSEEJSON) {
ut32 addr32 = (ut32)addr;
if (size==-1)
p->cb_printf ("%d", addr32);
else {
p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
addr32 = (ut32)addr;
if (elem == -1 || elem == 0) {
p->cb_printf ("%d", addr32);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i+=4;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
}
}
static void r_print_format_hexflag(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
ut64 addr;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
updateAddr (buf, i, endian, &addr, NULL);
if (MUSTSET) {
p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
} else if (mode & R_PRINT_DOT) {
p->cb_printf ("0x%08"PFMT64x, addr & UT32_MAX);
} else if (MUSTSEE) {
2014-08-01 19:33:52 +02:00
ut32 addr32 = (ut32)addr;
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
if (size==-1) {
p->cb_printf ("0x%08"PFMT64x, addr32);
} else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
addr32 = (ut32)addr;
if (elem == -1 || elem == 0) {
p->cb_printf ("0x%08"PFMT64x, addr32);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i+=4;
}
if (!SEEVALUE) p->cb_printf (" ]");
}
} else if (MUSTSEEJSON) {
ut32 addr32 = (ut32)addr;
if (size==-1)
p->cb_printf ("%d", addr32);
else {
p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
addr32 = (ut32)addr;
if (elem == -1 || elem == 0) {
p->cb_printf ("%d", addr32);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (",");
if (elem > -1) elem--;
i+=4;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
2014-08-01 19:33:52 +02:00
}
}
static int r_print_format_10bytes(const RPrint* p, int mode, const char* setval,
ut64 seeki, ut64 addr, ut8* buf) {
2014-08-01 19:33:52 +02:00
ut8 buffer[255];
int j;
if (MUSTSET) {
p->cb_printf ("?e pf B not yet implemented\n");
2015-10-25 03:28:29 +01:00
} else if (mode & R_PRINT_DOT) {
for (j = 0; j<10; j++)
2015-10-25 03:28:29 +01:00
p->cb_printf ("%02x ", buf[j]);
} else if (MUSTSEE) {
2014-08-01 19:33:52 +02:00
if (!p->iob.read_at) {
printf ("(cannot read memory)\n");
return -1;
2016-06-01 12:13:09 +02:00
}
p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
2015-10-31 12:06:40 +01:00
for (j=0; j<10; j++)
p->cb_printf ("%02x ", buf[j]);
if (!SEEVALUE) p->cb_printf (" ... (");
for (j=0; j<10; j++) {
if (!SEEVALUE) {
if (IS_PRINTABLE (buf[j]))
p->cb_printf ("%c", buf[j]);
else
p->cb_printf (".");
}
}
if (!SEEVALUE) p->cb_printf (")");
} else if (MUSTSEEJSON) {
if (!p->iob.read_at) {
printf ("(cannot read memory)\n");
return -1;
} else
p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248);
p->cb_printf ("[ %d", buf[0]);
j=1;
for (; j<10; j++)
p->cb_printf (", %d", buf[j]);
p->cb_printf ("]}");
return 0;
2014-08-01 19:33:52 +02:00
}
return 0;
}
static int r_print_format_hexpairs(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
2014-08-02 02:19:43 +02:00
int j;
size = (size==-1) ? 1 : size;
if (MUSTSET) {
p->cb_printf ("?e pf X not yet implemented\n");
2015-10-25 03:28:29 +01:00
} else if (mode & R_PRINT_DOT) {
2016-06-01 12:13:09 +02:00
for (j = 0; j < size; j++)
p->cb_printf ("%02x", buf[i + j]);
} else if (MUSTSEE) {
2014-08-02 02:19:43 +02:00
size = (size < 1) ? 1 : size;
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
2016-06-01 12:13:09 +02:00
for (j = 0; j < size; j++) {
p->cb_printf ("%02x ", buf[i + j]);
}
if (!SEEVALUE) p->cb_printf (" ... (");
for (j=0; j<size; j++) {
if (!SEEVALUE) {
if (IS_PRINTABLE (buf[j]))
p->cb_printf ("%c", buf[i+j]);
else
p->cb_printf (".");
}
}
p->cb_printf (")");
} else if (MUSTSEEJSON) {
size = (size < 1) ? 1 : size;
p->cb_printf ("[ %d", buf[0]);
2016-06-01 12:13:09 +02:00
j = 1;
for (; j < 10; j++)
p->cb_printf (", %d", buf[j]);
p->cb_printf ("]}");
return size;
2014-08-02 02:19:43 +02:00
}
return size;
}
static void r_print_format_float(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
ut64 addr;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
updateAddr (buf, i, endian, &addr, NULL);
if (MUSTSET) {
p->cb_printf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*4:0));
2015-10-25 03:28:29 +01:00
} else if (mode & R_PRINT_DOT) {
//p->cb_printf ("%s", setval);
p->cb_printf ("%f", (float)addr);
} else {
if (MUSTSEE)
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*4:0));
if (size==-1)
p->cb_printf ("%f", (float)addr);
else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
updateAddr (buf, i, endian, &addr, NULL);
if (elem == -1 || elem == 0) {
p->cb_printf ("%f", (float)addr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
i+=4;
}
if (!SEEVALUE) p->cb_printf (" ]");
}
if (MUSTSEEJSON) p->cb_printf ("}");
}
}
static void r_print_format_word(const RPrint* p, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
ut64 addr;
int elem = -1;
if (size >= ARRAYINDEX_COEF) {
elem = size/ARRAYINDEX_COEF-1;
size %= ARRAYINDEX_COEF;
}
if (endian)
addr = (*(buf+i))<<8 | (*(buf+i+1));
else addr = (*(buf+i+1))<<8 | (*(buf+i));
if (MUSTSET) {
p->cb_printf ("wx %s @ 0x%08"PFMT64x"\n", setval, seeki+((elem>=0)?elem*2:0));
2015-10-25 03:28:29 +01:00
} else if (mode & R_PRINT_DOT) {
if (size==-1)
p->cb_printf ("0x%04x", addr);
while ((size-=2)>0) { //size--) {
2015-10-25 03:28:29 +01:00
if (endian)
addr = (*(buf+i))<<8 | (*(buf+i+1));
else addr = (*(buf+i+1))<<8 | (*(buf+i));
if (elem == -1 || elem == 0) {
p->cb_printf ("%d", addr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (",");
if (elem > -1) elem--;
i+=2;
}
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki+((elem>=0)?elem*2:0));
2015-10-25 03:28:29 +01:00
if (size==-1) {
p->cb_printf ("0x%04x", addr);
2015-10-25 03:28:29 +01:00
} else {
if (!SEEVALUE) p->cb_printf ("[ ");
while (size--) {
if (endian)
addr = (*(buf+i))<<8 | (*(buf+i+1));
else addr = (*(buf+i+1))<<8 | (*(buf+i));
if (elem == -1 || elem == 0) {
p->cb_printf ("0x%04x", addr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (", ");
if (elem > -1) elem--;
2015-10-25 03:28:29 +01:00
i += 2;
}
if (!SEEVALUE) p->cb_printf (" ]");
}
} else if (MUSTSEEJSON) {
if (size==-1)
p->cb_printf ("%d", addr);
else {
p->cb_printf ("[ ");
while (size-=2 >0) {
if (endian)
addr = (*(buf+i))<<8 | (*(buf+i+1));
else addr = (*(buf+i+1))<<8 | (*(buf+i));
if (elem == -1 || elem == 0) {
p->cb_printf ("%d", addr);
if (elem == 0) elem = -2;
}
if (size != 0 && elem == -1)
p->cb_printf (",");
if (elem > -1) elem--;
i+=2;
}
p->cb_printf (" ]");
}
p->cb_printf ("}");
}
2014-08-02 02:19:43 +02:00
}
static void r_print_format_nulltermstring(const RPrint* p, const int len, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
if (MUSTSET) {
int buflen = strlen ((const char *)buf+seeki), vallen = strlen(setval);
char *newstring, *ons;
newstring = ons = strdup(setval);
if ((newstring[0] == '\"' && newstring[vallen-1] == '\"')
|| (newstring[0] == '\'' && newstring[vallen-1] == '\'')) {
newstring[vallen-1] = '\0';
newstring++;
vallen-=2;
}
if (vallen > buflen) {
eprintf ("Warning: new string is longer than previous one\n");
}
p->cb_printf ("wx ");
for (i=0;i<vallen;i++) {
if (i < vallen-3 && newstring[i] == '\\' && newstring[i+1] == 'x') {
p->cb_printf ("%c%c", newstring[i+2], newstring[i+3]);
i+=3;
} else {
p->cb_printf ("%2x", newstring[i]);
}
}
p->cb_printf (" @ 0x%08"PFMT64x"\n", seeki);
free(ons);
} else if (mode & R_PRINT_DOT) {
int j = i;
p->cb_printf ("\\\"", seeki);
for (; j<len && ((size==-1 || size-- >0) && buf[j]) ; j++) {
char ch = buf[j];
if (ch == '"') {
p->cb_printf ("\\\"");
} else if (IS_PRINTABLE (ch)) {
p->cb_printf ("%c", ch);
} else p->cb_printf (".");
}
p->cb_printf ("\\\"");
} else if (MUSTSEE) {
int j = i;
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
for (; j<len && ((size==-1 || size-- >0) && buf[j]) ; j++) {
if (IS_PRINTABLE (buf[j]))
p->cb_printf ("%c", buf[j]);
else p->cb_printf (".");
}
} else if (MUSTSEEJSON) {
int j = i;
p->cb_printf ("%d,\"string\":\"", seeki);
for (; j<len && ((size==-1 || size-- >0) && buf[j]) ; j++) {
if (IS_PRINTABLE (buf[j]))
p->cb_printf ("%c", buf[j]);
else p->cb_printf (".");
}
p->cb_printf ("\"}");
}
}
static void r_print_format_nulltermwidestring(const RPrint* p, const int len, int endian, int mode,
const char* setval, ut64 seeki, ut8* buf, int i, int size) {
if (MUSTSET) {
int vallen = strlen(setval);
char *newstring, *ons;
newstring = ons = strdup(setval);
if ((newstring[0] == '\"' && newstring[vallen-1] == '\"')
|| (newstring[0] == '\'' && newstring[vallen-1] == '\'')) {
newstring[vallen-1] = '\0';
newstring++;
vallen-=2;
}
if ((size = strlen (setval)) > r_wstr_clen((char*)(buf+seeki)))
eprintf ("Warning: new string is longer than previous one\n");
p->cb_printf ("ww %s @ 0x%08"PFMT64x"\n", newstring, seeki);
free(ons);
} else if (MUSTSEE) {
int j = i;
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
2015-04-23 02:12:45 +02:00
for (; j<len && ((size==-1 || size-->0) && buf[j]) ; j+=2) {
if (IS_PRINTABLE (buf[j]))
p->cb_printf ("%c", buf[j]);
else p->cb_printf (".");
}
}
}
static void r_print_format_bitfield(const RPrint* p, ut64 seeki, char* fmtname,
char* fieldname, ut64 addr, int mode, int size) {
char *bitfield = NULL;
switch (size) {
case 1: addr &= UT8_MAX; break;
case 2: addr &= UT16_MAX; break;
case 4: addr &= UT32_MAX; break;
}
if (MUSTSEE)
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
if (p->get_bitfield)
bitfield = p->get_bitfield (p->user, fmtname, addr);
if (bitfield && *bitfield) {
if (MUSTSEEJSON) p->cb_printf ("\"%s\"}", bitfield);
else if (MUSTSEE) p->cb_printf (" %s (bitfield) = %s\n", fieldname, bitfield);
} else {
if (MUSTSEEJSON) p->cb_printf ("\"`tb %s 0x%x`\"}", fmtname, addr);
else if (MUSTSEE) p->cb_printf (" %s (bitfield) = `tb %s 0x%x`\n",
fieldname, fmtname, addr);
}
free (bitfield);
}
static void r_print_format_enum (const RPrint* p, ut64 seeki, char* fmtname,
char* fieldname, ut64 addr, int mode, int size) {
char *enumvalue = NULL;
switch (size) {
case 1: addr &= UT8_MAX; break;
case 2: addr &= UT16_MAX; break;
case 4: addr &= UT32_MAX; break;
}
if (MUSTSEE)
if (!SEEVALUE) p->cb_printf ("0x%08"PFMT64x" = ", seeki);
if (p->get_enumname)
enumvalue = p->get_enumname (p->user, fmtname, addr);
if (enumvalue && *enumvalue) {
if (mode & R_PRINT_DOT) {
p->cb_printf ("%s.%s", fmtname, enumvalue);
} else if (MUSTSEEJSON) p->cb_printf ("\"%s\"}", fmtname);
else if (MUSTSEE) p->cb_printf (" %s (enum) = 0x%"PFMT64x" ; %s\n",
fieldname, addr, enumvalue);
} else {
if (MUSTSEEJSON) p->cb_printf ("\"`te %s 0x%x`\"}", fmtname, addr);
else if (MUSTSEE) p->cb_printf (" %s (enum) = %s\n",//`te %s 0x%x`\n",
fieldname, enumvalue); //fmtname, addr);
}
free (enumvalue);
}
static void r_print_format_register (const RPrint* p, int mode,
const char *name, const char* setval) {
2015-07-24 17:04:33 +02:00
RRegItem *ri = p->get_register (p->reg, name, R_REG_TYPE_ALL);
2016-05-30 15:30:55 +02:00
if (ri) {
if (MUSTSET) {
p->cb_printf ("dr %s=%s\n", name, setval);
} else if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf("%s : 0x%08"PFMT64x"\n", ri->name, p->get_register_value (p->reg, ri));
else p->cb_printf("0x%08"PFMT64x"\n", p->get_register_value (p->reg, ri));
} else if (MUSTSEEJSON) {
p->cb_printf ("%d}", p->get_register_value (p->reg, ri));
}
} else {
p->cb_printf ("Register %s does not exists\n", name);
}
}
// XXX: this is very incomplete. must be updated to handle all format chars
2015-02-05 01:59:32 +01:00
int r_print_format_struct_size(const char *f, RPrint *p, int mode) {
2016-02-26 15:35:02 -05:00
char *o, *end, *args, *fmt;
2016-05-30 15:30:55 +02:00
int size = 0, tabsize = 0, i, idx = 0, biggest = 0;
2016-02-26 15:35:02 -05:00
if (!f) return -1;
2016-05-30 15:30:55 +02:00
o = strdup (f);
2016-05-24 21:22:15 +01:00
if (!o) return -1;
2016-02-26 15:35:02 -05:00
end = strchr (o, ' ');
fmt = o;
if (!end && !(end = strchr (o, '\0'))) {
free (o);
2014-08-31 02:09:35 +02:00
return -1;
}
2014-11-26 01:03:48 +01:00
if (*end) {
*end = 0;
2016-05-30 15:30:55 +02:00
args = strdup (end + 1);
2014-11-26 01:03:48 +01:00
} else {
args = strdup ("");
}
2015-02-05 01:59:32 +01:00
if (fmt[0] == '0') {
mode |= R_PRINT_UNIONMODE;
fmt++;
} else {
mode &= ~R_PRINT_UNIONMODE;
}
2014-10-01 10:48:43 +02:00
r_str_word_set0 (args);
2014-11-01 22:12:05 +01:00
for (i=0; i<strlen (fmt); i++) {
2014-10-07 17:51:15 +02:00
if (fmt[i] == '[') {
char *end = strchr (fmt+i,']');
if (end == NULL) {
eprintf ("No end bracket.\n");
continue;
}
*end = '\0';
tabsize = r_num_math (NULL, fmt+i+1);
*end = ']';
while (fmt[i++]!=']');
} else {
tabsize = 1;
}
switch (fmt[i]) {
case 'c':
2014-11-01 03:48:41 +01:00
case 'b':
2014-10-07 17:51:15 +02:00
case '.':
case 'X':
size += tabsize*1;
2014-08-07 23:59:43 +02:00
break;
case 'w':
2014-10-07 17:51:15 +02:00
size += tabsize*2;
break;
case 'd':
2014-11-01 03:48:41 +01:00
case 'o':
2014-10-07 17:51:15 +02:00
case 'i':
case 'x':
case 'f':
case 's':
2014-11-01 03:48:41 +01:00
case 't':
case ':':
2014-10-07 17:51:15 +02:00
size += tabsize*4;
break;
2014-10-07 17:51:15 +02:00
case 'S':
case 'q':
size += tabsize*8;
break;
2014-11-01 03:48:41 +01:00
case 'z':
case 'Z':
size += tabsize;
break;
2014-08-07 23:59:43 +02:00
case '*':
2014-10-07 17:51:15 +02:00
size += tabsize*4;
2014-08-07 23:59:43 +02:00
i++;
break;
case 'B':
case 'E':
switch (tabsize) {
case 1: size+=1; break;
case 2: size+=2; break;
case 4: size+=4; break;
default: break;
}
break;
2014-10-01 10:48:43 +02:00
case '?':
{
const char *format = NULL;
char *endname = NULL, *structname = NULL;
2016-05-30 15:30:55 +02:00
structname = strdup (r_str_word_get0 (args, idx));
2014-10-01 10:48:43 +02:00
if (*structname == '(') {
endname = strchr (structname, ')');
} else {
eprintf ("Struct name missing (%s)\n", structname);
2016-05-30 15:30:55 +02:00
free (structname);
2014-10-01 10:48:43 +02:00
break;
}
if (endname) *endname = '\0';
2016-05-30 15:30:55 +02:00
format = r_strht_get (p->formats, structname + 1);
2014-10-01 10:48:43 +02:00
free (structname);
2015-02-05 01:59:32 +01:00
size += tabsize * r_print_format_struct_size (format, p, mode);
2014-10-01 10:48:43 +02:00
}
2015-02-05 01:59:32 +01:00
break;
2014-08-07 23:59:43 +02:00
// TODO continue list
default:
break;
}
2014-10-01 10:48:43 +02:00
idx++;
2015-02-05 01:59:32 +01:00
if (mode & R_PRINT_UNIONMODE) {
if (size > biggest) biggest = size;
size = 0;
}
2014-08-07 23:59:43 +02:00
}
free (o);
2014-10-01 10:48:43 +02:00
free (args);
return (mode & R_PRINT_UNIONMODE)? biggest: size;
2014-08-07 23:59:43 +02:00
}
static int r_print_format_struct(RPrint* p, ut64 seek, const ut8* b, int len,
char *name, int slide, int mode, const char *setval, char *field) {
const char *fmt;
2016-06-01 12:13:09 +02:00
char namefmt[128];
2016-05-30 15:30:55 +02:00
if ((slide % STRUCTPTR) > NESTDEPTH || (slide%STRUCTFLAG)/STRUCTPTR > NESTDEPTH) {
eprintf ("Too much nested struct, recursion too deep...\n");
2014-08-07 23:59:43 +02:00
return 0;
}
fmt = r_strht_get (p->formats, name);
2014-09-20 22:58:46 +02:00
if (!fmt || !*fmt) {
2014-09-23 15:24:56 +02:00
eprintf ("Undefined struct '%s'.\n", name);
2014-09-20 22:58:46 +02:00
return 0;
}
if (MUSTSEE && !SEEVALUE) {
2015-02-05 02:31:02 +01:00
snprintf (namefmt, sizeof (namefmt), "%%%ds", 10+6*slide%STRUCTPTR);
if (fmt[0] == '0')
p->cb_printf (namefmt, "union");
2015-10-25 03:28:29 +01:00
else p->cb_printf (namefmt, "struct");
p->cb_printf ("<%s>\n", name);
2015-02-05 02:31:02 +01:00
}
r_print_format (p, seek, b, len, fmt, mode, setval, field);
2016-06-01 12:13:09 +02:00
return r_print_format_struct_size (fmt, p, mode);
2014-08-07 23:59:43 +02:00
}
2016-02-08 11:36:34 +01:00
static char* get_args_offset( const char *arg ) {
char *args = strchr (arg, ' ');
char *sq_bracket = strchr (arg, '[');
int max = 30;
if (args && sq_bracket) {
char *csq_bracket = strchr(arg, ']');
while (args && csq_bracket && csq_bracket > args && max--) {
args = strchr (csq_bracket, ' ');
}
}
return args;
}
2014-12-22 11:55:07 +01:00
#define MINUSONE ((void*)(size_t)-1)
2014-11-09 20:56:22 +01:00
#define ISSTRUCT (tmp == '?' || (tmp == '*' && *(arg+1) == '?'))
2015-07-28 18:28:33 +02:00
R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, const int len,
2015-03-03 00:34:09 +01:00
const char *formatname, int mode, const char *setval, char *ofield) {
int nargs, i, j, invalid, nexti, idx, times, otimes, endian, isptr = 0;
2016-01-07 16:29:04 +01:00
const int old_bits = p->bits;
2015-03-05 23:50:46 +01:00
char *args = NULL, *bracket, tmp, last = 0;
ut64 addr = 0, addr64 = 0, seeki = 0;
static int slide = 0, oldslide = 0;
char namefmt[8], *field = NULL;
2015-03-03 00:34:09 +01:00
const char *arg = NULL;
const char *fmt = NULL;
const char *argend;
2015-07-28 18:28:33 +02:00
int viewflags = 0;
char *oarg = NULL;
2014-08-01 19:33:52 +02:00
ut8 *buf;
2015-07-24 17:04:33 +02:00
/* Load format from name into fmt */
if (!formatname) return 0;
2015-03-05 23:50:46 +01:00
fmt = r_strht_get (p->formats, formatname);
2015-10-25 03:28:29 +01:00
if (!fmt) fmt = formatname;
2015-07-24 17:04:33 +02:00
while (*fmt && iswhitechar (*fmt)) fmt++;
2014-12-19 13:16:04 +01:00
argend = fmt+strlen (fmt);
2015-03-05 23:50:46 +01:00
arg = fmt;
2015-01-29 03:01:44 +01:00
2014-08-02 14:47:45 +02:00
nexti = nargs = i = j = 0;
if (len < 1) return 0;
2015-06-27 19:36:30 +02:00
// len+2 to save space for the null termination in wide strings
buf = calloc (1,len + 2);
if (!buf) return 0;
memcpy (buf, b, len);
2013-02-22 21:05:08 +01:00
endian = p->big_endian;
2014-12-22 11:55:07 +01:00
if (ofield && ofield != MINUSONE) field = strdup (ofield);
/* get times */
otimes = times = atoi (arg);
if (times > 0) {
while (*arg >= '0' && *arg <= '9') arg++;
}
2014-08-02 02:19:43 +02:00
bracket = strchr (arg,'{');
if (bracket) {
char *end = strchr (arg, '}');
if (end == NULL) {
eprintf ("No end bracket. Try pm {ecx}b @ esi\n");
goto beach;
}
2015-10-25 03:28:29 +01:00
*end = '\0';
2016-06-01 12:13:09 +02:00
times = r_num_math (NULL, bracket + 1);
arg = end + 1;
}
2016-06-01 12:13:09 +02:00
if (*arg == '\0') {
goto beach;
}
2014-08-02 02:19:43 +02:00
/* get args */
2016-02-08 11:36:34 +01:00
args = get_args_offset (arg);
if (args) {
2016-06-01 12:13:09 +02:00
int l = 0, maxl = 0;
argend = args;
2016-06-01 12:13:09 +02:00
args = strdup (args + 1);
2014-07-27 20:06:09 +02:00
nargs = r_str_word_set0 (args);
2016-06-01 12:13:09 +02:00
if (nargs == 0) {
R_FREE (args);
2016-06-01 12:13:09 +02:00
}
for (i = 0; i < nargs; i++) {
2014-08-02 02:19:43 +02:00
const int len = strlen (r_str_word_get0 (args, i));
2016-06-01 12:13:09 +02:00
if (len > maxl) {
2014-08-02 02:19:43 +02:00
maxl = len;
2016-06-01 12:13:09 +02:00
}
}
l++;
2016-06-01 12:13:09 +02:00
const char *ends = " "; // XXX trailing space warning
snprintf (namefmt, sizeof (namefmt), "%%%ds :%s",
maxl + 6 * slide % STRUCTPTR, ends);
}
2014-10-26 02:22:58 +02:00
#define ISPOINTED ((slide%STRUCTFLAG)/STRUCTPTR<=(oldslide%STRUCTFLAG)/STRUCTPTR)
#define ISNESTED ((slide%STRUCTPTR)<=(oldslide%STRUCTPTR))
2016-06-01 12:13:09 +02:00
if (mode == R_PRINT_JSON && slide == 0) {
p->cb_printf ("[");
}
2015-02-05 01:59:32 +01:00
if (arg[0] == '0') {
mode |= R_PRINT_UNIONMODE;
arg++;
} else {
mode &= ~R_PRINT_UNIONMODE;
}
if (mode & R_PRINT_DOT) {
char *fmtname;
if (formatname && *formatname) {
if (strchr (formatname, ' ')) {
fmtname = r_str_newf ("0x%"PFMT64x, seek);
} else {
fmtname = strdup (formatname);
}
} else {
fmtname = r_str_newf ("0x%"PFMT64x, seek);
}
p->cb_printf ("digraph g { graph [ rank=same; rankdir=LR; ];\n");
p->cb_printf ("root [ rank=1; shape=record\nlabel=\"%s", fmtname);
}
2015-01-29 03:01:44 +01:00
/* go format */
i = 0;
2016-06-01 12:13:09 +02:00
if (!times) {
2014-08-02 02:19:43 +02:00
otimes = times = 1;
2016-06-01 12:13:09 +02:00
}
for (; times; times--) { // repeat N times
const char * orig = arg;
2014-10-26 02:22:58 +02:00
int first = 1;
2016-06-01 12:13:09 +02:00
if (otimes > 1) {
if (mode & R_PRINT_JSON) {
if (otimes > times) p->cb_printf (",");
p->cb_printf ("[{\"index\":%d,\"offset\":%d},", otimes-times, seek+i);
} else {
p->cb_printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times);
}
2014-10-26 02:22:58 +02:00
}
arg = orig;
2016-06-01 12:13:09 +02:00
for (idx = 0; i < len && arg < argend && *arg; arg++) {
2015-03-18 00:59:26 +01:00
int size = 0, elem = 0; /* size of the array, element of the array */
char *fieldname = NULL, *fmtname = NULL;
2015-02-05 01:59:32 +01:00
if (mode & R_PRINT_UNIONMODE) {
i = 0;
}
2016-06-01 12:13:09 +02:00
seeki = seek + i;
addr = 0LL;
invalid = 0;
2016-01-07 16:29:04 +01:00
p->bits = old_bits;
2014-07-16 23:11:33 +02:00
if (arg[0] == '[') {
char *end = strchr (arg,']');
2016-06-01 12:13:09 +02:00
if (!end) {
2014-07-16 23:11:33 +02:00
eprintf ("No end bracket.\n");
goto beach;
}
*end = '\0';
size = r_get_size (p->num, buf, endian, arg+1);
2014-07-16 23:11:33 +02:00
arg = end + 1;
*end = ']';
2014-07-16 23:11:33 +02:00
} else {
size = -1;
}
if (i+7<len) { // Max byte number where updateAddr will look into
2015-06-27 19:36:30 +02:00
updateAddr (buf, i, endian, &addr, &addr64);
} else {
2015-07-23 19:07:26 +02:00
eprintf ("Likely a heap buffer overflow in %s at %d\n", __FILE__, __LINE__);
2015-06-27 19:36:30 +02:00
goto beach;
}
2014-08-01 00:15:17 +02:00
tmp = *arg;
2014-07-30 18:01:33 +02:00
2016-06-01 12:13:09 +02:00
if (args == NULL) {
mode |= R_PRINT_ISFIELD;
2016-06-01 12:13:09 +02:00
}
if (mode & R_PRINT_MUSTSEE && otimes > 1) {
p->cb_printf (" ");
}
if (idx < nargs && tmp != 'e' && isptr == 0) {
char *dot = NULL, *bracket = NULL;
if (field)
dot = strchr (field, '.');
if (dot)
*dot = '\0';
2016-06-01 12:13:09 +02:00
free (oarg);
oarg = fieldname = strdup (r_str_word_get0 (args, idx));
if (ISSTRUCT || tmp=='E' || tmp=='B' || tmp=='r') {
if (*fieldname == '(') {
fmtname = fieldname+1;
fieldname = strchr (fieldname, ')');
if (fieldname) *fieldname++ = '\0';
else {
eprintf ("Missing closing parenthesis in format ')'\n");
goto beach;
}
} else {
eprintf ("Missing name (%s)\n", fieldname);
goto beach;
}
}
2016-06-01 12:13:09 +02:00
if (!args || (!field && ofield != MINUSONE)
|| (field && !strncmp (field, fieldname, \
strchr (field, '[')
? strchr (field, '[') - field
: strlen (field) + 1))) {
mode |= R_PRINT_ISFIELD;
} else {
mode &= ~R_PRINT_ISFIELD;
}
2015-07-23 17:10:34 +02:00
/* There we handle specific element in array */
2016-06-01 12:13:09 +02:00
if (field && (bracket = strchr (field, '[')) && mode & R_PRINT_ISFIELD) {
char *end = strchr (field, ']');
2016-06-01 12:13:09 +02:00
if (!end) {
eprintf ("Missing closing bracket\n");
goto beach;
}
*end = '\0';
elem = r_num_math (NULL, bracket+1)+1; // +1 to handle 0 index easily
for ( ; bracket < end; bracket++)
*bracket = '\0';
size += elem*ARRAYINDEX_COEF;
} else {
elem = -1;
}
idx++;
if (MUSTSEE && !SEEVALUE) {
p->cb_printf (namefmt, fieldname);
2014-07-27 20:04:27 +02:00
}
}
feed_me_again:
switch (isptr) {
2016-01-07 16:29:04 +01:00
case PTRSEEK:
2014-08-07 23:59:43 +02:00
{
nexti = i + (p->bits/8);
i = 0;
if (tmp == '?' ) seeki = addr;
memset (buf, '\0', len);
2016-06-01 12:13:09 +02:00
if (MUSTSEE) {
p->cb_printf ("(*0x%"PFMT64x")", addr);
}
isptr = (addr)? PTRBACK: NULLPTR;
2015-01-29 03:01:44 +01:00
if (/*addr<(b+len) && addr>=b && */p->iob.read_at) { /* The test was here to avoid segfault in the next line,
2014-09-14 15:17:45 +02:00
but len make it doesnt work... */
p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4);
2016-06-01 12:13:09 +02:00
if ( (i + 3) < len || (i + 7) < len) {
2015-06-27 19:36:30 +02:00
updateAddr (buf, i, endian, &addr, &addr64);
2016-06-01 12:13:09 +02:00
} else {
2015-06-27 19:36:30 +02:00
eprintf ("Likely a heap buffer overflow at %s at %d\n", __FILE__, __LINE__);
goto beach;
}
} else {
2014-08-31 16:10:38 +04:00
eprintf ("(SEGFAULT: cannot read memory at 0x%08"PFMT64x", Block: %s, blocksize: 0x%x)\n",
2014-08-07 23:59:43 +02:00
addr, b, len);
2016-06-01 12:13:09 +02:00
p->cb_printf ("\n");
2014-08-07 23:59:43 +02:00
goto beach;
}
}
break;
2016-01-07 16:29:04 +01:00
case PTRBACK:
// restore state after pointer seek
i = nexti;
memcpy (buf, b, len);
isptr = NOPTR;
arg--;
continue;
}
2016-06-01 12:13:09 +02:00
if (tmp == 0 && last != '*') {
break;
2016-06-01 12:13:09 +02:00
}
2014-08-02 02:19:43 +02:00
/* skip chars */
switch (tmp) {
2014-08-02 14:47:45 +02:00
case '*': // next char is a pointer
isptr = PTRSEEK;
arg++;
tmp = *arg; //last;
goto feed_me_again;
2014-08-02 02:19:43 +02:00
case '+': // toggle view flags
viewflags = !viewflags;
continue;
case 'e': // tmp swap endian
endian ^= 1;
continue;
2014-08-02 02:19:43 +02:00
case ':': // skip 4 bytes
if (size == -1) i+=4;
else while (size--) i+=4;
continue;
2014-08-02 02:19:43 +02:00
case '.': // skip 1 byte
2016-06-01 12:13:09 +02:00
i += (size == -1)? 1: size;
continue;
2014-08-02 02:19:43 +02:00
case 'p': // pointer reference
2016-01-07 16:29:04 +01:00
if (*(arg+1) == '2') {
p->bits = 16;
arg++;
} else if (*(arg+1) == '4') {
p->bits = 32;
arg++;
} else if (*(arg+1) == '8') {
p->bits = 64;
arg++;
}
switch (p->bits) {
case 16: tmp = 'w'; break;
case 32: tmp = 'x'; break;
default: tmp = 'q'; break;
}
break;
}
2015-03-03 00:34:09 +01:00
2015-01-29 03:01:44 +01:00
/* flags */
if (mode & R_PRINT_SEEFLAGS && isptr != NULLPTR) {
2016-04-03 01:43:16 +02:00
char *newname = NULL;
if (!fieldname) {
newname = fieldname = r_str_newf ("pf.%d", seeki);
}
2015-03-18 00:59:26 +01:00
if (mode & R_PRINT_UNIONMODE) {
p->cb_printf ("f %s=0x%08"PFMT64x"\n", formatname, seeki);
2015-03-18 00:59:26 +01:00
goto beach;
} else if (tmp == '?') {
p->cb_printf ("f %s.%s_", fmtname, fieldname);
2014-10-26 02:41:28 +02:00
} else if (tmp == 'E') {
p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname, seeki);
2015-01-29 03:01:44 +01:00
} else if (slide/STRUCTFLAG>0 && idx==1) {
p->cb_printf ("%s=0x%08"PFMT64x"\n", fieldname, seeki);
} else p->cb_printf ("f %s=0x%08"PFMT64x"\n", fieldname , seeki);
2016-04-03 01:43:16 +02:00
if (newname) {
free (newname);
newname = fieldname = NULL;
}
}
2015-03-03 00:34:09 +01:00
/* dot */
if (mode & R_PRINT_DOT) {
if (fieldname) {
p->cb_printf ("|{0x%"PFMT64x"|%c|%s|<%s>",
seeki, tmp, fieldname, fieldname);
} else {
p->cb_printf ("|{0x%"PFMT64x"|%c|",
seeki, tmp);
}
}
2015-01-29 03:01:44 +01:00
/* json */
if (MUSTSEEJSON && mode & R_PRINT_JSON) {
if (oldslide <= slide) {
if (first) first = 0;
else p->cb_printf (",");
} else if (oldslide) {
p->cb_printf ("]},");
2014-10-26 02:22:58 +02:00
}
p->cb_printf ("{\"name\":\"%s\",\"type\":\"", fieldname);
2014-10-26 02:22:58 +02:00
if (ISSTRUCT) {
p->cb_printf ("%s", fmtname);
2014-10-26 02:22:58 +02:00
} else {
p->cb_printf ("%c", tmp);
2014-10-26 02:22:58 +02:00
}
if (isptr) p->cb_printf ("*");
p->cb_printf ("\",\"offset\":%d,\"value\":",(isptr)?(seek+nexti-(p->bits/8)):seek+i);
2014-10-26 02:22:58 +02:00
}
2014-07-27 20:04:27 +02:00
if (isptr == NULLPTR) {
if (MUSTSEEJSON) p->cb_printf ("\"NULL\"}", tmp, seek+i);
2016-06-01 12:13:09 +02:00
else if (MUSTSEE) p->cb_printf (" NULL\n");
isptr = PTRBACK;
2014-08-07 23:59:43 +02:00
} else
2014-10-26 16:26:03 +01:00
/* format chars */
2015-06-27 19:36:30 +02:00
// before to enter in the switch statement check buf boundaries due to updateAddr
// might go beyond its len and it's usually called in each of the following functions
if (((i+3)<len) || (i+7)<len) {
switch (tmp) {
case 'u':
i+= r_print_format_uleb (p, endian, mode, setval, seeki, buf, i, size);
2015-06-27 19:36:30 +02:00
break;
case 't':
r_print_format_time (p, endian, mode, setval, seeki, buf, i, size);
2015-06-27 19:36:30 +02:00
i+= (size==-1) ? 4 : 4*size;
break;
case 'q':
r_print_format_quadword (p, endian, mode, setval, seeki, buf, i, size);
2014-09-14 15:17:45 +02:00
i += (size==-1) ? 8 : 8*size;
2015-06-27 19:36:30 +02:00
break;
case 'b':
r_print_format_byte (p, endian, mode, setval, seeki, buf, i, size);
2015-06-27 19:36:30 +02:00
i+= (size==-1) ? 1 : size;
break;
case 'C':
r_print_format_decchar (p, endian, mode,
setval, seeki, buf, i, size);
i+= (size==-1) ? 1 : size;
break;
case 'c':
r_print_format_char (p, endian, mode,
setval, seeki, buf, i, size);
i+= (size==-1) ? 1 : size;
break;
case 'X':
size = r_print_format_hexpairs (p, endian, mode,
setval, seeki, buf, i, size);
i += size;
break;
case 'T':
if (r_print_format_10bytes (p, mode,
2015-06-27 19:36:30 +02:00
setval, seeki, addr, buf) == 0)
i += (size==-1) ? 4 : 4*size;
break;
case 'f':
r_print_format_float (p, endian, mode, setval, seeki, buf, i, size);
2015-06-27 19:36:30 +02:00
i += (size==-1) ? 4 : 4*size;
break;
case 'i':
case 'd':
r_print_format_hex (p, endian, mode, setval, seeki, buf, i, size);
2015-06-27 19:36:30 +02:00
i+= (size==-1) ? 4 : 4*size;
break;
case 'D':
2016-06-06 10:36:09 +02:00
i += r_print_format_disasm (p, seeki, size);
2015-06-27 19:36:30 +02:00
break;
case 'o':
r_print_format_octal (p, endian, mode, setval, seeki, buf, i, size);
2016-06-01 12:13:09 +02:00
i += (size==-1) ? 4 : 4*size;
2015-06-27 19:36:30 +02:00
break;
case 'x':
r_print_format_hexflag (p, endian, mode, setval, seeki, buf, i, size);
2016-06-01 12:13:09 +02:00
i += (size==-1) ? 4 : 4*size;
2015-06-27 19:36:30 +02:00
break;
case 'w':
r_print_format_word(p, endian, mode, setval, seeki, buf, i, size);
2016-06-01 12:13:09 +02:00
i += (size==-1) ? 2 : 2*size;
2015-06-27 19:36:30 +02:00
break;
case 'z': // zero terminated string
r_print_format_nulltermstring (p, len, endian, mode, setval, seeki, buf, i, size);
if (size == -1)
i+=strlen((char*)buf+i)+1;
2014-10-26 02:22:58 +02:00
else
2015-06-27 19:36:30 +02:00
while (size--) i++;
break;
case 'Z': // zero terminated wide string
r_print_format_nulltermwidestring (p, len, endian, mode, setval, seeki, buf, i, size);
if (size == -1)
i += r_wstr_clen((char*)(buf+i))*2+2;
2015-06-27 19:36:30 +02:00
else
while (size--) i+=2;
break;
case 's':
if (r_print_format_string (p, seeki, addr64, addr, 0, mode) == 0)
i += (size==-1) ? 4 : 4*size;
break;
case 'S':
if (r_print_format_string (p, seeki, addr64, addr, 1, mode) == 0)
i += (size==-1) ? 8 : 8*size;
break;
case 'B': // resolve bitfield
if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF;
r_print_format_bitfield (p, seeki, fmtname, fieldname, addr, mode, size);
i+=(size==-1)?1:size;
break;
case 'E': // resolve enum
if (size >= ARRAYINDEX_COEF) size %= ARRAYINDEX_COEF;
r_print_format_enum (p, seeki, fmtname, fieldname, addr, mode, size);
2016-06-01 12:13:09 +02:00
i += (size==-1)? 1: size;
2015-06-27 19:36:30 +02:00
break;
case 'r':
r_print_format_register (p, mode, fmtname, setval);
break;
2015-06-27 19:36:30 +02:00
case '?':
{
int s = 0;
char *nxtfield = NULL;
if (size >= ARRAYINDEX_COEF) {
2016-06-01 12:13:09 +02:00
elem = size / ARRAYINDEX_COEF - 1;
2015-06-27 19:36:30 +02:00
size %= ARRAYINDEX_COEF;
}
if (!(mode & R_PRINT_ISFIELD)) nxtfield = MINUSONE;
else if (field) nxtfield = strchr (ofield, '.');
2016-06-01 12:13:09 +02:00
if (nxtfield != MINUSONE && nxtfield) nxtfield++;
2016-01-07 16:29:04 +01:00
2016-06-01 12:13:09 +02:00
if (MUSTSEE) {
if (!SEEVALUE) p->cb_printf ("\n");
2016-06-01 12:13:09 +02:00
}
2015-06-27 19:36:30 +02:00
if (MUSTSEEJSON) {
if (isptr)
p->cb_printf ("%d},", seeki);
2015-06-27 19:36:30 +02:00
else
p->cb_printf ("[");
2015-06-27 19:36:30 +02:00
}
2016-06-01 12:13:09 +02:00
if (mode & R_PRINT_SEEFLAGS) slide += STRUCTFLAG;
2015-06-27 19:36:30 +02:00
oldslide = slide;
slide += (isptr) ? STRUCTPTR : NESTEDSTRUCT;
if (size == -1) {
s = r_print_format_struct (p, seeki,
buf+i, len-i, fmtname, slide,
mode, setval, nxtfield);
2014-10-07 17:51:15 +02:00
i+= (isptr) ? 4 : s;
2015-06-27 19:36:30 +02:00
} else {
if (mode & R_PRINT_ISFIELD)
if (!SEEVALUE) p->cb_printf ("[\n");
2015-06-27 19:36:30 +02:00
while (size--) {
if (elem == -1 || elem == 0) {
mode |= R_PRINT_MUSTSEE;
if (elem == 0) elem = -2;
} else {
mode &= ~R_PRINT_MUSTSEE;
}
s = r_print_format_struct (p, seek+i,
buf+i, len-i, fmtname, slide, mode, setval, nxtfield);
if ((MUSTSEE || MUSTSEEJSON) && size != 0 && elem == -1) {
p->cb_printf (",");
if (MUSTSEE) p->cb_printf ("\n");
2015-06-27 19:36:30 +02:00
}
if (elem > -1) elem--;
i+= (isptr) ? 4 : s;
}
if (mode & R_PRINT_ISFIELD)
if (!SEEVALUE) p->cb_printf ("]");
if (MUSTSEEJSON) p->cb_printf ("]}]}");
2014-10-07 17:51:15 +02:00
}
2014-10-26 02:22:58 +02:00
oldslide = slide;
2015-06-27 19:36:30 +02:00
slide -= (isptr) ? STRUCTPTR : NESTEDSTRUCT;
if (mode & R_PRINT_SEEFLAGS) {
oldslide = slide;
slide-=STRUCTFLAG;
}
break;
}
default:
/* ignore unknown chars */
invalid = 1;
break;
} //switch
} else {
2015-07-23 19:07:26 +02:00
eprintf ("Likely a heap buffer overflow in %s at %d\n", __FILE__, __LINE__);
2015-06-27 19:36:30 +02:00
goto beach;
}
if (mode & R_PRINT_DOT) {
p->cb_printf ("}");
}
if (viewflags && p->offname) {
const char *s = p->offname (p->user, seeki);
2016-06-01 12:13:09 +02:00
if (s) p->cb_printf ("@(%s)", s);
s = p->offname (p->user, addr);
2016-06-01 12:13:09 +02:00
if (s) p->cb_printf ("*(%s)", s);
}
2016-06-01 12:13:09 +02:00
if (tmp != 'D' && !invalid && !fmtname && MUSTSEE) {
p->cb_printf ("\n");
2016-06-01 12:13:09 +02:00
}
last = tmp;
}
2016-06-01 12:13:09 +02:00
if (otimes > 1) {
if (MUSTSEEJSON) p->cb_printf ("]");
else p->cb_printf ("}\n");
}
arg = orig;
2014-10-26 02:22:58 +02:00
oldslide = 0;
}
2016-06-01 12:13:09 +02:00
if (mode & R_PRINT_JSON && slide==0) {
p->cb_printf("]\n");
}
if (mode & R_PRINT_DOT) {
p->cb_printf ("\"];\n}\n");
// TODO: show nested structs and field reference lines
}
beach:
2015-06-27 19:36:30 +02:00
free (oarg);
free (buf);
free (field);
free (args);
return i;
}