diff --git a/libr/core/cbin.c b/libr/core/cbin.c index bde4ac2af4..91ced61610 100644 --- a/libr/core/cbin.c +++ b/libr/core/cbin.c @@ -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", diff --git a/libr/core/cmd_info.c b/libr/core/cmd_info.c index 341fdecf05..05249abcce 100644 --- a/libr/core/cmd_info.c +++ b/libr/core/cmd_info.c @@ -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"