2016-03-31 11:21:51 +00:00
|
|
|
/* radare - LGPL - Copyright 2011-2016 - 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
|
|
|
|
Add Microsoft C++ demangler
- Contains 20 commits:
- init work of demangler
- add some comments
- add parsing of name, class_name, namespace of objects(class and global)
- refactor
- add parsing of some type codes
- add skeleton of state machine for type code parsing
- add parsing of standard type for type codes state machine
- add parsing of type codes: _{J,K,T,Z,W}
- add parsing of types __m** and union
- add parsing of type codes: _m***, struct *
- add parsing of W type codes: enums...
- refactor getting of namespaces and name variables
- add class type code parsing
- add parsing of long double and bool
- add parsing of X * const volatile
- add parsing of * and & ( Q, R, S, A )
- add parsing of array
- integrate some initial part of microsofr demangler to rabin2
- fix some small bugs
- add parsing of variable storage class and do some small fix
2015-01-17 20:15:20 +00:00
|
|
|
//TODO: mangler_branch: remove?
|
|
|
|
#include "mangling/demangler.h"
|
|
|
|
|
2015-02-11 01:05:22 +00:00
|
|
|
R_API void r_bin_demangle_list(RBin *bin) {
|
2015-02-19 21:56:49 +00:00
|
|
|
const char *langs[] = { "cxx", "java", "objc", "swift", "dlang", "msvc", NULL };
|
2015-02-11 01:05:22 +00:00
|
|
|
RBinPlugin *plugin;
|
|
|
|
RListIter *it;
|
|
|
|
int i;
|
|
|
|
if (!bin) return;
|
|
|
|
for (i=0; langs[i]; i++) {
|
|
|
|
eprintf ("%s\n", langs[i]);
|
|
|
|
}
|
|
|
|
r_list_foreach (bin->plugins, it, plugin) {
|
|
|
|
if (plugin->demangle) {
|
|
|
|
eprintf ("%s\n", plugin->name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API char *r_bin_demangle_plugin(RBin *bin, const char *name, const char *str) {
|
|
|
|
RBinPlugin *plugin;
|
|
|
|
RListIter *it;
|
|
|
|
if (!bin || !name || !str) return NULL;
|
|
|
|
r_list_foreach (bin->plugins, it, plugin) {
|
|
|
|
if (plugin->demangle) {
|
|
|
|
return plugin->demangle (str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
const char *w = NULL;
|
|
|
|
int is_array = 0;
|
2013-02-15 12:24:09 +00:00
|
|
|
const char *ptr;
|
2011-02-27 19:30:41 +00:00
|
|
|
int is_ret = 0;
|
|
|
|
int wlen = 0;
|
2013-02-15 12:24:09 +00:00
|
|
|
RBuffer *buf;
|
|
|
|
int n = 0;
|
|
|
|
char *ret;
|
2011-02-27 19:30:41 +00:00
|
|
|
|
|
|
|
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;
|
2013-05-14 01:13:49 +00:00
|
|
|
if (!str) break;
|
2011-02-27 19:30:41 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2015-10-19 11:21:12 +00:00
|
|
|
R_API char *r_bin_demangle_msvc(const char *str) {
|
2015-02-21 21:28:49 +00:00
|
|
|
char *out = NULL;
|
2015-02-19 17:39:55 +00:00
|
|
|
SDemangler *mangler = 0;
|
|
|
|
|
2015-10-19 11:21:12 +00:00
|
|
|
create_demangler (&mangler);
|
2016-05-19 15:20:35 +00:00
|
|
|
if (!mangler) return NULL;
|
2015-10-19 11:21:12 +00:00
|
|
|
if (init_demangler (mangler, (char *)str) == eDemanglerErrOK) {
|
2016-04-22 23:53:43 +00:00
|
|
|
mangler->demangle (mangler, &out/*demangled_name*/);
|
2015-02-19 17:39:55 +00:00
|
|
|
}
|
2015-10-19 11:21:12 +00:00
|
|
|
free_demangler (mangler);
|
2015-02-19 17:39:55 +00:00
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
2016-11-22 13:58:42 +00:00
|
|
|
R_API char *r_bin_demangle_cxx(RBinFile *binfile, const char *str, ut64 vaddr) {
|
2011-02-28 08:45:29 +00:00
|
|
|
char *out;
|
2014-09-24 09:41:16 +00:00
|
|
|
// DMGL_TYPES | DMGL_PARAMS | DMGL_ANSI | DMGL_VERBOSE
|
|
|
|
// | DMGL_RET_POSTFIX | DMGL_TYPES;
|
2015-02-07 00:41:54 +00:00
|
|
|
int i;
|
|
|
|
#if WITH_GPL
|
2017-05-25 13:40:50 +00:00
|
|
|
int flags = DMGL_NO_OPTS | DMGL_PARAMS;
|
2015-02-07 00:41:54 +00:00
|
|
|
#endif
|
2014-09-24 09:41:16 +00:00
|
|
|
const char *prefixes[] = {
|
|
|
|
"__symbol_stub1_",
|
|
|
|
"reloc.",
|
|
|
|
"sym.imp.",
|
|
|
|
"imp.",
|
|
|
|
NULL
|
|
|
|
};
|
2016-11-22 13:20:52 +00:00
|
|
|
if (str[0] == str[1] && *str == '_') {
|
2014-09-24 09:41:16 +00:00
|
|
|
str++;
|
2014-09-24 10:09:36 +00:00
|
|
|
} {
|
2016-11-22 13:20:52 +00:00
|
|
|
for (i = 0; prefixes[i]; i++) {
|
2014-09-24 09:41:16 +00:00
|
|
|
int plen = strlen (prefixes[i]);
|
|
|
|
if (!strncmp (str, prefixes[i], plen)) {
|
|
|
|
str += plen;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-02-07 00:41:54 +00:00
|
|
|
#if WITH_GPL
|
2011-02-28 08:45:29 +00:00
|
|
|
out = cplus_demangle_v3 (str, flags);
|
2015-02-07 00:41:54 +00:00
|
|
|
#else
|
|
|
|
/* TODO: implement a non-gpl alternative to c++v3 demangler */
|
|
|
|
out = NULL;
|
|
|
|
#endif
|
2015-02-06 22:59:19 +00:00
|
|
|
if (out) {
|
2014-09-19 13:29:11 +00:00
|
|
|
r_str_replace_char (out, ' ', 0);
|
Add Microsoft C++ demangler
- Contains 20 commits:
- init work of demangler
- add some comments
- add parsing of name, class_name, namespace of objects(class and global)
- refactor
- add parsing of some type codes
- add skeleton of state machine for type code parsing
- add parsing of standard type for type codes state machine
- add parsing of type codes: _{J,K,T,Z,W}
- add parsing of types __m** and union
- add parsing of type codes: _m***, struct *
- add parsing of W type codes: enums...
- refactor getting of namespaces and name variables
- add class type code parsing
- add parsing of long double and bool
- add parsing of X * const volatile
- add parsing of * and & ( Q, R, S, A )
- add parsing of array
- integrate some initial part of microsofr demangler to rabin2
- fix some small bugs
- add parsing of variable storage class and do some small fix
2015-01-17 20:15:20 +00:00
|
|
|
}
|
2016-11-22 13:20:52 +00:00
|
|
|
{
|
|
|
|
/* extract class/method information */
|
|
|
|
char *nerd = (char*)r_str_last (out, "::");
|
|
|
|
if (nerd && *nerd) {
|
|
|
|
*nerd = 0;
|
2016-11-22 13:58:42 +00:00
|
|
|
RBinSymbol *sym = r_bin_class_add_method (binfile, out, nerd + 2, 0);
|
|
|
|
if (sym) {
|
|
|
|
sym->vaddr = vaddr;
|
|
|
|
}
|
2016-11-22 13:20:52 +00:00
|
|
|
*nerd = ':';
|
|
|
|
}
|
|
|
|
}
|
2011-02-28 08:45:29 +00:00
|
|
|
return out;
|
2011-02-23 19:53:56 +00:00
|
|
|
}
|
2011-02-25 03:19:30 +00:00
|
|
|
|
2014-04-27 07:06:50 +00:00
|
|
|
R_API char *r_bin_demangle_objc(RBinFile *binfile, 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;
|
2015-07-17 11:42:18 +00:00
|
|
|
|
2016-11-22 13:20:52 +00:00
|
|
|
if (!binfile || !sym) {
|
2015-11-09 02:41:07 +00:00
|
|
|
return NULL;
|
2016-11-22 13:20:52 +00:00
|
|
|
}
|
2015-08-07 12:05:42 +00:00
|
|
|
if (binfile && binfile->o && binfile->o->classes) {
|
|
|
|
binfile = NULL;
|
2015-07-17 11:42:18 +00:00
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
/* classes */
|
|
|
|
if (!strncmp (sym, "_OBJC_Class_", 12)) {
|
2015-10-27 17:06:17 +00:00
|
|
|
ret = r_str_newf ("class %s", sym + 12);
|
2016-11-22 13:20:52 +00:00
|
|
|
if (binfile) {
|
|
|
|
r_bin_class_new (binfile, sym + 12,
|
|
|
|
NULL, R_BIN_CLASS_PUBLIC);
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
return ret;
|
2015-10-27 17:06:17 +00:00
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
if (!strncmp (sym, "_OBJC_CLASS_$_", 14)) {
|
2015-10-27 17:06:17 +00:00
|
|
|
ret = r_str_newf ("class %s", sym + 14);
|
2016-11-22 13:20:52 +00:00
|
|
|
if (binfile) {
|
|
|
|
r_bin_class_new (binfile, sym + 14,
|
|
|
|
NULL, R_BIN_CLASS_PUBLIC);
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
return ret;
|
2015-10-27 17:06:17 +00:00
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
/* fields */
|
|
|
|
if (!strncmp (sym, "_OBJC_IVAR_$_", 13)) {
|
|
|
|
char *p;
|
2015-10-27 17:06:17 +00:00
|
|
|
clas = strdup (sym + 13);
|
2012-11-07 03:25:42 +00:00
|
|
|
p = strchr (clas, '.');
|
|
|
|
type = "field";
|
|
|
|
if (p) {
|
|
|
|
*p = 0;
|
2016-11-09 01:28:14 +00:00
|
|
|
name = strdup (p + 1);
|
2015-10-27 17:06:17 +00:00
|
|
|
} else {
|
|
|
|
name = NULL;
|
|
|
|
}
|
2014-04-27 07:06:50 +00:00
|
|
|
if (binfile) r_bin_class_add_field (binfile, clas, name);
|
2015-10-27 17:06:17 +00:00
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
/* methods */
|
2015-11-09 02:41:07 +00:00
|
|
|
if (sym && sym[0] && sym[1] == '[') { // apple style
|
2012-11-07 03:25:42 +00:00
|
|
|
if (sym[0] == '+') type = "static";
|
|
|
|
else if (sym[0] == '-') type = "public";
|
|
|
|
if (type) {
|
2015-10-27 17:06:17 +00:00
|
|
|
clas = strdup (sym + 2);
|
2012-11-07 03:25:42 +00:00
|
|
|
name = strchr (clas, ' ');
|
2014-11-05 00:51:50 +00:00
|
|
|
if (name) {
|
|
|
|
*name++ = 0;
|
|
|
|
name = strdup (name);
|
2015-06-20 11:38:11 +00:00
|
|
|
if (!name){
|
|
|
|
free (clas);
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-10-27 17:06:17 +00:00
|
|
|
for (i = 0; name[i]; i++) {
|
2014-11-05 00:51:50 +00:00
|
|
|
if (name[i]==']') {
|
|
|
|
name[i] = 0;
|
2015-10-27 17:06:17 +00:00
|
|
|
}
|
2014-11-05 00:51:50 +00:00
|
|
|
if (name[i]==':') {
|
|
|
|
nargs++;
|
|
|
|
name[i] = 0;
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-10-27 17:06:17 +00:00
|
|
|
}
|
2015-11-22 20:56:23 +00:00
|
|
|
if (sym[0] == '_' && sym[1] && sym[2] == '_') { // gnu style
|
2015-11-01 04:47:16 +00:00
|
|
|
free (clas);
|
2015-10-27 17:06:17 +00:00
|
|
|
clas = strdup (sym + 3);
|
2012-11-07 03:25:42 +00:00
|
|
|
args = strstr (clas, "__");
|
|
|
|
if (!args) {
|
|
|
|
free (clas);
|
2017-07-10 09:20:03 +00:00
|
|
|
if (name != clas) {
|
|
|
|
free (name);
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*args = 0;
|
2017-07-10 09:20:03 +00:00
|
|
|
free (name);
|
2015-10-27 17:06:17 +00:00
|
|
|
name = strdup (args + 2);
|
2017-07-10 09:20:03 +00:00
|
|
|
if (!name) {
|
2015-06-20 11:38:11 +00:00
|
|
|
free (clas);
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
args = NULL;
|
2015-10-27 17:06:17 +00:00
|
|
|
for (i = 0; name[i]; i++) {
|
|
|
|
if (name[i] == '_') {
|
2012-11-07 03:25:42 +00:00
|
|
|
name[i] = 0;
|
|
|
|
nargs++;
|
|
|
|
}
|
|
|
|
}
|
2017-07-10 09:20:03 +00:00
|
|
|
if (sym[1] == 'i') {
|
|
|
|
type = "public";
|
|
|
|
} else if (sym[1] == 'c') {
|
|
|
|
type = "static";
|
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
}
|
|
|
|
if (type) {
|
|
|
|
if (!strcmp (type, "field")) {
|
2015-10-27 17:06:17 +00:00
|
|
|
ret = r_str_newf ("field int %s::%s", clas, name);
|
2012-11-07 03:25:42 +00:00
|
|
|
} else {
|
|
|
|
if (nargs) {
|
|
|
|
const char *arg = "int";
|
2015-10-27 17:06:17 +00:00
|
|
|
args = malloc (((strlen (arg) + 4) * nargs) + 1);
|
2012-11-07 03:25:42 +00:00
|
|
|
args[0] = 0;
|
2015-10-27 17:06:17 +00:00
|
|
|
for(i = 0;i < nargs; i++) {
|
2012-11-07 03:25:42 +00:00
|
|
|
strcat (args, arg);
|
2015-10-27 17:06:17 +00:00
|
|
|
if (i + 1 < nargs)
|
2012-11-07 03:25:42 +00:00
|
|
|
strcat (args, ", ");
|
|
|
|
}
|
2015-10-27 17:06:17 +00:00
|
|
|
} else {
|
|
|
|
args = strdup ("");
|
|
|
|
}
|
|
|
|
if (type && name && *name) {
|
|
|
|
ret = r_str_newf ("%s int %s::%s(%s)", type, clas, name, args);
|
2016-11-22 13:20:52 +00:00
|
|
|
if (binfile) {
|
|
|
|
r_bin_class_add_method (binfile, clas, name, nargs);
|
2016-11-22 13:58:42 +00:00
|
|
|
|
2016-11-22 13:20:52 +00:00
|
|
|
}
|
2014-11-05 00:51:50 +00:00
|
|
|
}
|
2012-11-07 03:25:42 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
free (clas);
|
|
|
|
free (args);
|
2014-01-16 23:13:01 +00:00
|
|
|
free (name);
|
2012-11-07 03:25:42 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2017-01-04 23:52:13 +00:00
|
|
|
static bool replace_seq (const char **in, char **out, const char *seq, char value) {
|
|
|
|
size_t len = strlen (seq);
|
|
|
|
|
|
|
|
if (strncmp (*in, seq, len)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
**out = value;
|
|
|
|
|
|
|
|
*in += len;
|
|
|
|
*out += 1;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-01-08 11:27:06 +00:00
|
|
|
#define RS(from, to) (replace_seq ((const char **)&in, &out, (const char *)from, to))
|
2017-01-04 23:52:13 +00:00
|
|
|
|
2017-01-08 11:27:06 +00:00
|
|
|
R_API char *r_bin_demangle_rust(RBinFile *binfile, const char *sym, ut64 vaddr) {
|
2017-01-04 23:52:13 +00:00
|
|
|
int len;
|
|
|
|
char *str, *out, *in;
|
|
|
|
|
|
|
|
str = r_bin_demangle_cxx (binfile, sym, vaddr);
|
|
|
|
|
|
|
|
if (!str) {
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
out = in = str;
|
|
|
|
len = strlen (str);
|
|
|
|
|
|
|
|
if (*in == '_') {
|
2017-01-05 10:55:36 +00:00
|
|
|
in++;
|
2017-01-04 23:52:13 +00:00
|
|
|
len--;
|
|
|
|
}
|
|
|
|
|
2017-03-09 22:14:56 +00:00
|
|
|
while ((len = strlen (in)) > 0) {
|
2017-01-04 23:52:13 +00:00
|
|
|
if (!(*in == '$' && (RS("$SP$", '@')
|
|
|
|
|| RS("$BP$", '*')
|
|
|
|
|| RS("$RF$", '&')
|
|
|
|
|| RS("$LT$", '<')
|
|
|
|
|| RS("$GT$", '>')
|
|
|
|
|| RS("$LP$", '(')
|
|
|
|
|| RS("$RP$", ')')
|
|
|
|
|| RS("$C$", ',')
|
|
|
|
// maybe a good idea to replace all utf-sequences by regexp \$u[0-9a-f]{2}\$ or so
|
|
|
|
|| RS("$u20$", ' ')
|
|
|
|
|| RS("$u22$", '\"')
|
|
|
|
|| RS("$u27$", '\'')
|
|
|
|
|| RS("$u2b$", '+')
|
|
|
|
|| RS("$u3b$", ';')
|
|
|
|
|| RS("$u5b$", '[')
|
|
|
|
|| RS("$u5d$", ']')
|
|
|
|
|| RS("$u7e$", '~')))) {
|
|
|
|
if (*in == '.') {
|
|
|
|
if (len > 0 && in[1] == '.') {
|
|
|
|
in += 2;
|
|
|
|
*out++ = ':';
|
|
|
|
*out++ = ':';
|
|
|
|
len--;
|
|
|
|
} else {
|
|
|
|
in += 1;
|
|
|
|
*out = '-';
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
*out++ = *in++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*out = '\0';
|
|
|
|
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2011-02-27 19:30:41 +00:00
|
|
|
R_API int r_bin_demangle_type (const char *str) {
|
2017-01-04 23:52:13 +00:00
|
|
|
if (!str || !*str) {
|
2015-01-02 18:27:31 +00:00
|
|
|
return R_BIN_NM_NONE;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "swift")) {
|
2015-01-02 03:32:53 +00:00
|
|
|
return R_BIN_NM_SWIFT;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "java")){
|
2015-01-10 00:00:01 +00:00
|
|
|
return R_BIN_NM_JAVA;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "objc")){
|
2015-01-02 03:32:53 +00:00
|
|
|
return R_BIN_NM_OBJC;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "cxx")){
|
2015-01-02 03:32:53 +00:00
|
|
|
return R_BIN_NM_CXX;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "dlang")){
|
2015-02-11 01:05:22 +00:00
|
|
|
return R_BIN_NM_DLANG;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "msvc")){
|
2015-02-19 17:39:55 +00:00
|
|
|
return R_BIN_NM_MSVC;
|
2017-01-04 23:52:13 +00:00
|
|
|
} if (!strcmp (str, "rust")){
|
|
|
|
return R_BIN_NM_RUST;
|
|
|
|
}
|
2015-01-02 03:32:53 +00:00
|
|
|
return R_BIN_NM_NONE;
|
2011-02-27 19:30:41 +00:00
|
|
|
}
|
|
|
|
|
2015-12-01 11:39:12 +00:00
|
|
|
R_API bool r_bin_lang_rust(RBinFile *binfile) {
|
2015-07-12 13:55:55 +00:00
|
|
|
RBinObject *o = binfile ? binfile->o : NULL;
|
|
|
|
RBinInfo *info = o ? o->info : NULL;
|
|
|
|
RBinSymbol *sym;
|
|
|
|
RListIter *iter;
|
2015-09-14 00:08:31 +00:00
|
|
|
int haslang = false;
|
2015-06-29 09:22:05 +00:00
|
|
|
|
2015-09-14 00:08:31 +00:00
|
|
|
if (info) {
|
|
|
|
r_list_foreach (o->symbols, iter, sym) {
|
2017-01-04 23:52:13 +00:00
|
|
|
if (sym->name && strstr (sym->name, "_$LT$")) {
|
2015-09-14 00:08:31 +00:00
|
|
|
haslang = true;
|
|
|
|
info->lang = "rust";
|
|
|
|
break;
|
|
|
|
}
|
2015-07-12 13:55:55 +00:00
|
|
|
}
|
|
|
|
}
|
2015-06-29 09:22:05 +00:00
|
|
|
// NOTE: if the rust binary is stripped we can check
|
|
|
|
// if the strings contain 'rust', but this can be too
|
|
|
|
// time consuming and spawn some false positives and,
|
|
|
|
// as long as lang detection is only useful for demangling
|
|
|
|
// there's no utility on catching this case.
|
2015-07-12 13:55:55 +00:00
|
|
|
return haslang;
|
2015-06-29 09:22:05 +00:00
|
|
|
}
|
|
|
|
|
2015-10-19 11:21:12 +00:00
|
|
|
R_API int r_bin_lang_type(RBinFile *binfile, const char *def, const char *sym) {
|
2015-06-28 11:09:21 +00:00
|
|
|
int type = 0;
|
2015-01-10 00:00:01 +00:00
|
|
|
RBinPlugin *plugin;
|
2015-10-19 11:21:12 +00:00
|
|
|
if (sym && sym[0] == sym[1] && sym[0] == '_') {
|
|
|
|
type = R_BIN_NM_CXX;
|
|
|
|
}
|
2015-01-10 00:00:01 +00:00
|
|
|
if (def && *def) {
|
|
|
|
type = r_bin_demangle_type (def);
|
|
|
|
if (type != R_BIN_NM_NONE)
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
plugin = r_bin_file_cur_plugin (binfile);
|
2015-10-19 11:21:12 +00:00
|
|
|
if (plugin && plugin->demangle_type) {
|
2015-01-10 00:00:01 +00:00
|
|
|
type = plugin->demangle_type (def);
|
2015-10-19 11:21:12 +00:00
|
|
|
} else {
|
2015-06-22 09:36:28 +00:00
|
|
|
if (binfile->o && binfile->o->info) {
|
|
|
|
type = r_bin_demangle_type (binfile->o->info->lang);
|
|
|
|
}
|
|
|
|
}
|
2015-10-19 11:21:12 +00:00
|
|
|
if (type == R_BIN_NM_NONE) {
|
2015-01-10 00:00:01 +00:00
|
|
|
type = r_bin_demangle_type (def);
|
2015-10-19 11:21:12 +00:00
|
|
|
}
|
2015-01-10 00:00:01 +00:00
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2016-11-22 13:58:42 +00:00
|
|
|
R_API char *r_bin_demangle(RBinFile *binfile, const char *def, const char *str, ut64 vaddr) {
|
2015-10-19 11:21:12 +00:00
|
|
|
int type = -1;
|
2016-02-18 12:52:31 +00:00
|
|
|
RBin *bin;
|
2016-11-22 13:58:42 +00:00
|
|
|
if (!binfile || !str || !*str) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2016-02-18 12:52:31 +00:00
|
|
|
bin = binfile->rbin;
|
2016-11-22 13:58:42 +00:00
|
|
|
if (!strncmp (str, "sym.", 4)) {
|
2016-02-07 20:44:35 +00:00
|
|
|
str += 4;
|
2016-11-22 13:58:42 +00:00
|
|
|
}
|
|
|
|
if (!strncmp (str, "imp.", 4)) {
|
2015-10-19 11:21:12 +00:00
|
|
|
str += 4;
|
2016-11-22 13:58:42 +00:00
|
|
|
}
|
2015-10-19 11:21:12 +00:00
|
|
|
if (!strncmp (str, "__", 2)) {
|
2016-05-03 02:31:36 +00:00
|
|
|
if (str[2] == 'T') {
|
|
|
|
type = R_BIN_NM_SWIFT;
|
|
|
|
} else {
|
|
|
|
type = R_BIN_NM_CXX;
|
|
|
|
// str++;
|
|
|
|
}
|
2015-10-19 11:21:12 +00:00
|
|
|
}
|
2016-03-13 14:43:12 +00:00
|
|
|
// if str is sym. or imp. when str+=4 str points to the end so just return
|
2016-11-22 13:20:52 +00:00
|
|
|
if (!*str) {
|
2016-03-13 14:43:12 +00:00
|
|
|
return NULL;
|
2016-11-22 13:20:52 +00:00
|
|
|
}
|
2015-10-19 11:21:12 +00:00
|
|
|
if (type == -1) {
|
|
|
|
type = r_bin_lang_type (binfile, def, str);
|
|
|
|
}
|
2011-02-25 03:19:30 +00:00
|
|
|
switch (type) {
|
|
|
|
case R_BIN_NM_JAVA: return r_bin_demangle_java (str);
|
2017-01-04 23:52:13 +00:00
|
|
|
case R_BIN_NM_RUST: return r_bin_demangle_rust (binfile, str, vaddr);
|
2015-01-10 00:00:01 +00:00
|
|
|
case R_BIN_NM_OBJC: return r_bin_demangle_objc (NULL, str);
|
2016-05-03 02:31:36 +00:00
|
|
|
case R_BIN_NM_SWIFT: return r_bin_demangle_swift (str, bin->demanglercmd);
|
2016-11-22 13:58:42 +00:00
|
|
|
case R_BIN_NM_CXX: return r_bin_demangle_cxx (binfile, str, vaddr);
|
2015-02-11 01:05:22 +00:00
|
|
|
case R_BIN_NM_DLANG: return r_bin_demangle_plugin (bin, "dlang", str);
|
2011-02-25 03:19:30 +00:00
|
|
|
}
|
|
|
|
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
|