mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-14 00:38:55 +00:00
1c143a3e3b
- Support spaces after dr? <reg>
188 lines
5.1 KiB
C
188 lines
5.1 KiB
C
/* radare - LGPL - Copyright 2009-2015 - pancake */
|
|
|
|
#include <r_reg.h>
|
|
#include <r_util.h>
|
|
|
|
R_API ut64 r_reg_get_value(RReg *reg, RRegItem *item) {
|
|
RRegSet *regset;
|
|
ut32 v32;
|
|
ut16 v16;
|
|
ut8 v8;
|
|
int off;
|
|
ut64 ret = 0LL;
|
|
if (!reg || !item)
|
|
return 0LL;
|
|
off = BITS2BYTES (item->offset);
|
|
regset = ®->regset[item->type];
|
|
#if 0
|
|
eprintf ("GET sz=%d off %d off = %d %d\n",
|
|
item->size, off, item->offset, (item->offset/8));
|
|
#endif
|
|
switch (item->size) {
|
|
case 80: // long double
|
|
ret = (ut64)r_reg_get_double (reg, item);
|
|
eprintf ("precission loss\n");
|
|
break;
|
|
case 1:
|
|
ret = (regset->arena->bytes[item->offset/8] & \
|
|
(1<<(item->offset%8)))?1:0;
|
|
break;
|
|
case 8:
|
|
if (regset->arena->size-off-1>=0) {
|
|
memcpy (&v8, regset->arena->bytes+off, 1);
|
|
ret = v8;
|
|
}
|
|
break;
|
|
case 16:
|
|
if (regset->arena->size-off-2>=0) {
|
|
r_mem_copyendian ((ut8*)&v16, (ut8*)regset->arena->bytes+off, 2, !reg->big_endian);
|
|
ret = v16;
|
|
}
|
|
break;
|
|
case 32:
|
|
if (off+4<=regset->arena->size) {
|
|
r_mem_copyendian ((ut8*)&v32, (ut8*)regset->arena->bytes+off, 4, !reg->big_endian);
|
|
ret = v32;
|
|
} else eprintf ("r_reg_get_value: 32bit oob read %d\n", off);
|
|
break;
|
|
case 64:
|
|
if (regset->arena->bytes && (off+8<=regset->arena->size))
|
|
r_mem_copyendian ((ut8*)&ret, (ut8*)regset->arena->bytes+off, 8, !reg->big_endian);
|
|
else eprintf ("r_reg_get_value: null or oob arena for current regset\n");
|
|
break;
|
|
default:
|
|
eprintf ("r_reg_get_value: Bit size %d not supported\n", item->size);
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
R_API int r_reg_set_value(RReg *reg, RRegItem *item, ut64 value) {
|
|
ut64 v64;
|
|
ut32 v32;
|
|
ut16 v16;
|
|
ut8 v8, *src;
|
|
|
|
if (!item) {
|
|
eprintf ("r_reg_set_value: item is NULL\n");
|
|
return R_FALSE;
|
|
}
|
|
switch (item->size) {
|
|
case 64: r_mem_copyendian ( (ut8*)&v64, (ut8*)&value, 8, !reg->big_endian); src = (ut8*)&v64; break;
|
|
case 32: r_mem_copyendian ( (ut8*)&v32, (ut8*)&value, 4, !reg->big_endian); src = (ut8*)&v32; break;
|
|
case 16: r_mem_copyendian ( (ut8*)&v16, (ut8*)&value, 2, !reg->big_endian); src = (ut8*)&v16; break;
|
|
case 8: v8 = (ut8)value; src = (ut8*)&v8; break;
|
|
case 1:
|
|
if (value) {
|
|
ut8 * buf = reg->regset[item->type].arena->bytes + (item->offset/8);
|
|
int bit = (item->offset%8);
|
|
ut8 mask = (1<<bit);
|
|
buf[0] = (buf[0] &(0xff^mask)) | mask;
|
|
} else {
|
|
ut8 * buf = reg->regset[item->type].arena->bytes + (item->offset/8);
|
|
int bit = item->offset % 8;
|
|
ut8 mask = 0xff ^ (1 << bit);
|
|
buf[0] = (buf[0] & mask) | 0;
|
|
}
|
|
return R_TRUE;
|
|
default:
|
|
eprintf ("r_reg_set_value: Bit size %d not supported\n", item->size);
|
|
return R_FALSE;
|
|
}
|
|
if (reg->regset[item->type].arena->size - BITS2BYTES (item->offset) - BITS2BYTES(item->size)>=0) {
|
|
r_mem_copybits (reg->regset[item->type].arena->bytes+
|
|
BITS2BYTES (item->offset), src, item->size);
|
|
return R_TRUE;
|
|
}
|
|
eprintf ("r_reg_set_value: Cannot set %s to 0x%"PFMT64x"\n", item->name, value);
|
|
return R_FALSE;
|
|
}
|
|
|
|
R_API ut64 r_reg_set_bvalue(RReg *reg, RRegItem *item, const char *str) {
|
|
ut64 num = UT64_MAX;
|
|
if (item && item->flags && str) {
|
|
num = r_str_bits_from_string (str, item->flags);
|
|
if (num == UT64_MAX)
|
|
num = r_num_math (NULL, str);
|
|
r_reg_set_value (reg, item, num);
|
|
}
|
|
return num;
|
|
}
|
|
|
|
// experimental new notation
|
|
#undef HEAP
|
|
#define HEAP
|
|
|
|
R_API HEAP char *r_reg_get_bvalue(RReg *reg, RRegItem *item) {
|
|
char *out = NULL;
|
|
if (reg && item && item->flags) {
|
|
out = malloc (strlen (item->flags)+1);
|
|
if (out) {
|
|
ut64 num = r_reg_get_value (reg, item);
|
|
r_str_bits (out, (ut8*)&num,
|
|
strlen (item->flags) * 8, item->flags);
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
/* packed registers */
|
|
// packbits can be 8, 16, 32 or 64
|
|
// result value is always casted into ut64
|
|
// TODO: use item->packed_size
|
|
R_API ut64 r_reg_get_pack(RReg *reg, RRegItem *item, int packidx, int packbits) {
|
|
int packbytes, packmod;
|
|
ut64 ret = 0LL;
|
|
RRegSet *regset;
|
|
int off;
|
|
if (!reg || !item)
|
|
return 0LL;
|
|
if (packbits<1) {
|
|
packbits = item->packed_size;
|
|
}
|
|
packbytes = packbits / 8;
|
|
packmod = packbits % 8;
|
|
if (packmod) {
|
|
eprintf ("Invalid bit size for packet register\n");
|
|
return 0LL;
|
|
}
|
|
off = BITS2BYTES (item->offset);
|
|
regset = ®->regset[item->type];
|
|
off += (packidx * packbytes);
|
|
if (regset->arena->size - off - 1 >= 0) {
|
|
memcpy (&ret, regset->arena->bytes + off, packbytes);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
R_API int r_reg_set_pack(RReg *reg, RRegItem *item, int packidx, int packbits, ut64 val) {
|
|
int packbytes, packmod;
|
|
int off = item->offset;
|
|
|
|
if (!reg || !item) {
|
|
eprintf ("r_reg_set_value: item is NULL\n");
|
|
return R_FALSE;
|
|
}
|
|
if (packbits<1) {
|
|
packbits = item->packed_size;
|
|
}
|
|
packbytes = packbits / 8;
|
|
packmod = packbits % 8;
|
|
if (packidx * packbits > item->size) {
|
|
eprintf ("Packed index is beyond the register size\n");
|
|
return R_FALSE;
|
|
}
|
|
if (packmod) {
|
|
eprintf ("Invalid bit size for packet register\n");
|
|
return R_FALSE;
|
|
}
|
|
if (reg->regset[item->type].arena->size - BITS2BYTES (off) - BITS2BYTES(packbytes) >= 0) {
|
|
r_mem_copybits (reg->regset[item->type].arena->bytes+
|
|
BITS2BYTES (off), (ut8*)&val, packbytes);
|
|
return R_TRUE;
|
|
}
|
|
eprintf ("r_reg_set_value: Cannot set %s to 0x%"PFMT64x"\n", item->name, val);
|
|
return R_FALSE;
|
|
}
|
|
|