Rizin
unix-like reverse engineering framework and cli tools
bin_wasm.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2017-2021 pancake <pancake@nopcode.org>
2 // SPDX-FileCopyrightText: 2017-2021 cgvwzq
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 // http://webassembly.org/docs/binary-encoding/#module-structure
6 
7 #include <rz_types.h>
8 #include <rz_util.h>
9 #include <rz_lib.h>
10 #include <rz_bin.h>
11 
12 #include "wasm/wasm.h"
13 #include "../format/wasm/wasm.h"
14 
15 static bool check_buffer(RzBuffer *rbuf) {
16  ut8 buf[4] = { 0 };
17  return rbuf && rz_buf_read_at(rbuf, 0, buf, 4) == 4 && !memcmp(buf, RZ_BIN_WASM_MAGIC_BYTES, 4);
18 }
19 
20 static bool find_export(const ut32 *p, const RzBinWasmExportEntry *q) {
22  return true;
23  }
24  return q->index != (*p);
25 }
26 
27 static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
28  rz_return_val_if_fail(bf && buf && rz_buf_size(buf) != UT64_MAX, false);
29 
30  if (check_buffer(buf)) {
31  obj->bin_obj = rz_bin_wasm_init(bf, buf);
32  return true;
33  }
34  return false;
35 }
36 
37 static void destroy(RzBinFile *bf) {
39 }
40 
41 static ut64 baddr(RzBinFile *bf) {
42  return 0;
43 }
44 
46  return NULL; // TODO
47 }
48 
49 static RzList *sections(RzBinFile *bf);
50 
51 static RzList *entries(RzBinFile *bf) {
52  RzBinWasmObj *bin = bf && bf->o ? bf->o->bin_obj : NULL;
53  // TODO
54  RzList *ret = NULL;
55  RzBinAddr *ptr = NULL;
56  ut64 addr = 0x0;
57 
58  if (!(ret = rz_list_newf((RzListFree)free))) {
59  return NULL;
60  }
61 
63  if (!addr) {
65  if (codes) {
67  RzBinWasmCodeEntry *func;
68  rz_list_foreach (codes, iter, func) {
69  addr = func->code;
70  break;
71  }
72  }
73  if (!addr) {
74  rz_list_free(ret);
75  return NULL;
76  }
77  }
78  if ((ptr = RZ_NEW0(RzBinAddr))) {
79  ptr->paddr = addr;
80  ptr->vaddr = addr;
81  rz_list_append(ret, ptr);
82  }
83  return ret;
84 }
85 
86 static RzList *sections(RzBinFile *bf) {
87  RzBinWasmObj *bin = bf && bf->o ? bf->o->bin_obj : NULL;
88  RzList *ret = NULL;
89  RzList *secs = NULL;
90  RzBinSection *ptr = NULL;
91  RzBinWasmSection *sec;
92 
93  if (!(ret = rz_list_newf((RzListFree)free))) {
94  return NULL;
95  }
96  if (!(secs = rz_bin_wasm_get_sections(bin))) {
97  rz_list_free(ret);
98  return NULL;
99  }
100  RzListIter *iter;
101  rz_list_foreach (secs, iter, sec) {
102  if (!(ptr = RZ_NEW0(RzBinSection))) {
103  rz_list_free(secs);
104  rz_list_free(ret);
105  return NULL;
106  }
107  ptr->name = strdup((char *)sec->name);
108  if (sec->id == RZ_BIN_WASM_SECTION_DATA || sec->id == RZ_BIN_WASM_SECTION_MEMORY) {
109  ptr->is_data = true;
110  }
111  ptr->size = sec->payload_len;
112  ptr->vsize = sec->payload_len;
113  ptr->vaddr = sec->offset;
114  ptr->paddr = sec->offset;
115  // TODO permissions
116  ptr->perm = 0;
117  rz_list_append(ret, ptr);
118  }
119  return ret;
120 }
121 
122 static RzList *symbols(RzBinFile *bf) {
123  RzBinWasmObj *bin = NULL;
124  RzList *ret = NULL, *codes = NULL, *imports = NULL, *exports = NULL;
125  RzBinSymbol *ptr = NULL;
126 
127  if (!bf || !bf->o || !bf->o->bin_obj) {
128  return NULL;
129  }
130  bin = bf->o->bin_obj;
131  if (!(ret = rz_list_newf((RzListFree)rz_bin_symbol_free))) {
132  return NULL;
133  }
134  if (!(codes = rz_bin_wasm_get_codes(bin))) {
135  goto bad_alloc;
136  }
137  if (!(imports = rz_bin_wasm_get_imports(bin))) {
138  goto bad_alloc;
139  }
140  if (!(exports = rz_bin_wasm_get_exports(bin))) {
141  goto bad_alloc;
142  }
143 
144  ut32 fcn_idx = 0,
145  table_idx = 0,
146  mem_idx = 0,
147  global_idx = 0;
148 
149  ut32 i = 0;
151  RzListIter *iter;
152  rz_list_foreach (imports, iter, imp) {
153  if (!(ptr = RZ_NEW0(RzBinSymbol))) {
154  goto bad_alloc;
155  }
156  ptr->name = strdup(imp->field_str);
157  ptr->libname = strdup(imp->module_str);
158  ptr->is_imported = true;
159  ptr->forwarder = "NONE";
160  ptr->bind = "NONE";
161  switch (imp->kind) {
163  ptr->type = RZ_BIN_TYPE_FUNC_STR;
164  fcn_idx++;
165  break;
167  ptr->type = "TABLE";
168  table_idx++;
169  break;
171  ptr->type = "MEMORY";
172  mem_idx++;
173  break;
176  global_idx++;
177  break;
178  }
179  ptr->size = 0;
180  ptr->vaddr = -1;
181  ptr->paddr = -1;
182  ptr->ordinal = i;
183  i += 1;
184  rz_list_append(ret, ptr);
185  }
186 
187  RzListIter *is_exp = NULL;
188  RzBinWasmCodeEntry *func;
189  // RzBinWasmExportEntry *export = NULL;
190  rz_list_foreach (codes, iter, func) {
191  if (!(ptr = RZ_NEW0(RzBinSymbol))) {
192  goto bad_alloc;
193  }
194 
195  const char *fcn_name = rz_bin_wasm_get_function_name(bin, fcn_idx);
196  if (fcn_name) {
197  ptr->name = strdup(fcn_name);
198 
199  is_exp = rz_list_find(exports, &fcn_idx, (RzListComparator)find_export);
200  if (is_exp) {
202  }
203  } else {
204  // fallback if symbol is not found.
205  ptr->name = rz_str_newf("fcn.%d", fcn_idx);
206  }
207 
208  ptr->forwarder = "NONE";
209  if (!ptr->bind) {
210  ptr->bind = "NONE";
211  }
212  ptr->type = RZ_BIN_TYPE_FUNC_STR;
213  ptr->size = func->len;
214  ptr->vaddr = (ut64)func->code;
215  ptr->paddr = (ut64)func->code;
216  ptr->ordinal = i;
217  i++;
218  fcn_idx++;
219  rz_list_append(ret, ptr);
220  }
221 
222  // TODO: globals, tables and memories
223  return ret;
224 bad_alloc:
225  // not so sure if imports should be freed.
226  rz_list_free(exports);
228  rz_list_free(ret);
229  return NULL;
230 }
231 
232 static RzList *imports(RzBinFile *bf) {
233  RzBinWasmObj *bin = NULL;
234  RzList *imports = NULL;
235  RzBinImport *ptr = NULL;
236 
237  if (!bf || !bf->o || !bf->o->bin_obj) {
238  return NULL;
239  }
240  bin = bf->o->bin_obj;
242  if (!ret) {
243  return NULL;
244  }
245  if (!(imports = rz_bin_wasm_get_imports(bin))) {
246  goto bad_alloc;
247  }
248 
249  RzBinWasmImportEntry *import = NULL;
250  ut32 i = 0;
251  RzListIter *iter;
252  rz_list_foreach (imports, iter, import) {
253  if (!(ptr = RZ_NEW0(RzBinImport))) {
254  goto bad_alloc;
255  }
256  ptr->name = strdup(import->field_str);
257  ptr->classname = strdup(import->module_str);
258  ptr->ordinal = i;
259  ptr->bind = "NONE";
260  switch (import->kind) {
262  ptr->type = "FUNC";
263  break;
265  ptr->type = "TABLE";
266  break;
268  ptr->type = "MEM";
269  break;
271  ptr->type = "GLOBAL";
272  break;
273  }
274  rz_list_append(ret, ptr);
275  }
276  return ret;
277 bad_alloc:
279  rz_list_free(ret);
280  return NULL;
281 }
282 
283 static RzList *libs(RzBinFile *bf) {
284  return NULL;
285 }
286 
287 static RzBinInfo *info(RzBinFile *bf) {
288  RzBinInfo *ret = NULL;
289 
290  if (!(ret = RZ_NEW0(RzBinInfo))) {
291  return NULL;
292  }
293  ret->file = strdup(bf->file);
294  ret->bclass = strdup("module");
295  ret->rclass = strdup("wasm");
296  ret->os = strdup("WebAssembly");
297  ret->arch = strdup("wasm");
298  ret->machine = strdup(ret->arch);
299  ret->subsystem = strdup("wasm");
300  ret->type = strdup("EXEC");
301  ret->bits = 32;
302  ret->has_va = 0;
303  ret->big_endian = false;
304  ret->dbg_info = 0;
305  return ret;
306 }
307 
308 static ut64 size(RzBinFile *bf) {
309  if (!bf || !bf->buf) {
310  return 0;
311  }
312  return rz_buf_size(bf->buf);
313 }
314 
315 /* inspired in http://www.phreedom.org/solar/code/tinype/tiny.97/tiny.asm */
316 static RzBuffer *create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt) {
318 #define B(x, y) rz_buf_append_bytes(buf, (const ut8 *)(x), y)
319 #define D(x) rz_buf_append_ut32(buf, x)
320  B("\x00"
321  "asm",
322  4);
323  B("\x01\x00\x00\x00", 4);
324  return buf;
325 }
326 
328  .name = "wasm",
329  .desc = "WebAssembly bin plugin",
330  .license = "MIT",
331  .load_buffer = &load_buffer,
332  .size = &size,
333  .destroy = &destroy,
334  .check_buffer = &check_buffer,
335  .baddr = &baddr,
336  .binsym = &binsym,
337  .entries = &entries,
339  .sections = &sections,
340  .symbols = &symbols,
341  .imports = &imports,
342  .info = &info,
343  .libs = &libs,
344  .create = &create,
345 };
346 
347 #ifndef RZ_PLUGIN_INCORE
350  .data = &rz_bin_plugin_wasm,
352 };
353 #endif
lzma_index ** i
Definition: index.h:629
RzList * rz_bin_wasm_get_sections(RzBinWasmObj *bin)
Definition: wasm.c:846
ut32 rz_bin_wasm_get_entrypoint(RzBinWasmObj *bin)
Definition: wasm.c:966
const char * rz_bin_wasm_get_function_name(RzBinWasmObj *bin, ut32 idx)
Definition: wasm.c:1237
RzList * rz_bin_wasm_get_imports(RzBinWasmObj *bin)
Definition: wasm.c:1003
RzList * rz_bin_wasm_get_codes(RzBinWasmObj *bin)
Definition: wasm.c:1168
RzList * rz_bin_wasm_get_exports(RzBinWasmObj *bin)
Definition: wasm.c:1026
RzBinWasmObj * rz_bin_wasm_init(RzBinFile *bf, RzBuffer *buf)
Definition: wasm.c:761
void rz_bin_wasm_destroy(RzBinFile *bf)
Definition: wasm.c:789
#define RZ_BIN_WASM_SECTION_MEMORY
Definition: wasm.h:26
@ RZ_BIN_WASM_EXTERNALKIND_Memory
Definition: wasm.h:48
@ RZ_BIN_WASM_EXTERNALKIND_Global
Definition: wasm.h:49
@ RZ_BIN_WASM_EXTERNALKIND_Table
Definition: wasm.h:47
@ RZ_BIN_WASM_EXTERNALKIND_Function
Definition: wasm.h:46
#define RZ_BIN_WASM_MAGIC_BYTES
Definition: wasm.h:15
#define RZ_BIN_WASM_SECTION_DATA
Definition: wasm.h:32
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API void rz_bin_import_free(RzBinImport *imp)
Definition: bin.c:137
RZ_API RZ_OWN RzList * rz_bin_maps_of_file_sections(RZ_NONNULL RzBinFile *binfile)
Create a list of RzBinMap from RzBinSections queried from the given file.
Definition: bin.c:1040
static RzBuffer * create(RzBin *bin, const ut8 *code, int codelen, const ut8 *data, int datalen, RzBinArchOptions *opt)
Definition: bin_wasm.c:316
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb)
Definition: bin_wasm.c:27
static RzList * symbols(RzBinFile *bf)
Definition: bin_wasm.c:122
static RzBinAddr * binsym(RzBinFile *bf, RzBinSpecialSymbol type)
Definition: bin_wasm.c:45
static ut64 size(RzBinFile *bf)
Definition: bin_wasm.c:308
static RzList * libs(RzBinFile *bf)
Definition: bin_wasm.c:283
static bool find_export(const ut32 *p, const RzBinWasmExportEntry *q)
Definition: bin_wasm.c:20
static void destroy(RzBinFile *bf)
Definition: bin_wasm.c:37
RZ_API RzLibStruct rizin_plugin
Definition: bin_wasm.c:348
static RzBinInfo * info(RzBinFile *bf)
Definition: bin_wasm.c:287
static bool check_buffer(RzBuffer *rbuf)
Definition: bin_wasm.c:15
#define B(x, y)
static ut64 baddr(RzBinFile *bf)
Definition: bin_wasm.c:41
RzBinPlugin rz_bin_plugin_wasm
Definition: bin_wasm.c:327
static RzList * entries(RzBinFile *bf)
Definition: bin_wasm.c:51
static RzList * sections(RzBinFile *bf)
Definition: bin_wasm.c:86
static RzList * imports(RzBinFile *bf)
Definition: bin_wasm.c:232
#define RZ_API
#define NULL
Definition: cris-opc.c:27
uint32_t ut32
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
void * p
Definition: libc.cpp:67
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
int type
Definition: mipsasm.c:17
int codes(struct state *s, const struct huffman *lencode, const struct huffman *distcode)
Definition: puff.c:436
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RzBinSpecialSymbol
Definition: rz_bin.h:136
#define RZ_BIN_BIND_GLOBAL_STR
Definition: rz_bin.h:107
#define RZ_BIN_TYPE_FUNC_STR
Definition: rz_bin.h:119
RZ_API st64 rz_buf_read_at(RZ_NONNULL RzBuffer *b, ut64 addr, RZ_NONNULL RZ_OUT ut8 *buf, ut64 len)
Read len bytes of the buffer at the specified address.
Definition: buf.c:1136
RZ_API RZ_OWN RzBuffer * rz_buf_new_with_bytes(RZ_NULLABLE RZ_BORROW const ut8 *bytes, ut64 len)
Creates a new buffer with a bytes array.
Definition: buf.c:465
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
@ RZ_LIB_TYPE_BIN
Definition: rz_lib.h:75
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
int(* RzListComparator)(const void *value, const void *list_data)
Definition: rz_list.h:33
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define UT64_MAX
Definition: rz_types_base.h:86
#define RZ_VERSION
Definition: rz_version.h:8
Definition: malloc.c:26
Definition: inftree9.h:24
ut64 vaddr
Definition: rz_bin.h:186
ut64 paddr
Definition: rz_bin.h:187
XX curplugin == o->plugin.
Definition: rz_bin.h:298
RzBinObject * o
Definition: rz_bin.h:305
char * file
Definition: rz_bin.h:299
RzBuffer * buf
Definition: rz_bin.h:303
const char * type
Definition: rz_bin.h:704
const char * bind
Definition: rz_bin.h:703
ut32 ordinal
Definition: rz_bin.h:707
char * name
Definition: rz_bin.h:701
char * classname
Definition: rz_bin.h:705
int has_va
Definition: rz_bin.h:228
char * type
Definition: rz_bin.h:211
char * os
Definition: rz_bin.h:219
char * subsystem
Definition: rz_bin.h:220
char * machine
Definition: rz_bin.h:216
char * bclass
Definition: rz_bin.h:212
char * file
Definition: rz_bin.h:210
ut64 dbg_info
Definition: rz_bin.h:240
char * rclass
Definition: rz_bin.h:213
char * arch
Definition: rz_bin.h:214
int big_endian
Definition: rz_bin.h:235
void * bin_obj
Definition: rz_bin.h:293
char * name
Definition: rz_bin.h:509
char * version
Definition: rz_bin.h:512
char * name
Definition: rz_bin.h:619
const char * bind
Definition: rz_bin.h:681
bool is_imported
Definition: rz_bin.h:684
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675
ut32 ordinal
Definition: rz_bin.h:692
const char * forwarder
Definition: rz_bin.h:680
char * libname
Definition: rz_bin.h:677
char field_str[RZ_BIN_WASM_STRING_LENGTH]
Definition: wasm.h:113
char module_str[RZ_BIN_WASM_STRING_LENGTH]
Definition: wasm.h:111
char name[RZ_BIN_WASM_STRING_LENGTH]
Definition: wasm.h:78
Definition: sdb.h:63
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58