diff options
author | eutarass | 2011-08-31 21:21:44 +0000 |
---|---|---|
committer | eutarass | 2011-08-31 21:21:44 +0000 |
commit | 7463eb8579edff3124184ee51beb6ba2e22aec5e (patch) | |
tree | d2959411bb71d6661fc5d0b378c6f307e31f3774 | |
parent | 840c6a544350f23f2f439be5bb8d8d3b11430e23 (diff) | |
download | org.eclipse.tcf.agent-7463eb8579edff3124184ee51beb6ba2e22aec5e.tar.gz org.eclipse.tcf.agent-7463eb8579edff3124184ee51beb6ba2e22aec5e.tar.xz org.eclipse.tcf.agent-7463eb8579edff3124184ee51beb6ba2e22aec5e.zip |
TCF Agent: added support for OP_piece and OP_bit_piece in DWARF location expressions.
-rw-r--r-- | services/dwarfcache.c | 4 | ||||
-rw-r--r-- | services/dwarfcache.h | 11 | ||||
-rw-r--r-- | services/dwarfexpr.c | 105 | ||||
-rw-r--r-- | services/symbols_elf.c | 83 |
4 files changed, 177 insertions, 26 deletions
diff --git a/services/dwarfcache.c b/services/dwarfcache.c index 06b1cfdc..e4ba697c 100644 --- a/services/dwarfcache.c +++ b/services/dwarfcache.c @@ -737,8 +737,8 @@ static void get_object_property_callback(U2_T Tag, U2_T Attr, U2_T Form) { U8_T get_numeric_property_value(PropertyValue * Value) { U8_T Res = 0; - if (Value->mRegister != NULL) { - str_exception(ERR_INV_CONTEXT, "Register variable"); + if (Value->mPieces != NULL || Value->mRegister != NULL) { + str_exception(ERR_INV_CONTEXT, "Constant DWARF attribute value expected"); } else if (Value->mAddr != NULL) { size_t i; diff --git a/services/dwarfcache.h b/services/dwarfcache.h index e7665754..93bec126 100644 --- a/services/dwarfcache.h +++ b/services/dwarfcache.h @@ -38,6 +38,7 @@ typedef struct PubNamesInfo PubNamesInfo; typedef struct PubNamesTable PubNamesTable; typedef struct ObjectArray ObjectArray; typedef struct SymbolInfo SymbolInfo; +typedef struct PropertyValuePiece PropertyValuePiece; typedef struct PropertyValue PropertyValue; typedef struct LineNumbersState LineNumbersState; typedef struct CompUnit CompUnit; @@ -118,6 +119,14 @@ struct PubNamesTable { unsigned mMax; }; +struct PropertyValuePiece { + int mBigEndian; + ContextAddress mAddress; + RegisterDefinition * mRegister; + U4_T mBitOffset; + U4_T mBitSize; +}; + struct PropertyValue { Context * mContext; int mFrame; @@ -129,6 +138,8 @@ struct PropertyValue { size_t mSize; int mBigEndian; RegisterDefinition * mRegister; + PropertyValuePiece * mPieces; + U4_T mPieceCnt; }; #define LINE_IsStmt 0x01 diff --git a/services/dwarfexpr.c b/services/dwarfexpr.c index 6def5985..33b8c9bc 100644 --- a/services/dwarfexpr.c +++ b/services/dwarfexpr.c @@ -23,6 +23,7 @@ #include <assert.h> #include <stdio.h> +#include <framework/events.h> #include <framework/myalloc.h> #include <framework/exceptions.h> #include <framework/errors.h> @@ -33,10 +34,58 @@ #include <services/stacktrace.h> #include <services/vm.h> +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; @@ -81,6 +130,7 @@ static U8_T get_fbreg(void) { { PropertyValue * OrgValue = sValue; + ValuePieces * OrgValuePieces = sValuePieces; ELF_Section * OrgSection = sSection; U8_T OrgSectionOffs = sSectionOffs; VMState OrgState = sState; @@ -97,6 +147,7 @@ static U8_T get_fbreg(void) { sState.object_address = OrgState.object_address; sSectionOffs = OrgSectionOffs; sSection = OrgSection; + sValuePieces = OrgValuePieces; sValue = OrgValue; } @@ -138,13 +189,34 @@ static void evaluate_expression(ELF_Section * Section, U1_T * Buf, size_t Size) 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); - if (sState.reg) { - sValue->mSize = sState.reg->size; - sValue->mBigEndian = sState.reg->big_endian; - sValue->mRegister = sState.reg; - } } static void evaluate_location(void) { @@ -200,6 +272,7 @@ void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) { 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; @@ -229,12 +302,26 @@ void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) { evaluate_expression(Unit->mDesc.mSection, sValue->mAddr, sValue->mSize); } - if (sValue->mRegister == NULL) { - assert(sState.stk_pos > 0); + 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]; - sValue->mSize = 0; } - sValue->mAddr = NULL; if (sState.stk_pos != stk_pos) { str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack"); diff --git a/services/symbols_elf.c b/services/symbols_elf.c index 9fccf9ce..b142a71a 100644 --- a/services/symbols_elf.c +++ b/services/symbols_elf.c @@ -1757,22 +1757,29 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big if (obj != NULL) { Trap trap; PropertyValue v; + static U1_T * bf = NULL; + static size_t bf_size = 0; if (set_trap(&trap)) { read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_const_value, &v); if (v.mAddr != NULL) { *size = v.mSize; *value = v.mAddr; } + else if (v.mRegister != NULL || v.mPieces != NULL) { + str_exception(ERR_INV_CONTEXT, "Constant DWARF attribute value expected"); + } else { - static U1_T bf[sizeof(v.mValue)]; U8_T n = v.mValue; size_t i = 0; - if (v.mRegister != NULL) exception(ERR_INV_CONTEXT); - for (i = 0; i < sizeof(bf); i++) { - bf[v.mBigEndian ? sizeof(bf) - i - 1 : i] = n & 0xffu; + if (bf_size < sizeof(v.mValue)) { + bf_size = sizeof(v.mValue); + bf = (U1_T *)loc_realloc(bf, bf_size); + } + for (i = 0; i < sizeof(v.mValue); i++) { + bf[v.mBigEndian ? sizeof(v.mValue) - i - 1 : i] = n & 0xffu; n = n >> 8; } - *size = sizeof(bf); + *size = sizeof(v.mValue); *value = bf; } *big_endian = v.mBigEndian; @@ -1784,11 +1791,48 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big } if (set_trap(&trap)) { read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_location, &v); - if (v.mRegister == NULL) { - exception(ERR_INV_CONTEXT); + if (v.mPieces != NULL) { + U4_T n = 0; + U4_T bf_offs = 0; + while (n < v.mPieceCnt) { + U4_T i; + U1_T pbf[32]; + PropertyValuePiece * piece = v.mPieces + n++; + U4_T piece_size = (piece->mBitSize + 7) / 8; + if (piece_size > sizeof(pbf)) exception(ERR_BUFFER_OVERFLOW); + if (bf_size < bf_offs / 8 + piece_size + 1) { + bf_size = bf_offs / 8 + piece_size + 1; + bf = (U1_T *)loc_realloc(bf, bf_size); + } + if (piece->mRegister) { + StackFrame * frame = NULL; + RegisterDefinition * def = piece->mRegister; + if (get_frame_info(v.mContext, v.mFrame, &frame) < 0) exception(errno); + if (read_reg_bytes(frame, def, 0, piece_size, pbf) < 0) exception(errno); + } + else { + if (context_read_mem(v.mContext, piece->mAddress, pbf, piece_size) < 0) exception(errno); + } + if (!piece->mBigEndian != !v.mBigEndian) swap_bytes(pbf, piece_size); + for (i = piece->mBitOffset; i < piece->mBitOffset + piece->mBitSize; i++) { + if (pbf[i / 8] & (1u << (i % 8))) { + bf[bf_offs / 8] |= (1u << (bf_offs % 8)); + } + else { + bf[bf_offs / 8] &= ~(1u << (bf_offs % 8)); + } + bf_offs++; + } + } + while (bf_offs % 8) { + bf[bf_offs / 8] &= ~(1u << (bf_offs % 8)); + bf_offs++; + } + *value = bf; + *size = bf_offs / 8; + *big_endian = v.mBigEndian; } - else { - static U1_T bf[32]; + else if (v.mRegister != NULL) { StackFrame * frame = NULL; RegisterDefinition * def = v.mRegister; ContextAddress sym_size = def->size; @@ -1796,7 +1840,10 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big unsigned val_size = 0; if (get_symbol_size(sym, &sym_size) < 0) exception(errno); - if (sym_size > sizeof(bf)) exception(ERR_BUFFER_OVERFLOW); + if (bf_size < sym_size) { + bf_size = (size_t)sym_size; + bf = (U1_T *)loc_realloc(bf, bf_size); + } if (get_frame_info(v.mContext, v.mFrame, &frame) < 0) exception(errno); val_size = def->size < sym_size ? (unsigned)def->size : (unsigned)sym_size; if (def->big_endian) val_offs = (unsigned)def->size - val_size; @@ -1805,6 +1852,9 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big *size = val_size; *big_endian = def->big_endian; } + else { + exception(ERR_INV_CONTEXT); + } clear_trap(&trap); return 0; } @@ -1884,17 +1934,20 @@ int get_symbol_address(const Symbol * sym, ContextAddress * address) { if (!set_trap(&trap)) return -1; if ((type->mTag != TAG_pointer_type && type->mTag != TAG_mod_pointer) || type->mType == NULL) exception(ERR_INV_CONTEXT); read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, sym->var, AT_location, &v); - if (v.mRegister == NULL) { - if (elf_read_memory_word(sym_ctx, sym->var->mCompUnit->mFile, - (ContextAddress)get_numeric_property_value(&v), &base) < 0) exception(errno); + if (v.mPieces != NULL) { + str_exception(ERR_UNSUPPORTED, "Unsupported location of 'this' pointer"); } - else { + else if (v.mRegister != NULL) { U8_T rv = 0; StackFrame * frame = NULL; if (get_frame_info(v.mContext, v.mFrame, &frame) < 0) exception(errno); if (read_reg_value(frame, v.mRegister, &rv) < 0) exception(errno); base = (ContextAddress)rv; } + else { + if (elf_read_memory_word(sym_ctx, sym->var->mCompUnit->mFile, + (ContextAddress)get_numeric_property_value(&v), &base) < 0) exception(errno); + } type = get_original_type(type->mType); if (!calc_member_offset(type, obj, &offs)) exception(ERR_INV_CONTEXT); clear_trap(&trap); @@ -1938,8 +1991,8 @@ int get_symbol_register(const Symbol * sym, Context ** ctx, int * frame, Registe if (unpack(sym) < 0) return -1; if (obj != NULL && obj->mTag != TAG_member && obj->mTag != TAG_inheritance) { Trap trap; - PropertyValue v; if (set_trap(&trap)) { + PropertyValue v; read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_location, &v); *ctx = sym_ctx; *frame = sym_frame; |