Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'agent/tcf/services')
-rw-r--r--agent/tcf/services/breakpoints.c42
1 files changed, 32 insertions, 10 deletions
diff --git a/agent/tcf/services/breakpoints.c b/agent/tcf/services/breakpoints.c
index ac28c360..61a07131 100644
--- a/agent/tcf/services/breakpoints.c
+++ b/agent/tcf/services/breakpoints.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007-2020 Wind River Systems, Inc. and others.
+ * Copyright (c) 2007-2023 Wind River Systems, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
@@ -54,6 +54,8 @@
# define ENABLE_SkipPrologueWhenPlanting 0
#endif
+#define MAX_WP_SIZE 0x10000
+
typedef struct BreakpointRef BreakpointRef;
typedef struct InstructionRef InstructionRef;
typedef struct BreakInstruction BreakInstruction;
@@ -287,11 +289,13 @@ static unsigned id2bp_hash(const char * id) {
}
static unsigned get_bp_access_types(BreakpointInfo * bp, int virtual_addr) {
+ /* Return breakpoint instruction access types for given breakpoint */
char * type = bp->type;
unsigned access_types = bp->access_mode;
if (access_types == 0 && (bp->file != NULL || bp->location != NULL)) access_types |= CTX_BP_ACCESS_INSTRUCTION;
if (virtual_addr && type != NULL && strcmp(type, "Software") == 0) access_types |= CTX_BP_ACCESS_SOFTWARE;
if (virtual_addr) access_types |= CTX_BP_ACCESS_VIRTUAL;
+ access_types &= ~CTX_BP_ACCESS_CHANGE; /* Handled by the service */
return access_types;
}
@@ -1650,6 +1654,7 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp
unsigned bit_offs = 0;
unsigned bit_size = 0;
void * bit_value = NULL;
+ int read_bit_value = 0;
int error = 0;
#if ENABLE_Expressions
Value v;
@@ -1697,8 +1702,7 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp
bit_offs += (unsigned)(addr & (size - 1)) * 8;
addr &= ~(size - 1);
if ((bp->access_mode & CTX_BP_ACCESS_DATA_READ) == 0) {
- bit_value = tmp_alloc_zero(size);
- if (!error && context_read_mem(ctx, addr, bit_value, size) < 0) error = errno;
+ read_bit_value = 1;
}
}
else if (bp->access_mode & (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE)) {
@@ -1716,6 +1720,19 @@ static void plant_at_address_expression(Context * ctx, ContextAddress ip, Breakp
}
#endif
}
+ if ((bp->access_mode & (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE)) != 0 && (bp->access_mode & CTX_BP_ACCESS_CHANGE) != 0) {
+ read_bit_value = 1;
+ }
+ if (!error && size == 0) error = set_errno(ERR_OTHER, "Invalid breakpoint size: 0");
+ if (!error && read_bit_value) {
+ if (size > MAX_WP_SIZE) {
+ error = set_fmt_errno(ERR_BUFFER_OVERFLOW, "Too large watchpoint size: > 0x%x", MAX_WP_SIZE);
+ }
+ else {
+ bit_value = tmp_alloc_zero(size);
+ if (!error && context_read_mem(ctx, addr, bit_value, size) < 0) error = errno;
+ }
+ }
if (error) {
address_expression_error(ctx, bp, error);
}
@@ -1925,14 +1942,19 @@ static void evaluate_condition(void * x) {
error = errno;
}
else {
- unsigned i;
int changed = 0;
- for (i = bi->bit_offs; i < bi->bit_offs + bi->bit_size; i++) {
- uint8_t v0 = ((uint8_t *)bi->bit_value)[i / 8];
- uint8_t v1 = ((uint8_t *)bi->bit_next)[i / 8];
- if ((v0 & (1 << (i % 8))) != (v1 & (1 << (i % 8)))) {
- changed = 1;
- break;
+ if (bi->bit_size == 0) {
+ changed = memcmp(bi->bit_value, bi->bit_next, size) != 0;
+ }
+ else {
+ unsigned i;
+ for (i = bi->bit_offs; i < bi->bit_offs + bi->bit_size; i++) {
+ uint8_t v0 = ((uint8_t *)bi->bit_value)[i / 8];
+ uint8_t v1 = ((uint8_t *)bi->bit_next)[i / 8];
+ if ((v0 & (1 << (i % 8))) != (v1 & (1 << (i % 8)))) {
+ changed = 1;
+ break;
+ }
}
}
if (!changed) condition_ok = 0;

Back to the top