Implement icc*, in sync with ic* to get C strcuts from mach0 classes into r2 ##bin

This commit is contained in:
pancake 2020-03-30 01:47:15 +02:00 committed by radare
parent 2b0962af31
commit 5881fcd2e1
2 changed files with 117 additions and 17 deletions

View File

@ -3060,6 +3060,84 @@ static int bin_trycatch(RCore *core, int mode) {
return true;
}
// https://nshipster.com/type-encodings/
static char *objc_type_toc(const char *objc_type) {
if (!objc_type) {
return strdup ("void*");
}
if (*objc_type == '^' && objc_type[1] == '{') {
char *a = strdup (objc_type + 2);
char *b = strchr (a, '>');
if (b) {
*b = 0;
}
a[strlen (a) - 1] = 0;
return a;
}
if (*objc_type == '<') {
char *a = strdup (objc_type + 1);
char *b = strchr (a, '>');
if (b) {
*b = 0;
}
return a;
}
if (!strcmp (objc_type, "f")) { return strdup ("float"); }
if (!strcmp (objc_type, "d")) { return strdup ("double"); }
if (!strcmp (objc_type, "i")) { return strdup ("int"); }
if (!strcmp (objc_type, "s")) { return strdup ("short"); }
if (!strcmp (objc_type, "l")) { return strdup ("long"); }
if (!strcmp (objc_type, "L")) { return strdup ("unsigned long"); }
if (!strcmp (objc_type, "*")) { return strdup ("char*"); }
if (!strcmp (objc_type, "c")) { return strdup ("bool"); }
if (!strcmp (objc_type, "v")) { return strdup ("void"); }
if (!strcmp (objc_type, "#")) { return strdup ("class"); }
if (!strcmp (objc_type, "B")) { return strdup ("cxxbool"); }
if (!strcmp (objc_type, "Q")) { return strdup ("uint64_t"); }
if (!strcmp (objc_type, "q")) { return strdup ("long long"); }
if (!strcmp (objc_type, "C")) { return strdup ("uint8_t"); }
if (strlen (objc_type) == 1) {
eprintf ("Unknown objc type '%s'\n", objc_type);
}
if (r_str_startswith (objc_type, "@\"")) {
char *s = r_str_newf ("struct %s", objc_type + 2);
s[strlen (s) - 1] = '*';
return s;
}
return strdup (objc_type);
}
static char *objc_name_toc(const char *objc_name) {
const char *n = r_str_lchr (objc_name, ')');
char *s = strdup (n? n + 1: objc_name);
char *p = strchr (s, '(');
if (p) {
*p = 0;
}
return s;
}
static void classdump_c(RCore *r, RBinClass *c) {
r_cons_printf ("typedef struct class_%s {\n", c->name);
RListIter *iter2;
RBinField *f;
// XXX this is a hack because r2 doesnt supports empty structs yet
// XXX https://github.com/radareorg/radare2/issues/16342
if (r_list_empty (c->fields)) {
r_cons_printf ("void *padding;\n");
}
r_list_foreach (c->fields, iter2, f) {
if (f->type && f->name) {
char *n = objc_name_toc (f->name);
char *t = objc_type_toc (f->type);
r_cons_printf (" %s %s; // %d\n", t, n, f->offset);
free (t);
free (n);
}
}
r_cons_printf ("} %s;\n\n", c->name);
}
static void classdump_objc(RCore *r, RBinClass *c) {
if (c->super) {
r_cons_printf ("@interface %s : %s\n{\n", c->name, c->super);
@ -3143,7 +3221,7 @@ static int bin_classes(RCore *r, int mode) {
return false;
}
r_flag_space_set (r->flags, R_FLAGS_FS_CLASSES);
} else if (IS_MODE_RAD (mode)) {
} else if (IS_MODE_RAD (mode) && !IS_MODE_CLASSDUMP (mode)) {
r_cons_println ("fs classes");
}
@ -3194,6 +3272,21 @@ static int bin_classes(RCore *r, int mode) {
r_cons_printf ("0x%08"PFMT64x" [0x%08"PFMT64x" - 0x%08"PFMT64x"] %s%s%s\n",
c->addr, at_min, at_max, c->name, c->super ? " " : "",
c->super ? c->super : "");
} else if (IS_MODE_CLASSDUMP (mode)) {
if (c) {
RBinFile *bf = r_bin_cur (r->bin);
if (bf && bf->o) {
if (IS_MODE_RAD (mode)) {
classdump_c (r, c);
} else if (bf->o->lang == R_BIN_NM_JAVA || (bf->o->info && bf->o->info->lang && strstr (bf->o->info->lang, "dalvik"))) {
classdump_java (r, c);
} else {
classdump_objc (r, c);
}
} else {
classdump_objc (r, c);
}
}
} else if (IS_MODE_RAD (mode)) {
char *n = __filterShell (name);
r_cons_printf ("\"f class.%s = 0x%"PFMT64x"\"\n", n, at_min);
@ -3228,6 +3321,23 @@ static int bin_classes(RCore *r, int mode) {
}
R_FREE (mflags);
}
r_list_foreach (c->fields, iter2, f) {
char *fn = r_str_newf ("field.%s.%s", c->name, f->name);
ut64 at = f->vaddr; // sym->vaddr + (f->vaddr & 0xffff);
r_cons_printf ("\"f %s = 0x%08"PFMT64x"\"\n", fn, at);
free (fn);
}
// C struct
r_cons_printf ("\"td struct %s {", c->name);
r_list_foreach (c->fields, iter2, f) {
char *n = objc_name_toc (f->name);
char *t = objc_type_toc (f->type);
r_cons_printf (" %s %s;", t, n);
free (t);
free (n);
}
r_cons_printf ("};\"\n");
} else if (IS_MODE_JSON (mode)) {
if (c->super) {
r_cons_printf ("%s{\"classname\":\"%s\",\"addr\":%"PFMT64d",\"index\":%d,\"visibility\":\"%s\",\"super\":\"%s\",\"methods\":[",
@ -3262,19 +3372,6 @@ static int bin_classes(RCore *r, int mode) {
}
}
r_cons_printf ("]}");
} else if (IS_MODE_CLASSDUMP (mode)) {
if (c) {
RBinFile *bf = r_bin_cur (r->bin);
if (bf && bf->o) {
if (bf->o->lang == R_BIN_NM_JAVA || (bf->o->info && bf->o->info->lang && strstr (bf->o->info->lang, "dalvik"))) {
classdump_java (r, c);
} else {
classdump_objc (r, c);
}
} else {
classdump_objc (r, c);
}
}
} else {
int m = 0;
r_cons_printf ("0x%08"PFMT64x" [0x%08"PFMT64x" - 0x%08"PFMT64x"] %6"PFMT64d" class %d %s",

View File

@ -1045,7 +1045,7 @@ static int cmd_info(void *data, const char *input) {
if (!obj) {
break;
}
if (input[2] && input[2] != 'j' && !strstr (input, "qq")) {
if (input[2] && input[2] != '*' && input[2] != 'j' && !strstr (input, "qq")) {
bool radare2 = strstr (input, "**") != NULL;
int idx = -1;
const char * cls_name = NULL;
@ -1134,7 +1134,7 @@ static int cmd_info(void *data, const char *input) {
r_cons_printf ("%s\n", cls->name);
}
}
} else if (input[1] == 'l' && obj) { // "icl"
} else if (input[1] == 'l') { // "icl"
r_list_foreach (obj->classes, iter, cls) {
r_list_foreach (cls->methods, iter2, sym) {
const char *comma = iter2->p? " ": "";
@ -1144,8 +1144,11 @@ static int cmd_info(void *data, const char *input) {
r_cons_newline ();
}
}
} else if (input[1] == 'c' && obj) { // "icc"
} else if (input[1] == 'c') { // "icc"
mode = R_MODE_CLASSDUMP;
if (input[2] == '*') {
mode |= R_MODE_RADARE;
}
RBININFO ("classes", R_CORE_BIN_ACC_CLASSES, NULL, r_list_length (obj->classes));
input = " ";
} else { // "icq"