2013-01-22 04:06:12 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2013 - pancake */
|
2012-02-27 02:07:32 +00:00
|
|
|
|
2013-11-14 12:52:03 +00:00
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
static int is_valid_input_num_value(RCore *core, char *input_value){
|
|
|
|
ut64 value = input_value ? r_num_math (core->num, input_value) : 0;
|
|
|
|
return !(value == 0 && input_value && *input_value == '0');
|
|
|
|
}
|
2013-11-14 12:52:03 +00:00
|
|
|
|
|
|
|
static ut64 get_input_num_value(RCore *core, char *input_value){
|
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
ut64 value = input_value ? r_num_math (core->num, input_value) : 0;
|
2013-11-14 12:52:03 +00:00
|
|
|
return value;
|
|
|
|
}
|
|
|
|
|
2013-11-25 01:03:54 +00:00
|
|
|
static void set_asm_configs(RCore *core, char *arch, ut32 bits, int segoff){
|
2013-11-14 12:52:03 +00:00
|
|
|
r_config_set (core->config, "asm.arch", arch);
|
|
|
|
r_config_set_i (core->config, "asm.bits", bits);
|
|
|
|
// XXX - this needs to be done here, because
|
|
|
|
// if arch == x86 and bits == 16, segoff automatically changes
|
2013-11-25 01:03:54 +00:00
|
|
|
r_config_set_i (core->config, "asm.segoff", segoff);
|
2013-11-14 12:52:03 +00:00
|
|
|
}
|
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
static int process_input(RCore *core, const char *input, ut64* blocksize, char **asm_arch, ut32 *bits) {
|
2013-11-14 12:52:03 +00:00
|
|
|
// input: start of the input string e.g. after the command symbols have been consumed
|
|
|
|
// size: blocksize if present, otherwise -1
|
|
|
|
// asm_arch: asm_arch to interpret as if present and valid, otherwise NULL;
|
|
|
|
// bits: bits to use if present, otherwise -1
|
|
|
|
|
|
|
|
int result = R_FALSE;
|
2013-12-01 23:43:44 +00:00
|
|
|
char *input_one = NULL, *input_two = NULL, *input_three = NULL;
|
2013-11-14 12:52:03 +00:00
|
|
|
char *str_clone = NULL,
|
|
|
|
*ptr_str_clone = NULL,
|
|
|
|
*trimmed_clone = NULL;
|
|
|
|
|
|
|
|
if (input == NULL || blocksize == NULL || asm_arch == NULL || bits == NULL) {
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
str_clone = strdup (input);
|
|
|
|
trimmed_clone = r_str_trim_head_tail (str_clone);
|
|
|
|
|
|
|
|
input_one = trimmed_clone;
|
|
|
|
|
|
|
|
ptr_str_clone = strchr (trimmed_clone, ' ');
|
|
|
|
// terminate input_one
|
|
|
|
if (ptr_str_clone) {
|
|
|
|
*ptr_str_clone = '\0';
|
|
|
|
input_two = (++ptr_str_clone);
|
|
|
|
ptr_str_clone = strchr (input_two, ' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
// terminate input_two
|
|
|
|
if (ptr_str_clone && input_two) {
|
|
|
|
*ptr_str_clone = '\0';
|
|
|
|
input_three = (++ptr_str_clone);
|
|
|
|
ptr_str_clone = strchr (input_three, ' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
// terminate input_three
|
|
|
|
if (ptr_str_clone && input_three) {
|
|
|
|
*ptr_str_clone = '\0';
|
|
|
|
ptr_str_clone = strchr (input_three, ' ');
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// command formats
|
|
|
|
// <size> <arch> <bits>
|
|
|
|
// <size> <arch>
|
|
|
|
// <size> <bits>
|
|
|
|
// <arch> <bits>
|
|
|
|
// <arch>
|
|
|
|
|
|
|
|
// initialize
|
|
|
|
*asm_arch = NULL;
|
|
|
|
*blocksize = *bits = -1;
|
|
|
|
|
|
|
|
if (input_one && input_two && input_three) {
|
|
|
|
// <size> <arch> <bits>
|
2013-11-24 00:44:00 +00:00
|
|
|
*blocksize = is_valid_input_num_value(core, input_one) ? get_input_num_value (core, input_one): 0;
|
2013-11-14 12:52:03 +00:00
|
|
|
*asm_arch = r_asm_is_valid (core->assembler, input_two) ? strdup (input_two) : NULL;
|
|
|
|
*bits = get_input_num_value (core, input_three);
|
|
|
|
result = R_TRUE;
|
|
|
|
|
|
|
|
} else if (input_one && input_two) {
|
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
*blocksize = is_valid_input_num_value(core, input_one) ? get_input_num_value (core, input_one): 0;
|
2013-11-14 12:52:03 +00:00
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
if (!is_valid_input_num_value(core, input_one) ) {
|
2013-11-14 12:52:03 +00:00
|
|
|
// input_one can only be one other thing
|
|
|
|
*asm_arch = r_asm_is_valid (core->assembler, input_one) ? strdup (input_one) : NULL;
|
2013-11-24 00:44:00 +00:00
|
|
|
*bits = is_valid_input_num_value(core, input_two) ? get_input_num_value (core, input_two): -1;
|
2013-11-14 12:52:03 +00:00
|
|
|
} else {
|
|
|
|
if (r_str_contains_macro (input_two) ){
|
|
|
|
r_str_truncate_cmd (input_two);
|
|
|
|
}
|
|
|
|
*asm_arch = r_asm_is_valid (core->assembler, input_two) ? strdup (input_two) : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = R_TRUE;
|
|
|
|
} else if (input_one) {
|
2013-12-01 23:43:44 +00:00
|
|
|
*blocksize = is_valid_input_num_value (core, input_one) ? get_input_num_value (core, input_one): 0;
|
|
|
|
if (!is_valid_input_num_value (core, input_one) ) {
|
2013-11-14 12:52:03 +00:00
|
|
|
// input_one can only be one other thing
|
2013-12-01 23:43:44 +00:00
|
|
|
if (r_str_contains_macro (input_one))
|
2013-11-14 12:52:03 +00:00
|
|
|
r_str_truncate_cmd (input_one);
|
|
|
|
*asm_arch = r_asm_is_valid (core->assembler, input_one) ? strdup (input_one) : NULL;
|
|
|
|
}
|
|
|
|
result = R_TRUE;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-10-15 23:10:27 +00:00
|
|
|
// > pxa
|
2013-11-14 12:52:03 +00:00
|
|
|
#define append(x,y) { strcat (x,y);x += strlen (y); }
|
2013-10-19 22:25:37 +00:00
|
|
|
static void annotated_hexdump(RCore *core, const char *str, int len) {
|
2013-10-16 00:45:03 +00:00
|
|
|
const int usecolor = r_config_get_i (core->config, "scr.color");
|
2013-10-15 01:56:01 +00:00
|
|
|
const int COLS = 16;
|
|
|
|
const ut8 *buf = core->block;
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
char *ebytes, *echars;
|
|
|
|
ut64 fend = UT64_MAX;
|
2013-10-15 23:10:27 +00:00
|
|
|
char *comment;
|
2013-10-15 01:56:01 +00:00
|
|
|
int rows = len/COLS;
|
2013-10-15 23:10:27 +00:00
|
|
|
char out[1024];
|
2013-10-15 01:56:01 +00:00
|
|
|
char *note[COLS];
|
|
|
|
int lnote[COLS];
|
2013-10-15 23:10:27 +00:00
|
|
|
char bytes[1024];
|
2013-10-16 00:45:03 +00:00
|
|
|
char chars[1024];
|
2013-10-15 23:10:27 +00:00
|
|
|
int i, j, low, max, marks, tmarks, setcolor, hascolor;
|
2013-10-15 01:56:01 +00:00
|
|
|
ut8 ch;
|
|
|
|
const char *colors[8] = {
|
|
|
|
Color_WHITE, Color_GREEN, Color_YELLOW, Color_RED,
|
|
|
|
Color_CYAN, Color_MAGENTA, Color_GRAY, Color_BLUE
|
|
|
|
};
|
2013-10-16 00:45:03 +00:00
|
|
|
int col = core->print->col;
|
2013-10-15 01:56:01 +00:00
|
|
|
|
2013-10-16 00:45:03 +00:00
|
|
|
if (usecolor) r_cons_strcat (Color_GREEN);
|
2013-10-15 23:10:27 +00:00
|
|
|
r_cons_strcat ("- offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF\n");
|
2013-10-16 00:45:03 +00:00
|
|
|
if (usecolor) r_cons_strcat (Color_RESET);
|
2013-10-15 23:10:27 +00:00
|
|
|
hascolor = 0;
|
|
|
|
tmarks = marks = 0;
|
2013-10-15 01:56:01 +00:00
|
|
|
for (i=0; i<rows; i++) {
|
|
|
|
bytes[0] = 0;
|
|
|
|
ebytes = bytes;
|
|
|
|
chars[0] = 0;
|
|
|
|
echars = chars;
|
2013-10-15 23:10:27 +00:00
|
|
|
hascolor = 0;
|
2013-10-15 01:56:01 +00:00
|
|
|
for (j=0; j<COLS; j++) {
|
|
|
|
note[j] = NULL;
|
|
|
|
lnote[j] = 0;
|
|
|
|
// collect comments
|
2013-10-15 23:10:27 +00:00
|
|
|
comment = r_meta_get_string (core->anal->meta, R_META_TYPE_COMMENT, addr+j);
|
|
|
|
if (comment) {
|
|
|
|
comment = r_str_prefix_all (comment, " ; ");
|
|
|
|
r_cons_strcat (comment);
|
|
|
|
free (comment);
|
|
|
|
}
|
2013-10-15 01:56:01 +00:00
|
|
|
// collect flags
|
|
|
|
RFlagItem *f = r_flag_get_i (core->flags, addr+j);
|
2013-10-15 23:10:27 +00:00
|
|
|
setcolor = 1;
|
2013-10-15 01:56:01 +00:00
|
|
|
if (f) {
|
2013-10-15 23:10:27 +00:00
|
|
|
fend = addr +j+ f->size;
|
2013-10-15 01:56:01 +00:00
|
|
|
note[j] = f->name;
|
|
|
|
marks++;
|
2013-10-15 23:10:27 +00:00
|
|
|
tmarks++;
|
|
|
|
} else {
|
|
|
|
if (fend==UT64_MAX || fend<=(addr+j))
|
|
|
|
setcolor = 0;
|
|
|
|
// use old flag if still valid
|
|
|
|
}
|
|
|
|
if (setcolor && !hascolor) {
|
|
|
|
hascolor = 1;
|
2013-10-16 00:45:03 +00:00
|
|
|
if (usecolor) {
|
2013-10-15 01:56:01 +00:00
|
|
|
#if 1
|
2013-10-16 00:45:03 +00:00
|
|
|
append (ebytes, colors[tmarks%5]);
|
2013-10-15 01:56:01 +00:00
|
|
|
#else
|
2013-10-16 00:45:03 +00:00
|
|
|
// psycodelia!
|
|
|
|
char *color = r_cons_color_random (0);
|
|
|
|
append (ebytes, color);
|
|
|
|
free (color);
|
2013-10-15 01:56:01 +00:00
|
|
|
#endif
|
2013-10-16 00:45:03 +00:00
|
|
|
} else {
|
|
|
|
append (ebytes, Color_INVERT);
|
|
|
|
}
|
2013-10-15 01:56:01 +00:00
|
|
|
}
|
|
|
|
ch = buf[(i*COLS)+j];
|
|
|
|
if (core->print->ocur!=-1) {
|
|
|
|
low = R_MIN (core->print->cur, core->print->ocur);
|
|
|
|
max = R_MAX (core->print->cur, core->print->ocur);
|
|
|
|
} else {
|
|
|
|
low = max = core->print->cur;
|
|
|
|
}
|
|
|
|
if (core->print->cur_enabled) {
|
2013-10-15 23:10:27 +00:00
|
|
|
int here = (i*COLS)+j;
|
|
|
|
if (low==max) {
|
2013-10-16 00:45:03 +00:00
|
|
|
if (low == here) {
|
|
|
|
append (echars, Color_INVERT);
|
2013-10-15 23:10:27 +00:00
|
|
|
append (ebytes, Color_INVERT);
|
2013-10-16 00:45:03 +00:00
|
|
|
}
|
2013-10-15 23:10:27 +00:00
|
|
|
} else {
|
2013-10-16 00:45:03 +00:00
|
|
|
if (here >= low && here <max) {
|
2013-10-15 23:10:27 +00:00
|
|
|
append (ebytes, Color_INVERT);
|
2013-10-16 00:45:03 +00:00
|
|
|
append (echars, Color_INVERT);
|
|
|
|
}
|
2013-10-15 01:56:01 +00:00
|
|
|
}
|
|
|
|
}
|
2013-10-15 23:10:27 +00:00
|
|
|
sprintf (ebytes, "%02x", ch);
|
2013-10-15 01:56:01 +00:00
|
|
|
ebytes += strlen (ebytes);
|
2013-10-16 00:45:03 +00:00
|
|
|
sprintf (echars, "%c", IS_PRINTABLE (ch)?ch:'.');
|
|
|
|
echars++;
|
2013-10-15 01:56:01 +00:00
|
|
|
if (core->print->cur_enabled) {
|
|
|
|
if (max == ((i*COLS)+j)) {
|
2013-10-15 23:10:27 +00:00
|
|
|
append (ebytes, Color_RESET);
|
2013-10-16 00:45:03 +00:00
|
|
|
append (echars, Color_RESET);
|
2013-10-15 23:10:27 +00:00
|
|
|
hascolor = 0;
|
|
|
|
}
|
2013-10-15 01:56:01 +00:00
|
|
|
}
|
2013-10-15 23:10:27 +00:00
|
|
|
if (j<15&&j%2) append (ebytes, " ");
|
|
|
|
|
|
|
|
|
2013-10-15 01:56:01 +00:00
|
|
|
if (fend!=UT64_MAX && fend == addr+j+1) {
|
2013-10-16 00:45:03 +00:00
|
|
|
if (usecolor) {
|
|
|
|
append (ebytes, Color_RESET);
|
|
|
|
append (echars, Color_RESET);
|
|
|
|
}
|
2013-10-15 01:56:01 +00:00
|
|
|
fend = UT64_MAX;
|
2013-10-15 23:10:27 +00:00
|
|
|
hascolor = 0;
|
2013-10-15 01:56:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// show comments and flags
|
|
|
|
if (marks>0) {
|
|
|
|
r_cons_strcat (" ");
|
|
|
|
memset (out, ' ', sizeof (out));
|
2013-10-15 23:10:27 +00:00
|
|
|
out[sizeof (out)-1] = 0;
|
2013-10-15 01:56:01 +00:00
|
|
|
for (j=0; j<COLS; j++) {
|
|
|
|
if (note[j]) {
|
2013-10-15 23:10:27 +00:00
|
|
|
int off = (j*3);
|
|
|
|
off -= (j/2);
|
|
|
|
if (j%2) off--;
|
|
|
|
memcpy (out+off, "/", 1);
|
|
|
|
memcpy (out+off+1, note[j], strlen (note[j]));
|
2013-10-15 01:56:01 +00:00
|
|
|
}
|
|
|
|
/// XXX overflow
|
|
|
|
}
|
2013-10-15 23:10:27 +00:00
|
|
|
out[70] = 0;
|
2013-10-15 01:56:01 +00:00
|
|
|
r_cons_strcat (out);
|
|
|
|
r_cons_newline ();
|
|
|
|
marks = 0;
|
|
|
|
}
|
2013-10-16 00:45:03 +00:00
|
|
|
if (usecolor) r_cons_strcat (Color_GREEN);
|
|
|
|
r_cons_printf ("0x%08"PFMT64x, addr);
|
|
|
|
if (usecolor) r_cons_strcat (Color_RESET);
|
|
|
|
r_cons_strcat ((col==1)?" |":" ");
|
2013-10-15 01:56:01 +00:00
|
|
|
r_cons_strcat (bytes);
|
2013-10-16 00:45:03 +00:00
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
r_cons_strcat ((col==1)?"| ":(col==2)?" |":" ");
|
2013-10-15 01:56:01 +00:00
|
|
|
r_cons_strcat (chars);
|
2013-10-16 00:45:03 +00:00
|
|
|
r_cons_strcat (Color_RESET);
|
|
|
|
if (col==2) r_cons_strcat ("|");
|
2013-10-15 01:56:01 +00:00
|
|
|
r_cons_newline ();
|
|
|
|
addr += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-14 01:30:12 +00:00
|
|
|
R_API void r_core_print_examine(RCore *core, const char *str) {
|
2013-10-14 20:23:05 +00:00
|
|
|
char cmd[128], *p;
|
|
|
|
ut64 addr = core->offset;
|
2013-10-14 01:30:12 +00:00
|
|
|
int size = (core->anal->bits/4);
|
|
|
|
int count = atoi (str);
|
2013-10-19 21:10:08 +00:00
|
|
|
int i, n;
|
2013-10-14 01:30:12 +00:00
|
|
|
if (count<1) count = 1;
|
|
|
|
// skipsapces
|
|
|
|
while (*str>='0' && *str<='9') str++;
|
|
|
|
#if 0
|
|
|
|
Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).
|
|
|
|
#endif
|
|
|
|
switch (str[1]) {
|
|
|
|
case 'b': size = 1; break;
|
|
|
|
case 'h': size = 2; break;
|
|
|
|
case 'w': size = 4; break;
|
|
|
|
case 'g': size = 8; break;
|
|
|
|
}
|
2013-10-14 20:23:05 +00:00
|
|
|
if ((p=strchr (str, ' ')))
|
|
|
|
addr = r_num_math (core->num, p+1);
|
2013-10-14 01:30:12 +00:00
|
|
|
switch (*str) {
|
|
|
|
case '?':
|
|
|
|
eprintf (
|
|
|
|
"Format is x/[num][format][size]\n"
|
2013-10-14 20:23:05 +00:00
|
|
|
"Num specifies the number of format elements to display\n"
|
2013-10-14 01:30:12 +00:00
|
|
|
"Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal),\n"
|
|
|
|
" t(binary), f(float), a(address), i(instruction), c(char) and s(string),\n"
|
|
|
|
" T(OSType), A(floating point values in hex).\n"
|
2013-10-14 20:23:05 +00:00
|
|
|
"Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes).\n"
|
2013-10-14 01:30:12 +00:00
|
|
|
);
|
|
|
|
break;
|
|
|
|
case 's':
|
2013-10-14 20:23:05 +00:00
|
|
|
snprintf (cmd, sizeof (cmd), "psb %d @ 0x%"PFMT64x, count*size, addr);
|
2013-10-14 01:30:12 +00:00
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
break;
|
|
|
|
case 'o':
|
2013-10-14 20:23:05 +00:00
|
|
|
snprintf (cmd, sizeof (cmd), "pxo %d @ 0x%"PFMT64x, count*size, addr);
|
2013-10-14 01:30:12 +00:00
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
case 'A': // XXX (float in hex wtf)
|
2013-10-19 21:10:08 +00:00
|
|
|
n = 3;
|
|
|
|
snprintf (cmd, sizeof (cmd), "pxo %d @ 0x%"PFMT64x,
|
|
|
|
count*size, addr);
|
|
|
|
strcpy (cmd, "pf ");
|
|
|
|
for (i=0;i<count && n<sizeof (cmd);i++)
|
|
|
|
cmd[n++] = 'f';
|
|
|
|
cmd[n] = 0;
|
|
|
|
r_core_cmd0 (core, cmd);
|
2013-10-14 01:30:12 +00:00
|
|
|
break;
|
|
|
|
case 'a':
|
|
|
|
case 'd':
|
2013-10-14 20:23:05 +00:00
|
|
|
snprintf (cmd, sizeof (cmd), "pxw %d @ 0x%"PFMT64x, count*size, addr);
|
2013-10-14 01:30:12 +00:00
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
break;
|
|
|
|
case 'i':
|
2013-10-14 20:23:05 +00:00
|
|
|
snprintf (cmd, sizeof (cmd), "pid %d @ 0x%"PFMT64x, count, addr);
|
2013-10-14 01:30:12 +00:00
|
|
|
r_core_cmd0 (core, cmd);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int printzoomcallback(void *user, int mode, ut64 addr, ut8 *bufz, ut64 size) {
|
|
|
|
RCore *core = (RCore *) user;
|
|
|
|
int j, ret = 0;
|
|
|
|
RListIter *iter;
|
|
|
|
RFlagItem *flag;
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
case 'p':
|
|
|
|
for (j=0; j<size; j++)
|
|
|
|
if (IS_PRINTABLE (bufz[j]))
|
|
|
|
ret++;
|
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
r_list_foreach (core->flags->flags, iter, flag)
|
|
|
|
if (flag->offset <= addr && addr < flag->offset+flag->size)
|
|
|
|
ret++;
|
|
|
|
break;
|
|
|
|
case 's':
|
|
|
|
j = r_flag_space_get (core->flags, "strings");
|
|
|
|
r_list_foreach (core->flags->flags, iter, flag) {
|
|
|
|
if (flag->space == j && ((addr <= flag->offset
|
|
|
|
&& flag->offset < addr+size)
|
|
|
|
|| (addr <= flag->offset+flag->size
|
|
|
|
&& flag->offset+flag->size < addr+size)))
|
|
|
|
ret++;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '0': // 0xFF
|
|
|
|
for (j=0; j<size; j++)
|
|
|
|
if (bufz[j] == 0)
|
|
|
|
ret++;
|
|
|
|
break;
|
|
|
|
case 'F': // 0xFF
|
|
|
|
for (j=0; j<size; j++)
|
|
|
|
if (bufz[j] == 0xff)
|
|
|
|
ret++;
|
|
|
|
break;
|
|
|
|
case 'e': // entropy
|
|
|
|
ret = (ut8) (r_hash_entropy_fraction (bufz, size)*255);
|
|
|
|
break;
|
|
|
|
case 'h': // head
|
|
|
|
default:
|
|
|
|
ret = *bufz;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2012-08-13 02:33:01 +00:00
|
|
|
|
|
|
|
R_API void r_core_print_cmp(RCore *core, ut64 from, ut64 to) {
|
|
|
|
long int delta = 0;
|
2012-08-13 03:10:04 +00:00
|
|
|
int col = core->cons->columns>123;
|
2012-08-13 02:33:01 +00:00
|
|
|
ut8 *b = malloc (core->blocksize);
|
|
|
|
ut64 addr = core->offset;
|
|
|
|
memset (b, 0xff, core->blocksize);
|
|
|
|
delta = addr - from;
|
|
|
|
r_core_read_at (core, to+delta, b, core->blocksize);
|
2013-10-04 11:57:49 +00:00
|
|
|
r_print_hexdiff (core->print, core->offset, core->block,
|
|
|
|
to+delta, b, core->blocksize, col);
|
2012-08-13 02:33:01 +00:00
|
|
|
free (b);
|
|
|
|
}
|
|
|
|
|
2013-04-30 22:40:26 +00:00
|
|
|
static int pdi(RCore *core, int l, int len, int ilen) {
|
|
|
|
int show_offset = r_config_get_i (core->config, "asm.offset");
|
|
|
|
int show_bytes = r_config_get_i (core->config, "asm.bytes");
|
|
|
|
int decode = r_config_get_i (core->config, "asm.decode");
|
2013-11-13 00:59:16 +00:00
|
|
|
int esil = r_config_get_i (core->config, "asm.esil");
|
2013-04-30 22:40:26 +00:00
|
|
|
const ut8 *buf = core->block;
|
|
|
|
int i, j, ret, err = 0;
|
|
|
|
RAsmOp asmop;
|
|
|
|
if (l==0) l = len;
|
|
|
|
for (i=j=0; j<len && j<l && i<ilen; i+=ret, j++) {
|
|
|
|
r_asm_set_pc (core->assembler, core->offset+i);
|
2013-10-04 11:57:49 +00:00
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf+i,
|
|
|
|
core->blocksize-i);
|
2013-04-30 22:40:26 +00:00
|
|
|
if (show_offset)
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" ", core->offset+i);
|
|
|
|
if (ret<1) {
|
|
|
|
ret = err = 1;
|
|
|
|
if (show_bytes)
|
|
|
|
r_cons_printf ("%14s%02x ", "", buf[i]);
|
|
|
|
r_cons_printf ("%s\n", "???");
|
|
|
|
} else {
|
|
|
|
if (show_bytes)
|
|
|
|
r_cons_printf ("%16s ", asmop.buf_hex);
|
2013-11-13 00:59:16 +00:00
|
|
|
if (decode || esil) {
|
2013-04-30 22:40:26 +00:00
|
|
|
RAnalOp analop = {0};
|
|
|
|
char *tmpopstr, *opstr;
|
|
|
|
r_anal_op (core->anal, &analop, core->offset+i,
|
|
|
|
buf+i, core->blocksize-i);
|
|
|
|
tmpopstr = r_anal_op_to_string (core->anal, &analop);
|
2013-11-13 00:59:16 +00:00
|
|
|
if (decode) {
|
|
|
|
opstr = (tmpopstr)? tmpopstr: strdup (asmop.buf_asm);
|
|
|
|
} else if (esil) {
|
|
|
|
opstr = strdup (analop.esil);
|
2013-11-15 00:54:14 +00:00
|
|
|
} else opstr = strdup (asmop.buf_asm);
|
2013-04-30 22:40:26 +00:00
|
|
|
r_cons_printf ("%s\n", opstr);
|
|
|
|
free (opstr);
|
|
|
|
} else r_cons_printf ("%s\n", asmop.buf_asm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
static int cmd_print(void *data, const char *input) {
|
|
|
|
RCore *core = (RCore *)data;
|
2013-02-11 09:51:45 +00:00
|
|
|
int mode, w, p, i, l, len, total[10];
|
|
|
|
ut64 off, from, to, at, ate, piece;
|
2012-02-27 01:40:27 +00:00
|
|
|
ut32 tbs = core->blocksize;
|
2012-07-06 00:17:44 +00:00
|
|
|
ut8 *ptr = core->block;
|
2013-02-11 09:51:45 +00:00
|
|
|
RCoreAnalStats *as;
|
|
|
|
ut64 n;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
2012-11-20 02:59:00 +00:00
|
|
|
l = len = core->blocksize;
|
2012-02-27 01:40:27 +00:00
|
|
|
if (input[0] && input[1]) {
|
2012-08-19 01:28:17 +00:00
|
|
|
const char *p = strchr (input, ' ');
|
|
|
|
if (p) {
|
|
|
|
l = (int) r_num_math (core->num, p+1);
|
2012-02-27 01:40:27 +00:00
|
|
|
/* except disasm and memoryfmt (pd, pm) */
|
2013-11-24 00:44:00 +00:00
|
|
|
if (input[0] != 'd' && input[0] != 'D' && input[0] != 'm' && input[0]!='a') {
|
2012-02-27 01:40:27 +00:00
|
|
|
if (l>0) len = l;
|
2013-10-19 21:10:08 +00:00
|
|
|
if (l>tbs) {
|
2013-10-21 10:54:34 +00:00
|
|
|
if (!r_core_block_size (core, l)) {
|
|
|
|
eprintf ("This block size is too big. Did you mean 'p%c @ %s' instead?\n",
|
|
|
|
*input, input+2);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
2013-10-19 21:10:08 +00:00
|
|
|
l = core->blocksize;
|
|
|
|
} else {
|
|
|
|
l = len;
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
}// else l = 0;
|
|
|
|
} else l = len;
|
2013-11-06 10:15:36 +00:00
|
|
|
|
2013-10-19 21:10:08 +00:00
|
|
|
if (len > core->blocksize)
|
|
|
|
len = core->blocksize;
|
2012-02-27 01:40:27 +00:00
|
|
|
|
2013-11-06 10:15:36 +00:00
|
|
|
if (input[0] != 'd' && input[0] != 'm' && input[0]!='a') {
|
|
|
|
n = core->blocksize_max;
|
|
|
|
i = (int)n;
|
|
|
|
if (i != n) i = 0;
|
|
|
|
if (i && l > i) {
|
|
|
|
eprintf ("This block size is too big (%d<%d). Did you mean 'p%c @ %s' instead?\n",
|
|
|
|
i, l, *input, input+2);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
|
2012-08-01 23:50:39 +00:00
|
|
|
if (input[0] && input[0]!='Z' && input[1] == 'f') {
|
2012-07-22 08:00:35 +00:00
|
|
|
RAnalFunction *f = r_anal_fcn_find (core->anal, core->offset,
|
2012-02-27 01:40:27 +00:00
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
2013-02-11 09:51:45 +00:00
|
|
|
if (f) len = f->size;
|
|
|
|
else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2012-08-29 15:24:30 +00:00
|
|
|
ptr = core->block;
|
2012-02-27 01:40:27 +00:00
|
|
|
core->num->value = len;
|
2013-10-19 22:25:37 +00:00
|
|
|
if (len>core->blocksize)
|
|
|
|
len = core->blocksize;
|
2012-02-27 01:40:27 +00:00
|
|
|
switch (*input) {
|
2013-09-18 20:16:18 +00:00
|
|
|
case 'w':
|
2013-11-19 01:55:22 +00:00
|
|
|
if (input[1]=='n') {
|
|
|
|
int i, n = r_num_rand (10);
|
|
|
|
ut64 num, base = r_num_get (core->num, "entry0");
|
|
|
|
if (!base) base = 0x8048000;
|
|
|
|
eprintf ("[+] Analyzing code starting at 0x%08"PFMT64x"...\n", base);
|
|
|
|
r_sys_sleep (3);
|
|
|
|
eprintf ("[+] Looking for vulnerabilities...\n");
|
|
|
|
r_sys_sleep (3);
|
|
|
|
eprintf ("[+] Found %d bugs...\n", n);
|
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
eprintf ("[+] Deeply analyzing bug %d at 0x%08"PFMT64x"...\n",
|
|
|
|
i, base+r_num_rand (0xffff));
|
|
|
|
r_sys_sleep (1);
|
|
|
|
}
|
|
|
|
eprintf ("[+] Finding ROP gadgets...\n");
|
|
|
|
n = r_num_rand (0x20);
|
|
|
|
num = base;
|
|
|
|
for (i=0; i<n; i++) {
|
|
|
|
num += r_num_rand (0xfff);
|
|
|
|
eprintf (" * 0x%08"PFMT64x" %d : %02x %02x ..\n",
|
|
|
|
num, r_num_rand (10),
|
|
|
|
r_num_rand (0xff), r_num_rand (0xff));
|
|
|
|
r_sys_sleep (r_num_rand (2));
|
|
|
|
}
|
|
|
|
eprintf ("[+] Cooking the shellcode...\n");
|
|
|
|
r_sys_sleep (4);
|
|
|
|
eprintf ("[+] Launching the exploit...\n");
|
|
|
|
r_sys_sleep (1);
|
|
|
|
r_sys_cmd ("sh");
|
|
|
|
} else {
|
|
|
|
char *cwd = r_sys_getdir ();
|
|
|
|
if (cwd) {
|
|
|
|
eprintf ("%s\n", cwd);
|
|
|
|
free (cwd);
|
|
|
|
}
|
2013-09-18 20:16:18 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-02-10 02:18:20 +00:00
|
|
|
case 'v':
|
2013-02-11 09:51:45 +00:00
|
|
|
mode = input[1];
|
2013-04-30 01:25:32 +00:00
|
|
|
w = len? len: core->print->cols * 4;
|
|
|
|
if (mode == 'j') r_cons_strcat ("{");
|
2013-02-11 09:51:45 +00:00
|
|
|
off = core->offset;
|
|
|
|
for (i=0; i<10; i++) total[i] = 0;
|
|
|
|
r_core_get_boundaries (core, "file", &from, &to);
|
|
|
|
piece = (to-from) / w;
|
|
|
|
if (piece<1) piece = 1;
|
|
|
|
as = r_core_anal_get_stats (core, from, to, piece);
|
|
|
|
//eprintf ("RANGE = %llx %llx\n", from, to);
|
2013-02-07 02:09:53 +00:00
|
|
|
switch (mode) {
|
2013-02-11 09:51:45 +00:00
|
|
|
case '?':
|
|
|
|
r_cons_printf ("Usage: p%%[jh] [pieces]\n");
|
|
|
|
r_cons_printf (" pv show ascii-art bar of metadata in file boundaries\n");
|
|
|
|
r_cons_printf (" pvj show json format\n");
|
|
|
|
r_cons_printf (" pvh show histogram analysis of metadata per block\n");
|
|
|
|
return 0;
|
2013-02-07 02:09:53 +00:00
|
|
|
case 'j':
|
2013-02-11 09:51:45 +00:00
|
|
|
r_cons_printf (
|
|
|
|
"\"from\":%"PFMT64d","
|
|
|
|
"\"to\":%"PFMT64d","
|
|
|
|
"\"blocksize\":%d,"
|
|
|
|
"\"blocks\":[", from, to, piece);
|
2013-02-07 02:09:53 +00:00
|
|
|
break;
|
|
|
|
case 'h':
|
2013-02-11 09:51:45 +00:00
|
|
|
r_cons_printf (".-------------.---------------------------------.\n");
|
|
|
|
r_cons_printf ("| offset | flags funcs cmts imps syms str |\n");
|
|
|
|
r_cons_printf ("|-------------)---------------------------------|\n");
|
2013-02-07 02:09:53 +00:00
|
|
|
break;
|
|
|
|
default:
|
2013-02-11 09:51:45 +00:00
|
|
|
r_cons_printf ("0x%"PFMT64x" [", from);
|
2013-02-07 02:09:53 +00:00
|
|
|
}
|
|
|
|
|
2013-02-11 09:51:45 +00:00
|
|
|
len = 0;
|
|
|
|
for (i=0; i<w; i++) {
|
|
|
|
at = from + (piece*i);
|
|
|
|
ate = at + piece;
|
|
|
|
p = (at-from)/piece;
|
|
|
|
switch (mode) {
|
|
|
|
case 'j':
|
|
|
|
r_cons_printf ("%s{",len?",":"");
|
|
|
|
if ((as->block[p].flags)
|
|
|
|
|| (as->block[p].functions)
|
|
|
|
|| (as->block[p].comments)
|
|
|
|
|| (as->block[p].imports)
|
|
|
|
|| (as->block[p].symbols)
|
|
|
|
|| (as->block[p].strings))
|
|
|
|
r_cons_printf ("\"offset\":%"PFMT64d",", at), l++;
|
|
|
|
// TODO: simplify with macro
|
|
|
|
l = 0;
|
|
|
|
if (as->block[p].flags) r_cons_printf ("%s\"flags\":%d", l?",":"", as->block[p].flags), l++;
|
|
|
|
if (as->block[p].functions) r_cons_printf ("%s\"functions\":%d", l?",":"", as->block[p].functions), l++;
|
|
|
|
if (as->block[p].comments) r_cons_printf ("%s\"comments\":%d", l?",":"", as->block[p].comments), l++;
|
|
|
|
if (as->block[p].imports) r_cons_printf ("%s\"imports\":%d", l?",":"", as->block[p].imports), l++;
|
|
|
|
if (as->block[p].symbols) r_cons_printf ("%s\"symbols\":%d", l?",":"", as->block[p].symbols), l++;
|
|
|
|
if (as->block[p].strings) r_cons_printf ("%s\"strings\":%d", l?",":"", as->block[p].strings), l++;
|
|
|
|
r_cons_strcat ("}");
|
|
|
|
len++;
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
total[0] += as->block[p].flags;
|
|
|
|
total[1] += as->block[p].functions;
|
|
|
|
total[2] += as->block[p].comments;
|
|
|
|
total[3] += as->block[p].imports;
|
|
|
|
total[4] += as->block[p].symbols;
|
|
|
|
total[5] += as->block[p].strings;
|
|
|
|
if ((as->block[p].flags)
|
|
|
|
|| (as->block[p].functions)
|
|
|
|
|| (as->block[p].comments)
|
|
|
|
|| (as->block[p].imports)
|
|
|
|
|| (as->block[p].symbols)
|
|
|
|
|| (as->block[p].strings))
|
|
|
|
r_cons_printf ("| 0x%09"PFMT64x" | %4d %4d %4d %4d %4d %4d |\n", at,
|
|
|
|
as->block[p].flags,
|
|
|
|
as->block[p].functions,
|
|
|
|
as->block[p].comments,
|
|
|
|
as->block[p].imports,
|
|
|
|
as->block[p].symbols,
|
|
|
|
as->block[p].strings);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (off>=at && off<ate) {
|
|
|
|
r_cons_memcat ("^", 1);
|
2013-02-06 09:35:23 +00:00
|
|
|
} else {
|
2013-02-11 09:51:45 +00:00
|
|
|
if (as->block[p].strings>0)
|
|
|
|
r_cons_memcat ("z", 1);
|
|
|
|
else if (as->block[p].imports>0)
|
|
|
|
r_cons_memcat ("i", 1);
|
|
|
|
else if (as->block[p].symbols>0)
|
|
|
|
r_cons_memcat ("s", 1);
|
|
|
|
else if (as->block[p].functions>0)
|
|
|
|
r_cons_memcat ("F", 1);
|
|
|
|
else if (as->block[p].flags>0)
|
|
|
|
r_cons_memcat ("f", 1);
|
|
|
|
else if (as->block[p].comments>0)
|
|
|
|
r_cons_memcat ("c", 1);
|
2013-02-06 09:35:23 +00:00
|
|
|
else r_cons_memcat (".", 1);
|
|
|
|
}
|
2013-02-11 09:51:45 +00:00
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
}
|
2013-02-11 09:51:45 +00:00
|
|
|
switch (mode) {
|
|
|
|
case 'j':
|
|
|
|
r_cons_strcat ("]}\n");
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
//r_cons_printf (" total | flags funcs cmts imps syms str |\n");
|
|
|
|
r_cons_printf ("|-------------)---------------------------------|\n");
|
|
|
|
r_cons_printf ("| total | %4d %4d %4d %4d %4d %4d |\n",
|
|
|
|
total[0], total[1], total[2], total[3], total[4], total[5]);
|
|
|
|
r_cons_printf ("`-------------'---------------------------------'\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_cons_printf ("] 0x%"PFMT64x"\n", to);
|
|
|
|
}
|
|
|
|
r_core_anal_stats_free (as);
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case '=':
|
2012-07-06 00:17:44 +00:00
|
|
|
switch (input[1]) {
|
|
|
|
case '?': // entropy
|
|
|
|
eprintf ("Usage: p=[bep?]\n");
|
|
|
|
eprintf (" p= print bytes of current block in bars\n");
|
|
|
|
eprintf (" p=b same as above\n");
|
|
|
|
eprintf (" p=e same as above but with entropy\n");
|
|
|
|
eprintf (" p=p print number of printable bytes for each filesize/blocksize\n");
|
|
|
|
break;
|
|
|
|
case 'e': // entropy
|
|
|
|
{
|
2012-07-12 01:55:09 +00:00
|
|
|
ut8 *p;
|
2012-07-06 00:17:44 +00:00
|
|
|
int psz, i = 0;
|
|
|
|
int fsz = core->file?core->file->size:0;
|
2012-08-29 15:24:30 +00:00
|
|
|
psz = fsz / core->blocksize;
|
2012-07-06 00:17:44 +00:00
|
|
|
ptr = malloc (core->blocksize);
|
|
|
|
eprintf ("offset = num * %d\n", psz);
|
|
|
|
p = malloc (psz);
|
|
|
|
for (i=0; i<core->blocksize; i++) {
|
|
|
|
r_core_read_at (core, i*psz, p, psz);
|
|
|
|
ptr[i] = (ut8) (256 * r_hash_entropy_fraction (p, psz));
|
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'p': // printable chars
|
|
|
|
{
|
2012-07-12 01:55:09 +00:00
|
|
|
ut8 *p;
|
2012-07-06 00:17:44 +00:00
|
|
|
int psz, i = 0, j, k;
|
|
|
|
int fsz = core->file?core->file->size:0;
|
|
|
|
psz = fsz/core->blocksize;
|
|
|
|
ptr = malloc (core->blocksize);
|
|
|
|
p = malloc (psz);
|
|
|
|
for (i=0; i<core->blocksize; i++) {
|
|
|
|
r_core_read_at (core, i*psz, p, psz);
|
|
|
|
for (j=k=0; j<psz; j++) {
|
|
|
|
if (IS_PRINTABLE (p[j]))
|
|
|
|
k++;
|
|
|
|
}
|
|
|
|
ptr[i] = k;
|
|
|
|
}
|
|
|
|
free (p);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
r_print_fill (core->print, ptr, core->blocksize);
|
2012-08-29 15:24:30 +00:00
|
|
|
if (ptr != core->block) {
|
2012-08-28 15:50:49 +00:00
|
|
|
free (ptr);
|
2012-08-29 15:24:30 +00:00
|
|
|
#if 0
|
|
|
|
int bsize = 512;
|
|
|
|
/* TODO: Reimplement using API */
|
|
|
|
char *out = r_sys_cmd_strf ("rahash2 -a entropy -b %d '%s'", bsize, core->file->filename);
|
2012-02-27 01:40:27 +00:00
|
|
|
if (out) {
|
|
|
|
r_cons_strcat (out);
|
|
|
|
free (out);
|
|
|
|
}
|
2012-08-29 15:24:30 +00:00
|
|
|
#endif
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
break;
|
2012-09-18 01:39:32 +00:00
|
|
|
case 'a':
|
2012-09-19 01:15:36 +00:00
|
|
|
if (input[1]=='d') {
|
|
|
|
RAsmCode *c;
|
|
|
|
r_asm_set_pc (core->assembler, core->offset);
|
|
|
|
c = r_asm_mdisassemble_hexstr (core->assembler, input+2);
|
|
|
|
if (c) {
|
|
|
|
r_cons_puts (c->buf_asm);
|
|
|
|
r_asm_code_free (c);
|
|
|
|
} else eprintf ("Invalid hexstr\n");
|
|
|
|
} else {
|
2012-09-18 01:39:32 +00:00
|
|
|
RAsmCode *acode;
|
|
|
|
r_asm_set_pc (core->assembler, core->offset);
|
|
|
|
acode = r_asm_massemble (core->assembler, input+1);
|
|
|
|
if (acode && *acode->buf_hex) {
|
|
|
|
r_cons_printf ("%s\n", acode->buf_hex);
|
|
|
|
r_asm_code_free (acode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
case 'b': {
|
2013-07-11 22:29:27 +00:00
|
|
|
ut32 n;
|
|
|
|
int i, c;
|
|
|
|
char buf[32];
|
|
|
|
#define P(x) (IS_PRINTABLE(x)?x:'.')
|
|
|
|
#define SPLIT_BITS(x) memmove (x+5, x+4, 5); x[4]=0
|
|
|
|
for (i=c=0; i<len; i++,c++) {
|
|
|
|
if (c==0) r_print_offset (core->print, core->offset+i, 0, 0);
|
|
|
|
r_str_bits (buf, core->block+i, 8, NULL);
|
|
|
|
SPLIT_BITS (buf);
|
|
|
|
r_cons_printf ("%s.%s ", buf, buf+5);
|
|
|
|
if (c==3) {
|
|
|
|
const ut8 *b = core->block + i-3;
|
2013-10-10 23:24:30 +00:00
|
|
|
#define K(x) (b[3-x]<<(8*x))
|
2013-11-14 12:52:03 +00:00
|
|
|
n = K (0) | K (1) | K (2) | K (3);
|
2013-07-11 22:29:27 +00:00
|
|
|
r_cons_printf ("0x%08x %c%c%c%c\n",
|
2013-11-14 12:52:03 +00:00
|
|
|
n, P (b[0]), P (b[1]), P (b[2]), P (b[3]));
|
2013-07-11 22:29:27 +00:00
|
|
|
c = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-07-11 23:04:05 +00:00
|
|
|
case 'B': {
|
|
|
|
const int size = len*8;
|
|
|
|
char *buf = malloc (size+1);
|
|
|
|
if (buf) {
|
|
|
|
r_str_bits (buf, core->block, size, NULL);
|
|
|
|
r_cons_printf ("%s\n", buf);
|
|
|
|
free (buf);
|
|
|
|
} else eprintf ("ERROR: Cannot malloc %d bytes\n", size);
|
|
|
|
}
|
|
|
|
break;
|
2013-01-25 02:47:09 +00:00
|
|
|
case 'I':
|
|
|
|
r_core_print_disasm_instructions (core, len, l);
|
|
|
|
break;
|
2013-01-22 17:08:33 +00:00
|
|
|
case 'i':
|
2013-08-24 21:45:10 +00:00
|
|
|
switch (input[1]) {
|
|
|
|
case '?':
|
|
|
|
r_cons_printf ("Usage: pi[df] [num]\n");
|
|
|
|
break;
|
|
|
|
case 'd':
|
2013-04-30 22:40:26 +00:00
|
|
|
pdi (core, l, len, core->blocksize);
|
2013-08-24 21:45:10 +00:00
|
|
|
break;
|
|
|
|
case 'f':
|
|
|
|
{
|
|
|
|
RAnalFunction *f = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (f) {
|
|
|
|
r_core_print_disasm_instructions (core, f->size, l);
|
|
|
|
} else {
|
|
|
|
r_core_print_disasm_instructions (core,
|
|
|
|
core->blocksize, l);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2013-04-30 22:40:26 +00:00
|
|
|
r_core_print_disasm_instructions (core,
|
|
|
|
core->blocksize, l);
|
2013-08-24 21:45:10 +00:00
|
|
|
break;
|
2013-04-30 22:40:26 +00:00
|
|
|
}
|
2013-08-24 21:45:10 +00:00
|
|
|
return 0;
|
2012-02-27 01:40:27 +00:00
|
|
|
case 'D':
|
|
|
|
case 'd':
|
2013-11-14 12:52:03 +00:00
|
|
|
{
|
2013-11-24 00:44:00 +00:00
|
|
|
ut64 current_offset = core->offset;
|
2013-12-01 23:43:44 +00:00
|
|
|
ut32 new_bits = -1;
|
2013-11-24 00:44:00 +00:00
|
|
|
ut64 use_blocksize = core->blocksize;
|
2013-12-02 00:28:06 +00:00
|
|
|
int segoff, old_bits, pos = 0;
|
2013-12-01 23:43:44 +00:00
|
|
|
ut8 settings_changed = R_FALSE, bw_disassemble = R_FALSE;
|
2013-12-02 00:28:06 +00:00
|
|
|
char *new_arch, *old_arch;
|
2013-11-14 12:52:03 +00:00
|
|
|
ut32 pd_result = R_FALSE, processed_cmd = R_FALSE;
|
2013-11-22 01:19:16 +00:00
|
|
|
old_arch = strdup (r_config_get (core->config, "asm.arch"));
|
|
|
|
segoff = r_config_get (core->config, "asm.segoff");
|
|
|
|
old_bits = r_config_get_i (core->config, "asm.bits");
|
2013-11-14 12:52:03 +00:00
|
|
|
// XXX - this is necessay b/c radare will automatically
|
|
|
|
// swap flags if arch is x86 and bits == 16 see: __setsegoff in config.c
|
|
|
|
|
|
|
|
// get to the space
|
2013-11-26 02:25:31 +00:00
|
|
|
if (input[0])
|
|
|
|
for (pos = 1; pos < R_BIN_SIZEOF_STRINGS && input[pos]; pos++)
|
|
|
|
if (input[pos] == ' ') break;
|
2013-11-14 12:52:03 +00:00
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
if (!process_input (core, input+pos, &use_blocksize, &new_arch, &new_bits)) {
|
2013-11-14 12:52:03 +00:00
|
|
|
// XXX - print help message
|
|
|
|
//return R_FALSE;
|
|
|
|
}
|
2013-12-01 23:43:44 +00:00
|
|
|
if (!use_blocksize)
|
|
|
|
use_blocksize = core->blocksize;
|
2013-11-14 12:52:03 +00:00
|
|
|
|
2013-11-24 00:44:00 +00:00
|
|
|
if (core->blocksize_max < use_blocksize && (int)use_blocksize < -core->blocksize_max) {
|
2013-12-01 23:43:44 +00:00
|
|
|
eprintf ("This block size is too big (%"PFMT64d"<%"PFMT64d"). Did you mean 'p%c @ 0x%08"PFMT64x"' instead?\n",
|
|
|
|
(ut64)core->blocksize_max, (ut64)use_blocksize, input[0], (ut64) use_blocksize);
|
2013-11-14 12:52:03 +00:00
|
|
|
return R_FALSE;
|
2013-11-24 00:44:00 +00:00
|
|
|
} else if (core->blocksize_max < use_blocksize && (int)use_blocksize > -core->blocksize_max) {
|
|
|
|
bw_disassemble = R_TRUE;
|
|
|
|
use_blocksize = -use_blocksize;
|
2013-11-14 12:52:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (new_arch == NULL) new_arch = strdup (old_arch);
|
|
|
|
if (new_bits == -1) new_bits = old_bits;
|
|
|
|
|
2013-11-22 18:24:32 +00:00
|
|
|
if (strcmp (new_arch, old_arch) != 0 || new_bits != old_bits){
|
2013-11-14 12:52:03 +00:00
|
|
|
set_asm_configs (core, new_arch, new_bits, segoff);
|
2013-11-22 18:24:32 +00:00
|
|
|
settings_changed = R_TRUE;
|
|
|
|
}
|
2013-11-14 12:52:03 +00:00
|
|
|
|
2012-02-27 01:40:27 +00:00
|
|
|
switch (input[1]) {
|
2013-04-30 22:40:26 +00:00
|
|
|
case 'i':
|
2013-11-14 12:52:03 +00:00
|
|
|
processed_cmd = R_TRUE;
|
2013-04-30 22:40:26 +00:00
|
|
|
pdi (core, l, len, (*input=='D')? len: core->blocksize);
|
2013-11-14 12:52:03 +00:00
|
|
|
pd_result = 0;
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
processed_cmd = R_TRUE;
|
2013-11-24 00:44:00 +00:00
|
|
|
if (input[1] == 's') bw_disassemble = 1;
|
|
|
|
if (bw_disassemble) {
|
|
|
|
RList *bwdhits = NULL;
|
|
|
|
RListIter *iter = NULL;
|
|
|
|
RCoreAsmHit *hit = NULL;
|
|
|
|
ut8 *buf;
|
|
|
|
ut8 ignore_invalid = R_TRUE;
|
|
|
|
|
|
|
|
if (*input == 'D'){
|
|
|
|
ignore_invalid = R_FALSE;
|
|
|
|
bwdhits = r_core_asm_back_disassemble_byte (core,
|
|
|
|
core->offset, use_blocksize, -1, 0);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
bwdhits = r_core_asm_back_disassemble_instr (core,
|
|
|
|
core->offset, use_blocksize, -1, 0);
|
|
|
|
|
|
|
|
if (bwdhits) {
|
|
|
|
int result = 0;
|
|
|
|
RAsmOp asmop;
|
|
|
|
memset(&asmop, 0, sizeof (RAnalOp));
|
|
|
|
buf = malloc (1024);
|
|
|
|
|
|
|
|
r_list_foreach (bwdhits, iter, hit) {
|
|
|
|
r_core_read_at (core, hit->addr, buf, hit->len);
|
|
|
|
result = r_asm_disassemble (core->assembler, &asmop, buf, hit->len);
|
|
|
|
if (result<1) {
|
2013-12-01 23:43:44 +00:00
|
|
|
const char *owallawalla = "????";
|
|
|
|
char *hex_str = r_hex_bin2strdup (buf, hit->len);
|
|
|
|
if (hex_str == NULL) hex_str = (char *)owallawalla;
|
2013-11-24 00:44:00 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" %16s <invalid>\n", hit->addr, hex_str);
|
|
|
|
if (hex_str && hex_str != owallawalla) free(hex_str);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %16s %s\n",
|
|
|
|
hit->addr, asmop.buf_hex, asmop.buf_asm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
r_list_free (bwdhits);
|
|
|
|
free (buf);
|
|
|
|
pd_result = R_TRUE;
|
|
|
|
} else {
|
|
|
|
pd_result = R_FALSE;
|
|
|
|
}
|
|
|
|
pd_result = 0;
|
|
|
|
} else {
|
2013-11-14 12:52:03 +00:00
|
|
|
RAsmOp asmop;
|
|
|
|
ut8 *buf = core->block;
|
|
|
|
|
|
|
|
// init larger block
|
|
|
|
if (core->blocksize <= use_blocksize) {
|
|
|
|
buf = malloc (use_blocksize+1);
|
|
|
|
if (buf) r_core_read_at (core, core->offset, buf, use_blocksize);
|
|
|
|
else {
|
|
|
|
eprintf ("Error failed to malloc memory for disasm buffer.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (buf) {
|
2013-11-24 00:44:00 +00:00
|
|
|
ut8 go_by_instr = input[0] == 'd';
|
|
|
|
ut32 pdn_offset = 0;
|
|
|
|
ut64 instr_cnt = 0;
|
|
|
|
|
|
|
|
int dresult = 0;
|
|
|
|
|
|
|
|
for (pdn_offset=0; pdn_offset < use_blocksize; ) {
|
|
|
|
dresult = r_asm_disassemble (core->assembler, &asmop, buf+pdn_offset, use_blocksize-pdn_offset);
|
|
|
|
if (dresult<1) {
|
2013-12-01 23:43:44 +00:00
|
|
|
const char *owallawalla = "????";
|
|
|
|
char *hex_str = r_hex_bin2strdup (buf+pdn_offset, 1);
|
|
|
|
if (hex_str == NULL) hex_str = (char*)owallawalla;
|
2013-11-24 00:44:00 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" %16s <invalid>\n", core->offset+pdn_offset, hex_str);
|
|
|
|
pdn_offset += 1;
|
|
|
|
instr_cnt += asmop.inst_len;
|
2013-12-01 23:43:44 +00:00
|
|
|
if (hex_str && hex_str != owallawalla) free (hex_str);
|
2013-11-14 12:52:03 +00:00
|
|
|
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" %16s %s\n",
|
2013-11-24 00:44:00 +00:00
|
|
|
core->offset+pdn_offset, asmop.buf_hex, asmop.buf_asm);
|
2013-12-01 23:43:44 +00:00
|
|
|
pdn_offset += (go_by_instr? asmop.inst_len: 1);
|
2013-11-14 12:52:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (buf != core->block) free (buf);
|
|
|
|
pd_result = R_TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
case 'a':
|
2013-11-14 12:52:03 +00:00
|
|
|
processed_cmd = R_TRUE;
|
2012-02-27 01:40:27 +00:00
|
|
|
{
|
|
|
|
RAsmOp asmop;
|
2013-10-04 11:57:49 +00:00
|
|
|
int ret, err = 0;
|
|
|
|
ut8 *buf = core->block;
|
|
|
|
if (l<1) l = len;
|
|
|
|
if (l>=core->blocksize) {
|
|
|
|
buf = malloc (l+1);
|
|
|
|
r_core_read_at (core, core->offset, buf, l);
|
|
|
|
}
|
|
|
|
for (i=0; i<l; i++ ) {
|
2013-04-30 22:40:26 +00:00
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop,
|
2013-10-04 11:57:49 +00:00
|
|
|
buf+i, l-i);
|
2012-02-27 01:40:27 +00:00
|
|
|
if (ret<1) {
|
|
|
|
ret = err = 1;
|
2013-10-04 11:57:49 +00:00
|
|
|
//r_cons_printf ("???\n");
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" ???\n", core->offset+i);
|
2012-02-27 01:40:27 +00:00
|
|
|
} else r_cons_printf ("0x%08"PFMT64x" %16s %s\n",
|
|
|
|
core->offset+i, asmop.buf_hex, asmop.buf_asm);
|
|
|
|
}
|
2013-10-04 11:57:49 +00:00
|
|
|
if (buf != core->block)
|
|
|
|
free (buf);
|
2013-11-14 12:52:03 +00:00
|
|
|
pd_result = R_TRUE;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-03-03 23:33:14 +00:00
|
|
|
case 'r': // pdr
|
2013-11-14 12:52:03 +00:00
|
|
|
processed_cmd = R_TRUE;
|
2012-08-29 12:46:19 +00:00
|
|
|
{
|
2013-11-14 12:52:03 +00:00
|
|
|
RAnalFunction *f = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (f) {
|
|
|
|
RListIter *iter;
|
|
|
|
RAnalBlock *b;
|
|
|
|
// XXX: hack must be reviewed/fixed in code analysis
|
|
|
|
if (r_list_length (f->bbs) == 1) {
|
|
|
|
b = r_list_get_top (f->bbs);
|
|
|
|
if (b->size > f->size) b->size = f->size;
|
|
|
|
}
|
|
|
|
// TODO: sort by addr
|
|
|
|
r_list_foreach (f->bbs, iter, b) {
|
|
|
|
r_core_cmdf (core, "pD %"PFMT64d" @0x%"PFMT64x, b->size, b->addr);
|
|
|
|
if (b->jump != UT64_MAX)
|
|
|
|
r_cons_printf ("-[true]-> 0x%08"PFMT64x"\n", b->jump);
|
|
|
|
if (b->fail != UT64_MAX)
|
|
|
|
r_cons_printf ("-[false]-> 0x%08"PFMT64x"\n", b->fail);
|
|
|
|
r_cons_printf ("--\n");
|
|
|
|
}
|
|
|
|
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
|
|
|
pd_result = R_TRUE;
|
2012-08-29 12:46:19 +00:00
|
|
|
}
|
|
|
|
break;
|
2013-11-14 12:52:03 +00:00
|
|
|
case 'b':
|
|
|
|
processed_cmd = R_TRUE;
|
|
|
|
{
|
|
|
|
RAnalBlock *b = r_anal_bb_from_offset (core->anal, core->offset);
|
|
|
|
if (b) {
|
|
|
|
ut8 *block = malloc (b->size+1);
|
|
|
|
if (block) {
|
|
|
|
r_core_read_at (core, b->addr, block, b->size);
|
|
|
|
core->num->value = r_core_print_disasm (
|
|
|
|
core->print, core, b->addr, block,
|
|
|
|
b->size, 9999, 0, 2);
|
|
|
|
free (block);
|
|
|
|
pd_result = 0;
|
|
|
|
}
|
|
|
|
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2013-11-14 12:52:03 +00:00
|
|
|
case 'f':
|
|
|
|
processed_cmd = R_TRUE;
|
2012-02-27 01:40:27 +00:00
|
|
|
{
|
2013-11-14 12:52:03 +00:00
|
|
|
RAnalFunction *f = r_anal_fcn_find (core->anal, core->offset,
|
|
|
|
R_ANAL_FCN_TYPE_FCN|R_ANAL_FCN_TYPE_SYM);
|
|
|
|
if (f) {
|
|
|
|
ut8 *block = malloc (f->size+1);
|
|
|
|
if (block) {
|
|
|
|
r_core_read_at (core, f->addr, block, f->size);
|
|
|
|
core->num->value = r_core_print_disasm (
|
|
|
|
core->print, core, f->addr, block,
|
|
|
|
f->size, 9999, 0, 2);
|
|
|
|
free (block);
|
|
|
|
pd_result = 0;
|
|
|
|
}
|
|
|
|
} else eprintf ("Cannot find function at 0x%08"PFMT64x"\n", core->offset);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2013-11-14 12:52:03 +00:00
|
|
|
l = 0;
|
|
|
|
break;
|
|
|
|
case 'l':
|
|
|
|
processed_cmd = R_TRUE;
|
|
|
|
{
|
|
|
|
RAsmOp asmop;
|
|
|
|
int j, ret;
|
|
|
|
const ut8 *buf = core->block;
|
|
|
|
if (l==0) l= len;
|
|
|
|
for (i=j=0; i<core->blocksize && j<l; i+=ret,j++ ) {
|
|
|
|
ret = r_asm_disassemble (core->assembler, &asmop, buf+i, len-i);
|
|
|
|
printf ("%d\n", ret);
|
|
|
|
if (ret<1) ret = 1;
|
|
|
|
}
|
|
|
|
pd_result = 0;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
break;
|
2012-11-08 08:49:27 +00:00
|
|
|
case 'j':
|
2013-11-14 12:52:03 +00:00
|
|
|
processed_cmd = R_TRUE;
|
2012-11-08 08:49:27 +00:00
|
|
|
r_core_print_disasm_json (core, core->offset,
|
|
|
|
core->block, core->blocksize);
|
2013-11-14 12:52:03 +00:00
|
|
|
pd_result = 0;
|
2012-02-27 01:40:27 +00:00
|
|
|
case '?':
|
2013-11-14 12:52:03 +00:00
|
|
|
processed_cmd = R_TRUE;
|
|
|
|
eprintf ("Usage: pd[f|i|l] [len] [arch] [bits] @ [addr]\n"
|
2012-02-27 01:40:27 +00:00
|
|
|
//TODO: eprintf (" pdr : disassemble resume\n");
|
2013-12-02 02:53:29 +00:00
|
|
|
" pda disassemble all possible opcodes (byte per byte)\n"
|
|
|
|
" pdj disassemble to json\n"
|
|
|
|
" pdb disassemble basic block\n"
|
|
|
|
" pdr recursive disassemble across the function graph\n"
|
|
|
|
" pdf disassemble function\n"
|
|
|
|
" pdi like 'pi', with offset and bytes\n"
|
|
|
|
" pdn disassemble N bytes (like pdi)\n"
|
|
|
|
" pdl show instruction sizes\n"
|
|
|
|
" pds disassemble with back sweep (greedy disassembly backwards)\n");
|
2013-11-14 12:52:03 +00:00
|
|
|
pd_result = 0;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2013-11-22 18:24:32 +00:00
|
|
|
if (!processed_cmd) {
|
2013-11-24 00:44:00 +00:00
|
|
|
RList *hits;
|
|
|
|
RListIter *iter;
|
|
|
|
RCoreAsmHit *hit;
|
|
|
|
ut8 *block = malloc (core->blocksize);
|
|
|
|
|
|
|
|
if (block && bw_disassemble) {
|
|
|
|
l = -l;
|
2013-11-22 18:24:32 +00:00
|
|
|
if (block) {
|
2013-11-24 00:44:00 +00:00
|
|
|
if (*input == 'D'){
|
|
|
|
hits = r_core_asm_back_disassemble_byte (core,
|
|
|
|
core->offset, core->blocksize, use_blocksize, 5);
|
|
|
|
} else {
|
|
|
|
hits = r_core_asm_back_disassemble_instr (core,
|
|
|
|
core->offset, core->blocksize, use_blocksize, 5);
|
|
|
|
}
|
|
|
|
if (hits) {
|
|
|
|
r_list_foreach (hits, iter, hit) {
|
2013-11-22 18:24:32 +00:00
|
|
|
r_core_read_at (core, hit->addr,
|
2013-11-24 00:44:00 +00:00
|
|
|
block, core->blocksize);
|
|
|
|
if (*input == 'D') {
|
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
|
|
|
core, hit->addr, block, core->blocksize, l, 0, 1);
|
|
|
|
r_cons_printf ("------\n");
|
|
|
|
} else {
|
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
|
|
|
core, hit->addr, block, hit->len, l, 0, 1);
|
|
|
|
}
|
2013-11-22 18:24:32 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2013-11-24 00:44:00 +00:00
|
|
|
if (hits) r_list_free (hits);
|
|
|
|
}
|
|
|
|
} else if (block){
|
|
|
|
ut64 idx = 0;
|
|
|
|
RAsmOp asmop;
|
|
|
|
|
2013-12-02 02:53:29 +00:00
|
|
|
// XXX: issue with small blocks
|
2013-12-01 23:43:44 +00:00
|
|
|
for (i=0; i < use_blocksize; i++ ) {
|
2013-12-02 02:53:29 +00:00
|
|
|
ut64 addr = core->offset + i;
|
2013-11-24 00:44:00 +00:00
|
|
|
r_core_read_at (core, addr,
|
|
|
|
block, core->blocksize);
|
|
|
|
if (*input == 'D') {
|
2013-12-02 02:53:29 +00:00
|
|
|
// l must be smaller than blocksize
|
|
|
|
if (l>=core->blocksize) {
|
|
|
|
eprintf ("Invalid length\n");
|
|
|
|
} else {
|
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
|
|
|
core, addr, block, l, l, 0, 1);
|
|
|
|
}
|
|
|
|
break;
|
2013-11-24 00:44:00 +00:00
|
|
|
} else {
|
2013-12-02 02:53:29 +00:00
|
|
|
/*
|
2013-12-01 23:43:44 +00:00
|
|
|
ut32 disasm_len = r_asm_disassemble (core->assembler, &asmop, block,
|
2013-11-24 00:44:00 +00:00
|
|
|
core->blocksize);
|
|
|
|
if (disasm_len == 0) disasm_len++;
|
2013-12-02 02:53:29 +00:00
|
|
|
*/
|
2013-11-24 00:44:00 +00:00
|
|
|
core->num->value = r_core_print_disasm (core->print,
|
2013-12-02 02:53:29 +00:00
|
|
|
core, addr, block, l, l, 0, 0);
|
|
|
|
i += core->num->value-1; //disasm_len;
|
|
|
|
break;
|
2013-11-24 00:44:00 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-24 00:44:00 +00:00
|
|
|
core->offset = current_offset;
|
|
|
|
if (block) free(block);
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
2013-11-14 12:52:03 +00:00
|
|
|
|
2013-11-22 18:24:32 +00:00
|
|
|
// change back asm setting is they were changed
|
|
|
|
if (settings_changed)
|
|
|
|
set_asm_configs (core, old_arch, old_bits, segoff);
|
2013-11-14 12:52:03 +00:00
|
|
|
|
|
|
|
free (old_arch);
|
|
|
|
free (new_arch);
|
|
|
|
|
|
|
|
if (processed_cmd)
|
|
|
|
return pd_result;
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case 's':
|
2012-08-28 15:50:49 +00:00
|
|
|
switch (input[1]) {
|
2012-08-29 15:24:30 +00:00
|
|
|
case '?':
|
|
|
|
r_cons_printf ("Usage: ps[zpw] [N]\n"
|
|
|
|
" ps = print string\n"
|
2013-10-14 01:30:12 +00:00
|
|
|
" psb = print strings in current block\n"
|
2013-10-14 22:26:17 +00:00
|
|
|
" psx = show string with scaped chars\n"
|
2012-08-29 15:24:30 +00:00
|
|
|
" psz = print zero terminated string\n"
|
|
|
|
" psp = print pascal string\n"
|
|
|
|
" psw = print wide string\n");
|
|
|
|
break;
|
2013-10-14 22:26:17 +00:00
|
|
|
case 'x':
|
2013-10-19 22:25:37 +00:00
|
|
|
r_print_string (core->print, core->offset, core->block, len, 0);
|
2013-10-14 22:26:17 +00:00
|
|
|
break;
|
2013-10-14 01:30:12 +00:00
|
|
|
case 'b':
|
|
|
|
{
|
|
|
|
char *s = malloc (core->blocksize+1);
|
|
|
|
int i, j, hasnl = 0;;
|
|
|
|
if (s) {
|
|
|
|
memset (s, 0, core->blocksize);
|
|
|
|
// TODO: filter more chars?
|
|
|
|
for (i=j=0;i<core->blocksize; i++) {
|
|
|
|
char ch = (char)core->block[i];
|
|
|
|
if (!ch) {
|
|
|
|
if (!hasnl) {
|
|
|
|
if (*s) r_cons_printf ("%s\n", s);
|
|
|
|
j = 0;
|
|
|
|
s[0] = 0;
|
|
|
|
}
|
|
|
|
hasnl = 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
hasnl = 0;
|
|
|
|
if (IS_PRINTABLE (ch))
|
|
|
|
s[j++] = ch;
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s", s); // TODO: missing newline?
|
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-08-29 15:24:30 +00:00
|
|
|
case 'z':
|
|
|
|
{
|
|
|
|
char *s = malloc (core->blocksize+1);
|
|
|
|
int i, j;
|
|
|
|
if (s) {
|
|
|
|
memset (s, 0, core->blocksize);
|
|
|
|
// TODO: filter more chars?
|
|
|
|
for (i=j=0;i<core->blocksize; i++) {
|
|
|
|
char ch = (char)core->block[i];
|
|
|
|
if (!ch) break;
|
|
|
|
if (IS_PRINTABLE (ch))
|
|
|
|
s[j++] = ch;
|
|
|
|
}
|
|
|
|
r_cons_printf ("%s\n", s);
|
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-08-28 15:50:49 +00:00
|
|
|
case 'p':
|
|
|
|
{
|
2012-02-27 01:40:27 +00:00
|
|
|
int mylen = core->block[0];
|
|
|
|
// TODO: add support for 2-4 byte length pascal strings
|
2012-08-28 15:50:49 +00:00
|
|
|
if (mylen < core->blocksize) {
|
|
|
|
r_print_string (core->print, core->offset,
|
2013-04-04 21:19:19 +00:00
|
|
|
core->block+1, mylen, R_PRINT_STRING_ZEROEND);
|
2012-08-28 15:50:49 +00:00
|
|
|
core->num->value = mylen;
|
|
|
|
} else core->num->value = 0; // error
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'w':
|
2013-02-25 08:36:07 +00:00
|
|
|
r_print_string (core->print, core->offset, core->block, len,
|
|
|
|
R_PRINT_STRING_WIDE | R_PRINT_STRING_ZEROEND);
|
2012-08-28 15:50:49 +00:00
|
|
|
break;
|
|
|
|
case ' ':
|
2012-02-27 01:40:27 +00:00
|
|
|
len = r_num_math (core->num, input+2);
|
2013-02-25 08:36:07 +00:00
|
|
|
r_print_string (core->print, core->offset, core->block, len, 0);
|
2012-08-28 15:50:49 +00:00
|
|
|
break;
|
|
|
|
default:
|
2013-02-25 08:36:07 +00:00
|
|
|
r_print_string (core->print, core->offset, core->block, len,
|
|
|
|
R_PRINT_STRING_ZEROEND);
|
2012-08-28 15:50:49 +00:00
|
|
|
break;
|
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
if (input[1]=='?') {
|
|
|
|
r_cons_printf ("Usage: pm [file|directory]\n"
|
|
|
|
" r_magic will use given file/dir as reference\n"
|
|
|
|
" output of those magic can contain expressions like:\n"
|
|
|
|
" foo@0x40 # use 'foo' magic file on address 0x40\n"
|
|
|
|
" @0x40 # use current magic file on address 0x40\n"
|
|
|
|
" \\n # append newline\n"
|
|
|
|
" e dir.magic # defaults to "R_MAGIC_PATH"\n"
|
|
|
|
);
|
|
|
|
} else r_core_magic (core, input+1, R_TRUE);
|
|
|
|
break;
|
|
|
|
case 'u':
|
2013-02-25 08:36:07 +00:00
|
|
|
r_print_string (core->print, core->offset, core->block, len,
|
2013-10-14 22:26:17 +00:00
|
|
|
R_PRINT_STRING_URLENCODE |
|
|
|
|
((input[1]=='w')?R_PRINT_STRING_WIDE:0));
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case 'c':
|
2012-09-27 17:35:19 +00:00
|
|
|
r_print_code (core->print, core->offset, core->block, len, input[1]);
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
r_print_raw (core->print, core->block, len);
|
|
|
|
break;
|
|
|
|
case 'x':
|
2013-01-04 09:16:41 +00:00
|
|
|
{
|
|
|
|
int show_offset = r_config_get_i (core->config, "asm.offset");
|
|
|
|
if (show_offset) {
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_HEADER;
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_OFFSET;
|
|
|
|
} else {
|
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_OFFSET;
|
|
|
|
core->print->flags &= ~R_PRINT_FLAGS_HEADER;
|
|
|
|
}
|
|
|
|
}
|
2012-09-27 17:35:19 +00:00
|
|
|
switch (input[1]) {
|
2013-10-14 01:30:12 +00:00
|
|
|
case '/':
|
|
|
|
r_core_print_examine (core, input+2);
|
|
|
|
break;
|
2012-10-25 10:55:28 +00:00
|
|
|
case '?':
|
2013-10-19 21:35:39 +00:00
|
|
|
eprintf ("Usage: px[afoswqWqQ][f]\n"
|
2012-10-25 10:55:28 +00:00
|
|
|
" px show hexdump\n"
|
2013-10-19 21:35:39 +00:00
|
|
|
" px/ same as x/ in gdb (help x)\n"
|
2013-10-15 01:56:01 +00:00
|
|
|
" pxa show annotated hexdump\n"
|
2012-10-25 10:55:28 +00:00
|
|
|
" pxf show hexdump of current function\n"
|
|
|
|
" pxo show octal dump\n"
|
2013-10-19 21:35:39 +00:00
|
|
|
" pxq show hexadecimal quad-words dump (64bit)\n"
|
|
|
|
" pxs show hexadecimal in sparse mode\n"
|
2012-10-25 10:55:28 +00:00
|
|
|
" pxQ same as above, but one per line\n"
|
2013-10-19 21:35:39 +00:00
|
|
|
" pxw show hexadecimal words dump (32bit)\n"
|
|
|
|
" pxW same as above, but one per line\n"
|
2012-10-25 10:55:28 +00:00
|
|
|
);
|
|
|
|
break;
|
2013-10-15 01:56:01 +00:00
|
|
|
case 'a':
|
2013-10-19 22:25:37 +00:00
|
|
|
if (len%16)
|
|
|
|
len += 16-(len%16);
|
|
|
|
annotated_hexdump (core, input+2, len);
|
2013-10-15 01:56:01 +00:00
|
|
|
break;
|
2012-09-27 17:35:19 +00:00
|
|
|
case 'o':
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 8, 1);
|
|
|
|
break;
|
|
|
|
case 'w':
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 32, 4);
|
|
|
|
break;
|
2012-10-25 10:55:28 +00:00
|
|
|
case 'W':
|
|
|
|
for (i=0; i<len; i+=4) {
|
2012-10-25 13:21:47 +00:00
|
|
|
ut32 *p = (ut32*)core->block+i;
|
2012-10-25 10:55:28 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" 0x%08x\n", core->offset+i, *p);
|
|
|
|
}
|
|
|
|
break;
|
2012-09-27 17:35:19 +00:00
|
|
|
case 'q':
|
|
|
|
r_print_hexdump (core->print, core->offset, core->block, len, 64, 8);
|
|
|
|
break;
|
2012-10-25 10:55:28 +00:00
|
|
|
case 'Q':
|
|
|
|
for (i=0; i<len; i+=8) {
|
2012-10-25 13:21:47 +00:00
|
|
|
ut64 *p = (ut64*)core->block+i;
|
2012-10-25 10:55:28 +00:00
|
|
|
r_cons_printf ("0x%08"PFMT64x" 0x%016"PFMT64x"\n",
|
|
|
|
core->offset+i, *p);
|
|
|
|
}
|
|
|
|
break;
|
2013-10-19 21:35:39 +00:00
|
|
|
case 's':
|
|
|
|
core->print->flags |= R_PRINT_FLAGS_SPARSE;
|
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, len, 16, 1);
|
|
|
|
core->print->flags &= (((ut32)-1) & (~R_PRINT_FLAGS_SPARSE));
|
|
|
|
break;
|
2012-09-27 17:35:19 +00:00
|
|
|
default: {
|
|
|
|
ut64 from = r_config_get_i (core->config, "diff.from");
|
|
|
|
ut64 to = r_config_get_i (core->config, "diff.to");
|
|
|
|
if (from == to && from == 0) {
|
2013-01-04 09:16:41 +00:00
|
|
|
r_print_hexdump (core->print, core->offset,
|
|
|
|
core->block, len, 16, 1);
|
2012-09-27 17:35:19 +00:00
|
|
|
} else {
|
|
|
|
r_core_print_cmp (core, from, to);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2012-08-13 02:33:01 +00:00
|
|
|
}
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
case '6':
|
|
|
|
{
|
|
|
|
int malen = (core->blocksize*4)+1;
|
|
|
|
ut8 *buf = malloc (malen);
|
2013-11-06 01:24:02 +00:00
|
|
|
if (!buf) break;
|
2012-02-27 01:40:27 +00:00
|
|
|
memset (buf, 0, malen);
|
|
|
|
switch (input[1]) {
|
|
|
|
case 'd':
|
2012-08-19 01:28:17 +00:00
|
|
|
if (r_base64_decode (buf, core->block, len))
|
|
|
|
r_cons_printf ("%s\n", buf);
|
2012-02-27 01:40:27 +00:00
|
|
|
else eprintf ("r_base64_decode: invalid stream\n");
|
|
|
|
break;
|
2013-11-06 01:24:02 +00:00
|
|
|
case '?':
|
2013-11-14 12:52:03 +00:00
|
|
|
eprintf ("Usage: p6[ed] [len] base 64 encode/decode\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2013-11-06 01:24:02 +00:00
|
|
|
case 'e':
|
|
|
|
default:
|
|
|
|
r_base64_encode (buf, core->block, len); //core->blocksize);
|
|
|
|
r_cons_printf ("%s\n", buf);
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
}
|
|
|
|
free (buf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case '8':
|
|
|
|
r_print_bytes (core->print, core->block, len, "%02x");
|
|
|
|
break;
|
|
|
|
case 'f':
|
2013-02-01 02:15:48 +00:00
|
|
|
if (input[1]=='.') {
|
2013-01-22 04:06:12 +00:00
|
|
|
if (input[2]=='\0') {
|
|
|
|
RListIter *iter;
|
|
|
|
RStrHT *sht = core->print->formats;
|
|
|
|
int *i;
|
|
|
|
r_list_foreach (sht->ls, iter, i) {
|
|
|
|
int idx = ((int)(size_t)i)-1;
|
|
|
|
const char *key = r_strpool_get (sht->sp, idx);
|
|
|
|
const char *val = r_strht_get (core->print->formats, key);
|
2013-02-01 02:15:48 +00:00
|
|
|
r_cons_printf ("pf.%s %s\n", key, val);
|
2013-01-22 04:06:12 +00:00
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (input[2]=='-') {
|
|
|
|
if (input[3]) r_strht_del (core->print->formats, input+3);
|
|
|
|
else r_strht_clear (core->print->formats);
|
|
|
|
} else {
|
|
|
|
char *name = strdup (input+2);
|
|
|
|
char *space = strchr (name, ' ');
|
|
|
|
if (space) {
|
|
|
|
*space++ = 0;
|
|
|
|
//printf ("SET (%s)(%s)\n", name, space);
|
|
|
|
r_strht_set (core->print->formats, name, space);
|
|
|
|
return 0;
|
|
|
|
} else {
|
2013-02-07 02:09:53 +00:00
|
|
|
const char *fmt;
|
|
|
|
char *eq, *dot = strchr (name, '.');
|
2013-02-01 02:15:48 +00:00
|
|
|
if (dot) {
|
|
|
|
// TODO: support multiple levels
|
|
|
|
*dot++ = 0;
|
|
|
|
eq = strchr (dot, '=');
|
|
|
|
if (eq) {
|
|
|
|
char *res;
|
|
|
|
fmt = r_strht_get (core->print->formats, name);
|
|
|
|
// TODO: spaguettti, reuse code below.. and handle atoi() too
|
2013-06-16 23:42:32 +00:00
|
|
|
if (fmt) {
|
|
|
|
res = strdup (fmt);
|
|
|
|
*eq++ = 0;
|
2013-02-01 02:15:48 +00:00
|
|
|
#if 0
|
2013-06-16 23:42:32 +00:00
|
|
|
ut64 v;
|
|
|
|
v = r_num_math (NULL, eq);
|
|
|
|
r_print_format (core->print, core->offset,
|
|
|
|
core->block, core->blocksize, fmt, v, eq);
|
2013-02-01 02:15:48 +00:00
|
|
|
#endif
|
2013-06-16 23:42:32 +00:00
|
|
|
r_str_word_set0 (res);
|
|
|
|
for (i = 1; ; i++) {
|
|
|
|
const char *k = r_str_word_get0 (res, i);
|
|
|
|
if (!k) break;
|
|
|
|
if (!strcmp (k, dot)) {
|
|
|
|
r_print_format (core->print, core->offset,
|
|
|
|
core->block, core->blocksize, fmt, i-1, eq);
|
|
|
|
break;
|
|
|
|
}
|
2013-02-01 02:15:48 +00:00
|
|
|
}
|
2013-06-16 23:42:32 +00:00
|
|
|
free (res);
|
2013-02-01 02:15:48 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const char *k, *fmt = r_strht_get (core->print->formats, name);
|
|
|
|
if (fmt) {
|
|
|
|
if (atoi (dot)>0 || *dot=='0') {
|
|
|
|
// indexed field access
|
|
|
|
r_print_format (core->print, core->offset,
|
|
|
|
core->block, core->blocksize, fmt, atoi (dot), NULL);
|
|
|
|
} else {
|
|
|
|
char *res = strdup (fmt);
|
|
|
|
r_str_word_set0 (res);
|
|
|
|
for (i = 1; ; i++) {
|
|
|
|
k = r_str_word_get0 (res, i);
|
|
|
|
if (!k) break;
|
|
|
|
if (!strcmp (k, dot)) {
|
|
|
|
r_print_format (core->print, core->offset,
|
|
|
|
core->block, core->blocksize, fmt, i-1, NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free (res);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
const char *fmt = r_strht_get (core->print->formats, name);
|
|
|
|
if (fmt) {
|
|
|
|
//printf ("GET (%s) = %s\n", name, fmt);
|
|
|
|
r_print_format (core->print, core->offset,
|
|
|
|
core->block, len, fmt, -1, NULL);
|
|
|
|
} else eprintf ("Unknown format (%s)\n", name);
|
|
|
|
}
|
2013-01-22 04:06:12 +00:00
|
|
|
}
|
|
|
|
free (name);
|
|
|
|
}
|
2013-02-07 02:09:53 +00:00
|
|
|
} else r_print_format (core->print, core->offset,
|
|
|
|
core->block, len, input+1, -1, NULL);
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
2013-02-12 01:42:34 +00:00
|
|
|
case 'k':
|
|
|
|
{
|
|
|
|
char *s = r_print_randomart (core->block, core->blocksize, core->offset);
|
|
|
|
r_cons_printf ("%s\n", s);
|
|
|
|
free (s);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'K':
|
|
|
|
{
|
2013-08-25 22:51:36 +00:00
|
|
|
int w, h;
|
|
|
|
RConsCanvas *c;
|
|
|
|
w = r_cons_get_size (&h);
|
2013-02-12 01:42:34 +00:00
|
|
|
ut64 offset0 = core->offset;
|
2013-08-25 22:51:36 +00:00
|
|
|
int cols = (w/20);
|
|
|
|
int rows = (h/12);
|
|
|
|
int i, j;
|
|
|
|
char *s;
|
|
|
|
if (rows<1) rows = 1;
|
|
|
|
c = r_cons_canvas_new (w, rows*11);
|
|
|
|
for (i = 0; i<rows; i++) {
|
|
|
|
for (j = 0; j<cols; j++) {
|
|
|
|
r_cons_canvas_gotoxy (c, j*20, i*11);
|
|
|
|
core->offset += core->blocksize;
|
|
|
|
r_core_read_at (core, core->offset, core->block, core->blocksize);
|
|
|
|
s = r_print_randomart (core->block, core->blocksize, core->offset);
|
|
|
|
r_cons_canvas_write (c, s);
|
|
|
|
free (s);
|
|
|
|
}
|
2013-02-12 01:42:34 +00:00
|
|
|
}
|
2013-08-25 22:51:36 +00:00
|
|
|
r_cons_canvas_print (c);
|
|
|
|
r_cons_canvas_free (c);
|
2013-02-12 01:42:34 +00:00
|
|
|
r_core_read_at (core, offset0, core->block, core->blocksize);
|
|
|
|
core->offset = offset0;
|
|
|
|
}
|
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
case 'n': // easter penis
|
|
|
|
for (l=0; l<10; l++) {
|
|
|
|
printf ("\r8");
|
2013-08-25 22:51:36 +00:00
|
|
|
for (len=0; len<l; len++)
|
2012-02-27 01:40:27 +00:00
|
|
|
printf ("=");
|
|
|
|
printf ("D");
|
|
|
|
r_sys_usleep (100000);
|
|
|
|
fflush (stdout);
|
|
|
|
}
|
|
|
|
for (l=0; l<3; l++) {
|
|
|
|
printf ("~");
|
|
|
|
fflush (stdout);
|
|
|
|
r_sys_usleep (100000);
|
|
|
|
}
|
|
|
|
printf ("\n");
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
switch (input[1]) {
|
2012-10-25 10:55:28 +00:00
|
|
|
case ' ':
|
|
|
|
case '\0':
|
|
|
|
for (l=0; l<len; l+=sizeof (time_t))
|
|
|
|
r_print_date_unix (core->print, core->block+l, sizeof (time_t));
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
for (l=0; l<len; l+=4)
|
|
|
|
r_print_date_dos (core->print, core->block+l, 4);
|
|
|
|
break;
|
|
|
|
case 'n':
|
2013-02-22 20:05:08 +00:00
|
|
|
core->print->big_endian = !core->print->big_endian;
|
2012-10-25 10:55:28 +00:00
|
|
|
for (l=0; l<len; l+=sizeof (ut64))
|
|
|
|
r_print_date_w32 (core->print, core->block+l, sizeof (ut64));
|
2013-02-22 20:05:08 +00:00
|
|
|
core->print->big_endian = !core->print->big_endian;
|
2012-10-25 10:55:28 +00:00
|
|
|
break;
|
2012-02-27 01:40:27 +00:00
|
|
|
case '?':
|
|
|
|
r_cons_printf (
|
|
|
|
"Usage: pt[dn?]\n"
|
2013-02-22 20:05:08 +00:00
|
|
|
" pt print unix time (32 bit cfg.big_endian)\n"
|
|
|
|
" ptd print dos time (32 bit cfg.big_endian)\n"
|
|
|
|
" ptn print ntfs time (64 bit !cfg.big_endian)\n"
|
2012-02-27 01:40:27 +00:00
|
|
|
" pt? show help message\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
break;
|
2012-08-01 23:50:39 +00:00
|
|
|
case 'z':
|
2012-02-27 01:40:27 +00:00
|
|
|
if (input[1]=='?') {
|
|
|
|
r_cons_printf (
|
2012-09-28 00:20:52 +00:00
|
|
|
"Usage: pz [len]\n"
|
2012-02-27 01:40:27 +00:00
|
|
|
" print N bytes where each byte represents a block of filesize/N\n"
|
|
|
|
"Configuration:\n"
|
|
|
|
" zoom.maxsz : max size of block\n"
|
|
|
|
" zoom.from : start address\n"
|
|
|
|
" zoom.to : end address\n"
|
|
|
|
" zoom.byte : specify how to calculate each byte\n"
|
|
|
|
" p : number of printable chars\n"
|
|
|
|
" f : count of flags in block\n"
|
|
|
|
" s : strings in range\n"
|
|
|
|
" 0 : number of bytes with value '0'\n"
|
|
|
|
" F : number of bytes with value 0xFF\n"
|
|
|
|
" e : calculate entropy and expand to 0-255 range\n"
|
|
|
|
" h : head (first byte value)\n"
|
|
|
|
"WARNING: On big files, use 'zoom.byte=h' or restrict ranges\n");
|
|
|
|
} else {
|
|
|
|
char *oldzoom = NULL;
|
|
|
|
ut64 maxsize = r_config_get_i (core->config, "zoom.maxsz");
|
|
|
|
ut64 from, to;
|
|
|
|
int oldva = core->io->va;
|
|
|
|
|
|
|
|
from = 0;
|
|
|
|
core->io->va = 0;
|
|
|
|
to = r_io_size (core->io);
|
|
|
|
from = r_config_get_i (core->config, "zoom.from");
|
|
|
|
to = r_config_get_i (core->config, "zoom.to");
|
2012-08-01 23:50:39 +00:00
|
|
|
if (input[1] && input[1] != ' ') {
|
2012-02-27 01:40:27 +00:00
|
|
|
oldzoom = strdup (r_config_get (core->config, "zoom.byte"));
|
|
|
|
if (!r_config_set (core->config, "zoom.byte", input+1)) {
|
|
|
|
eprintf ("Invalid zoom.byte mode (%s)\n", input+1);
|
|
|
|
free (oldzoom);
|
|
|
|
return R_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
r_print_zoom (core->print, core, printzoomcallback,
|
|
|
|
from, to, core->blocksize, (int)maxsize);
|
|
|
|
if (oldzoom) {
|
|
|
|
r_config_set (core->config, "zoom.byte", oldzoom);
|
|
|
|
free (oldzoom);
|
|
|
|
}
|
|
|
|
if (oldva)
|
|
|
|
core->io->va = oldva;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
r_cons_printf (
|
2013-01-25 02:47:09 +00:00
|
|
|
"Usage: p[=68abcdDfiImrstuxz] [arg|len]\n"
|
2013-02-01 09:44:05 +00:00
|
|
|
" p= show entropy bars of full file\n"
|
|
|
|
" p6[de] [len] base64 decode/encode\n"
|
|
|
|
" p8 [len] 8bit hexpair list of bytes\n"
|
2013-08-29 14:59:24 +00:00
|
|
|
" pa[d] [hex|asm] print code from hex or bytes of given data\n"
|
2013-07-11 22:29:27 +00:00
|
|
|
" p[bB] [len] bitstream of N bytes\n"
|
2013-02-01 09:44:05 +00:00
|
|
|
" pc[p] [len] output C (or python) format\n"
|
2013-02-07 02:09:53 +00:00
|
|
|
" p[dD][lf] [l] disassemble N opcodes/bytes (see pd?)\n"
|
|
|
|
" pf[?|.nam] [fmt] print formatted data (pf.name, pf.name $<expr>) \n"
|
2013-08-24 21:45:10 +00:00
|
|
|
" p[iI][df] [len] print N instructions/bytes (f=func) (see pi? and pdi)\n"
|
2013-02-01 09:44:05 +00:00
|
|
|
" pm [magic] print libmagic data (pm? for more information)\n"
|
|
|
|
" pr [len] print N raw bytes\n"
|
2013-02-12 01:42:34 +00:00
|
|
|
" p[kK] [len] print key in randomart (K is for mosaic)\n"
|
2013-02-01 09:44:05 +00:00
|
|
|
" ps[pwz] [len] print pascal/wide/zero-terminated strings\n"
|
|
|
|
" pt[dn?] [len] print different timestamps\n"
|
|
|
|
" pu[w] [len] print N url encoded bytes (w=wide)\n"
|
2013-11-14 12:52:03 +00:00
|
|
|
" pv[jh] [mode] bar|json|histogram blocks (mode: e?search.in)\n"
|
2013-07-11 23:04:05 +00:00
|
|
|
" p[xX][owq] [len] hexdump of N bytes (o=octal, w=32bit, q=64bit)\n"
|
2013-09-18 20:16:18 +00:00
|
|
|
" pz [len] print zoom view (see pz? for help)\n"
|
|
|
|
" pwd display current working directory\n");
|
2012-02-27 01:40:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (tbs != core->blocksize)
|
|
|
|
r_core_block_size (core, tbs);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-02-27 02:07:32 +00:00
|
|
|
static int cmd_hexdump(void *data, const char *input) {
|
|
|
|
return cmd_print (data, input-1);
|
|
|
|
}
|
2013-07-11 22:29:27 +00:00
|
|
|
|
2013-11-04 03:07:58 +00:00
|
|
|
// TODO : move to r_util? .. depends on r_cons...
|
2013-07-11 22:29:27 +00:00
|
|
|
R_API void r_print_offset(RPrint *p, ut64 off, int invert, int opt) {
|
|
|
|
int show_color = p->flags & R_PRINT_FLAGS_COLOR;
|
|
|
|
if (show_color) {
|
|
|
|
const char *k = r_cons_singleton ()->pal.offset; // TODO etooslow. must cache
|
|
|
|
if (invert)
|
|
|
|
r_cons_invert (R_TRUE, R_TRUE);
|
|
|
|
if (opt) {
|
|
|
|
ut32 s, a;
|
|
|
|
a = off & 0xffff;
|
|
|
|
s = (off-a)>>4;
|
|
|
|
r_cons_printf ("%s%04x:%04x"Color_RESET,
|
|
|
|
k, s&0xFFFF, a&0xFFFF);
|
|
|
|
} else r_cons_printf ("%s0x%08"PFMT64x""Color_RESET, k, off);
|
2013-10-24 21:11:56 +00:00
|
|
|
r_cons_puts (" ");
|
2013-11-04 03:07:58 +00:00
|
|
|
} else {
|
|
|
|
if (opt) {
|
|
|
|
ut32 s, a;
|
|
|
|
a = off & 0xffff;
|
|
|
|
s = (off-a)>>4;
|
|
|
|
r_cons_printf ("%04x:%04x", s&0xFFFF, a&0xFFFF);
|
|
|
|
} else {
|
|
|
|
r_cons_printf ("0x%08"PFMT64x" ", off);
|
|
|
|
}
|
|
|
|
}
|
2013-07-11 22:29:27 +00:00
|
|
|
}
|