Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2011-11-02 23:25:24 +0000
committerEugene Tarassov2011-11-02 23:25:24 +0000
commitb95d0997275c3e32a8f9211f04163fd01d39dab2 (patch)
treea069e6ee4b5c0254e39f15e12b9a9f027a1ac827
parentc0422c7ffc9a7c4bd4451b3979719fe126698962 (diff)
downloadorg.eclipse.tcf.agent-b95d0997275c3e32a8f9211f04163fd01d39dab2.tar.gz
org.eclipse.tcf.agent-b95d0997275c3e32a8f9211f04163fd01d39dab2.tar.xz
org.eclipse.tcf.agent-b95d0997275c3e32a8f9211f04163fd01d39dab2.zip
TCF Agent: added Breakpoints service API to access breakpoint attributes.
-rw-r--r--framework/streams.c4
-rw-r--r--services/breakpoints.c605
-rw-r--r--services/breakpoints.h46
3 files changed, 295 insertions, 360 deletions
diff --git a/framework/streams.c b/framework/streams.c
index 9d1a4f23..552c0876 100644
--- a/framework/streams.c
+++ b/framework/streams.c
@@ -97,13 +97,13 @@ void get_byte_array_output_stream_data(ByteArrayOutputStream * buf, char ** data
static int read_byte_array_input_stream(InputStream * inp) {
ByteArrayInputStream * buf = (ByteArrayInputStream *)((char *)inp - offsetof(ByteArrayInputStream, inp));
- if (buf->pos >= buf->max) return -1;
+ if (buf->pos >= buf->max) return MARKER_EOS;
return ((unsigned char *)buf->buf)[buf->pos++];
}
static int peek_byte_array_input_stream(InputStream * inp) {
ByteArrayInputStream * buf = (ByteArrayInputStream *)((char *)inp - offsetof(ByteArrayInputStream, inp));
- if (buf->pos >= buf->max) return -1;
+ if (buf->pos >= buf->max) return MARKER_EOS;
return ((unsigned char *)buf->buf)[buf->pos];
}
diff --git a/services/breakpoints.c b/services/breakpoints.c
index 1a8f2a15..4af52bf6 100644
--- a/services/breakpoints.c
+++ b/services/breakpoints.c
@@ -47,7 +47,6 @@
#include <services/pathmap.h>
typedef struct BreakpointRef BreakpointRef;
-typedef struct BreakpointAttribute BreakpointAttribute;
typedef struct InstructionRef InstructionRef;
typedef struct BreakInstruction BreakInstruction;
typedef struct EvaluationArgs EvaluationArgs;
@@ -62,12 +61,6 @@ struct BreakpointRef {
BreakpointInfo * bp;
};
-struct BreakpointAttribute {
- BreakpointAttribute * next;
- char * name;
- char * value;
-};
-
struct BreakpointInfo {
Context * ctx; /* NULL means all contexts */
LINK link_all;
@@ -79,7 +72,6 @@ struct BreakpointInfo {
int instruction_cnt;
ErrorReport * error;
char * address;
- char * type;
char * condition;
char ** context_ids;
char ** context_ids_prev;
@@ -94,6 +86,7 @@ struct BreakpointInfo {
int column;
int ignore_count;
int hit_count;
+ BreakpointAttribute * attrs;
BreakpointAttribute * unsupported;
EventPointCallBack * event_callback;
@@ -724,7 +717,6 @@ static ConditionEvaluationRequest * add_condition_evaluation_request(EvaluationR
ConditionEvaluationRequest * c = NULL;
assert(bp->instruction_cnt);
- assert(bp->unsupported == NULL);
assert(bp->error == NULL);
for (i = 0; i < req->bp_cnt; i++) {
@@ -832,7 +824,6 @@ static void free_bp(BreakpointInfo * bp) {
if (bp->ctx) context_unlock(bp->ctx);
release_error_report(bp->error);
loc_free(bp->address);
- loc_free(bp->type);
loc_free(bp->context_ids);
loc_free(bp->context_ids_prev);
loc_free(bp->context_names);
@@ -841,12 +832,12 @@ static void free_bp(BreakpointInfo * bp) {
loc_free(bp->file);
loc_free(bp->condition);
loc_free(bp->client_data);
- while (bp->unsupported != NULL) {
- BreakpointAttribute * u = bp->unsupported;
- bp->unsupported = u->next;
- loc_free(u->name);
- loc_free(u->value);
- loc_free(u);
+ while (bp->attrs != NULL) {
+ BreakpointAttribute * attr = bp->attrs;
+ bp->attrs = attr->next;
+ loc_free(attr->name);
+ loc_free(attr->value);
+ loc_free(attr);
}
assert(list_is_empty(&bp->link_clients));
loc_free(bp);
@@ -875,7 +866,6 @@ static void notify_breakpoints_status(void) {
}
}
assert(bp->enabled || instruction_cnt == 0);
- assert(bp->unsupported == NULL || instruction_cnt == 0);
assert(bp->instruction_cnt == instruction_cnt);
if (*bp->id) {
int i;
@@ -1269,13 +1259,6 @@ static void event_replant_breakpoints(void * arg) {
done_evaluation();
}
-static int str_equ(char * x, char * y) {
- if (x == y) return 1;
- if (x == NULL) return 0;
- if (y == NULL) return 0;
- return strcmp(x, y) == 0;
-}
-
static char ** str_arr_dup(char ** x) {
int n = 0;
int l = 0;
@@ -1375,142 +1358,6 @@ static void replant_breakpoint(BreakpointInfo * bp) {
}
}
-static int copy_breakpoint_info(BreakpointInfo * dst, BreakpointInfo * src) {
- int res = 0;
-
- if (strcmp(dst->id, src->id) != 0) {
- strcpy(dst->id, src->id);
- res = 1;
- }
-
- if (!str_equ(dst->address, src->address)) {
- loc_free(dst->address);
- dst->address = src->address;
- res = 1;
- }
- else {
- loc_free(src->address);
- }
- src->address = NULL;
-
- if (!str_equ(dst->type, src->type)) {
- loc_free(dst->type);
- dst->type = src->type;
- res = 1;
- }
- else {
- loc_free(src->type);
- }
- src->type = NULL;
-
- if (dst->access_mode != src->access_mode) {
- dst->access_mode = src->access_mode;
- res = 1;
- }
-
- if (dst->access_size != src->access_size) {
- dst->access_size = src->access_size;
- res = 1;
- }
-
- if (!str_equ(dst->condition, src->condition)) {
- loc_free(dst->condition);
- dst->condition = src->condition;
- res = 1;
- }
- else {
- loc_free(src->condition);
- }
- src->condition = NULL;
-
- if (!str_arr_equ(dst->context_ids, src->context_ids)) {
- loc_free(dst->context_ids);
- dst->context_ids = src->context_ids;
- res = 1;
- }
- else {
- loc_free(src->context_ids);
- }
- src->context_ids = NULL;
-
- if (!str_arr_equ(dst->context_names, src->context_names)) {
- loc_free(dst->context_names);
- dst->context_names = src->context_names;
- res = 1;
- }
- else {
- loc_free(src->context_names);
- }
- src->context_names = NULL;
-
- if (!str_arr_equ(dst->stop_group, src->stop_group)) {
- loc_free(dst->stop_group);
- dst->stop_group = src->stop_group;
- res = 1;
- }
- else {
- loc_free(src->stop_group);
- }
- src->stop_group = NULL;
-
- if (!str_equ(dst->file, src->file)) {
- loc_free(dst->file);
- dst->file = src->file;
- res = 1;
- }
- else {
- loc_free(src->file);
- }
- src->file = NULL;
-
- if (!str_equ(dst->client_data, src->client_data)) {
- loc_free(dst->client_data);
- dst->client_data = src->client_data;
- res = 1;
- }
- else {
- loc_free(src->client_data);
- }
- src->client_data = NULL;
-
- if (dst->line != src->line) {
- dst->line = src->line;
- res = 1;
- }
-
- if (dst->column != src->column) {
- dst->column = src->column;
- res = 1;
- }
-
- if (dst->ignore_count != src->ignore_count) {
- dst->ignore_count = src->ignore_count;
- res = 1;
- }
-
- if (dst->enabled != src->enabled) {
- dst->enabled = src->enabled;
- res = 1;
- }
-
- if (dst->unsupported != src->unsupported) {
- while (dst->unsupported != NULL) {
- BreakpointAttribute * u = dst->unsupported;
- dst->unsupported = u->next;
- loc_free(u->name);
- loc_free(u->value);
- loc_free(u);
- }
- dst->unsupported = src->unsupported;
- res = 1;
- }
- src->unsupported = NULL;
-
- if (res) dst->status_changed = 1;
-
- return res;
-}
-
static BreakpointInfo * find_breakpoint(char * id) {
int hash = id2bp_hash(id);
LINK * l = id2bp[hash].next;
@@ -1535,210 +1382,240 @@ static BreakpointRef * find_breakpoint_ref(BreakpointInfo * bp, Channel * channe
return NULL;
}
-static void read_breakpoint_properties(InputStream * inp, BreakpointInfo * bp) {
- memset(bp, 0, sizeof(BreakpointInfo));
+static BreakpointAttribute * read_breakpoint_properties(InputStream * inp) {
+ BreakpointAttribute * attrs = NULL;
if (read_stream(inp) != '{') exception(ERR_JSON_SYNTAX);
if (peek_stream(inp) == '}') {
read_stream(inp);
}
else {
+ BreakpointAttribute ** p = &attrs;
for (;;) {
int ch;
char name[256];
+ BreakpointAttribute * attr = (BreakpointAttribute *)loc_alloc(sizeof(BreakpointAttribute));
+
json_read_string(inp, name, sizeof(name));
if (read_stream(inp) != ':') exception(ERR_JSON_SYNTAX);
- if (strcmp(name, "ID") == 0) {
- json_read_string(inp, bp->id, sizeof(bp->id));
- }
- else if (strcmp(name, "Location") == 0) {
- bp->address = json_read_alloc_string(inp);
- }
- else if (strcmp(name, "Type") == 0) {
- bp->type = json_read_alloc_string(inp);
- }
- else if (strcmp(name, "AccessMode") == 0) {
- bp->access_mode = json_read_long(inp);
- }
- else if (strcmp(name, "Size") == 0) {
- bp->access_size = json_read_long(inp);
- }
- else if (strcmp(name, "Condition") == 0) {
- bp->condition = json_read_alloc_string(inp);
- }
- else if (strcmp(name, "ContextIds") == 0) {
- bp->context_ids = json_read_alloc_string_array(inp, NULL);
- }
- else if (strcmp(name, "ContextNames") == 0) {
- bp->context_names = json_read_alloc_string_array(inp, NULL);
- }
- else if (strcmp(name, "StopGroup") == 0) {
- bp->stop_group = json_read_alloc_string_array(inp, NULL);
- }
- else if (strcmp(name, "File") == 0) {
- bp->file = json_read_alloc_string(inp);
- }
- else if (strcmp(name, "Line") == 0) {
- bp->line = json_read_long(inp);
- }
- else if (strcmp(name, "Column") == 0) {
- bp->column = json_read_long(inp);
- }
- else if (strcmp(name, "IgnoreCount") == 0) {
- bp->ignore_count = json_read_long(inp);
- }
- else if (strcmp(name, "Enabled") == 0) {
- bp->enabled = json_read_boolean(inp);
- }
- else if (strcmp(name, "ClientData") == 0) {
- bp->client_data = json_read_object(inp);
- }
- else {
- BreakpointAttribute * u = (BreakpointAttribute *)loc_alloc(sizeof(BreakpointAttribute));
- u->name = loc_strdup(name);
- u->value = json_read_object(inp);
- u->next = bp->unsupported;
- bp->unsupported = u;
- }
+ attr->name = loc_strdup(name);
+ attr->value = json_read_object(inp);
+ *p = attr;
+ p = &attr->next;
+ attr->next = NULL;
+
ch = read_stream(inp);
if (ch == ',') continue;
if (ch == '}') break;
exception(ERR_JSON_SYNTAX);
}
}
+ return attrs;
}
-static void write_breakpoint_properties(OutputStream * out, BreakpointInfo * bp) {
- BreakpointAttribute * u = bp->unsupported;
-
- write_stream(out, '{');
-
- assert(*bp->id);
- json_write_string(out, "ID");
- write_stream(out, ':');
- json_write_string(out, bp->id);
-
- if (bp->address != NULL) {
- write_stream(out, ',');
- json_write_string(out, "Location");
- write_stream(out, ':');
- json_write_string(out, bp->address);
+static void read_id_attribute(BreakpointAttribute * attrs, char * id, size_t id_size) {
+ while (attrs != NULL) {
+ if (strcmp(attrs->name, BREAKPOINT_ID) == 0) {
+ ByteArrayInputStream buf;
+ InputStream * inp = create_byte_array_input_stream(&buf, attrs->value, strlen(attrs->value));
+ json_read_string(inp, id, id_size);
+ if (read_stream(inp) != MARKER_EOS) exception(ERR_JSON_SYNTAX);
+ return;
+ }
+ attrs = attrs->next;
}
+ str_exception(ERR_OTHER, "Breakpoint must have an ID");
+}
- if (bp->type != NULL) {
- write_stream(out, ',');
- json_write_string(out, "Type");
- write_stream(out, ':');
- json_write_string(out, bp->type);
- }
+static void set_breakpoint_attribute(BreakpointInfo * bp, const char * name, const char * value) {
+ BreakpointAttribute * attr = bp->attrs;
+ BreakpointAttribute ** ref = &bp->attrs;
- if (bp->access_mode != 0) {
- write_stream(out, ',');
- json_write_string(out, "AccessMode");
- write_stream(out, ':');
- json_write_long(out, bp->access_mode);
- }
+ while (attr != NULL) {
+ if (strcmp(attr->name, name) == 0) {
+ loc_free(attr->value);
+ attr->value = loc_strdup(value);
+ return;
+ }
+ ref = &attr->next;
+ attr = attr->next;
+ }
+ attr = (BreakpointAttribute *)loc_alloc_zero(sizeof(BreakpointAttribute));
+ attr->name = loc_strdup(name);
+ attr->value = loc_strdup(value);
+ *ref = attr;
+}
+
+static int set_breakpoint_attributes(BreakpointInfo * bp, BreakpointAttribute * new_attrs) {
+ int diff = 0;
+ BreakpointAttribute * old_attrs = bp->attrs;
+ BreakpointAttribute ** new_ref = &bp->attrs;
+ bp->attrs = NULL;
+
+ while (new_attrs != NULL) {
+ BreakpointAttribute * new_attr = new_attrs;
+ BreakpointAttribute * old_attr = old_attrs;
+ BreakpointAttribute ** old_ref = &old_attrs;
+ InputStream * buf_inp = NULL;
+ ByteArrayInputStream buf;
+ int unsupported_attr = 0;
+ char * name = new_attr->name;
+
+ new_attrs = new_attr->next;
+ new_attr->next = NULL;
+ while (old_attr && strcmp(old_attr->name, name)) {
+ old_ref = &old_attr->next;
+ old_attr = old_attr->next;
+ }
+
+ if (old_attr != NULL) {
+ assert(old_attr == *old_ref);
+ *old_ref = old_attr->next;
+ old_attr->next = NULL;
+ if (strcmp(old_attr->value, new_attr->value) == 0) {
+ *new_ref = old_attr;
+ new_ref = &old_attr->next;
+ loc_free(new_attr->value);
+ loc_free(new_attr->name);
+ loc_free(new_attr);
+ continue;
+ }
+ diff++;
+ loc_free(old_attr->value);
+ loc_free(old_attr->name);
+ loc_free(old_attr);
+ old_attr = NULL;
+ }
- if (bp->access_size != 0) {
- write_stream(out, ',');
- json_write_string(out, "Size");
- write_stream(out, ':');
- json_write_long(out, bp->access_size);
- }
+ *new_ref = new_attr;
+ new_ref = &new_attr->next;
- if (bp->condition != NULL) {
- write_stream(out, ',');
- json_write_string(out, "Condition");
- write_stream(out, ':');
- json_write_string(out, bp->condition);
- }
+ buf_inp = create_byte_array_input_stream(&buf, new_attr->value, strlen(new_attr->value));
- if (bp->context_ids != NULL) {
- char ** ids = bp->context_ids;
- write_stream(out, ',');
- json_write_string(out, "ContextIds");
- write_stream(out, ':');
- write_stream(out, '[');
- while (*ids != NULL) {
- if (ids != bp->context_ids) write_stream(out, ',');
- json_write_string(out, *ids++);
+ if (strcmp(name, BREAKPOINT_ID) == 0) {
+ json_read_string(buf_inp, bp->id, sizeof(bp->id));
}
- write_stream(out, ']');
- }
-
- if (bp->context_names != NULL) {
- char ** names = bp->context_names;
- write_stream(out, ',');
- json_write_string(out, "ContextNames");
- write_stream(out, ':');
- write_stream(out, '[');
- while (*names != NULL) {
- if (names != bp->context_names) write_stream(out, ',');
- json_write_string(out, *names++);
+ else if (strcmp(name, BREAKPOINT_LOCATION) == 0) {
+ loc_free(bp->address);
+ bp->address = json_read_alloc_string(buf_inp);
}
- write_stream(out, ']');
- }
-
- if (bp->stop_group != NULL) {
- char ** ids = bp->stop_group;
- write_stream(out, ',');
- json_write_string(out, "StopGroup");
- write_stream(out, ':');
- write_stream(out, '[');
- while (*ids != NULL) {
- if (ids != bp->stop_group) write_stream(out, ',');
- json_write_string(out, *ids++);
+ else if (strcmp(name, BREAKPOINT_ACCESSMODE) == 0) {
+ bp->access_mode = json_read_long(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_SIZE) == 0) {
+ bp->access_size = json_read_long(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_CONDITION) == 0) {
+ loc_free(bp->condition);
+ bp->condition = json_read_alloc_string(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_CONTEXTIDS) == 0) {
+ loc_free(bp->context_ids);
+ bp->context_ids = json_read_alloc_string_array(buf_inp, NULL);
+ }
+ else if (strcmp(name, BREAKPOINT_CONTEXTNAMES) == 0) {
+ loc_free(bp->context_names);
+ bp->context_names = json_read_alloc_string_array(buf_inp, NULL);
+ }
+ else if (strcmp(name, BREAKPOINT_STOP_GROUP) == 0) {
+ loc_free(bp->stop_group);
+ bp->stop_group = json_read_alloc_string_array(buf_inp, NULL);
+ }
+ else if (strcmp(name, BREAKPOINT_FILE) == 0) {
+ loc_free(bp->file);
+ bp->file = json_read_alloc_string(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_LINE) == 0) {
+ bp->line = json_read_long(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_COLUMN) == 0) {
+ bp->column = json_read_long(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_IGNORECOUNT) == 0) {
+ bp->ignore_count = json_read_long(buf_inp);
+ }
+ else if (strcmp(name, BREAKPOINT_ENABLED) == 0) {
+ bp->enabled = json_read_boolean(buf_inp);
+ }
+ else {
+ unsupported_attr = 1;
}
- write_stream(out, ']');
- }
- if (bp->file != NULL) {
- write_stream(out, ',');
- json_write_string(out, "File");
- write_stream(out, ':');
- json_write_string(out, bp->file);
+ if (!unsupported_attr && read_stream(buf_inp) != MARKER_EOS) exception(ERR_JSON_SYNTAX);
}
- if (bp->line > 0) {
- write_stream(out, ',');
- json_write_string(out, "Line");
- write_stream(out, ':');
- json_write_long(out, bp->line);
- }
+ while (old_attrs != NULL) {
+ BreakpointAttribute * old_attr = old_attrs;
+ char * name = old_attr->name;
+ old_attrs = old_attr->next;
- if (bp->column > 0) {
- write_stream(out, ',');
- json_write_string(out, "Column");
- write_stream(out, ':');
- json_write_long(out, bp->column);
- }
+ if (strcmp(name, BREAKPOINT_ID) == 0) {
+ bp->id[0] = 0;
+ }
+ else if (strcmp(name, BREAKPOINT_LOCATION) == 0) {
+ loc_free(bp->address);
+ bp->address = NULL;
+ }
+ else if (strcmp(name, BREAKPOINT_ACCESSMODE) == 0) {
+ bp->access_mode = 0;
+ }
+ else if (strcmp(name, BREAKPOINT_SIZE) == 0) {
+ bp->access_size = 0;
+ }
+ else if (strcmp(name, BREAKPOINT_CONDITION) == 0) {
+ loc_free(bp->condition);
+ bp->condition = NULL;
+ }
+ else if (strcmp(name, BREAKPOINT_CONTEXTIDS) == 0) {
+ loc_free(bp->context_ids);
+ bp->context_ids = NULL;
+ }
+ else if (strcmp(name, BREAKPOINT_CONTEXTNAMES) == 0) {
+ loc_free(bp->context_names);
+ bp->context_names = NULL;
+ }
+ else if (strcmp(name, BREAKPOINT_STOP_GROUP) == 0) {
+ loc_free(bp->stop_group);
+ bp->stop_group = NULL;
+ }
+ else if (strcmp(name, BREAKPOINT_FILE) == 0) {
+ loc_free(bp->file);
+ bp->file = NULL;
+ }
+ else if (strcmp(name, BREAKPOINT_LINE) == 0) {
+ bp->line = 0;
+ }
+ else if (strcmp(name, BREAKPOINT_COLUMN) == 0) {
+ bp->column = 0;
+ }
+ else if (strcmp(name, BREAKPOINT_IGNORECOUNT) == 0) {
+ bp->ignore_count = 0;
+ }
+ else if (strcmp(name, BREAKPOINT_ENABLED) == 0) {
+ bp->enabled = 0;
+ }
- if (bp->ignore_count > 0) {
- write_stream(out, ',');
- json_write_string(out, "IgnoreCount");
- write_stream(out, ':');
- json_write_long(out, bp->ignore_count);
+ loc_free(old_attr->value);
+ loc_free(old_attr->name);
+ loc_free(old_attr);
+ diff++;
}
- if (bp->enabled) {
- write_stream(out, ',');
- json_write_string(out, "Enabled");
- write_stream(out, ':');
- json_write_boolean(out, bp->enabled);
- }
+ return diff;
+}
- if (bp->client_data) {
- write_stream(out, ',');
- json_write_string(out, "ClientData");
- write_stream(out, ':');
- write_string(out, bp->client_data);
- }
+static void write_breakpoint_properties(OutputStream * out, BreakpointInfo * bp) {
+ int cnt = 0;
+ BreakpointAttribute * attr = bp->attrs;
- while (u != NULL) {
- write_stream(out, ',');
- json_write_string(out, u->name);
+ write_stream(out, '{');
+
+ while (attr != NULL) {
+ if (cnt > 0) write_stream(out, ',');
+ json_write_string(out, attr->name);
write_stream(out, ':');
- write_string(out, u->value);
- u = u->next;
+ write_string(out, attr->value);
+ attr = attr->next;
+ cnt++;
}
write_stream(out, '}');
@@ -1784,38 +1661,39 @@ static void send_event_context_removed(BreakpointInfo * bp) {
write_stream(out, MARKER_EOM);
}
-static void add_breakpoint(Channel * c, BreakpointInfo * bp) {
+static void add_breakpoint(Channel * c, BreakpointAttribute * attrs) {
+ char id[256];
BreakpointRef * r = NULL;
- BreakpointInfo * p = NULL;
+ BreakpointInfo * bp = NULL;
int added = 0;
int chng = 0;
- assert(*bp->id);
- p = find_breakpoint(bp->id);
- if (p == NULL) {
- int hash = id2bp_hash(bp->id);
- p = (BreakpointInfo *)loc_alloc_zero(sizeof(BreakpointInfo));
- list_init(&p->link_clients);
- list_add_last(&p->link_all, &breakpoints);
- list_add_last(&p->link_id, id2bp + hash);
- }
- chng = copy_breakpoint_info(p, bp);
- if (list_is_empty(&p->link_clients)) added = 1;
- else r = find_breakpoint_ref(p, c);
+ read_id_attribute(attrs, id, sizeof(id));
+ bp = find_breakpoint(id);
+ if (bp == NULL) {
+ int hash = id2bp_hash(id);
+ bp = (BreakpointInfo *)loc_alloc_zero(sizeof(BreakpointInfo));
+ list_init(&bp->link_clients);
+ list_add_last(&bp->link_all, &breakpoints);
+ list_add_last(&bp->link_id, id2bp + hash);
+ }
+ chng = set_breakpoint_attributes(bp, attrs);
+ if (list_is_empty(&bp->link_clients)) added = 1;
+ else r = find_breakpoint_ref(bp, c);
if (r == NULL) {
unsigned inp_hash = (unsigned)(uintptr_t)c / 16 % INP2BR_HASH_SIZE;
r = (BreakpointRef *)loc_alloc_zero(sizeof(BreakpointRef));
list_add_last(&r->link_inp, inp2br + inp_hash);
- list_add_last(&r->link_bp, &p->link_clients);
+ list_add_last(&r->link_bp, &bp->link_clients);
r->channel = c;
- r->bp = p;
- p->client_cnt++;
+ r->bp = bp;
+ bp->client_cnt++;
}
- assert(r->bp == p);
- assert(!list_is_empty(&p->link_clients));
- if (chng || added) replant_breakpoint(p);
- if (added) send_event_context_added(&broadcast_group->out, p);
- else if (chng) send_event_context_changed(p);
+ assert(r->bp == bp);
+ assert(!list_is_empty(&bp->link_clients));
+ if (chng || added) replant_breakpoint(bp);
+ if (added) send_event_context_added(&broadcast_group->out, bp);
+ else if (chng) send_event_context_changed(bp);
}
static void remove_ref(Channel * c, BreakpointRef * br) {
@@ -1874,9 +1752,7 @@ static void command_ini_bps(char * token, Channel * c) {
else {
for (;;) {
int ch;
- BreakpointInfo bp;
- read_breakpoint_properties(&c->inp, &bp);
- add_breakpoint(c, &bp);
+ add_breakpoint(c, read_breakpoint_properties(&c->inp));
ch = read_stream(&c->inp);
if (ch == ',') continue;
if (ch == ']') break;
@@ -1969,12 +1845,11 @@ static void command_get_status(char * token, Channel * c) {
}
static void command_bp_add(char * token, Channel * c) {
- BreakpointInfo bp;
- read_breakpoint_properties(&c->inp, &bp);
+ BreakpointAttribute * props = read_breakpoint_properties(&c->inp);
if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- add_breakpoint(c, &bp);
+ add_breakpoint(c, props);
write_stringz(&c->out, "R");
write_stringz(&c->out, token);
@@ -1983,12 +1858,11 @@ static void command_bp_add(char * token, Channel * c) {
}
static void command_bp_change(char * token, Channel * c) {
- BreakpointInfo bp;
- read_breakpoint_properties(&c->inp, &bp);
+ BreakpointAttribute * props = read_breakpoint_properties(&c->inp);
if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
- add_breakpoint(c, &bp);
+ add_breakpoint(c, props);
write_stringz(&c->out, "R");
write_stringz(&c->out, token);
@@ -2018,6 +1892,7 @@ static void command_bp_enable(char * token, Channel * c) {
if (bp != NULL && !list_is_empty(&bp->link_clients) && !bp->enabled) {
bp->enabled = 1;
bp->hit_count = 0;
+ set_breakpoint_attribute(bp, BREAKPOINT_ENABLED, "true");
replant_breakpoint(bp);
send_event_context_changed(bp);
}
@@ -2058,6 +1933,7 @@ static void command_bp_disable(char * token, Channel * c) {
bp = find_breakpoint(id);
if (bp != NULL && !list_is_empty(&bp->link_clients) && bp->enabled) {
bp->enabled = 0;
+ set_breakpoint_attribute(bp, BREAKPOINT_ENABLED, "false");
replant_breakpoint(bp);
send_event_context_changed(bp);
}
@@ -2181,6 +2057,19 @@ static void command_get_capabilities(char * token, Channel * c) {
write_stream(&c->out, MARKER_EOM);
}
+void iterate_breakpoints(IterateBreakpointsCallBack * callback, void * args) {
+ LINK * l = breakpoints.next;
+ while (l != &breakpoints) {
+ BreakpointInfo * bp = link_all2bp(l);
+ l = l->next;
+ callback(bp, args);
+ }
+}
+
+BreakpointAttribute * get_breakpoint_attributes(BreakpointInfo * bp) {
+ return bp->attrs;
+}
+
int is_breakpoint_address(Context * ctx, ContextAddress address) {
Context * mem = NULL;
ContextAddress mem_addr = 0;
diff --git a/services/breakpoints.h b/services/breakpoints.h
index 0a3e7aed..da5012ed 100644
--- a/services/breakpoints.h
+++ b/services/breakpoints.h
@@ -27,10 +27,56 @@
#include <framework/protocol.h>
typedef struct BreakpointInfo BreakpointInfo;
+typedef struct BreakpointAttribute BreakpointAttribute;
+
+struct BreakpointAttribute {
+ BreakpointAttribute * next;
+ char * name; /* Attribute name */
+ char * value; /* Attribute value as JSON string */
+};
#if SERVICE_Breakpoints
/*
+ * Breakpoint attribute names.
+ * Clients may define additional attributes.
+ */
+#define BREAKPOINT_ID "ID"
+#define BREAKPOINT_ENABLED "Enabled"
+#define BREAKPOINT_TYPE "BreakpointType"
+#define BREAKPOINT_CONTEXTNAMES "ContextNames"
+#define BREAKPOINT_CONTEXTIDS "ContextIds"
+#define BREAKPOINT_EXECUTABLEPATHS "ExecPaths"
+#define BREAKPOINT_LOCATION "Location"
+#define BREAKPOINT_SIZE "Size"
+#define BREAKPOINT_ACCESSMODE "AccessMode"
+#define BREAKPOINT_FILE "File"
+#define BREAKPOINT_LINE "Line"
+#define BREAKPOINT_COLUMN "Column"
+#define BREAKPOINT_PATTERN "MaskValue"
+#define BREAKPOINT_MASK "Mask"
+#define BREAKPOINT_STOP_GROUP "StopGroup"
+#define BREAKPOINT_IGNORECOUNT "IgnoreCount"
+#define BREAKPOINT_TIME "Time"
+#define BREAKPOINT_SCALE "TimeScale"
+#define BREAKPOINT_UNITS "TimeUnits"
+#define BREAKPOINT_CONDITION "Condition"
+#define BREAKPOINT_TEMPORARY "Temporary"
+#define BREAKPOINT_CLIENT_DATA "ClientData"
+
+
+/*
+ * Iterate all breakpoints known to the Breakpoints service.
+ */
+typedef void IterateBreakpointsCallBack(BreakpointInfo *, void *);
+extern void iterate_breakpoints(IterateBreakpointsCallBack * callback, void * args);
+
+/*
+ * Get the list of breakpoint attributes.
+ */
+extern BreakpointAttribute * get_breakpoint_attributes(BreakpointInfo * bp);
+
+/*
* The function is called from context.c every time a context is stopped by breakpoint.
* The function evaluates breakpoint condition and calls suspend_debug_context() if the condition is true.
*/

Back to the top