1 /* radare - LGPL - Copyright 2019 - pancake */
2 
3 #include <r_core.h>
4 
5 typedef struct {
6 	ut64 addr;
7 	ut64 faddr;
8 	RAnalFunction *fcn;
9 	int pos; // related to columns
10 	int cur; // current row selected
11 	RList *columns;
12 	RCore *core;
13 	bool canLeft;
14 	bool canRight;
15 } RCoreVisualViewZigns;
16 
17 static const char *cur_name = NULL;
18 
print_item(void * _core,void * _item,bool selected)19 static char *print_item (void *_core, void *_item, bool selected) {
20 	RSignItem *item = _item;
21 	int i;
22 	int bytes_mask = 0;
23 	int bytes_size = item->bytes->size;
24 	//  int bytes_null = bytes_size - bytes_mask;
25 	if (item->bytes->mask) {
26 		for (i = 0; i < bytes_size;i++) {
27 			if (item->bytes->mask[i]) {
28 				bytes_mask++;
29 			}
30 		}
31 	}
32 	if (selected && item->name) {
33 		cur_name = strdup (item->name);
34 	}
35 	return r_str_newf ("%c 0x%08"PFMT64x" bytes=%d/%d %20s\n", selected?'>':' ',
36 		item->addr, bytes_mask, bytes_size, item->name);
37 }
38 
__signs(RCoreVisualViewZigns * status,ut64 addr,bool update)39 static RList *__signs(RCoreVisualViewZigns *status, ut64 addr, bool update) {
40 	RCore *core = status->core;
41 	return r_sign_get_list (core->anal);
42 }
43 
__core_visual_view_zigns_update(RCore * core,RCoreVisualViewZigns * status)44 R_API int __core_visual_view_zigns_update(RCore *core, RCoreVisualViewZigns *status) {
45 	int h, w = r_cons_get_size (&h);
46 	r_cons_clear00 ();
47 	int colh = h -2;
48 	int colw = w -1;
49 	RList *col0 = __signs (status, status->addr, true);
50 	char *col0str = r_str_widget_list (core, col0, colh, status->cur, print_item);
51 
52 	char *title = r_str_newf ("[r2-visual-signatures] 0x%08"PFMT64x" 0x%08"PFMT64x, status->addr, status->faddr);
53 	if (title) {
54 		r_cons_strcat_at (title, 0, 0, w - 1, 2);
55 		free (title);
56 	}
57 	r_cons_strcat_at (col0str, 0, 2, colw, colh);
58 	r_list_free (col0);
59 	r_cons_flush();
60 	return 0;
61 }
62 
r_core_visual_view_zigns(RCore * core)63 R_API int r_core_visual_view_zigns(RCore *core) {
64 	RCoreVisualViewZigns status = {0};
65 	status.core = core;
66 	status.addr = core->offset;
67 	status.fcn = NULL;
68 
69 	while (true) {
70 		__core_visual_view_zigns_update (core, &status);
71 		int ch = r_cons_readchar ();
72 		if (ch == -1 || ch == 4) {
73 			return true;
74 		}
75 		ch = r_cons_arrow_to_hjkl (ch); // get ESC+char, return 'hjkl' char
76 		switch (ch) {
77 		case 'g':
78 			r_core_cmd0 (core, "zg");
79 			break;
80 		case 'h':
81 			if (status.canLeft) {
82 				if (status.pos) {
83 					status.addr = status.faddr;
84 				}
85 				status.pos = 1;
86 				status.cur = 0;
87 			}
88 			break;
89 		case 'l':
90 			if (status.canRight) {
91 				if (status.pos) {
92 					status.addr = status.faddr;
93 				}
94 				status.pos = 2;
95 				status.cur = 0;
96 			}
97 			break;
98 		case 'd':
99 			if (cur_name && *cur_name) {
100 				r_sign_delete (core->anal, cur_name);
101 				R_FREE (cur_name);
102 			}
103 			break;
104 		case 'J':
105 			status.cur += 10;
106 			break;
107 		case 'K':
108 			if (status.cur > 10) {
109 				status.cur -= 10;
110 			} else {
111 				status.cur = 0;
112 			}
113 			break;
114 		case '.':
115 			status.pos = 0;
116 			break;
117 		case 9:
118 		case ' ':
119 		case '\r':
120 		case '\n':
121 			if (status.pos) {
122 				r_core_seek (core, status.faddr, true);
123 			} else {
124 				r_core_seek (core, status.addr, true);
125 			}
126 			return true;
127 			break;
128 		case '_':
129 			r_core_cmd0 (core, "z*~...");
130 			break;
131 		case 'j':
132 			status.cur++;
133 			break;
134 		case 'k':
135 			if (status.cur > 0) {
136 				status.cur--;
137 			} else {
138 				status.cur = 0;
139 			}
140 			break;
141 		case '?':
142 			r_cons_clear00 ();
143 			r_cons_printf (
144 			"vbz: Visual Zignatures:\n\n"
145 			" jkJK  - scroll up/down\n"
146 			" d     - delete current signature\n"
147 			" g     - regenerate signatures\n"
148 			" q     - quit this visual mode\n"
149 			" _     - enter the hud\n"
150 			" :     - enter command\n");
151 			r_cons_flush ();
152 			r_cons_any_key (NULL);
153 			break;
154 		case 'q':
155 			R_FREE (cur_name);
156 			return false;
157 		case ':': // TODO: move this into a separate helper function
158 			{
159 			char cmd[1024];
160 			r_cons_show_cursor (true);
161 			r_cons_set_raw (0);
162 			cmd[0]='\0';
163 			r_line_set_prompt (":> ");
164 			if (r_cons_fgets (cmd, sizeof (cmd), 0, NULL) < 0) {
165 				cmd[0] = '\0';
166 			}
167 			r_core_cmd_task_sync (core, cmd, 1);
168 			r_cons_set_raw (1);
169 			r_cons_show_cursor (false);
170 			if (cmd[0]) {
171 				r_cons_any_key (NULL);
172 			}
173 			r_cons_clear ();
174 			}
175 			break;
176 		}
177 	}
178 	return false;
179 }
180