Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--agent/agent.vcproj8
-rw-r--r--agent/cmake/build-gcc-debug.sh5
-rw-r--r--agent/tcf/framework/cpudefs.c91
-rw-r--r--agent/tcf/framework/cpudefs.h108
-rw-r--r--agent/tcf/main/test.c1
-rw-r--r--agent/tcf/services/dwarf.h10
-rw-r--r--agent/tcf/services/dwarfcache.c99
-rw-r--r--agent/tcf/services/dwarfcache.h42
-rw-r--r--agent/tcf/services/dwarfecomp.c346
-rw-r--r--agent/tcf/services/dwarfecomp.h34
-rw-r--r--agent/tcf/services/dwarfexpr.c288
-rw-r--r--agent/tcf/services/dwarfexpr.h17
-rw-r--r--agent/tcf/services/dwarfframe.c96
-rw-r--r--agent/tcf/services/dwarfframe.h6
-rw-r--r--agent/tcf/services/dwarfio.c14
-rw-r--r--agent/tcf/services/elf-loader.c2
-rw-r--r--agent/tcf/services/expressions.c135
-rw-r--r--agent/tcf/services/linenumbers.h4
-rw-r--r--agent/tcf/services/linenumbers_elf.c64
-rw-r--r--agent/tcf/services/pathmap.c9
-rw-r--r--agent/tcf/services/stacktrace.c2
-rw-r--r--agent/tcf/services/symbols.c32
-rw-r--r--agent/tcf/services/symbols.h42
-rw-r--r--agent/tcf/services/symbols_elf.c567
-rw-r--r--agent/tcf/services/symbols_proxy.c114
-rw-r--r--agent/tcf/services/symbols_win32.c61
-rw-r--r--agent/tcf/services/vm.c145
-rw-r--r--agent/tcf/services/vm.h32
-rw-r--r--server/server.vcproj48
-rw-r--r--tests/test-dwarf/dwarf-test.vcproj8
-rw-r--r--tests/test-dwarf/tcf/backend/backend.c132
32 files changed, 1796 insertions, 767 deletions
diff --git a/.gitignore b/.gitignore
index f4fc061d..4512374f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,7 +15,6 @@ agent/vc++
agent/cmake/msvc-debug
agent/cmake/msvc-release
agent/cmake/gcc-release
-agent/cmake/build-gcc-debug.sh
agent/cmake/gcc-debug
# server/
diff --git a/agent/agent.vcproj b/agent/agent.vcproj
index f13dd7c6..786d1fd3 100644
--- a/agent/agent.vcproj
+++ b/agent/agent.vcproj
@@ -664,6 +664,14 @@
>
</File>
<File
+ RelativePath=".\tcf\services\dwarfecomp.c"
+ >
+ </File>
+ <File
+ RelativePath=".\tcf\services\dwarfecomp.h"
+ >
+ </File>
+ <File
RelativePath=".\tcf\services\dwarfexpr.c"
>
</File>
diff --git a/agent/cmake/build-gcc-debug.sh b/agent/cmake/build-gcc-debug.sh
new file mode 100644
index 00000000..c75c3366
--- /dev/null
+++ b/agent/cmake/build-gcc-debug.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+[ -d gcc-debug ] || mkdir gcc-debug
+cd gcc-debug
+[ -f Makefile ] || cmake -DCMAKE_BUILD_TYPE=Debug -G "Unix Makefiles" ../..
+make $*
diff --git a/agent/tcf/framework/cpudefs.c b/agent/tcf/framework/cpudefs.c
index 56442fd9..77f45e84 100644
--- a/agent/tcf/framework/cpudefs.c
+++ b/agent/tcf/framework/cpudefs.c
@@ -213,101 +213,134 @@ int id2register(const char * id, Context ** ctx, int * frame, RegisterDefinition
return 0;
}
-static void stack_trace_error(void) {
+static void location_expression_error(void) {
str_exception(ERR_OTHER, "Invalid stack trace program");
}
-uint64_t evaluate_stack_trace_commands(Context * ctx, StackFrame * frame, StackTracingCommandSequence * cmds) {
- static uint64_t * stk = NULL;
- static int stk_size = 0;
+LocationExpressionState * evaluate_location_expression(Context * ctx, StackFrame * frame,
+ LocationExpressionCommand * cmds, unsigned cmd_cnt,
+ uint64_t * args, unsigned args_cnt) {
+ unsigned i;
+ unsigned stk_pos = 0;
+ unsigned stk_max = 0;
+ uint64_t * stk = NULL;
+ LocationExpressionState * state = (LocationExpressionState *)tmp_alloc_zero(sizeof(LocationExpressionState));
- int i;
- int stk_pos = 0;
-
- for (i = 0; i < cmds->cmds_cnt; i++) {
- StackTracingCommand * cmd = cmds->cmds + i;
- if (stk_pos >= stk_size) {
- stk_size += 4;
- stk = (uint64_t *)loc_realloc(stk, sizeof(uint64_t) * stk_size);
+ state->ctx = ctx;
+ state->stack_frame = frame;
+ state->args = args;
+ state->args_cnt = args_cnt;
+ for (i = 0; i < cmd_cnt; i++) {
+ LocationExpressionCommand * cmd = cmds + i;
+ if (stk_pos >= stk_max) {
+ stk_max += 4;
+ stk = (uint64_t *)tmp_realloc(stk, sizeof(uint64_t) * stk_max);
}
switch (cmd->cmd) {
case SFT_CMD_NUMBER:
- stk[stk_pos++] = cmd->num;
+ stk[stk_pos++] = cmd->args.num;
break;
case SFT_CMD_REGISTER:
- if (read_reg_value(frame, cmd->reg, stk + stk_pos) < 0) exception(errno);
+ if (read_reg_value(frame, cmd->args.reg, stk + stk_pos) < 0) exception(errno);
stk_pos++;
break;
case SFT_CMD_FP:
stk[stk_pos++] = frame->fp;
break;
case SFT_CMD_DEREF:
- if (stk_pos < 1) stack_trace_error();
+ if (stk_pos < 1) location_expression_error();
{
size_t j;
- size_t size = cmd->size;
+ size_t size = cmd->args.deref.size;
uint64_t n = 0;
uint8_t buf[8];
if (context_read_mem(ctx, (ContextAddress)stk[stk_pos - 1], buf, size) < 0) exception(errno);
for (j = 0; j < size; j++) {
- n = (n << 8) | buf[cmd->big_endian ? j : size - j - 1];
+ n = (n << 8) | buf[cmd->args.deref.big_endian ? j : size - j - 1];
}
stk[stk_pos - 1] = n;
}
break;
case SFT_CMD_ADD:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] + stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_SUB:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] - stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_AND:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] & stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_OR:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] | stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_GE:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] >= stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_GT:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] > stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_LE:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] <= stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_LT:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] = stk[stk_pos - 2] < stk[stk_pos - 1];
stk_pos--;
break;
case SFT_CMD_SHL:
- if (stk_pos < 2) stack_trace_error();
+ if (stk_pos < 2) location_expression_error();
stk[stk_pos - 2] <<= stk[stk_pos - 1];
stk_pos--;
break;
+ case SFT_CMD_SHR:
+ if (stk_pos < 2) location_expression_error();
+ stk[stk_pos - 2] >>= stk[stk_pos - 1];
+ stk_pos--;
+ break;
+ case SFT_CMD_ARG:
+ if (cmd->args.arg_no >= args_cnt) location_expression_error();
+ stk[stk_pos++] = args[cmd->args.arg_no];
+ break;
+ case SFT_CMD_USER:
+ state->stk = stk;
+ state->stk_pos = stk_pos;
+ state->stk_max = stk_max;
+ state->reg_id_scope = cmd->args.user.reg_id_scope;
+ state->code = cmd->args.user.code_addr;
+ state->code_len = cmd->args.user.code_size;
+ state->code_pos = 0;
+ state->addr_size = cmd->args.user.addr_size;
+ state->big_endian = cmd->args.user.big_endian;
+ state->client_op = NULL;
+ if (cmd->args.user.func(state) < 0) exception(errno);
+ stk_max = state->stk_max;
+ stk_pos = state->stk_pos;
+ stk = state->stk;
+ break;
default:
- stack_trace_error();
+ location_expression_error();
break;
}
}
- if (stk_pos == 0) stack_trace_error();
- return stk[stk_pos - 1];
+ state->stk = stk;
+ state->stk_pos = stk_pos;
+ state->stk_max = stk_max;
+ return state;
}
#endif /* ENABLE_DebugContext */
diff --git a/agent/tcf/framework/cpudefs.h b/agent/tcf/framework/cpudefs.h
index 4040b657..55fa7254 100644
--- a/agent/tcf/framework/cpudefs.h
+++ b/agent/tcf/framework/cpudefs.h
@@ -71,7 +71,14 @@ struct RegisterDefinition {
const char * role; /* the role the register plays in a program execution */
};
-/* Stack tracing command codes */
+typedef struct RegisterIdScope {
+ uint16_t machine;
+ uint8_t os_abi;
+ uint8_t big_endian;
+ uint8_t id_type;
+} RegisterIdScope;
+
+/* Location expression command codes */
#define SFT_CMD_NUMBER 1
#define SFT_CMD_REGISTER 2
#define SFT_CMD_FP 3
@@ -85,32 +92,73 @@ struct RegisterDefinition {
#define SFT_CMD_LE 11
#define SFT_CMD_LT 12
#define SFT_CMD_SHL 13
+#define SFT_CMD_SHR 14
+#define SFT_CMD_ARG 15
+#define SFT_CMD_USER 16
-/* Stack tracing command */
-typedef struct StackTracingCommand {
- int cmd;
- int64_t num;
- size_t size;
+typedef struct LocationPiece {
int big_endian;
+ ContextAddress addr;
RegisterDefinition * reg;
-} StackTracingCommand;
-
-/* Stack tracing command sequence */
-typedef struct StackTracingCommandSequence {
- RegisterDefinition * reg;
- int cmds_cnt;
- int cmds_max;
- StackTracingCommand cmds[1];
-} StackTracingCommandSequence;
+ void * value;
+ size_t size;
+ unsigned bit_offs;
+ unsigned bit_size;
+} LocationPiece;
-/* Complete stack tracing info for a range of instruction addresses */
-typedef struct StackTracingInfo {
- ContextAddress addr;
- ContextAddress size;
- StackTracingCommandSequence * fp;
- StackTracingCommandSequence ** regs;
- int reg_cnt;
-} StackTracingInfo;
+typedef struct LocationExpressionState {
+ /* Evaluation context */
+ Context * ctx;
+ struct StackFrame * stack_frame;
+ RegisterIdScope reg_id_scope;
+ int big_endian;
+ size_t addr_size;
+ uint64_t * args;
+ unsigned args_cnt;
+
+ /* Code to execute */
+ uint8_t * code;
+ size_t code_pos;
+ size_t code_len;
+
+ /* Client callback */
+ void (*client_op)(uint8_t op);
+
+ /* Result */
+ LocationPiece * pieces;
+ unsigned pieces_cnt;
+ unsigned pieces_max;
+
+ /* Evaluation stack */
+ unsigned stk_pos;
+ unsigned stk_max;
+ uint64_t * stk;
+} LocationExpressionState;
+
+typedef struct LocationExpressionCommand LocationExpressionCommand;
+typedef int LocationExpressionCallback(LocationExpressionState *);
+
+/* Location expression command */
+struct LocationExpressionCommand {
+ int cmd;
+ union {
+ int64_t num;
+ RegisterDefinition * reg;
+ struct {
+ size_t size;
+ int big_endian;
+ } deref;
+ struct {
+ LocationExpressionCallback * func;
+ RegisterIdScope reg_id_scope;
+ uint8_t * code_addr;
+ size_t code_size;
+ size_t addr_size;
+ int big_endian;
+ } user;
+ unsigned arg_no;
+ } args;
+};
#define STACK_BOTTOM_FRAME 0
#define STACK_NO_FRAME (-1)
@@ -118,19 +166,13 @@ typedef struct StackTracingInfo {
typedef struct StackFrame {
int is_top_frame;
+ int is_walked; /* Data collected by: 0 - crawl, 1 - walk */
int has_reg_data;
Context * ctx;
ContextAddress fp; /* frame address */
RegisterData * regs; /* register values */
} StackFrame;
-typedef struct RegisterIdScope {
- uint16_t machine;
- uint8_t os_abi;
- uint8_t big_endian;
- uint8_t id_type;
-} RegisterIdScope;
-
/* Return array of CPU register definitions. Last item in the array has name == NULL */
extern RegisterDefinition * get_reg_definitions(Context * ctx);
@@ -186,8 +228,10 @@ extern uint8_t * get_break_instruction(Context * ctx, size_t * size);
*/
extern int crawl_stack_frame(StackFrame * frame, StackFrame * down);
-/* Execute stack tracing command sequence */
-extern uint64_t evaluate_stack_trace_commands(Context * ctx, StackFrame * frame, StackTracingCommandSequence * cmds);
+/* Execute location expression */
+extern LocationExpressionState * evaluate_location_expression(Context * ctx, StackFrame * frame,
+ LocationExpressionCommand * cmds, unsigned cmds_cnt,
+ uint64_t * args, unsigned args_cnt);
#endif /* ENABLE_DebugContext */
diff --git a/agent/tcf/main/test.c b/agent/tcf/main/test.c
index 47a62cb9..974d4e27 100644
--- a/agent/tcf/main/test.c
+++ b/agent/tcf/main/test.c
@@ -59,6 +59,7 @@ public:
int tcf_cpp_test_class::s_int = 1;
int tcf_cpp_test_class::tcf_cpp_test_class_nested::s_int = 2;
tcf_cpp_test_class_extension * tcf_cpp_text_ce = (tcf_cpp_test_class_extension *)3;
+int tcf_cpp_test_class_extension::* tcf_cpp_test_member_ptr = &tcf_cpp_test_class_extension::f_int;
extern "C" {
diff --git a/agent/tcf/services/dwarf.h b/agent/tcf/services/dwarf.h
index 7df3f5c5..20a47e2b 100644
--- a/agent/tcf/services/dwarf.h
+++ b/agent/tcf/services/dwarf.h
@@ -206,7 +206,17 @@
#define AT_call_file 0x0058 /* v3 */
#define AT_call_line 0x0059 /* v3 */
#define AT_description 0x005a /* v3 */
+#define AT_object_pointer 0x0064 /* v3 */
#define AT_endianity 0x0065 /* v3 */
+#define AT_elemental 0x0066 /* v3 */
+#define AT_pure 0x0067 /* v3 */
+#define AT_recursive 0x0068 /* v3 */
+#define AT_signature 0x0069 /* v4 */
+#define AT_main_subprogram 0x006a /* v4 */
+#define AT_data_bit_offset 0x006b /* v4 */
+#define AT_const_expr 0x006c /* v4 */
+#define AT_enum_class 0x006d /* v4 */
+#define AT_linkage_name 0x006e /* v4 */
#define AT_lo_user_v1 0x0200
#define AT_hi_user_v1 0x03ff
#define AT_push_mask 0x0220
diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c
index 15cd804e..73c8e13e 100644
--- a/agent/tcf/services/dwarfcache.c
+++ b/agent/tcf/services/dwarfcache.c
@@ -35,6 +35,13 @@
#define OBJ_HASH(Cache,ID) (((U4_T)(ID) + ((U4_T)(ID) >> 8)) % Cache->mObjectHashSize)
+#define OBJECT_ARRAY_SIZE 128
+
+typedef struct ObjectArray {
+ struct ObjectArray * mNext;
+ ObjectInfo mArray[OBJECT_ARRAY_SIZE];
+} ObjectArray;
+
typedef struct ObjectReference {
ELF_Section * sec;
ObjectInfo * obj;
@@ -488,6 +495,11 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) {
add_object_reference(dio_gFormSection, add_object_info((ContextAddress)dio_gFormData), Info);
Info->mFlags |= DOIF_abstract_origin;
break;
+ case AT_extension:
+ dio_ChkRef(Form);
+ add_object_reference(dio_gFormSection, add_object_info((ContextAddress)dio_gFormData), Info);
+ Info->mFlags |= DOIF_extension;
+ break;
case AT_low_pc:
dio_ChkAddr(Form);
Info->u.mAddr.mLowPC = (ContextAddress)dio_gFormData;
@@ -586,12 +598,18 @@ static void read_object_refs(void) {
}
if (ref.obj != NULL) {
assert(ref.org->mTag != 0);
+ if (ref.obj->mFlags & DOIF_specification) ref.org->mDefinition = ref.obj;
if (ref.obj->mName == NULL) ref.obj->mName = ref.org->mName;
if (ref.obj->mType == NULL) ref.obj->mType = ref.org->mType;
- ref.obj->mFlags |= ref.org->mFlags & ~DOIF_children_loaded;
- assert(ref.obj->mDefinition == NULL);
- ref.obj->mDefinition = ref.org->mDefinition;
- ref.org->mDefinition = ref.obj;
+ ref.obj->mFlags |= ref.org->mFlags & ~(DOIF_children_loaded | DOIF_declaration | DOIF_specification);
+ if (ref.obj->mFlags & DOIF_external) {
+ ObjectInfo * cls = ref.org;
+ while (cls->mParent != NULL &&
+ (cls->mParent->mTag == TAG_class_type || cls->mParent->mTag == TAG_structure_type)) {
+ cls = cls->mParent;
+ }
+ cls->mFlags |= DOIF_external;
+ }
}
}
sObjRefsPos = 0;
@@ -773,7 +791,7 @@ static void create_pub_names(ELF_Section * debug_info, PubNamesTable * tbl) {
while (unit != NULL) {
ObjectInfo * obj = get_dwarf_children(unit);
while (obj != NULL) {
- if (obj->mFlags & DOIF_external) {
+ if ((obj->mFlags & DOIF_external) && obj->mDefinition == NULL) {
unsigned h;
PubNamesInfo * info = NULL;
if (tbl->mCnt >= tbl->mMax) {
@@ -926,10 +944,12 @@ static void * gop_gFormDataAddr = NULL;
static ELF_Section * gop_gFormSection = NULL;
static U8_T gop_gSpecification = 0;
static U8_T gop_gAbstractOrigin = 0;
+static U8_T gop_gExtension = 0;
static void get_object_property_callback(U2_T Tag, U2_T Attr, U2_T Form) {
if (Attr == AT_specification_v2) gop_gSpecification = dio_gFormData;
if (Attr == AT_abstract_origin) gop_gAbstractOrigin = dio_gFormData;
+ if (Attr == AT_extension) gop_gExtension = dio_gFormData;
if (Attr != gop_gAttr) return;
gop_gForm = Form;
gop_gFormData = dio_gFormData;
@@ -941,8 +961,7 @@ 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 ||
- (Value->mAddr != NULL && Value->mForm == FORM_EXPR_VALUE)) {
+ if (Value->mPieces != NULL) {
str_exception(ERR_INV_DWARF, "Constant DWARF attribute value expected");
}
else if (Value->mAddr != NULL) {
@@ -958,7 +977,7 @@ U8_T get_numeric_property_value(PropertyValue * Value) {
return Res;
}
-static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T Attr, PropertyValue * Value) {
+void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T Attr, PropertyValue * Value) {
memset(Value, 0, sizeof(PropertyValue));
Value->mContext = Ctx;
@@ -1038,11 +1057,13 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
gop_gForm = 0;
gop_gSpecification = 0;
gop_gAbstractOrigin = 0;
+ gop_gExtension = 0;
dio_ReadEntry(get_object_property_callback, gop_gAttr);
dio_ExitSection();
if (gop_gForm != 0) break;
if (gop_gSpecification != 0) dio_EnterSection(&sCompUnit->mDesc, sDebugSection, gop_gSpecification - sDebugSection->addr);
else if (gop_gAbstractOrigin != 0) dio_EnterSection(&sCompUnit->mDesc, sDebugSection, gop_gAbstractOrigin - sDebugSection->addr);
+ else if (gop_gExtension != 0) dio_EnterSection(&sCompUnit->mDesc, sDebugSection, gop_gExtension - sDebugSection->addr);
else break;
}
@@ -1054,7 +1075,7 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
case FORM_REF4 :
case FORM_REF8 :
case FORM_REF_UDATA :
- if (Attr == AT_import || Attr == AT_specification_v2) {
+ if (Attr == AT_import || Attr == AT_specification_v2 || Attr == AT_constaining_type) {
Value->mValue = gop_gFormData;
}
else {
@@ -1062,12 +1083,13 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
ObjectInfo * RefObj = find_object(sCache, (ContextAddress)gop_gFormData);
if (RefObj == NULL) exception(ERR_INV_DWARF);
- read_and_evaluate_dwarf_object_property(Ctx, Frame, 0, RefObj, AT_location, &ValueAddr);
- if (ValueAddr.mRegister != NULL) {
+ read_and_evaluate_dwarf_object_property(Ctx, Frame, RefObj, AT_location, &ValueAddr);
+ if (ValueAddr.mPieceCnt == 1 && ValueAddr.mPieces[0].reg != NULL && ValueAddr.mPieces[0].bit_size == 0) {
static U1_T Buf[8];
StackFrame * Frame = NULL;
+ RegisterDefinition * Register = ValueAddr.mPieces[0].reg;
if (get_frame_info(ValueAddr.mContext, ValueAddr.mFrame, &Frame) < 0) exception(errno);
- if (read_reg_bytes(Frame, ValueAddr.mRegister, 0, ValueAddr.mRegister->size, Buf) < 0) exception(errno);
+ if (read_reg_bytes(Frame, Register, 0, Register->size, Buf) < 0) exception(errno);
Value->mAddr = Buf;
Value->mSize = ValueAddr.mSize;
Value->mBigEndian = ValueAddr.mBigEndian;
@@ -1075,14 +1097,13 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
else {
static U1_T Buf[8];
PropertyValue ValueSize;
- ContextAddress Addr;
size_t Size;
- Addr = (ContextAddress)get_numeric_property_value(&ValueAddr);
- read_and_evaluate_dwarf_object_property(Ctx, Frame, Addr, RefObj, AT_byte_size, &ValueSize);
+ dwarf_expression_obj_addr = get_numeric_property_value(&ValueAddr);
+ read_and_evaluate_dwarf_object_property(Ctx, Frame, RefObj, AT_byte_size, &ValueSize);
Size = (size_t)get_numeric_property_value(&ValueSize);
if (Size < 1 || Size > sizeof(Buf)) exception(ERR_INV_DATA_TYPE);
- if (context_read_mem(Ctx, Addr, Buf, Size) < 0) exception(errno);
+ if (context_read_mem(Ctx, (ContextAddress)dwarf_expression_obj_addr, Buf, Size) < 0) exception(errno);
Value->mAddr = Buf;
Value->mSize = Size;
}
@@ -1126,7 +1147,7 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
}
if (Obj->mTag == TAG_ptr_to_member_type) {
Value->mForm = FORM_UDATA;
- Value->mValue = sCompUnit->mDesc.mAddressSize * 2;
+ Value->mValue = sCompUnit->mDesc.mAddressSize;
break;
}
if (Obj->mTag == TAG_structure_type || Obj->mTag == TAG_class_type || Obj->mTag == TAG_union_type) {
@@ -1137,7 +1158,7 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
ObjectInfo * d = c;
while (d->mTag == TAG_imported_declaration) {
PropertyValue v;
- read_and_evaluate_dwarf_object_property(Ctx, Frame, 0, d, AT_import, &v);
+ read_and_evaluate_dwarf_object_property(Ctx, Frame, d, AT_import, &v);
d = find_object(
(DWARFCache *)Obj->mCompUnit->mFile->dwarf_dt_cache,
(ContextAddress)get_numeric_property_value(&v));
@@ -1151,6 +1172,14 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
case TAG_typedef:
case TAG_subprogram:
case TAG_template_type_param:
+ case TAG_class_type:
+ case TAG_structure_type:
+ case TAG_union_type:
+ case TAG_enumeration_type:
+ break;
+ case TAG_member:
+ if (d->mFlags & DOIF_external) break;
+ OK = 0;
break;
default:
OK = 0;
@@ -1160,6 +1189,7 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
}
if (OK) {
Value->mForm = FORM_UDATA;
+ Value->mAddr = 0;
Value->mValue = 0;
break;
}
@@ -1173,16 +1203,36 @@ static void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Ob
sDebugSection = NULL;
}
-void read_and_evaluate_dwarf_object_property(Context * Ctx, int Frame, U8_T Base, ObjectInfo * Obj, U2_T Attr, PropertyValue * Value) {
+void read_and_evaluate_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T Attr, PropertyValue * Value) {
read_dwarf_object_property(Ctx, Frame, Obj, Attr, Value);
assert(Value->mContext == Ctx);
assert(Value->mFrame == Frame);
assert(Value->mObject == Obj);
assert(Value->mAttr == Attr);
if (Value->mForm == FORM_EXPRLOC) {
- dwarf_evaluate_expression(Base, Value);
+ dwarf_evaluate_expression(Value);
+ }
+ else if (Attr == AT_data_member_location) {
+ switch (Value->mForm) {
+ case FORM_DATA1 :
+ case FORM_DATA4 :
+ case FORM_DATA8 :
+ case FORM_SDATA :
+ case FORM_UDATA :
+ Value->mValue = dwarf_expression_obj_addr + get_numeric_property_value(Value);
+ Value->mForm = FORM_UDATA;
+ Value->mAddr = NULL;
+ Value->mSize = 0;
+ break;
+ case FORM_BLOCK1 :
+ case FORM_BLOCK2 :
+ case FORM_BLOCK4 :
+ case FORM_BLOCK :
+ dwarf_evaluate_expression(Value);
+ break;
+ }
}
- else if (Attr == AT_location || Attr == AT_data_member_location || Attr == AT_string_length || Attr == AT_frame_base) {
+ else if (Attr == AT_location || Attr == AT_string_length || Attr == AT_frame_base || Attr == AT_use_location) {
switch (Value->mForm) {
case FORM_DATA4 :
case FORM_DATA8 :
@@ -1190,7 +1240,7 @@ void read_and_evaluate_dwarf_object_property(Context * Ctx, int Frame, U8_T Base
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
- dwarf_evaluate_expression(Base, Value);
+ dwarf_evaluate_expression(Value);
break;
}
}
@@ -1200,7 +1250,7 @@ void read_and_evaluate_dwarf_object_property(Context * Ctx, int Frame, U8_T Base
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
- dwarf_evaluate_expression(Base, Value);
+ dwarf_evaluate_expression(Value);
break;
}
}
@@ -1599,8 +1649,9 @@ UnitAddressRange * find_comp_unit_addr_range(DWARFCache * cache, ContextAddress
first = rp->mAddr + rp->mSize <= addr_min;
}
if (first) return rk;
+ h = k;
}
- if (rk->mAddr >= addr_min) h = k;
+ else if (rk->mAddr >= addr_min) h = k;
else l = k + 1;
}
return NULL;
diff --git a/agent/tcf/services/dwarfcache.h b/agent/tcf/services/dwarfcache.h
index 1714881d..e4a357bc 100644
--- a/agent/tcf/services/dwarfcache.h
+++ b/agent/tcf/services/dwarfcache.h
@@ -28,9 +28,9 @@
#if ENABLE_ELF && ENABLE_DebugContext
+#include <tcf/framework/errors.h>
#include <tcf/services/tcf_elf.h>
#include <tcf/services/dwarfio.h>
-#include <tcf/framework/errors.h>
#ifndef ENABLE_DWARF_LAZY_LOAD
# define ENABLE_DWARF_LAZY_LOAD 1
@@ -40,9 +40,7 @@ typedef struct FileInfo FileInfo;
typedef struct ObjectInfo ObjectInfo;
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;
@@ -52,8 +50,8 @@ typedef struct FrameInfoRange FrameInfoRange;
typedef struct DWARFCache DWARFCache;
struct FileInfo {
- char * mName;
- char * mDir;
+ const char * mName;
+ const char * mDir;
U4_T mModTime;
U4_T mSize;
unsigned mNameHash;
@@ -71,7 +69,8 @@ struct FileInfo {
#define DOIF_artificial 0x0004
#define DOIF_specification 0x0008
#define DOIF_abstract_origin 0x0010
-#define DOIF_children_loaded 0x0020
+#define DOIF_extension 0x0020
+#define DOIF_children_loaded 0x0040
struct ObjectInfo {
@@ -89,7 +88,7 @@ struct ObjectInfo {
U2_T mFlags;
CompUnit * mCompUnit;
ObjectInfo * mType;
- char * mName;
+ const char * mName;
union {
U2_T mFundType;
@@ -117,13 +116,6 @@ struct ObjectInfo {
} u;
};
-#define OBJECT_ARRAY_SIZE 128
-
-struct ObjectArray {
- ObjectArray * mNext;
- ObjectInfo mArray[OBJECT_ARRAY_SIZE];
-};
-
struct PubNamesInfo {
unsigned mNext;
ContextAddress mID;
@@ -136,15 +128,6 @@ struct PubNamesTable {
unsigned mMax;
};
-struct PropertyValuePiece {
- int mBigEndian;
- ContextAddress mAddress;
- RegisterDefinition * mRegister;
- U1_T * mValue;
- U4_T mBitOffset;
- U4_T mBitSize;
-};
-
struct PropertyValue {
Context * mContext;
int mFrame;
@@ -155,8 +138,7 @@ struct PropertyValue {
U1_T * mAddr;
size_t mSize;
int mBigEndian;
- RegisterDefinition * mRegister;
- PropertyValuePiece * mPieces;
+ LocationPiece * mPieces;
U4_T mPieceCnt;
};
@@ -244,7 +226,7 @@ struct DWARFCache {
ELF_Section * mEHFrame;
ObjectInfo ** mObjectHash;
unsigned mObjectHashSize;
- ObjectArray * mObjectList;
+ struct ObjectArray * mObjectList;
unsigned mObjectArrayPos;
UnitAddressRange * mAddrRanges;
unsigned mAddrRangesCnt;
@@ -288,10 +270,16 @@ extern ObjectInfo * find_object(DWARFCache * cache, ContextAddress ID);
extern UnitAddressRange * find_comp_unit_addr_range(DWARFCache * cache, ContextAddress addr_min, ContextAddress addr_max);
/*
+ * Read a property of a DWARF object, perform ELF relocations if any.
+ * FORM_ADDR values are mapped to run-time address space.
+ */
+extern void read_dwarf_object_property(Context * Ctx, int Frame, ObjectInfo * Obj, U2_T Attr, PropertyValue * Value);
+
+/*
* Read and evaluate a property of a DWARF object, perform ELF relocations if any.
* FORM_ADDR values are mapped to run-time address space.
*/
-extern void read_and_evaluate_dwarf_object_property(Context * ctx, int frame, U8_T base, ObjectInfo * obj, U2_T attr_tag, PropertyValue * value);
+extern void read_and_evaluate_dwarf_object_property(Context * ctx, int frame, ObjectInfo * obj, U2_T attr_tag, PropertyValue * value);
/*
* Convert PropertyValue to a number.
diff --git a/agent/tcf/services/dwarfecomp.c b/agent/tcf/services/dwarfecomp.c
new file mode 100644
index 00000000..53beba42
--- /dev/null
+++ b/agent/tcf/services/dwarfecomp.c
@@ -0,0 +1,346 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ *******************************************************************************/
+
+/*
+ * Transformation of DWARF expressions to a portable form.
+ *
+ * Functions in this module use exceptions to report errors, see exceptions.h
+ */
+
+#include <tcf/config.h>
+
+#if ENABLE_ELF && ENABLE_DebugContext
+
+#include <assert.h>
+#include <tcf/framework/myalloc.h>
+#include <tcf/framework/exceptions.h>
+#include <tcf/services/dwarf.h>
+#include <tcf/services/dwarfecomp.h>
+
+static U1_T * buf = NULL;
+static size_t buf_pos = 0;
+static size_t buf_max = 0;
+static DWARFExpressionInfo * expr = NULL;
+static size_t expr_pos = 0;
+static Context * expr_ctx = NULL;
+static U8_T expr_ip = 0;
+
+static void add(unsigned n) {
+ if (buf_pos >= buf_max) {
+ buf_max *= 2;
+ buf = (U1_T *)tmp_realloc(buf, buf_max);
+ }
+ buf[buf_pos++] = (U1_T)n;
+}
+
+static void copy(size_t n) {
+ while (n > 0) {
+ if (expr_pos >= expr->expr_size) exception(ERR_INV_DWARF);
+ add(expr->expr_addr[expr_pos++]);
+ n--;
+ }
+}
+
+static void copy_leb128(void) {
+ for (;;) {
+ U1_T n = expr->expr_addr[expr_pos++];
+ add(n);
+ if ((n & 0x80) == 0) break;
+ }
+}
+
+static void add_uleb128(U8_T x) {
+ for (;;) {
+ U1_T n = (U1_T)(x & 0x7Fu);
+ x = x >> 7;
+ if (x == 0) {
+ add(n);
+ break;
+ }
+ add(n | 0x80u);
+ }
+}
+
+#if 0
+/* Not used yet */
+static void add_sleb128(I8_T x) {
+ for (;;) {
+ U1_T n = (U1_T)(x & 0x7Fu);
+ x = x >> 7;
+ if (x == 0 || (x == 0xFFu && (n & 0x40))) {
+ add(n);
+ break;
+ }
+ add(n | 0x80u);
+ }
+}
+#endif
+
+static void add_expression(DWARFExpressionInfo * info);
+
+static void op_addr(void) {
+ ContextAddress addr = 0;
+ ELF_Section * section = NULL;
+ U8_T pos = 0;
+
+ expr_pos++;
+ pos = expr->expr_addr + expr_pos - (U1_T *)expr->section->data;
+ dio_EnterSection(&expr->unit->mDesc, expr->section, pos);
+ addr = (ContextAddress)dio_ReadAddress(&section);
+ expr_pos += (size_t)(dio_GetPos() - pos);
+ dio_ExitSection();
+ addr = elf_map_to_run_time_address(expr_ctx, expr->unit->mFile, section, addr);
+ if (errno) str_exception(errno, "Cannot get object run-time address");
+ add(OP_constu);
+ add_uleb128(addr);
+}
+
+static void op_fbreg(void) {
+ PropertyValue fp;
+ DWARFExpressionInfo info;
+ ObjectInfo * parent = get_parent_function(expr->object);
+
+ expr_pos++;
+ memset(&fp, 0, sizeof(fp));
+ if (parent == NULL) str_exception(ERR_INV_DWARF, "OP_fbreg: no parent function");
+ read_dwarf_object_property(expr_ctx, STACK_NO_FRAME, parent, AT_frame_base, &fp);
+ dwarf_find_expression(&fp, expr_ip, &info);
+ switch (*info.expr_addr) {
+ case OP_reg:
+ add(OP_basereg);
+ {
+ unsigned i = 1;
+ while (i < info.unit->mDesc.mAddressSize + 1u) {
+ add(info.expr_addr[i++]);
+ }
+ }
+ copy_leb128();
+ return;
+ case OP_regx:
+ add(OP_bregx);
+ {
+ unsigned i = 1;
+ for (;;) {
+ U1_T n = info.expr_addr[i++];
+ add(n);
+ if ((n & 0x80) == 0) break;
+ }
+ }
+ copy_leb128();
+ return;
+ case OP_reg0:
+ case OP_reg1:
+ case OP_reg2:
+ case OP_reg3:
+ case OP_reg4:
+ case OP_reg5:
+ case OP_reg6:
+ case OP_reg7:
+ case OP_reg8:
+ case OP_reg9:
+ case OP_reg10:
+ case OP_reg11:
+ case OP_reg12:
+ case OP_reg13:
+ case OP_reg14:
+ case OP_reg15:
+ case OP_reg16:
+ case OP_reg17:
+ case OP_reg18:
+ case OP_reg19:
+ case OP_reg20:
+ case OP_reg21:
+ case OP_reg22:
+ case OP_reg23:
+ case OP_reg24:
+ case OP_reg25:
+ case OP_reg26:
+ case OP_reg27:
+ case OP_reg28:
+ case OP_reg29:
+ case OP_reg30:
+ case OP_reg31:
+ add(OP_breg0 + (*info.expr_addr - OP_reg0));
+ copy_leb128();
+ return;
+ }
+ add_expression(&info);
+ add(OP_consts);
+ copy_leb128();
+ add(OP_add);
+}
+
+static void add_expression(DWARFExpressionInfo * info) {
+ DWARFExpressionInfo * org_expr = expr;
+ size_t org_expr_pos = expr_pos;
+
+ if (expr != NULL && info->code_size) {
+ if (expr->code_size) {
+ if (info->code_addr > expr->code_addr) {
+ U8_T d = info->code_addr - expr->code_addr;
+ assert(expr->code_size > d);
+ expr->code_addr += d;
+ expr->code_size -= d;
+ }
+ if (info->code_addr + info->code_size < expr->code_addr + expr->code_size) {
+ U8_T d = (expr->code_addr + expr->code_size) - (info->code_addr + info->code_size);
+ assert(expr->code_size > d);
+ expr->code_size -= d;
+ }
+ }
+ else {
+ expr->code_addr = info->code_addr;
+ expr->code_size = info->code_size;
+ }
+ }
+
+ expr = info;
+ expr_pos = 0;
+ while (expr_pos < info->expr_size) {
+ U1_T op = info->expr_addr[expr_pos];
+ switch (op) {
+ case OP_const1u:
+ case OP_const1s:
+ case OP_pick:
+ case OP_deref_size:
+ case OP_xderef_size:
+ copy(2);
+ break;
+ case OP_const:
+ case OP_reg:
+ case OP_basereg:
+ copy(1 + info->unit->mDesc.mAddressSize);
+ break;
+ case OP_const2u:
+ case OP_const2s:
+ copy(3);
+ break;
+ case OP_const4u:
+ case OP_const4s:
+ copy(5);
+ break;
+ case OP_const8u:
+ case OP_const8s:
+ copy(9);
+ break;
+ case OP_constu:
+ case OP_consts:
+ case OP_plus_uconst:
+ case OP_regx:
+ case OP_breg0:
+ case OP_breg1:
+ case OP_breg2:
+ case OP_breg3:
+ case OP_breg4:
+ case OP_breg5:
+ case OP_breg6:
+ case OP_breg7:
+ case OP_breg8:
+ case OP_breg9:
+ case OP_breg10:
+ case OP_breg11:
+ case OP_breg12:
+ case OP_breg13:
+ case OP_breg14:
+ case OP_breg15:
+ case OP_breg16:
+ case OP_breg17:
+ case OP_breg18:
+ case OP_breg19:
+ case OP_breg20:
+ case OP_breg21:
+ case OP_breg22:
+ case OP_breg23:
+ case OP_breg24:
+ case OP_breg25:
+ case OP_breg26:
+ case OP_breg27:
+ case OP_breg28:
+ case OP_breg29:
+ case OP_breg30:
+ case OP_breg31:
+ case OP_piece:
+ add(op);
+ expr_pos++;
+ copy_leb128();
+ break;
+ case OP_bra:
+ case OP_skip:
+ str_exception(ERR_UNSUPPORTED, "OP_bra/OP_skip not supported yet");
+ break;
+ case OP_bregx:
+ case OP_bit_piece:
+ add(op);
+ expr_pos++;
+ copy_leb128();
+ copy_leb128();
+ break;
+ case OP_implicit_value:
+ {
+ unsigned i = 0;
+ size_t j = expr_pos + 1u;
+ size_t size = 0;
+ for (;; i += 7) {
+ U1_T n = info->expr_addr[j++];
+ size |= (n & 0x7Fu) << i;
+ if ((n & 0x80) == 0) break;
+ }
+ copy(j + size - expr_pos);
+ }
+ break;
+ case OP_fbreg:
+ op_fbreg();
+ break;
+ case OP_addr:
+ op_addr();
+ break;
+ case OP_form_tls_address:
+ case OP_GNU_push_tls_address:
+ case OP_GNU_implicit_pointer:
+ case OP_call2:
+ case OP_call4:
+ case OP_call_ref:
+ str_fmt_exception(ERR_OTHER, "Unsupported DWARF expression op 0x%02x", op);
+ break;
+ default:
+ add(op);
+ expr_pos++;
+ break;
+ }
+ }
+ expr = org_expr;
+ expr_pos = org_expr_pos;
+}
+
+void dwarf_transform_expression(Context * ctx, ContextAddress ip, DWARFExpressionInfo * info) {
+ buf_pos = 0;
+ buf_max = info->expr_size * 2;
+ buf = (U1_T *)tmp_alloc(buf_max);
+ expr_ctx = ctx;
+ expr_ip = ip;
+ expr = NULL;
+ add_expression(info);
+ info->expr_addr = buf;
+ info->expr_size = buf_pos;
+ buf_pos = 0;
+ buf_max = 0;
+ buf = NULL;
+ expr = NULL;
+ expr_pos = 0;
+ expr_ctx = NULL;
+ expr_ip = 0;
+}
+
+#endif
diff --git a/agent/tcf/services/dwarfecomp.h b/agent/tcf/services/dwarfecomp.h
new file mode 100644
index 00000000..612f54af
--- /dev/null
+++ b/agent/tcf/services/dwarfecomp.h
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ *******************************************************************************/
+
+/*
+ * Transformation of DWARF expressions to a portable form.
+ *
+ * Functions in this module use exceptions to report errors, see exceptions.h
+ */
+#ifndef D_dwarfecomp
+#define D_dwarfecomp
+
+#include <tcf/config.h>
+
+#if ENABLE_ELF && ENABLE_DebugContext
+
+#include <tcf/services/dwarfexpr.h>
+
+extern void dwarf_transform_expression(Context * ctx, ContextAddress ip, DWARFExpressionInfo * info);
+
+#endif /* ENABLE_ELF && ENABLE_DebugContext */
+
+#endif /* D_dwarfecomp */
diff --git a/agent/tcf/services/dwarfexpr.c b/agent/tcf/services/dwarfexpr.c
index 27145c4b..a9291cfd 100644
--- a/agent/tcf/services/dwarfexpr.c
+++ b/agent/tcf/services/dwarfexpr.c
@@ -35,23 +35,23 @@
#include <tcf/services/elf-loader.h>
#include <tcf/services/vm.h>
-static VMState * sState = NULL;
+U8_T dwarf_expression_obj_addr = 0;
+U8_T dwarf_expression_pm_value = 0;
+
+static int sStackFrame = 0;
+static LocationExpressionState * sState = NULL;
static ELF_Section * sSection = NULL;
static U8_T sSectionOffs = 0;
static PropertyValue * sValue = NULL;
-static PropertyValuePiece * sValuePieces = NULL;
-static U4_T sValuePiecesCnt = 0;
-static U4_T sValuePiecesMax = 0;
-
-static PropertyValuePiece * add_piece(void) {
- PropertyValuePiece * Piece;
- if (sValuePiecesCnt >= sValuePiecesMax) {
- sValuePiecesMax += 8;
- sValuePieces = (PropertyValuePiece *)tmp_realloc(sValuePieces,
- sizeof(PropertyValuePiece) * sValuePiecesMax);
+
+static LocationPiece * add_piece(void) {
+ LocationPiece * Piece = NULL;
+ if (sState->pieces_cnt >= sState->pieces_max) {
+ sState->pieces_max += 4;
+ sState->pieces = (LocationPiece *)tmp_realloc(sState->pieces, sState->pieces_max * sizeof(LocationPiece));
}
- Piece = sValuePieces + sValuePiecesCnt++;
- memset(Piece, 0, sizeof(PropertyValuePiece));
+ Piece = sState->pieces + sState->pieces_cnt++;
+ memset(Piece, 0, sizeof(LocationPiece));
return Piece;
}
@@ -62,7 +62,7 @@ static StackFrame * get_stack_frame(PropertyValue * sValue) {
return Info;
}
-static ObjectInfo * get_parent_function(ObjectInfo * Info) {
+ObjectInfo * get_parent_function(ObjectInfo * Info) {
while (Info != NULL) {
switch (Info->mTag) {
case TAG_global_subroutine:
@@ -96,10 +96,11 @@ static U8_T get_fbreg(void) {
if (Parent == NULL) str_exception(ERR_INV_DWARF, "OP_fbreg: no parent function");
memset(&FP, 0, sizeof(FP));
- read_and_evaluate_dwarf_object_property(sState->ctx, sState->stack_frame, 0, Parent, AT_frame_base, &FP);
+ read_and_evaluate_dwarf_object_property(sState->ctx, sStackFrame, Parent, AT_frame_base, &FP);
+ assert(get_stack_frame(&FP) == sState->stack_frame);
- if (FP.mRegister != NULL) {
- if (read_reg_value(get_stack_frame(&FP), FP.mRegister, &addr) < 0) exception(errno);
+ if (FP.mPieceCnt == 1 && FP.mPieces[0].reg != NULL && FP.mPieces[0].bit_size == 0) {
+ if (read_reg_value(sState->stack_frame, FP.mPieces[0].reg, &addr) < 0) exception(errno);
}
else {
addr = get_numeric_property_value(&FP);
@@ -130,58 +131,44 @@ static void evaluate_implicit_pointer(void) {
U8_T DioPos = dio_GetPos();
if (Info == NULL) str_exception(ERR_INV_DWARF, "OP_GNU_implicit_pointer: invalid object reference");
memset(&FP, 0, sizeof(FP));
- read_and_evaluate_dwarf_object_property(sState->ctx, sState->stack_frame, 0, Info, sValue->mAttr, &FP);
+ read_and_evaluate_dwarf_object_property(sState->ctx, sStackFrame, Info, sValue->mAttr, &FP);
if (FP.mPieces != NULL) {
U4_T Cnt = 0;
U4_T BitOffset = 0;
while (Cnt < FP.mPieceCnt) {
- PropertyValuePiece * OrgPiece = FP.mPieces + Cnt++;
- if (BitOffset + OrgPiece->mBitSize > Offset * 8) {
- PropertyValuePiece * Piece = add_piece();
+ LocationPiece * OrgPiece = FP.mPieces + Cnt++;
+ if (OrgPiece->bit_size == 0) OrgPiece->bit_size = OrgPiece->size * 8;
+ if (BitOffset + OrgPiece->bit_size > Offset * 8) {
+ LocationPiece * Piece = add_piece();
*Piece = *OrgPiece;
if (BitOffset < Offset * 8) {
- Piece->mBitOffset += Offset * 8 - BitOffset;
- Piece->mBitSize -= Offset * 8 - BitOffset;
+ Piece->bit_offs += Offset * 8 - BitOffset;
+ Piece->bit_size -= Offset * 8 - BitOffset;
}
}
- BitOffset += OrgPiece->mBitSize;
+ BitOffset += OrgPiece->bit_size;
}
}
- else if (FP.mRegister != NULL) {
- PropertyValuePiece * Piece = add_piece();
- if (Offset > FP.mRegister->size) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- Piece->mBigEndian = FP.mRegister->big_endian;
- Piece->mRegister = FP.mRegister;
- Piece->mBitOffset = Offset * 8;
- Piece->mBitSize = (FP.mRegister->size - Offset) * 8;
- }
- else if (FP.mAddr != NULL) {
- PropertyValuePiece * Piece = add_piece();
- if (Offset > FP.mSize) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- Piece->mBigEndian = FP.mBigEndian;
- Piece->mValue = FP.mAddr;
- Piece->mBitOffset = Offset * 8;
- Piece->mBitSize = (FP.mSize - Offset) * 8;
- }
else {
- PropertyValuePiece * Piece = add_piece();
+ LocationPiece * Piece = add_piece();
if (Offset > sizeof(FP.mValue)) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- Piece->mBigEndian = big_endian_host();
- Piece->mValue = (U1_T *)tmp_alloc(sizeof(FP.mValue));
- Piece->mBitOffset = Offset * 8;
- Piece->mBitSize = (sizeof(FP.mValue) - Offset) * 8;
+ Piece->big_endian = big_endian_host();
+ Piece->size = sizeof(FP.mValue);
+ Piece->value = (U1_T *)tmp_alloc(sizeof(FP.mValue));
+ Piece->bit_offs = Offset * 8;
+ Piece->bit_size = (sizeof(FP.mValue) - Offset) * 8;
}
dio_EnterSection(&Unit->mDesc, sSection, DioPos);
}
static void client_op(uint8_t op) {
- dio_SetPos(sSectionOffs + sState->code_pos);
+ dio_EnterSection(&sValue->mObject->mCompUnit->mDesc, sSection, 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");
+ if (sState->stack_frame == NULL) str_exception(ERR_INV_CONTEXT, "Invalid stack frame");
sState->stk[sState->stk_pos++] = get_fbreg();
break;
case OP_form_tls_address:
@@ -207,163 +194,135 @@ static void client_op(uint8_t op) {
str_fmt_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op 0x%02x", op);
}
sState->code_pos = (size_t)(dio_GetPos() - sSectionOffs);
+ dio_ExitSection();
}
-static void evaluate_expression(ELF_Section * Section, U1_T * Buf, size_t Size) {
- int error = 0;
- CompUnit * Unit = sValue->mObject->mCompUnit;
+void dwarf_find_expression(PropertyValue * Value, U8_T IP, DWARFExpressionInfo * Info) {
+ CompUnit * Unit = Value->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) {
- while (!error) {
- PropertyValuePiece * Piece = add_piece();
- if (sState->reg) {
- Piece->mRegister = sState->reg;
- Piece->mBigEndian = sState->reg->big_endian;
+ memset(Info, 0, sizeof(DWARFExpressionInfo));
+ Info->object = Value->mObject;
+ Info->unit = Unit;
+
+ 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) {
+ U8_T Base = 0;
+ U8_T Offset = 0;
+ U8_T AddrMax = ~(U8_T)0;
+ DWARFCache * Cache = (DWARFCache *)Unit->mFile->dwarf_dt_cache;
+
+ 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_ReadUX(Value->mSize);
+ dio_ExitSection();
+ Base = Unit->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 (S0 == NULL) S0 = Unit->mTextSection;
+ if (S1 == NULL) S1 = Unit->mTextSection;
+ if (Addr0 == AddrMax) {
+ Base = Addr1;
}
- 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 if (Addr0 == 0 && Addr1 == 0) {
+ break;
}
- else if (sState->stk_pos == 0) {
- /* An empty location description represents a piece or all of an object that is
- * present in the source but not in the object code (perhaps due to optimization). */
- size_t size = (sState->piece_bits + 7) / 8;
- Piece->mValue = (U1_T *)tmp_alloc_zero(size);
+ else if (S0 != S1 || Addr0 > Addr1) {
+ str_exception(ERR_INV_DWARF, "Invalid .debug_loc section");
}
else {
- Piece->mAddress = (ContextAddress)sState->stk[--sState->stk_pos];
- Piece->mBigEndian = sState->big_endian;
+ U2_T Size = dio_ReadU2();
+ U8_T RTAddr0 = elf_map_to_run_time_address(Value->mContext, Unit->mFile, S0, (ContextAddress)(Base + Addr0));
+ U8_T RTAddr1 = Addr1 - Addr0 + RTAddr0;
+ if (RTAddr0 != 0 && IP >= RTAddr0 && IP < RTAddr1) {
+ Info->code_addr = RTAddr0;
+ Info->code_size = RTAddr1 - RTAddr0;
+ Info->section = Cache->mDebugLoc;
+ Info->expr_addr = dio_GetDataPtr();
+ Info->expr_size = Size;
+ dio_ExitSection();
+ return;
+ }
+ dio_Skip(Size);
}
- Piece->mBitOffset = sState->piece_offs;
- Piece->mBitSize = sState->piece_bits;
- if (sState->stk_pos != 0) str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
- if (sState->code_pos >= sState->code_len) break;
- if (evaluate_vm_expression(sState) < 0) error = errno;
}
+ dio_ExitSection();
+ str_exception(ERR_OTHER, "Object is not available at this location in the code");
}
- 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);
- }
+ else {
+ Info->section = Unit->mDesc.mSection;
+ Info->expr_addr = Value->mAddr;
+ Info->expr_size = Value->mSize;
}
- 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) {
+void dwarf_evaluate_expression(PropertyValue * v) {
CompUnit * Unit = v->mObject->mCompUnit;
- VMState * OrgState = sState;
+ LocationExpressionState * OrgState = sState;
ELF_Section * OrgSection = sSection;
U8_T OrgSectionOffs = sSectionOffs;
PropertyValue * OrgValue = sValue;
- PropertyValuePiece * OrgValuePieces = sValuePieces;
- U4_T OrgValuePiecesCnt = sValuePiecesCnt;
- U4_T OrgValuePiecesMax = sValuePiecesMax;
+ DWARFExpressionInfo Info;
+ U8_T IP = 0;
+ U8_T args[2];
sValue = v;
- sValuePieces = NULL;
- sValuePiecesCnt = 0;
- sValuePiecesMax = 0;
- sState = (VMState *)tmp_alloc_zero(sizeof(VMState));
+ sStackFrame = sValue->mFrame;
+ sState = (LocationExpressionState *)tmp_alloc_zero(sizeof(LocationExpressionState));
+ sState->stk = (U8_T *)tmp_alloc(sizeof(U8_T) * (sState->stk_max = 8));
sState->ctx = sValue->mContext;
+ sState->stack_frame = get_stack_frame(v);
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->args = args;
sState->client_op = client_op;
+ args[0] = dwarf_expression_obj_addr;
+ args[1] = dwarf_expression_pm_value;
if (sValue->mAttr == AT_data_member_location) {
- sState->stk = (U8_T *)tmp_alloc(sizeof(U8_T) * (sState->stk_max = 8));
- sState->stk[sState->stk_pos++] = BaseAddress;
+ sState->stk[sState->stk_pos++] = dwarf_expression_obj_addr;
+ sState->args_cnt = 1;
+ }
+ if (sValue->mAttr == AT_use_location) {
+ sState->stk[sState->stk_pos++] = dwarf_expression_pm_value;
+ sState->stk[sState->stk_pos++] = dwarf_expression_obj_addr;
+ sState->args_cnt = 2;
}
- if (sValue->mRegister != NULL || sValue->mAddr == NULL || sValue->mSize == 0) {
+ if (sValue->mPieces != 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);
+ if (read_reg_value(sState->stack_frame, get_PC_definition(sValue->mContext), &IP) < 0) exception(errno);
}
+ dwarf_find_expression(sValue, IP, &Info);
+ sState->code = Info.expr_addr;
+ sState->code_len = Info.expr_size;
+ sState->code_pos = 0;
+ sSection = Info.section;
+ sSectionOffs = Info.expr_addr - (U1_T *)sSection->data;
+ if (evaluate_vm_expression(sState) < 0) exception(errno);
+ assert(sState->code_pos == sState->code_len);
+
sValue->mForm = FORM_EXPR_VALUE;
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;
- sValue->mPieceCnt = sValuePiecesCnt;
- }
- else if (sState->reg) {
- sValue->mSize = sState->reg->size;
- 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;
+ if (sState->pieces_cnt) {
+ sValue->mPieces = sState->pieces;
+ sValue->mPieceCnt = sState->pieces_cnt;
}
else {
sValue->mValue = sState->stk[--sState->stk_pos];
@@ -377,9 +336,6 @@ void dwarf_evaluate_expression(U8_T BaseAddress, PropertyValue * v) {
sSection = OrgSection;
sSectionOffs = OrgSectionOffs;
sValue = OrgValue;
- sValuePieces = OrgValuePieces;
- sValuePiecesCnt = OrgValuePiecesCnt;
- sValuePiecesMax = OrgValuePiecesMax;
}
#endif /* ENABLE_ELF && ENABLE_DebugContext */
diff --git a/agent/tcf/services/dwarfexpr.h b/agent/tcf/services/dwarfexpr.h
index 1ebbd484..c40a8ce5 100644
--- a/agent/tcf/services/dwarfexpr.h
+++ b/agent/tcf/services/dwarfexpr.h
@@ -30,7 +30,22 @@
/* PropertyValue format for expresson evaluation results */
#define FORM_EXPR_VALUE 0x00ff
-extern void dwarf_evaluate_expression(U8_T base, PropertyValue * value);
+extern U8_T dwarf_expression_obj_addr;
+extern U8_T dwarf_expression_pm_value;
+
+typedef struct DWARFExpressionInfo {
+ U8_T code_addr;
+ U8_T code_size;
+ CompUnit * unit;
+ ObjectInfo * object;
+ ELF_Section * section;
+ U1_T * expr_addr;
+ size_t expr_size;
+} DWARFExpressionInfo;
+
+extern ObjectInfo * get_parent_function(ObjectInfo * info);
+extern void dwarf_find_expression(PropertyValue * Value, U8_T IP, DWARFExpressionInfo * info);
+extern void dwarf_evaluate_expression(PropertyValue * value);
#endif /* ENABLE_ELF && ENABLE_DebugContext */
diff --git a/agent/tcf/services/dwarfframe.c b/agent/tcf/services/dwarfframe.c
index d2fb540d..72b6851b 100644
--- a/agent/tcf/services/dwarfframe.c
+++ b/agent/tcf/services/dwarfframe.c
@@ -109,15 +109,15 @@ static StackFrameRules rules;
U8_T dwarf_stack_trace_addr = 0;
U8_T dwarf_stack_trace_size = 0;
-StackTracingCommandSequence * dwarf_stack_trace_fp = NULL;
+StackFrameRegisterLocation * dwarf_stack_trace_fp = NULL;
int dwarf_stack_trace_regs_cnt = 0;
-StackTracingCommandSequence ** dwarf_stack_trace_regs = NULL;
+StackFrameRegisterLocation ** dwarf_stack_trace_regs = NULL;
static int trace_regs_max = 0;
-static int trace_cmds_max = 0;
-static int trace_cmds_cnt = 0;
-static StackTracingCommand * trace_cmds = NULL;
+static unsigned trace_cmds_max = 0;
+static unsigned trace_cmds_cnt = 0;
+static LocationExpressionCommand * trace_cmds = NULL;
static RegisterRules * get_reg(StackFrameRegisters * regs, int reg) {
while (reg >= regs->regs_max) {
@@ -423,11 +423,11 @@ static void exec_stack_frame_instruction(void) {
}
}
-static StackTracingCommand * add_command(int op) {
- StackTracingCommand * cmd = NULL;
+static LocationExpressionCommand * add_command(int op) {
+ LocationExpressionCommand * cmd = NULL;
if (trace_cmds_cnt >= trace_cmds_max) {
trace_cmds_max += 16;
- trace_cmds = (StackTracingCommand *)loc_realloc(trace_cmds, trace_cmds_max * sizeof(StackTracingCommand));
+ trace_cmds = (LocationExpressionCommand *)loc_realloc(trace_cmds, trace_cmds_max * sizeof(LocationExpressionCommand));
}
cmd = trace_cmds + trace_cmds_cnt++;
memset(cmd, 0, sizeof(*cmd));
@@ -435,15 +435,15 @@ static StackTracingCommand * add_command(int op) {
return cmd;
}
-static void add_command_sequence(StackTracingCommandSequence ** ptr, RegisterDefinition * reg) {
- StackTracingCommandSequence * seq = *ptr;
+static void add_command_sequence(StackFrameRegisterLocation ** ptr, RegisterDefinition * reg) {
+ StackFrameRegisterLocation * seq = *ptr;
if (seq == NULL || seq->cmds_max < trace_cmds_cnt) {
- *ptr = seq = (StackTracingCommandSequence *)loc_realloc(seq, sizeof(StackTracingCommandSequence) + (trace_cmds_cnt - 1) * sizeof(StackTracingCommand));
+ *ptr = seq = (StackFrameRegisterLocation *)loc_realloc(seq, sizeof(StackFrameRegisterLocation) + (trace_cmds_cnt - 1) * sizeof(LocationExpressionCommand));
seq->cmds_max = trace_cmds_cnt;
}
seq->reg = reg;
seq->cmds_cnt = trace_cmds_cnt;
- memcpy(seq->cmds, trace_cmds, trace_cmds_cnt * sizeof(StackTracingCommand));
+ memcpy(seq->cmds, trace_cmds, trace_cmds_cnt * sizeof(LocationExpressionCommand));
}
static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) {
@@ -459,52 +459,52 @@ static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) {
ContextAddress rt_addr = elf_map_to_run_time_address(
rules.ctx, rules.section->file, section, (ContextAddress)lt_addr);
if (errno) str_exception(ERR_INV_DWARF, "Cannot get object run-time address");
- add_command(SFT_CMD_NUMBER)->num = rt_addr;
+ add_command(SFT_CMD_NUMBER)->args.num = rt_addr;
}
break;
case OP_deref:
{
- StackTracingCommand * cmd = add_command(SFT_CMD_DEREF);
- cmd->size = rules.address_size;
- cmd->big_endian = rules.section->file->big_endian;
+ LocationExpressionCommand * cmd = add_command(SFT_CMD_DEREF);
+ cmd->args.deref.size = rules.address_size;
+ cmd->args.deref.big_endian = rules.section->file->big_endian;
}
break;
case OP_deref_size:
{
- StackTracingCommand * cmd = add_command(SFT_CMD_DEREF);
- cmd->size = dio_ReadU1();
- cmd->big_endian = rules.section->file->big_endian;
+ LocationExpressionCommand * cmd = add_command(SFT_CMD_DEREF);
+ cmd->args.deref.size = dio_ReadU1();
+ cmd->args.deref.big_endian = rules.section->file->big_endian;
}
break;
case OP_const1u:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadU1();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU1();
break;
case OP_const1s:
- add_command(SFT_CMD_NUMBER)->num = (I1_T)dio_ReadU1();
+ add_command(SFT_CMD_NUMBER)->args.num = (I1_T)dio_ReadU1();
break;
case OP_const2u:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadU2();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU2();
break;
case OP_const2s:
- add_command(SFT_CMD_NUMBER)->num = (I2_T)dio_ReadU2();
+ add_command(SFT_CMD_NUMBER)->args.num = (I2_T)dio_ReadU2();
break;
case OP_const4u:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadU4();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU4();
break;
case OP_const4s:
- add_command(SFT_CMD_NUMBER)->num = (I4_T)dio_ReadU4();
+ add_command(SFT_CMD_NUMBER)->args.num = (I4_T)dio_ReadU4();
break;
case OP_const8u:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadU8();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8();
break;
case OP_const8s:
- add_command(SFT_CMD_NUMBER)->num = (I8_T)dio_ReadU8();
+ add_command(SFT_CMD_NUMBER)->args.num = (I8_T)dio_ReadU8();
break;
case OP_constu:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadU8LEB128();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8LEB128();
break;
case OP_consts:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadS8LEB128();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadS8LEB128();
break;
case OP_and:
add_command(SFT_CMD_AND);
@@ -519,7 +519,7 @@ static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) {
add_command(SFT_CMD_ADD);
break;
case OP_plus_uconst:
- add_command(SFT_CMD_NUMBER)->num = dio_ReadU8LEB128();
+ add_command(SFT_CMD_NUMBER)->args.num = dio_ReadU8LEB128();
add_command(SFT_CMD_ADD);
break;
case OP_ge:
@@ -569,7 +569,7 @@ static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) {
case OP_lit29:
case OP_lit30:
case OP_lit31:
- add_command(SFT_CMD_NUMBER)->num = op - OP_lit0;
+ add_command(SFT_CMD_NUMBER)->args.num = op - OP_lit0;
break;
case OP_breg0:
case OP_breg1:
@@ -607,9 +607,9 @@ static void add_dwarf_expression_commands(U8_T cmds_offs, U4_T cmds_size) {
I8_T offs = dio_ReadS8LEB128();
RegisterDefinition * def = get_reg_by_id(rules.ctx, op - OP_breg0, &rules.reg_id_scope);
if (def == NULL) str_exception(errno, "Cannot read DWARF frame info");
- add_command(SFT_CMD_REGISTER)->reg = def;
+ add_command(SFT_CMD_REGISTER)->args.reg = def;
if (offs != 0) {
- add_command(SFT_CMD_NUMBER)->num = offs;
+ add_command(SFT_CMD_NUMBER)->args.num = offs;
add_command(SFT_CMD_ADD);
}
}
@@ -631,24 +631,24 @@ static void generate_register_commands(RegisterRules * reg, RegisterDefinition *
case RULE_OFFSET:
add_command(SFT_CMD_FP);
if (reg->offset != 0) {
- add_command(SFT_CMD_NUMBER)->num = reg->offset;
+ add_command(SFT_CMD_NUMBER)->args.num = reg->offset;
add_command(SFT_CMD_ADD);
}
if (reg->rule == RULE_OFFSET) {
- StackTracingCommand * cmd = add_command(SFT_CMD_DEREF);
- cmd->size = dst_reg_def->size;
- if (cmd->size > rules.address_size) cmd->size = rules.address_size;
- cmd->big_endian = rules.section->file->big_endian;
+ LocationExpressionCommand * cmd = add_command(SFT_CMD_DEREF);
+ cmd->args.deref.size = dst_reg_def->size;
+ if (cmd->args.deref.size > rules.address_size) cmd->args.deref.size = rules.address_size;
+ cmd->args.deref.big_endian = rules.section->file->big_endian;
}
break;
case RULE_SAME_VALUE:
if (src_reg_def == NULL) return;
- add_command(SFT_CMD_REGISTER)->reg = src_reg_def;
+ add_command(SFT_CMD_REGISTER)->args.reg = src_reg_def;
break;
case RULE_REGISTER:
{
RegisterDefinition * src_sef = get_reg_by_id(rules.ctx, reg->offset, &rules.reg_id_scope);
- if (src_sef != NULL) add_command(SFT_CMD_REGISTER)->reg = src_sef;
+ if (src_sef != NULL) add_command(SFT_CMD_REGISTER)->args.reg = src_sef;
}
break;
case RULE_EXPRESSION:
@@ -656,10 +656,10 @@ static void generate_register_commands(RegisterRules * reg, RegisterDefinition *
add_command(SFT_CMD_FP);
add_dwarf_expression_commands(reg->expression, reg->offset);
if (reg->rule == RULE_EXPRESSION) {
- StackTracingCommand * cmd = add_command(SFT_CMD_DEREF);
- cmd->size = dst_reg_def->size;
- if (cmd->size > rules.address_size) cmd->size = rules.address_size;
- cmd->big_endian = rules.section->file->big_endian;
+ LocationExpressionCommand * cmd = add_command(SFT_CMD_DEREF);
+ cmd->args.deref.size = dst_reg_def->size;
+ if (cmd->args.deref.size > rules.address_size) cmd->args.deref.size = rules.address_size;
+ cmd->args.deref.big_endian = rules.section->file->big_endian;
}
break;
default:
@@ -669,7 +669,7 @@ static void generate_register_commands(RegisterRules * reg, RegisterDefinition *
if (dwarf_stack_trace_regs_cnt >= trace_regs_max) {
int i;
trace_regs_max += 16;
- dwarf_stack_trace_regs = (StackTracingCommandSequence **)loc_realloc(dwarf_stack_trace_regs, trace_regs_max * sizeof(StackTracingCommandSequence *));
+ dwarf_stack_trace_regs = (StackFrameRegisterLocation **)loc_realloc(dwarf_stack_trace_regs, trace_regs_max * sizeof(StackFrameRegisterLocation *));
for (i = dwarf_stack_trace_regs_cnt; i < trace_regs_max; i++) dwarf_stack_trace_regs[i] = NULL;
}
if (trace_cmds_cnt == 0) return;
@@ -699,9 +699,9 @@ static void generate_commands(void) {
case RULE_OFFSET:
reg_def = get_reg_by_id(rules.ctx, rules.cfa_register, &rules.reg_id_scope);
if (reg_def != NULL) {
- add_command(SFT_CMD_REGISTER)->reg = reg_def;
+ add_command(SFT_CMD_REGISTER)->args.reg = reg_def;
if (rules.cfa_offset != 0) {
- add_command(SFT_CMD_NUMBER)->num = rules.cfa_offset;
+ add_command(SFT_CMD_NUMBER)->args.num = rules.cfa_offset;
add_command(SFT_CMD_ADD);
}
}
@@ -1012,7 +1012,7 @@ void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, ELF_Section * te
dwarf_stack_trace_regs_cnt = 0;
if (dwarf_stack_trace_fp == NULL) {
- dwarf_stack_trace_fp = (StackTracingCommandSequence *)loc_alloc_zero(sizeof(StackTracingCommandSequence));
+ dwarf_stack_trace_fp = (StackFrameRegisterLocation *)loc_alloc_zero(sizeof(StackFrameRegisterLocation));
dwarf_stack_trace_fp->cmds_max = 1;
}
dwarf_stack_trace_fp->cmds_cnt = 0;
diff --git a/agent/tcf/services/dwarfframe.h b/agent/tcf/services/dwarfframe.h
index 48a0c2f7..3cddbfdb 100644
--- a/agent/tcf/services/dwarfframe.h
+++ b/agent/tcf/services/dwarfframe.h
@@ -26,8 +26,8 @@
#if ENABLE_ELF && ENABLE_DebugContext
-#include <tcf/framework/context.h>
#include <tcf/services/dwarfcache.h>
+#include <tcf/services/symbols.h>
/*
* Lookup stack tracing information in ELF file, in .debug_frame and .eh_frame sections.
@@ -46,10 +46,10 @@ extern void get_dwarf_stack_frame_info(Context * ctx, ELF_File * file, ELF_Secti
extern U8_T dwarf_stack_trace_addr;
extern U8_T dwarf_stack_trace_size;
-extern StackTracingCommandSequence * dwarf_stack_trace_fp;
+extern StackFrameRegisterLocation * dwarf_stack_trace_fp;
extern int dwarf_stack_trace_regs_cnt;
-extern StackTracingCommandSequence ** dwarf_stack_trace_regs;
+extern StackFrameRegisterLocation ** dwarf_stack_trace_regs;
#endif /* ENABLE_ELF && ENABLE_DebugContext */
diff --git a/agent/tcf/services/dwarfio.c b/agent/tcf/services/dwarfio.c
index 34ee2c8b..ee3d477e 100644
--- a/agent/tcf/services/dwarfio.c
+++ b/agent/tcf/services/dwarfio.c
@@ -209,7 +209,7 @@ U4_T dio_ReadULEB128(void) {
int i = 0;
for (;; i += 7) {
U1_T n = dio_ReadU1();
- Res |= (n & 0x7Fu) << i;
+ Res |= (U4_T)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) break;
}
return Res;
@@ -220,9 +220,9 @@ I4_T dio_ReadSLEB128(void) {
int i = 0;
for (;; i += 7) {
U1_T n = dio_ReadU1();
- Res |= (n & 0x7Fu) << i;
+ Res |= (U4_T)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) {
- Res |= -(n & 0x40) << i;
+ Res |= -(I4_T)(n & 0x40) << i;
break;
}
}
@@ -234,7 +234,7 @@ U8_T dio_ReadU8LEB128(void) {
int i = 0;
for (;; i += 7) {
U1_T n = dio_ReadU1();
- Res |= (n & 0x7Fu) << i;
+ Res |= (U8_T)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) break;
}
return Res;
@@ -245,9 +245,9 @@ I8_T dio_ReadS8LEB128(void) {
int i = 0;
for (;; i += 7) {
U1_T n = dio_ReadU1();
- Res |= (n & 0x7Fu) << i;
+ Res |= (U8_T)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) {
- Res |= -(n & 0x40) << i;
+ Res |= -(I8_T)(n & 0x40) << i;
break;
}
}
@@ -507,6 +507,7 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) {
case AT_specification_v1:
case AT_specification_v2:
case AT_abstract_origin:
+ case AT_extension:
break;
default:
switch (Form) {
@@ -757,6 +758,7 @@ void dio_ChkBlock(U2_T Form, U1_T ** Buf, size_t * Size) {
case FORM_DATA2 :
case FORM_DATA4 :
case FORM_DATA8 :
+ case FORM_EXPRLOC :
case FORM_SEC_OFFSET:
assert(dio_gFormDataAddr >= sSection->data);
assert((U1_T *)dio_gFormDataAddr < (U1_T *)sSection->data + sSection->size);
diff --git a/agent/tcf/services/elf-loader.c b/agent/tcf/services/elf-loader.c
index 627741b0..7bb573d7 100644
--- a/agent/tcf/services/elf-loader.c
+++ b/agent/tcf/services/elf-loader.c
@@ -198,7 +198,7 @@ static ContextAddress find_module(Context * ctx, ELF_File * exe_file, ELF_File *
else if (strcmp(name, "l_tls_modid") == 0) offs_l_tls_modid = offs;
}
if (offs_l_addr == 0 || offs_l_next == 0 || offs_l_tls_modid == 0)
- str_exception(errno, "Invalid 'link_map' fields");
+ str_exception(ERR_OTHER, "Invalid 'link_map' fields");
while (link != 0) {
ContextAddress l_tls_modid = 0;
if (elf_read_memory_word(ctx, exe_file, link + offs_l_tls_modid, &l_tls_modid) < 0) exception(errno);
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index 6ba8b326..40b4852a 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -72,6 +72,8 @@
#define SY_SIZEOF 279
#define SY_NAME 280
#define SY_SCOPE 281
+#define SY_PM_D 282
+#define SY_PM_R 283
#define MODE_NORMAL 0
#define MODE_TYPE 1
@@ -289,7 +291,14 @@ static void next_sy(void) {
case ';':
case '?':
case ',':
+ text_sy = ch;
+ return;
case '.':
+ if (text_ch == '*') {
+ next_ch();
+ text_sy = SY_PM_D;
+ return;
+ }
text_sy = ch;
return;
case ':':
@@ -303,6 +312,11 @@ static void next_sy(void) {
case '-':
if (text_ch == '>') {
next_ch();
+ if (text_ch == '*') {
+ next_ch();
+ text_sy = SY_PM_R;
+ return;
+ }
text_sy = SY_REF;
return;
}
@@ -1156,14 +1170,33 @@ static void op_deref(int mode, Value * v) {
}
#if ENABLE_Symbols
-static void find_field(Symbol * sym, ContextAddress offs, const char * name, Symbol ** res, ContextAddress * res_offs) {
+static void evaluate_symbol_address(Symbol * sym, ContextAddress obj_addr, ContextAddress index, ContextAddress * addr) {
+ LocationExpressionState * state = NULL;
+ LocationInfo * loc_info = NULL;
+ StackFrame * stk_info = NULL;
+ uint64_t args[2];
+
+ args[0] = obj_addr;
+ args[1] = index;
+ if (get_location_info(sym, &loc_info) < 0) {
+ error(errno, "Cannot get symbol location expression");
+ }
+ if (get_frame_info(expression_context, expression_frame, &stk_info) < 0) {
+ error(errno, "Cannot get stack frame info");
+ }
+ state = evaluate_location_expression(expression_context, stk_info, loc_info->cmds, loc_info->cmds_cnt, args, 2);
+ if (state->stk_pos != 1) error(ERR_INV_EXPRESSION, "Cannot evaluate symbol address");
+ *addr = (ContextAddress)state->stk[0];
+}
+
+static void find_field(Symbol * class_sym, ContextAddress obj_addr, const char * name, const char * id, Symbol ** field_sym, ContextAddress * field_addr) {
Symbol ** children = NULL;
Symbol ** inheritance = NULL;
int count = 0;
int h = 0;
int i;
- if (get_symbol_children(sym, &children, &count) < 0) {
+ if (get_symbol_children(class_sym, &children, &count) < 0) {
error(errno, "Cannot retrieve field list");
}
for (i = 0; i < count; i++) {
@@ -1175,19 +1208,17 @@ static void find_field(Symbol * sym, ContextAddress offs, const char * name, Sym
if (inheritance == NULL) inheritance = (Symbol **)tmp_alloc(sizeof(Symbol *) * count);
inheritance[h++] = children[i];
}
- else if (strcmp(s, name) == 0) {
- *res = children[i];
- *res_offs = offs;
+ else if (name != NULL ? strcmp(s, name) == 0 : strcmp(symbol2id(children[i]), id) == 0) {
+ evaluate_symbol_address(children[i], obj_addr, 0, field_addr);
+ *field_sym = children[i];
return;
}
}
for (i = 0; i < h; i++) {
ContextAddress x = 0;
- if (get_symbol_offset(inheritance[i], &x) < 0) {
- error(errno, "Cannot retrieve field offset");
- }
- find_field(inheritance[i], offs + x, name, res, res_offs);
- if (*res != NULL) return;
+ evaluate_symbol_address(inheritance[i], obj_addr, 0, &x);
+ find_field(inheritance[i], x, name, id, field_sym, field_addr);
+ if (*field_sym != NULL) return;
}
}
#endif
@@ -1195,6 +1226,7 @@ static void find_field(Symbol * sym, ContextAddress offs, const char * name, Sym
static void op_field(int mode, Value * v) {
char * id = NULL;
char * name = NULL;
+ if (!v->remote) error(ERR_INV_EXPRESSION, "L-value expected");
if (text_sy == SY_ID) id = (char *)text_val.value;
else if (text_sy == SY_NAME) name = (char *)text_val.value;
else error(ERR_INV_EXPRESSION, "Field name expected");
@@ -1204,59 +1236,31 @@ static void op_field(int mode, Value * v) {
#if ENABLE_Symbols
Symbol * sym = NULL;
int sym_class = 0;
- ContextAddress size = 0;
- ContextAddress offs = 0;
+ ContextAddress addr = 0;
- if (id != NULL) {
- if (id2symbol(id, &sym) < 0) error(errno, "Invalid field ID");
- }
- else {
- find_field(v->type, 0, name, &sym, &offs);
- }
+ find_field(v->type, v->address, name, id, &sym, &addr);
if (sym == NULL) {
- error(ERR_SYM_NOT_FOUND, "Symbol not found");
+ error(ERR_SYM_NOT_FOUND, "Invalid field name or ID");
}
if (get_symbol_class(sym, &sym_class) < 0) {
error(errno, "Cannot retrieve symbol class");
}
if (sym_class == SYM_CLASS_FUNCTION) {
- ContextAddress word = 0;
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 (mode == MODE_NORMAL && get_symbol_address(sym, &word) < 0) {
- error(errno, "Cannot retrieve symbol address");
- }
- set_ctx_word_value(v, word);
+ set_ctx_word_value(v, addr);
v->function = 1;
}
else {
- ContextAddress x = 0;
- if (sym_class != SYM_CLASS_REFERENCE) {
- error(ERR_UNSUPPORTED, "Invalid symbol class");
- }
+ ContextAddress size = 0;
if (get_symbol_size(sym, &size) < 0) {
error(errno, "Cannot retrieve field size");
}
- if (get_symbol_offset(sym, &x) < 0) {
- error(errno, "Cannot retrieve field offset");
- }
- offs += x;
- if (v->sym != NULL && v->size == 0 && get_symbol_size(v->sym, &v->size) < 0) {
- error(errno, "Cannot retrieve symbol size");
- }
- if (offs + size > v->size) {
- error(ERR_INV_EXPRESSION, "Invalid field offset and/or size");
- }
- if (v->remote) {
- if (mode != MODE_TYPE) v->address += offs;
- }
- else {
- v->value = (uint8_t *)v->value + offs;
- }
+ v->address = addr;
+ v->size = size;
v->sym = NULL;
v->reg = NULL;
- v->size = size;
if (get_symbol_type(sym, &v->type) < 0) {
error(errno, "Cannot retrieve symbol type");
}
@@ -1641,13 +1645,50 @@ static void unary_expression(int mode, Value * v) {
#endif
}
-static void multiplicative_expression(int mode, Value * v) {
+static void pm_expression(int mode, Value * v) {
unary_expression(mode, v);
- while (text_sy == '*' || text_sy == '/' || text_sy == '%') {
+#if ENABLE_Symbols
+ while (text_sy == SY_PM_D || text_sy == SY_PM_R) {
Value x;
int sy = text_sy;
next_sy();
unary_expression(mode, &x);
+ if (x.type == NULL || x.type_class != TYPE_CLASS_MEMBER_PTR) {
+ error(ERR_INV_EXPRESSION, "Invalid type: pointer to member expected");
+ }
+ if (mode != MODE_SKIP) {
+ ContextAddress obj = 0;
+ ContextAddress ptr = 0;
+ ContextAddress addr = 0;
+ if (sy == SY_PM_D) {
+ if (!v->remote) error(ERR_INV_EXPRESSION, "L-value expected");
+ obj = v->address;
+ }
+ else {
+ obj = (ContextAddress)to_uns(mode, v);
+ }
+ ptr = (ContextAddress)to_uns(mode, &x);
+ evaluate_symbol_address(x.type, obj, ptr, &addr);
+ set_ctx_word_value(v, addr);
+ v->constant = 0;
+ if (get_symbol_base_type(x.type, &v->type) < 0) {
+ error(ERR_INV_EXPRESSION, "Cannot get pointed type");
+ }
+ if (get_symbol_type_class(x.type, &v->type_class) < 0) {
+ error(ERR_INV_EXPRESSION, "Cannot get pointed type class");
+ }
+ }
+ }
+#endif
+}
+
+static void multiplicative_expression(int mode, Value * v) {
+ pm_expression(mode, v);
+ while (text_sy == '*' || text_sy == '/' || text_sy == '%') {
+ Value x;
+ int sy = text_sy;
+ next_sy();
+ pm_expression(mode, &x);
if (mode != MODE_SKIP) {
if (!is_number(v) || !is_number(&x)) {
error(ERR_INV_EXPRESSION, "Numeric types expected");
diff --git a/agent/tcf/services/linenumbers.h b/agent/tcf/services/linenumbers.h
index fa4d5141..75519e67 100644
--- a/agent/tcf/services/linenumbers.h
+++ b/agent/tcf/services/linenumbers.h
@@ -26,8 +26,8 @@
#include <tcf/framework/context.h>
typedef struct CodeArea {
- char * directory;
- char * file;
+ const char * directory;
+ const char * file;
uint32_t file_mtime;
uint32_t file_size;
ContextAddress start_address;
diff --git a/agent/tcf/services/linenumbers_elf.c b/agent/tcf/services/linenumbers_elf.c
index 3415f932..37e22a0e 100644
--- a/agent/tcf/services/linenumbers_elf.c
+++ b/agent/tcf/services/linenumbers_elf.c
@@ -42,7 +42,7 @@
#include <tcf/services/stacktrace.h>
#include <tcf/services/pathmap.h>
-static int is_absolute_path(char * fnm) {
+static int is_absolute_path(const char * fnm) {
if (fnm[0] == '/') return 1;
if (fnm[0] == '\\') return 1;
if (fnm[0] != 0 && fnm[1] == ':') {
@@ -52,7 +52,7 @@ static int is_absolute_path(char * fnm) {
return 0;
}
-static int compare_path(Channel * chnl, Context * ctx, char * file, char * pwd, char * dir, char * name) {
+static int compare_path(Channel * chnl, Context * ctx, const char * file, const char * pwd, const char * dir, const char * name) {
int i, j;
char buf[FILE_PATH_SIZE];
char * full_name = NULL;
@@ -61,7 +61,7 @@ static int compare_path(Channel * chnl, Context * ctx, char * file, char * pwd,
if (name == NULL) return 0;
if (is_absolute_path(name)) {
- full_name = name;
+ full_name = (char *)name;
}
else if (dir != NULL && is_absolute_path(dir)) {
snprintf(full_name = buf, sizeof(buf), "%s/%s", dir, name);
@@ -73,7 +73,7 @@ static int compare_path(Channel * chnl, Context * ctx, char * file, char * pwd,
snprintf(full_name = buf, sizeof(buf), "%s/%s", pwd, name);
}
else {
- full_name = name;
+ full_name = (char *)name;
}
full_name = canonic_path_map_file_name(full_name);
#if SERVICE_PathMap
@@ -81,6 +81,11 @@ static int compare_path(Channel * chnl, Context * ctx, char * file, char * pwd,
full_name = apply_path_map(chnl, ctx, buf, PATH_MAP_TO_CLIENT);
if (full_name != buf) full_name = canonic_path_map_file_name(full_name);
#endif
+ while (file[0] == '.') {
+ if (file[1] == '.' && file[2] == '/') file += 3;
+ else if (file[1] == '/') file += 2;
+ else break;
+ }
i = strlen(file);
j = strlen(full_name);
return i <= j && strcmp(file, full_name + j - i) == 0;
@@ -97,18 +102,28 @@ static LineNumbersState * get_next_in_text(CompUnit * unit, LineNumbersState * s
return next;
}
+static LineNumbersState * get_next_in_code(CompUnit * unit, LineNumbersState * state) {
+ LineNumbersState * next = state + 1;
+ if (next >= unit->mStates + unit->mStatesCnt) return NULL;
+ if (state->mFlags & LINE_EndSequence) return NULL;
+ return next;
+}
+
static void call_client(CompUnit * unit, LineNumbersState * state,
ContextAddress state_addr, LineNumbersCallBack * client, void * args) {
CodeArea area;
- LineNumbersState * next = get_next_in_text(unit, state);
+ LineNumbersState * code_next = get_next_in_code(unit, state);
+ LineNumbersState * text_next = get_next_in_text(unit, state);
FileInfo * file_info = unit->mFiles + state->mFile;
- if (state->mAddress >= (state + 1)->mAddress) return;
+ if (code_next == NULL) return;
+ if (state->mAddress >= code_next->mAddress) return;
+
memset(&area, 0, sizeof(area));
area.start_line = state->mLine;
area.start_column = state->mColumn;
- area.end_line = next ? next->mLine : state->mLine;
- area.end_column = next ? next->mColumn : 0;
+ area.end_line = text_next ? text_next->mLine : state->mLine + 1;
+ area.end_column = text_next ? text_next->mColumn : 0;
area.directory = unit->mDir;
if (state->mFileName != NULL) {
@@ -130,8 +145,8 @@ static void call_client(CompUnit * unit, LineNumbersState * state,
area.file_mtime = file_info->mModTime;
area.file_size = file_info->mSize;
area.start_address = state_addr;
- area.end_address = (state + 1)->mAddress - state->mAddress + state_addr;
- if (next != NULL) area.next_address = next->mAddress;
+ area.end_address = code_next->mAddress - state->mAddress + state_addr;
+ if (text_next != NULL) area.next_address = text_next->mAddress;
area.isa = state->mISA;
area.is_statement = (state->mFlags & LINE_IsStmt) != 0;
area.basic_block = (state->mFlags & LINE_BasicBlock) != 0;
@@ -146,7 +161,7 @@ static void unit_line_to_address(Context * ctx, CompUnit * unit, unsigned file,
LineNumbersCallBack * client, void * args) {
if (unit->mStatesCnt >= 2) {
unsigned l = 0;
- unsigned h = unit->mStatesCnt - 1;
+ unsigned h = unit->mStatesCnt;
while (l < h) {
unsigned k = (h + l) / 2;
LineNumbersState * state = unit->mStatesIndex[k];
@@ -162,20 +177,22 @@ static void unit_line_to_address(Context * ctx, CompUnit * unit, unsigned file,
l = k + 1;
}
else {
- unsigned i = k;
- while (i > 0) {
- LineNumbersState * prev = unit->mStatesIndex[i - 1];
+ while (k > 0) {
+ LineNumbersState * prev = unit->mStatesIndex[k - 1];
if (prev->mFile != state->mFile) break;
if (prev->mLine != state->mLine) break;
if (prev->mColumn != state->mColumn) break;
state = prev;
- i--;
+ k--;
}
for (;;) {
ContextAddress addr = elf_map_to_run_time_address(ctx, unit->mFile, unit->mTextSection, state->mAddress);
if (errno == 0) call_client(unit, state, addr, client, args);
- if (i == k) break;
- state = unit->mStatesIndex[++i];
+ if (++k >= unit->mStatesCnt) break;
+ state = unit->mStatesIndex[k];
+ if (state->mFile > file) break;
+ if (state->mLine > line) break;
+ if (state->mColumn > column) break;
}
break;
}
@@ -252,12 +269,11 @@ int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, L
ContextAddress range_rt_addr = 0;
UnitAddressRange * range = elf_find_unit(ctx, addr0, addr1, &range_rt_addr);
if (range == NULL) break;
- assert(range_rt_addr != 0);
if (!range->mUnit->mLineInfoLoaded) load_line_numbers(range->mUnit);
if (range->mUnit->mStatesCnt >= 2) {
CompUnit * unit = range->mUnit;
unsigned l = 0;
- unsigned h = unit->mStatesCnt - 1;
+ unsigned h = unit->mStatesCnt;
ContextAddress addr_min = addr0 - range_rt_addr + range->mAddr;
ContextAddress addr_max = addr1 - range_rt_addr + range->mAddr;
if (addr_min < range->mAddr) addr_min = range->mAddr;
@@ -269,9 +285,8 @@ int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, L
h = k;
}
else {
- LineNumbersState * next = state + 1;
- assert(next->mAddress >= state->mAddress);
- if (next->mAddress <= addr_min) {
+ LineNumbersState * next = get_next_in_code(unit, state);
+ if (next != NULL && next->mAddress <= addr_min) {
l = k + 1;
}
else {
@@ -279,17 +294,14 @@ int address_to_line(Context * ctx, ContextAddress addr0, ContextAddress addr1, L
LineNumbersState * prev = unit->mStates + k - 1;
if (state->mAddress <= addr_min) break;
if (prev->mAddress >= addr_max) break;
- next = state;
state = prev;
k--;
}
for (;;) {
call_client(unit, state, state->mAddress - range->mAddr + range_rt_addr, client, args);
- k++;
- if (k >= unit->mStatesCnt - 1) break;
+ if (++k >= unit->mStatesCnt) break;
state = unit->mStates + k;
if (state->mAddress >= addr_max) break;
- next = state + 1;
}
break;
}
diff --git a/agent/tcf/services/pathmap.c b/agent/tcf/services/pathmap.c
index b3281c4a..bc8c020b 100644
--- a/agent/tcf/services/pathmap.c
+++ b/agent/tcf/services/pathmap.c
@@ -46,10 +46,13 @@ char * canonic_path_map_file_name(const char * fnm) {
if (buf_pos > 0 && *fnm == '.' && (fnm[1] == '/' || fnm[1] == '\\')) {
unsigned j = buf_pos - 1;
if (j > 0 && buf[j - 1] != '/') {
+ buf[buf_pos] = 0;
while (j > 0 && buf[j - 1] != '/') j--;
- buf_pos = j;
- fnm += 2;
- continue;
+ if (strcmp(buf + j, "./") && strcmp(buf + j, "../")) {
+ buf_pos = j;
+ fnm += 2;
+ continue;
+ }
}
}
}
diff --git a/agent/tcf/services/stacktrace.c b/agent/tcf/services/stacktrace.c
index 82fafeb8..d8035464 100644
--- a/agent/tcf/services/stacktrace.c
+++ b/agent/tcf/services/stacktrace.c
@@ -109,7 +109,7 @@ static void trace_stack(Context * ctx, StackTrace * stack) {
break;
}
#endif
- if (frame.fp == 0) {
+ if (frame.is_walked == 0) {
trace(LOG_STACK, " *** frame info not available ***");
loc_free(down.regs);
memset(&down, 0, sizeof(down));
diff --git a/agent/tcf/services/symbols.c b/agent/tcf/services/symbols.c
index 214b7976..a563a227 100644
--- a/agent/tcf/services/symbols.c
+++ b/agent/tcf/services/symbols.c
@@ -26,6 +26,7 @@
#include <tcf/framework/cache.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/symbols.h>
+#include <tcf/services/vm.h>
static const char * SYMBOLS = "Symbols";
@@ -47,6 +48,7 @@ static void command_get_context_cache_client(void * x) {
Symbol * type = NULL;
Symbol * base = NULL;
Symbol * index = NULL;
+ Symbol * container = NULL;
int has_size = 0;
int has_length = 0;
int has_lower_bound = 0;
@@ -75,6 +77,7 @@ static void command_get_context_cache_client(void * x) {
get_symbol_type(sym, &type);
get_symbol_base_type(sym, &base);
get_symbol_index_type(sym, &index);
+ get_symbol_containing_type(sym, &container);
has_size = get_symbol_size(sym, &size) == 0;
has_length = get_symbol_length(sym, &length) == 0;
if (has_length) {
@@ -159,6 +162,13 @@ static void command_get_context_cache_client(void * x) {
write_stream(&c->out, ',');
}
+ if (container != NULL) {
+ json_write_string(&c->out, "ContainigTypeID");
+ write_stream(&c->out, ':');
+ json_write_string(&c->out, symbol2id(container));
+ write_stream(&c->out, ',');
+ }
+
if (has_size) {
json_write_string(&c->out, "Size");
write_stream(&c->out, ':');
@@ -586,28 +596,36 @@ typedef struct CommandFindFrameInfo {
ContextAddress addr;
} CommandFindFrameInfo;
-static void write_commands(OutputStream * out, Context * ctx, StackTracingCommandSequence * seq) {
+static void write_commands(OutputStream * out, Context * ctx, StackFrameRegisterLocation * seq) {
if (seq != NULL) {
- int i;
+ unsigned i;
write_stream(out, '[');
for (i = 0; i < seq->cmds_cnt; i++) {
- StackTracingCommand * cmd = seq->cmds + i;
+ LocationExpressionCommand * cmd = seq->cmds + i;
if (i > 0) write_stream(out, ',');
json_write_long(out, cmd->cmd);
switch (cmd->cmd) {
case SFT_CMD_NUMBER:
write_stream(out, ',');
- json_write_int64(out, cmd->num);
+ json_write_int64(out, cmd->args.num);
break;
case SFT_CMD_REGISTER:
write_stream(out, ',');
- json_write_string(out, register2id(ctx, STACK_NO_FRAME, cmd->reg));
+ json_write_string(out, register2id(ctx, STACK_NO_FRAME, cmd->args.reg));
break;
case SFT_CMD_DEREF:
write_stream(out, ',');
- json_write_ulong(out, cmd->size);
+ json_write_ulong(out, cmd->args.deref.size);
+ write_stream(out, ',');
+ json_write_boolean(out, cmd->args.deref.big_endian);
+ break;
+ case SFT_CMD_USER:
+ write_stream(out, ',');
+ json_write_binary(out, cmd->args.user.code_addr, cmd->args.user.code_size);
write_stream(out, ',');
- json_write_boolean(out, cmd->big_endian);
+ /* TODO: SFT_CMD_USER parameters */
+ write_stream(out, '{');
+ write_stream(out, '}');
break;
}
}
diff --git a/agent/tcf/services/symbols.h b/agent/tcf/services/symbols.h
index 884699d2..aca6da0c 100644
--- a/agent/tcf/services/symbols.h
+++ b/agent/tcf/services/symbols.h
@@ -46,6 +46,7 @@ typedef struct Symbol Symbol;
#define TYPE_CLASS_COMPOSITE 6
#define TYPE_CLASS_ENUMERATION 7
#define TYPE_CLASS_FUNCTION 8
+#define TYPE_CLASS_MEMBER_PTR 9
typedef uint32_t SYM_FLAGS;
@@ -75,6 +76,35 @@ typedef uint32_t SYM_FLAGS;
typedef void EnumerateSymbolsCallBack(void *, Symbol *);
+#if ENABLE_DebugContext
+
+typedef struct LocationInfo {
+ ContextAddress addr;
+ ContextAddress size;
+ LocationExpressionCommand * cmds;
+ unsigned cmds_cnt;
+ unsigned cmds_max;
+} LocationInfo;
+
+/* Stack tracing command sequence */
+typedef struct StackFrameRegisterLocation {
+ RegisterDefinition * reg;
+ unsigned cmds_cnt;
+ unsigned cmds_max;
+ LocationExpressionCommand cmds[1];
+} StackFrameRegisterLocation;
+
+/* Complete stack tracing info for a range of instruction addresses */
+typedef struct StackTracingInfo {
+ ContextAddress addr;
+ ContextAddress size;
+ StackFrameRegisterLocation * fp;
+ StackFrameRegisterLocation ** regs;
+ int reg_cnt;
+} StackTracingInfo;
+
+#endif
+
#if ENABLE_Symbols
/*
@@ -119,7 +149,6 @@ extern const char * symbol2id(const Symbol * sym);
*/
extern int id2symbol(const char * id, Symbol ** sym);
-
/*************** Functions for retrieving symbol properties ***************************************/
/*
* Each function retireves one particular attribute of an object or type.
@@ -154,12 +183,16 @@ extern int get_symbol_name(const Symbol * sym, char ** name);
/* Get value size of the type, in bytes */
extern int get_symbol_size(const Symbol * sym, ContextAddress * size);
-/* Get base type ID */
+/* Get base type: pointer or member pointer - pointed object type,
+ * array - elements type, function - result type */
extern int get_symbol_base_type(const Symbol * sym, Symbol ** base_type);
-/* Get array index type ID */
+/* Get array index type */
extern int get_symbol_index_type(const Symbol * sym, Symbol ** index_type);
+/* Get containing type: field (member) or member pointer - parent structure */
+extern int get_symbol_containing_type(const Symbol * sym, Symbol ** containing_type);
+
/* Get array length (number of elements) */
extern int get_symbol_length(const Symbol * sym, ContextAddress * length);
@@ -200,6 +233,9 @@ extern int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol **
*/
extern ContextAddress is_plt_section(Context * ctx, ContextAddress addr);
+/* Get object location expression */
+extern int get_location_info(const Symbol * sym, LocationInfo ** info);
+
/*
* For given context and its registers in a stack frame,
* compute stack frame location and next frame register values.
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index 785d87db..b4b34a7e 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -38,9 +38,11 @@
#include <tcf/services/dwarf.h>
#include <tcf/services/dwarfcache.h>
#include <tcf/services/dwarfexpr.h>
+#include <tcf/services/dwarfecomp.h>
#include <tcf/services/dwarfframe.h>
#include <tcf/services/stacktrace.h>
#include <tcf/services/symbols.h>
+#include <tcf/services/vm.h>
#if ENABLE_RCBP_TEST
# include <tcf/main/test.h>
#endif
@@ -111,6 +113,12 @@ static struct BaseTypeAlias {
#define SYMBOL_MAGIC 0x34875234
+/* This function is used for DWARF testing */
+extern ObjectInfo * get_symbol_object(Symbol * sym);
+ObjectInfo * get_symbol_object(Symbol * sym) {
+ return sym->obj;
+}
+
static Symbol * alloc_symbol(void) {
Symbol * s = (Symbol *)tmp_alloc_zero(sizeof(Symbol));
s->magic = SYMBOL_MAGIC;
@@ -207,6 +215,7 @@ static int is_frame_based_object(Symbol * sym) {
case TAG_enumeration_type:
case TAG_pointer_type:
case TAG_reference_type:
+ case TAG_ptr_to_member_type:
return 0;
}
break;
@@ -369,7 +378,7 @@ static int get_num_prop(ObjectInfo * obj, U2_T at, U8_T * res) {
PropertyValue v;
if (!set_trap(&trap)) return 0;
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, at, &v);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, at, &v);
*res = get_numeric_property_value(&v);
clear_trap(&trap);
return 1;
@@ -395,7 +404,7 @@ static int check_in_range(ObjectInfo * obj, ContextAddress rt_offs, ContextAddre
U8_T offs = 0;
int res = 0;
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_ranges, &v);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_ranges, &v);
offs = get_numeric_property_value(&v);
dio_EnterSection(&unit->mDesc, debug_ranges, offs);
for (;;) {
@@ -424,46 +433,49 @@ static int check_in_range(ObjectInfo * obj, ContextAddress rt_offs, ContextAddre
return 0;
}
-static int map_to_sym_table(ObjectInfo * obj, Symbol ** sym);
-
/* If 'sym' represents a declaration, replace it with definition - if possible */
static ObjectInfo * find_definition(ObjectInfo * decl) {
- Symbol * sym = NULL;
if (decl == NULL) return NULL;
if (!(decl->mFlags & DOIF_declaration)) return decl;
if (decl->mDefinition != NULL) return decl->mDefinition;
- if (map_to_sym_table(decl, &sym) && sym->obj != NULL) return sym->obj;
return decl;
}
-static int find_in_object_tree(ObjectInfo * list, ContextAddress rt_offs, ContextAddress ip, const char * name, Symbol ** sym) {
+static int find_in_object_tree(ObjectInfo * parent, ContextAddress rt_offs, ContextAddress ip, const char * name, Symbol ** sym) {
Symbol * sym_imp = NULL; /* Imported from a namespace */
Symbol * sym_enu = NULL; /* Enumeration constant */
Symbol * sym_cur = NULL; /* Found in current scope */
Symbol * sym_base = NULL; /* Found in base class (inherited) */
Symbol * sym_this = NULL; /* Found in 'this' reference */
- ObjectInfo * obj = list;
+ ObjectInfo * obj = get_dwarf_children(parent);
+ U8_T obj_ptr = 0;
+
+ if (parent->mTag == TAG_subprogram) get_num_prop(parent, AT_object_pointer, &obj_ptr);
+
while (obj != NULL) {
if (obj->mName != NULL && !(obj->mFlags & DOIF_specification)) {
if (strcmp(obj->mName, name) == 0) {
object2symbol(obj, &sym_cur);
}
- if (sym_frame != STACK_NO_FRAME && (obj->mFlags & DOIF_artificial) && strcmp(obj->mName, "this") == 0) {
- ObjectInfo * type = get_original_type(obj);
- if ((type->mTag == TAG_pointer_type || type->mTag == TAG_mod_pointer) && type->mType != NULL) {
- type = get_original_type(type->mType);
- find_in_object_tree(get_dwarf_children(type), 0, 0, name, &sym_this);
- if (sym_this != NULL) {
- sym_this->ctx = sym_ctx;
- sym_this->frame = sym_frame;
- sym_this->var = obj;
+ if (parent->mTag == TAG_subprogram) {
+ if (obj->mID == obj_ptr || (obj_ptr == 0 && obj->mTag == TAG_formal_parameter &&
+ (obj->mFlags & DOIF_artificial) && strcmp(obj->mName, "this") == 0)) {
+ ObjectInfo * type = get_original_type(obj);
+ if ((type->mTag == TAG_pointer_type || type->mTag == TAG_mod_pointer) && type->mType != NULL) {
+ type = get_original_type(type->mType);
+ find_in_object_tree(type, 0, 0, name, &sym_this);
+ if (sym_this != NULL) {
+ sym_this->ctx = sym_ctx;
+ sym_this->frame = sym_frame;
+ sym_this->var = obj;
+ }
}
}
}
}
switch (obj->mTag) {
case TAG_enumeration_type:
- find_in_object_tree(get_dwarf_children(obj), 0, 0, name, &sym_enu);
+ find_in_object_tree(obj, 0, 0, name, &sym_enu);
break;
case TAG_global_subroutine:
case TAG_inlined_subroutine:
@@ -472,19 +484,19 @@ static int find_in_object_tree(ObjectInfo * list, ContextAddress rt_offs, Contex
case TAG_entry_point:
case TAG_lexical_block:
if (ip != 0 && check_in_range(obj, rt_offs, ip)) {
- if (find_in_object_tree(get_dwarf_children(obj), rt_offs, ip, name, sym)) return 1;
+ if (find_in_object_tree(obj, rt_offs, ip, name, sym)) return 1;
}
break;
case TAG_inheritance:
- find_in_object_tree(get_dwarf_children(obj->mType), 0, 0, name, &sym_base);
+ find_in_object_tree(obj->mType, 0, 0, name, &sym_base);
break;
case TAG_imported_module:
{
PropertyValue p;
ObjectInfo * module;
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_import, &p);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_import, &p);
module = find_object(get_dwarf_cache(obj->mCompUnit->mFile), (ContextAddress)p.mValue);
- if (module != NULL) find_in_object_tree(get_dwarf_children(module), 0, 0, name, &sym_imp);
+ if (module != NULL) find_in_object_tree(module, 0, 0, name, &sym_imp);
}
break;
}
@@ -495,7 +507,16 @@ static int find_in_object_tree(ObjectInfo * list, ContextAddress rt_offs, Contex
if (*sym == NULL) *sym = sym_this;
if (*sym == NULL) *sym = sym_enu;
if (*sym == NULL) *sym = sym_imp;
- if (*sym != NULL && sym_ip != 0) (*sym)->obj = find_definition((*sym)->obj);
+
+ if (*sym == NULL && (parent->mFlags & DOIF_extension)) {
+ PropertyValue p;
+ ObjectInfo * name_space;
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, parent, AT_extension, &p);
+ name_space = find_object(get_dwarf_cache(obj->mCompUnit->mFile), (ContextAddress)p.mValue);
+ if (name_space != NULL) find_in_object_tree(name_space, 0, 0, name, &sym_imp);
+ }
+
+ if (*sym != NULL) (*sym)->obj = find_definition((*sym)->obj);
return *sym != NULL;
}
@@ -505,9 +526,9 @@ static int find_in_dwarf(const char * name, Symbol ** sym) {
*sym = NULL;
if (range != NULL) {
CompUnit * unit = range->mUnit;
- if (find_in_object_tree(get_dwarf_children(unit->mObject), rt_addr - range->mAddr, sym_ip, name, sym)) return 1;
+ if (find_in_object_tree(unit->mObject, rt_addr - range->mAddr, sym_ip, name, sym)) return 1;
if (unit->mBaseTypes != NULL) {
- if (find_in_object_tree(get_dwarf_children(unit->mBaseTypes->mObject), 0, 0, name, sym)) return 1;
+ if (find_in_object_tree(unit->mBaseTypes->mObject, 0, 0, name, sym)) return 1;
}
}
return 0;
@@ -813,7 +834,7 @@ int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * s
DWARFCache * cache = get_dwarf_cache(get_dwarf_file(file));
UnitAddressRange * range = find_comp_unit_addr_range(cache, sym_ip, sym_ip);
if (range != NULL) {
- found = find_in_object_tree(get_dwarf_children(range->mUnit->mObject), 0, 0, name, res);
+ found = find_in_object_tree(range->mUnit->mObject, 0, 0, name, res);
}
if (!found) {
found = find_by_name_in_sym_table(cache, name, res);
@@ -834,7 +855,7 @@ int find_symbol_in_scope(Context * ctx, int frame, ContextAddress ip, Symbol * s
if (!found && !error && scope != NULL && scope->obj != NULL) {
Trap trap;
if (set_trap(&trap)) {
- found = find_in_object_tree(get_dwarf_children(scope->obj), 0, 0, name, res);
+ found = find_in_object_tree(scope->obj, 0, 0, name, res);
clear_trap(&trap);
}
else {
@@ -1000,7 +1021,6 @@ static void enumerate_local_vars(ObjectInfo * obj, int level, ContextAddress rt_
int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * call_back, void * args) {
Trap trap;
if (!set_trap(&trap)) return -1;
- if (frame == STACK_TOP_FRAME && (frame = get_top_frame(ctx)) < 0) exception(errno);
if (get_sym_context(ctx, frame, 0) < 0) exception(errno);
if (sym_ip != 0) {
ContextAddress rt_addr = 0;
@@ -1172,7 +1192,6 @@ ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
int get_stack_tracing_info(Context * ctx, ContextAddress rt_addr, StackTracingInfo ** info) {
/* TODO: no debug info exists for linux-gate.so, need to read stack tracing information from the kernel */
- /* TODO: support for separate debug info files */
ELF_File * file = NULL;
ELF_Section * sec = NULL;
ContextAddress lt_addr = 0;
@@ -1226,16 +1245,23 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) {
Trap trap;
if (set_trap(&trap)) {
int i;
- frame->fp = (ContextAddress)evaluate_stack_trace_commands(ctx, frame, info->fp);
+ LocationExpressionState * state;
+ state = evaluate_location_expression(ctx, frame, info->fp->cmds, info->fp->cmds_cnt, NULL, 0);
+ if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid stack trace expression");
+ frame->fp = (ContextAddress)state->stk[0];
+ frame->is_walked = 1;
for (i = 0; i < info->reg_cnt; i++) {
int ok = 0;
uint64_t v = 0;
Trap trap_reg;
if (set_trap(&trap_reg)) {
/* If a saved register value cannot be evaluated - ignore it */
- v = evaluate_stack_trace_commands(ctx, frame, info->regs[i]);
+ state = evaluate_location_expression(ctx, frame, info->regs[i]->cmds, info->regs[i]->cmds_cnt, NULL, 0);
+ if (state->stk_pos == 1) {
+ v = state->stk[0];
+ ok = 1;
+ }
clear_trap(&trap_reg);
- ok = 1;
}
if (ok && write_reg_value(down, info->regs[i]->reg, v) < 0) exception(errno);
}
@@ -1314,7 +1340,7 @@ static int map_to_sym_table(ObjectInfo * obj, Symbol ** sym) {
if (set_trap(&trap)) {
PropertyValue p;
DWARFCache * cache = get_dwarf_cache(obj->mCompUnit->mFile);
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_MIPS_linkage_name, &p);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_MIPS_linkage_name, &p);
if (p.mAddr != NULL) found = find_by_name_in_sym_table(cache, (char *)p.mAddr, sym);
clear_trap(&trap);
}
@@ -1322,8 +1348,77 @@ static int map_to_sym_table(ObjectInfo * obj, Symbol ** sym) {
return found;
}
+static U8_T read_string_length(ObjectInfo * obj);
+
+static int get_object_size(ObjectInfo * obj, unsigned dimension, U8_T * byte_size, U8_T * bit_size) {
+ U8_T n = 0, m = 0;
+ obj = find_definition(obj);
+ if (get_num_prop(obj, AT_byte_size, &n)) {
+ *byte_size = n;
+ return 1;
+ }
+ if (get_num_prop(obj, AT_bit_size, &n)) {
+ *byte_size = (n + 7) / 8;
+ *bit_size = n;
+ return 1;
+ }
+ switch (obj->mTag) {
+ case TAG_enumerator:
+ case TAG_formal_parameter:
+ case TAG_unspecified_parameters:
+ case TAG_template_type_param:
+ case TAG_global_variable:
+ case TAG_local_variable:
+ case TAG_variable:
+ case TAG_inheritance:
+ case TAG_member:
+ case TAG_constant:
+ case TAG_const_type:
+ case TAG_volatile_type:
+ case TAG_restrict_type:
+ case TAG_shared_type:
+ case TAG_typedef:
+ if (obj->mType == NULL) return 0;
+ return get_object_size(obj->mType, 0, byte_size, bit_size);
+ case TAG_global_subroutine:
+ case TAG_subroutine:
+ case TAG_subprogram:
+ if (obj->u.mAddr.mHighPC > obj->u.mAddr.mLowPC) {
+ *byte_size = obj->u.mAddr.mHighPC - obj->u.mAddr.mLowPC;
+ return 1;
+ }
+ return 0;
+ case TAG_string_type:
+ *byte_size = read_string_length(obj);
+ return 1;
+ case TAG_array_type:
+ {
+ unsigned i = 0;
+ U8_T length = 1;
+ ObjectInfo * idx = get_dwarf_children(obj);
+ while (idx != NULL) {
+ if (i++ >= dimension) length *= get_array_index_length(idx);
+ idx = idx->mSibling;
+ }
+ if (get_num_prop(obj, AT_stride_size, &n)) {
+ *byte_size = (n * length + 7) / 8;
+ *bit_size = n * length;
+ return 1;
+ }
+ if (obj->mType == NULL) return 0;
+ if (!get_object_size(obj->mType, 0, &n, &m)) return 0;
+ if (m != 0) {
+ *byte_size = (m * length + 7) / 8;
+ *bit_size = m * length;
+ }
+ *byte_size = n * length;
+ }
+ return 1;
+ }
+ return 0;
+}
+
static void read_object_value(PropertyValue * v, void ** value, size_t * size, int * big_endian) {
- assert(v->mForm == FORM_EXPR_VALUE);
if (v->mPieces != NULL) {
U4_T n = 0;
U1_T * bf = NULL;
@@ -1331,27 +1426,27 @@ static void read_object_value(PropertyValue * v, void ** value, size_t * size, i
U4_T bf_offs = 0;
while (n < v->mPieceCnt) {
U4_T i;
- PropertyValuePiece * piece = v->mPieces + n++;
- U4_T piece_size = (piece->mBitSize + 7) / 8;
+ LocationPiece * piece = v->mPieces + n++;
+ U4_T piece_size = piece->size ? piece->size : (piece->bit_offs + piece->bit_size + 7) / 8;
+ U4_T piece_bits = piece->bit_size ? piece->bit_size : piece->size * 8;
U1_T * pbf = (U1_T *)tmp_alloc(piece_size);
if (bf_size < bf_offs / 8 + piece_size + 1) {
bf_size = bf_offs / 8 + piece_size + 1;
bf = (U1_T *)tmp_realloc(bf, bf_size);
}
- if (piece->mRegister) {
+ if (piece->reg) {
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);
+ if (read_reg_bytes(frame, piece->reg, 0, piece_size, pbf) < 0) exception(errno);
}
- else if (piece->mValue) {
- memcpy(pbf, piece->mValue, piece_size);
+ else if (piece->value) {
+ memcpy(pbf, piece->value, piece_size);
}
else {
- if (context_read_mem(v->mContext, piece->mAddress, pbf, piece_size) < 0) exception(errno);
+ if (context_read_mem(v->mContext, piece->addr, 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 (!piece->big_endian != !v->mBigEndian) swap_bytes(pbf, piece_size);
+ for (i = piece->bit_offs; i < piece->bit_offs + piece_bits; i++) {
if (pbf[i / 8] & (1u << (i % 8))) {
bf[bf_offs / 8] |= (1u << (bf_offs % 8));
}
@@ -1369,29 +1464,6 @@ static void read_object_value(PropertyValue * v, void ** value, size_t * size, i
*size = bf_offs / 8;
*big_endian = v->mBigEndian;
}
- else if (v->mRegister != NULL) {
- StackFrame * frame = NULL;
- RegisterDefinition * def = v->mRegister;
- ContextAddress sym_size = 0;
- ContextAddress bit_size = 0;
- unsigned val_offs = 0;
- unsigned val_size = 0;
- U1_T * bf = NULL;
- U8_T n = 0;
-
- if (get_num_prop(v->mObject, AT_byte_size, &n)) sym_size = (ContextAddress)n;
- else if (get_num_prop(v->mObject, AT_bit_size, &n)) sym_size = ((bit_size = (ContextAddress)n) + 7) / 8;
- else sym_size = def->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;
- bf = (U1_T *)tmp_alloc(val_size);
- if (read_reg_bytes(frame, def, val_offs, val_size, bf) < 0) exception(errno);
- if (bit_size % 8 != 0) bf[bit_size / 8] &= (1 << (bit_size % 8)) - 1;
- *value = bf;
- *size = val_size;
- *big_endian = def->big_endian;
- }
else if (v->mAddr != NULL) {
*value = v->mAddr;
*size = v->mSize;
@@ -1399,19 +1471,17 @@ static void read_object_value(PropertyValue * v, void ** value, size_t * size, i
}
else {
U1_T * bf = NULL;
- size_t val_size = 0;
- size_t bit_size = 0;
- U8_T n = 0;
+ U8_T val_size = 0;
+ U8_T bit_size = 0;
- if (get_num_prop(v->mObject, AT_byte_size, &n)) val_size = (size_t)n;
- else if (get_num_prop(v->mObject, AT_bit_size, &n)) val_size = ((bit_size = (size_t)n) + 7) / 8;
+ if (get_object_size(v->mObject, 0, &val_size, &bit_size)) {}
else if (v->mAttr == AT_string_length) val_size = v->mObject->mCompUnit->mDesc.mAddressSize;
else str_exception(ERR_INV_DWARF, "Unknown object size");
- bf = (U1_T *)tmp_alloc(val_size);
- if (context_read_mem(sym_ctx, (ContextAddress)v->mValue, bf, val_size) < 0) exception(errno);
+ bf = (U1_T *)tmp_alloc((size_t)val_size);
+ if (context_read_mem(sym_ctx, (ContextAddress)v->mValue, bf, (size_t)val_size) < 0) exception(errno);
if (bit_size % 8 != 0) bf[bit_size / 8] &= (1 << (bit_size % 8)) - 1;
*value = bf;
- *size = val_size;
+ *size = (size_t)val_size;
*big_endian = v->mBigEndian;
}
}
@@ -1437,7 +1507,7 @@ static U8_T read_string_length(ObjectInfo * obj) {
if (set_trap(&trap)) {
PropertyValue v;
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_string_length, &v);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_string_length, &v);
len = read_cardinal_object_value(&v);
clear_trap(&trap);
return len;
@@ -1446,7 +1516,7 @@ static U8_T read_string_length(ObjectInfo * obj) {
exception(trap.error);
}
if (get_num_prop(obj, AT_byte_size, &len)) return len;
- str_exception(ERR_INV_DWARF, "Unknown lemgth of a string type");
+ str_exception(ERR_INV_DWARF, "Unknown length of a string type");
return 0;
}
@@ -1530,6 +1600,9 @@ int get_symbol_type_class(const Symbol * sym, int * type_class) {
case TAG_mod_reference:
*type_class = TYPE_CLASS_POINTER;
return 0;
+ case TAG_ptr_to_member_type:
+ *type_class = TYPE_CLASS_MEMBER_PTR;
+ return 0;
case TAG_class_type:
case TAG_structure_type:
case TAG_union_type:
@@ -1653,7 +1726,7 @@ int get_symbol_name(const Symbol * sym, char ** name) {
*name = (char *)constant_pseudo_symbols[(int)sym->length].name;
}
else if (sym->obj != NULL) {
- *name = sym->obj->mName;
+ *name = (char *)sym->obj->mName;
}
else if (sym->tbl != NULL) {
ELF_SymbolInfo info;
@@ -1694,86 +1767,42 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) {
if (unpack(sym) < 0) return -1;
*size = 0;
if (obj != NULL) {
- Trap trap;
int ok = 0;
U8_T sz = 0;
+ U8_T n = 0;
- if (!set_trap(&trap)) return -1;
- if (sym->dimension == 0 && obj->mTag != TAG_string_type) {
- ok = get_num_prop(obj, AT_byte_size, &sz);
- }
- if (!ok && sym->sym_class == SYM_CLASS_FUNCTION) {
- if (obj->u.mAddr.mHighPC > obj->u.mAddr.mLowPC) {
- ok = 1;
- sz = obj->u.mAddr.mHighPC - obj->u.mAddr.mLowPC;
- }
- }
- else if (!ok) {
- ObjectInfo * ref = NULL;
- if (sym->sym_class == SYM_CLASS_REFERENCE) {
- ref = obj;
- if (obj->mType != NULL) {
- obj = obj->mType;
- if (sym->dimension == 0) ok = get_num_prop(obj, AT_byte_size, &sz);
- }
- }
- while (!ok && obj->mType != NULL) {
- if (!is_modified_type(obj) && obj->mTag != TAG_enumeration_type) break;
- obj = find_definition(obj->mType);
- if (sym->dimension == 0) ok = get_num_prop(obj, AT_byte_size, &sz);
- }
- if (!ok && obj->mTag == TAG_array_type) {
- unsigned i = 0;
- U8_T length = 1;
- ObjectInfo * elem_type = obj->mType;
- ObjectInfo * idx = get_dwarf_children(obj);
- while (idx != NULL) {
- if (i++ >= sym->dimension) length *= get_array_index_length(idx);
- idx = idx->mSibling;
- }
- ok = get_num_prop(obj, AT_stride_size, &sz);
- if (ok) {
- sz = (sz * length + 7) / 8;
- }
- else {
- if (elem_type == NULL) str_exception(ERR_OTHER, "Unknown array element type");
- ok = get_num_prop(elem_type, AT_byte_size, &sz);
- while (!ok && elem_type->mType != NULL) {
- if (!is_modified_type(elem_type) && elem_type->mTag != TAG_enumeration_type) break;
- elem_type = elem_type->mType;
- ok = get_num_prop(elem_type, AT_byte_size, &sz);
+ ok = get_object_size(obj, sym->dimension, &sz, &n);
+ if (!ok && sym->sym_class == SYM_CLASS_REFERENCE) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ PropertyValue v;
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_location, &v);
+ if (v.mPieces) {
+ U4_T i = 0, j = 0;
+ while (i < v.mPieceCnt) {
+ LocationPiece * p = v.mPieces + i++;
+ if (p->bit_size) j += p->bit_size;
+ else sz += p->size;
}
- if (ok) sz *= length;
+ sz += (j + 7) / 8;
+ ok = 1;
}
+ clear_trap(&trap);
}
- if (!ok && obj->mTag == TAG_string_type) {
- sz = read_string_length(obj);
+ }
+ if (!ok && sym->sym_class == SYM_CLASS_REFERENCE) {
+ Symbol * elf_sym = NULL;
+ ContextAddress elf_sym_size = 0;
+ if (map_to_sym_table(obj, &elf_sym) && get_symbol_size(elf_sym, &elf_sym_size) == 0) {
+ sz = elf_sym_size;
ok = 1;
}
- if (!ok && ref && ref->mTag != TAG_member && ref->mTag != TAG_inheritance) {
- Trap trap;
- if (set_trap(&trap)) {
- PropertyValue v;
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, ref, AT_location, &v);
- if (v.mRegister) {
- sz = v.mRegister->size;
- ok = 1;
- }
- clear_trap(&trap);
- }
- }
- if (!ok && ref != NULL) {
- Symbol * elf_sym = NULL;
- ContextAddress elf_sym_size = 0;
- if (map_to_sym_table(ref, &elf_sym) && get_symbol_size(elf_sym, &elf_sym_size) == 0) {
- sz = elf_sym_size;
- ok = 1;
- }
- }
}
- if (!ok) str_exception(ERR_INV_DWARF, "Object has no size attribute");
+ if (!ok) {
+ set_errno(ERR_INV_DWARF, "Object has no size attribute");
+ return -1;
+ }
*size = (ContextAddress)sz;
- clear_trap(&trap);
}
else if (sym->tbl != NULL) {
ELF_SymbolInfo info;
@@ -1892,6 +1921,31 @@ int get_symbol_index_type(const Symbol * sym, Symbol ** index_type) {
return -1;
}
+int get_symbol_containing_type(const Symbol * sym, Symbol ** containing_type) {
+ ObjectInfo * obj = sym->obj;
+ if (obj != NULL) {
+ if (unpack(sym) < 0) return -1;
+ if (obj->mTag == TAG_ptr_to_member_type) {
+ U8_T id = 0;
+ if (get_num_prop(obj, AT_constaining_type, &id)) {
+ ObjectInfo * type = find_object(get_dwarf_cache(obj->mCompUnit->mFile), (ContextAddress)id);
+ if (type != NULL) {
+ object2symbol(type, containing_type);
+ return 0;
+ }
+ }
+ set_errno(ERR_INV_DWARF, "Invalid AT_constaining_type attribute");
+ return -1;
+ }
+ if (obj->mTag == TAG_member && obj->mParent != NULL) {
+ object2symbol(obj->mParent, containing_type);
+ return 0;
+ }
+ }
+ errno = ERR_UNSUPPORTED;
+ return -1;
+}
+
int get_symbol_length(const Symbol * sym, ContextAddress * length) {
ObjectInfo * obj = sym->obj;
assert(sym->magic == SYMBOL_MAGIC);
@@ -2060,6 +2114,7 @@ int get_symbol_offset(const Symbol * sym, ContextAddress * offset) {
if (unpack(sym) < 0) return -1;
if (obj != NULL && (obj->mTag == TAG_member || obj->mTag == TAG_inheritance)) {
U8_T v;
+ dwarf_expression_obj_addr = 0;
if (get_num_prop(obj, AT_data_member_location, &v)) {
*offset = (ContextAddress)v;
return 0;
@@ -2100,26 +2155,8 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big
Trap trap;
PropertyValue v;
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 {
- U8_T n = v.mValue;
- size_t i = 0;
- U1_T * bf = (U1_T *)tmp_alloc(sizeof(v.mValue));
- for (i = 0; i < sizeof(v.mValue); i++) {
- bf[v.mBigEndian ? sizeof(v.mValue) - i - 1 : i] = n & 0xffu;
- n = n >> 8;
- }
- *size = sizeof(v.mValue);
- *value = bf;
- }
- *big_endian = v.mBigEndian;
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_const_value, &v);
+ read_object_value(&v, value, size, big_endian);
clear_trap(&trap);
return 0;
}
@@ -2127,7 +2164,7 @@ int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big
return -1;
}
if (set_trap(&trap)) {
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_location, &v);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_location, &v);
read_object_value(&v, value, size, big_endian);
clear_trap(&trap);
return 0;
@@ -2170,14 +2207,16 @@ static int calc_member_offset(ObjectInfo * type, ObjectInfo * member, ContextAdd
PropertyValue v;
ObjectInfo * obj = NULL;
if (member->mParent == type) {
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, member, AT_data_member_location, &v);
+ dwarf_expression_obj_addr = 0;
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, member, AT_data_member_location, &v);
*offs = (ContextAddress)get_numeric_property_value(&v);
return 1;
}
obj = get_dwarf_children(type);
while (obj != NULL) {
if (obj->mTag == TAG_inheritance && calc_member_offset(obj->mType, member, offs)) {
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_data_member_location, &v);
+ dwarf_expression_obj_addr = 0;
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_data_member_location, &v);
*offs += (ContextAddress)get_numeric_property_value(&v);
return 1;
}
@@ -2186,19 +2225,178 @@ static int calc_member_offset(ObjectInfo * type, ObjectInfo * member, ContextAdd
return 0;
}
-int get_symbol_address(const Symbol * sym, ContextAddress * address) {
+static LocationInfo * location_info = NULL;
+static LocationExpressionState * user_command_state = NULL;
+
+static void user_command_client_op(uint8_t op) {
+ switch (op) {
+#if 0
+ case OP_addr:
+ U8_T addr = dio_ReadAddress(&section);
+ addr = elf_map_to_run_time_address(user_command_state->ctx, Unit->mFile, section, (ContextAddress)addr);
+ if (errno) str_exception(errno, "Cannot get object run-time address");
+ user_command_state->stk[user_command_state->stk_pos++] = addr;
+ break;
+#endif
+ default:
+ str_fmt_exception(ERR_UNSUPPORTED, "Unsupported location expression op 0x%02x", op);
+ break;
+ }
+}
+
+static int user_command_callback(LocationExpressionState * state) {
+ user_command_state = state;
+ state->client_op = user_command_client_op;
+ return evaluate_vm_expression(state);
+}
+
+static LocationExpressionCommand * add_location_command(int op) {
+ LocationExpressionCommand * cmd = NULL;
+ if (location_info->cmds_cnt >= location_info->cmds_max) {
+ location_info->cmds_max += 4;
+ location_info->cmds = (LocationExpressionCommand *)tmp_realloc(location_info->cmds,
+ sizeof(LocationExpressionCommand) * location_info->cmds_max);
+ }
+ cmd = location_info->cmds + location_info->cmds_cnt++;
+ memset(cmd, 0, sizeof(LocationExpressionCommand));
+ cmd->cmd = op;
+ return cmd;
+}
+
+static LocationExpressionCommand * add_user_command(PropertyValue * v) {
+ DWARFExpressionInfo info;
+ LocationExpressionCommand * cmd = add_location_command(SFT_CMD_USER);
+
+ dwarf_find_expression(v, sym_ip, &info);
+ dwarf_transform_expression(sym_ctx, sym_ip, &info);
+ location_info->addr = info.code_addr;
+ location_info->size = info.code_size;
+ cmd->args.user.code_addr = info.expr_addr;
+ cmd->args.user.code_size = info.expr_size;
+ cmd->args.user.reg_id_scope = v->mObject->mCompUnit->mRegIdScope;
+ cmd->args.user.addr_size = v->mObject->mCompUnit->mDesc.mAddressSize;
+ cmd->args.user.big_endian = v->mBigEndian;
+ cmd->args.user.func = user_command_callback;
+ return cmd;
+}
+
+int get_location_info(const Symbol * sym, LocationInfo ** info) {
ObjectInfo * obj = sym->obj;
+
assert(sym->magic == SYMBOL_MAGIC);
+ *info = location_info = (LocationInfo *)tmp_alloc_zero(sizeof(LocationInfo));
+
+ if (sym->has_address) {
+ add_location_command(SFT_CMD_NUMBER)->args.num = sym->address;
+ return 0;
+ }
+
if (is_array_type_pseudo_symbol(sym) ||
is_cardinal_type_pseudo_symbol(sym) ||
is_constant_pseudo_symbol(sym)) {
errno = ERR_INV_CONTEXT;
return -1;
}
+
+ if (unpack(sym) < 0) return -1;
+
+ if (obj != NULL) {
+ Trap trap;
+ PropertyValue v;
+ if (obj->mTag == TAG_ptr_to_member_type) {
+ if (set_trap(&trap)) {
+ read_dwarf_object_property(sym_ctx, sym_frame, obj, AT_use_location, &v);
+ add_location_command(SFT_CMD_ARG)->args.arg_no = 1;
+ add_location_command(SFT_CMD_ARG)->args.arg_no = 0;
+ add_user_command(&v);
+ clear_trap(&trap);
+ return 0;
+ }
+ else {
+ if (errno != ERR_SYM_NOT_FOUND) set_errno(errno, "Cannot evaluate member location expression");
+ else set_errno(ERR_OTHER, "Member location info not avaiable");
+ return -1;
+ }
+ }
+ if (obj->mTag == TAG_member || obj->mTag == TAG_inheritance) {
+ if (set_trap(&trap)) {
+ read_dwarf_object_property(sym_ctx, sym_frame, obj, AT_data_member_location, &v);
+ switch (v.mForm) {
+ case FORM_DATA1 :
+ case FORM_DATA4 :
+ case FORM_DATA8 :
+ case FORM_SDATA :
+ case FORM_UDATA :
+ add_location_command(SFT_CMD_ARG)->args.arg_no = 0;
+ add_location_command(SFT_CMD_NUMBER)->args.num = get_numeric_property_value(&v);
+ add_location_command(SFT_CMD_ADD);
+ break;
+ case FORM_BLOCK1 :
+ case FORM_BLOCK2 :
+ case FORM_BLOCK4 :
+ case FORM_BLOCK :
+ add_location_command(SFT_CMD_ARG)->args.arg_no = 0;
+ add_user_command(&v);
+ break;
+ }
+ clear_trap(&trap);
+ return 0;
+ }
+ else {
+ if (errno != ERR_SYM_NOT_FOUND) set_errno(errno, "Cannot evaluate member location expression");
+ else set_errno(ERR_OTHER, "Member location info not avaiable");
+ return -1;
+ }
+ }
+ {
+ U8_T addr = 0;
+ Symbol * s = NULL;
+ if (set_trap(&trap)) {
+ read_dwarf_object_property(sym_ctx, sym_frame, obj, AT_location, &v);
+ add_user_command(&v);
+ clear_trap(&trap);
+ return 0;
+ }
+ else if (errno != ERR_SYM_NOT_FOUND) {
+ set_errno(errno, "Cannot evaluate location expression");
+ return -1;
+ }
+ if (get_num_prop(obj, AT_low_pc, &addr)) {
+ add_location_command(SFT_CMD_NUMBER)->args.num = addr;
+ return 0;
+ }
+ if (get_error_code(errno) != ERR_SYM_NOT_FOUND) return -1;
+ if (map_to_sym_table(obj, &s)) return get_location_info(s, info);
+ }
+ }
+
+ if (sym->tbl != NULL) {
+ ELF_SymbolInfo info;
+ ContextAddress addr = 0;
+ unpack_elf_symbol_info(sym->tbl, sym->index, &info);
+ if (syminfo2address(sym_ctx, &info, &addr) < 0) return -1;
+ add_location_command(SFT_CMD_NUMBER)->args.num = addr;
+ return 0;
+ }
+
+ set_errno(ERR_OTHER, "No object location info found in DWARF data");
+ return -1;
+}
+
+int get_symbol_address(const Symbol * sym, ContextAddress * address) {
+ ObjectInfo * obj = sym->obj;
+
+ assert(sym->magic == SYMBOL_MAGIC);
if (sym->has_address) {
*address = sym->address;
return 0;
}
+ if (is_array_type_pseudo_symbol(sym) ||
+ is_cardinal_type_pseudo_symbol(sym) ||
+ is_constant_pseudo_symbol(sym)) {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
if (unpack(sym) < 0) return -1;
if (obj != NULL && (obj->mFlags & DOIF_external) == 0 && sym->var != NULL) {
/* The symbol represents a member of a class instance */
@@ -2213,7 +2411,7 @@ int get_symbol_address(const Symbol * sym, ContextAddress * address) {
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);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, sym->var, AT_location, &v);
base = (ContextAddress)read_cardinal_object_value(&v);
type = get_original_type(type->mType);
if (!calc_member_offset(type, obj, &offs)) exception(ERR_INV_CONTEXT);
@@ -2250,29 +2448,28 @@ int get_symbol_address(const Symbol * sym, ContextAddress * address) {
int get_symbol_register(const Symbol * sym, Context ** ctx, int * frame, RegisterDefinition ** reg) {
ObjectInfo * obj = sym->obj;
+
assert(sym->magic == SYMBOL_MAGIC);
- if (is_array_type_pseudo_symbol(sym) ||
- is_cardinal_type_pseudo_symbol(sym) ||
- is_constant_pseudo_symbol(sym) ||
- sym->has_address) {
- errno = ERR_INV_CONTEXT;
- return -1;
- }
- if (unpack(sym) < 0) return -1;
- if (obj != NULL && obj->mTag != TAG_member && obj->mTag != TAG_inheritance) {
+ if (!sym->has_address && obj != NULL && obj->mTag != TAG_member && obj->mTag != TAG_inheritance) {
Trap trap;
+ if (unpack(sym) < 0) return -1;
if (set_trap(&trap)) {
PropertyValue v;
- read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, 0, obj, AT_location, &v);
+ read_and_evaluate_dwarf_object_property(sym_ctx, sym_frame, obj, AT_location, &v);
*ctx = sym_ctx;
*frame = sym_frame;
- *reg = v.mRegister;
+ if (v.mPieceCnt == 1 && v.mPieces[0].reg != NULL && v.mPieces[0].bit_size == 0) {
+ *reg = v.mPieces[0].reg;
+ }
+ else {
+ *reg = NULL;
+ }
clear_trap(&trap);
return 0;
}
}
- errno = ERR_INV_CONTEXT;
+ set_errno(ERR_OTHER, "Symbol is not located in a register");
return -1;
}
diff --git a/agent/tcf/services/symbols_proxy.c b/agent/tcf/services/symbols_proxy.c
index 7b39a2fc..ef986fc1 100644
--- a/agent/tcf/services/symbols_proxy.c
+++ b/agent/tcf/services/symbols_proxy.c
@@ -145,8 +145,8 @@ typedef struct StackFrameCache {
uint64_t address;
uint64_t size;
- StackTracingCommandSequence * fp;
- StackTracingCommandSequence ** regs;
+ StackFrameRegisterLocation * fp;
+ StackFrameRegisterLocation ** regs;
int regs_cnt;
int disposed;
@@ -297,6 +297,17 @@ static void free_list_sym_cache(ListSymCache * c) {
}
}
+static void free_sft_sequence(StackFrameRegisterLocation * seq) {
+ if (seq != NULL) {
+ unsigned i = 0;
+ while (i < seq->cmds_cnt) {
+ LocationExpressionCommand * cmd = seq->cmds + i++;
+ if (cmd->cmd == SFT_CMD_USER) loc_free(cmd->args.user.code_addr);
+ }
+ loc_free(seq);
+ }
+}
+
static void free_stack_frame_cache(StackFrameCache * c) {
list_remove(&c->link_syms);
c->disposed = 1;
@@ -305,9 +316,9 @@ static void free_stack_frame_cache(StackFrameCache * c) {
cache_dispose(&c->cache);
release_error_report(c->error);
context_unlock(c->ctx);
- for (i = 0; i < c->regs_cnt; i++) loc_free(c->regs[i]);
+ for (i = 0; i < c->regs_cnt; i++) free_sft_sequence(c->regs[i]);
+ free_sft_sequence(c->fp);
loc_free(c->regs);
- loc_free(c->fp);
loc_free(c);
}
}
@@ -832,6 +843,11 @@ int get_symbol_index_type(const Symbol * sym, Symbol ** type) {
return 0;
}
+int get_symbol_containing_type(const Symbol * sym, Symbol ** containing_type) {
+ errno = ERR_UNSUPPORTED;
+ return -1;
+}
+
int get_symbol_size(const Symbol * sym, ContextAddress * size) {
SymInfoCache * c = get_sym_info_cache(sym);
if (c == NULL) return -1;
@@ -1073,27 +1089,60 @@ int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol ** ptr) {
static int trace_cmds_cnt = 0;
static int trace_cmds_max = 0;
-static StackTracingCommand * trace_cmds = NULL;
+static LocationExpressionCommand * trace_cmds = NULL;
static int trace_regs_cnt = 0;
static int trace_regs_max = 0;
-static StackTracingCommandSequence ** trace_regs = NULL;
+static StackFrameRegisterLocation ** trace_regs = NULL;
static int trace_error = 0;
+static LocationInfo * location_info = NULL;
+
ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
/* TODO: is_plt_section() in symbols proxy */
return 0;
}
+static LocationExpressionCommand * add_location_command(int op) {
+ LocationExpressionCommand * cmd = NULL;
+ if (location_info->cmds_cnt >= location_info->cmds_max) {
+ location_info->cmds_max += 4;
+ location_info->cmds = (LocationExpressionCommand *)tmp_realloc(location_info->cmds,
+ sizeof(LocationExpressionCommand) * location_info->cmds_max);
+ }
+ cmd = location_info->cmds + location_info->cmds_cnt++;
+ memset(cmd, 0, sizeof(LocationExpressionCommand));
+ cmd->cmd = op;
+ return cmd;
+}
+
+int get_location_info(const Symbol * sym, LocationInfo ** loc) {
+ SymInfoCache * c = get_sym_info_cache(sym);
+ if (c == NULL) return -1;
+ *loc = location_info = (LocationInfo *)tmp_alloc_zero(sizeof(LocationInfo));
+ if (c->has_address) {
+ add_location_command(SFT_CMD_NUMBER)->args.num = c->address;
+ return 0;
+ }
+ if (c->has_offset) {
+ add_location_command(SFT_CMD_ARG)->args.arg_no = 0;
+ add_location_command(SFT_CMD_NUMBER)->args.num = c->offset;
+ add_location_command(SFT_CMD_ADD);
+ return 0;
+ }
+ set_errno(ERR_OTHER, "No object location info found");
+ return -1;
+}
+
static void read_stack_trace_command(InputStream * inp, void * args) {
char id[256];
Context * ctx = NULL;
int frame = STACK_NO_FRAME;
- StackTracingCommand * cmd = NULL;
+ LocationExpressionCommand * cmd = NULL;
if (trace_cmds_cnt >= trace_cmds_max) {
trace_cmds_max += 16;
- trace_cmds = (StackTracingCommand *)loc_realloc(trace_cmds, trace_cmds_max * sizeof(StackTracingCommand));
+ trace_cmds = (LocationExpressionCommand *)loc_realloc(trace_cmds, trace_cmds_max * sizeof(LocationExpressionCommand));
}
cmd = trace_cmds + trace_cmds_cnt++;
memset(cmd, 0, sizeof(*cmd));
@@ -1101,18 +1150,22 @@ static void read_stack_trace_command(InputStream * inp, void * args) {
switch (cmd->cmd) {
case SFT_CMD_NUMBER:
if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
- cmd->num = json_read_int64(inp);
+ cmd->args.num = json_read_int64(inp);
break;
case SFT_CMD_REGISTER:
if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
json_read_string(inp, id, sizeof(id));
- if (id2register(id, &ctx, &frame, &cmd->reg) < 0) trace_error = errno;
+ if (id2register(id, &ctx, &frame, &cmd->args.reg) < 0) trace_error = errno;
break;
case SFT_CMD_DEREF:
if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
- cmd->size = json_read_ulong(inp);
+ cmd->args.deref.size = json_read_ulong(inp);
if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
- cmd->big_endian = json_read_boolean(inp);
+ cmd->args.deref.big_endian = json_read_boolean(inp);
+ break;
+ case SFT_CMD_USER:
+ if (read_stream(inp) != ',') exception(ERR_JSON_SYNTAX);
+ cmd->args.user.code_addr = (uint8_t *)json_read_alloc_binary(inp, &cmd->args.user.code_size);
break;
}
}
@@ -1120,14 +1173,14 @@ static void read_stack_trace_command(InputStream * inp, void * args) {
static void read_stack_trace_register(InputStream * inp, const char * id, void * args) {
if (trace_regs_cnt >= trace_regs_max) {
trace_regs_max += 16;
- trace_regs = (StackTracingCommandSequence **)loc_realloc(trace_regs, trace_regs_max * sizeof(StackTracingCommandSequence *));
+ trace_regs = (StackFrameRegisterLocation **)loc_realloc(trace_regs, trace_regs_max * sizeof(StackFrameRegisterLocation *));
}
trace_cmds_cnt = 0;
if (json_read_array(inp, read_stack_trace_command, NULL)) {
Context * ctx = NULL;
int frame = STACK_NO_FRAME;
- StackTracingCommandSequence * reg = (StackTracingCommandSequence *)loc_alloc(
- sizeof(StackTracingCommandSequence) + (trace_cmds_cnt - 1) * sizeof(StackTracingCommand));
+ StackFrameRegisterLocation * reg = (StackFrameRegisterLocation *)loc_alloc(
+ sizeof(StackFrameRegisterLocation) + (trace_cmds_cnt - 1) * sizeof(LocationExpressionCommand));
if (id2register(id, &ctx, &frame, &reg->reg) < 0) {
trace_error = errno;
loc_free(reg);
@@ -1135,7 +1188,7 @@ static void read_stack_trace_register(InputStream * inp, const char * id, void *
else {
reg->cmds_cnt = trace_cmds_cnt;
reg->cmds_max = trace_cmds_cnt;
- memcpy(reg->cmds, trace_cmds, trace_cmds_cnt * sizeof(StackTracingCommand));
+ memcpy(reg->cmds, trace_cmds, trace_cmds_cnt * sizeof(LocationExpressionCommand));
trace_regs[trace_regs_cnt++] = reg;
}
}
@@ -1168,18 +1221,18 @@ static void validate_frame(Channel * c, void * args, int error) {
}
trace_cmds_cnt = 0;
if (json_read_array(&c->inp, read_stack_trace_command, NULL)) {
- f->fp = (StackTracingCommandSequence *)loc_alloc(sizeof(StackTracingCommandSequence) + (trace_cmds_cnt - 1) * sizeof(StackTracingCommand));
+ f->fp = (StackFrameRegisterLocation *)loc_alloc(sizeof(StackFrameRegisterLocation) + (trace_cmds_cnt - 1) * sizeof(LocationExpressionCommand));
f->fp->reg = NULL;
f->fp->cmds_cnt = trace_cmds_cnt;
f->fp->cmds_max = trace_cmds_cnt;
- memcpy(f->fp->cmds, trace_cmds, trace_cmds_cnt * sizeof(StackTracingCommand));
+ memcpy(f->fp->cmds, trace_cmds, trace_cmds_cnt * sizeof(LocationExpressionCommand));
}
if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
trace_regs_cnt = 0;
if (json_read_struct(&c->inp, read_stack_trace_register, NULL)) {
f->regs_cnt = trace_regs_cnt;
- f->regs = (StackTracingCommandSequence **)loc_alloc(trace_regs_cnt * sizeof(StackTracingCommandSequence *));
- memcpy(f->regs, trace_regs, trace_regs_cnt * sizeof(StackTracingCommandSequence *));
+ f->regs = (StackFrameRegisterLocation **)loc_alloc(trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
+ memcpy(f->regs, trace_regs, trace_regs_cnt * sizeof(StackFrameRegisterLocation *));
}
if (read_stream(&c->inp) != 0) exception(ERR_JSON_SYNTAX);
if (read_stream(&c->inp) != MARKER_EOM) exception(ERR_JSON_SYNTAX);
@@ -1256,10 +1309,25 @@ int get_next_stack_frame(StackFrame * frame, StackFrame * down) {
Trap trap;
if (set_trap(&trap)) {
int i;
- frame->fp = (ContextAddress)evaluate_stack_trace_commands(ctx, frame, f->fp);
+ LocationExpressionState * state;
+ state = evaluate_location_expression(ctx, frame, f->fp->cmds, f->fp->cmds_cnt, NULL, 0);
+ if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid stack trace expression");
+ frame->fp = (ContextAddress)state->stk[0];
+ frame->is_walked = 1;
for (i = 0; i < f->regs_cnt; i++) {
- uint64_t v = evaluate_stack_trace_commands(ctx, frame, f->regs[i]);
- if (write_reg_value(down, f->regs[i]->reg, v) < 0) exception(errno);
+ int ok = 0;
+ uint64_t v = 0;
+ Trap trap_reg;
+ if (set_trap(&trap_reg)) {
+ /* If a saved register value cannot be evaluated - ignore it */
+ state = evaluate_location_expression(ctx, frame, f->regs[i]->cmds, f->regs[i]->cmds_cnt, NULL, 0);
+ if (state->stk_pos == 1) {
+ v = state->stk[0];
+ ok = 1;
+ }
+ clear_trap(&trap_reg);
+ }
+ if (ok && write_reg_value(down, f->regs[i]->reg, v) < 0) exception(errno);
}
clear_trap(&trap);
}
diff --git a/agent/tcf/services/symbols_win32.c b/agent/tcf/services/symbols_win32.c
index 3b2c8d7a..0e5a4791 100644
--- a/agent/tcf/services/symbols_win32.c
+++ b/agent/tcf/services/symbols_win32.c
@@ -121,6 +121,7 @@ static size_t context_extension_offset = 0;
static char * tmp_buf = NULL;
static int tmp_buf_size = 0;
+static LocationInfo * location_info = NULL;
#define SYMBOL_MAGIC 0x34875234
@@ -590,6 +591,11 @@ int get_symbol_index_type(const Symbol * sym, Symbol ** type) {
return 0;
}
+int get_symbol_containing_type(const Symbol * sym, Symbol ** containing_type) {
+ errno = ERR_UNSUPPORTED;
+ return -1;
+}
+
int get_symbol_length(const Symbol * sym, ContextAddress * length) {
DWORD res = 0;
Symbol type = *sym;
@@ -1136,6 +1142,61 @@ ContextAddress is_plt_section(Context * ctx, ContextAddress addr) {
return 0;
}
+static LocationExpressionCommand * add_location_command(int op) {
+ LocationExpressionCommand * cmd = NULL;
+ if (location_info->cmds_cnt >= location_info->cmds_max) {
+ location_info->cmds_max += 4;
+ location_info->cmds = (LocationExpressionCommand *)tmp_realloc(location_info->cmds,
+ sizeof(LocationExpressionCommand) * location_info->cmds_max);
+ }
+ cmd = location_info->cmds + location_info->cmds_cnt++;
+ memset(cmd, 0, sizeof(LocationExpressionCommand));
+ cmd->cmd = op;
+ return cmd;
+}
+
+int get_location_info(const Symbol * sym, LocationInfo ** loc) {
+ DWORD dword = 0;
+ SYMBOL_INFO * info = NULL;
+
+ assert(sym->magic == SYMBOL_MAGIC);
+ *loc = location_info = (LocationInfo *)tmp_alloc_zero(sizeof(LocationInfo));
+
+ if (sym->address != 0) {
+ add_location_command(SFT_CMD_NUMBER)->args.num = sym->address;
+ return 0;
+ }
+
+ if (sym->base || sym->info) {
+ errno = ERR_INV_CONTEXT;
+ return -1;
+ }
+
+ if (get_type_info(sym, TI_GET_OFFSET, &dword) == 0) {
+ add_location_command(SFT_CMD_ARG)->args.arg_no = 0;
+ add_location_command(SFT_CMD_NUMBER)->args.num = dword;
+ add_location_command(SFT_CMD_ADD);
+ return 0;
+ }
+
+ if (get_sym_info(sym, sym->index, &info) < 0) return -1;
+
+ if (is_register(info)) {
+ set_errno(ERR_INV_CONTEXT, "Register variable");
+ return -1;
+ }
+
+ if (is_frame_relative(info)) {
+ add_location_command(SFT_CMD_FP);
+ add_location_command(SFT_CMD_NUMBER)->args.num = info->Address - sizeof(ContextAddress) * 2;
+ add_location_command(SFT_CMD_ADD);
+ return 0;
+ }
+
+ add_location_command(SFT_CMD_NUMBER)->args.num = info->Address;
+ return 0;
+}
+
int get_stack_tracing_info(Context * ctx, ContextAddress addr, StackTracingInfo ** info) {
*info = NULL;
return 0;
diff --git a/agent/tcf/services/vm.c b/agent/tcf/services/vm.c
index 4bf94809..347cbfb6 100644
--- a/agent/tcf/services/vm.c
+++ b/agent/tcf/services/vm.c
@@ -25,9 +25,12 @@
#include <tcf/services/dwarf.h>
#include <tcf/services/vm.h>
-#define check_e_stack(n) { if (state->stk_pos < n) inv_dwarf("Invalid DWARF expression stack"); }
+#define check_e_stack(n) { if (state->stk_pos < n) inv_dwarf("Invalid location expression stack"); }
-static VMState * state = NULL;
+static LocationExpressionState * state = NULL;
+static RegisterDefinition * reg_def = NULL;
+static void * value_addr = NULL;
+static size_t value_size = 0;
static uint8_t * code = NULL;
static size_t code_pos = 0;
static size_t code_len = 0;
@@ -36,13 +39,6 @@ static void inv_dwarf(const char * msg) {
str_exception(ERR_INV_DWARF, msg);
}
-static StackFrame * get_stack_frame(void) {
- StackFrame * info = NULL;
- if (state->stack_frame == STACK_NO_FRAME) return NULL;
- if (get_frame_info(state->ctx, state->stack_frame, &info) < 0) exception(errno);
- return info;
-}
-
static uint64_t read_memory(uint64_t addr, size_t size) {
size_t i;
uint64_t n = 0;
@@ -83,7 +79,7 @@ static uint32_t read_u4leb128(void) {
int i = 0;
for (;; i += 7) {
uint8_t n = read_u1();
- res |= (n & 0x7Fu) << i;
+ res |= (uint32_t)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) break;
}
return res;
@@ -94,7 +90,7 @@ static uint64_t read_u8leb128(void) {
int i = 0;
for (;; i += 7) {
uint8_t n = read_u1();
- res |= (n & 0x7Fu) << i;
+ res |= (uint64_t)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) break;
}
return res;
@@ -105,9 +101,9 @@ static int64_t read_i8leb128(void) {
int i = 0;
for (;; i += 7) {
uint8_t n = read_u1();
- res |= (n & 0x7Fu) << i;
+ res |= (uint64_t)(n & 0x7Fu) << i;
if ((n & 0x80) == 0) {
- res |= -(n & 0x40) << i;
+ res |= -(int64_t)(n & 0x40) << i;
break;
}
}
@@ -136,19 +132,48 @@ static uint64_t read_ua(void) {
return 0;
}
-static void set_state(VMState * s) {
+static LocationPiece * add_piece(void) {
+ LocationPiece * piece = NULL;
+ if (state->pieces_cnt >= state->pieces_max) {
+ state->pieces_max += 4;
+ state->pieces = (LocationPiece *)tmp_realloc(state->pieces, state->pieces_max * sizeof(LocationPiece));
+ }
+ piece = state->pieces + state->pieces_cnt++;
+ memset(piece, 0, sizeof(LocationPiece));
+ if (reg_def != NULL) {
+ piece->reg = reg_def;
+ piece->size = reg_def->size;
+ piece->big_endian = reg_def->big_endian;
+ }
+ else if (value_addr != NULL) {
+ piece->value = value_addr;
+ piece->size = value_size;
+ piece->big_endian = state->big_endian;
+ }
+ else if (state->stk_pos == 0) {
+ /* An empty location description represents a piece or all of an object that is
+ * present in the source but not in the object code (perhaps due to optimization). */
+ }
+ else {
+ state->stk_pos--;
+ piece->addr = (ContextAddress)state->stk[state->stk_pos];
+ piece->big_endian = state->big_endian;
+ }
+ reg_def = NULL;
+ value_addr = NULL;
+ return piece;
+}
+
+static void set_state(LocationExpressionState * s) {
state = s;
code = state->code;
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;
+ reg_def = NULL;
}
-static void get_state(VMState * s) {
+static void get_state(LocationExpressionState * s) {
+ if (reg_def != NULL || value_addr != NULL) add_piece();
s->code_pos = code_pos;
state = NULL;
code = NULL;
@@ -166,9 +191,10 @@ static int is_end_of_loc_expr(void) {
static void evaluate_expression(void) {
uint64_t data = 0;
- if (code_len == 0) inv_dwarf("DWARF expression size = 0");
+ if (code_len == 0) inv_dwarf("location expression size = 0");
- while (code_pos < code_len && state->piece_bits == 0) {
+ while (code_pos < code_len) {
+ LocationPiece * piece = NULL;
uint8_t op = code[code_pos++];
if (state->stk_pos + 4 > state->stk_max) {
@@ -281,7 +307,7 @@ static void evaluate_expression(void) {
case OP_div:
check_e_stack(2);
state->stk_pos--;
- if (state->stk[state->stk_pos] == 0) inv_dwarf("Division by zero in DWARF expression");
+ if (state->stk[state->stk_pos] == 0) inv_dwarf("Division by zero in location expression");
state->stk[state->stk_pos - 1] /= state->stk[state->stk_pos];
break;
case OP_minus:
@@ -292,7 +318,7 @@ static void evaluate_expression(void) {
case OP_mod:
check_e_stack(2);
state->stk_pos--;
- if (state->stk[state->stk_pos] == 0) inv_dwarf("Division by zero in DWARF expression");
+ if (state->stk[state->stk_pos] == 0) inv_dwarf("Division by zero in location expression");
state->stk[state->stk_pos - 1] %= state->stk[state->stk_pos];
break;
case OP_mul:
@@ -472,25 +498,25 @@ static void evaluate_expression(void) {
case OP_reg31:
{
unsigned n = op - OP_reg0;
- if (!is_end_of_loc_expr()) inv_dwarf("OP_reg must be last instruction");
- state->reg = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
- if (state->reg == NULL) exception(errno);
+ if (!is_end_of_loc_expr()) inv_dwarf("OP_reg* must be last instruction");
+ reg_def = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
+ if (reg_def == NULL) exception(errno);
}
break;
case OP_regx:
{
unsigned n = (unsigned)read_u4leb128();
if (!is_end_of_loc_expr()) inv_dwarf("OP_regx must be last instruction");
- state->reg = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
- if (state->reg == NULL) exception(errno);
+ reg_def = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
+ if (reg_def == NULL) exception(errno);
}
break;
case OP_reg:
{
unsigned n = (unsigned)read_ua();
if (!is_end_of_loc_expr()) inv_dwarf("OP_reg must be last instruction");
- state->reg = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
- if (state->reg == NULL) exception(errno);
+ reg_def = get_reg_by_id(state->ctx, n, &state->reg_id_scope);
+ if (reg_def == NULL) exception(errno);
}
break;
case OP_breg0:
@@ -528,7 +554,7 @@ static void evaluate_expression(void) {
{
RegisterDefinition * def = get_reg_by_id(state->ctx, op - OP_breg0, &state->reg_id_scope);
if (def == NULL) exception(errno);
- if (read_reg_value(get_stack_frame(), def, state->stk + state->stk_pos) < 0) exception(errno);
+ if (read_reg_value(state->stack_frame, def, state->stk + state->stk_pos) < 0) exception(errno);
state->stk[state->stk_pos++] += read_i8leb128();
}
break;
@@ -536,7 +562,7 @@ static void evaluate_expression(void) {
{
RegisterDefinition * def = get_reg_by_id(state->ctx, (unsigned)read_u4leb128(), &state->reg_id_scope);
if (def == NULL) exception(errno);
- if (read_reg_value(get_stack_frame(), def, state->stk + state->stk_pos) < 0) exception(errno);
+ if (read_reg_value(state->stack_frame, def, state->stk + state->stk_pos) < 0) exception(errno);
state->stk[state->stk_pos++] += read_i8leb128();
}
break;
@@ -544,13 +570,13 @@ static void evaluate_expression(void) {
{
RegisterDefinition * def = get_reg_by_id(state->ctx, (unsigned)read_ua(), &state->reg_id_scope);
if (def == NULL) exception(errno);
- if (read_reg_value(get_stack_frame(), def, state->stk + state->stk_pos) < 0) exception(errno);
+ if (read_reg_value(state->stack_frame, def, state->stk + state->stk_pos) < 0) exception(errno);
state->stk_pos++;
}
break;
case OP_call_frame_cfa:
{
- StackFrame * frame = get_stack_frame();
+ StackFrame * frame = state->stack_frame;
if (frame == NULL) str_exception(ERR_INV_ADDRESS, "Stack frame address not available");
state->stk[state->stk_pos++] = frame->fp;
}
@@ -558,46 +584,37 @@ static void evaluate_expression(void) {
case OP_nop:
break;
case OP_push_object_address:
- state->stk[state->stk_pos++] = state->object_address;
+ if (state->args_cnt == 0) str_exception(ERR_INV_ADDRESS, "Invalid address of containing object");
+ state->stk[state->stk_pos++] = state->args[0];
break;
case OP_piece:
- state->piece_bits = read_u4leb128() * 8;
- 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--;
- }
+ piece = add_piece();
+ piece->size = read_u4leb128();
break;
case OP_bit_piece:
- state->piece_bits = read_u4leb128();
- 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;
- }
+ piece = add_piece();
+ piece->bit_size = read_u4leb128();
+ piece->bit_offs = read_u4leb128();
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;
+ value_size = read_u4leb128();
+ if (code_pos + value_size > code_len) inv_dwarf("Invalid command");
+ value_addr = tmp_alloc(value_size);
+ memcpy(value_addr, code + code_pos, value_size);
+ code_pos += value_size;
if (!is_end_of_loc_expr()) 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);
+ value_size = sizeof(uint64_t);
+ value_addr = tmp_alloc(value_size);
+ memcpy(value_addr, state->stk + state->stk_pos, value_size);
if (!is_end_of_loc_expr()) 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--) {
+ size_t i, j, n = value_size >> 1;
+ char * p = (char *)value_addr;
+ for (i = 0, j = value_size - 1; i < n; i++, j--) {
char x = p[i];
p[i] = p[j];
p[j] = x;
@@ -609,7 +626,7 @@ static void evaluate_expression(void) {
case OP_call_ref:
default:
{
- VMState * s = state;
+ LocationExpressionState * s = state;
get_state(s);
s->client_op(op);
set_state(s);
@@ -618,7 +635,7 @@ static void evaluate_expression(void) {
}
}
-int evaluate_vm_expression(VMState * vm_state) {
+int evaluate_vm_expression(LocationExpressionState * vm_state) {
int error = 0;
Trap trap;
diff --git a/agent/tcf/services/vm.h b/agent/tcf/services/vm.h
index b541c511..f174b03b 100644
--- a/agent/tcf/services/vm.h
+++ b/agent/tcf/services/vm.h
@@ -23,37 +23,7 @@
#include <tcf/framework/context.h>
-typedef struct VMState {
- /* Evaluation context */
- Context * ctx;
- int stack_frame;
- int big_endian;
- size_t addr_size;
- uint64_t object_address;
- RegisterIdScope reg_id_scope;
-
- /* Code to execute */
- uint8_t * code;
- size_t code_pos;
- size_t code_len;
-
- /* VM callback */
- void (*client_op)(uint8_t op);
-
- /* Result */
- RegisterDefinition * reg;
- void * value_addr;
- size_t value_size;
- uint32_t piece_offs;
- uint32_t piece_bits;
-
- /* Stack */
- unsigned stk_pos;
- unsigned stk_max;
- uint64_t * stk;
-} VMState;
-
-extern int evaluate_vm_expression(VMState * state);
+extern int evaluate_vm_expression(LocationExpressionState * state);
#endif /* ENABLE_DebugContext */
diff --git a/server/server.vcproj b/server/server.vcproj
index 5501097f..c3068a38 100644
--- a/server/server.vcproj
+++ b/server/server.vcproj
@@ -96,12 +96,11 @@
/>
</Configuration>
<Configuration
- Name="Release|Win32"
+ Name="Debug|x64"
OutputDirectory="$(SolutionDir)\obj\MSVC\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)\obj\MSVC\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
- WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -117,15 +116,16 @@
/>
<Tool
Name="VCMIDLTool"
+ TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="2"
- EnableIntrinsicFunctions="true"
+ Optimization="0"
AdditionalIncludeDirectories=".;../agent"
- PreprocessorDefinitions="NDEBUG;_CONSOLE"
- RuntimeLibrary="2"
- EnableFunctionLevelLinking="true"
+ PreprocessorDefinitions="_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
@@ -143,14 +143,12 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="WS2_32.lib Iphlpapi.lib"
- LinkIncremental="1"
+ LinkIncremental="2"
GenerateDebugInformation="true"
SubSystem="1"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
- TargetMachine="1"
+ TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
@@ -175,11 +173,12 @@
/>
</Configuration>
<Configuration
- Name="Debug|x64"
+ Name="Release|Win32"
OutputDirectory="$(SolutionDir)\obj\MSVC\$(PlatformName)\$(ConfigurationName)"
IntermediateDirectory="$(SolutionDir)\obj\MSVC\$(PlatformName)\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="1"
+ WholeProgramOptimization="1"
>
<Tool
Name="VCPreBuildEventTool"
@@ -195,16 +194,15 @@
/>
<Tool
Name="VCMIDLTool"
- TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
- Optimization="0"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
AdditionalIncludeDirectories=".;../agent"
- PreprocessorDefinitions="_DEBUG;_CONSOLE"
- MinimalRebuild="true"
- BasicRuntimeChecks="3"
- RuntimeLibrary="3"
+ PreprocessorDefinitions="NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="3"
@@ -222,12 +220,14 @@
<Tool
Name="VCLinkerTool"
AdditionalDependencies="WS2_32.lib Iphlpapi.lib"
- LinkIncremental="2"
+ LinkIncremental="1"
GenerateDebugInformation="true"
SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
RandomizedBaseAddress="1"
DataExecutionPrevention="2"
- TargetMachine="17"
+ TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
@@ -383,6 +383,14 @@
>
</File>
<File
+ RelativePath="..\agent\tcf\services\dwarfecomp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\agent\tcf\services\dwarfecomp.h"
+ >
+ </File>
+ <File
RelativePath="..\agent\tcf\services\dwarfexpr.c"
>
</File>
diff --git a/tests/test-dwarf/dwarf-test.vcproj b/tests/test-dwarf/dwarf-test.vcproj
index aaddecaa..bcabaf02 100644
--- a/tests/test-dwarf/dwarf-test.vcproj
+++ b/tests/test-dwarf/dwarf-test.vcproj
@@ -462,6 +462,14 @@
>
</File>
<File
+ RelativePath="..\..\agent\tcf\services\dwarfecomp.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\agent\tcf\services\dwarfecomp.h"
+ >
+ </File>
+ <File
RelativePath="..\..\agent\tcf\services\dwarfexpr.c"
>
</File>
diff --git a/tests/test-dwarf/tcf/backend/backend.c b/tests/test-dwarf/tcf/backend/backend.c
index ce30e0b5..6d98d28d 100644
--- a/tests/test-dwarf/tcf/backend/backend.c
+++ b/tests/test-dwarf/tcf/backend/backend.c
@@ -35,6 +35,9 @@
#include <tcf/services/linenumbers.h>
#include <tcf/services/memorymap.h>
#include <tcf/services/dwarfframe.h>
+#include <tcf/services/dwarfcache.h>
+#include <tcf/services/stacktrace.h>
+#include <tcf/services/dwarf.h>
#include <tcf/backend/backend.h>
@@ -70,6 +73,8 @@ static char ** files = NULL;
static unsigned files_max = 0;
static unsigned files_cnt = 0;
+extern ObjectInfo * get_symbol_object(Symbol * sym);
+
static RegisterDefinition * get_reg_by_dwarf_id(unsigned id) {
static RegisterDefinition ** map = NULL;
static unsigned map_length = 0;
@@ -266,6 +271,7 @@ static void error(const char * func) {
static void line_numbers_callback(CodeArea * area, void * args) {
CodeArea * dst = (CodeArea *)args;
+ if (area->start_address > pc || area->end_address <= pc) return;
*dst = *area;
}
@@ -309,6 +315,8 @@ static void loc_var_func(void * args, Symbol * sym) {
size_t value_size = 0;
int value_big_endian = 0;
char * name = NULL;
+ StackFrame * frame_info = NULL;
+ LocationInfo * loc_info = NULL;
if (get_symbol_flags(sym, &flags) < 0) {
error("get_symbol_flags");
@@ -323,10 +331,32 @@ static void loc_var_func(void * args, Symbol * sym) {
if (strncmp(errno_to_str(err), "Object location or value info not available", 43) == 0) return;
if (strncmp(errno_to_str(err), "No object location info found", 29) == 0) return;
if (strncmp(errno_to_str(err), "Object is not available", 23) == 0) return;
- if (strncmp(errno_to_str(err), "Division by zero in DWARF", 25) == 0) return;
+ if (strncmp(errno_to_str(err), "Division by zero in location", 28) == 0) return;
if (strncmp(errno_to_str(err), "Cannot find loader debug", 24) == 0) return;
errno = err;
- error("get_symbol_address");
+ error("get_symbol_value");
+ }
+ }
+ else if (get_location_info(sym, &loc_info) < 0) {
+ error("get_location_info");
+ }
+ else if (get_frame_info(elf_ctx, STACK_TOP_FRAME, &frame_info) < 0) {
+ error("get_frame_info");
+ }
+ else {
+ Trap trap;
+ assert(loc_info->cmds_cnt > 0);
+ assert(loc_info->size == 0 || (loc_info->addr <= pc && loc_info->addr + loc_info->size > pc));
+ if (set_trap(&trap)) {
+ LocationExpressionState * state = evaluate_location_expression(elf_ctx, frame_info, loc_info->cmds, loc_info->cmds_cnt, NULL, 0);
+ if (state->stk_pos != 1) str_exception(ERR_OTHER, "invalid location expression stack");
+ if (state->stk[0] != addr) str_fmt_exception(ERR_OTHER,
+ "ID 0x%" PRIX64 ": invalid location expression result 0x%" PRIX64 " != 0x%" PRIX64,
+ get_symbol_object(sym)->mID, state->stk[0], addr);
+ clear_trap(&trap);
+ }
+ else {
+ error("evaluate_location_expression");
}
}
if (get_symbol_class(sym, &symbol_class) < 0) {
@@ -358,31 +388,39 @@ static void loc_var_func(void * args, Symbol * sym) {
}
}
if (type != NULL) {
+ Symbol * container = NULL;
if (get_symbol_type_class(sym, &type_class) < 0) {
error("get_symbol_type_class");
}
if (get_symbol_flags(type, &flags) < 0) {
error("get_symbol_flags");
}
- if (type_class == TYPE_CLASS_ARRAY) {
- if (get_symbol_index_type(type, &index_type) < 0) {
+ if (get_symbol_index_type(type, &index_type) < 0) {
+ if (type_class == TYPE_CLASS_ARRAY) {
error("get_symbol_index_type");
}
- if (get_symbol_base_type(type, &base_type) < 0) {
+ }
+ if (get_symbol_base_type(type, &base_type) < 0) {
+ if (type_class == TYPE_CLASS_ARRAY || type_class == TYPE_CLASS_FUNCTION ||
+ type_class == TYPE_CLASS_POINTER || type_class == TYPE_CLASS_MEMBER_PTR) {
error("get_symbol_base_type");
}
- if (get_symbol_length(type, &length) < 0) {
+ }
+ if (get_symbol_containing_type(type, &container) < 0) {
+ if (type_class == TYPE_CLASS_MEMBER_PTR) {
+ error("get_symbol_containing_type");
+ }
+ }
+ if (get_symbol_length(type, &length) < 0) {
+ if (type_class == TYPE_CLASS_ARRAY) {
error("get_symbol_length");
}
+ }
+ if (type_class == TYPE_CLASS_ARRAY) {
if (get_symbol_lower_bound(type, &lower_bound) < 0) {
error("get_symbol_lower_bound");
}
}
- else if (type_class == TYPE_CLASS_POINTER) {
- if (get_symbol_base_type(type, &base_type) < 0) {
- error("get_symbol_base_type");
- }
- }
else if (type_class == TYPE_CLASS_ENUMERATION) {
int i;
int count = 0;
@@ -450,6 +488,7 @@ static void next_pc(void) {
ContextAddress lt_addr;
ELF_File * lt_file;
ELF_Section * lt_sec;
+ ObjectInfo * func_object = NULL;
struct timespec time_now;
Trap trap;
int test_cnt = 0;
@@ -494,6 +533,7 @@ static void next_pc(void) {
set_regs_PC(elf_ctx, pc);
send_context_changed_event(elf_ctx);
+ func_object = NULL;
if (find_symbol_by_addr(elf_ctx, STACK_NO_FRAME, pc, &sym) < 0) {
if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
error("find_symbol_by_addr");
@@ -504,6 +544,7 @@ static void next_pc(void) {
char name_buf[0x1000];
ContextAddress addr = 0;
ContextAddress size = 0;
+ func_object = get_symbol_object(sym);
if (get_symbol_name(sym, &name) < 0) {
error("get_symbol_name");
}
@@ -547,15 +588,34 @@ static void next_pc(void) {
error("address_to_line");
}
else if (area.start_line > 0) {
+ CodeArea a;
char elf_file_name[0x1000];
+ if (area.start_address > pc || area.end_address <= pc) {
+ errno = set_errno(ERR_OTHER, "Invalid line area address");
+ error("address_to_line");
+ }
+ memset(&a, 0, sizeof(a));
strlcpy(elf_file_name, area.file, sizeof(elf_file_name));
- if (line_to_address(elf_ctx, elf_file_name, area.start_line, area.start_column, line_numbers_callback, &area) < 0) {
+ if (line_to_address(elf_ctx, elf_file_name, area.start_line, area.start_column, line_numbers_callback, &a) < 0) {
error("line_to_address");
}
- }
-
- if (enumerate_symbols(elf_ctx, STACK_TOP_FRAME, loc_var_func, NULL) < 0) {
- error("enumerate_symbols");
+ if (a.start_line > area.start_line || a.end_line <= area.start_line) {
+ errno = set_errno(ERR_OTHER, "Invalid line area line numbers");
+ error("line_to_address");
+ }
+ if (a.start_address > pc || a.end_address <= pc) {
+ errno = set_errno(ERR_OTHER, "Invalid line area address");
+ error("line_to_address");
+ }
+ if (a.start_address != area.start_address || a.end_address != area.end_address) {
+ if (pc < 0x1000) {
+ /* Bug in GCC: lines in multiple units are mapped to same (invalid) addresses near address zero */
+ }
+ else {
+ errno = set_errno(ERR_OTHER, "Invalid line area address");
+ error("line_to_address");
+ }
+ }
}
lt_file = NULL;
@@ -571,6 +631,38 @@ static void next_pc(void) {
error("get_dwarf_stack_frame_info");
}
+ if (enumerate_symbols(elf_ctx, STACK_TOP_FRAME, loc_var_func, NULL) < 0) {
+ error("enumerate_symbols");
+ }
+
+ if (func_object != NULL) {
+ if (set_trap(&trap)) {
+ StackFrame * frame = NULL;
+ if (get_frame_info(elf_ctx, STACK_TOP_FRAME, &frame) < 0) exception(errno);
+ if (frame->fp != frame_addr) {
+ PropertyValue v;
+ uint64_t addr = 0;
+ memset(&v, 0, sizeof(v));
+ read_and_evaluate_dwarf_object_property(elf_ctx, STACK_TOP_FRAME, func_object, AT_frame_base, &v);
+ if (v.mPieceCnt == 1 && v.mPieces[0].reg != NULL && v.mPieces[0].bit_size == 0) {
+ if (read_reg_value(frame, v.mPieces[0].reg, &addr) < 0) exception(errno);
+ }
+ else {
+ addr = get_numeric_property_value(&v);
+ }
+ if (addr != frame->fp) {
+ /* AT_frame_base is not valid in prologue and epilogue.
+ str_exception(ERR_OTHER, "Invalid FP");
+ */
+ }
+ }
+ clear_trap(&trap);
+ }
+ else if (trap.error != ERR_SYM_NOT_FOUND) {
+ error("AT_frame_base");
+ }
+ }
+
test_cnt++;
if (test_cnt % 10 == 0) tmp_gc();
@@ -697,7 +789,12 @@ static void next_file(void) {
r->dwarf_id = (int16_t)(j == 0 ? -1 : j - 1);
r->eh_frame_id = r->dwarf_id;
r->name = reg_names[j];
- snprintf(reg_names[j], sizeof(reg_names[j]), "R%d", j);
+ if (j == 0) {
+ snprintf(reg_names[j], sizeof(reg_names[j]), "PC");
+ }
+ else {
+ snprintf(reg_names[j], sizeof(reg_names[j]), "R%d", j - 1);
+ }
r->offset = reg_size;
r->size = f->elf64 ? 8 : 4;
if (j == 0) r->role = "PC";
@@ -737,6 +834,7 @@ static void add_dir(const char * dir_name) {
if (strcmp(e->d_name, ".") == 0) continue;
if (strcmp(e->d_name, "..") == 0) continue;
if (strcmp(e->d_name + strlen(e->d_name) - 6, ".debug") == 0) continue;
+ if (strcmp(e->d_name + strlen(e->d_name) - 4, ".txt") == 0) continue;
snprintf(path, sizeof(path), "%s/%s", dir_name, e->d_name);
if (stat(path, &st) == 0) {
if (S_ISDIR(st.st_mode)) {

Back to the top