radare2/libr/parse/parse.c

322 lines
7.3 KiB
C
Raw Normal View History

2016-02-16 01:08:09 +00:00
/* radare2 - LGPL - Copyright 2009-2016 - nibble, pancake, maijin */
#include <stdio.h>
#include <r_types.h>
#include <r_parse.h>
#include <list.h>
#include "../config.h"
2013-06-20 07:54:42 +00:00
R_LIB_VERSION (r_parse);
static RParsePlugin *parse_static_plugins[] =
{ R_PARSE_STATIC_PLUGINS };
R_API RParse *r_parse_new() {
int i;
2015-09-28 09:21:23 +00:00
RParse *p = R_NEW0 (RParse);
if (!p) return NULL;
p->parsers = r_list_new ();
p->parsers->free = NULL; // memleak
p->notin_flagspace = -1;
p->flagspace = -1;
for (i=0; parse_static_plugins[i]; i++) {
2016-04-13 11:54:23 +00:00
r_parse_add (p, parse_static_plugins[i]);
}
return p;
}
R_API void r_parse_free(RParse *p) {
r_list_free (p->parsers);
free (p);
}
R_API int r_parse_add(RParse *p, RParsePlugin *foo) {
if (foo->init)
foo->init (p->user);
r_list_append (p->parsers, foo);
2015-09-14 00:08:31 +00:00
return true;
}
R_API int r_parse_use(RParse *p, const char *name) {
RListIter *iter;
RParsePlugin *h;
r_list_foreach (p->parsers, iter, h) {
if (!strcmp (h->name, name)) {
p->cur = h;
2015-09-14 00:08:31 +00:00
return true;
}
}
2015-09-14 00:08:31 +00:00
return false;
}
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;
char *s, *o;
data[0]='\0';
if (p->cur && p->cur->assemble) {
o = data+strlen (data);
do {
s = strchr (str, ';');
if (s) *s='\0';
ret = p->cur->assemble (p, o, str);
if (!ret) break;
if (s) {
str = s + 1;
o = o+strlen (data);
o[0]='\n';
o[1]='\0';
o++;
}
} while (s);
}
free (in);
return ret;
}
R_API int r_parse_parse(RParse *p, const char *data, char *str) {
if (p->cur && p->cur->parse)
return p->cur->parse (p, data, str);
2015-09-14 00:08:31 +00:00
return false;
}
#define isx86separator(x) ( \
(x)==' '||(x)=='\t'||(x)=='\n'|| (x)=='\r'||(x)==' '|| \
(x)==','||(x)==';'||(x)=='['||(x)==']'|| \
(x)=='('||(x)==')'||(x)=='{'||(x)=='}'||(x)=='\x1b')
2015-10-20 21:37:20 +00:00
static bool isvalidflag(RFlagItem *flag) {
return (flag && strchr (flag->name, '.'));
}
2015-11-23 22:33:50 +00:00
static char *findNextNumber(char *op) {
2015-11-24 00:24:47 +00:00
bool ansi_found = false;
2015-11-23 22:33:50 +00:00
char *p = op;
if (p && *p) {
2015-11-24 00:24:47 +00:00
const char *o = NULL;
2015-11-23 22:33:50 +00:00
while (*p) {
if (*p == 0x1b) {
p++;
2015-11-24 00:24:47 +00:00
if (!*p) break;
2015-11-23 22:33:50 +00:00
if (*p == '[') {
2015-11-24 00:24:47 +00:00
p++;
if (p[0] && p[1] == ';') {
// "\x1b[%d;2;%d;%d;%dm", fgbg, r, g, b
// "\x1b[%d;5;%dm", fgbg, rgb (r, g, b)
for (; p[0] && p[1] && p[0] != 0x1b && p[1] != '\\'; p++);
if (p[1] == '\\') p++;
} else {
// "\x1b[%dm", 30 + k
for (; *p && *p != 'J' && *p != 'm' && *p != 'H'; p++);
if (*p) p++;
}
ansi_found = true;
2015-11-23 22:33:50 +00:00
}
2015-11-24 00:24:47 +00:00
o = p - 1;
2015-11-23 22:33:50 +00:00
} else {
2015-11-24 00:24:47 +00:00
bool is_space = ansi_found;
ansi_found = false;
if (!is_space) {
is_space = (p != op && (*o == ' ' || *o == ',' || *o == '['));
}
2015-11-23 22:33:50 +00:00
if (is_space && *p >= '0' && *p <= '9')
return p;
2015-11-24 00:24:47 +00:00
o = p++;
}
}
}
return NULL;
}
static int filter(RParse *p, RFlag *f, char *data, char *str, int len, bool big_endian) {
char *ptr = data, *ptr2;
RAnalFunction *fcn;
RFlagItem *flag;
ut64 off;
2016-03-22 11:45:05 +00:00
bool x86 = false;
if (p&&p->cur&&p->cur->name) {
if (strstr (p->cur->name, "x86")) x86 = true;
if (strstr (p->cur->name, "m68k")) x86 = true;
}
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)
2015-10-20 21:37:20 +00:00
memmove (ptr2, ptr2 + 6, strlen (ptr2+ 6) + 1);
2014-11-18 23:26:26 +00:00
#endif
ptr2 = NULL;
2015-11-23 01:54:33 +00:00
// remove "dword" 2
while ((ptr = findNextNumber (ptr))) {
if (x86) for (ptr2 = ptr; *ptr2 && !isx86separator (*ptr2); ptr2++);
2015-11-23 01:54:33 +00:00
else for (ptr2 = ptr; *ptr2 && (*ptr2!=']' || (*ptr2=='\x1b') || !isseparator (*ptr2)); ptr2++);
off = r_num_math (NULL, ptr);
2015-11-23 22:55:44 +00:00
if (off > 0xff) {
fcn = r_anal_get_fcn_in (p->anal, off, 0);
if (fcn) {
if (fcn->addr == off) {
*ptr = 0;
// hack to realign pointer for colours
ptr2--;
if (*ptr2 != 0x1b)
ptr2++;
snprintf (str, len, "%s%s%s", data, fcn->name,
(ptr!=ptr2)? ptr2: "");
return true;
}
}
if (f) {
flag = r_flag_get_i2 (f, off);
if (!flag) {
flag = r_flag_get_i (f, off);
}
if (isvalidflag (flag)) {
if (p->notin_flagspace != -1) {
if (p->flagspace == flag->space)
continue;
2015-11-23 22:55:44 +00:00
} else if (p->flagspace != -1 && (p->flagspace != flag->space)) {
ptr = ptr2;
continue;
}
*ptr = 0;
// hack to realign pointer for colours
ptr2--;
if (*ptr2 != 0x1b)
ptr2++;
snprintf (str, len, "%s%s%s", data, flag->name,
(ptr != ptr2)? ptr2: "");
return true;
}
}
}
if (p->hint) {
int pnumleft, immbase = p->hint->immbase;
2016-01-06 00:47:54 +00:00
char num[256], *pnum;
bool is_hex = false;
2015-12-31 15:28:16 +00:00
strncpy (num, ptr, sizeof (num)-2);
pnum = num;
if (!strncmp (pnum, "0x", 2)) {
is_hex = true;
pnum += 2;
}
for (; *pnum; pnum++) {
if ((is_hex && ishexchar(*pnum)) || IS_NUMBER(*pnum))
continue;
break;
}
2016-01-06 00:47:54 +00:00
*pnum = 0;
switch (immbase) {
2015-11-23 22:33:50 +00:00
case 0:
// do nothing
break;
case 1:
r_num_to_bits (num, off);
strcat (num, "b");
break;
case 2: // hack for ascii
memset (num, 0, sizeof (num));
2016-01-06 00:47:54 +00:00
pnum = num;
*pnum++ = '\'';
pnumleft = sizeof (num) - 2;
2016-01-06 00:47:54 +00:00
// Convert *off* to ascii string, byte by byte.
// Since *num* is 256 bytes long, we can omit
// overflow checks.
while (off) {
ut8 ch;
2016-01-06 00:47:54 +00:00
if (big_endian) {
2016-01-06 00:47:54 +00:00
ch = off >> (8 * (sizeof(off) - 1));
off <<= 8;
} else {
ch = off & 0xff;
off >>= 8;
}
//Skip first '\x00' bytes
if (num[1] == '\0' && ch == '\0') continue;
if (IS_PRINTABLE(ch)) {
*pnum++ = ch;
pnumleft --;
2016-01-06 00:47:54 +00:00
} else {
int sz = snprintf (pnum, pnumleft, "\\x%2.2x", ch);
2016-01-06 00:47:54 +00:00
if (sz < 0) break;
pnum += sz;
pnumleft -= sz;
2016-01-06 00:47:54 +00:00
}
}
*pnum++ = '\'';
*pnum = '\0';
break;
case 8:
2015-11-23 01:54:33 +00:00
snprintf (num, sizeof (num), "0%o", (int)off);
break;
case 10:
2015-12-22 21:59:57 +00:00
snprintf (num, sizeof (num), "%" PFMT64d, (st64)off);
break;
2016-02-03 11:29:32 +00:00
case 32:
{
ut32 ip32 = off;
ut8 *ip = (ut8*)&ip32;
snprintf (num, sizeof (num), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
break;
2016-02-03 16:05:03 +00:00
case 80:
2016-02-16 01:08:09 +00:00
if (p && p->anal && p->anal->syscall) {
2016-02-03 16:05:03 +00:00
RSyscallItem *si;
si = r_syscall_get (p->anal->syscall, off, -1);
if (si)
snprintf (num, sizeof (num), "%s()", si->name);
2016-02-03 16:51:55 +00:00
else snprintf (num, sizeof (num), "unknown()");
2016-02-03 16:05:03 +00:00
}
break;
case 16:
/* do nothing */
default:
snprintf (num, sizeof (num), "0x%"PFMT64x, (ut64) off);
break;
}
*ptr = 0;
snprintf (str, len, "%s%s%s", data, num, (ptr != ptr2)? ptr2: "");
return true;
}
ptr = ptr2;
}
strncpy (str, data, len);
2015-09-14 00:08:31 +00:00
return false;
}
R_API int r_parse_filter(RParse *p, RFlag *f, char *data, char *str, int len, bool big_endian) {
filter (p, f, data, str, len, big_endian);
if (p->cur && p->cur->filter)
return p->cur->filter (p, f, data, str, len, big_endian);
2015-09-14 00:08:31 +00:00
return false;
}
2015-11-19 22:12:08 +00:00
R_API bool r_parse_varsub(RParse *p, RAnalFunction *f, ut64 addr, int oplen, char *data, char *str, int len) {
if (p->cur && p->cur->varsub) {
2015-11-19 22:12:08 +00:00
return p->cur->varsub (p, f, addr, oplen, data, str, len);
}
2015-09-14 00:08:31 +00:00
return false;
}
/* 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;
}