diff options
Diffstat (limited to 'agent/tcf/services')
-rw-r--r-- | agent/tcf/services/breakpoints.c | 42 |
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; |