blob: 7cbab8579ee227d0cffa7b4f4d8f10b278e0587f [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012, 2014 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.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* Wind River Systems - initial API and implementation
*******************************************************************************/
/*
* Symbols service - common code that is shared between different implementations of the service.
*/
#include <tcf/config.h>
#if SERVICE_Symbols || ENABLE_SymbolsProxy
#include <tcf/framework/myalloc.h>
#include <tcf/framework/exceptions.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/symbols.h>
#include <tcf/services/vm.h>
static LocationInfo * loc_info = NULL;
static LocationExpressionState * evaluate_symbol_location(const Symbol * sym, unsigned args_cnt) {
Trap trap;
Context * ctx = NULL;
int frame = STACK_NO_FRAME;
StackFrame * frame_info = NULL;
LocationExpressionState * state = NULL;
static uint64_t args[] = { 0, 0 };
if (get_symbol_frame(sym, &ctx, &frame) < 0) return NULL;
if (get_location_info(sym, &loc_info) < 0) return NULL;
if (loc_info->args_cnt != args_cnt) {
set_errno(ERR_OTHER, "Wrong object kind");
return NULL;
}
if (frame != STACK_NO_FRAME && get_frame_info(ctx, frame, &frame_info) < 0) return NULL;
if (!set_trap(&trap)) return NULL;
state = evaluate_location_expression(ctx, frame_info,
loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, args, args_cnt);
clear_trap(&trap);
return state;
}
int get_symbol_address(const Symbol * sym, ContextAddress * address) {
LocationExpressionState * state = evaluate_symbol_location(sym, 0);
if (state == NULL) return -1;
if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0 &&
state->pieces->reg == NULL && state->pieces->value == NULL &&
state->pieces->bit_offs == 0) {
*address = state->pieces->addr;
return 0;
}
if (state->pieces_cnt > 0) {
set_errno(ERR_OTHER, "Cannot get object address: the symbol is a bit field");
return -1;
}
if (state->stk_pos == 1) {
*address = (ContextAddress)state->stk[0];
return 0;
}
set_errno(ERR_OTHER, "Object does not have memory address");
return -1;
}
int get_symbol_offset(const Symbol * sym, ContextAddress * offset) {
LocationExpressionState * state = evaluate_symbol_location(sym, 1);
if (state == NULL) return -1;
if (state->pieces_cnt == 1 && state->pieces->implicit_pointer == 0 &&
state->pieces->reg == NULL && state->pieces->value == NULL &&
state->pieces->bit_offs == 0) {
*offset = state->pieces->addr;
return 0;
}
if (state->pieces_cnt > 0) {
set_errno(ERR_OTHER, "Cannot get member offset: the symbol is a bit field");
return -1;
}
if (state->stk_pos == 1) {
*offset = (ContextAddress)state->stk[0];
return 0;
}
set_errno(ERR_OTHER, "Object does not have member offset");
return -1;
}
int get_symbol_register(const Symbol * sym, Context ** ctx, int * frame, RegisterDefinition ** reg) {
LocationExpressionState * state = evaluate_symbol_location(sym, 0);
if (state == NULL) return -1;
if (state->pieces_cnt == 1 && state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
if (get_symbol_frame(sym, ctx, frame) < 0) return -1;
*reg = state->pieces->reg;
return 0;
}
set_errno(ERR_OTHER, "Symbol is not located in a register");
return -1;
}
int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big_endian) {
Trap trap;
LocationExpressionState * state = evaluate_symbol_location(sym, 0);
if (state == NULL) return -1;
if (!set_trap(&trap)) return -1;
if (state->pieces_cnt > 0) {
read_location_pieces(state->ctx, state->stack_frame,
state->pieces, state->pieces_cnt, loc_info->big_endian, value, size);
}
else {
ContextAddress sym_size = 0;
size_t buf_size = 0;
void * buf = NULL;
if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid location expression");
if (get_symbol_size(sym, &sym_size) < 0) exception(errno);
buf_size = (size_t)sym_size;
buf = tmp_alloc(buf_size);
if (context_read_mem(state->ctx, (ContextAddress)state->stk[0], buf, buf_size) < 0) exception(errno);
*value = buf;
*size = buf_size;
}
*big_endian = loc_info->big_endian;
clear_trap(&trap);
return 0;
}
#endif