Fix #14540 - klass->super must be an RList instead of char* ##bin
This commit is contained in:
parent
ddda012afc
commit
f09557c7f8
|
@ -1051,7 +1051,10 @@ R_IPI RBinClass *r_bin_class_new(const char *name, const char *super, int view)
|
|||
RBinClass *c = R_NEW0 (RBinClass);
|
||||
if (c) {
|
||||
c->name = strdup (name);
|
||||
c->super = super? strdup (super): NULL;
|
||||
if (super) {
|
||||
c->super = r_list_newf (free);
|
||||
r_list_append (c->super, strdup (super));
|
||||
}
|
||||
c->methods = r_list_newf (r_bin_symbol_free);
|
||||
c->fields = r_list_newf (r_bin_field_free);
|
||||
c->visibility = view;
|
||||
|
@ -1062,7 +1065,7 @@ R_IPI RBinClass *r_bin_class_new(const char *name, const char *super, int view)
|
|||
R_IPI void r_bin_class_free(RBinClass *k) {
|
||||
if (k) {
|
||||
free (k->name);
|
||||
free (k->super);
|
||||
r_list_free (k->super);
|
||||
free (k->visibility_str);
|
||||
r_list_free (k->methods);
|
||||
r_list_free (k->fields);
|
||||
|
@ -1075,8 +1078,9 @@ R_API RBinClass *r_bin_file_add_class(RBinFile *bf, const char *name, const char
|
|||
RBinClass *c = __getClass (bf, name);
|
||||
if (c) {
|
||||
if (super) {
|
||||
free (c->super);
|
||||
c->super = strdup (super);
|
||||
r_list_free (c->super);
|
||||
c->super = r_list_newf (free);
|
||||
r_list_append (c->super, strdup (super));
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
|
|
@ -1189,7 +1189,8 @@ void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe,
|
|||
|
||||
klass->addr = c.isa;
|
||||
if (c.superclass) {
|
||||
klass->super = get_class_name (c.superclass, bf);
|
||||
klass->super = r_list_newf (free);
|
||||
r_list_append (klass->super, get_class_name (c.superclass, bf));
|
||||
} else if (relocs) {
|
||||
struct reloc_t reloc_at_class_addr;
|
||||
reloc_at_class_addr.addr = p + sizeof (mach0_ut);
|
||||
|
@ -1200,7 +1201,8 @@ void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe,
|
|||
char *target_class_name = (char*) ((struct reloc_t*) found->data)->name;
|
||||
if (r_str_startswith (target_class_name, _objc_class)) {
|
||||
target_class_name += _objc_class_len;
|
||||
klass->super = strdup (target_class_name);
|
||||
klass->super = r_list_newf (free);
|
||||
r_list_append (klass->super, strdup (target_class_name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1208,7 +1210,7 @@ void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe,
|
|||
|
||||
#if SWIFT_SUPPORT
|
||||
if (q (c.data + n_value) & 7) {
|
||||
eprintf ("This is a Swift class\n");
|
||||
R_LOG_DEBUG ("This is a Swift class");
|
||||
}
|
||||
#endif
|
||||
if (!is_meta_class && !dupe) {
|
||||
|
@ -1616,9 +1618,10 @@ static RList *MACH0_(parse_categories)(RBinFile *bf, RSkipList *relocs, objc_cac
|
|||
if (cpar) {
|
||||
*cpar = 0;
|
||||
}
|
||||
r_list_free (klass->super);
|
||||
klass->super = r_list_newf (free);
|
||||
r_list_append (klass->super, super);
|
||||
// char *name = strdup (super + idx);
|
||||
free (klass->super);
|
||||
klass->super = super;
|
||||
// free (klass->name);
|
||||
// klass->name = name;
|
||||
}
|
||||
|
|
|
@ -1467,7 +1467,10 @@ static void parse_class(RBinFile *bf, RBinDexClass *c, int class_index, int *met
|
|||
cls->addr = dex->header.class_offset + (class_index * DEX_CLASS_SIZE);
|
||||
cls->methods = r_list_new ();
|
||||
const char *super = dex_class_super_name (dex, c);
|
||||
cls->super = super? strdup (super): NULL;
|
||||
if (super) {
|
||||
cls->super = r_list_newf (free);
|
||||
r_list_append (cls->super, strdup (super));
|
||||
}
|
||||
if (!cls->methods) {
|
||||
free (cls);
|
||||
goto beach;
|
||||
|
@ -1484,7 +1487,15 @@ static void parse_class(RBinFile *bf, RBinDexClass *c, int class_index, int *met
|
|||
rbin->cb_printf (" Class descriptor : '%s;'\n", cls->name);
|
||||
rbin->cb_printf (" Access flags : 0x%04x (%s)\n", c->access_flags,
|
||||
r_str_get (cls->visibility_str));
|
||||
rbin->cb_printf (" Superclass : '%s'\n", cls->super);
|
||||
if (cls->super) {
|
||||
char *sk;
|
||||
RListIter *iter;
|
||||
rbin->cb_printf (" Superclass : '");
|
||||
r_list_foreach (cls->super, iter, sk) {
|
||||
rbin->cb_printf ("%s%s", iter->n? ",": "", sk);
|
||||
}
|
||||
rbin->cb_printf ("'\n");
|
||||
}
|
||||
rbin->cb_printf (" Interfaces -\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -3454,7 +3454,28 @@ static void classdump_c(RCore *r, RBinClass *c) {
|
|||
|
||||
static void classdump_objc(RCore *r, RBinClass *c) {
|
||||
if (c->super) {
|
||||
r_cons_printf ("@interface %s : %s\n{\n", c->name, c->super);
|
||||
int n = 0;
|
||||
r_cons_printf ("@interface %s :", c->name);
|
||||
const char *sk;
|
||||
RListIter *iter;
|
||||
r_list_foreach (c->super, iter, sk) {
|
||||
switch (n) {
|
||||
case 0:
|
||||
r_cons_printf (" %s", sk);
|
||||
break;
|
||||
case 1:
|
||||
r_cons_printf ("< %s", sk);
|
||||
break;
|
||||
default:
|
||||
r_cons_printf (", %s", sk);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (r_list_length (c->super) > 1) {
|
||||
r_cons_printf (" >\n{\n");
|
||||
} else {
|
||||
r_cons_printf ("\n{\n");
|
||||
}
|
||||
} else {
|
||||
r_cons_printf ("@interface %s\n{\n", c->name);
|
||||
}
|
||||
|
@ -3586,9 +3607,11 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
|
|||
} else if (IS_MODE_SIMPLEST (mode)) {
|
||||
r_cons_printf ("%s\n", c->name);
|
||||
} else if (IS_MODE_SIMPLE (mode)) {
|
||||
char *supers = r_str_list_join (c->super, ", ");
|
||||
r_cons_printf ("0x%08"PFMT64x" [0x%08"PFMT64x" - 0x%08"PFMT64x"] %s %s%s%s\n",
|
||||
c->addr, at_min, at_max, r_bin_lang_tostring (c->lang), c->name, c->super ? " " : "",
|
||||
r_str_get (c->super));
|
||||
r_str_get (supers));
|
||||
free (supers);
|
||||
} else if (IS_MODE_CLASSDUMP (mode)) {
|
||||
if (c) {
|
||||
RBinFile *bf = r_bin_cur (r->bin);
|
||||
|
@ -3607,14 +3630,17 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
|
|||
} else if (IS_MODE_RAD (mode)) {
|
||||
char *n = __filterShell (name);
|
||||
r_cons_printf ("\"f class.%s = 0x%"PFMT64x"\"\n", n, at_min);
|
||||
free (n);
|
||||
if (c->super) {
|
||||
char *cn = c->name; // __filterShell (c->name);
|
||||
char *su = c->super; // __filterShell (c->super);
|
||||
r_cons_printf ("\"f super.%s.%s = %d\"\n",
|
||||
cn, su, c->index);
|
||||
// free (cn);
|
||||
// free (su);
|
||||
char *cn = c->name;
|
||||
RListIter *iter;
|
||||
const char *sk;
|
||||
r_list_foreach (c->super, iter, sk) {
|
||||
char *fsk = strdup (sk);
|
||||
r_name_filter (fsk, -1);
|
||||
r_cons_printf ("\"f super.%s.%s = %d\"\n",
|
||||
cn, fsk, c->index);
|
||||
free (fsk);
|
||||
}
|
||||
}
|
||||
r_list_foreach (c->methods, iter2, sym) {
|
||||
char *mflags = r_core_bin_method_flags_str (sym->method_flags, mode);
|
||||
|
@ -3662,6 +3688,7 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
|
|||
}
|
||||
}
|
||||
r_cons_printf ("};\"\n");
|
||||
free (n);
|
||||
} else if (IS_MODE_JSON (mode)) {
|
||||
pj_o (pj);
|
||||
pj_ks (pj, "classname", c->name);
|
||||
|
@ -3673,7 +3700,13 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
|
|||
pj_ki (pj, "index", c->index);
|
||||
if (c->super) {
|
||||
pj_ks (pj, "visibility", r_str_get (c->visibility_str));
|
||||
pj_ks (pj, "super", c->super);
|
||||
RListIter *iter;
|
||||
const char *sk;
|
||||
pj_ka (pj, "super");
|
||||
r_list_foreach (c->super, iter, sk) {
|
||||
pj_s (pj, sk);
|
||||
}
|
||||
pj_end (pj);
|
||||
}
|
||||
pj_ka (pj, "methods");
|
||||
r_list_foreach (c->methods, iter2, sym) {
|
||||
|
@ -3723,7 +3756,9 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
|
|||
r_cons_printf ("0x%08"PFMT64x" [0x%08"PFMT64x" - 0x%08"PFMT64x"] %6"PFMT64d" %s class %d %s",
|
||||
c->addr, at_min, at_max, (at_max - at_min), cl, c->index, c->name);
|
||||
if (c->super) {
|
||||
r_cons_printf (" :: %s\n", c->super);
|
||||
char *csv = r_str_list_join (c->super, ", ");
|
||||
r_cons_printf (" :: %s\n", csv);
|
||||
free (csv);
|
||||
} else {
|
||||
r_cons_newline ();
|
||||
}
|
||||
|
|
|
@ -1300,41 +1300,51 @@ static int cmd_info(void *data, const char *input) {
|
|||
} else if (input[1] == ',') { // "ic,"
|
||||
// ic,
|
||||
cmd_ic_comma (core, input);
|
||||
} else if (input[1] == 'g') {
|
||||
} else if (input[1] == 'g') { // "icg"
|
||||
RBinClass *cls;
|
||||
RListIter *iter;
|
||||
RListIter *iter, *iter2;
|
||||
RBinObject *obj = r_bin_cur_object (core->bin);
|
||||
if (!obj) {
|
||||
break;
|
||||
}
|
||||
bool fullGraph = true;
|
||||
const char *match = r_str_trim_head_ro (input + 2);
|
||||
if (*match) {
|
||||
if (R_STR_ISNOTEMPTY (match)) {
|
||||
r_list_foreach (obj->classes, iter, cls) {
|
||||
if (cls->super && strstr (cls->super, match)) {
|
||||
r_cons_printf ("agn %s\n", cls->super);
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
r_cons_printf ("age %s %s\n", cls->super, cls->name);
|
||||
} else if (strstr (cls->name, match)) {
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
char *sk;
|
||||
if (!match || !strstr (cls->name, match)) {
|
||||
continue;
|
||||
}
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
if (cls->super) {
|
||||
r_list_foreach (cls->super, iter2, sk) {
|
||||
if (match && strstr (sk, match)) {
|
||||
r_cons_printf ("agn %s\n", sk);
|
||||
r_cons_printf ("age %s %s\n", sk, cls->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (fullGraph) {
|
||||
r_list_foreach (obj->classes, iter, cls) {
|
||||
if (cls->super) {
|
||||
r_cons_printf ("agn %s\n", cls->super);
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
r_cons_printf ("age %s %s\n", cls->super, cls->name);
|
||||
} else {
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
const char *sk;
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
r_list_foreach (cls->super, iter2, sk) {
|
||||
r_cons_printf ("agn %s\n", sk);
|
||||
r_cons_printf ("age %s %s\n", sk, cls->name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
r_list_foreach (obj->classes, iter, cls) {
|
||||
if (cls->super && !strstr (cls->super, "NSObject")) {
|
||||
r_cons_printf ("agn %s\n", cls->super);
|
||||
char *sk;
|
||||
RListIter *iter;
|
||||
r_list_foreach (cls->super, iter, sk) {
|
||||
if (strstr (sk, "NSObject")) {
|
||||
continue;
|
||||
}
|
||||
r_cons_printf ("agn %s\n", sk);
|
||||
r_cons_printf ("agn %s\n", cls->name);
|
||||
r_cons_printf ("age %s %s\n", cls->super, cls->name);
|
||||
r_cons_printf ("age %s %s\n", sk, cls->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -509,7 +509,7 @@ typedef struct r_bin_section_t {
|
|||
typedef struct r_bin_class_t {
|
||||
char *name;
|
||||
// TODO: char *module;
|
||||
char *super;
|
||||
RList *super; // list of char*
|
||||
char *visibility_str; // XXX only used by java
|
||||
int index;
|
||||
ut64 addr;
|
||||
|
|
|
@ -701,25 +701,25 @@ R_API void r_bin_java_get_import_json_definitions(RBinJavaObj *bin, PJ *pj) {
|
|||
R_API void r_bin_java_get_class_info_json(RBinJavaObj *bin, PJ *pj) {
|
||||
r_return_if_fail (bin && pj);
|
||||
RList *classes = r_bin_java_get_classes (bin);
|
||||
RBinClass *class_ = r_list_get_n (classes, 0);
|
||||
RBinClass *klass = r_list_get_n (classes, 0);
|
||||
|
||||
// pj dict already opened
|
||||
|
||||
if (class_) {
|
||||
if (klass) {
|
||||
int dummy = 0;
|
||||
RListIter *iter;
|
||||
RBinClass *class_v = NULL;
|
||||
RBinClass *klassv = NULL;
|
||||
// add access flags like in methods
|
||||
bool is_public = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_PUBLIC) != 0);
|
||||
bool is_final = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_FINAL) != 0);
|
||||
bool is_super = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
|
||||
bool is_interface = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0);
|
||||
bool is_abstract = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ABSTRACT) != 0);
|
||||
bool is_synthetic = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SYNTHETIC) != 0);
|
||||
bool is_annotation = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ANNOTATION) != 0);
|
||||
bool is_enum = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ENUM) != 0);
|
||||
bool is_public = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_PUBLIC) != 0);
|
||||
bool is_final = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_FINAL) != 0);
|
||||
bool is_super = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
|
||||
bool is_interface = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0);
|
||||
bool is_abstract = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_ABSTRACT) != 0);
|
||||
bool is_synthetic = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_SYNTHETIC) != 0);
|
||||
bool is_annotation = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_ANNOTATION) != 0);
|
||||
bool is_enum = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_ENUM) != 0);
|
||||
|
||||
pj_ki (pj, "access_flags", class_->visibility);
|
||||
pj_ki (pj, "access_flags", klass->visibility);
|
||||
pj_ki (pj, "is_public", is_public);
|
||||
pj_ki (pj, "is_final", is_final);
|
||||
pj_ki (pj, "is_super", is_super);
|
||||
|
@ -728,20 +728,26 @@ R_API void r_bin_java_get_class_info_json(RBinJavaObj *bin, PJ *pj) {
|
|||
pj_ki (pj, "is_synthetic", is_synthetic);
|
||||
pj_ki (pj, "is_annotation", is_annotation);
|
||||
pj_ki (pj, "is_enum", is_enum);
|
||||
pj_ks (pj, "name", class_->name);
|
||||
|
||||
pj_ks (pj, "super", r_str_get (class_->super));
|
||||
pj_ks (pj, "name", klass->name);
|
||||
if (klass->super) {
|
||||
const char *sk;
|
||||
pj_ka (pj, "super");
|
||||
r_list_foreach (klass->super, iter, sk) {
|
||||
pj_ks (pj, "super", sk);
|
||||
}
|
||||
pj_end (pj);
|
||||
}
|
||||
|
||||
pj_ka (pj, "interfaces");
|
||||
|
||||
r_list_foreach (classes, iter, class_v) {
|
||||
r_list_foreach (classes, iter, klassv) {
|
||||
if (!dummy) {
|
||||
dummy++;
|
||||
continue;
|
||||
}
|
||||
// enumerate all interface classes and append them to the interfaces
|
||||
if ((class_v->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0) {
|
||||
pj_s (pj, class_v->name);
|
||||
if ((klassv->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0) {
|
||||
pj_s (pj, klassv->name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2859,7 +2865,13 @@ R_API RList *r_bin_java_get_classes(RBinJavaObj *bin) {
|
|||
k->methods = r_bin_java_enum_class_methods (bin, bin->cf2.this_class);
|
||||
k->fields = r_bin_java_enum_class_fields (bin, bin->cf2.this_class);
|
||||
k->name = r_bin_java_get_this_class_name (bin);
|
||||
k->super = r_bin_java_get_name_from_bin_cp_list (bin, bin->cf2.super_class);
|
||||
char *n = r_bin_java_get_name_from_bin_cp_list (bin, bin->cf2.super_class);
|
||||
if (R_STR_ISNOTEMPTY (n)) {
|
||||
k->super = r_list_newf (free);
|
||||
r_list_append (k->super, n);
|
||||
} else {
|
||||
free (n);
|
||||
}
|
||||
k->index = (idx++);
|
||||
k->lang = R_BIN_LANG_JAVA;
|
||||
r_list_append (classes, k);
|
||||
|
|
|
@ -2,7 +2,7 @@ NAME=java prototypes in json
|
|||
FILE=bins/java/jdwpexeccmd.class
|
||||
CMDS=java prototypes j
|
||||
EXPECT=<<EOF
|
||||
{"access_flags":33,"is_public":1,"is_final":0,"is_super":1,"is_interface":0,"is_abstract":0,"is_synthetic":0,"is_annotation":0,"is_enum":0,"name":"JDWPExecCmd","super":"java/lang/Object","interfaces":[],"methods":[{"access_flags":1,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":0,"is_protected":0,"is_super":0,"addr":825,"offset":803,"class_name":"java/lang/Object","signature":"()V","name":"<init>","fq_name":"java/lang/Object.<init>.()V","prototype":"public void <init> ()"},{"access_flags":9,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":1,"is_protected":0,"is_super":0,"addr":868,"offset":846,"class_name":"JDWPExecCmd","signature":"(Ljava/lang/String;)Ljava/lang/String;","name":"run","fq_name":"JDWPExecCmd.run.(Ljava/lang/String;)Ljava/lang/String;","prototype":"public static java.lang.String run (java.lang.String)"}],"fields":[],"imports":["java.lang.StringBuilder","java.io.BufferedReader","java.io.InputStreamReader","java.lang.Exception","JDWPExecCmd","java.lang.Object","java.lang.String","java.lang.Process","java.io.BufferedReader","java.lang.Exception","java.lang.Runtime","java.lang.Process","java.lang.String"]}
|
||||
{"access_flags":33,"is_public":1,"is_final":0,"is_super":1,"is_interface":0,"is_abstract":0,"is_synthetic":0,"is_annotation":0,"is_enum":0,"name":"JDWPExecCmd","super":["super":"java/lang/Object"],"interfaces":[],"methods":[{"access_flags":1,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":0,"is_protected":0,"is_super":0,"addr":825,"offset":803,"class_name":"java/lang/Object","signature":"()V","name":"<init>","fq_name":"java/lang/Object.<init>.()V","prototype":"public void <init> ()"},{"access_flags":9,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":1,"is_protected":0,"is_super":0,"addr":868,"offset":846,"class_name":"JDWPExecCmd","signature":"(Ljava/lang/String;)Ljava/lang/String;","name":"run","fq_name":"JDWPExecCmd.run.(Ljava/lang/String;)Ljava/lang/String;","prototype":"public static java.lang.String run (java.lang.String)"}],"fields":[],"imports":["java.lang.StringBuilder","java.io.BufferedReader","java.io.InputStreamReader","java.lang.Exception","JDWPExecCmd","java.lang.Object","java.lang.String","java.lang.Process","java.io.BufferedReader","java.lang.Exception","java.lang.Runtime","java.lang.Process","java.lang.String"]}
|
||||
EOF
|
||||
RUN
|
||||
|
||||
|
|
|
@ -4217,8 +4217,8 @@ icg Hello
|
|||
icg no_match
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
agn java/lang/Object
|
||||
agn Hello
|
||||
agn java/lang/Object
|
||||
age java/lang/Object Hello
|
||||
agn Hello
|
||||
EOF
|
||||
|
|
Loading…
Reference in New Issue