mirror of
https://github.com/radareorg/radare2.git
synced 2025-02-09 07:42:25 +00:00
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:
parent
c853c02880
commit
c6e8fb1e30
@ -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~...)");
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user