1 /* radare - LGPL - Copyright 2009-2018 - pancake */
2 
3 #include <r_core.h> // just to get the RPrint instance
4 #include <r_debug.h>
5 #include <r_cons.h>
6 #include <r_reg.h>
7 
r_debug_reg_sync(RDebug * dbg,int type,int write)8 R_API int r_debug_reg_sync(RDebug *dbg, int type, int write) {
9 	int i, n, size;
10 	if (!dbg || !dbg->reg || !dbg->h) {
11 		return false;
12 	}
13 	// There's no point in syncing a dead target
14 	if (r_debug_is_dead (dbg)) {
15 		return false;
16 	}
17 	// Check if the functions needed are available
18 	if (write && !dbg->h->reg_write) {
19 		return false;
20 	}
21 	if (!write && !dbg->h->reg_read) {
22 		return false;
23 	}
24 	// Sync all the types sequentially if asked
25 	i = (type == R_REG_TYPE_ALL)? R_REG_TYPE_GPR: type;
26 	// Check to get the correct arena when using @ into reg profile (arena!=type)
27 	// if request type is positive and the request regset don't have regs
28 	if (i >= R_REG_TYPE_GPR && dbg->reg->regset[i].regs && !dbg->reg->regset[i].regs->length) {
29 		// seek into the other arena for redirections.
30 		for (n = R_REG_TYPE_GPR; n < R_REG_TYPE_LAST; n++) {
31 			// get regset mask
32 			int mask = dbg->reg->regset[n].maskregstype;
33 			// convert request arena to mask value
34 			int v = ((int)1 << i);
35 			// skip checks on same request arena and check if this arena have inside the request arena type
36 			if (n != i && (mask & v)) {
37 				//eprintf(" req = %i arena = %i mask = %x search = %x \n", i, n, mask, v);
38 				//eprintf(" request arena %i found at arena %i\n", i, n );
39 				// if this arena have the request arena type, force to use this arena.
40 				i = n;
41 				break;
42 			}
43 		}
44 	}
45 	do {
46 		if (write) {
47 			ut8 *buf = r_reg_get_bytes (dbg->reg, i, &size);
48 			if (!buf || !dbg->h->reg_write (dbg, i, buf, size)) {
49 				if (i == R_REG_TYPE_GPR) {
50 					eprintf ("r_debug_reg: error writing "
51 						"registers %d to %d\n", i, dbg->tid);
52 				}
53 				if (type != R_REG_TYPE_ALL || i == R_REG_TYPE_GPR) {
54 					free (buf);
55 					return false;
56 				}
57 			}
58 			free (buf);
59 		} else {
60 			// int bufsize = R_MAX (1024, dbg->reg->size*2); // i know. its hacky
61 			int bufsize = dbg->reg->size;
62 			//int bufsize = dbg->reg->regset[i].arena->size;
63 			if (bufsize > 0) {
64 				ut8 *buf = calloc (1 + 1, bufsize);
65 				if (!buf) {
66 					return false;
67 				}
68 				//we have already checked dbg->h and dbg->h->reg_read above
69 				size = dbg->h->reg_read (dbg, i, buf, bufsize);
70 				// we need to check against zero because reg_read can return false
71 				if (size > 0) {
72 					r_reg_set_bytes (dbg->reg, i, buf, size); //R_MIN (size, bufsize));
73 			//		free (buf);
74 			//		return true;
75 				}
76 				free (buf);
77 			}
78 		}
79 		// DO NOT BREAK R_REG_TYPE_ALL PLEASE
80 		//   break;
81 		// Continue the synchronization or just stop if it was asked only for a single type of regs
82 		i++;
83 	} while ((type == R_REG_TYPE_ALL) && (i < R_REG_TYPE_LAST));
84 	return true;
85 }
86 
r_debug_reg_list(RDebug * dbg,int type,int size,PJ * pj,int rad,const char * use_color)87 R_API bool r_debug_reg_list(RDebug *dbg, int type, int size, PJ *pj, int rad, const char *use_color) {
88 	int delta, cols, n = 0;
89 	const char *fmt, *fmt2, *kwhites;
90 	RPrint *pr = NULL;
91 	int colwidth = 20;
92 	RListIter *iter;
93 	RRegItem *item;
94 	RList *head;
95 	ut64 diff;
96 	char strvalue[256];
97 	bool isJson = (rad == 'j' || rad == 'J');
98 	if (!dbg || !dbg->reg) {
99 		return false;
100 	}
101 	if (dbg->corebind.core) {
102 		pr = ((RCore*)dbg->corebind.core)->print;
103 	}
104 	if (size != 0 && !(dbg->reg->bits & size)) {
105 		// TODO: verify if 32bit exists, otherwise use 64 or 8?
106 		size = 32;
107 	}
108 	if (dbg->bits & R_SYS_BITS_64) {
109 		//fmt = "%s = 0x%08"PFMT64x"%s";
110 		fmt = "%s = %s%s";
111 		fmt2 = "%s%7s%s %s%s";
112 		kwhites = "         ";
113 		colwidth = dbg->regcols? 20: 25;
114 		cols = 3;
115 	} else {
116 		//fmt = "%s = 0x%08"PFMT64x"%s";
117 		fmt = "%s = %s%s";
118 		fmt2 = "%s%7s%s %s%s";
119 		kwhites = "    ";
120 		colwidth = 20;
121 		cols = 4;
122 	}
123 	if (dbg->regcols) {
124 		cols = dbg->regcols;
125 	}
126 	if (isJson) {
127 		pj_o (pj);
128 	}
129 	// with the new field "arena" into reg items why need
130 	// to get all arenas.
131 
132 	int itmidx = -1;
133 	dbg->creg = NULL;
134 	head = r_reg_get_list (dbg->reg, type);
135 	if (!head) {
136 		return false;
137 	}
138 	if (rad == 1 || rad == '*') {
139 		dbg->cb_printf ("fs+%s\n", R_FLAGS_FS_REGISTERS);
140 	}
141 	r_list_foreach (head, iter, item) {
142 		ut64 value;
143 		utX valueBig;
144 		if (type != -1) {
145 			if (type != item->type && R_REG_TYPE_FLG != item->type) {
146 				continue;
147 			}
148 			if (size != 0 && size != item->size) {
149 				continue;
150 			}
151 		}
152 		// Is this register being asked?
153 		if (dbg->q_regs) {
154 			if (!r_list_empty (dbg->q_regs)) {
155 				RListIter *iterreg;
156 				RList *q_reg = dbg->q_regs;
157 				char *q_name;
158 				bool found = false;
159 				r_list_foreach (q_reg, iterreg, q_name) {
160 					if (!strcmp (item->name, q_name)) {
161 						found = true;
162 						break;
163 					}
164 				}
165 				if (!found) {
166 					continue;
167 				}
168 				r_list_delete (q_reg, iterreg);
169 			} else {
170 				// List is empty, all requested regs were taken, no need to go further
171 				goto beach;
172 			}
173 		}
174 		int regSize = item->size;
175 		if (regSize < 80) {
176 			value = r_reg_get_value (dbg->reg, item);
177 			r_reg_arena_swap (dbg->reg, false);
178 			diff = r_reg_get_value (dbg->reg, item);
179 			r_reg_arena_swap (dbg->reg, false);
180 			delta = value - diff;
181 			if (isJson) {
182 				pj_kn (pj, item->name, value);
183 			} else {
184 				if (pr && pr->wide_offsets && dbg->bits & R_SYS_BITS_64) {
185 					snprintf (strvalue, sizeof (strvalue),"0x%016"PFMT64x, value);
186 				} else {
187 					snprintf (strvalue, sizeof (strvalue),"0x%08"PFMT64x, value);
188 				}
189 			}
190 		} else {
191 			value = r_reg_get_value_big (dbg->reg, item, &valueBig);
192 			switch (regSize) {
193 				case 80:
194 					snprintf (strvalue, sizeof (strvalue), "0x%04x%016"PFMT64x"", valueBig.v80.High, valueBig.v80.Low);
195 					break;
196 				case 96:
197 					snprintf (strvalue, sizeof (strvalue), "0x%08x%016"PFMT64x"", valueBig.v96.High, valueBig.v96.Low);
198 					break;
199 				case 128:
200 					snprintf (strvalue, sizeof (strvalue), "0x%016"PFMT64x"%016"PFMT64x"", valueBig.v128.High, valueBig.v128.Low);
201 					break;
202 				case 256:
203 					snprintf (strvalue, sizeof (strvalue), "0x%016"PFMT64x"%016"PFMT64x"%016"PFMT64x"%016"PFMT64x"",
204 							valueBig.v256.High.High, valueBig.v256.High.Low, valueBig.v256.Low.High, valueBig.v256.Low.Low);
205 					break;
206 				default:
207 					snprintf (strvalue, sizeof (strvalue), "ERROR");
208 			}
209 			if (isJson) {
210 				pj_ks (pj, item->name, strvalue);
211 			}
212 			delta = 0; // TODO: calculate delta with big values.
213 		}
214 		itmidx++;
215 
216 		if (isJson) {
217 			continue;
218 		}
219 		switch (rad) {
220 			case '-':
221 				dbg->cb_printf ("f-%s\n", item->name);
222 				break;
223 			case 'R':
224 				dbg->cb_printf ("aer %s = %s\n", item->name, strvalue);
225 				break;
226 			case 1:
227 			case '*':
228 				dbg->cb_printf ("f %s %d %s\n", item->name, item->size / 8, strvalue);
229 				break;
230 			case '.':
231 				dbg->cb_printf ("dr %s=%s\n", item->name, strvalue);
232 				break;
233 			case '=':
234 				{
235 					int len, highlight = use_color && pr && pr->cur_enabled && itmidx == pr->cur;
236 					char whites[32], content[300];
237 					const char *a = "", *b = "";
238 					if (highlight) {
239 						a = Color_INVERT;
240 						b = Color_INVERT_RESET;
241 						dbg->creg = item->name;
242 					}
243 					strcpy (whites, kwhites);
244 					if (delta && use_color) {
245 						dbg->cb_printf ("%s", use_color);
246 					}
247 					snprintf (content, sizeof (content),
248 							fmt2, "", item->name, "", strvalue, "");
249 					len = colwidth - strlen (content);
250 					if (len < 0) {
251 						len = 0;
252 					}
253 					memset (whites, ' ', sizeof (whites));
254 					whites[len] = 0;
255 					dbg->cb_printf (fmt2, a, item->name, b, strvalue,
256 							((n+1)%cols)? whites: "\n");
257 					if (highlight) {
258 						dbg->cb_printf (Color_INVERT_RESET);
259 					}
260 					if (delta && use_color) {
261 						dbg->cb_printf (Color_RESET);
262 					}
263 				}
264 				break;
265 			case 'd':
266 			case 3:
267 				if (delta) {
268 					char woot[512];
269 					snprintf (woot, sizeof (woot),
270 							" was 0x%"PFMT64x" delta %d\n", diff, delta);
271 					dbg->cb_printf (fmt, item->name, strvalue, woot);
272 				}
273 				break;
274 			default:
275 				if (delta && use_color) {
276 					dbg->cb_printf ("%s", use_color);
277 					dbg->cb_printf (fmt, item->name, strvalue, Color_RESET"\n");
278 				} else {
279 					dbg->cb_printf (fmt, item->name, strvalue, "\n");
280 				}
281 				break;
282 		}
283 		n++;
284 	}
285 	if (rad == 1 || rad == '*') {
286 		dbg->cb_printf ("fs-\n");
287 	}
288 beach:
289 	if (isJson) {
290 		pj_end (pj);
291 	} else if (n > 0 && (rad == 2 || rad == '=') && ((n%cols))) {
292 		dbg->cb_printf ("\n");
293 	}
294 	return n != 0;
295 }
296 
r_debug_reg_set(struct r_debug_t * dbg,const char * name,ut64 num)297 R_API int r_debug_reg_set(struct r_debug_t *dbg, const char *name, ut64 num) {
298 	RRegItem *ri;
299 	int role = r_reg_get_name_idx (name);
300 	if (!dbg || !dbg->reg) {
301 		return false;
302 	}
303 	if (role != -1) {
304 		name = r_reg_get_name (dbg->reg, role);
305 	}
306 	ri = r_reg_get (dbg->reg, name, R_REG_TYPE_ALL);
307 	if (ri) {
308 		r_reg_set_value (dbg->reg, ri, num);
309 		r_debug_reg_sync (dbg, R_REG_TYPE_ALL, true);
310 	}
311 	return (ri != NULL);
312 }
313 
r_debug_reg_get(RDebug * dbg,const char * name)314 R_API ut64 r_debug_reg_get(RDebug *dbg, const char *name) {
315 	// ignores errors
316 	return r_debug_reg_get_err (dbg, name, NULL, NULL);
317 }
318 
r_debug_reg_get_err(RDebug * dbg,const char * name,int * err,utX * value)319 R_API ut64 r_debug_reg_get_err(RDebug *dbg, const char *name, int *err, utX *value) {
320 	RRegItem *ri = NULL;
321 	ut64 ret = 0LL;
322 	int role = r_reg_get_name_idx (name);
323 	const char *pname = name;
324 	if (err) {
325 		*err = 0;
326 	}
327 	if (!dbg || !dbg->reg) {
328 		if (err) {
329 			*err = 1;
330 		}
331 		return UT64_MAX;
332 	}
333 	if (role != -1) {
334 		name = r_reg_get_name (dbg->reg, role);
335 		if (!name || *name == '\0') {
336 			eprintf ("No debug register profile defined for '%s'.\n", pname);
337 			if (err) {
338 				*err = 1;
339 			}
340 			return UT64_MAX;
341 		}
342 	}
343 	ri = r_reg_get (dbg->reg, name, R_REG_TYPE_ALL);
344 	if (ri) {
345 		r_debug_reg_sync (dbg, R_REG_TYPE_ALL, false);
346 		if (value && ri->size > 64) {
347 			if (err) {
348 				*err = ri->size;
349 			}
350 			ret = r_reg_get_value_big (dbg->reg, ri, value);
351 		} else {
352 		    ret = r_reg_get_value (dbg->reg, ri);
353 		}
354 	} else {
355 		if (err) {
356 			*err = 1;
357 		}
358 	}
359 	return ret;
360 }
361 
362 // XXX: dup for get_Err!
r_debug_num_callback(RNum * userptr,const char * str,int * ok)363 R_API ut64 r_debug_num_callback(RNum *userptr, const char *str, int *ok) {
364 	RDebug *dbg = (RDebug *)userptr;
365 	// resolve using regnu
366 	return r_debug_reg_get_err (dbg, str, ok, NULL);
367 }
368