1 /* radare - LGPL - Copyright 2009-2019 - pancake */
2
3 #include <r_reg.h>
4 #include <r_util.h>
5
6 typedef ut32 ut27;
r_read_me27(const ut8 * buf,int boff)7 static ut27 r_read_me27(const ut8 *buf, int boff) {
8 ut27 ret = 0;
9 r_mem_copybits_delta ((ut8 *)&ret, 18, buf, boff, 9);
10 r_mem_copybits_delta ((ut8 *)&ret, 9, buf, boff + 9, 9);
11 r_mem_copybits_delta ((ut8 *)&ret, 0, buf, boff + 18, 9);
12 return ret;
13 }
14
r_reg_get_value_big(RReg * reg,RRegItem * item,utX * val)15 R_API ut64 r_reg_get_value_big(RReg *reg, RRegItem *item, utX *val) {
16 r_return_val_if_fail (reg && item, 0);
17
18 ut64 ret = 0LL;
19 int off = BITS2BYTES (item->offset);
20 RRegSet *regset = ®->regset[item->arena];
21 if (!regset->arena) {
22 return 0LL;
23 }
24 switch (item->size) {
25 case 80: // word + qword
26 if (regset->arena->bytes && (off + 10 <= regset->arena->size)) {
27 val->v80.Low = *((ut64 *)(regset->arena->bytes + off));
28 val->v80.High = *((ut16 *)(regset->arena->bytes + off + 8));
29 } else {
30 eprintf ("r_reg_get_value: null or oob arena for current regset\n");
31 }
32 ret = val->v80.Low;
33 break;
34 case 96: // dword + qword
35 if (regset->arena->bytes && (off + 12 <= regset->arena->size)) {
36 val->v96.Low = *((ut64 *)(regset->arena->bytes + off));
37 val->v96.High = *((ut32 *)(regset->arena->bytes + off + 8));
38 } else {
39 eprintf ("r_reg_get_value: null or oob arena for current regset\n");
40 }
41 ret = val->v96.Low;
42 break;
43 case 128: // qword + qword
44 if (regset->arena->bytes && (off + 16 <= regset->arena->size)) {
45 val->v128.Low = *((ut64 *)(regset->arena->bytes + off));
46 val->v128.High = *((ut64 *)(regset->arena->bytes + off + 8));
47 } else {
48 eprintf ("r_reg_get_value: null or oob arena for current regset\n");
49 }
50 ret = val->v128.Low;
51 break;
52 case 256:// qword + qword + qword + qword
53 if (regset->arena->bytes && (off + 32 <= regset->arena->size)) {
54 val->v256.Low.Low = *((ut64 *)(regset->arena->bytes + off));
55 val->v256.Low.High = *((ut64 *)(regset->arena->bytes + off + 8));
56 val->v256.High.Low = *((ut64 *)(regset->arena->bytes + off + 16));
57 val->v256.High.High = *((ut64 *)(regset->arena->bytes + off + 24));
58 } else {
59 eprintf ("r_reg_get_value: null or oob arena for current regset\n");
60 }
61 ret = val->v256.Low.Low;
62 break;
63 default:
64 eprintf ("r_reg_get_value_big: Bit size %d not supported\n", item->size);
65 break;
66 }
67 return ret;
68 }
69
r_reg_get_value(RReg * reg,RRegItem * item)70 R_API ut64 r_reg_get_value(RReg *reg, RRegItem *item) {
71 r_return_val_if_fail (reg && item, 0);
72 if (!reg || !item || item->offset == -1) {
73 return 0LL;
74 }
75 int off = BITS2BYTES (item->offset);
76 RRegSet *regset = ®->regset[item->arena];
77 if (!regset->arena) {
78 return 0LL;
79 }
80 switch (item->size) {
81 case 1: {
82 int offset = item->offset / 8;
83 if (offset >= regset->arena->size) {
84 break;
85 }
86 return (regset->arena->bytes[offset] &
87 (1 << (item->offset % 8)))
88 ? 1
89 : 0;
90 } break;
91 case 4:
92 if (regset->arena->size - off - 1 >= 0) {
93 return (r_read_at_ble8 (regset->arena->bytes, off)) & 0xF;
94 }
95 break;
96 case 8:
97 if (regset->arena->size - off - 1 >= 0) {
98 return r_read_at_ble8 (regset->arena->bytes, off);
99 }
100 break;
101 case 16:
102 if (regset->arena->size - off - 2 >= 0) {
103 return r_read_ble16 (regset->arena->bytes + off, reg->big_endian);
104 }
105 break;
106 case 27:
107 if (off + 3 < regset->arena->size) {
108 return r_read_me27 (regset->arena->bytes + off, 0);
109 }
110 break;
111 case 32:
112 if (off + 4 <= regset->arena->size) {
113 return r_read_ble32 (regset->arena->bytes + off, reg->big_endian);
114 }
115 eprintf ("r_reg_get_value: 32bit oob read %d\n", off);
116 break;
117 case 64:
118 if (regset->arena && regset->arena->bytes && (off + 8 <= regset->arena->size)) {
119 return r_read_ble64 (regset->arena->bytes + off, reg->big_endian);
120 }
121 //eprintf ("r_reg_get_value: null or oob arena for current regset\n");
122 break;
123 case 80: // long double
124 case 96: // long floating value
125 // FIXME: It is a precision loss, please implement me properly!
126 return (ut64)r_reg_get_longdouble (reg, item);
127 case 128:
128 case 256:
129 // XXX 128 & 256 bit
130 return (ut64)r_reg_get_longdouble (reg, item);
131 default:
132 eprintf ("r_reg_get_value: Bit size %d not supported\n", item->size);
133 break;
134 }
135 return 0LL;
136 }
137
r_reg_get_value_by_role(RReg * reg,RRegisterId role)138 R_API ut64 r_reg_get_value_by_role(RReg *reg, RRegisterId role) {
139 // TODO use mapping from RRegisterId to RRegItem (via RRegSet)
140 return r_reg_get_value (reg, r_reg_get (reg, r_reg_get_name (reg, role), -1));
141 }
142
r_reg_set_value(RReg * reg,RRegItem * item,ut64 value)143 R_API bool r_reg_set_value(RReg *reg, RRegItem *item, ut64 value) {
144 ut8 bytes[12];
145 ut8 *src = bytes;
146 r_return_val_if_fail (reg && item, false);
147
148 if (r_reg_is_readonly (reg, item)) {
149 return true;
150 }
151 if (item->offset < 0) {
152 return true;
153 }
154 RRegArena *arena = reg->regset[item->arena].arena;
155 if (!arena) {
156 return false;
157 }
158 switch (item->size) {
159 case 80:
160 case 96: // long floating value
161 r_reg_set_longdouble (reg, item, (long double)value);
162 break;
163 case 64:
164 if (reg->big_endian) {
165 r_write_be64 (src, value);
166 } else {
167 r_write_le64 (src, value);
168 }
169 break;
170 case 32:
171 if (reg->big_endian) {
172 r_write_be32 (src, value);
173 } else {
174 r_write_le32 (src, value);
175 }
176 break;
177 case 16:
178 if (reg->big_endian) {
179 r_write_be16 (src, value);
180 } else {
181 r_write_le16 (src, value);
182 }
183 break;
184 case 8:
185 r_write_ble8 (src, (ut8) (value & UT8_MAX));
186 break;
187 case 1:
188 if (value) {
189 ut8 *buf = arena->bytes + (item->offset / 8);
190 int bit = (item->offset % 8);
191 ut8 mask = (1 << bit);
192 buf[0] = (buf[0] & (0xff ^ mask)) | mask;
193 } else {
194 int idx = item->offset / 8;
195 if (idx + item->size > arena->size) {
196 eprintf ("RRegSetOverflow %d vs %d\n", idx + item->size, arena->size);
197 return false;
198 }
199 ut8 *buf = arena->bytes + idx;
200 int bit = item->offset % 8;
201 ut8 mask = 0xff ^ (1 << bit);
202 buf[0] = (buf[0] & mask) | 0;
203 }
204 return true;
205 case 128:
206 case 256:
207 // XXX 128 & 256 bit
208 return false; // (ut64)r_reg_get_longdouble (reg, item);
209 default:
210 eprintf ("r_reg_set_value: Bit size %d not supported\n", item->size);
211 return false;
212 }
213 const bool fits_in_arena = (arena->size - BITS2BYTES (item->offset) - BITS2BYTES (item->size)) >= 0;
214 if (src && fits_in_arena) {
215 r_mem_copybits (reg->regset[item->arena].arena->bytes +
216 BITS2BYTES (item->offset),
217 src, item->size);
218 return true;
219 }
220 eprintf ("r_reg_set_value: Cannot set %s to 0x%" PFMT64x "\n", item->name, value);
221 return false;
222 }
223
r_reg_set_value_by_role(RReg * reg,RRegisterId role,ut64 val)224 R_API bool r_reg_set_value_by_role(RReg *reg, RRegisterId role, ut64 val) {
225 // TODO use mapping from RRegisterId to RRegItem (via RRegSet)
226 RRegItem *r = r_reg_get (reg, r_reg_get_name (reg, role), -1);
227 return r_reg_set_value (reg, r, val);
228 }
229
r_reg_set_bvalue(RReg * reg,RRegItem * item,const char * str)230 R_API ut64 r_reg_set_bvalue(RReg *reg, RRegItem *item, const char *str) {
231 ut64 num = UT64_MAX;
232 if (item && item->flags && str) {
233 num = r_str_bits_from_string (str, item->flags);
234 if (num == UT64_MAX) {
235 num = r_num_math (NULL, str);
236 }
237 r_reg_set_value (reg, item, num);
238 }
239 return num;
240 }
241
r_reg_get_bvalue(RReg * reg,RRegItem * item)242 R_API R_HEAP char *r_reg_get_bvalue(RReg *reg, RRegItem *item) {
243 char *out = NULL;
244 if (reg && item && item->flags) {
245 out = malloc (strlen (item->flags) + 1);
246 if (out) {
247 ut64 num = r_reg_get_value (reg, item);
248 r_str_bits (out, (ut8 *)&num,
249 strlen (item->flags) * 8, item->flags);
250 }
251 }
252 return out;
253 }
254
255 /* packed registers */
256 // packbits can be 8, 16, 32 or 64
257 // result value is always casted into ut64
258 // TODO: support packbits=128 for xmm registers
r_reg_get_pack(RReg * reg,RRegItem * item,int packidx,int packbits)259 R_API ut64 r_reg_get_pack(RReg *reg, RRegItem *item, int packidx, int packbits) {
260 r_return_val_if_fail (reg && item, 0LL);
261
262 if (packbits < 1) {
263 packbits = item->packed_size;
264 }
265 if (packbits > 64) {
266 packbits = 64;
267 eprintf ("Does not support pack bits > 64\n");
268 }
269
270 ut64 ret = 0LL;
271 const int packbytes = packbits / 8;
272 const int packmod = packbits % 8;
273 if (packmod) {
274 eprintf ("Invalid bit size for packet register\n");
275 return 0LL;
276 }
277 if ((packidx + 1) * packbits > item->size) {
278 eprintf ("Packed index is beyond the register size\n");
279 return 0LL;
280 }
281 RRegSet *regset = ®->regset[item->arena];
282 if (!regset->arena) {
283 return 0LL;
284 }
285 int off = BITS2BYTES (item->offset);
286 off += (packidx * packbytes);
287 if (regset->arena->size - off - 1 >= 0) {
288 int i;
289 for (i = packbytes - 1; i >= 0; i--) {
290 ret = (ret << 8) | regset->arena->bytes[off + i];
291 }
292 }
293 return ret;
294 }
295
296 // TODO: support packbits=128 for xmm registers
r_reg_set_pack(RReg * reg,RRegItem * item,int packidx,int packbits,ut64 val)297 R_API int r_reg_set_pack(RReg *reg, RRegItem *item, int packidx, int packbits, ut64 val) {
298 r_return_val_if_fail (reg && reg->regset->arena && item, false);
299
300 if (packbits < 1) {
301 packbits = item->packed_size;
302 }
303 if (packbits > 64) {
304 packbits = 64;
305 eprintf ("Does not support pack bits > 64\n");
306 }
307
308 int packbytes = packbits / 8;
309 if ((packidx + 1) * packbits > item->size) {
310 eprintf ("Packed index is beyond the register size\n");
311 return false;
312 }
313 int off = BITS2BYTES (item->offset);
314 off += (packidx * packbytes);
315 if (reg->regset[item->arena].arena->size - BITS2BYTES (off) - BITS2BYTES (packbytes) >= 0) {
316 ut8 *dst = reg->regset[item->arena].arena->bytes + off;
317 int i;
318 for (i = 0; i < packbytes; i++, val >>= 8) {
319 dst[i] = val & 0xff;
320 }
321 return true;
322 }
323 eprintf ("r_reg_set_value: Cannot set %s to 0x%" PFMT64x "\n", item->name, val);
324 return false;
325 }
326