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