2015-04-16 04:42:07 +00:00
|
|
|
/* radare - LGPL - Copyright 2009-2015 - nibble, pancake */
|
2009-02-24 14:58:21 +00:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <r_types.h>
|
|
|
|
#include <r_parse.h>
|
|
|
|
#include <list.h>
|
2009-08-14 01:44:12 +00:00
|
|
|
#include "../config.h"
|
|
|
|
|
2013-06-20 07:54:42 +00:00
|
|
|
R_LIB_VERSION (r_parse);
|
2013-06-14 00:51:33 +00:00
|
|
|
|
2012-07-22 08:00:35 +00:00
|
|
|
static RParsePlugin *parse_static_plugins[] =
|
2009-08-14 01:44:12 +00:00
|
|
|
{ R_PARSE_STATIC_PLUGINS };
|
2009-02-24 14:58:21 +00:00
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
R_API RParse *r_parse_new() {
|
2010-05-20 15:40:58 +00:00
|
|
|
int i;
|
2011-10-05 00:38:37 +00:00
|
|
|
RParsePlugin *static_plugin;
|
|
|
|
RParse *p = R_NEW (RParse);
|
|
|
|
if (!p) return NULL;
|
|
|
|
p->user = NULL;
|
2012-11-12 23:53:52 +00:00
|
|
|
p->parsers = r_list_new ();
|
|
|
|
p->parsers->free = NULL; // memleak
|
2012-11-13 01:00:00 +00:00
|
|
|
p->notin_flagspace = -1;
|
|
|
|
p->flagspace = -1;
|
2012-11-12 23:53:52 +00:00
|
|
|
for (i=0; parse_static_plugins[i]; i++) {
|
2011-10-05 00:38:37 +00:00
|
|
|
static_plugin = R_NEW (RParsePlugin);
|
2012-11-12 23:53:52 +00:00
|
|
|
memcpy (static_plugin, parse_static_plugins[i],
|
|
|
|
sizeof (RParsePlugin));
|
2011-10-05 00:38:37 +00:00
|
|
|
r_parse_add (p, static_plugin);
|
2009-09-24 10:29:05 +00:00
|
|
|
}
|
|
|
|
return p;
|
2009-02-24 14:58:21 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
R_API void r_parse_free(RParse *p) {
|
2012-11-12 23:53:52 +00:00
|
|
|
r_list_free (p->parsers);
|
2011-10-05 00:38:37 +00:00
|
|
|
free (p);
|
2010-05-20 15:40:58 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
R_API int r_parse_add(RParse *p, RParsePlugin *foo) {
|
2009-02-24 14:58:21 +00:00
|
|
|
if (foo->init)
|
2011-10-05 00:38:37 +00:00
|
|
|
foo->init (p->user);
|
2012-11-12 23:53:52 +00:00
|
|
|
r_list_append (p->parsers, foo);
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2009-02-24 14:58:21 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
R_API int r_parse_use(RParse *p, const char *name) {
|
2012-11-12 23:53:52 +00:00
|
|
|
RListIter *iter;
|
|
|
|
RParsePlugin *h;
|
|
|
|
r_list_foreach (p->parsers, iter, h) {
|
2011-10-05 00:38:37 +00:00
|
|
|
if (!strcmp (h->name, name)) {
|
2009-02-24 14:58:21 +00:00
|
|
|
p->cur = h;
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2009-02-24 14:58:21 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2009-02-24 14:58:21 +00:00
|
|
|
}
|
|
|
|
|
2011-10-05 00:38:37 +00:00
|
|
|
R_API int r_parse_assemble(RParse *p, char *data, char *str) {
|
|
|
|
char *in = strdup (str);
|
2015-09-14 00:08:31 +00:00
|
|
|
int ret = false;
|
2009-09-24 10:29:05 +00:00
|
|
|
char *s, *o;
|
2009-08-14 02:19:54 +00:00
|
|
|
|
|
|
|
data[0]='\0';
|
|
|
|
if (p->cur && p->cur->assemble) {
|
2011-10-05 00:38:37 +00:00
|
|
|
o = data+strlen (data);
|
2009-08-14 02:19:54 +00:00
|
|
|
do {
|
2011-10-05 00:38:37 +00:00
|
|
|
s = strchr (str, ';');
|
2009-09-24 10:29:05 +00:00
|
|
|
if (s) *s='\0';
|
2011-10-05 00:38:37 +00:00
|
|
|
ret = p->cur->assemble (p, o, str);
|
2009-08-14 02:19:54 +00:00
|
|
|
if (!ret) break;
|
|
|
|
if (s) {
|
|
|
|
str = s + 1;
|
2011-10-05 00:38:37 +00:00
|
|
|
o = o+strlen (data);
|
2009-08-14 02:19:54 +00:00
|
|
|
o[0]='\n';
|
|
|
|
o[1]='\0';
|
2011-10-05 00:38:37 +00:00
|
|
|
o++;
|
2009-08-14 02:19:54 +00:00
|
|
|
}
|
2011-10-05 00:38:37 +00:00
|
|
|
} while (s);
|
2009-08-14 02:19:54 +00:00
|
|
|
}
|
2011-10-05 00:38:37 +00:00
|
|
|
free (in);
|
2009-08-14 02:19:54 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-05 10:40:16 +00:00
|
|
|
R_API int r_parse_parse(RParse *p, const char *data, char *str) {
|
2011-02-23 14:17:06 +00:00
|
|
|
if (p->cur && p->cur->parse)
|
2011-10-05 00:38:37 +00:00
|
|
|
return p->cur->parse (p, data, str);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2011-02-23 14:17:06 +00:00
|
|
|
}
|
|
|
|
|
2013-05-21 23:49:18 +00:00
|
|
|
#define isx86separator(x) ( \
|
|
|
|
(x)==' '||(x)=='\t'||(x)=='\n'|| (x)=='\r'||(x)==' '|| \
|
|
|
|
(x)==','||(x)==';'||(x)=='['||(x)==']'|| \
|
2013-07-04 12:08:58 +00:00
|
|
|
(x)=='('||(x)==')'||(x)=='{'||(x)=='}'||(x)=='\x1b')
|
2013-05-21 23:49:18 +00:00
|
|
|
|
2013-09-29 23:14:04 +00:00
|
|
|
static int isvalidflag(RFlagItem *flag) {
|
|
|
|
if (flag && strchr (flag->name, '.')) {
|
|
|
|
return 1; //strlen (flag->name)>3) {
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2013-05-21 23:49:18 +00:00
|
|
|
static int filter(RParse *p, RFlag *f, char *data, char *str, int len) {
|
|
|
|
char *ptr = data, *ptr2;
|
|
|
|
RAnalFunction *fcn;
|
|
|
|
RFlagItem *flag;
|
|
|
|
ut64 off;
|
|
|
|
int x86 = (p&&p->cur&&p->cur->name)?
|
|
|
|
(strstr (p->cur->name, "x86")? 1: 0): 0;
|
2014-05-10 19:29:33 +00:00
|
|
|
if (!data || !p) return 0;
|
2014-11-18 23:26:26 +00:00
|
|
|
#if FILTER_DWORD
|
|
|
|
ptr2 = strstr (ptr, "dword ");
|
|
|
|
if (ptr2)
|
|
|
|
memmove (ptr2, ptr2+6, strlen (ptr2+6)+1);
|
|
|
|
#endif
|
2013-05-21 23:49:18 +00:00
|
|
|
ptr2 = NULL;
|
2014-11-18 23:26:26 +00:00
|
|
|
// remove "dword" ?
|
2013-05-21 23:49:18 +00:00
|
|
|
while ((ptr = strstr (ptr, "0x"))) {
|
|
|
|
if (x86) for (ptr2 = ptr; *ptr2 && !isx86separator (*ptr2); ptr2++);
|
2013-07-23 15:11:51 +00:00
|
|
|
else for (ptr2 = ptr; *ptr2 && ((*ptr2=='\x1b')||!isseparator (*ptr2)); ptr2++);
|
2013-05-21 23:49:18 +00:00
|
|
|
off = r_num_math (NULL, ptr);
|
2014-09-24 21:59:36 +00:00
|
|
|
// small numbers should not be replaced by flags
|
|
|
|
if (off <0xff) {
|
|
|
|
ptr = ptr2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
// old behaviour: only hide flags at 0
|
2013-05-21 23:49:18 +00:00
|
|
|
if (!off) {
|
|
|
|
ptr = ptr2;
|
|
|
|
continue;
|
|
|
|
}
|
2014-09-24 21:59:36 +00:00
|
|
|
#endif
|
2014-09-26 13:40:17 +00:00
|
|
|
fcn = r_anal_get_fcn_in (p->anal, off, 0);
|
2013-05-21 23:49:18 +00:00
|
|
|
if (fcn) {
|
|
|
|
if (fcn->addr == off) {
|
|
|
|
*ptr = 0;
|
2014-06-07 09:46:28 +00:00
|
|
|
// hack to realign pointer for colours
|
|
|
|
ptr2--;
|
|
|
|
if (*ptr2!=0x1b)
|
|
|
|
ptr2++;
|
2013-05-21 23:49:18 +00:00
|
|
|
snprintf (str, len, "%s%s%s", data, fcn->name,
|
|
|
|
(ptr!=ptr2)? ptr2: "");
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2013-05-21 23:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (f) {
|
2013-09-29 23:14:04 +00:00
|
|
|
flag = r_flag_get_i2 (f, off);
|
2015-05-28 22:51:57 +00:00
|
|
|
if (!flag) {
|
2014-02-13 02:11:23 +00:00
|
|
|
flag = r_flag_get_i (f, off);
|
2015-05-28 22:51:57 +00:00
|
|
|
}
|
2013-09-29 23:14:04 +00:00
|
|
|
if (isvalidflag (flag)) {
|
2013-05-21 23:49:18 +00:00
|
|
|
if (p->notin_flagspace != -1) {
|
|
|
|
if (p->flagspace == flag->space)
|
|
|
|
continue;
|
|
|
|
} else
|
|
|
|
if (p->flagspace != -1 && \
|
|
|
|
(p->flagspace != flag->space)) {
|
|
|
|
ptr = ptr2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
*ptr = 0;
|
2014-06-07 09:46:28 +00:00
|
|
|
// hack to realign pointer for colours
|
2014-05-16 14:47:44 +00:00
|
|
|
ptr2--;
|
|
|
|
if (*ptr2!=0x1b)
|
|
|
|
ptr2++;
|
2013-05-21 23:49:18 +00:00
|
|
|
snprintf (str, len, "%s%s%s", data, flag->name,
|
|
|
|
(ptr!=ptr2)? ptr2: "");
|
2015-09-14 00:08:31 +00:00
|
|
|
return true;
|
2013-05-21 23:49:18 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-27 23:00:06 +00:00
|
|
|
if (p->hint) {
|
|
|
|
int immbase = p->hint->immbase;
|
|
|
|
char num[32];
|
|
|
|
switch (immbase) {
|
|
|
|
case 1:
|
|
|
|
r_num_to_bits (num, off);
|
|
|
|
strcat (num, "b");
|
|
|
|
break;
|
|
|
|
case 2: // hack for ascii
|
2015-09-28 00:04:08 +00:00
|
|
|
snprintf (num, sizeof(num), "'%c'", (char)off);
|
2015-09-27 23:00:06 +00:00
|
|
|
break;
|
|
|
|
case 8:
|
2015-09-28 00:04:08 +00:00
|
|
|
snprintf (num, sizeof(num), "0%o", (int)off);
|
2015-09-27 23:00:06 +00:00
|
|
|
break;
|
|
|
|
case 10:
|
2015-09-28 00:04:08 +00:00
|
|
|
snprintf (num, sizeof(num), "%d", (int)off);
|
2015-09-27 23:00:06 +00:00
|
|
|
break;
|
|
|
|
case 16:
|
|
|
|
/* do nothing */
|
|
|
|
default:
|
2015-09-28 00:04:08 +00:00
|
|
|
snprintf (num, sizeof(num), "0x%x", (ut32) off);
|
2015-09-27 23:00:06 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
*ptr = 0;
|
|
|
|
snprintf (str, len, "%s%s%s", data, num,
|
|
|
|
(ptr!=ptr2)? ptr2: "");
|
|
|
|
return true;
|
|
|
|
}
|
2013-05-21 23:49:18 +00:00
|
|
|
ptr = ptr2;
|
|
|
|
}
|
|
|
|
strncpy (str, data, len);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2013-05-21 23:49:18 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 08:00:35 +00:00
|
|
|
R_API int r_parse_filter(RParse *p, RFlag *f, char *data, char *str, int len) {
|
2013-05-21 23:49:18 +00:00
|
|
|
filter (p, f, data, str, len);
|
2010-03-19 03:32:42 +00:00
|
|
|
if (p->cur && p->cur->filter)
|
2011-10-05 00:38:37 +00:00
|
|
|
return p->cur->filter (p, f, data, str, len);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2010-03-19 01:49:30 +00:00
|
|
|
}
|
|
|
|
|
2012-07-22 08:00:35 +00:00
|
|
|
R_API int r_parse_varsub(RParse *p, RAnalFunction *f, char *data, char *str, int len) {
|
2011-02-23 14:17:06 +00:00
|
|
|
if (p->cur && p->cur->varsub)
|
2011-10-05 00:38:37 +00:00
|
|
|
return p->cur->varsub (p, f, data, str, len);
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2009-02-24 14:58:21 +00:00
|
|
|
}
|
2012-11-12 23:53:52 +00:00
|
|
|
|
|
|
|
/* setters */
|
|
|
|
R_API void r_parse_set_user_ptr(RParse *p, void *user) {
|
|
|
|
p->user = user;
|
|
|
|
}
|
|
|
|
|
|
|
|
R_API void r_parse_set_flagspace(RParse *p, int fs) {
|
|
|
|
p->flagspace = fs;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: DEPRECATE */
|
|
|
|
R_API int r_parse_list(RParse *p) {
|
|
|
|
RListIter *iter;
|
|
|
|
RParsePlugin *h;
|
|
|
|
r_list_foreach (p->parsers, iter, h) {
|
|
|
|
printf ("parse %10s %s\n", h->name, h->desc);
|
|
|
|
}
|
2015-09-14 00:08:31 +00:00
|
|
|
return false;
|
2012-11-12 23:53:52 +00:00
|
|
|
}
|