Add anal classes to "Vb" (#16383) ##visual

* base draft for Vb for anal classes
* Added color and boundary check
* Added placeholder print of selection from class.c
This commit is contained in:
HoundThe 2020-04-04 10:58:08 +02:00 committed by GitHub
parent c853c02880
commit c6e8fb1e30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 217 additions and 0 deletions

View File

@ -2131,6 +2131,7 @@ R_API void r_core_visual_browse(RCore *core, const char *input) {
" _ hud mode (V_)\n"
" 1 bit editor (vd1)\n"
" b blocks\n"
" a anal classes\n"
" c classes\n"
" C comments\n"
" d debug traces\n"
@ -2212,6 +2213,9 @@ R_API void r_core_visual_browse(RCore *core, const char *input) {
case 'c': // "vbc"
r_core_visual_classes (core);
break;
case 'a': // "vba"
r_core_visual_anal_classes (core);
break;
case 'C': // "vbC"
r_core_visual_comments (core);
//r_core_cmd0 (core, "s $(CC~...)");

View File

@ -1345,6 +1345,218 @@ R_API int r_core_visual_classes(RCore *core) {
return true;
}
static void anal_class_print(RAnal *anal, const char *class_name) {
RVector *bases = r_anal_class_base_get_all (anal, class_name);
RVector *vtables = r_anal_class_vtable_get_all (anal, class_name);
RVector *methods = r_anal_class_method_get_all (anal, class_name);
r_cons_print (class_name);
if (bases) {
RAnalBaseClass *base;
bool first = true;
r_vector_foreach (bases, base) {
if (first) {
r_cons_print (": ");
first = false;
} else {
r_cons_print (", ");
}
r_cons_print (base->class_name);
}
r_vector_free (bases);
}
r_cons_print ("\n");
if (vtables) {
RAnalVTable *vtable;
r_vector_foreach (vtables, vtable) {
r_cons_printf (" %2s vtable 0x%"PFMT64x" @ +0x%"PFMT64x" size:+0x%"PFMT64x"\n", vtable->id, vtable->addr, vtable->offset, vtable->size);
}
r_vector_free (vtables);
}
r_cons_print ("\n");
if (methods) {
RAnalMethod *meth;
r_vector_foreach (methods, meth) {
r_cons_printf (" %s @ 0x%"PFMT64x, meth->name, meth->addr);
if (meth->vtable_offset >= 0) {
r_cons_printf (" (vtable + 0x%"PFMT64x")\n", (ut64)meth->vtable_offset);
} else {
r_cons_print ("\n");
}
}
r_vector_free (methods);
}
}
static const char *show_anal_classes(RCore *core, char mode, int *idx, SdbList *list, const char *class_name) {
bool show_color = r_config_get_i (core->config, "scr.color");
SdbListIter *iter;
SdbKv *kv;
int i = 0;
int skip = *idx - 10;
const char * cur_class;
r_cons_printf ("[hjkl_/Cfm]> anal classes:\n\n");
if (mode == 'd' && class_name) {
anal_class_print (core->anal, class_name);
return class_name;
}
ls_foreach (list, iter, kv) {
if (*idx > 10) {
skip--;
if (skip > 0) {
i++;
continue;
}
}
class_name = sdbkv_key (kv);
if (show_color) {
const char *pointer = "- ";
const char *txt_clr = "";
if (i == *idx) {
pointer = Color_GREEN ">>";
txt_clr = Color_YELLOW;
cur_class = class_name;
}
r_cons_printf ("%s" Color_RESET " %02d"
" %s%s\n" Color_RESET, pointer, i, txt_clr, class_name);
} else {
r_cons_printf ("%s %02d %s\n", (i==*idx) ? ">>" : "- ", i, class_name);
}
i++;
}
return cur_class;
}
// TODO add other commands that Vbc has
// Should the classes be refreshed after command execution with :
// in case new class information would be added?
// Add grep?
R_API int r_core_visual_anal_classes(RCore *core) {
int ch, index = 0;
char command[1024];
SdbList *list = r_anal_class_get_all (core->anal, true);
int oldcur = 0;
char mode = ' ';
const char *class_name = "";
if (r_list_empty (list)) {
r_cons_message ("No Classes");
goto cleanup;
}
for (;;) {
int cols;
r_cons_clear00 ();
class_name = show_anal_classes (core, mode, &index, list, class_name);
/* update terminal size */
(void) r_cons_get_size (&cols);
r_cons_visual_flush ();
ch = r_cons_readchar ();
if (ch == -1 || ch == 4) {
goto cleanup;
}
ch = r_cons_arrow_to_hjkl (ch); // get ESC+char, return 'hjkl' char
switch (ch) {
case 'C':
r_config_toggle (core->config, "scr.color");
break;
case 'J':
index += 10;
if (index >= list->length) {
index = list->length -1;
}
break;
case 'j':
if (++index >= list->length) {
index = 0;
}
break;
case 'k':
if (--index < 0) {
index = list->length - 1;
}
break;
case 'K':
index -= 10;
if (index < 0) {
index = 0;
}
break;
case 'g':
index = 0;
break;
case 'G':
index = list->length - 1;
break;
case 'h':
case 127: // backspace
case 'b': // back
case 'Q':
case 'c':
case 'q':
if (mode == ' ') {
goto cleanup;
}
mode = ' ';
index = oldcur;
break;
case 'l':
case ' ':
case '\r':
case '\n':
mode = 'd';
break;
case '?':
r_cons_clear00 ();
r_cons_printf (
"\nVF: Visual Classes help:\n\n"
" q - quit menu\n"
" j/k - down/up keys\n"
" h/b - go back\n"
" g/G - go first/last item\n"
" l/' ' - accept current selection\n"
" : - enter command\n");
r_cons_flush ();
r_cons_any_key (NULL);
break;
case ':':
r_cons_show_cursor (true);
r_cons_set_raw (0);
command[0] = '\0';
r_line_set_prompt (":> ");
if (r_cons_fgets (command, sizeof (command), 0, NULL) < 0) {
command[0]='\0';
}
//line[strlen(line)-1]='\0';
r_core_cmd (core, command, 1);
r_cons_set_raw (1);
r_cons_show_cursor (false);
if (command[0]) {
r_cons_any_key (NULL);
}
//cons_gotoxy(0,0);
r_cons_clear ();
break;
}
}
cleanup:
ls_free(list);
return true;
}
static int flag_name_sort(const void *a, const void *b) {
const RFlagItem *fa = (const RFlagItem *)a;
const RFlagItem *fb = (const RFlagItem *)b;

View File

@ -441,6 +441,7 @@ R_API bool r_core_prevop_addr(RCore* core, ut64 start_addr, int numinstrs, ut64*
R_API ut64 r_core_prevop_addr_force(RCore *core, ut64 start_addr, int numinstrs);
R_API bool r_core_visual_hudstuff(RCore *core);
R_API int r_core_visual_classes(RCore *core);
R_API int r_core_visual_anal_classes(RCore *core);
R_API int r_core_visual_types(RCore *core);
R_API int r_core_visual(RCore *core, const char *input);
R_API int r_core_visual_graph(RCore *core, RAGraph *g, RAnalFunction *_fcn, int is_interactive);