Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2011-11-22 22:36:31 +0000
committerEugene Tarassov2011-11-22 22:36:31 +0000
commitab275578b73691a8ee94743f0f8d8f10f741c8b7 (patch)
treea10d23189858d8afe008ddb4fe34cd7760684763 /agent/tcf/services
parent80c2e8900c49cb99e0b4835a43eb0e6b2b291f98 (diff)
downloadorg.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.h7
-rw-r--r--agent/tcf/services/dwarfcache.c22
-rw-r--r--agent/tcf/services/dwarfcache.h8
-rw-r--r--agent/tcf/services/dwarfexpr.c12
-rw-r--r--agent/tcf/services/dwarfexpr.h3
-rw-r--r--agent/tcf/services/dwarfio.c97
-rw-r--r--agent/tcf/services/expressions.c28
-rw-r--r--agent/tcf/services/linenumbers_elf.c9
-rw-r--r--agent/tcf/services/symbols_elf.c26
-rw-r--r--agent/tcf/services/tcf_elf.h2
-rw-r--r--agent/tcf/services/vm.c29
-rw-r--r--agent/tcf/services/vm.h2
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;

Back to the top