Rizin
unix-like reverse engineering framework and cli tools
rvalue.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 Florian Märkl <info@florianmaerkl.de>
2 // SPDX-FileCopyrightText: 2009-2019 pancake <pancake@nopcode.org>
3 // SPDX-License-Identifier: LGPL-3.0-only
4 
5 #include <rz_reg.h>
6 #include <rz_util.h>
7 
12  rz_return_val_if_fail(reg && item, NULL);
13  RzRegSet *regset = &reg->regset[item->arena];
14  if (reg->big_endian) {
15  return rz_bv_new_from_bytes_be(regset->arena->bytes, item->offset, item->size);
16  } else {
17  return rz_bv_new_from_bytes_le(regset->arena->bytes, item->offset, item->size);
18  }
19 }
20 
27  rz_return_val_if_fail(reg && item && bv, false);
28  if (rz_bv_len(bv) != item->size) {
29  return false;
30  }
31  if (item->offset % 8) {
32  // TODO: this needs a bit offset arg in rz_bv_set_to_bytes_be()
33  if (item->size == 1) {
34  // workaround for flags edge-case while the offset mentioned above is not implemented yet
36  return true;
37  }
38  RZ_LOG_ERROR("rz_reg_set_bv() for non-byte-aligned regs not supported yet.\n");
39  return false;
40  }
41  RzRegSet *regset = &reg->regset[item->arena];
42  int boff = item->offset / 8;
43  if (reg->big_endian) {
44  rz_bv_set_to_bytes_be(bv, regset->arena->bytes + boff);
45  } else {
46  rz_bv_set_to_bytes_le(bv, regset->arena->bytes + boff);
47  }
48  return true;
49 }
50 
51 typedef ut32 ut27;
52 static ut27 rz_read_me27(const ut8 *buf, int boff) {
53  ut27 ret = 0;
54  rz_mem_copybits_delta((ut8 *)&ret, 18, buf, boff, 9);
55  rz_mem_copybits_delta((ut8 *)&ret, 9, buf, boff + 9, 9);
56  rz_mem_copybits_delta((ut8 *)&ret, 0, buf, boff + 18, 9);
57  return ret;
58 }
59 
61  rz_return_val_if_fail(reg && item, 0);
62 
63  ut64 ret = 0LL;
64  int off = BITS2BYTES(item->offset);
65  RzRegSet *regset = &reg->regset[item->arena];
66  if (!regset->arena) {
67  return 0LL;
68  }
69  switch (item->size) {
70  case 80: // word + qword
71  if (regset->arena->bytes && (off + 10 <= regset->arena->size)) {
72  val->v80.Low = *((ut64 *)(regset->arena->bytes + off));
73  val->v80.High = *((ut16 *)(regset->arena->bytes + off + 8));
74  } else {
75  eprintf("rz_reg_get_value: null or oob arena for current regset\n");
76  }
77  ret = val->v80.Low;
78  break;
79  case 96: // dword + qword
80  if (regset->arena->bytes && (off + 12 <= regset->arena->size)) {
81  val->v96.Low = *((ut64 *)(regset->arena->bytes + off));
82  val->v96.High = *((ut32 *)(regset->arena->bytes + off + 8));
83  } else {
84  eprintf("rz_reg_get_value: null or oob arena for current regset\n");
85  }
86  ret = val->v96.Low;
87  break;
88  case 128: // qword + qword
89  if (regset->arena->bytes && (off + 16 <= regset->arena->size)) {
90  val->v128.Low = *((ut64 *)(regset->arena->bytes + off));
91  val->v128.High = *((ut64 *)(regset->arena->bytes + off + 8));
92  } else {
93  eprintf("rz_reg_get_value: null or oob arena for current regset\n");
94  }
95  ret = val->v128.Low;
96  break;
97  case 256: // qword + qword + qword + qword
98  if (regset->arena->bytes && (off + 32 <= regset->arena->size)) {
99  val->v256.Low.Low = *((ut64 *)(regset->arena->bytes + off));
100  val->v256.Low.High = *((ut64 *)(regset->arena->bytes + off + 8));
101  val->v256.High.Low = *((ut64 *)(regset->arena->bytes + off + 16));
102  val->v256.High.High = *((ut64 *)(regset->arena->bytes + off + 24));
103  } else {
104  eprintf("rz_reg_get_value: null or oob arena for current regset\n");
105  }
106  ret = val->v256.Low.Low;
107  break;
108  default:
109  break;
110  }
111  return ret;
112 }
113 
115  rz_return_val_if_fail(reg && item, 0);
116  if (!reg || !item || item->offset == -1) {
117  return 0LL;
118  }
119  int off = BITS2BYTES(item->offset);
120  RzRegSet *regset = &reg->regset[item->arena];
121  if (!regset->arena) {
122  return 0LL;
123  }
124  switch (item->size) {
125  case 1: {
126  int offset = item->offset / 8;
127  if (offset >= regset->arena->size) {
128  break;
129  }
130  return (regset->arena->bytes[offset] &
131  (1 << (item->offset % 8)))
132  ? 1
133  : 0;
134  } break;
135  case 4:
136  if (regset->arena->size - off - 1 >= 0) {
137  return (rz_read_at_ble8(regset->arena->bytes, off)) & 0xF;
138  }
139  break;
140  case 8:
141  if (regset->arena->size - off - 1 >= 0) {
142  return rz_read_at_ble8(regset->arena->bytes, off);
143  }
144  break;
145  case 16:
146  if (regset->arena->size - off - 2 >= 0) {
147  return rz_read_ble16(regset->arena->bytes + off, reg->big_endian);
148  }
149  break;
150  case 27:
151  if (off + 3 < regset->arena->size) {
152  return rz_read_me27(regset->arena->bytes + off, 0);
153  }
154  break;
155  case 32:
156  if (off + 4 <= regset->arena->size) {
157  return rz_read_ble32(regset->arena->bytes + off, reg->big_endian);
158  }
159  eprintf("rz_reg_get_value: 32bit oob read %d\n", off);
160  break;
161  case 64:
162  if (regset->arena && regset->arena->bytes && (off + 8 <= regset->arena->size)) {
163  return rz_read_ble64(regset->arena->bytes + off, reg->big_endian);
164  }
165  // eprintf ("rz_reg_get_value: null or oob arena for current regset\n");
166  break;
167  case 80: // long double
168  case 96: // long floating value
169  // FIXME: It is a precision loss, please implement me properly!
170  return (ut64)rz_reg_get_longdouble(reg, item);
171  case 128:
172  case 256:
173  // XXX 128 & 256 bit
174  return (ut64)rz_reg_get_longdouble(reg, item);
175  default:
176  break;
177  }
178  return 0LL;
179 }
180 
182  // TODO use mapping from RzRegisterId to RzRegItem (via RzRegSet)
183  return rz_reg_get_value(reg, rz_reg_get(reg, rz_reg_get_name(reg, role), -1));
184 }
185 
187  ut8 bytes[12];
188  ut8 *src = bytes;
189  bool unset_src = false;
190  rz_return_val_if_fail(reg && item, false);
191 
192  if (rz_reg_is_readonly(reg, item)) {
193  return true;
194  }
195  if (item->offset < 0) {
196  return true;
197  }
198  RzRegArena *arena = reg->regset[item->arena].arena;
199  if (!arena) {
200  return false;
201  }
202  switch (item->size) {
203  case 80:
204  case 96: // long floating value
205  rz_reg_set_longdouble(reg, item, (long double)value);
206  unset_src = true;
207  break;
208  case 64:
209  if (reg->big_endian) {
211  } else {
213  }
214  break;
215  case 32:
216  if (reg->big_endian) {
218  } else {
220  }
221  break;
222  case 16:
223  if (reg->big_endian) {
225  } else {
227  }
228  break;
229  case 8:
231  break;
232  case 1:
233  if (value) {
234  ut8 *buf = arena->bytes + (item->offset / 8);
235  int bit = (item->offset % 8);
236  ut8 mask = (1 << bit);
237  buf[0] = (buf[0] & (0xff ^ mask)) | mask;
238  } else {
239  int idx = item->offset / 8;
240  if (idx + item->size > arena->size) {
241  eprintf("RzRegSetOverflow %d vs %d\n", idx + item->size, arena->size);
242  return false;
243  }
244  ut8 *buf = arena->bytes + idx;
245  int bit = item->offset % 8;
246  ut8 mask = 0xff ^ (1 << bit);
247  buf[0] = (buf[0] & mask) | 0;
248  }
249  return true;
250  case 128:
251  case 256:
252  // XXX 128 & 256 bit
253  return false; // (ut64)rz_reg_get_longdouble (reg, item);
254  default:
255  RZ_LOG_ERROR("rz_reg_set_value: Bit size %d not supported\n", item->size);
256  return false;
257  }
258  const bool fits_in_arena = (arena->size - BITS2BYTES(item->offset) - BITS2BYTES(item->size)) >= 0;
259  if (!unset_src && fits_in_arena) {
260  rz_mem_copybits(reg->regset[item->arena].arena->bytes +
261  BITS2BYTES(item->offset),
262  src, item->size);
263  return true;
264  }
265  eprintf("rz_reg_set_value: Cannot set %s to 0x%" PFMT64x "\n", item->name, value);
266  return false;
267 }
268 
270  // TODO use mapping from RzRegisterId to RzRegItem (via RzRegSet)
271  const char *name = rz_reg_get_name(reg, role);
272  if (!name) {
273  return false;
274  }
275  RzRegItem *r = rz_reg_get(reg, name, -1);
276  return rz_reg_set_value(reg, r, val);
277 }
278 
280  ut64 num = UT64_MAX;
281  if (item && item->flags && str) {
283  if (num == UT64_MAX) {
284  num = rz_num_math(NULL, str);
285  }
286  rz_reg_set_value(reg, item, num);
287  }
288  return num;
289 }
290 
292  char *out = NULL;
293  if (reg && item && item->flags) {
294  out = malloc(strlen(item->flags) + 1);
295  if (out) {
296  ut64 num = rz_reg_get_value(reg, item);
297  rz_str_bits(out, (ut8 *)&num,
298  strlen(item->flags) * 8, item->flags);
299  }
300  }
301  return out;
302 }
303 
304 /* packed registers */
305 // packbits can be 8, 16, 32 or 64
306 // result value is always casted into ut64
307 // TODO: support packbits=128 for xmm registers
308 RZ_API ut64 rz_reg_get_pack(RzReg *reg, RzRegItem *item, int packidx, int packbits) {
309  rz_return_val_if_fail(reg && item, 0LL);
310 
311  if (packbits < 1) {
312  packbits = item->packed_size;
313  }
314  if (packbits > 64) {
315  packbits = 64;
316  eprintf("Does not support pack bits > 64\n");
317  }
318 
319  ut64 ret = 0LL;
320  const int packbytes = packbits / 8;
321  const int packmod = packbits % 8;
322  if (packmod) {
323  eprintf("Invalid bit size for packet register\n");
324  return 0LL;
325  }
326  if ((packidx + 1) * packbits > item->size) {
327  eprintf("Packed index is beyond the register size\n");
328  return 0LL;
329  }
330  RzRegSet *regset = &reg->regset[item->arena];
331  if (!regset->arena) {
332  return 0LL;
333  }
334  int off = BITS2BYTES(item->offset);
335  off += (packidx * packbytes);
336  if (regset->arena->size - off - 1 >= 0) {
337  int i;
338  for (i = packbytes - 1; i >= 0; i--) {
339  ret = (ret << 8) | regset->arena->bytes[off + i];
340  }
341  }
342  return ret;
343 }
344 
345 // TODO: support packbits=128 for xmm registers
346 RZ_API int rz_reg_set_pack(RzReg *reg, RzRegItem *item, int packidx, int packbits, ut64 val) {
347  rz_return_val_if_fail(reg && reg->regset->arena && item, false);
348 
349  if (packbits < 1) {
350  packbits = item->packed_size;
351  }
352  if (packbits > 64) {
353  packbits = 64;
354  eprintf("Does not support pack bits > 64\n");
355  }
356 
357  int packbytes = packbits / 8;
358  if ((packidx + 1) * packbits > item->size) {
359  eprintf("Packed index is beyond the register size\n");
360  return false;
361  }
362  int off = BITS2BYTES(item->offset);
363  off += (packidx * packbytes);
364  if (reg->regset[item->arena].arena->size - BITS2BYTES(off) - BITS2BYTES(packbytes) >= 0) {
365  ut8 *dst = reg->regset[item->arena].arena->bytes + off;
366  int i;
367  for (i = 0; i < packbytes; i++, val >>= 8) {
368  dst[i] = val & 0xff;
369  }
370  return true;
371  }
372  eprintf("rz_reg_set_value: Cannot set %s to 0x%" PFMT64x "\n", item->name, val);
373  return false;
374 }
#define mask()
lzma_index ** i
Definition: index.h:629
lzma_index * src
Definition: index.h:567
ut16 val
Definition: armass64_const.h:6
static ut8 bytes[32]
Definition: asm_arc.c:23
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
static int value
Definition: cmd_api.c:93
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RzCryptoSelector bit
Definition: crypto.c:16
#define r
Definition: crypto_rc6.c:12
uint16_t ut16
uint32_t ut32
RZ_API bool rz_reg_set_longdouble(RzReg *reg, RzRegItem *item, long double value)
Definition: double.c:94
RZ_API long double rz_reg_get_longdouble(RzReg *reg, RzRegItem *item)
Definition: double.c:67
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
#define reg(n)
uint8_t ut8
Definition: lh5801.h:11
void * malloc(size_t size)
Definition: malloc.c:123
static static fork const void static count static fd const char const char static newpath char char char static envp time_t static t const char static mode static whence const char static dir time_t static t unsigned static seconds const char struct utimbuf static buf static inc static sig const char static mode static oldfd struct tms static buf static getgid static geteuid const char static filename static arg static mask struct ustat static ubuf static getppid static setsid static egid sigset_t static set struct timeval struct timezone static tz fd_set fd_set fd_set struct timeval static timeout const char char static bufsiz const char static swapflags void static offset const char static length static mode static who const char struct statfs static buf unsigned unsigned num
Definition: sflib.h:126
char * dst
Definition: lz4.h:724
int idx
Definition: setup.py:197
int off
Definition: pal.c:13
RZ_API RzRegItem * rz_reg_get(RzReg *reg, const char *name, int type)
Definition: reg.c:344
RZ_API const char * rz_reg_get_name(RzReg *reg, int role)
Definition: reg.c:147
RZ_API bool rz_reg_is_readonly(RzReg *reg, RzRegItem *item)
Definition: reg.c:311
#define eprintf(x, y...)
Definition: rlcc.c:7
RZ_API bool rz_reg_set_value_by_role(RzReg *reg, RzRegisterId role, ut64 val)
Definition: rvalue.c:269
RZ_API bool rz_reg_set_bv(RZ_NONNULL RzReg *reg, RZ_NONNULL RzRegItem *item, RZ_NONNULL const RzBitVector *bv)
Definition: rvalue.c:26
RZ_API ut64 rz_reg_get_value_big(RzReg *reg, RzRegItem *item, utX *val)
Definition: rvalue.c:60
RZ_API ut64 rz_reg_set_bvalue(RzReg *reg, RzRegItem *item, const char *str)
Definition: rvalue.c:279
RZ_API int rz_reg_set_pack(RzReg *reg, RzRegItem *item, int packidx, int packbits, ut64 val)
Definition: rvalue.c:346
RZ_API ut64 rz_reg_get_pack(RzReg *reg, RzRegItem *item, int packidx, int packbits)
Definition: rvalue.c:308
RZ_API RzBitVector * rz_reg_get_bv(RZ_NONNULL RzReg *reg, RZ_NONNULL RzRegItem *item)
Definition: rvalue.c:11
RZ_API ut64 rz_reg_get_value_by_role(RzReg *reg, RzRegisterId role)
Definition: rvalue.c:181
RZ_API RZ_HEAP char * rz_reg_get_bvalue(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:291
RZ_API bool rz_reg_set_value(RzReg *reg, RzRegItem *item, ut64 value)
Definition: rvalue.c:186
ut32 ut27
Definition: rvalue.c:51
static ut27 rz_read_me27(const ut8 *buf, int boff)
Definition: rvalue.c:52
RZ_API ut64 rz_reg_get_value(RzReg *reg, RzRegItem *item)
Definition: rvalue.c:114
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
RZ_API void rz_bv_set_to_bytes_le(RZ_NONNULL const RzBitVector *bv, RZ_OUT RZ_NONNULL ut8 *buf)
Set the buffer contents from the given bitvector's bits in little endian format.
Definition: bitvector.c:1318
RZ_API ut64 rz_bv_to_ut64(RZ_NONNULL const RzBitVector *x)
Definition: bitvector.c:1454
RZ_API ut32 rz_bv_len(RZ_NONNULL const RzBitVector *bv)
Definition: bitvector.c:1140
RZ_API RZ_OWN RzBitVector * rz_bv_new_from_bytes_be(RZ_IN RZ_NONNULL const ut8 *buf, ut32 bit_offset, ut32 size)
Definition: bitvector.c:1207
RZ_API RZ_OWN RzBitVector * rz_bv_new_from_bytes_le(RZ_IN RZ_NONNULL const ut8 *buf, ut32 bit_offset, ut32 size)
Definition: bitvector.c:1194
RZ_API void rz_bv_set_to_bytes_be(RZ_NONNULL const RzBitVector *bv, RZ_OUT RZ_NONNULL ut8 *buf)
Set the buffer contents from the given bitvector's bits in big endian format.
Definition: bitvector.c:1349
static void rz_write_le32(void *dest, ut32 val)
Definition: rz_endian.h:256
static ut64 rz_read_ble64(const void *src, bool big_endian)
Definition: rz_endian.h:501
static void rz_write_le16(void *dest, ut16 val)
Definition: rz_endian.h:222
static void rz_write_be16(void *dest, ut16 val)
Definition: rz_endian.h:60
static void rz_write_ble8(void *dest, ut8 val)
Definition: rz_endian.h:23
static void rz_write_be64(void *dest, ut64 val)
Definition: rz_endian.h:119
static ut32 rz_read_ble32(const void *src, bool big_endian)
Definition: rz_endian.h:497
static ut16 rz_read_ble16(const void *src, bool big_endian)
Definition: rz_endian.h:493
static ut8 rz_read_at_ble8(const void *src, size_t offset)
Definition: rz_endian.h:19
static void rz_write_le64(void *dest, ut64 val)
Definition: rz_endian.h:277
static void rz_write_be32(void *dest, ut32 val)
Definition: rz_endian.h:98
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API void rz_mem_copybits_delta(ut8 *dst, int doff, const ut8 *src, int soff, int bits)
Definition: mem.c:141
RZ_API void rz_mem_copybits(ut8 *dst, const ut8 *src, int bits)
Definition: mem.c:79
RZ_API ut64 rz_num_math(RzNum *num, const char *str)
Definition: unum.c:456
RzRegisterId
Definition: rz_reg.h:42
RZ_API ut64 rz_str_bits_from_string(const char *buf, const char *bitz)
Definition: str.c:266
RZ_API int rz_str_bits(char *strout, const ut8 *buf, int len, const char *bitz)
Definition: str.c:195
#define RZ_HEAP
Definition: rz_types.h:254
#define RZ_NONNULL
Definition: rz_types.h:64
#define BITS2BYTES(x)
Definition: rz_types.h:280
#define PFMT64x
Definition: rz_types.h:393
#define UT64_MAX
Definition: rz_types_base.h:86
#define UT8_MAX
structure for bitvector
Definition: rz_bitvector.h:19
Definition: z80asm.h:102
ut8 * bytes
Definition: rz_reg.h:131
int size
in bits> 8,16,32,64 ... 128/256
Definition: rz_reg.h:120
int arena
In which arena is this reg living. Usually equals type.
Definition: rz_reg.h:127
char * flags
Definition: rz_reg.h:124
int packed_size
0 means no packed register, 1byte pack, 2b pack...
Definition: rz_reg.h:122
int offset
Offset into register profile in bits.
Definition: rz_reg.h:121
char * name
Definition: rz_reg.h:118
RzRegArena * arena
Definition: rz_reg.h:136
ut64(WINAPI *w32_GetEnabledXStateFeatures)()