diff --git a/libr/bp/bp.c b/libr/bp/bp.c index fc3b165ba5..1917e9e929 100644 --- a/libr/bp/bp.c +++ b/libr/bp/bp.c @@ -284,8 +284,8 @@ R_API int r_bp_list(RBreakpoint *bp, int rad) { " %d %c%c%c %s %s %s cmd=\"%s\" cond=\"%s\" " \ "name=\"%s\" module=\"%s\"\n", b->addr, b->addr + b->size, b->size, - (b->rwx & R_BP_PROT_READ) ? 'r' : '-', - (b->rwx & R_BP_PROT_WRITE) ? 'w' : '-', + ((b->rwx & R_BP_PROT_READ) | (b->rwx & R_BP_PROT_ACCESS)) ? 'r' : '-', + ((b->rwx & R_BP_PROT_WRITE)| (b->rwx & R_BP_PROT_ACCESS)) ? 'w' : '-', (b->rwx & R_BP_PROT_EXEC) ? 'x' : '-', b->hw ? "hw": "sw", b->trace ? "trace" : "break", diff --git a/libr/core/cmd_debug.c b/libr/core/cmd_debug.c index 042463f5cb..95fc0bf59b 100644 --- a/libr/core/cmd_debug.c +++ b/libr/core/cmd_debug.c @@ -76,7 +76,7 @@ static const char *help_msg_db[] = { "dbh-", " ", "Remove breakpoint plugin handler", "dbt", "[?]", "Show backtrace. See dbt? for more details", "dbx", " [expr]", "Set expression for bp in current offset", - "dbw", " ", "Add watchpoint", + "dbw", " ", "Add watchpoint", "drx", " number addr len rwx", "Modify hardware breakpoint", "drx-", "number", "Clear hardware breakpoint", NULL @@ -96,6 +96,11 @@ static const char *help_msg_dbt[] = { NULL }; +static const char *help_msg_dbw[] = { + "Usage: dbw", " "," # Add watchpoint", + NULL +}; + static const char *help_msg_dc[] = { "Usage: dc", "", "Execution continuation commands", "dc", "", "Continue execution of all children", @@ -1445,7 +1450,7 @@ static void get_hash_debug_file(RCore *core, const char *path, char *hash, int h RBinSection *s; r_list_foreach (sects, iter, s) { if (strstr (s->name, ".note.gnu.build-id")) { - if (r_buf_read_at (binfile->buf, s->vaddr + 16, (ut8*)buf, 20) == 20) { + if (r_buf_read_at (binfile->buf, s->vaddr + 16, buf, 20) == 20) { break; } eprintf ("Cannot read from buffer\n"); @@ -3405,13 +3410,26 @@ static void r_core_cmd_bp(RCore *core, const char *input) { int sl = r_str_word_set0 (str); addr = r_num_math (core->num, DB_ARG(0)); if (watch) { - if (sl == 2) { - rw = (strcmp (DB_ARG(1), "r") == 0 ? R_BP_PROT_READ : R_BP_PROT_WRITE); - } else { - eprintf ("Usage: dbw # Add watchpoint\n"); + if (sl == 2) { + if (!strcmp (DB_ARG(1), "r")){ + rw = R_BP_PROT_READ; + } + else if (!strcmp (DB_ARG(1), "w")){ + rw = R_BP_PROT_WRITE; + } + else if (!strcmp (DB_ARG(1), "rw")){ + rw = R_BP_PROT_ACCESS; + } + else{ + r_core_cmd_help (core, help_msg_dbw); free (str); break; } + } else { + r_core_cmd_help (core, help_msg_dbw); + free (str); + break; + } } if (validAddress (core, addr)) { bpi = r_debug_bp_add (core->dbg, addr, hwbp, watch, rw, NULL, 0); diff --git a/libr/debug/p/debug_gdb.c b/libr/debug/p/debug_gdb.c index 555f4e59cc..1a3e8afd16 100644 --- a/libr/debug/p/debug_gdb.c +++ b/libr/debug/p/debug_gdb.c @@ -976,17 +976,43 @@ static int r_debug_gdb_breakpoint (RBreakpoint *bp, RBreakpointItem *b, bool set if (!b) { return false; } - bpsize = b->size; - // TODO handle rwx and conditions - if (set) - ret = b->hw? - gdbr_set_hwbp (desc, b->addr, "", bpsize): - gdbr_set_bp (desc, b->addr, "", bpsize); - else - ret = b->hw? - gdbr_remove_hwbp (desc, b->addr, bpsize): - gdbr_remove_bp (desc, b->addr, bpsize); + // TODO handle conditions + switch (b->rwx){ + case R_BP_PROT_EXEC : { + if (set) + ret = b->hw? + gdbr_set_hwbp (desc, b->addr, "", bpsize): + gdbr_set_bp (desc, b->addr, "", bpsize); + else + ret = b->hw? + gdbr_remove_hwbp (desc, b->addr, bpsize): + gdbr_remove_bp (desc, b->addr, bpsize); + break; + } + // TODO handle size (area of watch in upper layer and then bpsize. For the moment watches are set on exact on byte + case R_BP_PROT_WRITE : { + if (set) + gdbr_set_hww (desc, b->addr, "", 1); + else + gdbr_remove_hwbp (desc, b->addr, 1); + break; + } + case R_BP_PROT_READ : { + if (set) + gdbr_set_hwr (desc, b->addr, "", 1); + else + gdbr_remove_hwr (desc, b->addr, 1); + break; + } + case R_BP_PROT_ACCESS : { + if (set) + gdbr_set_hwa (desc, b->addr, "", 1); + else + gdbr_remove_hwa (desc, b->addr, 1); + break; + } + } return !ret; } diff --git a/libr/include/r_bp.h b/libr/include/r_bp.h index da2e613dac..1a9dd125dc 100644 --- a/libr/include/r_bp.h +++ b/libr/include/r_bp.h @@ -62,8 +62,7 @@ typedef struct r_bp_item_t { char *expr; /* to be used for named breakpoints (see r_debug_bp_update) */ } RBreakpointItem; -struct r_bp_t; -typedef int (*RBreakpointCallback)(struct r_bp_t *bp, RBreakpointItem *b, bool set); +typedef int (*RBreakpointCallback)(void *bp, RBreakpointItem *b, bool set); typedef struct r_bp_t { void *user; @@ -89,6 +88,7 @@ enum { R_BP_PROT_EXEC = 1, R_BP_PROT_WRITE = 2, R_BP_PROT_READ = 4, + R_BP_PROT_ACCESS = 8, }; typedef struct r_bp_trace_t { diff --git a/shlr/gdb/include/gdbclient/commands.h b/shlr/gdb/include/gdbclient/commands.h index d7f5cb69ac..a385dd14e1 100644 --- a/shlr/gdb/include/gdbclient/commands.h +++ b/shlr/gdb/include/gdbclient/commands.h @@ -101,9 +101,14 @@ int test_command(libgdbr_t *g, const char *command); */ int gdbr_set_bp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp); int gdbr_set_hwbp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp); +int gdbr_set_hww(libgdbr_t *g, ut64 address, const char *conditions, int sizebp); +int gdbr_set_hwr(libgdbr_t *g, ut64 address, const char *conditions, int sizebp); +int gdbr_set_hwa(libgdbr_t *g, ut64 address, const char *conditions, int sizebp); int gdbr_remove_bp(libgdbr_t *g, ut64 address, int sizebp); int gdbr_remove_hwbp(libgdbr_t *g, ut64 address, int sizebp); - +int gdbr_remove_hww(libgdbr_t *g, ut64 address, int sizebp); +int gdbr_remove_hwr(libgdbr_t *g, ut64 address, int sizebp); +int gdbr_remove_hwa(libgdbr_t *g, ut64 address, int sizebp); /*! * File read from remote target (only one file open at a time for now) */ diff --git a/shlr/gdb/include/gdbclient/core.h b/shlr/gdb/include/gdbclient/core.h index 033578fa46..9fa03e4b27 100644 --- a/shlr/gdb/include/gdbclient/core.h +++ b/shlr/gdb/include/gdbclient/core.h @@ -28,11 +28,17 @@ #define CMD_RBP "z0" #define CMD_HBP "Z1" #define CMD_RHBP "z1" +#define CMD_HWW "Z2" +#define CMD_RHWW "z2" +#define CMD_HWR "Z3" +#define CMD_RHWR "z3" +#define CMD_HWA "Z4" +#define CMD_RHWA "z4" #define CMD_QRCMD "qRcmd," -#define CMD_C "vCont" -#define CMD_C_CONT "c" +#define CMD_C "vCont" +#define CMD_C_CONT "c" #define CMD_C_CONT_SIG "C" -#define CMD_C_STEP "s" +#define CMD_C_STEP "s" enum Breakpoint { BREAKPOINT, diff --git a/shlr/gdb/src/gdbclient/core.c b/shlr/gdb/src/gdbclient/core.c index c6fdb044c2..38ab028316 100644 --- a/shlr/gdb/src/gdbclient/core.c +++ b/shlr/gdb/src/gdbclient/core.c @@ -981,10 +981,16 @@ int set_bp(libgdbr_t *g, ut64 address, const char *conditions, enum Breakpoint t "%s,%"PFMT64x ",%d", CMD_HBP, address, sizebp); break; case WRITE_WATCHPOINT: + ret = snprintf (tmp, sizeof (tmp) - 1, + "%s,%"PFMT64x ",%d", CMD_HWW, address, sizebp); break; case READ_WATCHPOINT: + ret = snprintf (tmp, sizeof (tmp) - 1, + "%s,%"PFMT64x ",%d", CMD_HWR, address, sizebp); break; case ACCESS_WATCHPOINT: + ret = snprintf (tmp, sizeof (tmp) - 1, + "%s,%"PFMT64x ",%d", CMD_HWA, address, sizebp); break; default: break; @@ -1012,6 +1018,18 @@ int gdbr_set_hwbp(libgdbr_t *g, ut64 address, const char *conditions, int sizebp return set_bp (g, address, conditions, HARDWARE_BREAKPOINT, sizebp); } +int gdbr_set_hww(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) { + return set_bp (g, address, conditions, WRITE_WATCHPOINT, sizebp); +} + +int gdbr_set_hwr(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) { + return set_bp (g, address, conditions, READ_WATCHPOINT, sizebp); +} + +int gdbr_set_hwa(libgdbr_t *g, ut64 address, const char *conditions, int sizebp) { + return set_bp (g, address, conditions, ACCESS_WATCHPOINT, sizebp); +} + int gdbr_remove_bp(libgdbr_t *g, ut64 address, int sizebp) { return remove_bp (g, address, BREAKPOINT, sizebp); } @@ -1020,6 +1038,19 @@ int gdbr_remove_hwbp(libgdbr_t *g, ut64 address, int sizebp) { return remove_bp (g, address, HARDWARE_BREAKPOINT, sizebp); } +int gdbr_remove_hww(libgdbr_t *g, ut64 address, int sizebp) { + return remove_bp (g, address, WRITE_WATCHPOINT, sizebp); +} + +int gdbr_remove_hwr(libgdbr_t *g, ut64 address, int sizebp) { + return remove_bp (g, address, READ_WATCHPOINT, sizebp); +} + +int gdbr_remove_hwa(libgdbr_t *g, ut64 address, int sizebp) { + return remove_bp (g, address, ACCESS_WATCHPOINT, sizebp); +} + + int remove_bp(libgdbr_t *g, ut64 address, enum Breakpoint type, int sizebp) { char tmp[255] = {0}; int ret = -1; @@ -1034,10 +1065,13 @@ int remove_bp(libgdbr_t *g, ut64 address, enum Breakpoint type, int sizebp) { ret = snprintf (tmp, sizeof (tmp) - 1, "%s,%"PFMT64x ",%d", CMD_RHBP, address, sizebp); break; case WRITE_WATCHPOINT: + ret = snprintf (tmp, sizeof (tmp) - 1, "%s,%"PFMT64x ",%d", CMD_RHWW, address, sizebp); break; case READ_WATCHPOINT: + ret = snprintf (tmp, sizeof (tmp) - 1, "%s,%"PFMT64x ",%d", CMD_RHWR, address, sizebp); break; case ACCESS_WATCHPOINT: + ret = snprintf (tmp, sizeof (tmp) - 1, "%s,%"PFMT64x ",%d", CMD_RHWA, address, sizebp); break; default: break;