/* radare - LGPL - Copyright 2009-2015 - nibble, pancake */ #include #include #include #include #include "../config.h" R_LIB_VERSION (r_parse); static RParsePlugin *parse_static_plugins[] = { R_PARSE_STATIC_PLUGINS }; R_API RParse *r_parse_new() { int i; RParsePlugin *static_plugin; RParse *p = R_NEW (RParse); if (!p) return NULL; p->user = 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++) { static_plugin = R_NEW (RParsePlugin); memcpy (static_plugin, parse_static_plugins[i], sizeof (RParsePlugin)); r_parse_add (p, static_plugin); } 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); 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; return true; } } return false; } R_API int r_parse_assemble(RParse *p, char *data, char *str) { char *in = strdup (str); 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); return false; } #define isx86separator(x) ( \ (x)==' '||(x)=='\t'||(x)=='\n'|| (x)=='\r'||(x)==' '|| \ (x)==','||(x)==';'||(x)=='['||(x)==']'|| \ (x)=='('||(x)==')'||(x)=='{'||(x)=='}'||(x)=='\x1b') static int isvalidflag(RFlagItem *flag) { if (flag && strchr (flag->name, '.')) { return 1; //strlen (flag->name)>3) { } return 0; } 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; if (!data || !p) return 0; #if FILTER_DWORD ptr2 = strstr (ptr, "dword "); if (ptr2) memmove (ptr2, ptr2+6, strlen (ptr2+6)+1); #endif ptr2 = NULL; // remove "dword" ? while ((ptr = strstr (ptr, "0x"))) { if (x86) for (ptr2 = ptr; *ptr2 && !isx86separator (*ptr2); ptr2++); else for (ptr2 = ptr; *ptr2 && ((*ptr2=='\x1b')||!isseparator (*ptr2)); ptr2++); off = r_num_math (NULL, ptr); // small numbers should not be replaced by flags if (off <0xff) { ptr = ptr2; continue; } #if 0 // old behaviour: only hide flags at 0 if (!off) { ptr = ptr2; continue; } #endif 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; } 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 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 snprintf (num, sizeof(num), "'%c'", (char)off); break; case 8: snprintf (num, sizeof(num), "0%o", (int)off); break; case 10: snprintf (num, sizeof(num), "%d", (int)off); break; case 16: /* do nothing */ default: snprintf (num, sizeof(num), "0x%x", (ut32) off); break; } *ptr = 0; snprintf (str, len, "%s%s%s", data, num, (ptr!=ptr2)? ptr2: ""); return true; } ptr = ptr2; } strncpy (str, data, len); return false; } R_API int r_parse_filter(RParse *p, RFlag *f, char *data, char *str, int len) { filter (p, f, data, str, len); if (p->cur && p->cur->filter) return p->cur->filter (p, f, data, str, len); return false; } R_API int r_parse_varsub(RParse *p, RAnalFunction *f, char *data, char *str, int len) { if (p->cur && p->cur->varsub) return p->cur->varsub (p, f, data, str, len); 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); } return false; }