2012-11-07 03:25:42 +00:00
|
|
|
/* radare - LGPL - Copyright 2011-2012 - pancake */
|
2011-02-23 19:53:56 +00:00
|
|
|
|
|
|
|
#include <r_bin.h>
|
2011-02-28 08:45:29 +00:00
|
|
|
#include <cxx/demangle.h>
|
2011-02-23 19:53:56 +00:00
|
|
|
|
2011-02-27 19:30:41 +00:00
|
|
|
// http://code.google.com/p/smali/wiki/TypesMethodsAndFields
|
2011-02-23 19:53:56 +00:00
|
|
|
R_API char *r_bin_demangle_java(const char *str) {
|
2011-02-27 19:30:41 +00:00
|
|
|
RBuffer *buf;
|
|
|
|
const char *w = NULL;
|
|
|
|
int n = 0;
|
2012-11-07 03:25:42 +00:00
|
|
|
char *ret;
|
2011-02-27 19:30:41 +00:00
|
|
|
const char *ptr;
|
|
|
|
int is_array = 0;
|
|
|
|
int is_ret = 0;
|
|
|
|
int wlen = 0;
|
|
|
|
|
|
|
|
ptr = strchr (str, '(');
|
|
|
|
if (!ptr)
|
|
|
|
return NULL;
|
|
|
|
buf = r_buf_new ();
|
2011-09-19 00:39:33 +00:00
|
|
|
if (!buf) return NULL;
|
2011-02-27 19:30:41 +00:00
|
|
|
r_buf_append_bytes (buf, (const ut8*)str, (int)(size_t)(ptr-str));
|
|
|
|
r_buf_append_bytes (buf, (const ut8*)" (", 2);
|
|
|
|
while (*str) {
|
|
|
|
switch (*str) {
|
|
|
|
case ')':
|
|
|
|
is_ret = 1;
|
|
|
|
break;
|
|
|
|
case '[':
|
|
|
|
is_array = 1;
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
str++;
|
|
|
|
ptr = strchr (str, ';');
|
|
|
|
if (ptr) {
|
|
|
|
w = str;
|
|
|
|
wlen = (int)(size_t)(ptr-str);
|
|
|
|
}
|
|
|
|
str = ptr;
|
|
|
|
break;
|
|
|
|
case 'I': w = "int"; wlen = 3; break;
|
|
|
|
case 'C': w = "char"; wlen = 4; break;
|
|
|
|
case 'B': w = "byte"; wlen = 4; break;
|
|
|
|
case 'V': w = "void"; wlen = 4; break;
|
|
|
|
case 'J': w = "long"; wlen = 4; break;
|
|
|
|
case 'F': w = "float"; wlen = 5; break;
|
|
|
|
case 'S': w = "short"; wlen = 5; break;
|
|
|
|
case 'D': w = "double"; wlen = 6; break;
|
|
|
|
case 'Z': w = "boolean"; wlen = 7; break;
|
|
|
|
}
|
|
|
|
if (w) {
|
|
|
|
if (is_ret) {
|
|
|
|
r_buf_prepend_bytes (buf, (const ut8*)" ", 1);
|
|
|
|
r_buf_prepend_bytes (buf, (const ut8*)w, wlen);
|
|
|
|
r_buf_append_bytes (buf, (const ut8*)")", 1);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
if (n++>0)
|
|
|
|
r_buf_append_bytes (buf, (const ut8*)", ", 2);
|
|
|
|
r_buf_append_bytes (buf, (const ut8*)w, wlen);
|
|
|
|
}
|
|
|
|
if (is_array) {
|
|
|
|
r_buf_append_bytes (buf, (const ut8*)"[]", 2);
|
|
|
|
is_array = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
w = NULL;
|
|
|
|
str++;
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
ret = r_buf_to_string (buf);
|
|
|
|
r_buf_free (buf);
|
|
|
|
return ret;
|
2011-02-23 19:53:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API char *r_bin_demangle_cxx(const char *str) {
|
2011-02-28 08:45:29 +00:00
|
|
|
char *out;
|
|
|
|
int flags = DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE; // | DMGL_RET_POSTFIX | DMGL_TYPES;
|
|
|
|
out = cplus_demangle_v3 (str, flags);
|
|
|
|
return out;
|
2011-02-23 19:53:56 +00:00
|
|
|
}
|
2011-02-25 03:19:30 +00:00
|
|
|
|
2012-11-07 09:41:12 +00:00
|
|
|
R_API char *r_bin_demangle_objc(RBin *bin, const char *sym) {
|
2012-11-07 03:25:42 +00:00
|
|
|
char *ret = NULL;
|
|
|
|
char *clas = NULL;
|
|
|
|
char *name = NULL;
|
|
|
|
char *args = NULL;
|
|
|
|
int i, nargs = 0;
|
|
|
|
const char *type = NULL;
|
|
|
|
/* classes */
|
|
|
|
if (!strncmp (sym, "_OBJC_Class_", 12)) {
|
|
|
|
ret = malloc (10+strlen (sym));
|
|
|
|
sprintf (ret, "class %s", sym+12);
|
2012-11-07 09:41:12 +00:00
|
|
|
if (bin) r_bin_class_new (bin, sym+12, NULL, R_BIN_CLASS_PUBLIC);
|
2012-11-07 03:25:42 +00:00
|
|
|
return ret;
|
|
|
|
} else
|
|
|
|
if (!strncmp (sym, "_OBJC_CLASS_$_", 14)) {
|
|
|
|
ret = malloc (10+strlen (sym));
|
|
|
|
sprintf (ret, "class %s", sym+14);
|
2012-11-07 09:41:12 +00:00
|
|
|
if (bin) r_bin_class_new (bin, sym+14, NULL, R_BIN_CLASS_PUBLIC);
|
2012-11-07 03:25:42 +00:00
|
|
|
return ret;
|
|
|
|
} else
|
|
|
|
/* fields */
|
|
|
|
if (!strncmp (sym, "_OBJC_IVAR_$_", 13)) {
|
|
|
|
char *p;
|
|
|
|
clas = strdup (sym+13);
|
|
|
|
p = strchr (clas, '.');
|
|
|
|
type = "field";
|
|
|
|
if (p) {
|
|
|
|
*p = 0;
|
|
|
|
name = p+1;
|
|
|
|
} else name = NULL;
|
2012-11-07 09:41:12 +00:00
|
|
|
if (bin) r_bin_class_add_field (bin, clas, name);
|
2012-11-07 03:25:42 +00:00
|
|
|
} else
|
|
|
|
/* methods */
|
|
|
|
if (sym[1] == '[') { // apple style
|
|
|
|
if (sym[0] == '+') type = "static";
|
|
|
|
else if (sym[0] == '-') type = "public";
|
|
|
|
if (type) {
|
|
|
|
clas = strdup (sym+2);
|
|
|
|
name = strchr (clas, ' ');
|
|
|
|
if (name) *name++ = 0;
|
|
|
|
for (i=0;name[i];i++) {
|
|
|
|
if (name[i]==']') {
|
|
|
|
name[i] = 0;
|
|
|
|
} else
|
|
|
|
if (name[i]==':') {
|
|
|
|
nargs++;
|
|
|
|
name[i] = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
if (sym[0]=='_' && sym[2]=='_') { // gnu style
|
|
|
|
clas = strdup (sym+3);
|
|
|
|
args = strstr (clas, "__");
|
|
|
|
if (!args) {
|
|
|
|
free (clas);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*args = 0;
|
|
|
|
name = strdup (args+2);
|
|
|
|
args = NULL;
|
|
|
|
for (i=0; name[i]; i++) {
|
|
|
|
if (name[i]=='_') {
|
|
|
|
name[i] = 0;
|
|
|
|
nargs++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (sym[1] == 'i') { // instance method
|
|
|
|
type = "public";
|
|
|
|
} else if (sym[1] == 'c') { // static method
|
|
|
|
type = "static";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (type) {
|
|
|
|
if (!strcmp (type, "field")) {
|
|
|
|
ret = malloc (strlen (type)+strlen (name)+32);
|
|
|
|
sprintf (ret, "field int %s::%s", clas, name);
|
|
|
|
} else {
|
|
|
|
if (nargs) {
|
|
|
|
const char *arg = "int";
|
|
|
|
args = malloc (((strlen (arg)+4) * nargs)+1);
|
|
|
|
args[0] = 0;
|
|
|
|
for(i=0;i<nargs; i++) {
|
|
|
|
strcat (args, arg);
|
|
|
|
if (i+1<nargs)
|
|
|
|
strcat (args, ", ");
|
|
|
|
}
|
|
|
|
} else args = strdup ("");
|
|
|
|
ret = malloc (strlen (type)+strlen (name)+
|
|
|
|
strlen(clas)+strlen(args)+15);
|
|
|
|
sprintf (ret, "%s int %s::%s(%s)", type, clas, name, args);
|
2012-11-07 09:41:12 +00:00
|
|
|
if (bin) {
|
|
|
|
r_bin_class_add_method (bin, clas, name, nargs);
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free (clas);
|
|
|
|
free (args);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-02-27 19:30:41 +00:00
|
|
|
R_API int r_bin_demangle_type (const char *str) {
|
|
|
|
// XXX: add
|
2011-02-28 09:22:40 +00:00
|
|
|
return R_BIN_NM_CXX;
|
2011-02-27 19:30:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
R_API char *r_bin_demangle (RBin *bin, const char *str) {
|
|
|
|
int type;
|
2012-08-04 21:48:06 +00:00
|
|
|
if (bin && bin->cur.curplugin && bin->cur.curplugin->demangle_type)
|
|
|
|
type = bin->cur.curplugin->demangle_type (str);
|
2011-02-27 19:30:41 +00:00
|
|
|
else type = r_bin_demangle_type (str);
|
2011-02-25 03:19:30 +00:00
|
|
|
switch (type) {
|
|
|
|
case R_BIN_NM_JAVA: return r_bin_demangle_java (str);
|
|
|
|
case R_BIN_NM_CXX: return r_bin_demangle_cxx (str);
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
2011-02-27 19:30:41 +00:00
|
|
|
|
|
|
|
#ifdef TEST
|
|
|
|
main() {
|
|
|
|
char *out, str[128];
|
2011-09-18 18:41:36 +00:00
|
|
|
strncpy (str, "_Z1hic", sizeof (str)-1);
|
|
|
|
strncpy (str, "main(Ljava/lang/String;I)V", sizeof (str)-1);
|
|
|
|
strncpy (str, "main([Ljava/lang/String;)V", sizeof (str)-1);
|
2011-10-05 00:38:37 +00:00
|
|
|
strncpy (str, "foo([III)Ljava/lang/Integer;", sizeof (str)-1);
|
2011-02-27 19:30:41 +00:00
|
|
|
//out = cplus_demangle_v3 (str, flags);
|
|
|
|
out = r_bin_demangle_java (str); //, flags);
|
|
|
|
printf ("INPUT (%s)\n", str);
|
|
|
|
printf ("OUTPUT (%s)\n", out);
|
|
|
|
}
|
|
|
|
#endif
|