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