diff options
author | eutarass | 2011-02-08 19:35:40 +0000 |
---|---|---|
committer | eutarass | 2011-02-08 19:35:40 +0000 |
commit | afea90d60a38824cfbc269414665646812977511 (patch) | |
tree | 9e222c97a274b572a5426e639d34068d12833087 | |
parent | cf5162334b38786bed6e5fdf76575ed9f6604f93 (diff) | |
download | org.eclipse.tcf.agent-afea90d60a38824cfbc269414665646812977511.tar.gz org.eclipse.tcf.agent-afea90d60a38824cfbc269414665646812977511.tar.xz org.eclipse.tcf.agent-afea90d60a38824cfbc269414665646812977511.zip |
Bug 336474: [cdt] Add support for C/C++ Watchpoints
-rw-r--r-- | services/breakpoints.c | 61 | ||||
-rw-r--r-- | services/diagnostics.c | 4 | ||||
-rw-r--r-- | services/expressions.c | 17 | ||||
-rw-r--r-- | services/expressions.h | 11 | ||||
-rw-r--r-- | services/symbols.c | 9 | ||||
-rw-r--r-- | services/symbols.h | 4 | ||||
-rw-r--r-- | services/symbols_elf.c | 4 | ||||
-rw-r--r-- | services/symbols_proxy.c | 7 | ||||
-rw-r--r-- | services/symbols_win32.c | 27 |
9 files changed, 86 insertions, 58 deletions
diff --git a/services/breakpoints.c b/services/breakpoints.c index a1fc558d..05a785a1 100644 --- a/services/breakpoints.c +++ b/services/breakpoints.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -945,41 +945,50 @@ static void expr_cache_exit(EvaluationArgs * args) { run_ctrl_unlock(); } -static void evaluate_address_expression(void * x) { - EvaluationArgs * args = (EvaluationArgs *)x; - BreakpointInfo * bp = args->bp; +static void plant_at_address_expression(Context * ctx, ContextAddress ip, BreakpointInfo * bp) { ContextAddress addr = 0; ContextAddress size = 1; int error = 0; Value v; - assert(cache_enter_cnt > 0); - if (evaluate_expression(args->ctx, STACK_NO_FRAME, bp->address, 1, &v) < 0) error = errno; + if (evaluate_expression(ctx, STACK_NO_FRAME, ip, bp->address, 1, &v) < 0) error = errno; if (!error && value_to_address(&v, &addr) < 0) error = errno; if (bp->access_mode & (CTX_BP_ACCESS_DATA_READ | CTX_BP_ACCESS_DATA_WRITE)) { - Symbol * type = v.type; - if (type != NULL) { - int type_class = 0; - Symbol * base_type = NULL; - if (!error && get_symbol_type_class(type, &type_class) < 0) error = errno; - if (!error && type_class != TYPE_CLASS_POINTER) error = set_errno(ERR_INV_DATA_TYPE, "Pointer expected"); - if (!error && get_symbol_base_type(type, &base_type) < 0) error = errno; - if (!error && base_type != NULL && get_symbol_size(base_type, &size) < 0) error = errno; - } - else { - size = context_word_size(args->ctx); + size = context_word_size(ctx); +#if ENABLE_Symbols + { + Symbol * type = v.type; + if (type != NULL) { + int type_class = 0; + Symbol * base_type = NULL; + if (!error && get_symbol_type_class(type, &type_class) < 0) error = errno; + if (!error && type_class != TYPE_CLASS_POINTER) error = set_errno(ERR_INV_DATA_TYPE, "Pointer expected"); + if (!error && get_symbol_base_type(type, &base_type) < 0) error = errno; + if (!error && base_type != NULL && get_symbol_size(base_type, &size) < 0) error = errno; + } } +#endif } - if (error) address_expression_error(args->ctx, bp, error); - else plant_breakpoint(args->ctx, bp, addr, size); + if (error) address_expression_error(ctx, bp, error); + else plant_breakpoint(ctx, bp, addr, size); +} + +static void evaluate_address_expression(void * x) { + EvaluationArgs * args = (EvaluationArgs *)x; + assert(cache_enter_cnt > 0); + plant_at_address_expression(args->ctx, 0, args->bp); expr_cache_exit(args); } #if ENABLE_LineNumbers static void plant_breakpoint_address_iterator(CodeArea * area, void * x) { EvaluationArgs * args = (EvaluationArgs *)x; - BreakpointInfo * bp = args->bp; - plant_breakpoint(args->ctx, bp, area->start_address, 1); + if (args->bp->address == NULL) { + plant_breakpoint(args->ctx, args->bp, area->start_address, 1); + } + else { + plant_at_address_expression(args->ctx, area->start_address, args->bp); + } } static void evaluate_text_location(void * x) { @@ -1029,7 +1038,7 @@ static void evaluate_condition(void * x) { if (bp->condition != NULL) { Value v; int b = 0; - if (evaluate_expression(ctx, STACK_TOP_FRAME, bp->condition, 1, &v) < 0 || value_to_boolean(&v, &b) < 0) { + if (evaluate_expression(ctx, STACK_TOP_FRAME, 0, bp->condition, 1, &v) < 0 || value_to_boolean(&v, &b) < 0) { int no = get_error_code(errno); if (no == ERR_CACHE_MISS) continue; if (no == ERR_CHANNEL_CLOSED) continue; @@ -1076,10 +1085,7 @@ static void event_replant_breakpoints(void * arg) { l = l->next; if (is_disabled(bp)) continue; if (!check_context_ids(bp, ctx)) continue; - if (bp->address != NULL) { - expr_cache_enter(evaluate_address_expression, bp, ctx); - } - else if (bp->file != NULL) { + if (bp->file != NULL) { #if ENABLE_LineNumbers expr_cache_enter(evaluate_text_location, bp, ctx); #else @@ -1087,6 +1093,9 @@ static void event_replant_breakpoints(void * arg) { address_expression_error(NULL, bp, errno); #endif } + else if (bp->address != NULL) { + expr_cache_enter(evaluate_address_expression, bp, ctx); + } else { address_expression_error(NULL, bp, ERR_INV_EXPRESSION); } diff --git a/services/diagnostics.c b/services/diagnostics.c index 76b0bd90..ae5d316d 100644 --- a/services/diagnostics.c +++ b/services/diagnostics.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -251,7 +251,7 @@ static void get_symbol_cache_client(void * x) { if (ctx->exited) { error = ERR_ALREADY_EXITED; } - else if (find_symbol_by_name(ctx, STACK_NO_FRAME, args->name, &sym) < 0) { + else if (find_symbol_by_name(ctx, STACK_NO_FRAME, 0, args->name, &sym) < 0) { error = errno; } else if (get_symbol_address(sym, &addr) < 0) { diff --git a/services/expressions.c b/services/expressions.c index d138715a..488452db 100644 --- a/services/expressions.c +++ b/services/expressions.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -86,6 +86,7 @@ static StringValue * str_alloc_list = NULL; static Context * expression_context = NULL; static int expression_frame = STACK_NO_FRAME; +static ContextAddress expression_addr = 0; #define MAX_ID_CALLBACKS 8 static ExpressionIdentifierCallBack * id_callbacks[MAX_ID_CALLBACKS]; @@ -547,7 +548,7 @@ static int identifier(char * name, Value * v) { #if ENABLE_Symbols { Symbol * sym = NULL; - if (find_symbol_by_name(expression_context, expression_frame, name, &sym) < 0) { + if (find_symbol_by_name(expression_context, expression_frame, expression_addr, name, &sym) < 0) { if (get_error_code(errno) != ERR_SYM_NOT_FOUND) error(errno, "Cannot read symbol data"); } else { @@ -1777,11 +1778,12 @@ static void expression(int mode, Value * v) { conditional_expression(mode, v); } -static int evaluate_type(Context * ctx, int frame, char * s, Value * v) { +static int evaluate_type(Context * ctx, int frame, ContextAddress addr, char * s, Value * v) { Trap trap; expression_context = ctx; expression_frame = frame; + expression_addr = addr; if (!set_trap(&trap)) return -1; str_pool_cnt = 0; while (str_alloc_list != NULL) { @@ -1800,11 +1802,12 @@ static int evaluate_type(Context * ctx, int frame, char * s, Value * v) { return 0; } -int evaluate_expression(Context * ctx, int frame, char * s, int load, Value * v) { +int evaluate_expression(Context * ctx, int frame, ContextAddress addr, char * s, int load, Value * v) { Trap trap; expression_context = ctx; expression_frame = frame; + expression_addr = addr; if (!set_trap(&trap)) return -1; if (s == NULL || *s == 0) str_exception(ERR_INV_EXPRESSION, "Empty expression"); str_pool_cnt = 0; @@ -2201,7 +2204,7 @@ static void command_create_cache_client(void * x) { else if (id2frame(e->parent, &ctx, &frame) < 0) { err = errno; } - if (!err && evaluate_type(ctx, frame, e->script, &value) < 0) err = errno; + if (!err && evaluate_type(ctx, frame, 0, e->script, &value) < 0) err = errno; if (!err) { e->can_assign = value.remote; e->type_class = value.type_class; @@ -2260,7 +2263,7 @@ static void command_evaluate_cache_client(void * x) { memset(&value, 0, sizeof(value)); if (expression_context_id(args->id, &ctx, &frame, &expr) < 0) err = errno; if (!err && frame != STACK_NO_FRAME && !ctx->stopped) err = ERR_IS_RUNNING; - if (!err && evaluate_expression(ctx, frame, expr->script, 0, &value) < 0) err = errno; + if (!err && evaluate_expression(ctx, frame, 0, expr->script, 0, &value) < 0) err = errno; if (value.size >= 0x100000) err = ERR_BUFFER_OVERFLOW; cache_exit(); @@ -2346,7 +2349,7 @@ static void command_assign_cache_client(void * x) { memset(&value, 0, sizeof(value)); if (expression_context_id(args->id, &ctx, &frame, &expr) < 0) err = errno; if (!err && frame != STACK_NO_FRAME && !ctx->stopped) err = ERR_IS_RUNNING; - if (!err && evaluate_expression(ctx, frame, expr->script, 0, &value) < 0) err = errno; + if (!err && evaluate_expression(ctx, frame, 0, expr->script, 0, &value) < 0) err = errno; if (!err && !value.remote) err = ERR_INV_EXPRESSION; if (!err && context_write_mem(ctx, value.address, args->value_buf, args->value_size) < 0) err = errno; diff --git a/services/expressions.h b/services/expressions.h index dbf0fc35..a88b9d19 100644 --- a/services/expressions.h +++ b/services/expressions.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -47,10 +47,15 @@ typedef int ExpressionIdentifierCallBack(Context *, int /*frame*/, char * /*name /* * Evaluate given expression in given context. - * If load != 0 then result value is always loaded into a local buffer. + * 'ctx' - debug context to use for memory access and symbols lookup. + * 'frame' - stack frame to use for registers and local variables values. + * 'addr' - instruction address for symbols lookup, ignored if frame != STACK_NO_FRAME. + * 's' - the expression text. + * If load != 0 then result value is always loaded into a local buffer, + * otherwise 'v' can point to a value in the target memory. * Return 0 if no errors, otherwise return -1 and sets errno. */ -extern int evaluate_expression(Context * ctx, int frame, char * s, int load, Value * v); +extern int evaluate_expression(Context * ctx, int frame, ContextAddress addr, char * s, int load, Value * v); /* * Cast a Value to a boolean - 0 or 1. diff --git a/services/symbols.c b/services/symbols.c index 172b06ce..ab0f1166 100644 --- a/services/symbols.c +++ b/services/symbols.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -271,6 +271,7 @@ static void command_get_children(char * token, Channel * c) { typedef struct CommandFindByNameArgs { char token[256]; char id[256]; + ContextAddress ip; char * name; } CommandFindByNameArgs; @@ -286,7 +287,7 @@ static void command_find_by_name_cache_client(void * x) { if (ctx == NULL) err = set_errno(ERR_INV_CONTEXT, args->id); else if (ctx->exited) err = ERR_ALREADY_EXITED; - if (err == 0 && find_symbol_by_name(ctx, frame, args->name, &sym) < 0) err = errno; + if (err == 0 && find_symbol_by_name(ctx, frame, args->ip, args->name, &sym) < 0) err = errno; cache_exit(); @@ -311,6 +312,10 @@ static void command_find_by_name(char * token, Channel * c) { json_read_string(&c->inp, args.id, sizeof(args.id)); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + if (peek_stream(&c->inp) != '"' && peek_stream(&c->inp) != 'n') { + args.ip = (ContextAddress)json_read_uint64(&c->inp); + if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); + } args.name = json_read_alloc_string(&c->inp); if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX); if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX); diff --git a/services/symbols.h b/services/symbols.h index ccb75a56..2fbc8b6f 100644 --- a/services/symbols.h +++ b/services/symbols.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -59,7 +59,7 @@ typedef void EnumerateSymbolsCallBack(void *, Symbol *); * On error, returns -1 and sets errno. * On success returns 0. */ -extern int find_symbol_by_name(Context * ctx, int frame, char * name, Symbol ** sym); +extern int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol ** sym); /* * Find symbol information for given address in given context. diff --git a/services/symbols_elf.c b/services/symbols_elf.c index 3bfb40e9..f4851bf0 100644 --- a/services/symbols_elf.c +++ b/services/symbols_elf.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -330,7 +330,7 @@ static int find_by_name_in_sym_table(DWARFCache * cache, char * name, Symbol ** return cnt == 1; } -int find_symbol_by_name(Context * ctx, int frame, char * name, Symbol ** res) { +int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol ** res) { int error = 0; int found = 0; diff --git a/services/symbols_proxy.c b/services/symbols_proxy.c index 98f9e967..51b8cf75 100644 --- a/services/symbols_proxy.c +++ b/services/symbols_proxy.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -430,7 +430,7 @@ static void validate_find(Channel * c, void * args, int error) { if (trap.error) exception(trap.error); } -int find_symbol_by_name(Context * ctx, int frame, char * name, Symbol ** sym) { +int find_symbol_by_name(Context * ctx, int frame, ContextAddress addr, char * name, Symbol ** sym) { uint64_t ip = 0; LINK * l = NULL; SymbolsCache * syms = NULL; @@ -442,6 +442,7 @@ int find_symbol_by_name(Context * ctx, int frame, char * name, Symbol ** sym) { if (frame == STACK_NO_FRAME) { ctx = context_get_group(ctx, CONTEXT_GROUP_PROCESS); + ip = addr; } else { StackFrame * info = NULL; @@ -503,6 +504,8 @@ int find_symbol_by_name(Context * ctx, int frame, char * name, Symbol ** sym) { json_write_string(&c->out, ctx->id); } write_stream(&c->out, 0); + json_write_uint64(&c->out, ip); + write_stream(&c->out, 0); json_write_string(&c->out, name); write_stream(&c->out, 0); write_stream(&c->out, MARKER_EOM); diff --git a/services/symbols_win32.c b/services/symbols_win32.c index 864323e7..aa7df58f 100644 --- a/services/symbols_win32.c +++ b/services/symbols_win32.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2010 Wind River Systems, Inc. and others. + * Copyright (c) 2007, 2011 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. @@ -116,9 +116,12 @@ static SymbolCacheEntry symbol_cache[SYMBOL_CACHE_SIZE]; static char * tmp_buf = NULL; static int tmp_buf_size = 0; -static int get_stack_frame(Context * ctx, int frame, IMAGEHLP_STACK_FRAME * stack_frame) { +static int get_stack_frame(Context * ctx, int frame, ContextAddress ip, IMAGEHLP_STACK_FRAME * stack_frame) { memset(stack_frame, 0, sizeof(IMAGEHLP_STACK_FRAME)); - if (frame != STACK_NO_FRAME && ctx->parent != NULL) { + if (frame == STACK_NO_FRAME) { + stack_frame->InstructionOffset = ip; + } + else if (ctx->parent != NULL) { uint64_t v = 0; StackFrame * frame_info; if (get_frame_info(ctx, frame, &frame_info) < 0) return -1; @@ -806,8 +809,8 @@ static void add_cache_symbol(HANDLE process, ULONG64 pc, PCSTR name, Symbol * sy } } -static int set_pe_context(Context * ctx, int frame, HANDLE process, IMAGEHLP_STACK_FRAME * stack_frame) { - if (get_stack_frame(ctx, frame, stack_frame) < 0) return -1; +static int set_pe_context(Context * ctx, int frame, ContextAddress ip, HANDLE process, IMAGEHLP_STACK_FRAME * stack_frame) { + if (get_stack_frame(ctx, frame, ip, stack_frame) < 0) return -1; if (!SymSetContext(process, stack_frame, NULL)) { DWORD err = GetLastError(); @@ -816,7 +819,7 @@ static int set_pe_context(Context * ctx, int frame, HANDLE process, IMAGEHLP_STA } else if (err == ERROR_MOD_NOT_FOUND && frame != STACK_NO_FRAME) { /* No local symbols data, search global scope */ - if (get_stack_frame(ctx, STACK_NO_FRAME, stack_frame) < 0) return -1; + if (get_stack_frame(ctx, STACK_NO_FRAME, 0, stack_frame) < 0) return -1; if (!SymSetContext(process, stack_frame, NULL)) { err = GetLastError(); if (err != ERROR_SUCCESS) { @@ -838,14 +841,14 @@ static int set_pe_context(Context * ctx, int frame, HANDLE process, IMAGEHLP_STA return 0; } -static int find_pe_symbol_by_name(Context * ctx, int frame, char * name, Symbol * sym) { +static int find_pe_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol * sym) { HANDLE process = get_context_handle(ctx->parent == NULL ? ctx : ctx->parent); ULONG64 buffer[(sizeof(SYMBOL_INFO) + MAX_SYM_NAME * sizeof(TCHAR) + sizeof(ULONG64) - 1) / sizeof(ULONG64)]; SYMBOL_INFO * info = (SYMBOL_INFO *)buffer; IMAGEHLP_STACK_FRAME stack_frame; DWORD err; - if (set_pe_context(ctx, frame, process, &stack_frame) < 0) return -1; + if (set_pe_context(ctx, frame, ip, process, &stack_frame) < 0) return -1; memset(info, 0, sizeof(SYMBOL_INFO)); info->SizeOfStruct = sizeof(SYMBOL_INFO); @@ -882,7 +885,7 @@ static int find_pe_symbol_by_addr(Context * ctx, int frame, ContextAddress addr, IMAGEHLP_STACK_FRAME stack_frame; DWORD err; - if (set_pe_context(ctx, frame, process, &stack_frame) < 0) return -1; + if (set_pe_context(ctx, frame, 0, process, &stack_frame) < 0) return -1; memset(info, 0, sizeof(SYMBOL_INFO)); info->SizeOfStruct = sizeof(SYMBOL_INFO); @@ -915,12 +918,12 @@ static int find_basic_type_symbol(Context * ctx, char * name, Symbol * sym) { return -1; } -int find_symbol_by_name(Context * ctx, int frame, char * name, Symbol ** sym) { +int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, char * name, Symbol ** sym) { int found = 0; *sym = alloc_symbol(); (*sym)->ctx = ctx; if (frame == STACK_TOP_FRAME && (frame = get_top_frame(ctx)) < 0) return -1; - if (find_pe_symbol_by_name(ctx, frame, name, *sym) >= 0) found = 1; + if (find_pe_symbol_by_name(ctx, frame, ip, name, *sym) >= 0) found = 1; else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) return -1; #if ENABLE_RCBP_TEST if (!found) { @@ -987,7 +990,7 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_ if (frame == STACK_TOP_FRAME) frame = get_top_frame(ctx); if (frame == STACK_TOP_FRAME) return -1; - if (get_stack_frame(ctx, frame, &stack_frame) < 0) return -1; + if (get_stack_frame(ctx, frame, 0, &stack_frame) < 0) return -1; if (!SymSetContext(process, &stack_frame, NULL)) { DWORD err = GetLastError(); |