Initial support for C++ classes extracted from the demangler

This commit is contained in:
pancake 2016-11-22 14:20:52 +01:00
parent 414310836a
commit 7b94a79dcd
5 changed files with 77 additions and 29 deletions

View File

@ -2163,18 +2163,20 @@ R_API RBinObject *r_bin_get_object(RBin *bin) {
R_API RList * /*<RBinClass>*/ r_bin_get_classes(RBin *bin) {
RBinObject *o = r_bin_cur_object (bin);
if (o) return o->classes;
return NULL;
return o? o->classes: NULL;
}
R_API RBinClass *r_bin_class_new(RBinFile *binfile, const char *name, const char *super, int view) {
RBinObject *o = binfile? binfile->o: NULL;
RList *list = NULL;
RBinClass *c;
if (!o)
if (!o) {
return NULL;
}
list = o->classes;
if (!name) return NULL;
if (!name) {
return NULL;
}
c = r_bin_class_get (binfile, name);
if (c) {
if (super) {
@ -2184,15 +2186,18 @@ R_API RBinClass *r_bin_class_new(RBinFile *binfile, const char *name, const char
return c;
}
c = R_NEW0 (RBinClass);
if (!c) return NULL;
if (!c) {
return NULL;
}
c->name = strdup (name);
c->super = super? strdup (super): NULL;
c->index = r_list_length (list);
c->methods = r_list_new ();
c->fields = r_list_new ();
c->visibility = view;
if (!list)
if (!list) {
list = o->classes = r_list_new ();
}
r_list_append (list, c);
return c;
}
@ -2214,14 +2219,25 @@ R_API RBinClass *r_bin_class_get(RBinFile *binfile, const char *name) {
R_API int r_bin_class_add_method(RBinFile *binfile, const char *classname, const char *name, int nargs) {
RBinClass *c = r_bin_class_get (binfile, classname);
RBinSymbol *sym = R_NEW0 (RBinSymbol);
if (!sym) return false;
sym->name = strdup (name);
if (c) {
r_list_append (c->methods, sym);
return true;
if (!c) {
c = r_bin_class_new (binfile, classname, NULL, 0);
if (!c) {
eprintf ("Cannot allocate class %s\n", classname);
return false;
}
}
c = r_bin_class_new (binfile, classname, NULL, 0);
RBinSymbol *m;
RListIter *iter;
r_list_foreach (c->methods, iter, m) {
if (!strcmp (m->name, name)) {
return false;
}
}
RBinSymbol *sym = R_NEW0 (RBinSymbol);
if (!sym) {
return false;
}
sym->name = strdup (name);
r_list_append (c->methods, sym);
return true;
}

View File

@ -117,7 +117,7 @@ R_API char *r_bin_demangle_msvc(const char *str) {
return out;
}
R_API char *r_bin_demangle_cxx(const char *str) {
R_API char *r_bin_demangle_cxx(RBinFile *binfile, const char *str) {
char *out;
// DMGL_TYPES | DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE
// | DMGL_RET_POSTFIX | DMGL_TYPES;
@ -132,10 +132,10 @@ R_API char *r_bin_demangle_cxx(const char *str) {
"imp.",
NULL
};
if (str[0]==str[1] && *str=='_') {
if (str[0] == str[1] && *str == '_') {
str++;
} {
for (i=0; prefixes[i]; i++) {
for (i = 0; prefixes[i]; i++) {
int plen = strlen (prefixes[i]);
if (!strncmp (str, prefixes[i], plen)) {
str += plen;
@ -149,11 +149,18 @@ R_API char *r_bin_demangle_cxx(const char *str) {
/* TODO: implement a non-gpl alternative to c++v3 demangler */
out = NULL;
#endif
if (out) {
r_str_replace_char (out, ' ', 0);
}
{
/* extract class/method information */
char *nerd = (char*)r_str_last (out, "::");
if (nerd && *nerd) {
*nerd = 0;
r_bin_class_add_method (binfile, out, nerd + 2, 0);
*nerd = ':';
}
}
return out;
}
@ -165,23 +172,27 @@ R_API char *r_bin_demangle_objc(RBinFile *binfile, const char *sym) {
int i, nargs = 0;
const char *type = NULL;
if (!binfile || !sym)
if (!binfile || !sym) {
return NULL;
}
if (binfile && binfile->o && binfile->o->classes) {
binfile = NULL;
}
/* classes */
if (!strncmp (sym, "_OBJC_Class_", 12)) {
ret = r_str_newf ("class %s", sym + 12);
if (binfile) r_bin_class_new (binfile, sym + 12,
NULL, R_BIN_CLASS_PUBLIC);
if (binfile) {
r_bin_class_new (binfile, sym + 12,
NULL, R_BIN_CLASS_PUBLIC);
}
return ret;
}
if (!strncmp (sym, "_OBJC_CLASS_$_", 14)) {
ret = r_str_newf ("class %s", sym + 14);
if (binfile) r_bin_class_new (binfile, sym + 14,
NULL, R_BIN_CLASS_PUBLIC);
if (binfile) {
r_bin_class_new (binfile, sym + 14,
NULL, R_BIN_CLASS_PUBLIC);
}
return ret;
}
/* fields */
@ -268,7 +279,9 @@ R_API char *r_bin_demangle_objc(RBinFile *binfile, const char *sym) {
}
if (type && name && *name) {
ret = r_str_newf ("%s int %s::%s(%s)", type, clas, name, args);
if (binfile) r_bin_class_add_method (binfile, clas, name, nargs);
if (binfile) {
r_bin_class_add_method (binfile, clas, name, nargs);
}
}
}
}
@ -364,18 +377,19 @@ R_API char *r_bin_demangle(RBinFile *binfile, const char *def, const char *str)
}
}
// if str is sym. or imp. when str+=4 str points to the end so just return
if (!*str)
if (!*str) {
return NULL;
}
if (type == -1) {
type = r_bin_lang_type (binfile, def, str);
}
switch (type) {
case R_BIN_NM_JAVA: return r_bin_demangle_java (str);
/* rust uses the same mangling as c++ and appends a uniqueid */
case R_BIN_NM_RUST: return r_bin_demangle_cxx (str);
case R_BIN_NM_RUST: return r_bin_demangle_cxx (binfile, str);
case R_BIN_NM_OBJC: return r_bin_demangle_objc (NULL, str);
case R_BIN_NM_SWIFT: return r_bin_demangle_swift (str, bin->demanglercmd);
case R_BIN_NM_CXX: return r_bin_demangle_cxx (str);
case R_BIN_NM_CXX: return r_bin_demangle_cxx (binfile, str);
case R_BIN_NM_DLANG: return r_bin_demangle_plugin (bin, "dlang", str);
}
return NULL;

View File

@ -508,7 +508,7 @@ R_API const char *r_bin_entry_type_string(int etype);
R_API char* r_bin_demangle(RBinFile *binfile, const char *lang, const char *str);
R_API int r_bin_demangle_type (const char *str);
R_API char *r_bin_demangle_java(const char *str);
R_API char *r_bin_demangle_cxx(const char *str);
R_API char *r_bin_demangle_cxx(RBinFile *binfile, const char *str);
R_API char *r_bin_demangle_msvc(const char *str);
R_API char *r_bin_demangle_swift(const char *s, bool syscmd);
R_API char *r_bin_demangle_objc(RBinFile *binfile, const char *sym);

View File

@ -132,5 +132,6 @@ R_API char *r_str_between(const char *str, const char *prefix, const char *suffi
R_API bool r_str_startswith(const char *str, const char *needle);
R_API bool r_str_endswith(const char *str, const char *needle);
R_API bool r_str_isnumber (const char *str);
R_API const char *r_str_last (const char *in, const char *ch);
#endif // R_STR_H

View File

@ -2513,3 +2513,20 @@ R_API bool r_str_isnumber (const char *str) {
}
return isnum;
}
/* TODO: optimize to start searching by the end of the string */
R_API const char *r_str_last(const char *str, const char *ch) {
char *ptr, *end = NULL;
if (!str || !ch) {
return NULL;
}
do {
ptr = strstr (str, ch);
if (!ptr) {
break;
}
end = ptr;
str = ptr + 1;
} while (true);
return end;
}