mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-11 23:16:05 +00:00
ee39ba239a
* Add support for thumb mode ARM disassembler - Workaround a warning in r_vm for arm-16 * More work on drx.c, but still not integrated
176 lines
5.0 KiB
C
176 lines
5.0 KiB
C
#include <r_types.h>
|
|
|
|
/* -------------------- drx.h ------------------- */
|
|
#define DRXN 7
|
|
#define DR_STATUS 6
|
|
#define DR_CONTROL 7
|
|
|
|
#define DR_LOCAL_ENABLE_SHIFT 0 /* Extra shift to the local enable bit. */
|
|
#define DR_GLOBAL_ENABLE_SHIFT 1 /* Extra shift to the global enable bit. */
|
|
#define DR_ENABLE_SIZE 2 /* Two enable bits per debug register. */
|
|
|
|
/* Fields reserved by Intel. This includes the GD (General Detect
|
|
Enable) flag, which causes a debug exception to be generated when a
|
|
MOV instruction accesses one of the debug registers.
|
|
|
|
FIXME: My Intel manual says we should use 0xF800, not 0xFC00. */
|
|
#define DR_CONTROL_RESERVED (0xFC00)
|
|
|
|
#define I386_DR_CONTROL_MASK (~DR_CONTROL_RESERVED)
|
|
|
|
#define DR_LOCAL_SLOWDOWN (0x100)
|
|
#define DR_GLOBAL_SLOWDOWN (0x200)
|
|
|
|
/* DR7 fields */
|
|
/* How many bits to skip in DR7 to get to R/W and LEN fields. */
|
|
#define DR_CONTROL_SHIFT 16
|
|
/* How many bits in DR7 per R/W and LEN field for each watchpoint. */
|
|
#define DR_CONTROL_SIZE 4
|
|
|
|
#define DR_RW_EXECUTE (0x0) /* Break on instruction execution. */
|
|
#define DR_RW_WRITE (0x1) /* Break on data writes. */
|
|
#define DR_RW_IORW (0x2) /* Break on I/O reads or writes (not supported (2001) */
|
|
#define DR_RW_READ (0x3) /* Break on data reads or writes. */
|
|
|
|
/* Debug registers' indices. */
|
|
#define DR_NADDR 4 /* The number of debug address registers. */
|
|
#define DR_STATUS 6 /* Index of debug status register (DR6). */
|
|
#define DR_CONTROL 7 /* Index of debug control register (DR7). */
|
|
|
|
// is ut64 on 64 bitz ?
|
|
//#define drxt ut64
|
|
#define drxt ut32
|
|
|
|
#define DR_LEN_1 (0<<2) /* 1-byte region watch or breakpoint. */
|
|
#define DR_LEN_2 (1<<2) /* 2-byte region watch. */
|
|
#define DR_LEN_4 (3<<2) /* 4-byte region watch. */
|
|
#define DR_LEN_8 (2<<2) /* 8-byte region watch (AMD64). */
|
|
|
|
#define I386_DR_CONTROL_MASK (~DR_CONTROL_RESERVED)
|
|
|
|
/* unused */
|
|
#define I386_DR_VACANT(control, i) \
|
|
((control & (3 << (DR_ENABLE_SIZE * (i)))) == 0)
|
|
/* local/global */
|
|
#define I386_DR_LOCAL_ENABLE(control, i) \
|
|
control |= (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
|
|
#define I386_DR_GLOBAL_ENABLE(control, i) \
|
|
control |= (1 << (DR_GLOBAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i)))
|
|
|
|
#define I386_DR_IS_LOCAL_ENABLED(control, i) \
|
|
(control & (1 << (DR_LOCAL_ENABLE_SHIFT + DR_ENABLE_SIZE * (i))))
|
|
/* enable/disable */
|
|
#define I386_DR_IS_ENABLED(control, i) \
|
|
control & (3 << (DR_ENABLE_SIZE * (i)))
|
|
|
|
#define I386_DR_ENABLE(control, i) \
|
|
control |= (3 << (DR_ENABLE_SIZE * (i)))
|
|
#define I386_DR_DISABLE(control, i) \
|
|
control &= ~(3 << (DR_ENABLE_SIZE * (i)))
|
|
|
|
#define I386_DR_SET_RW_LEN(control, i,rwlen) \
|
|
do { \
|
|
control &= ~(0x0f << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \
|
|
control |= ((rwlen) << (DR_CONTROL_SHIFT+DR_CONTROL_SIZE*(i))); \
|
|
} while (0)
|
|
#define I386_DR_GET_RW_LEN(control, i) \
|
|
((control >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
|
|
|
|
/* ----------------------------- */
|
|
|
|
int drx_set(drxt *drx, int n, ut64 addr, int len, int rwx, int global) {
|
|
ut32 control = drx[DR_CONTROL];
|
|
if (n<0 || n>4) {
|
|
eprintf ("Invalid DRX index (0-4)\n");
|
|
return R_FALSE;
|
|
}
|
|
if (rwx<0 || rwx>3)
|
|
rwx = 0; // defaults to X
|
|
switch (len) {
|
|
case 1:
|
|
len = 0;
|
|
break;
|
|
case 2:
|
|
len = 1<<2;
|
|
break;
|
|
case 4:
|
|
len = 3<<2;
|
|
break;
|
|
case 8:
|
|
len = 2<<2; // AMD64 only
|
|
break;
|
|
default:
|
|
eprintf ("Invalid DRX length\n");
|
|
return R_FALSE;
|
|
}
|
|
I386_DR_SET_RW_LEN (control, n, len|rwx);
|
|
if (global) {
|
|
I386_DR_GLOBAL_ENABLE (control, n);
|
|
control |= DR_GLOBAL_SLOWDOWN;
|
|
} else {
|
|
I386_DR_LOCAL_ENABLE (control, n);
|
|
control |= DR_LOCAL_SLOWDOWN; // XXX: This is wrong
|
|
}
|
|
control &= I386_DR_CONTROL_MASK;
|
|
drx[n] = addr;
|
|
drx[DR_CONTROL] = control;
|
|
}
|
|
|
|
ut64 drx_get(drxt *drx, int n, int *rwx, int *len, int *global, int *enabled) {
|
|
int ret = I386_DR_GET_RW_LEN (drx[DR_CONTROL], n);
|
|
if (global) *global = I386_DR_IS_LOCAL_ENABLED (drx[7], n);
|
|
if (len) switch ((ret&0x3)<<2) {
|
|
case DR_LEN_1: *len = 1; break;
|
|
case DR_LEN_2: *len = 2; break;
|
|
case DR_LEN_4: *len = 4; break;
|
|
case DR_LEN_8: *len = 8; break;
|
|
}
|
|
if (enabled) *enabled = I386_DR_IS_ENABLED (drx[7], n);
|
|
if (rwx) *rwx = ret & 0x3;
|
|
return (ut64)drx[n];
|
|
}
|
|
|
|
int drx_next(drxt *drx) {
|
|
int i;
|
|
for(i=0; i<4; i++)
|
|
if (!drx[i])
|
|
return i;
|
|
return -1;
|
|
}
|
|
|
|
void drx_list(drxt *drx) {
|
|
ut64 addr;
|
|
int i, rwx, len, g, en;
|
|
for(i=0; i<4; i++) {
|
|
addr = drx_get (drx, i, &rwx, &len, &g, &en);
|
|
printf ("%c dr%d %c%c 0x%08llx %d\n",
|
|
en?'*':'-', i, g?'g':'l',
|
|
(rwx==DR_RW_READ)?'r':
|
|
(rwx==DR_RW_WRITE)?'w':
|
|
(rwx==DR_RW_EXECUTE)?'x':
|
|
(rwx==DR_RW_IORW)?'i':'?',
|
|
addr, len);
|
|
}
|
|
}
|
|
|
|
void drx_init(drxt *r) {
|
|
memset (r, 0, sizeof (drxt)*(DRXN+1));
|
|
}
|
|
|
|
void drx_enable(drxt *r, int n, int enabled) {
|
|
if (enabled) I386_DR_ENABLE (r[DR_CONTROL], n);
|
|
else I386_DR_DISABLE (r[DR_CONTROL], n);
|
|
}
|
|
|
|
#if MAIN
|
|
int main() {
|
|
drxt regs[DRXN];
|
|
drx_init (regs);
|
|
drx_set (regs, 1, 0x8048123, 1, DR_RW_EXECUTE, 0);
|
|
drx_set (regs, 0, 0x8048123, 4, DR_RW_READ, 1);
|
|
//drx_enable (regs, 0, R_TRUE);
|
|
// drx_enable (regs, 0, R_FALSE);
|
|
drx_list (regs);
|
|
}
|
|
#endif
|