Rizin
unix-like reverse engineering framework and cli tools
parse_common.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2018-2021 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
30 typedef struct {
31  const char *mnemonic;
33  const char *grammar;
35 
36 typedef struct {
37  const char *expected;
38  const char *pseudo;
40 
41 typedef struct {
42  const char *expected;
43  const char *replace;
44  int flag; // 0 for first match, 1 for all matches
46 
47 typedef struct {
49  size_t direct_length;
54  int max_args;
55  RzList *(*tokenize)(const char *assembly, size_t length);
57 
58 #define RZ_PSEUDO_DEFINE_GRAMMAR(x, y) \
59  { .mnemonic = x, .mnemonic_length = sizeof(x) - 1, .grammar = y }
60 
61 #define RZ_PSEUDO_DEFINE_DIRECT(x, y) \
62  { .expected = x, .pseudo = y }
63 
64 #define RZ_PSEUDO_DEFINE_REPLACE(x, y, f) \
65  { .expected = x, .replace = y, .flag = f }
66 
67 #define RZ_PSEUDO_DEFINE_CONFIG(d, l, r, m, t) \
68  { \
69  .direct = d, \
70  .direct_length = RZ_ARRAY_SIZE(d), \
71  .replace = r, \
72  .replace_length = RZ_ARRAY_SIZE(r), \
73  .lexicon = l, \
74  .lexicon_length = RZ_ARRAY_SIZE(l), \
75  .max_args = m, \
76  .tokenize = t, \
77  }
78 
79 #define RZ_PSEUDO_DEFINE_CONFIG_NO_DIRECT(l, r, m, t) \
80  { \
81  .direct = NULL, \
82  .direct_length = 0, \
83  .replace = r, \
84  .replace_length = RZ_ARRAY_SIZE(r), \
85  .lexicon = l, \
86  .lexicon_length = RZ_ARRAY_SIZE(l), \
87  .max_args = m, \
88  .tokenize = t, \
89  }
90 
91 #define RZ_PSEUDO_DEFINE_CONFIG_ONLY_LEXICON(l, m, t) \
92  { \
93  .direct = NULL, \
94  .direct_length = 0, \
95  .replace = NULL, \
96  .replace_length = 0, \
97  .lexicon = l, \
98  .lexicon_length = RZ_ARRAY_SIZE(l), \
99  .max_args = m, \
100  .tokenize = t, \
101  }
102 
103 static bool rz_pseudo_convert(const RzPseudoConfig *config, const char *assembly, RzStrBuf *sb) {
104  rz_return_val_if_fail(config && config->tokenize && config->lexicon, false);
105 
106  size_t i, p;
107  const char *tmp = NULL;
108  const RzPseudoGrammar *gr = NULL;
109  const RzPseudoReplace *rp = NULL;
110 
111  if (!strcmp(assembly, "invalid")) {
112  return true;
113  } else if (!strncmp(assembly, "trunc", 5)) {
114  return true;
115  } else if (!strcmp(assembly, "nop")) {
116  return true;
117  }
118  size_t length = strlen(assembly);
119 
120  for (i = 0; i < config->direct_length; ++i) {
121  tmp = config->direct[i].expected;
122  if (!strcmp(assembly, tmp)) {
123  rz_strbuf_set(sb, config->direct[i].pseudo);
124  return true;
125  }
126  }
127 
128  size_t mnemonic_length = length;
129  if ((tmp = strchr(assembly, ' '))) {
130  mnemonic_length = tmp - assembly;
131  }
132  for (i = 0; i < config->lexicon_length; ++i) {
133  gr = &config->lexicon[i];
134  if (gr->mnemonic_length == mnemonic_length && !strncmp(gr->mnemonic, assembly, mnemonic_length)) {
135  break;
136  }
137  gr = NULL;
138  }
139  if (!gr) {
140  rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
141  return true;
142  }
143 
144  RzList *tokens = config->tokenize(assembly, length);
145  if (!tokens) {
146  rz_strbuf_setf(sb, "asm(\"%s\")", assembly);
147  return true;
148  }
149 
150  for (i = 0, p = 0; gr->grammar[p]; ++p) {
151  int index = gr->grammar[p] - '0';
152  if (index > 0 && index < config->max_args) {
153  tmp = (const char *)rz_list_get_n(tokens, index);
154  if (!tmp) {
155  tmp = "?";
156  }
157  rz_strbuf_append_n(sb, gr->grammar + i, p - i);
158  i = p + 1;
160  } else if (gr->grammar[p] == '#') {
161  rz_strbuf_append_n(sb, gr->grammar + i, p - i);
162  i = p + 1;
163  p++;
164  while (gr->grammar[p] && !IS_WHITESPACE(gr->grammar[p])) {
165  ++p;
166  }
167  }
168  }
169 
170  if (i < p) {
171  rz_strbuf_append_n(sb, gr->grammar + i, p - i);
172  }
173 
174  char *result = rz_strbuf_drain_nofree(sb);
175  for (int i = 0; i < config->replace_length; ++i) {
176  rp = &config->replace[i];
177  result = rz_str_replace(result, rp->expected, rp->replace, rp->flag);
178  }
179  rz_strbuf_set(sb, result);
180  free(result);
181 
182  rz_list_free(tokens);
183  return true;
184 }
lzma_index ** i
Definition: index.h:629
static SblHeader sb
Definition: bin_mbn.c:26
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void length
Definition: sflib.h:133
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
static char * rp[]
Definition: i8080dis.c:36
void * p
Definition: libc.cpp:67
RZ_API RZ_BORROW void * rz_list_get_n(RZ_NONNULL const RzList *list, ut32 n)
Returns the N-th element of the list.
Definition: list.c:574
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
static bool rz_pseudo_convert(const RzPseudoConfig *config, const char *assembly, RzStrBuf *sb)
Definition: parse_common.c:103
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API char * rz_str_replace(char *str, const char *key, const char *val, int g)
Definition: str.c:1110
#define IS_WHITESPACE(x)
Definition: rz_str_util.h:13
RZ_API RZ_OWN char * rz_strbuf_drain_nofree(RzStrBuf *sb)
Definition: strbuf.c:349
RZ_API const char * rz_strbuf_set(RzStrBuf *sb, const char *s)
Definition: strbuf.c:153
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API const char * rz_strbuf_setf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API bool rz_strbuf_append_n(RzStrBuf *sb, const char *s, size_t l)
Definition: strbuf.c:229
const RzPseudoGrammar * lexicon
Definition: parse_common.c:52
const RzPseudoReplace * replace
Definition: parse_common.c:50
size_t replace_length
Definition: parse_common.c:51
size_t lexicon_length
Definition: parse_common.c:53
const RzPseudoDirect * direct
Definition: parse_common.c:48
size_t direct_length
Definition: parse_common.c:49
const char * expected
Definition: parse_common.c:37
const char * pseudo
Definition: parse_common.c:38
const char * mnemonic
Definition: parse_common.c:31
const char * grammar
Definition: parse_common.c:33
size_t mnemonic_length
Definition: parse_common.c:32
const char * expected
Definition: parse_common.c:42
const char * replace
Definition: parse_common.c:43