1 /* radare - LGPL - Copyright 2009-2020 - pancake */
2
3 #include <r_reg.h>
4 #include <r_util.h>
5
6 R_LIB_VERSION (r_reg);
7
8 static const char *types[R_REG_TYPE_LAST + 1] = {
9 "gpr", "drx", "fpu", "mmx", "xmm", "ymm", "flg", "seg", NULL
10 };
11
12 // Take the 32bits name of a register, and return the 64 bit name of it.
13 // If there is no equivalent 64 bit register return NULL.
14 // SLOW
r_reg_32_to_64(RReg * reg,const char * rreg32)15 R_API const char *r_reg_32_to_64(RReg *reg, const char *rreg32) {
16 int i, j = -1;
17 RListIter *iter;
18 RRegItem *item;
19 for (i = 0; i < R_REG_TYPE_LAST; i++) {
20 r_list_foreach (reg->regset[i].regs, iter, item) {
21 if (item->size == 32 && !r_str_casecmp (rreg32, item->name)) {
22 j = item->offset;
23 break;
24 }
25 }
26 }
27 if (j != -1) {
28 for (i = 0; i < R_REG_TYPE_LAST; i++) {
29 r_list_foreach (reg->regset[i].regs, iter, item) {
30 if (item->offset == j && item->size == 64) {
31 return item->name;
32 }
33 }
34 }
35 }
36 return NULL;
37 }
38
39 // Take the 64 bits name of a register, and return the 32 bit name of it.
40 // If there is no equivalent 32 bit register return NULL.
41 // SLOW
r_reg_64_to_32(RReg * reg,const char * rreg64)42 R_API const char *r_reg_64_to_32(RReg *reg, const char *rreg64) {
43 int i, j = -1;
44 RListIter *iter;
45 RRegItem *item;
46 for (i = 0; i < R_REG_TYPE_LAST; i++) {
47 r_list_foreach (reg->regset[i].regs, iter, item) {
48 if (item->size == 64 && !r_str_casecmp (rreg64, item->name)) {
49 j = item->offset;
50 break;
51 }
52 }
53 }
54 if (j != -1) {
55 for (i = 0; i < R_REG_TYPE_LAST; i++) {
56 r_list_foreach (reg->regset[i].regs, iter, item) {
57 if (item->offset == j && item->size == 32) {
58 return item->name;
59 }
60 }
61 }
62 }
63 return NULL;
64 }
65
r_reg_get_type(int idx)66 R_API const char *r_reg_get_type(int idx) {
67 return (idx >= 0 && idx < R_REG_TYPE_LAST) ? types[idx] : NULL;
68 }
69
r_reg_get_name_by_type(RReg * reg,const char * alias_name)70 R_API const char *r_reg_get_name_by_type(RReg *reg, const char *alias_name) {
71 const int n = r_reg_get_name_idx (alias_name);
72 return (n != -1)? r_reg_get_name (reg, n): NULL;
73 }
74
r_reg_type_by_name(const char * str)75 R_API int r_reg_type_by_name(const char *str) {
76 r_return_val_if_fail (str, -1);
77 int i;
78 for (i = 0; i < R_REG_TYPE_LAST && types[i]; i++) {
79 if (!strcmp (types[i], str)) {
80 return i;
81 }
82 }
83 if (!strcmp (str, "all")) {
84 return R_REG_TYPE_ALL;
85 }
86 return -1;
87 }
88
r_reg_item_free(RRegItem * item)89 R_API void r_reg_item_free(RRegItem *item) {
90 free (item->name);
91 free (item->flags);
92 free (item);
93 }
94
r_reg_get_name_idx(const char * type)95 R_API int r_reg_get_name_idx(const char *type) {
96 r_return_val_if_fail (type, -1);
97 if (type[0] && type[1] && !type[2])
98 switch (*type | (type[1] << 8)) {
99 /* flags */
100 case 'Z' + ('F' << 8): return R_REG_NAME_ZF;
101 case 'S' + ('F' << 8): return R_REG_NAME_SF;
102 case 'C' + ('F' << 8): return R_REG_NAME_CF;
103 case 'O' + ('F' << 8): return R_REG_NAME_OF;
104 /* gpr */
105 case 'P' + ('C' << 8): return R_REG_NAME_PC;
106 case 'S' + ('R' << 8): return R_REG_NAME_SR;
107 case 'L' + ('R' << 8): return R_REG_NAME_LR;
108 case 'S' + ('P' << 8): return R_REG_NAME_SP;
109 case 'B' + ('P' << 8): return R_REG_NAME_BP;
110 case 'S' + ('N' << 8): return R_REG_NAME_SN;
111 /* args */
112 case 'A' + ('0' << 8): return R_REG_NAME_A0;
113 case 'A' + ('1' << 8): return R_REG_NAME_A1;
114 case 'A' + ('2' << 8): return R_REG_NAME_A2;
115 case 'A' + ('3' << 8): return R_REG_NAME_A3;
116 case 'A' + ('4' << 8): return R_REG_NAME_A4;
117 case 'A' + ('5' << 8): return R_REG_NAME_A5;
118 case 'A' + ('6' << 8): return R_REG_NAME_A6;
119 case 'A' + ('7' << 8): return R_REG_NAME_A7;
120 case 'A' + ('8' << 8): return R_REG_NAME_A8;
121 case 'A' + ('9' << 8): return R_REG_NAME_A9;
122 /* return values */
123 case 'R' + ('0' << 8): return R_REG_NAME_R0;
124 case 'R' + ('1' << 8): return R_REG_NAME_R1;
125 case 'R' + ('2' << 8): return R_REG_NAME_R2;
126 case 'R' + ('3' << 8): return R_REG_NAME_R3;
127 }
128 return -1;
129 }
130
r_reg_set_name(RReg * reg,int role,const char * name)131 R_API bool r_reg_set_name(RReg *reg, int role, const char *name) {
132 r_return_val_if_fail (reg && name, false);
133 if (role >= 0 && role < R_REG_NAME_LAST) {
134 reg->name[role] = r_str_dup (reg->name[role], name);
135 return true;
136 }
137 return false;
138 }
139
r_reg_get_name(RReg * reg,int role)140 R_API const char *r_reg_get_name(RReg *reg, int role) {
141 if (reg && role >= 0 && role < R_REG_NAME_LAST) {
142 return reg->name[role];
143 }
144 return NULL;
145 }
146
147 static const char *roles[R_REG_NAME_LAST + 1] = {
148 "PC", "SP", "SR", "BP", "LR",
149 "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9",
150 "R0", "R1", "R2", "R3",
151 "ZF", "SF", "CF", "OF",
152 "SN",
153 NULL
154 };
155
r_reg_get_role(int role)156 R_API const char *r_reg_get_role(int role) {
157 if (role >= 0 && role < R_REG_NAME_LAST) {
158 return roles[role];
159 }
160 return NULL;
161 }
162
r_reg_free_internal(RReg * reg,bool init)163 R_API void r_reg_free_internal(RReg *reg, bool init) {
164 r_return_if_fail (reg);
165 ut32 i;
166
167 r_list_free (reg->roregs);
168 reg->roregs = NULL;
169 R_FREE (reg->reg_profile_str);
170 R_FREE (reg->reg_profile_cmt);
171
172 for (i = 0; i < R_REG_NAME_LAST; i++) {
173 if (reg->name[i]) {
174 R_FREE (reg->name[i]);
175 }
176 }
177 for (i = 0; i < R_REG_TYPE_LAST; i++) {
178 ht_pp_free (reg->regset[i].ht_regs);
179 reg->regset[i].ht_regs = NULL;
180 if (!reg->regset[i].pool) {
181 continue;
182 }
183 if (init) {
184 r_list_free (reg->regset[i].regs);
185 reg->regset[i].regs = r_list_newf ((RListFree)r_reg_item_free);
186 } else {
187 r_list_free (reg->regset[i].regs);
188 reg->regset[i].regs = NULL;
189 // Ensure arena is freed and its registered in the pool
190 if (!r_list_delete_data (reg->regset[i].pool, reg->regset[i].arena)) {
191 r_reg_arena_free (reg->regset[i].arena);
192 }
193 reg->regset[i].arena = NULL;
194 r_list_free (reg->regset[i].pool);
195 reg->regset[i].pool = NULL;
196 }
197 }
198 if (!init) {
199 r_list_free (reg->allregs);
200 reg->allregs = NULL;
201 }
202 reg->size = 0;
203 }
204
regcmp(RRegItem * a,RRegItem * b)205 static int regcmp(RRegItem *a, RRegItem *b) {
206 int offa = (a->offset * 16) + a->size;
207 int offb = (b->offset * 16) + b->size;
208 return (offa > offb) - (offa < offb);
209 }
210
r_reg_reindex(RReg * reg)211 R_API void r_reg_reindex(RReg *reg) {
212 int i, index;
213 RListIter *iter;
214 RRegItem *r;
215 RList *all = r_list_newf (NULL);
216 for (i = 0; i < R_REG_TYPE_LAST; i++) {
217 r_list_foreach (reg->regset[i].regs, iter, r) {
218 r_list_append (all, r);
219 }
220 }
221 r_list_sort (all, (RListComparator)regcmp);
222 index = 0;
223 r_list_foreach (all, iter, r) {
224 r->index = index++;
225 }
226 r_list_free (reg->allregs);
227 reg->allregs = all;
228 }
229
r_reg_index_get(RReg * reg,int idx)230 R_API RRegItem *r_reg_index_get(RReg *reg, int idx) {
231 RRegItem *r;
232 RListIter *iter;
233 if (idx < 0) {
234 return NULL;
235 }
236 if (!reg->allregs) {
237 r_reg_reindex (reg);
238 }
239 r_list_foreach (reg->allregs, iter, r) {
240 if (r->index == idx) {
241 return r;
242 }
243 }
244 return NULL;
245 }
246
r_reg_free(RReg * reg)247 R_API void r_reg_free(RReg *reg) {
248 if (reg) {
249 r_reg_free_internal (reg, false);
250 free (reg);
251 }
252 }
253
r_reg_new(void)254 R_API RReg *r_reg_new(void) {
255 RRegArena *arena;
256 RReg *reg = R_NEW0 (RReg);
257 int i;
258 if (!reg) {
259 return NULL;
260 }
261 for (i = 0; i < R_REG_TYPE_LAST; i++) {
262 arena = r_reg_arena_new (0);
263 if (!arena) {
264 free (reg);
265 return NULL;
266 }
267 reg->regset[i].pool = r_list_newf ((RListFree)r_reg_arena_free);
268 reg->regset[i].regs = r_list_newf ((RListFree)r_reg_item_free);
269 r_list_push (reg->regset[i].pool, arena);
270 reg->regset[i].arena = arena;
271 }
272 r_reg_arena_push (reg);
273 for (i = 0; i < R_REG_TYPE_LAST; i++) {
274 reg->regset[i].cur = r_list_tail (reg->regset[i].pool);
275 }
276 return reg;
277 }
278
r_reg_is_readonly(RReg * reg,RRegItem * item)279 R_API bool r_reg_is_readonly(RReg *reg, RRegItem *item) {
280 const char *name;
281 RListIter *iter;
282 if (!reg->roregs) {
283 return false;
284 }
285 // XXX O(n)
286 r_list_foreach (reg->roregs, iter, name) {
287 if (!strcmp (item->name, name)) {
288 return true;
289 }
290 }
291 return false;
292 }
293
r_reg_setv(RReg * reg,const char * name,ut64 val)294 R_API ut64 r_reg_setv(RReg *reg, const char *name, ut64 val) {
295 r_return_val_if_fail (reg && name, UT64_MAX);
296 RRegItem *ri = r_reg_get (reg, name, -1);
297 return ri? r_reg_set_value (reg, ri, val): UT64_MAX;
298 }
299
r_reg_getv(RReg * reg,const char * name)300 R_API ut64 r_reg_getv(RReg *reg, const char *name) {
301 r_return_val_if_fail (reg && name, UT64_MAX);
302 RRegItem *ri = r_reg_get (reg, name, -1);
303 return ri? r_reg_get_value (reg, ri): UT64_MAX;
304 }
305
r_reg_get(RReg * reg,const char * name,int type)306 R_API RRegItem *r_reg_get(RReg *reg, const char *name, int type) {
307 int i, e;
308 r_return_val_if_fail (reg && name, NULL);
309 //TODO: define flag register as R_REG_TYPE_FLG
310 if (type == R_REG_TYPE_FLG) {
311 type = R_REG_TYPE_GPR;
312 }
313 if (type == -1) {
314 i = 0;
315 e = R_REG_TYPE_LAST;
316 int alias = r_reg_get_name_idx (name);
317 if (alias != -1) {
318 const char *nname = r_reg_get_name (reg, alias);
319 if (nname) {
320 name = nname;
321 }
322 }
323 } else {
324 i = type;
325 e = type + 1;
326 }
327 for (; i < e; i++) {
328 HtPP *pp = reg->regset[i].ht_regs;
329 if (pp) {
330 bool found = false;
331 RRegItem *item = ht_pp_find (pp, name, &found);
332 if (found) {
333 return item;
334 }
335 }
336 }
337 return NULL;
338 }
339
r_reg_get_list(RReg * reg,int type)340 R_API RList *r_reg_get_list(RReg *reg, int type) {
341 if (type == R_REG_TYPE_ALL) {
342 return reg->allregs;
343 }
344
345 RList *regs;
346 int i, mask;
347 if (type < 0 || type > (R_REG_TYPE_LAST - 1)) {
348 return NULL;
349 }
350
351 regs = reg->regset[type].regs;
352 if (r_list_length (regs) == 0) {
353 mask = ((int)1 << type);
354 for (i = 0; i < R_REG_TYPE_LAST; i++) {
355 if (reg->regset[i].maskregstype & mask) {
356 regs = reg->regset[i].regs;
357 }
358 }
359 }
360
361 return regs;
362 }
363
364 // TODO regsize is in bits, delta in bytes, maybe we should standarize this..
r_reg_get_at(RReg * reg,int type,int regsize,int delta)365 R_API RRegItem *r_reg_get_at(RReg *reg, int type, int regsize, int delta) {
366 r_return_val_if_fail (reg, NULL);
367 RList *list = r_reg_get_list (reg, type);
368 RRegItem *ri;
369 RListIter *iter;
370 r_list_foreach (list, iter, ri) {
371 if (ri->size == regsize) {
372 if (BITS2BYTES (ri->offset) == delta) {
373 return ri;
374 }
375 }
376 }
377 return NULL;
378 }
379
380 /* return the next register in the current regset that differs from */
r_reg_next_diff(RReg * reg,int type,const ut8 * buf,int buflen,RRegItem * prev_ri,int regsize)381 R_API RRegItem *r_reg_next_diff(RReg *reg, int type, const ut8 *buf, int buflen, RRegItem *prev_ri, int regsize) {
382 r_return_val_if_fail (reg && buf, NULL);
383 if (type < 0 || type > (R_REG_TYPE_LAST - 1)) {
384 return NULL;
385 }
386 RRegArena *arena = reg->regset[type].arena;
387 int prev_offset = prev_ri ? (prev_ri->offset / 8) + (prev_ri->size / 8) : 0;
388 RList *list = reg->regset[type].regs;
389 RRegItem *ri;
390 RListIter *iter;
391 int offset;
392 r_list_foreach (list, iter, ri) {
393 offset = ri->offset / 8;
394 if (offset > prev_offset) {
395 if (memcmp (arena->bytes + offset, buf + offset, ri->size / 8)) {
396 return ri;
397 }
398 }
399 }
400 return NULL;
401 }
402
r_reg_regset_get(RReg * r,int type)403 R_API RRegSet *r_reg_regset_get(RReg *r, int type) {
404 r_return_val_if_fail (r, NULL);
405 if (type < 0 || type >= R_REG_TYPE_LAST) {
406 return NULL;
407 }
408 RRegSet *rs = &r->regset[type];
409 return rs->arena ? rs : NULL;
410 }
411