From a107edc216f94c5ec059fdf74541908bc7e979bb Mon Sep 17 00:00:00 2001 From: Eugene Tarassov Date: Thu, 10 Nov 2011 17:19:02 -0800 Subject: Agent code is moved into separate "agent" directory, all C code moved into "tcf" directory. --- agent/tcf/services/dwarfexpr.c | 333 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 333 insertions(+) create mode 100644 agent/tcf/services/dwarfexpr.c (limited to 'agent/tcf/services/dwarfexpr.c') diff --git a/agent/tcf/services/dwarfexpr.c b/agent/tcf/services/dwarfexpr.c new file mode 100644 index 00000000..48dee578 --- /dev/null +++ b/agent/tcf/services/dwarfexpr.c @@ -0,0 +1,333 @@ +/******************************************************************************* + * Copyright (c) 2008, 2010 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 + +#if ENABLE_ELF && ENABLE_DebugContext + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct ValuePieces { + U4_T mCnt; + U4_T mMax; + PropertyValuePiece * mArray; + struct ValuePieces * mNext; +} ValuePieces; + +static VMState sState; +static ELF_Section * sSection = NULL; +static U8_T sSectionOffs = 0; +static PropertyValue * sValue = NULL; +static ValuePieces * sValuePieces = NULL; + +static ValuePieces * sFreeValuePieces = NULL; +static ValuePieces * sBusyValuePieces = NULL; +static unsigned sValuePiecesCnt = 0; +static int sValuePiecesPosted = 0; + +static void free_value_pieces(void * args) { + while (sBusyValuePieces != NULL) { + ValuePieces * Pieces = sBusyValuePieces; + sBusyValuePieces = Pieces->mNext; + Pieces->mNext = sFreeValuePieces; + sFreeValuePieces = Pieces; + } + while (sFreeValuePieces != NULL && sValuePiecesCnt > 16) { + ValuePieces * Pieces = sFreeValuePieces; + sFreeValuePieces = sFreeValuePieces->mNext; + sValuePiecesCnt--; + loc_free(Pieces->mArray); + loc_free(Pieces); + } +} + +static ValuePieces * alloc_value_pieces(void) { + ValuePieces * Pieces = sFreeValuePieces; + if (Pieces == NULL) { + Pieces = (ValuePieces *)loc_alloc_zero(sizeof(ValuePieces)); + sValuePiecesCnt++; + } + else { + sFreeValuePieces = sFreeValuePieces->mNext; + } + Pieces->mNext = sBusyValuePieces; + sBusyValuePieces = Pieces; + if (!sValuePiecesPosted && sValuePiecesCnt > 8) { + post_event(free_value_pieces, NULL); + sValuePiecesPosted = 1; + } + Pieces->mCnt = 0; + return Pieces; +} + +static StackFrame * get_stack_frame(PropertyValue * sValue) { + StackFrame * Info = NULL; + if (sValue->mFrame == STACK_NO_FRAME) return NULL; + if (get_frame_info(sValue->mContext, sValue->mFrame, &Info) < 0) exception(errno); + return Info; +} + +static ObjectInfo * get_parent_function(ObjectInfo * Info) { + while (Info != NULL) { + switch (Info->mTag) { + case TAG_global_subroutine: + case TAG_subroutine: + case TAG_subprogram: + case TAG_entry_point: + return Info; + } + Info = Info->mParent; + } + return NULL; +} + +static U8_T read_address(void) { + U8_T addr = 0; + ELF_Section * section = NULL; + CompUnit * Unit = sValue->mObject->mCompUnit; + + addr = dio_ReadAddress(§ion); + addr = elf_map_to_run_time_address(sState.ctx, Unit->mFile, section, (ContextAddress)addr); + if (addr == 0) str_exception(ERR_INV_ADDRESS, "Object has no RT address"); + return addr; +} + +static U8_T get_fbreg(void) { + PropertyValue FP; + CompUnit * Unit = sValue->mObject->mCompUnit; + ObjectInfo * Parent = get_parent_function(sValue->mObject); + U8_T addr = 0; + + if (Parent == NULL) str_exception(ERR_INV_DWARF, "OP_fbreg: no parent function"); + memset(&FP, 0, sizeof(FP)); + + { + PropertyValue * OrgValue = sValue; + ValuePieces * OrgValuePieces = sValuePieces; + ELF_Section * OrgSection = sSection; + U8_T OrgSectionOffs = sSectionOffs; + VMState OrgState = sState; + + read_and_evaluate_dwarf_object_property(sState.ctx, sState.stack_frame, 0, Parent, AT_frame_base, &FP); + + assert(sState.ctx == OrgState.ctx); + assert(sState.addr_size == OrgState.addr_size); + assert(sState.big_endian == OrgState.big_endian); + + sState.code = OrgState.code; + sState.code_pos = OrgState.code_pos; + sState.code_len = OrgState.code_len; + sState.object_address = OrgState.object_address; + sSectionOffs = OrgSectionOffs; + sSection = OrgSection; + sValuePieces = OrgValuePieces; + sValue = OrgValue; + } + + if (FP.mRegister != NULL) { + if (read_reg_value(get_stack_frame(&FP), FP.mRegister, &addr) < 0) exception(errno); + } + else { + addr = get_numeric_property_value(&FP); + } + dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs + sState.code_pos); + return addr + dio_ReadS8LEB128(); +} + +static void client_op(uint8_t op) { + dio_SetPos(sSectionOffs + sState.code_pos); + switch (op) { + case OP_addr: + sState.stk[sState.stk_pos++] = read_address(); + break; + case OP_fbreg: + if (sState.stack_frame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "Invalid stack frame"); + sState.stk[sState.stk_pos++] = get_fbreg(); + break; + default: + trace(LOG_ALWAYS, "Unsupported DWARF expression op 0x%02x", op); + str_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op"); + } + sState.code_pos = (size_t)(dio_GetPos() - sSectionOffs); +} + +static void evaluate_expression(ELF_Section * Section, U1_T * Buf, size_t Size) { + int error = 0; + CompUnit * Unit = sValue->mObject->mCompUnit; + + sState.code = Buf; + sState.code_len = Size; + sState.code_pos = 0; + sSection = Section; + sSectionOffs = Buf - (U1_T *)Section->data; + dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs); + if (evaluate_vm_expression(&sState) < 0) error = errno; + if (!error && sState.piece_bits) { + sValuePieces = alloc_value_pieces(); + while (!error) { + PropertyValuePiece * Piece; + if (sValuePieces->mCnt >= sValuePieces->mMax) { + sValuePieces->mMax += 8; + sValuePieces->mArray = (PropertyValuePiece *)loc_realloc(sValuePieces->mArray, + sizeof(PropertyValuePiece) * sValuePieces->mMax); + } + Piece = sValuePieces->mArray + sValuePieces->mCnt++; + memset(Piece, 0, sizeof(PropertyValuePiece)); + if (sState.reg) { + Piece->mRegister = sState.reg; + Piece->mBigEndian = sState.reg->big_endian; + } + else { + Piece->mAddress = sState.stk[--sState.stk_pos]; + Piece->mBigEndian = sState.big_endian; + } + Piece->mBitOffset = sState.piece_offs; + Piece->mBitSize = sState.piece_bits; + if (sState.code_pos >= sState.code_len) break; + if (evaluate_vm_expression(&sState) < 0) error = errno; + } + } + dio_ExitSection(); + assert(error || sState.code_pos == sState.code_len); + if (error) exception(error); +} + +static void evaluate_location(void) { + U8_T IP = 0; + U8_T Offset = 0; + U8_T Base = 0; + CompUnit * Unit = sValue->mObject->mCompUnit; + DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache; + U8_T AddrMax = ~(U8_T)0; + + 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, sValue->mAddr - (U1_T *)Unit->mDesc.mSection->data); + Offset = dio_ReadUX(sValue->mSize); + dio_ExitSection(); + Base = Unit->mLowPC; + if (Unit->mDesc.mAddressSize < 8) AddrMax = ((U8_T)1 << Unit->mDesc.mAddressSize * 8) - 1; + if (read_reg_value(get_stack_frame(sValue), get_PC_definition(sValue->mContext), &IP) < 0) exception(errno); + 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 (S0 == NULL) S0 = Unit->mTextSection; + if (S1 == NULL) S1 = Unit->mTextSection; + if (Addr0 == AddrMax) { + Base = Addr1; + } + else if (Addr0 == 0 && Addr1 == 0) { + break; + } + else if (S0 != S1 || Addr0 > Addr1) { + str_exception(ERR_INV_DWARF, "Invalid .debug_loc section"); + } + else { + U2_T Size = dio_ReadU2(); + U8_T RTAddr0 = elf_map_to_run_time_address(sValue->mContext, Unit->mFile, S0, (ContextAddress)(Base + Addr0)); + U8_T RTAddr1 = Addr1 - Addr0 + RTAddr0; + if (RTAddr0 != 0 && IP >= RTAddr0 && IP < RTAddr1) { + U1_T * Buf = dio_GetDataPtr(); + dio_ExitSection(); + evaluate_expression(Cache->mDebugLoc, Buf, Size); + return; + } + dio_Skip(Size); + } + } + dio_ExitSection(); + str_exception(ERR_OTHER, "Object is not available at this location in the code"); +} + +void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) { + unsigned stk_pos = 0; + CompUnit * Unit = v->mObject->mCompUnit; + + sValue = v; + sValuePieces = NULL; + sState.ctx = sValue->mContext; + sState.addr_size = Unit->mDesc.mAddressSize; + sState.big_endian = Unit->mFile->big_endian; + sState.stack_frame = sValue->mFrame; + sState.reg_id_scope = Unit->mRegIdScope; + sState.object_address = BaseAddress; + sState.client_op = client_op;; + + if (sValue->mAttr != AT_frame_base) sState.stk_pos = 0; + stk_pos = sState.stk_pos; + + if (sValue->mAttr == AT_data_member_location) { + if (sState.stk_pos >= sState.stk_max) { + sState.stk_max += 8; + sState.stk = (U8_T *)loc_alloc(sizeof(U8_T) * sState.stk_max); + } + sState.stk[sState.stk_pos++] = BaseAddress; + } + if (sValue->mRegister != NULL || sValue->mAddr == NULL || sValue->mSize == 0) { + str_exception(ERR_INV_DWARF, "invalid DWARF expression reference"); + } + if (sValue->mForm == FORM_DATA4 || sValue->mForm == FORM_DATA8) { + if (sValue->mFrame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "need stack frame"); + evaluate_location(); + } + else { + evaluate_expression(Unit->mDesc.mSection, sValue->mAddr, sValue->mSize); + } + + sValue->mAddr = NULL; + sValue->mValue = 0; + sValue->mSize = 0; + sValue->mBigEndian = sState.big_endian; + sValue->mRegister = NULL; + sValue->mPieces = NULL; + sValue->mPieceCnt = 0; + + if (sValuePieces) { + sValue->mPieces = sValuePieces->mArray; + sValue->mPieceCnt = sValuePieces->mCnt; + } + else if (sState.reg) { + sValue->mSize = sState.reg->size; + sValue->mBigEndian = sState.reg->big_endian; + sValue->mRegister = sState.reg; + } + else { + sValue->mValue = sState.stk[--sState.stk_pos]; + } + + if (sState.stk_pos != stk_pos) { + str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack"); + } +} + +#endif /* ENABLE_ELF && ENABLE_DebugContext */ -- cgit v1.2.3