diff options
author | Eugene Tarassov | 2011-11-22 22:36:31 +0000 |
---|---|---|
committer | Eugene Tarassov | 2011-11-22 22:36:31 +0000 |
commit | ab275578b73691a8ee94743f0f8d8f10f741c8b7 (patch) | |
tree | a10d23189858d8afe008ddb4fe34cd7760684763 /agent/tcf/services | |
parent | 80c2e8900c49cb99e0b4835a43eb0e6b2b291f98 (diff) | |
download | org.eclipse.tcf.agent-ab275578b73691a8ee94743f0f8d8f10f741c8b7.tar.gz org.eclipse.tcf.agent-ab275578b73691a8ee94743f0f8d8f10f741c8b7.tar.xz org.eclipse.tcf.agent-ab275578b73691a8ee94743f0f8d8f10f741c8b7.zip |
TCF Agent: added DWARF 4 support.
Diffstat (limited to 'agent/tcf/services')
-rw-r--r-- | agent/tcf/services/dwarf.h | 7 | ||||
-rw-r--r-- | agent/tcf/services/dwarfcache.c | 22 | ||||
-rw-r--r-- | agent/tcf/services/dwarfcache.h | 8 | ||||
-rw-r--r-- | agent/tcf/services/dwarfexpr.c | 12 | ||||
-rw-r--r-- | agent/tcf/services/dwarfexpr.h | 3 | ||||
-rw-r--r-- | agent/tcf/services/dwarfio.c | 97 | ||||
-rw-r--r-- | agent/tcf/services/expressions.c | 28 | ||||
-rw-r--r-- | agent/tcf/services/linenumbers_elf.c | 9 | ||||
-rw-r--r-- | agent/tcf/services/symbols_elf.c | 26 | ||||
-rw-r--r-- | agent/tcf/services/tcf_elf.h | 2 | ||||
-rw-r--r-- | agent/tcf/services/vm.c | 29 | ||||
-rw-r--r-- | agent/tcf/services/vm.h | 2 |
12 files changed, 177 insertions, 68 deletions
diff --git a/agent/tcf/services/dwarf.h b/agent/tcf/services/dwarf.h index 0b6873c4..142d76c8 100644 --- a/agent/tcf/services/dwarf.h +++ b/agent/tcf/services/dwarf.h @@ -113,6 +113,10 @@ #define FORM_REF8 0x0014 #define FORM_REF_UDATA 0x0015 #define FORM_INDIRECT 0x0016 +#define FORM_SEC_OFFSET 0x0017 /* v4 */ +#define FORM_EXPRLOC 0x0018 /* v4 */ +#define FORM_FLAG_PRESENT 0x0019 /* v4 */ +#define FORM_REF_SIG8 0x0020 /* v4 */ #define AT_sibling 0x0001 #define AT_location 0x0002 @@ -375,6 +379,8 @@ #define OP_call_ref 0x9a #define OP_call_frame_cfa 0x9c #define OP_bit_piece 0x9d +#define OP_implicit_value 0x9e /* v4 */ +#define OP_stack_value 0x9f /* v4 */ #define OP_lo_user 0xe0 #define OP_hi_user 0xff @@ -490,6 +496,7 @@ #define DW_LNE_end_sequence 1 #define DW_LNE_set_address 2 #define DW_LNE_define_file 3 +#define DW_LNE_set_discriminator 4 /* v4 */ #define DW_LNE_lo_user 0x80 /* v3 */ #define DW_LNE_hi_user 0xff /* v3 */ diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c index ffa97b81..2fa9d063 100644 --- a/agent/tcf/services/dwarfcache.c +++ b/agent/tcf/services/dwarfcache.c @@ -765,11 +765,13 @@ 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->mPieces != NULL || Value->mRegister != NULL) { - str_exception(ERR_INV_CONTEXT, "Constant DWARF attribute value expected"); + if (Value->mPieces != NULL || Value->mRegister != NULL || + (Value->mAddr != NULL && Value->mForm == FORM_EXPR_VALUE)) { + str_exception(ERR_INV_DWARF, "Constant DWARF attribute value expected"); } else if (Value->mAddr != NULL) { size_t i; + if (Value->mSize > 8) str_exception(ERR_INV_DWARF, "Invalid size of DWARF attribute value"); for (i = 0; i < Value->mSize; i++) { Res = (Res << 8) | Value->mAddr[Value->mBigEndian ? i : Value->mSize - i - 1]; } @@ -1152,20 +1154,24 @@ static void load_line_numbers_v1(CompUnit * Unit, U4_T unit_size) { } static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) { + U2_T version = 0; U8_T header_pos = 0; U1_T opcode_base = 0; U1_T opcode_size[256]; U8_T header_size = 0; U1_T min_instruction_length = 0; + U1_T max_ops_per_instruction = 1; U1_T is_stmt_default = 0; I1_T line_base = 0; U1_T line_range = 0; LineNumbersState state; - dio_ReadU2(); /* line info version */ + version = dio_ReadU2(); + if (version < 2 || version > 4) str_exception(ERR_INV_DWARF, "Invalid line number info version"); header_size = dwarf64 ? dio_ReadU8() : (U8_T)dio_ReadU4(); header_pos = dio_GetPos(); min_instruction_length = dio_ReadU1(); + if (version >= 4) max_ops_per_instruction = dio_ReadU1(); is_stmt_default = dio_ReadU1() != 0; line_base = (I1_T)dio_ReadU1(); line_range = dio_ReadU1(); @@ -1204,10 +1210,13 @@ static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) { while (dio_GetPos() < Unit->mLineInfoOffs + unit_size) { U1_T opcode = dio_ReadU1(); if (opcode >= opcode_base) { - state.mLine += (unsigned)((int)((opcode - opcode_base) % line_range) + line_base); - state.mAddress += (opcode - opcode_base) / line_range * min_instruction_length; + unsigned op_advance = (opcode - opcode_base) / line_range; + state.mLine += (U4_T)((int)((opcode - opcode_base) % line_range) + line_base); + state.mAddress += (state.mOpIndex + op_advance) / max_ops_per_instruction * min_instruction_length; + state.mOpIndex = (state.mOpIndex + op_advance) % max_ops_per_instruction; add_state(Unit, &state); state.mFlags &= ~(LINE_BasicBlock | LINE_PrologueEnd | LINE_EpilogueBegin); + state.mDiscriminator = 0; } else if (opcode == 0) { U4_T op_size = dio_ReadULEB128(); @@ -1241,6 +1250,9 @@ static void load_line_numbers_v2(CompUnit * Unit, U8_T unit_size, int dwarf64) { if (s != Unit->mTextSection) state.mAddress = 0; } break; + case DW_LNE_set_discriminator: + state.mDiscriminator = dio_ReadULEB128(); + break; default: dio_Skip(op_size - 1); break; diff --git a/agent/tcf/services/dwarfcache.h b/agent/tcf/services/dwarfcache.h index 59b5bb47..6797b9ac 100644 --- a/agent/tcf/services/dwarfcache.h +++ b/agent/tcf/services/dwarfcache.h @@ -130,6 +130,7 @@ struct PropertyValuePiece { int mBigEndian; ContextAddress mAddress; RegisterDefinition * mRegister; + U1_T * mValue; U4_T mBitOffset; U4_T mBitSize; }; @@ -164,6 +165,8 @@ struct LineNumbersState { U2_T mColumn; U1_T mFlags; U1_T mISA; + U1_T mOpIndex; + U1_T mDiscriminator; }; struct CompUnit { @@ -266,7 +269,10 @@ extern UnitAddressRange * find_comp_unit_addr_range(DWARFCache * cache, ContextA */ extern void read_and_evaluate_dwarf_object_property(Context * ctx, int frame, U8_T base, ObjectInfo * obj, U2_T attr_tag, PropertyValue * value); -/* Convert PropertyValue to a number */ +/* + * Convert PropertyValue to a number. + * Note: result of location expression evaluation can be converted only if the expression represents a memory address. + */ extern U8_T get_numeric_property_value(PropertyValue * Value); /* diff --git a/agent/tcf/services/dwarfexpr.c b/agent/tcf/services/dwarfexpr.c index 1ebce6c8..016af6ac 100644 --- a/agent/tcf/services/dwarfexpr.c +++ b/agent/tcf/services/dwarfexpr.c @@ -98,6 +98,7 @@ static ObjectInfo * get_parent_function(ObjectInfo * Info) { while (Info != NULL) { switch (Info->mTag) { case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: @@ -204,6 +205,11 @@ static void evaluate_expression(ELF_Section * Section, U1_T * Buf, size_t Size) Piece->mRegister = sState.reg; Piece->mBigEndian = sState.reg->big_endian; } + else if (sState.value_addr) { + Piece->mValue = (U1_T *)sState.value_addr; + if (sState.value_size * 8 < sState.piece_bits) str_exception(ERR_INV_DWARF, "Invalid object piece size"); + Piece->mBigEndian = sState.big_endian; + } else { Piece->mAddress = sState.stk[--sState.stk_pos]; Piece->mBigEndian = sState.big_endian; @@ -304,6 +310,7 @@ void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) { evaluate_expression(Unit->mDesc.mSection, sValue->mAddr, sValue->mSize); } + sValue->mForm = FORM_EXPR_VALUE; sValue->mAddr = NULL; sValue->mValue = 0; sValue->mSize = 0; @@ -321,6 +328,11 @@ void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) { sValue->mBigEndian = sState.reg->big_endian; sValue->mRegister = sState.reg; } + else if (sState.value_addr) { + sValue->mAddr = (U1_T *)sState.value_addr; + sValue->mSize = sState.value_size; + sValue->mBigEndian = sState.big_endian; + } else { sValue->mValue = sState.stk[--sState.stk_pos]; } diff --git a/agent/tcf/services/dwarfexpr.h b/agent/tcf/services/dwarfexpr.h index 7fde2b62..1ebbd484 100644 --- a/agent/tcf/services/dwarfexpr.h +++ b/agent/tcf/services/dwarfexpr.h @@ -27,6 +27,9 @@ #include <tcf/services/dwarfcache.h> +/* PropertyValue format for expresson evaluation results */ +#define FORM_EXPR_VALUE 0x00ff + extern void dwarf_evaluate_expression(U8_T base, PropertyValue * value); #endif /* ENABLE_ELF && ENABLE_DebugContext */ diff --git a/agent/tcf/services/dwarfio.c b/agent/tcf/services/dwarfio.c index a545fe87..eef9b448 100644 --- a/agent/tcf/services/dwarfio.c +++ b/agent/tcf/services/dwarfio.c @@ -412,27 +412,33 @@ void dio_ReadAttribute(U2_T Attr, U2_T Form) { return; } switch (Form) { - case FORM_ADDR : dio_ReadFormAddr(); break; - case FORM_REF : dio_ReadFormRef(); break; - case FORM_BLOCK1 : dio_ReadFormBlock(dio_ReadU1()); break; - case FORM_BLOCK2 : dio_ReadFormBlock(dio_ReadU2()); break; - case FORM_BLOCK4 : dio_ReadFormBlock(dio_ReadU4()); break; - case FORM_BLOCK : dio_ReadFormBlock(dio_ReadULEB128()); break; - case FORM_DATA1 : dio_ReadFormData(1, dio_ReadU1()); break; - case FORM_DATA2 : dio_ReadFormData(2, dio_ReadU2()); break; - case FORM_DATA4 : dio_ReadFormData(4, dio_ReadU4()); break; - case FORM_DATA8 : dio_ReadFormData(8, dio_ReadU8()); break; - case FORM_SDATA : dio_ReadFormData(8, dio_ReadS8LEB128()); dio_gFormDataAddr = NULL; break; - case FORM_UDATA : dio_ReadFormData(8, dio_ReadU8LEB128()); dio_gFormDataAddr = NULL; break; - case FORM_FLAG : dio_ReadFormData(1, dio_ReadU1()); break; - case FORM_STRING : dio_ReadFormString(); break; - case FORM_STRP : dio_ReadFormStringRef(); break; - case FORM_REF_ADDR : dio_ReadFormRefAddr(); break; - case FORM_REF1 : dio_ReadFormRelRef(dio_ReadU1()); break; - case FORM_REF2 : dio_ReadFormRelRef(dio_ReadU2()); break; - case FORM_REF4 : dio_ReadFormRelRef(dio_ReadU4()); break; - case FORM_REF8 : dio_ReadFormRelRef(dio_ReadU8()); break; - case FORM_REF_UDATA : dio_ReadFormRelRef(dio_ReadULEB128()); break; + case FORM_ADDR : dio_ReadFormAddr(); break; + case FORM_REF : dio_ReadFormRef(); break; + case FORM_BLOCK1 : dio_ReadFormBlock(dio_ReadU1()); break; + case FORM_BLOCK2 : dio_ReadFormBlock(dio_ReadU2()); break; + case FORM_BLOCK4 : dio_ReadFormBlock(dio_ReadU4()); break; + case FORM_BLOCK : dio_ReadFormBlock(dio_ReadULEB128()); break; + case FORM_DATA1 : dio_ReadFormData(1, dio_ReadU1()); break; + case FORM_DATA2 : dio_ReadFormData(2, dio_ReadU2()); break; + case FORM_DATA4 : dio_ReadFormData(4, dio_ReadU4()); break; + case FORM_DATA8 : dio_ReadFormData(8, dio_ReadU8()); break; + case FORM_SDATA : dio_ReadFormData(8, dio_ReadS8LEB128()); dio_gFormDataAddr = NULL; break; + case FORM_UDATA : dio_ReadFormData(8, dio_ReadU8LEB128()); dio_gFormDataAddr = NULL; break; + case FORM_FLAG : dio_ReadFormData(1, dio_ReadU1()); break; + case FORM_FLAG_PRESENT : dio_ReadFormData(0, 1); break; + case FORM_STRING : dio_ReadFormString(); break; + case FORM_STRP : dio_ReadFormStringRef(); break; + case FORM_REF_ADDR : dio_ReadFormRefAddr(); break; + case FORM_REF1 : dio_ReadFormRelRef(dio_ReadU1()); break; + case FORM_REF2 : dio_ReadFormRelRef(dio_ReadU2()); break; + case FORM_REF4 : dio_ReadFormRelRef(dio_ReadU4()); break; + case FORM_REF8 : dio_ReadFormRelRef(dio_ReadU8()); break; + case FORM_REF_UDATA : dio_ReadFormRelRef(dio_ReadULEB128()); break; + case FORM_SEC_OFFSET: if (sUnit->m64bit) dio_ReadFormData(8, dio_ReadU8()); + else dio_ReadFormData(4, dio_ReadU4()); + break; + case FORM_EXPRLOC : dio_ReadFormBlock(dio_ReadULEB128()); break; + case FORM_REF_SIG8 : dio_ReadFormData(8, dio_ReadU8()); break; default: str_exception(ERR_INV_DWARF, "invalid FORM"); } } @@ -504,27 +510,31 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) { break; default: switch (Form) { - case FORM_ADDR : sDataPos += sAddressSize; continue; - case FORM_REF : sDataPos += 4; continue; - case FORM_BLOCK1 : sDataPos += dio_ReadU1F(); continue; - case FORM_BLOCK2 : sDataPos += dio_ReadU2(); continue; - case FORM_BLOCK4 : sDataPos += dio_ReadU4(); continue; - case FORM_BLOCK : sDataPos += dio_ReadULEB128(); continue; - case FORM_DATA1 : sDataPos++; continue; - case FORM_DATA2 : sDataPos += 2; continue; - case FORM_DATA4 : sDataPos += 4; continue; - case FORM_DATA8 : sDataPos += 8; continue; - case FORM_SDATA : dio_ReadS8LEB128(); continue; - case FORM_UDATA : dio_ReadU8LEB128(); continue; - case FORM_FLAG : sDataPos++; continue; - case FORM_STRING : dio_ReadFormString(); continue; - case FORM_STRP : sDataPos += (sUnit->m64bit ? 8 : 4); continue; - case FORM_REF_ADDR : sDataPos += sRefAddressSize; continue; - case FORM_REF1 : sDataPos++; continue; - case FORM_REF2 : sDataPos += 2; continue; - case FORM_REF4 : sDataPos += 4; continue; - case FORM_REF8 : sDataPos += 8; continue; - case FORM_REF_UDATA : dio_ReadULEB128(); continue; + case FORM_ADDR : sDataPos += sAddressSize; continue; + case FORM_REF : sDataPos += 4; continue; + case FORM_BLOCK1 : sDataPos += dio_ReadU1F(); continue; + case FORM_BLOCK2 : sDataPos += dio_ReadU2(); continue; + case FORM_BLOCK4 : sDataPos += dio_ReadU4(); continue; + case FORM_BLOCK : sDataPos += dio_ReadULEB128(); continue; + case FORM_DATA1 : sDataPos++; continue; + case FORM_DATA2 : sDataPos += 2; continue; + case FORM_DATA4 : sDataPos += 4; continue; + case FORM_DATA8 : sDataPos += 8; continue; + case FORM_SDATA : dio_ReadS8LEB128(); continue; + case FORM_UDATA : dio_ReadU8LEB128(); continue; + case FORM_FLAG : sDataPos++; continue; + case FORM_FLAG_PRESENT : continue; + case FORM_STRING : dio_ReadFormString(); continue; + case FORM_STRP : sDataPos += (sUnit->m64bit ? 8 : 4); continue; + case FORM_REF_ADDR : sDataPos += sRefAddressSize; continue; + case FORM_REF1 : sDataPos++; continue; + case FORM_REF2 : sDataPos += 2; continue; + case FORM_REF4 : sDataPos += 4; continue; + case FORM_REF8 : sDataPos += 8; continue; + case FORM_REF_UDATA : dio_ReadULEB128(); continue; + case FORM_SEC_OFFSET : sDataPos += (sUnit->m64bit ? 8 : 4); continue; + case FORM_EXPRLOC : sDataPos += dio_ReadULEB128(); continue; + case FORM_REF_SIG8 : sDataPos += 8; continue; } } } @@ -694,7 +704,8 @@ static void dio_FindAbbrevTable(void) { void dio_ChkFlag(U2_T Form) { switch (Form) { - case FORM_FLAG : + case FORM_FLAG : + case FORM_FLAG_PRESENT : return; } str_exception(ERR_INV_DWARF, "FORM_FLAG expected"); diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c index 126c99dd..e4240e3e 100644 --- a/agent/tcf/services/expressions.c +++ b/agent/tcf/services/expressions.c @@ -593,7 +593,7 @@ static void set_value_endianness(Value * v, Symbol * sym, Symbol * type) { } /* Note: sym2value() does NOT set v->size if v->sym != NULL */ -static int sym2value(Symbol * sym, Value * v) { +static int sym2value(int mode, Symbol * sym, Value * v) { int sym_class = 0; memset(v, 0, sizeof(Value)); if (get_symbol_class(sym, &sym_class) < 0) { @@ -624,7 +624,7 @@ static int sym2value(Symbol * sym, Value * v) { } break; case SYM_CLASS_REFERENCE: - if (get_symbol_address(sym, &v->address) < 0) { + if (mode == MODE_NORMAL && get_symbol_address(sym, &v->address) < 0) { int endianness = 0; size_t size = 0; void * value = NULL; @@ -647,16 +647,16 @@ static int sym2value(Symbol * sym, Value * v) { } else { set_value_endianness(v, sym, v->type); - v->sym = sym; v->remote = 1; } + v->sym = sym; break; case SYM_CLASS_FUNCTION: { ContextAddress word = 0; v->type_class = TYPE_CLASS_CARDINAL; if (v->type != NULL) get_array_symbol(v->type, 0, &v->type); - if (get_symbol_address(sym, &word) < 0) { + if (mode == MODE_NORMAL && get_symbol_address(sym, &word) < 0) { error(errno, "Cannot retrieve symbol address"); } set_ctx_word_value(v, word); @@ -671,7 +671,7 @@ static int sym2value(Symbol * sym, Value * v) { } #endif -static int identifier(Value * scope, char * name, Value * v) { +static int identifier(int mode, Value * scope, char * name, Value * v) { int i; memset(v, 0, sizeof(Value)); if (scope == NULL) { @@ -710,7 +710,7 @@ static int identifier(Value * scope, char * name, Value * v) { if (get_error_code(errno) != ERR_SYM_NOT_FOUND) error(errno, "Cannot read symbol data"); } else { - return sym2value(sym, v); + return sym2value(mode, sym, v); } } #elif ENABLE_RCBP_TEST @@ -733,7 +733,7 @@ static int qualified_name(int mode, Value * scope, Value * v) { for (;;) { if (text_sy != SY_NAME) error(ERR_INV_EXPRESSION, "Identifier expected"); if (mode != MODE_SKIP) { - sym_class = identifier(scope, (char *)text_val.value, v); + sym_class = identifier(mode, scope, (char *)text_val.value, v); if (sym_class < 0) error(ERR_INV_EXPRESSION, "Undefined identifier '%s'", text_val.value); } else { @@ -818,7 +818,7 @@ static int type_name(int mode, Symbol ** type) { next_sy(); } while (text_sy == SY_NAME); - sym_class = identifier(NULL, name, &v); + sym_class = identifier(mode, NULL, name, &v); if (sym_class < 0) return 0; if (text_sy == SY_SCOPE) { Value scope = v; @@ -1108,7 +1108,7 @@ static void primary_expression(int mode, Value * v) { if (!ok) { Symbol * sym = NULL; if (id2symbol(id, &sym) >= 0) { - int sym_class = sym2value(sym, v); + int sym_class = sym2value(mode, sym, v); if (sym_class == SYM_CLASS_TYPE) error(ERR_INV_EXPRESSION, "Illegal usage of type '%s'", id); ok = 1; } @@ -1224,7 +1224,7 @@ static void op_field(int mode, Value * v) { v->type_class = TYPE_CLASS_CARDINAL; get_symbol_type(sym, &v->type); if (v->type != NULL) get_array_symbol(v->type, 0, &v->type); - if (get_symbol_address(sym, &word) < 0) { + if (mode == MODE_NORMAL && get_symbol_address(sym, &word) < 0) { error(errno, "Cannot retrieve symbol address"); } set_ctx_word_value(v, word); @@ -2620,6 +2620,14 @@ static void command_evaluate_cache_client(void * x) { json_write_string(&c->out, symbol2id(value.type)); cnt++; } + + if (value.sym != NULL) { + if (cnt > 0) write_stream(&c->out, ','); + json_write_string(&c->out, "Symbol"); + write_stream(&c->out, ':'); + json_write_string(&c->out, symbol2id(value.sym)); + cnt++; + } #endif if (value.reg != NULL) { if (cnt > 0) write_stream(&c->out, ','); diff --git a/agent/tcf/services/linenumbers_elf.c b/agent/tcf/services/linenumbers_elf.c index 9cdf9f61..22107bb3 100644 --- a/agent/tcf/services/linenumbers_elf.c +++ b/agent/tcf/services/linenumbers_elf.c @@ -199,7 +199,13 @@ int line_to_address(Context * ctx, char * file_name, int line, int column, h = calc_file_name_hash(fnm); while (file != NULL) { Trap trap; - /* TODO: support for separate debug info files */ + if (file->debug_info_file_name != NULL && !file->debug_info_file) { + ELF_File * debug = elf_open(file->debug_info_file_name); + if (debug != NULL) { + debug->debug_info_file = 1; + file = debug; + } + } if (set_trap(&trap)) { DWARFCache * cache = get_dwarf_cache(file); ObjectInfo * info = cache->mCompUnits; @@ -223,6 +229,7 @@ int line_to_address(Context * ctx, char * file_name, int line, int column, } else { err = trap.error; + trace(LOG_ALWAYS, "Cannot load DWARF line numbers section: %s", err); break; } file = elf_list_next(ctx); diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c index eaee5c84..f4b01dad 100644 --- a/agent/tcf/services/symbols_elf.c +++ b/agent/tcf/services/symbols_elf.c @@ -218,6 +218,7 @@ static void object2symbol(ObjectInfo * obj, Symbol ** res) { sym->obj = obj; switch (obj->mTag) { case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: @@ -281,6 +282,7 @@ static ObjectInfo * get_object_type(ObjectInfo * obj) { if (obj != NULL) { switch (obj->mTag) { case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: @@ -435,11 +437,11 @@ static int find_in_object_tree(ObjectInfo * list, ContextAddress rt_offs, Contex find_in_object_tree(obj->mChildren, 0, 0, name, &sym_enu); break; case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: case TAG_lexical_block: - case TAG_inlined_subroutine: if (ip != 0 && check_in_range(obj, rt_offs, ip)) { if (find_in_object_tree(obj->mChildren, rt_offs, ip, name, sym)) return 1; } @@ -820,11 +822,11 @@ static int find_by_addr_in_unit(ObjectInfo * obj, int level, ContextAddress rt_o while (obj != NULL) { switch (obj->mTag) { case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: case TAG_lexical_block: - case TAG_inlined_subroutine: if (check_in_range(obj, rt_offs, addr)) { object2symbol(obj, res); return 1; @@ -928,11 +930,11 @@ static void enumerate_local_vars(ObjectInfo * obj, int level, ContextAddress rt_ while (obj != NULL) { switch (obj->mTag) { case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: case TAG_lexical_block: - case TAG_inlined_subroutine: if (check_in_range(obj, rt_offs, sym_ip)) { enumerate_local_vars(obj->mChildren, level + 1, rt_offs, call_back, args); } @@ -1350,6 +1352,7 @@ int get_symbol_type_class(const Symbol * sym, int * type_class) { while (obj != NULL) { switch (obj->mTag) { case TAG_global_subroutine: + case TAG_inlined_subroutine: case TAG_subroutine: case TAG_subprogram: case TAG_entry_point: @@ -1872,7 +1875,7 @@ int get_symbol_offset(const Symbol * sym, ContextAddress * offset) { *offset = (ContextAddress)v; return 0; } - errno = ERR_INV_CONTEXT; + set_errno(ERR_OTHER, "Symbol does not have a member offset"); return -1; } @@ -1932,6 +1935,7 @@ 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); + assert(v.mForm == FORM_EXPR_VALUE); if (v.mPieces != NULL) { U4_T n = 0; U4_T bf_offs = 0; @@ -1951,6 +1955,9 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big 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 (piece->mValue) { + memcpy(pbf, piece->mValue, piece_size); + } else { if (context_read_mem(v.mContext, piece->mAddress, pbf, piece_size) < 0) exception(errno); } @@ -1993,8 +2000,13 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big *size = val_size; *big_endian = def->big_endian; } + else if (v.mAddr != NULL) { + *value = v.mAddr; + *size = v.mSize; + *big_endian = v.mBigEndian; + } else { - exception(ERR_INV_CONTEXT); + str_exception(ERR_OTHER, "Invalid object location data"); } clear_trap(&trap); return 0; @@ -2029,7 +2041,7 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big *big_endian = big_endian_host(); return 0; } - errno = ERR_INV_CONTEXT; + set_errno(ERR_OTHER, "Symbol does not have a value"); return -1; } @@ -2120,7 +2132,7 @@ int get_symbol_address(const Symbol * sym, ContextAddress * address) { return syminfo2address(sym_ctx, &info, address); } - errno = ERR_INV_CONTEXT; + set_errno(ERR_OTHER, "Symbol does not have a memory address"); return -1; } diff --git a/agent/tcf/services/tcf_elf.h b/agent/tcf/services/tcf_elf.h index 3a4217a8..644a9ab7 100644 --- a/agent/tcf/services/tcf_elf.h +++ b/agent/tcf/services/tcf_elf.h @@ -407,7 +407,7 @@ struct ELF_File { int age; int listed; - int debug_info_file; + int debug_info_file; /* 1 means this file contains debug info only - no code */ char * debug_info_file_name; }; diff --git a/agent/tcf/services/vm.c b/agent/tcf/services/vm.c index 056ef891..cdb3b89e 100644 --- a/agent/tcf/services/vm.c +++ b/agent/tcf/services/vm.c @@ -142,6 +142,8 @@ static void set_state(VMState * s) { code_pos = state->code_pos; code_len = state->code_len; state->reg = NULL; + state->value_addr = NULL; + state->value_size = 0; state->piece_offs = 0; state->piece_bits = 0; } @@ -549,6 +551,7 @@ static void evaluate_expression(void) { state->piece_offs = 0; if (code_pos < code_len && state->piece_bits == 0) { if (state->reg) state->reg = NULL; + else if (state->value_addr) state->value_addr = NULL; else state->stk_pos--; } break; @@ -557,10 +560,36 @@ static void evaluate_expression(void) { state->piece_offs = read_u4leb128(); if (code_pos < code_len && state->piece_bits == 0) { if (state->reg) state->reg = NULL; + else if (state->value_addr) state->value_addr = NULL; else state->stk_pos--; state->piece_offs = 0; } break; + case OP_implicit_value: + state->value_size = read_u4leb128(); + if (code_pos + state->value_size > code_len) inv_dwarf("Invalid command"); + state->value_addr = tmp_alloc(state->value_size); + memcpy(state->value_addr, code + code_pos, state->value_size); + code_pos += state->value_size; + if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_implicit_value must be last instruction"); + break; + case OP_stack_value: + check_e_stack(1); + state->stk_pos--; + state->value_size = sizeof(uint64_t); + state->value_addr = tmp_alloc(state->value_size); + memcpy(state->value_addr, state->stk + state->stk_pos, state->value_size); + if (code_pos < code_len && code[code_pos] != OP_piece) inv_dwarf("OP_stack_value must be last instruction"); + if (big_endian_host() != state->big_endian) { + size_t i, j, n = state->value_size >> 1; + char * p = (char *)state->value_addr; + for (i = 0, j = state->value_size - 1; i < n; i++, j--) { + char x = p[i]; + p[i] = p[j]; + p[j] = x; + } + } + break; case OP_call2: case OP_call4: case OP_call_ref: diff --git a/agent/tcf/services/vm.h b/agent/tcf/services/vm.h index 3e3e0d57..b541c511 100644 --- a/agent/tcf/services/vm.h +++ b/agent/tcf/services/vm.h @@ -42,6 +42,8 @@ typedef struct VMState { /* Result */ RegisterDefinition * reg; + void * value_addr; + size_t value_size; uint32_t piece_offs; uint32_t piece_bits; |