blob: 76b02c9d25e62d68521b49439d5ffe90ed083d49 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2013 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
*******************************************************************************/
/*
* This module implements DWARF expressions evaluation.
*/
#include <tcf/config.h>
#if ENABLE_ELF && ENABLE_DebugContext
#include <assert.h>
#include <tcf/framework/myalloc.h>
#include <tcf/framework/exceptions.h>
#include <tcf/framework/errors.h>
#include <tcf/services/dwarf.h>
#include <tcf/services/dwarfexpr.h>
#include <tcf/services/dwarfecomp.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/vm.h>
void dwarf_get_expression_list(PropertyValue * Value, DWARFExpressionInfo ** List) {
CompUnit * Unit = Value->mObject->mCompUnit;
if (Value->mAddr == NULL || Value->mSize == 0) str_exception(ERR_INV_DWARF, "Invalid format of location expression");
if (Value->mForm == FORM_DATA4 || Value->mForm == FORM_DATA8 || Value->mForm == FORM_SEC_OFFSET) {
U8_T Base = 0;
U8_T Offset = 0;
U8_T AddrMax = ~(U8_T)0;
DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache;
DWARFExpressionInfo * Last = NULL;
assert(Cache->magic == DWARF_CACHE_MAGIC);
if (Cache->mDebugLoc == NULL) str_exception(ERR_INV_DWARF, "Missing .debug_loc section");
dio_EnterSection(&Unit->mDesc, Unit->mDesc.mSection, Value->mAddr - (U1_T *)Unit->mDesc.mSection->data);
Offset = dio_ReadAddressX(NULL, Value->mSize);
dio_ExitSection();
Base = Unit->mObject->u.mCode.mLowPC;
if (Unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << Unit->mDesc.mAddressSize * 8) - 1;
dio_EnterSection(&Unit->mDesc, Cache->mDebugLoc, Offset);
for (;;) {
ELF_Section * S0 = NULL;
ELF_Section * S1 = NULL;
U8_T Addr0 = dio_ReadAddress(&S0);
U8_T Addr1 = dio_ReadAddress(&S1);
if (Addr0 == AddrMax) {
Base = Addr1;
}
else if (Addr0 == 0 && Addr1 == 0) {
break;
}
else if (Addr0 > Addr1) {
str_exception(ERR_INV_DWARF, "Invalid .debug_loc section");
}
else {
U2_T Size = dio_ReadU2();
U8_T RT_Addr0 = 0;
U8_T RT_Addr1 = 0;
if (S0 == NULL) S0 = Unit->mTextSection;
if (S1 == NULL) S1 = Unit->mTextSection;
RT_Addr0 = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, Base + Addr0);
if (!errno) RT_Addr1 = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S1, Base + Addr1);
if (!errno) {
DWARFExpressionInfo * Info = (DWARFExpressionInfo *)tmp_alloc_zero(sizeof(DWARFExpressionInfo));
Info->object = Value->mObject;
Info->code_addr = RT_Addr0;
Info->code_size = RT_Addr1 - RT_Addr0;
Info->section = Cache->mDebugLoc;
Info->expr_addr = dio_GetDataPtr();
Info->expr_size = Size;
Info->attr = Value->mAttr;
Info->form = Value->mForm;
if (Last == NULL) *List = Info;
else Last->next = Info;
Last = Info;
}
dio_Skip(Size);
}
}
dio_ExitSection();
if (Last == NULL) str_exception(ERR_OTHER, "Object is not available at this location in the code");
}
else {
DWARFExpressionInfo * Info = (DWARFExpressionInfo *)tmp_alloc_zero(sizeof(DWARFExpressionInfo));
Info->object = Value->mObject;
Info->section = Unit->mDesc.mSection;
Info->expr_addr = Value->mAddr;
Info->expr_size = Value->mSize;
Info->attr = Value->mAttr;
Info->form = Value->mForm;
*List = Info;
}
}
void dwarf_evaluate_expression(PropertyValue * Value, uint64_t * args, unsigned args_cnt) {
CompUnit * Unit = Value->mObject->mCompUnit;
LocationExpressionState * State = NULL;
DWARFExpressionInfo * Info = NULL;
State = (LocationExpressionState *)tmp_alloc_zero(sizeof(LocationExpressionState));
State->stk = (U8_T *)tmp_alloc(sizeof(U8_T) * (State->stk_max = 8));
State->ctx = Value->mContext;
if (Value->mFrame != STACK_NO_FRAME &&
get_frame_info(Value->mContext, Value->mFrame, &State->stack_frame) < 0)
exception(errno);
State->addr_size = Unit->mDesc.mAddressSize;
State->reg_id_scope = Unit->mRegIdScope;
State->args = args;
State->args_cnt = args_cnt;
if (Value->mAttr == AT_data_member_location) {
if (args_cnt < 1) str_exception(ERR_INV_ADDRESS, "Invalid address of containing object");
State->stk[State->stk_pos++] = args[0];
}
else if (Value->mAttr == AT_use_location) {
if (args_cnt < 2) str_exception(ERR_INV_ADDRESS, "Invalid address of containing object");
State->stk[State->stk_pos++] = args[1];
State->stk[State->stk_pos++] = args[0];
}
if (Value->mPieces != NULL || Value->mAddr == NULL || Value->mSize == 0) {
str_exception(ERR_INV_DWARF, "Invalid DWARF expression reference");
}
dwarf_get_expression_list(Value, &Info);
dwarf_transform_expression(Value->mContext, Value->mFrame, Info);
State->code = Info->expr_addr;
State->code_len = Info->expr_size;
if (evaluate_vm_expression(State) < 0) exception(errno);
assert(State->code_pos == State->code_len);
Value->mForm = FORM_EXPR_VALUE;
Value->mAddr = NULL;
Value->mValue = 0;
Value->mSize = 0;
Value->mBigEndian = State->reg_id_scope.big_endian;
Value->mPieces = NULL;
Value->mPieceCnt = 0;
if (State->pieces_cnt) {
Value->mPieces = State->pieces;
Value->mPieceCnt = State->pieces_cnt;
}
else {
Value->mValue = State->stk[--State->stk_pos];
}
if (State->stk_pos != 0) {
str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
}
}
#endif /* ENABLE_ELF && ENABLE_DebugContext */