2018-05-28 23:42:54 +02:00
|
|
|
/* radare2 - LGPL - Copyright 2009-2018 - nibble, pancake, maijin */
|
2009-02-24 15:58:21 +01:00
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
|
|
|
#include <r_types.h>
|
|
|
|
#include <r_parse.h>
|
2017-05-26 02:43:26 +02:00
|
|
|
#include <config.h>
|
2009-08-14 01:44:12 +00:00
|
|
|
|
2013-06-20 09:54:42 +02:00
|
|
|
R_LIB_VERSION (r_parse);
|
2013-06-14 02:51:33 +02:00
|
|
|
|
2012-07-22 12:00:35 +04:00
|
|
|
static RParsePlugin *parse_static_plugins[] =
|
2009-08-14 01:44:12 +00:00
|
|
|
{ R_PARSE_STATIC_PLUGINS };
|
2009-02-24 15:58:21 +01:00
|
|
|
|
2011-10-05 02:38:37 +02:00
|
|
|
R_API RParse *r_parse_new() {
|
2010-05-20 17:40:58 +02:00
|
|
|
int i;
|
2015-09-28 11:21:23 +02:00
|
|
|
RParse *p = R_NEW0 (RParse);
|
2016-11-02 22:49:36 +01:00
|
|
|
if (!p) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-11-13 00:53:52 +01:00
|
|
|
p->parsers = r_list_new ();
|
2016-05-24 21:22:15 +01:00
|
|
|
if (!p->parsers) {
|
|
|
|
r_parse_free (p);
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-11-13 00:53:52 +01:00
|
|
|
p->parsers->free = NULL; // memleak
|
2012-11-13 02:00:00 +01:00
|
|
|
p->notin_flagspace = -1;
|
|
|
|
p->flagspace = -1;
|
2018-05-11 15:40:25 +08:00
|
|
|
p->pseudo = false;
|
2017-03-17 11:54:34 +01:00
|
|
|
p->relsub = false;
|
2018-09-30 11:41:19 -04:00
|
|
|
p->tailsub = false;
|
2017-06-28 01:29:04 +02:00
|
|
|
p->minval = 0x100;
|
2017-03-17 11:54:34 +01:00
|
|
|
p->localvar_only = false;
|
2016-11-02 22:49:36 +01:00
|
|
|
for (i = 0; parse_static_plugins[i]; i++) {
|
2016-04-13 17:24:23 +05:30
|
|
|
r_parse_add (p, parse_static_plugins[i]);
|
2009-09-24 12:29:05 +02:00
|
|
|
}
|
|
|
|
return p;
|
2009-02-24 15:58:21 +01:00
|
|
|
}
|
|
|
|
|
2011-10-05 02:38:37 +02:00
|
|
|
R_API void r_parse_free(RParse *p) {
|
2012-11-13 00:53:52 +01:00
|
|
|
r_list_free (p->parsers);
|
2011-10-05 02:38:37 +02:00
|
|
|
free (p);
|
2010-05-20 17:40:58 +02:00
|
|
|
}
|
|
|
|
|
2011-10-05 02:38:37 +02:00
|
|
|
R_API int r_parse_add(RParse *p, RParsePlugin *foo) {
|
2016-10-18 01:49:32 +02:00
|
|
|
if (foo->init) {
|
2011-10-05 02:38:37 +02:00
|
|
|
foo->init (p->user);
|
2016-10-18 01:49:32 +02:00
|
|
|
}
|
2012-11-13 00:53:52 +01:00
|
|
|
r_list_append (p->parsers, foo);
|
2015-09-14 02:08:31 +02:00
|
|
|
return true;
|
2009-02-24 15:58:21 +01:00
|
|
|
}
|
|
|
|
|
2011-10-05 02:38:37 +02:00
|
|
|
R_API int r_parse_use(RParse *p, const char *name) {
|
2012-11-13 00:53:52 +01:00
|
|
|
RListIter *iter;
|
|
|
|
RParsePlugin *h;
|
|
|
|
r_list_foreach (p->parsers, iter, h) {
|
2011-10-05 02:38:37 +02:00
|
|
|
if (!strcmp (h->name, name)) {
|
2009-02-24 15:58:21 +01:00
|
|
|
p->cur = h;
|
2015-09-14 02:08:31 +02:00
|
|
|
return true;
|
2009-02-24 15:58:21 +01:00
|
|
|
}
|
|
|
|
}
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2009-02-24 15:58:21 +01:00
|
|
|
}
|
|
|
|
|
2011-10-05 02:38:37 +02:00
|
|
|
R_API int r_parse_assemble(RParse *p, char *data, char *str) {
|
|
|
|
char *in = strdup (str);
|
2015-09-14 02:08:31 +02:00
|
|
|
int ret = false;
|
2009-09-24 12:29:05 +02:00
|
|
|
char *s, *o;
|
2009-08-14 02:19:54 +00:00
|
|
|
|
|
|
|
data[0]='\0';
|
|
|
|
if (p->cur && p->cur->assemble) {
|
2016-11-02 22:49:36 +01:00
|
|
|
o = data + strlen (data);
|
2009-08-14 02:19:54 +00:00
|
|
|
do {
|
2011-10-05 02:38:37 +02:00
|
|
|
s = strchr (str, ';');
|
2016-11-02 22:49:36 +01:00
|
|
|
if (s) {
|
|
|
|
*s = '\0';
|
|
|
|
}
|
2011-10-05 02:38:37 +02:00
|
|
|
ret = p->cur->assemble (p, o, str);
|
2016-11-02 22:49:36 +01:00
|
|
|
if (!ret) {
|
|
|
|
break;
|
|
|
|
}
|
2009-08-14 02:19:54 +00:00
|
|
|
if (s) {
|
|
|
|
str = s + 1;
|
2016-10-18 01:49:32 +02:00
|
|
|
o = o + strlen (data);
|
|
|
|
o[0] = '\n';
|
|
|
|
o[1] = '\0';
|
2011-10-05 02:38:37 +02:00
|
|
|
o++;
|
2009-08-14 02:19:54 +00:00
|
|
|
}
|
2011-10-05 02:38:37 +02:00
|
|
|
} while (s);
|
2009-08-14 02:19:54 +00:00
|
|
|
}
|
2011-10-05 02:38:37 +02:00
|
|
|
free (in);
|
2009-08-14 02:19:54 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2011-10-05 12:40:16 +02:00
|
|
|
R_API int r_parse_parse(RParse *p, const char *data, char *str) {
|
2016-11-02 22:49:36 +01:00
|
|
|
if (p->cur && p->cur->parse) {
|
2011-10-05 02:38:37 +02:00
|
|
|
return p->cur->parse (p, data, str);
|
2016-11-02 22:49:36 +01:00
|
|
|
}
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2011-02-23 15:17:06 +01:00
|
|
|
}
|
|
|
|
|
2013-05-22 01:49:18 +02:00
|
|
|
#define isx86separator(x) ( \
|
|
|
|
(x)==' '||(x)=='\t'||(x)=='\n'|| (x)=='\r'||(x)==' '|| \
|
|
|
|
(x)==','||(x)==';'||(x)=='['||(x)==']'|| \
|
2013-07-04 14:08:58 +02:00
|
|
|
(x)=='('||(x)==')'||(x)=='{'||(x)=='}'||(x)=='\x1b')
|
2013-05-22 01:49:18 +02:00
|
|
|
|
2015-10-20 23:37:20 +02:00
|
|
|
static bool isvalidflag(RFlagItem *flag) {
|
2016-08-11 02:32:23 +02:00
|
|
|
if (flag) {
|
|
|
|
if (strchr (flag->name, '.')) {
|
|
|
|
return strncmp (flag->name, "section.", 8);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
2013-09-30 01:14:04 +02:00
|
|
|
}
|
|
|
|
|
2015-11-23 23:33:50 +01:00
|
|
|
static char *findNextNumber(char *op) {
|
2018-05-28 23:42:54 +02:00
|
|
|
if (!op) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-11-24 01:24:47 +01:00
|
|
|
bool ansi_found = false;
|
2015-11-23 23:33:50 +01:00
|
|
|
char *p = op;
|
2018-05-28 23:42:54 +02:00
|
|
|
const char *o = NULL;
|
|
|
|
while (*p) {
|
|
|
|
if (p[0] == 0x1b && p[1] == '[') {
|
|
|
|
ansi_found = true;
|
|
|
|
p += 2;
|
2018-11-21 22:35:48 +01:00
|
|
|
for (; *p && *p != 'J' && *p != 'm' && *p != 'H'; p++) {
|
|
|
|
;
|
|
|
|
}
|
|
|
|
if (*p) {
|
|
|
|
p++;
|
|
|
|
if (!*p) {
|
|
|
|
break;
|
2015-11-24 01:24:47 +01:00
|
|
|
}
|
2018-05-28 23:42:54 +02:00
|
|
|
}
|
|
|
|
o = p - 1;
|
|
|
|
} else {
|
|
|
|
bool is_space = ansi_found;
|
|
|
|
ansi_found = false;
|
|
|
|
if (!is_space) {
|
|
|
|
is_space = p == op;
|
|
|
|
if (!is_space && o) {
|
|
|
|
is_space = (*o == ' ' || *o == ',' || *o == '[');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (*p == '[') {
|
|
|
|
p++;
|
|
|
|
if (!*p) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!IS_DIGIT (*p)) {
|
2017-03-24 02:42:31 +01:00
|
|
|
char *t = p;
|
2018-09-13 10:17:26 +02:00
|
|
|
for (; *t && *t != ']'; t++) {
|
|
|
|
;
|
|
|
|
}
|
2018-05-28 23:42:54 +02:00
|
|
|
if (*t == ']') {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
p = t;
|
|
|
|
if (!*p) {
|
|
|
|
break;
|
2017-03-24 02:42:31 +01:00
|
|
|
}
|
|
|
|
}
|
2015-11-23 23:04:49 +01:00
|
|
|
}
|
2018-05-28 23:42:54 +02:00
|
|
|
if (is_space && IS_DIGIT (*p)) {
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
o = p++;
|
2015-11-23 23:04:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2018-09-30 11:41:19 -04:00
|
|
|
static char *findEnd(const char *s) {
|
|
|
|
while (*s == 'x' || IS_HEXCHAR (*s)) {
|
|
|
|
s++;
|
|
|
|
// also skip ansi escape codes here :?
|
|
|
|
}
|
|
|
|
return strdup (s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void insert(char *dst, const char *src) {
|
|
|
|
char *endNum = findEnd (dst);
|
|
|
|
strcpy (dst, src);
|
|
|
|
strcpy (dst + strlen (src), endNum);
|
|
|
|
free (endNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int filter(RParse *p, ut64 addr, RFlag *f, char *data, char *str, int len, bool big_endian) {
|
2017-03-08 01:09:30 +05:30
|
|
|
char *ptr = data, *ptr2, *ptr_backup;
|
2013-05-22 01:49:18 +02:00
|
|
|
RAnalFunction *fcn;
|
|
|
|
RFlagItem *flag;
|
|
|
|
ut64 off;
|
2016-03-22 12:45:05 +01:00
|
|
|
bool x86 = false;
|
2018-10-11 01:17:48 +08:00
|
|
|
bool arm = false;
|
2017-03-08 01:09:30 +05:30
|
|
|
bool computed = false;
|
2016-08-11 02:32:23 +02:00
|
|
|
if (p && p->cur && p->cur->name) {
|
2018-09-13 10:17:26 +02:00
|
|
|
if (strstr (p->cur->name, "x86")) {
|
|
|
|
x86 = true;
|
|
|
|
}
|
|
|
|
if (strstr (p->cur->name, "m68k")) {
|
|
|
|
x86 = true;
|
|
|
|
}
|
2018-10-11 01:17:48 +08:00
|
|
|
if (strstr (p->cur->name, "arm")) {
|
|
|
|
arm = true;
|
|
|
|
}
|
2016-03-22 12:45:05 +01:00
|
|
|
}
|
2016-08-11 02:32:23 +02:00
|
|
|
if (!data || !p) {
|
|
|
|
return 0;
|
|
|
|
}
|
2014-11-19 00:26:26 +01:00
|
|
|
#if FILTER_DWORD
|
|
|
|
ptr2 = strstr (ptr, "dword ");
|
2016-08-11 02:32:23 +02:00
|
|
|
if (ptr2) {
|
2018-09-30 11:41:19 -04:00
|
|
|
char *src = ptr2 + 6;
|
|
|
|
memmove (ptr2, src, strlen (src) + 1);
|
2016-08-11 02:32:23 +02:00
|
|
|
}
|
2017-05-05 02:11:02 +02:00
|
|
|
ptr2 = strstr (ptr, "qword ");
|
|
|
|
if (ptr2) {
|
2018-09-30 11:41:19 -04:00
|
|
|
char *src = ptr2 + 6;
|
|
|
|
memmove (ptr2, src, strlen (src) + 1);
|
2017-05-05 02:11:02 +02:00
|
|
|
}
|
2014-11-19 00:26:26 +01:00
|
|
|
#endif
|
2013-05-22 01:49:18 +02:00
|
|
|
ptr2 = NULL;
|
2015-11-23 02:54:33 +01:00
|
|
|
// remove "dword" 2
|
2017-05-04 14:51:05 +02:00
|
|
|
char *nptr;
|
|
|
|
while ((nptr = findNextNumber (ptr))) {
|
2017-05-05 02:11:02 +02:00
|
|
|
#if 0
|
2017-05-06 22:56:50 +02:00
|
|
|
char *optr = ptr;
|
2017-05-05 02:11:02 +02:00
|
|
|
if (nptr[1]== ' ') {
|
|
|
|
for (nptr++;*nptr && *nptr >='0' && *nptr <= '9'; nptr++) {
|
|
|
|
}
|
|
|
|
ptr = nptr;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
#endif
|
2017-05-04 14:51:05 +02:00
|
|
|
ptr = nptr;
|
2016-08-11 02:32:23 +02:00
|
|
|
if (x86) {
|
2017-05-04 14:51:05 +02:00
|
|
|
for (ptr2 = ptr; *ptr2 && !isx86separator (*ptr2); ptr2++) {
|
|
|
|
// eprintf ("(%s) (%c)\n", optr, *ptr2);
|
|
|
|
}
|
2018-03-14 18:32:17 +01:00
|
|
|
} else {
|
2018-09-13 10:17:26 +02:00
|
|
|
for (ptr2 = ptr; *ptr2 && (*ptr2 != ']' && (*ptr2 != '\x1b') && !IS_SEPARATOR (*ptr2)); ptr2++) {
|
|
|
|
;
|
|
|
|
}
|
2016-08-11 02:32:23 +02:00
|
|
|
}
|
2013-05-22 01:49:18 +02:00
|
|
|
off = r_num_math (NULL, ptr);
|
2017-06-28 01:29:04 +02:00
|
|
|
if (off >= p->minval) {
|
2016-09-01 23:50:28 +03:00
|
|
|
fcn = p->analb.get_fcn_in (p->anal, off, 0);
|
2016-08-11 02:32:23 +02:00
|
|
|
if (fcn && fcn->addr == off) {
|
|
|
|
*ptr = 0;
|
|
|
|
// hack to realign pointer for colours
|
|
|
|
ptr2--;
|
|
|
|
if (*ptr2 != 0x1b) {
|
|
|
|
ptr2++;
|
2015-11-23 23:04:49 +01:00
|
|
|
}
|
2016-08-11 02:32:23 +02:00
|
|
|
snprintf (str, len, "%s%s%s", data, fcn->name,
|
|
|
|
(ptr != ptr2)? ptr2: "");
|
|
|
|
return true;
|
2015-05-29 00:51:57 +02:00
|
|
|
}
|
2015-11-23 23:04:49 +01:00
|
|
|
if (f) {
|
2017-02-03 08:53:57 +00:00
|
|
|
RFlagItem *flag2;
|
2015-11-23 23:04:49 +01:00
|
|
|
flag = r_flag_get_i2 (f, off);
|
2017-03-08 01:09:30 +05:30
|
|
|
computed = false;
|
2015-11-23 23:04:49 +01:00
|
|
|
if (!flag) {
|
|
|
|
flag = r_flag_get_i (f, off);
|
|
|
|
}
|
2018-10-11 01:17:48 +08:00
|
|
|
if ((!flag || arm) && p->relsub_addr) {
|
2017-03-08 01:09:30 +05:30
|
|
|
computed = true;
|
2017-02-03 08:53:57 +00:00
|
|
|
flag2 = r_flag_get_i2 (f, p->relsub_addr);
|
|
|
|
if (!flag2) {
|
|
|
|
flag2 = r_flag_get_i (f, p->relsub_addr);
|
|
|
|
}
|
2018-10-11 01:17:48 +08:00
|
|
|
if (!flag || arm) {
|
2017-02-03 08:53:57 +00:00
|
|
|
flag = flag2;
|
|
|
|
}
|
|
|
|
}
|
2015-11-23 23:04:49 +01:00
|
|
|
if (isvalidflag (flag)) {
|
|
|
|
if (p->notin_flagspace != -1) {
|
2016-08-11 02:32:23 +02:00
|
|
|
if (p->flagspace == flag->space) {
|
2015-11-23 23:04:49 +01:00
|
|
|
continue;
|
2016-08-11 02:32:23 +02:00
|
|
|
}
|
2015-11-23 23:55:44 +01:00
|
|
|
} else if (p->flagspace != -1 && (p->flagspace != flag->space)) {
|
|
|
|
ptr = ptr2;
|
|
|
|
continue;
|
|
|
|
}
|
2015-11-23 23:04:49 +01:00
|
|
|
// hack to realign pointer for colours
|
|
|
|
ptr2--;
|
2016-08-11 02:32:23 +02:00
|
|
|
if (*ptr2 != 0x1b) {
|
2015-11-23 23:04:49 +01:00
|
|
|
ptr2++;
|
2016-08-11 02:32:23 +02:00
|
|
|
}
|
2017-03-08 01:09:30 +05:30
|
|
|
ptr_backup = ptr;
|
|
|
|
if (computed && ptr != ptr2 && *ptr) {
|
|
|
|
if (*ptr2 == ']') {
|
|
|
|
ptr2++;
|
2018-09-13 10:17:26 +02:00
|
|
|
for (ptr--; ptr > data && *ptr != '['; ptr--) {
|
|
|
|
;
|
|
|
|
}
|
2017-03-08 01:09:30 +05:30
|
|
|
if (ptr == data) {
|
|
|
|
ptr = ptr_backup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*ptr = 0;
|
2018-07-02 20:06:09 +02:00
|
|
|
snprintf (str, len, "%s%s%s", data, f->realnames? flag->realname : flag->name,
|
2016-08-11 02:32:23 +02:00
|
|
|
(ptr != ptr2) ? ptr2 : "");
|
2017-05-05 02:11:02 +02:00
|
|
|
bool banned = false;
|
|
|
|
{
|
|
|
|
const char *p = strchr (str, '[');
|
|
|
|
const char *a = strchr (str, '+');
|
|
|
|
const char *m = strchr (str, '*');
|
2017-05-19 13:32:03 +02:00
|
|
|
if (p && (a || m)) {
|
2017-05-05 02:11:02 +02:00
|
|
|
banned = true;
|
|
|
|
}
|
|
|
|
}
|
2018-09-30 11:41:19 -04:00
|
|
|
if (p->relsub_addr && !banned) {
|
2017-04-04 21:00:21 +08:00
|
|
|
int flag_len = strlen (flag->name);
|
|
|
|
char *ptr_end = str + strlen (data) + flag_len - 1;
|
|
|
|
char *ptr_right = ptr_end + 1, *ptr_left, *ptr_esc;
|
|
|
|
bool ansi_found = false;
|
2018-06-12 16:43:44 +02:00
|
|
|
if (!*ptr_end) {
|
|
|
|
return true;
|
|
|
|
}
|
2017-04-04 21:00:21 +08:00
|
|
|
while (*ptr_right) {
|
|
|
|
if (*ptr_right == 0x1b) {
|
2018-09-13 10:17:26 +02:00
|
|
|
while (*ptr_right && *ptr_right != 'm') {
|
|
|
|
ptr_right++;
|
|
|
|
}
|
2017-05-05 02:11:02 +02:00
|
|
|
if (*ptr_right) {
|
|
|
|
ptr_right++;
|
|
|
|
}
|
2017-04-04 21:00:21 +08:00
|
|
|
ansi_found = true;
|
|
|
|
continue;
|
2017-05-05 02:11:02 +02:00
|
|
|
}
|
|
|
|
if (*ptr_right == ']') {
|
2017-04-04 21:00:21 +08:00
|
|
|
ptr_left = ptr_esc = ptr_end - flag_len;
|
|
|
|
while (ptr_left >= str) {
|
|
|
|
if (*ptr_left == '[' &&
|
2017-05-05 02:11:02 +02:00
|
|
|
(ptr_left == str || *(ptr_left - 1) != 0x1b)) {
|
|
|
|
break;
|
|
|
|
}
|
2017-04-04 21:00:21 +08:00
|
|
|
ptr_left--;
|
|
|
|
}
|
2017-05-05 02:11:02 +02:00
|
|
|
if (ptr_left < str) {
|
|
|
|
break;
|
|
|
|
}
|
2018-09-13 10:17:26 +02:00
|
|
|
for (; ptr_esc >= str && *ptr_esc != 0x1b; ptr_esc--) {
|
|
|
|
;
|
|
|
|
}
|
2017-05-05 02:11:02 +02:00
|
|
|
if (ptr_esc < str) {
|
|
|
|
ptr_esc = ptr_end - flag_len + 1;
|
|
|
|
}
|
2017-10-16 15:37:17 +02:00
|
|
|
int copied_len = ptr_end - ptr_esc + 1;
|
|
|
|
if (copied_len < 1) {
|
|
|
|
break;
|
|
|
|
}
|
2017-04-04 21:00:21 +08:00
|
|
|
memmove (ptr_left, ptr_esc, copied_len);
|
2018-09-30 11:41:19 -04:00
|
|
|
char *dptr_left = strcpy (ptr_left + copied_len,
|
2018-06-29 12:03:52 +01:00
|
|
|
(ansi_found && ptr_right - ptr_end + 1 >= 4) ? Color_RESET : "");
|
|
|
|
int dlen = strlen (dptr_left);
|
|
|
|
dptr_left += dlen;
|
2018-09-30 11:41:19 -04:00
|
|
|
char *dptr_end = ptr_right + 1;
|
2018-07-05 23:02:59 +08:00
|
|
|
while (*dptr_end) {
|
|
|
|
dptr_end++;
|
|
|
|
}
|
2018-06-29 12:03:52 +01:00
|
|
|
int llen = dptr_end - (ptr_right + 1);
|
|
|
|
memmove (dptr_left, ptr_right + 1, llen);
|
|
|
|
dptr_left[llen] = 0;
|
2017-05-05 02:11:02 +02:00
|
|
|
}
|
|
|
|
break;
|
2017-04-04 21:00:21 +08:00
|
|
|
}
|
|
|
|
}
|
2015-11-23 23:04:49 +01:00
|
|
|
return true;
|
2013-05-22 01:49:18 +02:00
|
|
|
}
|
2018-09-30 11:41:19 -04:00
|
|
|
if (p->tailsub) { // && off > UT32_MAX && addr > UT32_MAX) {
|
|
|
|
if (off != UT64_MAX) {
|
|
|
|
if (off == addr) {
|
|
|
|
insert (ptr, "$$");
|
|
|
|
} else {
|
|
|
|
ut64 tail = r_num_tail_base (NULL, addr, off);
|
|
|
|
if (tail != UT64_MAX) {
|
|
|
|
char str[128];
|
|
|
|
snprintf (str, sizeof (str), "..%"PFMT64x, tail);
|
|
|
|
insert (ptr, str);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-05-22 01:49:18 +02:00
|
|
|
}
|
|
|
|
}
|
2015-09-28 01:00:06 +02:00
|
|
|
if (p->hint) {
|
2016-01-07 13:11:05 +01:00
|
|
|
int pnumleft, immbase = p->hint->immbase;
|
2017-10-31 23:22:20 +08:00
|
|
|
char num[256] = {0}, *pnum, *tmp;
|
2016-03-16 16:14:01 +13:00
|
|
|
bool is_hex = false;
|
2017-03-27 23:13:56 +05:30
|
|
|
int tmp_count;
|
2017-10-31 23:22:20 +08:00
|
|
|
if (p->hint->offset) {
|
|
|
|
*ptr = 0;
|
|
|
|
snprintf (str, len, "%s%s%s", data, p->hint->offset, (ptr != ptr2)? ptr2: "");
|
|
|
|
return true;
|
|
|
|
}
|
2015-12-31 16:28:16 +01:00
|
|
|
strncpy (num, ptr, sizeof (num)-2);
|
2016-03-16 16:14:01 +13:00
|
|
|
pnum = num;
|
|
|
|
if (!strncmp (pnum, "0x", 2)) {
|
|
|
|
is_hex = true;
|
|
|
|
pnum += 2;
|
|
|
|
}
|
|
|
|
for (; *pnum; pnum++) {
|
2018-05-21 18:05:46 +02:00
|
|
|
if ((is_hex && IS_HEXCHAR (*pnum)) || IS_DIGIT (*pnum)) {
|
2015-12-19 17:04:01 +01:00
|
|
|
continue;
|
2016-11-02 22:49:36 +01:00
|
|
|
}
|
2015-12-19 17:04:01 +01:00
|
|
|
break;
|
|
|
|
}
|
2016-01-06 03:47:54 +03:00
|
|
|
*pnum = 0;
|
2015-09-28 01:00:06 +02:00
|
|
|
switch (immbase) {
|
2015-11-23 23:33:50 +01:00
|
|
|
case 0:
|
|
|
|
// do nothing
|
|
|
|
break;
|
2017-09-01 03:49:01 -07:00
|
|
|
case 1: // hack for ascii
|
2017-03-27 23:13:56 +05:30
|
|
|
tmp_count = 0;
|
|
|
|
for (tmp = data; tmp < ptr; tmp++) {
|
2017-04-26 18:49:38 +08:00
|
|
|
if (*tmp == 0x1b) {
|
|
|
|
while (tmp < ptr - 1 && *tmp != 'm') {
|
|
|
|
tmp++;
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
} else if (*tmp == '[') {
|
2017-03-27 23:13:56 +05:30
|
|
|
tmp_count++;
|
|
|
|
} else if (*tmp == ']') {
|
|
|
|
tmp_count--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (tmp_count > 0) {
|
|
|
|
ptr = ptr2;
|
|
|
|
continue;
|
|
|
|
}
|
2016-01-07 13:11:05 +01:00
|
|
|
memset (num, 0, sizeof (num));
|
2016-01-06 03:47:54 +03:00
|
|
|
pnum = num;
|
|
|
|
*pnum++ = '\'';
|
2016-01-07 13:11:05 +01:00
|
|
|
pnumleft = sizeof (num) - 2;
|
2016-01-06 03:47:54 +03:00
|
|
|
// Convert *off* to ascii string, byte by byte.
|
|
|
|
// Since *num* is 256 bytes long, we can omit
|
|
|
|
// overflow checks.
|
|
|
|
while (off) {
|
2016-01-07 13:11:05 +01:00
|
|
|
ut8 ch;
|
|
|
|
if (big_endian) {
|
2016-01-06 03:47:54 +03:00
|
|
|
ch = off & 0xff;
|
|
|
|
off >>= 8;
|
2016-11-02 22:49:36 +01:00
|
|
|
} else {
|
2017-12-22 13:19:02 +01:00
|
|
|
ch = off >> (8 * (sizeof (off) - 1));
|
2016-11-02 22:49:36 +01:00
|
|
|
off <<= 8;
|
2016-01-06 03:47:54 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
//Skip first '\x00' bytes
|
2016-11-02 22:49:36 +01:00
|
|
|
if (num[1] == '\0' && ch == '\0') {
|
|
|
|
continue;
|
|
|
|
}
|
2016-01-06 03:47:54 +03:00
|
|
|
if (IS_PRINTABLE(ch)) {
|
|
|
|
*pnum++ = ch;
|
2016-01-07 13:11:05 +01:00
|
|
|
pnumleft --;
|
2016-01-06 03:47:54 +03:00
|
|
|
} else {
|
2016-01-07 13:11:05 +01:00
|
|
|
int sz = snprintf (pnum, pnumleft, "\\x%2.2x", ch);
|
2016-11-02 22:49:36 +01:00
|
|
|
if (sz < 0) {
|
|
|
|
break;
|
|
|
|
}
|
2016-01-06 03:47:54 +03:00
|
|
|
pnum += sz;
|
2016-01-07 13:11:05 +01:00
|
|
|
pnumleft -= sz;
|
2016-01-06 03:47:54 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
*pnum++ = '\'';
|
|
|
|
*pnum = '\0';
|
2015-09-28 01:00:06 +02:00
|
|
|
break;
|
2017-09-01 03:49:01 -07:00
|
|
|
case 2:
|
|
|
|
r_num_to_bits (num, off);
|
|
|
|
strcat (num, "b");
|
|
|
|
break;
|
2017-11-09 12:57:51 +01:00
|
|
|
case 3:
|
|
|
|
{
|
|
|
|
ut64 swap = 0;
|
|
|
|
if (big_endian) {
|
|
|
|
swap = off & 0xffff;
|
|
|
|
} else {
|
|
|
|
if (off >> 32) {
|
|
|
|
r_mem_swapendian ((ut8*)&swap, (const ut8*)&off, sizeof (off));
|
|
|
|
} else if (off >> 16) {
|
|
|
|
ut32 port = 0;
|
|
|
|
r_mem_swapendian ((ut8*)&port, (const ut8*)&off, sizeof (port));
|
|
|
|
swap = port;
|
|
|
|
} else {
|
|
|
|
ut16 port = 0;
|
|
|
|
r_mem_swapendian ((ut8*)&port, (const ut8*)&off, sizeof (port));
|
|
|
|
swap = port;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
snprintf (num, sizeof (num), "htons (%d)", (int)(swap & 0xFFFF));
|
|
|
|
}
|
|
|
|
break;
|
2015-09-28 01:00:06 +02:00
|
|
|
case 8:
|
2015-11-23 02:54:33 +01:00
|
|
|
snprintf (num, sizeof (num), "0%o", (int)off);
|
2015-09-28 01:00:06 +02:00
|
|
|
break;
|
|
|
|
case 10:
|
2015-12-22 22:59:57 +01:00
|
|
|
snprintf (num, sizeof (num), "%" PFMT64d, (st64)off);
|
2015-09-28 01:00:06 +02:00
|
|
|
break;
|
2016-02-03 12:29:32 +01: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 17:05:03 +01:00
|
|
|
case 80:
|
2016-02-16 02:08:09 +01:00
|
|
|
if (p && p->anal && p->anal->syscall) {
|
2016-02-03 17:05:03 +01:00
|
|
|
RSyscallItem *si;
|
|
|
|
si = r_syscall_get (p->anal->syscall, off, -1);
|
2016-10-02 00:37:09 +02:00
|
|
|
if (si) {
|
2016-02-03 17:05:03 +01:00
|
|
|
snprintf (num, sizeof (num), "%s()", si->name);
|
2016-10-02 00:37:09 +02:00
|
|
|
} else {
|
|
|
|
snprintf (num, sizeof (num), "unknown()");
|
|
|
|
}
|
2016-02-03 17:05:03 +01:00
|
|
|
}
|
|
|
|
break;
|
2015-09-28 01:00:06 +02:00
|
|
|
case 16:
|
|
|
|
/* do nothing */
|
|
|
|
default:
|
2015-11-23 23:04:49 +01:00
|
|
|
snprintf (num, sizeof (num), "0x%"PFMT64x, (ut64) off);
|
2015-09-28 01:00:06 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
*ptr = 0;
|
2015-11-23 23:04:49 +01:00
|
|
|
snprintf (str, len, "%s%s%s", data, num, (ptr != ptr2)? ptr2: "");
|
2015-09-28 01:00:06 +02:00
|
|
|
return true;
|
|
|
|
}
|
2013-05-22 01:49:18 +02:00
|
|
|
ptr = ptr2;
|
|
|
|
}
|
|
|
|
strncpy (str, data, len);
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2013-05-22 01:49:18 +02:00
|
|
|
}
|
|
|
|
|
2018-08-13 16:59:08 +02:00
|
|
|
R_API char *r_parse_immtrim (char *opstr) {
|
2017-11-29 18:56:12 +01:00
|
|
|
if (!opstr || !*opstr) {
|
2018-08-13 16:59:08 +02:00
|
|
|
return NULL;
|
2017-11-29 18:56:12 +01:00
|
|
|
}
|
|
|
|
char *n = strstr (opstr, "0x");
|
|
|
|
if (n) {
|
|
|
|
char *p = n + 2;
|
2018-05-21 18:05:46 +02:00
|
|
|
while (IS_HEXCHAR (*p)) {
|
2017-11-29 18:56:12 +01:00
|
|
|
p++;
|
|
|
|
}
|
|
|
|
memmove (n, p, strlen (p) + 1);
|
|
|
|
}
|
2017-11-30 00:14:08 +01:00
|
|
|
if (strstr (opstr, " - ]")) {
|
2018-08-13 16:59:08 +02:00
|
|
|
opstr = r_str_replace (opstr, " - ]", "]", 1);
|
2017-11-30 00:14:08 +01:00
|
|
|
}
|
|
|
|
if (strstr (opstr, " + ]")) {
|
2018-08-13 16:59:08 +02:00
|
|
|
opstr = r_str_replace (opstr, " + ]", "]", 1);
|
2017-11-30 00:14:08 +01:00
|
|
|
}
|
|
|
|
if (strstr (opstr, ", ]")) {
|
2018-08-13 16:59:08 +02:00
|
|
|
opstr = r_str_replace (opstr, ", ]", "]", 1);
|
2017-11-30 00:14:08 +01:00
|
|
|
}
|
2017-11-29 18:56:12 +01:00
|
|
|
if (strstr (opstr, " - ")) {
|
2018-08-13 16:59:08 +02:00
|
|
|
opstr = r_str_replace (opstr, " - ", "-", 1);
|
2017-11-29 18:56:12 +01:00
|
|
|
}
|
|
|
|
if (strstr (opstr, " + ")) {
|
2018-08-13 16:59:08 +02:00
|
|
|
opstr = r_str_replace (opstr, " + ", "+", 1);
|
2017-11-29 18:56:12 +01:00
|
|
|
}
|
2018-08-13 16:59:08 +02:00
|
|
|
return opstr;
|
2017-11-29 18:56:12 +01:00
|
|
|
}
|
|
|
|
|
2018-09-30 11:41:19 -04:00
|
|
|
R_API int r_parse_filter(RParse *p, ut64 addr, RFlag *f, char *data, char *str, int len, bool big_endian) {
|
|
|
|
filter (p, addr, f, data, str, len, big_endian);
|
2016-11-02 22:49:36 +01:00
|
|
|
if (p->cur && p->cur->filter) {
|
2018-09-30 11:41:19 -04:00
|
|
|
return p->cur->filter (p, addr, f, data, str, len, big_endian);
|
2016-11-02 22:49:36 +01:00
|
|
|
}
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2010-03-19 02:49:30 +01:00
|
|
|
}
|
|
|
|
|
2015-11-19 23:12:08 +01:00
|
|
|
R_API bool r_parse_varsub(RParse *p, RAnalFunction *f, ut64 addr, int oplen, char *data, char *str, int len) {
|
2015-11-27 18:27:44 +01:00
|
|
|
if (p->cur && p->cur->varsub) {
|
2015-11-19 23:12:08 +01:00
|
|
|
return p->cur->varsub (p, f, addr, oplen, data, str, len);
|
2015-11-27 18:27:44 +01:00
|
|
|
}
|
2015-09-14 02:08:31 +02:00
|
|
|
return false;
|
2009-02-24 15:58:21 +01:00
|
|
|
}
|
2012-11-13 00:53:52 +01: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 02:08:31 +02:00
|
|
|
return false;
|
2012-11-13 00:53:52 +01:00
|
|
|
}
|