/* radare - LGPL - Copyright 2007-2013 - pancake */ #if 0 # TEST DAT PTR SHIT e asm.bits=32 wv 0x10 wv 0x10 @ 4 w hello @ 0x10 pf ss pf *x*x pf *z*z #endif #include "r_cons.h" #include "r_util.h" #include "r_print.h" static int nullprintf(const char *fmt, ...) { return 0; } static void print_format_help(RPrint *p) { p->printf ( "Usage: pf[.key[.field[=value]]|[ val]]|[times][format] [arg0 arg1 ...]\n" "Examples:\n" " pf 10xiz pointer length string\n" " pf {array_size}b @ array_base\n" " pf. # list all formats\n" " pf.obj xxdz prev next size name\n" " pf.obj # run stored format\n" " pf.obj.name # show string inside object\n" " pf.obj.size=33 # set new size\n" "Format chars:\n" " e - temporally swap endian\n" //" D - double (8 bytes)\n" " f - float value (4 bytes)\n" " c - char (signed byte)\n" " b - byte (unsigned)\n" " B - show 10 first bytes of buffer\n" // B must be for binary ?? " i - %%i integer value (4 bytes)\n" " w - word (2 bytes unsigned short in hex)\n" " q - quadword (8 bytes)\n" " p - pointer reference (2, 4 or 8 bytes)\n" " d - 0x%%08x hexadecimal value (4 bytes)\n" " D - disassemble one opcode\n" " x - 0x%%08x hexadecimal value and flag (fd @ addr)\n" " z - \\0 terminated string\n" " Z - \\0 terminated wide string\n" " s - 32bit pointer to string (4 bytes)\n" " S - 64bit pointer to string (8 bytes)\n" //" t - unix timestamp string\n" " * - next char is pointer (honors asm.bits)\n" " + - toggle show flags for each offset\n" " : - skip 4 bytes\n" " . - skip 1 byte\n"); } /* TODO: needs refactoring */ R_API int r_print_format(RPrint *p, ut64 seek, const ut8* b, int len, const char *fmt, int elem, const char *setval) { int nargs, i, j, nexti, idx, times, otimes, endian, isptr = 0; int (*realprintf)(const char *str, ...); int (*oldprintf)(const char *str, ...); const char *argend = fmt+strlen (fmt); ut64 addr = 0, addr64 = 0, seeki = 0;; char *args = NULL, *bracket, tmp, last = 0; const char *arg = fmt; int viewflags = 0; char namefmt[8]; ut8 *buf, buffer[256]; nexti = nargs = endian = i = j = 0; if (len<1) return 0; buf = malloc (len); if (!buf) return 0; memcpy (buf, b, len); endian = p->big_endian; oldprintf = NULL; realprintf = p->printf; while (*arg && iswhitechar (*arg)) arg++; /* get times */ otimes = times = atoi (arg); if (times > 0) while ((*arg>='0'&&*arg<='9')) arg++; bracket = strchr (arg,'{'); if (bracket) { char *end = strchr (arg,'}'); if (end == NULL) { eprintf ("No end bracket. Try pm {ecx}b @ esi\n"); goto beach; } *end='\0'; times = r_num_math (NULL, bracket+1); arg = end + 1; } if (*arg=='\0') { print_format_help (p); goto beach; } /* get args */ args = strchr (arg, ' '); if (args) { int l=0, maxl = 0; argend = args; args = strdup (args+1); nargs = r_str_word_set0 (args+1); if (nargs == 0) R_FREE (args); for (i=0; imaxl) maxl = len; } l++; snprintf (namefmt, sizeof (namefmt), "%%%ds : ", maxl); } /* go format */ i = 0; if (!times) otimes = times = 1; for (; times; times--) { // repeat N times const char * orig = arg; if (otimes>1) p->printf ("0x%08"PFMT64x" [%d] {\n", seek+i, otimes-times); idx = 0; arg = orig; for (idx=0; ibits/8); i = 0; tmp = *arg; memset (buf, '\0', len); p->printf ("(*0x%"PFMT64x") ", addr); if (p->iob.read_at) { p->iob.read_at (p->iob.io, (ut64)addr, buf, len-4); } else { eprintf ("(cannot read memory)\n"); break; } isptr = 2; break; case 2: // restore state after pointer seek i = nexti; seeki = seek+i; memcpy (buf, b, len); isptr = 0; arg--; idx--; continue; } if (tmp == 0 && last != '*') break; /* skip chars */ switch (tmp) { case '*': isptr = 1; if (i<=0 || !arg[1]) break; arg++; tmp = *arg; //last; // arg--; // idx--; goto feed_me_again; case '+': idx--; viewflags = !viewflags; continue; case 'e': // tmp swap endian idx--; endian ^= 1; continue; case ':': // skip char i+=4; idx-=4; continue; case '.': // skip char i++; idx--; continue; case 'p': tmp = (p->bits==64)?'q': 'x'; //tmp = (sizeof (void*)==8)? 'q': 'x'; break; case '?': // help print_format_help (p); idx--; i = len; // exit continue; } if (otimes>1) p->printf (" "); #define MUSTSET (setval && elem == idx) #define MUSTSEE (elem == -1 || elem == idx) if (MUSTSEE) { if (!(MUSTSET)) { if (oldprintf) p->printf = oldprintf; if (idxprintf (namefmt, r_str_word_get0 (args, idx)); } } else { if (!oldprintf) oldprintf = p->printf; p->printf = nullprintf; } /* cmt chars */ switch (tmp) { #if 0 case 'n': // enable newline j ^= 1; continue; #endif #if 0 case 't': /* unix timestamp */ D cons_printf("0x%08x = ", config.seek+i); { /* dirty hack */ int oldfmt = last_print_format; ut64 old = config.seek; radare_seek(config.seek+i, SEEK_SET); radare_read(0); print_data(config.seek+i, "8", buf+i, 4, FMT_TIME_UNIX); last_print_format=oldfmt; radare_seek(old, SEEK_SET); } break; #endif case 'e': if (MUSTSET) { realprintf ("?e pf e not yet supported\n"); } else { double doub; memcpy (&doub, buf+i, sizeof (double)); p->printf ("0x%08"PFMT64x" = (double) ", seeki); p->printf ("%e", doub); i += 8; } break; case 'q': if (MUSTSET) { realprintf ("wv8 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("(qword) "); p->printf ("0x%08"PFMT64x" ", addr64); } i += 8; break; case 'b': if (MUSTSET) { realprintf ("w %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("%d ; 0x%02x ; '%c' ", buf[i], buf[i], IS_PRINTABLE (buf[i])?buf[i]:0); } i++; break; case 'c': if (MUSTSET) { realprintf ("?e pf c not yet implemented\n"); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("%d ; %d ; '%c' ", buf[i], (char)buf[i], IS_PRINTABLE (buf[i])?buf[i]:0); } i++; break; case 'B': if (MUSTSET) { realprintf ("?e pf B not yet implemented\n"); } else { memset (buffer, '\0', 255); if (!p->iob.read_at) { printf ("(cannot read memory)\n"); break; } else p->iob.read_at (p->iob.io, (ut64)addr, buffer, 248); p->printf ("0x%08"PFMT64x" = ", seeki); for (j=0; j<10; j++) p->printf ("%02x ", buf[j]); p->printf (" ... ("); for (j=0; j<10; j++) if (IS_PRINTABLE (buf[j])) p->printf ("%c", buf[j]); p->printf (")"); } i += 4; break; case 'f': if (MUSTSET) { realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = %f", seeki, (float)(addr)); } i += 4; break; case 'i': case 'd': // TODO: support unsigned int? if (MUSTSET) { realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("%"PFMT64d" ", addr); } i += 4; break; case 'D': if (p->disasm && p->user) i += p->disasm (p->user, seeki); break; case 'x': if (MUSTSET) { realprintf ("wv4 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { ut32 addr32 = (ut32)addr; p->printf ("0x%08"PFMT64x" = ", seeki); p->printf ("0x%08"PFMT64x" ", addr32); } //if (string_flag_offset(buf, (ut64)addr32, -1)) // p->printf("; %s", buf); i += 4; break; case 'w': case '1': // word (16 bits) if (MUSTSET) { realprintf ("wv2 %s @ 0x%08"PFMT64x"\n", setval, seeki); } else { p->printf ("0x%08x = ", seeki); if (endian) addr = (*(buf+i))<<8 | (*(buf+i+1)); else addr = (*(buf+i+1))<<8 | (*(buf+i)); p->printf ("0x%04x ", addr); } i+=2; break; case 'z': // zero terminated string if (MUSTSET) { realprintf ("?e pf z not yet supported\n"); } else { p->printf ("0x%08"PFMT64x" = ", seeki); for (; buf[i]&&iprintf ("%c", buf[i]); else p->printf ("."); } } break; case 'Z': // zero terminated wide string p->printf ("0x%08"PFMT64x" = ", seeki); for (; buf[i] && iprintf ("%c", buf[i]); else p->printf ("."); } p->printf (" "); break; case 's': p->printf ("0x%08"PFMT64x" = ", seeki); memset (buffer, '\0', 255); if (p->iob.read_at) { p->iob.read_at (p->iob.io, (ut64)addr, buffer, sizeof (buffer)-8); } else { printf ("(cannot read memory)\n"); break; } p->printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ", seeki, addr); p->printf ("%s ", buffer); i += 4; break; case 'S': p->printf ("0x%08"PFMT64x" = ", seeki); memset (buffer, '\0', 255); if (p->iob.read_at) { p->iob.read_at (p->iob.io, addr64, buffer, sizeof (buffer)-8); } else { printf ("(cannot read memory)\n"); break; } p->printf ("0x%08"PFMT64x" -> 0x%08"PFMT64x" ", seeki, addr); p->printf ("%s ", buffer); i += 8; break; default: /* ignore unknown chars */ break; } if (viewflags && p->offname) { const char *s = p->offname (p->user, seeki); if (s) p->printf ("@(%s)", s); s = p->offname (p->user, addr); if (s) p->printf ("*(%s)", s); } if (tmp != 'D') p->printf ("\n"); last = tmp; } if (otimes>1) p->printf ("}\n"); arg = orig; idx = 0; } if (oldprintf) p->printf = oldprintf; beach: free (buf); if (args) { free (args); } return i; }