1 /* radare - LGPL - Copyright 2014-2018 condret */
2
3 #include <string.h>
4 #include <r_types.h>
5 #include <r_asm.h>
6 #include <r_anal.h>
7 #include <r_lib.h>
8 #include <r_io.h>
9 #define WS_API static
10 #include "../../asm/arch/whitespace/wsdis.c"
11
ws_find_label(int l,const RIOBind * iob)12 static ut64 ws_find_label(int l, const RIOBind *iob) {
13 RIO *io = iob->io;
14 ut64 cur = 0, size = iob->desc_size (io->desc);
15 ut8 buf[128];
16 RAsmOp aop;
17 iob->read_at (iob->io, cur, buf, 128);
18 while (cur <= size && wsdis (&aop, buf, 128)) {
19 const char *buf_asm = r_strbuf_get (&aop.buf_asm); // r_asm_op_get_asm (&aop);
20 if (buf_asm && (strlen (buf_asm) > 4) && buf_asm[0] == 'm' && buf_asm[1] == 'a' && l == atoi (buf_asm + 5)) {
21 return cur;
22 }
23 cur = cur + aop.size;
24 iob->read_at (iob->io, cur, buf, 128);
25 }
26 return 0;
27 }
28
ws_anal(RAnal * anal,RAnalOp * op,ut64 addr,const ut8 * data,int len,RAnalOpMask mask)29 static int ws_anal(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *data, int len, RAnalOpMask mask) {
30 op->addr = addr;
31 op->type = R_ANAL_OP_TYPE_UNK;
32 RAsmOp *aop = R_NEW0 (RAsmOp);
33 op->size = wsdis (aop, data, len);
34 if (op->size) {
35 const char *buf_asm = r_strbuf_get (&aop->buf_asm); // r_asm_op_get_asm (aop);
36 switch (*buf_asm) {
37 case 'n':
38 op->type = R_ANAL_OP_TYPE_NOP;
39 break;
40 case 'e':
41 op->type = R_ANAL_OP_TYPE_TRAP;
42 break;
43 case 'd':
44 op->type = (buf_asm[1] == 'u')? R_ANAL_OP_TYPE_UPUSH: R_ANAL_OP_TYPE_DIV;
45 break;
46 case 'i':
47 op->type = R_ANAL_OP_TYPE_ILL;
48 break;
49 case 'a':
50 op->type = R_ANAL_OP_TYPE_ADD;
51 break;
52 case 'm':
53 op->type = (buf_asm[1] == 'o') ? R_ANAL_OP_TYPE_MOD : R_ANAL_OP_TYPE_MUL;
54 break;
55 case 'r':
56 op->type = R_ANAL_OP_TYPE_RET;
57 break;
58 case 'l':
59 op->type = R_ANAL_OP_TYPE_LOAD;
60 break;
61 case 'c':
62 if (buf_asm[1] == 'a') {
63 op->type = R_ANAL_OP_TYPE_CALL;
64 op->fail = addr + aop->size;
65 op->jump = ws_find_label (atoi (buf_asm + 5), &anal->iob);
66 } else {
67 op->type = R_ANAL_OP_TYPE_UPUSH;
68 }
69 break;
70 case 'j':
71 if (buf_asm[1] == 'm') {
72 op->type = R_ANAL_OP_TYPE_JMP;
73 op->jump = ws_find_label(atoi (buf_asm + 4), &anal->iob);
74 } else {
75 op->type = R_ANAL_OP_TYPE_CJMP;
76 op->jump = ws_find_label(atoi(buf_asm + 3), &anal->iob);
77 }
78 op->fail = addr + aop->size;
79 break;
80 case 'g':
81 op->type = R_ANAL_OP_TYPE_IO;
82 break;
83 case 'p':
84 if (buf_asm[1] == 'o') {
85 op->type = R_ANAL_OP_TYPE_POP;
86 } else {
87 if (buf_asm[2] == 's') {
88 op->type = R_ANAL_OP_TYPE_PUSH;
89 if (127 > atoi (buf_asm + 5) && atoi (buf_asm + 5) >= 33) {
90 char c[4];
91 c[3] = '\0';
92 c[0] = c[2] = '\'';
93 c[1] = (char) atoi (buf_asm + 5);
94 r_meta_set_string (anal, R_META_TYPE_COMMENT, addr, c);
95 }
96 } else {
97 op->type = R_ANAL_OP_TYPE_IO;
98 }
99 }
100 break;
101 case 's':
102 switch (buf_asm[1]) {
103 case 'u':
104 op->type = R_ANAL_OP_TYPE_SUB;
105 break;
106 case 't':
107 op->type = R_ANAL_OP_TYPE_STORE;
108 break;
109 case 'l':
110 op->type = R_ANAL_OP_TYPE_LOAD; // XXX
111 break;
112 case 'w':
113 op->type = R_ANAL_OP_TYPE_ROR;
114 }
115 break;
116 }
117 }
118 free (aop);
119 return op->size;
120 }
121
122 RAnalPlugin r_anal_plugin_ws = {
123 .name = "ws",
124 .desc = "Space, tab and linefeed analysis plugin",
125 .license = "LGPL3",
126 .arch = "ws",
127 .bits = 32,
128 .op = &ws_anal,
129 };
130
131 #ifndef R2_PLUGIN_INCORE
132 R_API RLibStruct radare_plugin = {
133 .type = R_LIB_TYPE_ANAL,
134 .data = &r_anal_plugin_ws,
135 .version = R2_VERSION
136 };
137 #endif
138