Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2012-04-25 15:01:05 +0000
committerEugene Tarassov2012-04-25 15:01:05 +0000
commit16a9c044ef5f3ff650dc8b29e4c63a3d7cbb96ee (patch)
treed1b4647d1c90321204934093b6923e8380cfc7ab
parent69dc4424c5bad8cd4b521e43b5b377aaf9283e43 (diff)
downloadorg.eclipse.tcf.agent-16a9c044ef5f3ff650dc8b29e4c63a3d7cbb96ee.tar.gz
org.eclipse.tcf.agent-16a9c044ef5f3ff650dc8b29e4c63a3d7cbb96ee.tar.xz
org.eclipse.tcf.agent-16a9c044ef5f3ff650dc8b29e4c63a3d7cbb96ee.zip
TCF Agent: wider usage of location expressions instead of get_symbol_address, get_symbol_offset
-rw-r--r--agent/agent.vcproj4
-rw-r--r--agent/tcf/services/dwarfcache.c1
-rw-r--r--agent/tcf/services/dwarfecomp.c47
-rw-r--r--agent/tcf/services/dwarfexpr.c354
-rw-r--r--agent/tcf/services/dwarfexpr.h3
-rw-r--r--agent/tcf/services/expressions.c26
-rw-r--r--agent/tcf/services/symbols.c137
-rw-r--r--agent/tcf/services/symbols.h4
-rw-r--r--agent/tcf/services/symbols_common.c118
-rw-r--r--agent/tcf/services/symbols_elf.c394
-rw-r--r--agent/tcf/services/symbols_proxy.c208
-rw-r--r--agent/tcf/services/symbols_win32.c101
-rw-r--r--server/server.vcproj4
-rw-r--r--tests/test-dwarf/dwarf-test.vcproj4
-rw-r--r--tests/test-dwarf/tcf/backend/backend.c378
15 files changed, 837 insertions, 946 deletions
diff --git a/agent/agent.vcproj b/agent/agent.vcproj
index 93e6f1c9..4326d117 100644
--- a/agent/agent.vcproj
+++ b/agent/agent.vcproj
@@ -836,6 +836,10 @@
>
</File>
<File
+ RelativePath=".\tcf\services\symbols_common.c"
+ >
+ </File>
+ <File
RelativePath=".\tcf\services\symbols_elf.c"
>
</File>
diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c
index d84f6558..397456f3 100644
--- a/agent/tcf/services/dwarfcache.c
+++ b/agent/tcf/services/dwarfcache.c
@@ -1399,6 +1399,7 @@ void read_and_evaluate_dwarf_object_property(Context * Ctx, int Frame, ObjectInf
else if (Attr == AT_data_member_location) {
switch (Value->mForm) {
case FORM_DATA1 :
+ case FORM_DATA2 :
case FORM_DATA4 :
case FORM_DATA8 :
case FORM_SDATA :
diff --git a/agent/tcf/services/dwarfecomp.c b/agent/tcf/services/dwarfecomp.c
index 43506ed0..88c89061 100644
--- a/agent/tcf/services/dwarfecomp.c
+++ b/agent/tcf/services/dwarfecomp.c
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2011 Wind River Systems, Inc. and others.
+ * Copyright (c) 2011, 2012 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.
@@ -124,6 +124,21 @@ static void op_addr(void) {
add_uleb128(addr);
}
+static ObjectInfo * get_parent_function(ObjectInfo * info) {
+ while (info != NULL) {
+ switch (info->mTag) {
+ case TAG_global_subroutine:
+ case TAG_inlined_subroutine:
+ case TAG_subroutine:
+ case TAG_subprogram:
+ case TAG_entry_point:
+ return info;
+ }
+ info = get_dwarf_parent(info);
+ }
+ return NULL;
+}
+
static void op_fbreg(void) {
PropertyValue fp;
DWARFExpressionInfo info;
@@ -202,13 +217,12 @@ static void op_fbreg(void) {
static void op_implicit_pointer(void) {
Trap trap;
PropertyValue pv;
- DWARFExpressionInfo info;
U1_T op = expr->expr_addr[expr_pos];
CompUnit * unit = expr->object->mCompUnit;
int arg_size = unit->mDesc.m64bit ? 8 : 4;
ObjectInfo * ref_obj = NULL;
ContextAddress ref_id = 0;
- U4_T offset = 0;
+ U8_T offset = 0;
U8_T dio_pos = 0;
expr_pos++;
@@ -216,7 +230,7 @@ static void op_implicit_pointer(void) {
dio_pos = expr->expr_addr + expr_pos - (U1_T *)expr->section->data;
dio_EnterSection(&expr->unit->mDesc, expr->section, dio_pos);
ref_id = dio_ReadUX(arg_size);
- offset = dio_ReadULEB128();
+ offset = dio_ReadU8LEB128();
expr_pos += (size_t)(dio_GetPos() - dio_pos);
dio_ExitSection();
@@ -225,21 +239,34 @@ static void op_implicit_pointer(void) {
memset(&pv, 0, sizeof(pv));
if (set_trap(&trap)) {
+ DWARFExpressionInfo info;
read_dwarf_object_property(expr_ctx, STACK_NO_FRAME, ref_obj, AT_location, &pv);
+ dwarf_find_expression(&pv, expr_ip, &info);
+ add_expression(&info);
+ if (offset != 0) {
+ add(OP_TCF_offset);
+ add_uleb128(offset);
+ }
clear_trap(&trap);
}
else if (trap.error == ERR_SYM_NOT_FOUND) {
+ size_t i;
read_dwarf_object_property(expr_ctx, STACK_NO_FRAME, ref_obj, AT_const_value, &pv);
+ if (pv.mAddr == NULL) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
+ if (offset != 0) {
+ if (offset > pv.mSize) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
+ pv.mSize -= (size_t)offset;
+ pv.mAddr = (U1_T *)pv.mAddr + offset;
+ }
+ add(OP_implicit_value);
+ add_uleb128(pv.mSize);
+ for (i = 0; i < pv.mSize; i++) {
+ add(*((U1_T *)pv.mAddr + i));
+ }
}
else {
exception(trap.error);
}
- dwarf_find_expression(&pv, expr_ip, &info);
- add_expression(&info);
- if (offset != 0) {
- add(OP_TCF_offset);
- add_uleb128(offset);
- }
}
static void op_push_tls_address(void) {
diff --git a/agent/tcf/services/dwarfexpr.c b/agent/tcf/services/dwarfexpr.c
index c084a5c5..c86246bd 100644
--- a/agent/tcf/services/dwarfexpr.c
+++ b/agent/tcf/services/dwarfexpr.c
@@ -22,268 +22,18 @@
#if ENABLE_ELF && ENABLE_DebugContext
#include <assert.h>
-#include <stdio.h>
-#include <tcf/framework/events.h>
#include <tcf/framework/myalloc.h>
#include <tcf/framework/exceptions.h>
#include <tcf/framework/errors.h>
-#include <tcf/framework/trace.h>
#include <tcf/services/dwarf.h>
-#include <tcf/services/dwarfio.h>
#include <tcf/services/dwarfexpr.h>
+#include <tcf/services/dwarfecomp.h>
#include <tcf/services/stacktrace.h>
-#include <tcf/services/elf-loader.h>
#include <tcf/services/vm.h>
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 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 = sState->pieces + sState->pieces_cnt++;
- memset(Piece, 0, sizeof(LocationPiece));
- return Piece;
-}
-
-static StackFrame * get_stack_frame(PropertyValue * sValue) {
- StackFrame * Info = NULL;
- if (sValue->mFrame == STACK_NO_FRAME) return NULL;
- if (get_frame_info(sValue->mContext, sValue->mFrame, &Info) < 0) exception(errno);
- return Info;
-}
-
-ObjectInfo * get_parent_function(ObjectInfo * Info) {
- while (Info != NULL) {
- switch (Info->mTag) {
- case TAG_global_subroutine:
- case TAG_inlined_subroutine:
- case TAG_subroutine:
- case TAG_subprogram:
- case TAG_entry_point:
- return Info;
- }
- Info = get_dwarf_parent(Info);
- }
- return NULL;
-}
-
-static U8_T read_address(void) {
- U8_T addr = 0;
- ELF_Section * section = NULL;
- CompUnit * Unit = sValue->mObject->mCompUnit;
-
- addr = dio_ReadAddress(&section);
- addr = elf_map_to_run_time_address(sState->ctx, Unit->mFile, section, (ContextAddress)addr);
- if (errno) str_exception(errno, "Cannot get object run-time address");
- return addr;
-}
-
-static U8_T get_fbreg(void) {
- PropertyValue FP;
- CompUnit * Unit = sValue->mObject->mCompUnit;
- ObjectInfo * Parent = get_parent_function(sValue->mObject);
- U8_T addr = 0;
-
- if (Parent == NULL) str_exception(ERR_INV_DWARF, "OP_fbreg: no parent function");
- memset(&FP, 0, sizeof(FP));
- read_and_evaluate_dwarf_object_property(sState->ctx, sStackFrame, Parent, AT_frame_base, &FP);
- assert(get_stack_frame(&FP) == sState->stack_frame);
-
- 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);
- }
- dio_EnterSection(&Unit->mDesc, sSection, sSectionOffs + sState->code_pos);
- return addr + dio_ReadS8LEB128();
-}
-
-static U8_T evaluate_tls_address(U8_T Offset) {
- U8_T addr = 0;
- CompUnit * Unit = sValue->mObject->mCompUnit;
- U8_T DioPos = dio_GetPos();
-
- if (!context_has_state(sState->ctx)) str_exception(ERR_INV_CONTEXT,
- "Thread local variable, but context is not a thread");
-
- addr = get_tls_address(sState->ctx, Unit->mFile) + Offset;
-
- dio_EnterSection(&Unit->mDesc, sSection, DioPos);
- return addr;
-}
-
-static void evaluate_implicit_pointer(uint8_t op) {
- Trap trap;
- PropertyValue PV;
- CompUnit * Unit = sValue->mObject->mCompUnit;
- int ArgSize = op == OP_GNU_implicit_pointer && Unit->mDesc.mVersion < 3 ? Unit->mDesc.mAddressSize : (Unit->mDesc.m64bit ? 8 : 4);
- ContextAddress id = dio_ReadUX(ArgSize);
- U4_T Offset = dio_ReadULEB128();
- U8_T DioPos = dio_GetPos();
- ObjectInfo * Info = find_object(get_dwarf_cache(Unit->mFile), id);
- if (Info == NULL) str_exception(ERR_INV_DWARF, "OP_implicit_pointer: invalid object reference");
- memset(&PV, 0, sizeof(PV));
- if (set_trap(&trap)) {
- read_and_evaluate_dwarf_object_property(sState->ctx, sStackFrame, Info, AT_location, &PV);
- clear_trap(&trap);
- }
- else if (trap.error == ERR_SYM_NOT_FOUND) {
- read_and_evaluate_dwarf_object_property(sState->ctx, sStackFrame, Info, AT_const_value, &PV);
- }
- else {
- exception(trap.error);
- }
- assert(sValue->mBigEndian == PV.mBigEndian);
- if (PV.mPieces != NULL) {
- U4_T Cnt = 0;
- U4_T BitOffset = 0;
- while (Cnt < PV.mPieceCnt) {
- LocationPiece * OrgPiece = PV.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->bit_offs += Offset * 8 - BitOffset;
- Piece->bit_size -= Offset * 8 - BitOffset;
- }
- if (Piece->bit_offs == 0 && Piece->bit_size % 8 == 0) {
- Piece->size = Piece->bit_size / 8;
- Piece->bit_size = 0;
- }
- }
- BitOffset += OrgPiece->bit_size;
- }
- }
- else if (PV.mAddr != NULL) {
- LocationPiece * Piece = add_piece();
- if (Offset > PV.mSize) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- Piece->size = PV.mSize - Offset;
- Piece->value = PV.mAddr + Offset;
- }
- else if (PV.mForm == FORM_EXPR_VALUE) {
- sState->stk[sState->stk_pos++] = PV.mValue + Offset;
- }
- else {
- LocationPiece * Piece = add_piece();
- U1_T * Buf = (U1_T *)tmp_alloc(sizeof(PV.mValue));
- if (Offset > sizeof(PV.mValue)) str_exception(ERR_INV_DWARF, "Invalid OP_GNU_implicit_pointer");
- memcpy(Buf, &PV.mValue, sizeof(PV.mValue));
- if (big_endian_host() != PV.mBigEndian) swap_bytes(Buf, Piece->size);
- Piece->size = sizeof(PV.mValue) - Offset;
- Piece->value = Buf + Offset;
- }
- dio_EnterSection(&Unit->mDesc, sSection, DioPos);
-}
-
-static void evaluate_call(U8_T ID) {
- PropertyValue PV;
- U8_T DioPos = dio_GetPos();
- uint8_t * OrgCode = sState->code;
- size_t OrgCodePos = sState->code_pos;
- size_t OrgCodeLen = sState->code_len;
- ELF_Section * OrgSection = sSection;
- U8_T OrgSectionOffs = sSectionOffs;
- PropertyValue * OrgValue = sValue;
- CompUnit * Unit = sValue->mObject->mCompUnit;
- ObjectInfo * Obj = find_object(get_dwarf_cache(Unit->mFile), ID);
- DWARFExpressionInfo Info;
- U8_T IP = 0;
-
- if (Obj == NULL) str_exception(ERR_INV_DWARF, "Invalid reference in OP_call");
- read_dwarf_object_property(sValue->mContext, sValue->mFrame, Obj, AT_location, &PV);
-
- sValue = &PV;
-
- 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");
- 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);
-
- sState->code = OrgCode;
- sState->code_pos = OrgCodePos;
- sState->code_len = OrgCodeLen;
- sSection = OrgSection;
- sSectionOffs = OrgSectionOffs;
- sValue = OrgValue;
- dio_EnterSection(&Unit->mDesc, sSection, DioPos);
-}
-
-static void client_op(uint8_t op) {
- CompUnit * Unit = sValue->mObject->mCompUnit;
- dio_EnterSection(&Unit->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 == NULL) str_exception(ERR_INV_CONTEXT, "Invalid stack frame");
- sState->stk[sState->stk_pos++] = get_fbreg();
- break;
- case OP_form_tls_address:
- if (sState->stk_pos == 0) str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
- sState->stk[sState->stk_pos - 1] = evaluate_tls_address(sState->stk[sState->stk_pos - 1]);
- break;
- case OP_GNU_push_tls_address:
- if (sState->stk_pos == 0 && sState->code_pos < sState->code_len) {
- /* This looks like a bug in GCC: offset sometimes is emitted after OP_GNU_push_tls_address */
- switch (dio_ReadU1()) {
- case OP_const4u: sState->stk[sState->stk_pos++] = dio_ReadU4(); break;
- case OP_const8u: sState->stk[sState->stk_pos++] = dio_ReadU8(); break;
- case OP_constu: sState->stk[sState->stk_pos++] = dio_ReadU8LEB128(); break;
- }
- }
- if (sState->stk_pos == 0) str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
- sState->stk[sState->stk_pos - 1] = evaluate_tls_address(sState->stk[sState->stk_pos - 1]);
- break;
- case OP_implicit_pointer:
- case OP_GNU_implicit_pointer:
- evaluate_implicit_pointer(op);
- break;
- case OP_call2:
- evaluate_call(Unit->mDesc.mSection->addr + Unit->mDesc.mUnitOffs + dio_ReadU2());
- break;
- case OP_call4:
- evaluate_call(Unit->mDesc.mSection->addr + Unit->mDesc.mUnitOffs + dio_ReadU4());
- break;
- case OP_call_ref:
- {
- ELF_Section * Section = NULL;
- int Size = Unit->mDesc.m64bit ? 8 : 4;
- if (Unit->mDesc.mVersion < 3) Size = Unit->mDesc.mAddressSize;
- evaluate_call(dio_ReadAddressX(&Section, Size));
- }
- break;
- default:
- str_fmt_exception(ERR_UNSUPPORTED, "Unsupported DWARF expression op 0x%02x", op);
- }
- sState->code_pos = (size_t)(dio_GetPos() - sSectionOffs);
- dio_ExitSection();
-}
-
void dwarf_find_expression(PropertyValue * Value, U8_T IP, DWARFExpressionInfo * Info) {
CompUnit * Unit = Value->mObject->mCompUnit;
@@ -349,79 +99,69 @@ void dwarf_find_expression(PropertyValue * Value, U8_T IP, DWARFExpressionInfo *
}
}
-void dwarf_evaluate_expression(PropertyValue * PV) {
- CompUnit * Unit = PV->mObject->mCompUnit;
- LocationExpressionState * OrgState = sState;
- ELF_Section * OrgSection = sSection;
- U8_T OrgSectionOffs = sSectionOffs;
- PropertyValue * OrgValue = sValue;
+void dwarf_evaluate_expression(PropertyValue * Value) {
+ CompUnit * Unit = Value->mObject->mCompUnit;
+ LocationExpressionState * State = NULL;
DWARFExpressionInfo Info;
U8_T IP = 0;
U8_T args[2];
- sValue = PV;
- 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(PV);
- sState->addr_size = Unit->mDesc.mAddressSize;
- sState->reg_id_scope = Unit->mRegIdScope;
- sState->args = args;
- sState->client_op = client_op;
+ State = (LocationExpressionState *)tmp_alloc_zero(sizeof(LocationExpressionState));
+ State->stk = (U8_T *)tmp_alloc(sizeof(U8_T) * (State->stk_max = 8));
+ State->ctx = Value->mContext;
+ if (Value->mFrame != STACK_NO_FRAME &&
+ get_frame_info(Value->mContext, Value->mFrame, &State->stack_frame) < 0)
+ exception(errno);
+ State->addr_size = Unit->mDesc.mAddressSize;
+ State->reg_id_scope = Unit->mRegIdScope;
+ State->args = args;
args[0] = dwarf_expression_obj_addr;
args[1] = dwarf_expression_pm_value;
- if (sValue->mAttr == AT_data_member_location) {
- sState->stk[sState->stk_pos++] = dwarf_expression_obj_addr;
- sState->args_cnt = 1;
+ if (Value->mAttr == AT_data_member_location) {
+ State->stk[State->stk_pos++] = dwarf_expression_obj_addr;
+ State->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 (Value->mAttr == AT_use_location) {
+ State->stk[State->stk_pos++] = dwarf_expression_pm_value;
+ State->stk[State->stk_pos++] = dwarf_expression_obj_addr;
+ State->args_cnt = 2;
}
- if (sValue->mPieces != NULL || sValue->mAddr == NULL || sValue->mSize == 0) {
+ if (Value->mPieces != NULL || Value->mAddr == NULL || Value->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");
- 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->reg_id_scope.big_endian;
- sValue->mPieces = NULL;
- sValue->mPieceCnt = 0;
-
- if (sState->pieces_cnt) {
- sValue->mPieces = sState->pieces;
- sValue->mPieceCnt = sState->pieces_cnt;
+ if (Value->mForm == FORM_DATA4 || Value->mForm == FORM_DATA8) {
+ if (Value->mFrame == STACK_NO_FRAME) str_exception(ERR_INV_CONTEXT, "Need stack frame");
+ if (read_reg_value(State->stack_frame, get_PC_definition(Value->mContext), &IP) < 0) exception(errno);
+ }
+
+ dwarf_find_expression(Value, IP, &Info);
+ dwarf_transform_expression(Value->mContext, IP, &Info);
+ State->code = Info.expr_addr;
+ State->code_len = Info.expr_size;
+ State->code_pos = 0;
+ if (evaluate_vm_expression(State) < 0) exception(errno);
+ assert(State->code_pos == State->code_len);
+
+ Value->mForm = FORM_EXPR_VALUE;
+ Value->mAddr = NULL;
+ Value->mValue = 0;
+ Value->mSize = 0;
+ Value->mBigEndian = State->reg_id_scope.big_endian;
+ Value->mPieces = NULL;
+ Value->mPieceCnt = 0;
+
+ if (State->pieces_cnt) {
+ Value->mPieces = State->pieces;
+ Value->mPieceCnt = State->pieces_cnt;
}
else {
- sValue->mValue = sState->stk[--sState->stk_pos];
+ Value->mValue = State->stk[--State->stk_pos];
}
- if (sState->stk_pos != 0) {
+ if (State->stk_pos != 0) {
str_exception(ERR_INV_DWARF, "Invalid DWARF expression stack");
}
-
- sState = OrgState;
- sSection = OrgSection;
- sSectionOffs = OrgSectionOffs;
- sValue = OrgValue;
}
#endif /* ENABLE_ELF && ENABLE_DebugContext */
diff --git a/agent/tcf/services/dwarfexpr.h b/agent/tcf/services/dwarfexpr.h
index c40a8ce5..79d0ed32 100644
--- a/agent/tcf/services/dwarfexpr.h
+++ b/agent/tcf/services/dwarfexpr.h
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2010 Wind River Systems, Inc. and others.
+ * Copyright (c) 2008, 2012 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.
@@ -43,7 +43,6 @@ typedef struct DWARFExpressionInfo {
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);
diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c
index e3ca94aa..0c386214 100644
--- a/agent/tcf/services/expressions.c
+++ b/agent/tcf/services/expressions.c
@@ -694,24 +694,7 @@ static int sym2value(int mode, Symbol * sym, Value * v) {
}
switch (sym_class) {
case SYM_CLASS_VALUE:
- {
- int endianness = 0;
- size_t size = 0;
- void * value = NULL;
- if (get_symbol_value(sym, &value, &size, &endianness) < 0) {
- error(errno, "Cannot retrieve symbol value");
- }
- v->big_endian = endianness;
- v->constant = 1;
- v->size = size;
- if (value != NULL) {
- v->value = tmp_alloc(size);
- memcpy(v->value, value, size);
- }
- }
- break;
case SYM_CLASS_REFERENCE:
- set_value_endianness(v, sym, v->type);
if (mode == MODE_NORMAL) {
LocationExpressionState * state = NULL;
LocationInfo * loc_info = NULL;
@@ -732,20 +715,19 @@ static int sym2value(int mode, Symbol * sym, Value * v) {
size_t size = 0;
void * value = NULL;
read_location_peices(expression_context, frame_info,
- state->pieces, state->pieces_cnt, v->big_endian, &value, &size);
+ state->pieces, state->pieces_cnt, loc_info->big_endian, &value, &size);
if (state->pieces_cnt == 1 && state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
v->reg = state->pieces->reg;
}
v->size = size;
- if (value != NULL) {
- v->value = tmp_alloc(size);
- memcpy(v->value, value, size);
- }
+ v->value = value;
}
+ v->big_endian = loc_info->big_endian;
}
else {
v->remote = 1;
}
+ v->constant = sym_class == SYM_CLASS_VALUE;
v->sym = sym;
break;
case SYM_CLASS_FUNCTION:
diff --git a/agent/tcf/services/symbols.c b/agent/tcf/services/symbols.c
index 4e0e0336..62b3aec9 100644
--- a/agent/tcf/services/symbols.c
+++ b/agent/tcf/services/symbols.c
@@ -43,67 +43,20 @@ static void list_add(Symbol * sym) {
list_buf[list_cnt++] = sym;
}
-static LocationExpressionState * evaluate_symbol_location(const Symbol * sym, unsigned args_cnt) {
+static LocationExpressionState * evaluate_location(Context * ctx, int frame, LocationInfo * loc_info) {
Trap trap;
- Context * ctx = NULL;
- int frame = STACK_NO_FRAME;
- LocationInfo * loc_info = NULL;
StackFrame * frame_info = NULL;
LocationExpressionState * state = NULL;
static uint64_t args[] = { 0, 0 };
- if (get_symbol_frame(sym, &ctx, &frame) < 0) return NULL;
- if (get_location_info(sym, &loc_info) < 0) return NULL;
- if (loc_info->args_cnt != args_cnt) {
- set_errno(ERR_OTHER, "Wrong object kind");
- return NULL;
- }
if (frame != STACK_NO_FRAME && get_frame_info(ctx, frame, &frame_info) < 0) return NULL;
if (!set_trap(&trap)) return NULL;
state = evaluate_location_expression(ctx, frame_info,
- loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, args, args_cnt);
+ loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, args, loc_info->args_cnt);
clear_trap(&trap);
return state;
}
-int get_symbol_address(const Symbol * sym, ContextAddress * address) {
- LocationExpressionState * state = evaluate_symbol_location(sym, 0);
- if (state == NULL) return -1;
- if (state->stk_pos == 1) {
- *address = (ContextAddress)state->stk[0];
- return 0;
- }
- set_errno(ERR_OTHER, "Symbol does not have a memory address");
- return -1;
-}
-
-int get_symbol_register(const Symbol * sym, Context ** ctx, int * frame, RegisterDefinition ** reg) {
- LocationExpressionState * state = evaluate_symbol_location(sym, 0);
- if (state == NULL) return -1;
- if (state->pieces_cnt == 1 && state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
- if (get_symbol_frame(sym, ctx, frame) < 0) return -1;
- *reg = state->pieces->reg;
- return 0;
- }
- set_errno(ERR_OTHER, "Symbol is not located in a register");
- return -1;
-}
-
-int get_symbol_offset(const Symbol * sym, ContextAddress * offset) {
- LocationExpressionState * state = evaluate_symbol_location(sym, 1);
- if (state == NULL) return -1;
- if (state->pieces_cnt > 0) {
- set_errno(ERR_OTHER, "Cannot get member offset: the symbol is a bit field");
- return -1;
- }
- if (state->stk_pos == 1) {
- *offset = (ContextAddress)state->stk[0];
- return 0;
- }
- set_errno(ERR_OTHER, "Symbol does not have a member offset");
- return -1;
-}
-
typedef struct CommandGetContextArgs {
char token[256];
char id[256];
@@ -128,6 +81,7 @@ static void command_get_context_cache_client(void * x) {
int has_lower_bound = 0;
int has_offset = 0;
int has_address = 0;
+ int has_frame = 0;
int big_endian = 0;
ContextAddress size = 0;
ContextAddress length = 0;
@@ -154,36 +108,49 @@ static void command_get_context_cache_client(void * x) {
get_symbol_base_type(sym, &base);
get_symbol_index_type(sym, &index);
get_symbol_container(sym, &container);
+ has_frame = get_symbol_frame(sym, &ctx, &frame) == 0;
has_size = get_symbol_size(sym, &size) == 0;
has_length = get_symbol_length(sym, &length) == 0;
- if (has_length) {
- has_lower_bound = get_symbol_lower_bound(sym, &lower_bound) == 0;
- }
- if (sym_class == SYM_CLASS_REFERENCE) {
- has_offset = get_symbol_offset(sym, &offset) == 0;
- }
- if (sym_class == SYM_CLASS_REFERENCE || sym_class == SYM_CLASS_FUNCTION) {
- LocationExpressionState * state = evaluate_symbol_location(sym, 0);
- if (state != NULL) {
- if (state->stk_pos == 1) {
- address = (ContextAddress)state->stk[0];
- has_address = 1;
+ if (has_length) has_lower_bound = get_symbol_lower_bound(sym, &lower_bound) == 0;
+ if (sym_class == SYM_CLASS_REFERENCE || sym_class == SYM_CLASS_FUNCTION || sym_class == SYM_CLASS_VALUE) {
+ LocationInfo * loc_info = NULL;
+ if (has_frame && get_location_info(sym, &loc_info) == 0) {
+ LocationExpressionState * state = NULL;
+ if (loc_info->args_cnt == 0) {
+ /* Absolute location */
+ state = evaluate_location(ctx, frame, loc_info);
+ if (state != NULL) {
+ if (state->stk_pos == 1) {
+ address = (ContextAddress)state->stk[0];
+ has_address = 1;
+ }
+ if (state->pieces_cnt == 1 && state->pieces->reg != NULL &&
+ state->pieces->reg->size == state->pieces->size) {
+ reg = state->pieces->reg;
+ }
+ if (state->pieces_cnt > 0) {
+ Trap trap;
+ if (set_trap(&trap)) {
+ read_location_peices(state->ctx, state->stack_frame,
+ state->pieces, state->pieces_cnt, loc_info->big_endian, &value, &value_size);
+ big_endian = loc_info->big_endian;
+ clear_trap(&trap);
+ }
+ }
+ }
}
- if (state->pieces_cnt == 1 && state->pieces->reg != NULL &&
- state->pieces->reg->size == state->pieces->size) {
- reg = state->pieces->reg;
+ else if (loc_info->args_cnt == 1) {
+ /* Relative location */
+ state = evaluate_location(ctx, frame, loc_info);
+ if (state != NULL && state->stk_pos == 1) {
+ offset = (ContextAddress)state->stk[0];
+ has_offset = 1;
+ }
}
}
}
- if (sym_class == SYM_CLASS_VALUE) {
- get_symbol_value(sym, &value, &value_size, &big_endian);
- }
- if (sym_class == SYM_CLASS_REFERENCE && !has_address && !has_offset) {
- get_symbol_value(sym, &value, &value_size, &big_endian);
- assert(value == NULL || update_policy == UPDATE_ON_EXE_STATE_CHANGES);
- }
get_symbol_flags(sym, &flags);
- get_symbol_frame(sym, &ctx, &frame);
+ assert(value == NULL || update_policy == UPDATE_ON_EXE_STATE_CHANGES);
}
cache_exit();
@@ -323,7 +290,7 @@ static void command_get_context_cache_client(void * x) {
}
}
- if (frame != STACK_NO_FRAME) {
+ if (has_frame && frame != STACK_NO_FRAME) {
json_write_string(&c->out, "Frame");
write_stream(&c->out, ':');
json_write_long(&c->out, frame);
@@ -781,7 +748,7 @@ static void write_commands(OutputStream * out, Context * ctx, LocationExpression
if (cmd->args.piece.reg == NULL) write_string(out, "null");
else json_write_string(out, register2id(ctx, STACK_NO_FRAME, cmd->args.piece.reg));
write_stream(out, ',');
- if (cmd->args.piece.value != NULL) write_string(out, "null");
+ if (cmd->args.piece.value == NULL) write_string(out, "null");
else json_write_binary(out, cmd->args.piece.value, (cmd->args.piece.bit_size + 7) / 8);
break;
}
@@ -823,27 +790,13 @@ static void command_get_location_info_cache_client(void * x) {
}
else {
write_stream(&c->out, '{');
+ json_write_string(&c->out, "BigEndian");
+ write_stream(&c->out, ':');
+ json_write_boolean(&c->out, info->big_endian);
+ write_stream(&c->out, ',');
json_write_string(&c->out, "ValueCmds");
write_stream(&c->out, ':');
write_commands(&c->out, ctx, info->value_cmds.cmds, info->value_cmds.cnt);
- if (info->length_cmds.cnt > 0) {
- write_stream(&c->out, ',');
- json_write_string(&c->out, "LengthCmds");
- write_stream(&c->out, ':');
- write_commands(&c->out, ctx, info->length_cmds.cmds, info->length_cmds.cnt);
- if (info->length_size > 0) {
- write_stream(&c->out, ',');
- json_write_string(&c->out, "LengthSize");
- write_stream(&c->out, ':');
- json_write_uint64(&c->out, info->length_size);
- }
- if (info->length_bits > 0) {
- write_stream(&c->out, ',');
- json_write_string(&c->out, "LengthBits");
- write_stream(&c->out, ':');
- json_write_ulong(&c->out, info->length_bits);
- }
- }
if (info->args_cnt) {
write_stream(&c->out, ',');
json_write_string(&c->out, "ArgCnt");
diff --git a/agent/tcf/services/symbols.h b/agent/tcf/services/symbols.h
index 1af80552..733625f8 100644
--- a/agent/tcf/services/symbols.h
+++ b/agent/tcf/services/symbols.h
@@ -97,11 +97,9 @@ typedef struct LocationCommands {
typedef struct LocationInfo {
ContextAddress code_addr;
ContextAddress code_size;
+ int big_endian;
unsigned args_cnt;
LocationCommands value_cmds;
- LocationCommands length_cmds;
- ContextAddress length_size;
- unsigned length_bits;
} LocationInfo;
/* Stack tracing command sequence */
diff --git a/agent/tcf/services/symbols_common.c b/agent/tcf/services/symbols_common.c
new file mode 100644
index 00000000..e808050a
--- /dev/null
+++ b/agent/tcf/services/symbols_common.c
@@ -0,0 +1,118 @@
+/*******************************************************************************
+ * Copyright (c) 2012 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
+ *******************************************************************************/
+
+/*
+ * Symbols service - common code that is shared between different implementations of the service.
+ */
+
+#include <tcf/config.h>
+
+#if SERVICE_Symbols || ENABLE_SymbolsProxy
+
+#include <tcf/framework/myalloc.h>
+#include <tcf/framework/exceptions.h>
+#include <tcf/services/stacktrace.h>
+#include <tcf/services/symbols.h>
+#include <tcf/services/vm.h>
+
+static LocationInfo * loc_info = NULL;
+
+static LocationExpressionState * evaluate_symbol_location(const Symbol * sym, unsigned args_cnt) {
+ Trap trap;
+ Context * ctx = NULL;
+ int frame = STACK_NO_FRAME;
+ StackFrame * frame_info = NULL;
+ LocationExpressionState * state = NULL;
+ static uint64_t args[] = { 0, 0 };
+
+ if (get_symbol_frame(sym, &ctx, &frame) < 0) return NULL;
+ if (get_location_info(sym, &loc_info) < 0) return NULL;
+ if (loc_info->args_cnt != args_cnt) {
+ set_errno(ERR_OTHER, "Wrong object kind");
+ return NULL;
+ }
+ if (frame != STACK_NO_FRAME && get_frame_info(ctx, frame, &frame_info) < 0) return NULL;
+ if (!set_trap(&trap)) return NULL;
+ state = evaluate_location_expression(ctx, frame_info,
+ loc_info->value_cmds.cmds, loc_info->value_cmds.cnt, args, args_cnt);
+ clear_trap(&trap);
+ return state;
+}
+
+int get_symbol_address(const Symbol * sym, ContextAddress * address) {
+ LocationExpressionState * state = evaluate_symbol_location(sym, 0);
+ if (state == NULL) return -1;
+ if (state->stk_pos == 1) {
+ *address = (ContextAddress)state->stk[0];
+ return 0;
+ }
+ set_errno(ERR_OTHER, "Symbol does not have a memory address");
+ return -1;
+}
+
+int get_symbol_register(const Symbol * sym, Context ** ctx, int * frame, RegisterDefinition ** reg) {
+ LocationExpressionState * state = evaluate_symbol_location(sym, 0);
+ if (state == NULL) return -1;
+ if (state->pieces_cnt == 1 && state->pieces->reg != NULL && state->pieces->reg->size == state->pieces->size) {
+ if (get_symbol_frame(sym, ctx, frame) < 0) return -1;
+ *reg = state->pieces->reg;
+ return 0;
+ }
+ set_errno(ERR_OTHER, "Symbol is not located in a register");
+ return -1;
+}
+
+int get_symbol_offset(const Symbol * sym, ContextAddress * offset) {
+ LocationExpressionState * state = evaluate_symbol_location(sym, 1);
+ if (state == NULL) return -1;
+ if (state->pieces_cnt > 0) {
+ set_errno(ERR_OTHER, "Cannot get member offset: the symbol is a bit field");
+ return -1;
+ }
+ if (state->stk_pos == 1) {
+ *offset = (ContextAddress)state->stk[0];
+ return 0;
+ }
+ set_errno(ERR_OTHER, "Symbol does not have a member offset");
+ return -1;
+}
+
+int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big_endian) {
+ Trap trap;
+ LocationExpressionState * state = evaluate_symbol_location(sym, 0);
+ if (state == NULL) return -1;
+ if (!set_trap(&trap)) return -1;
+ if (state->pieces_cnt > 0) {
+ read_location_peices(state->ctx, state->stack_frame,
+ state->pieces, state->pieces_cnt, loc_info->big_endian, value, size);
+ }
+ else {
+ ContextAddress sym_size = 0;
+ size_t buf_size = 0;
+ void * buf = NULL;
+ if (state->stk_pos != 1) str_exception(ERR_OTHER, "Invalid location expression");
+ if (get_symbol_size(sym, &sym_size) < 0) exception(errno);
+ buf_size = (size_t)sym_size;
+ buf = tmp_alloc(buf_size);
+ if (context_read_mem(state->ctx, (ContextAddress)state->stk[0], buf, buf_size) < 0) exception(errno);
+ *value = buf;
+ *size = buf_size;
+ }
+ *big_endian = loc_info->big_endian;
+ clear_trap(&trap);
+ return 0;
+}
+
+#endif
diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c
index b74d47bc..941a4ef7 100644
--- a/agent/tcf/services/symbols_elf.c
+++ b/agent/tcf/services/symbols_elf.c
@@ -260,10 +260,6 @@ static int is_frame_based_object(Symbol * sym) {
else if (get_symbol_address(sym, &addr) < 0) {
res = 1;
}
- else {
- sym->has_address = 1;
- sym->address = addr;
- }
}
if (!res) {
@@ -1662,7 +1658,7 @@ static void read_object_value(PropertyValue * v, void ** value, size_t * size, i
else {
U1_T * p = (U1_T *)&v->mValue;
if (val_size > sizeof(v->mValue)) str_exception(ERR_INV_DWARF, "Unknown object size");
- if (big_endian_host()) p += (size_t)val_size;
+ if (big_endian_host()) p += sizeof(v->mValue) - (size_t)val_size;
memcpy(bf, p, (size_t)val_size);
*big_endian = big_endian_host();
}
@@ -1725,11 +1721,16 @@ int get_symbol_type(const Symbol * sym, Symbol ** type) {
return 0;
}
if (sym->sym_class == SYM_CLASS_FUNCTION) {
- *type = alloc_symbol();
- (*type)->ctx = sym->ctx;
- (*type)->frame = STACK_NO_FRAME;
- (*type)->sym_class = SYM_CLASS_TYPE;
- (*type)->base = (Symbol *)sym;
+ if (obj == NULL) {
+ *type = NULL;
+ }
+ else {
+ *type = alloc_symbol();
+ (*type)->ctx = sym->ctx;
+ (*type)->frame = STACK_NO_FRAME;
+ (*type)->sym_class = SYM_CLASS_TYPE;
+ (*type)->base = (Symbol *)sym;
+ }
return 0;
}
if (unpack(sym) < 0) return -1;
@@ -2078,6 +2079,9 @@ int get_symbol_base_type(const Symbol * sym, Symbol ** base_type) {
}
return err_no_info();
}
+ if (sym->base->sym_class == SYM_CLASS_REFERENCE) {
+ return err_no_info();
+ }
*base_type = sym->base;
return 0;
}
@@ -2121,9 +2125,7 @@ int get_symbol_index_type(const Symbol * sym, Symbol ** index_type) {
ObjectInfo * obj = sym->obj;
assert(sym->magic == SYMBOL_MAGIC);
if (is_array_type_pseudo_symbol(sym)) {
- if (sym->base->sym_class == SYM_CLASS_FUNCTION) {
- return err_wrong_obj();
- }
+ if (sym->base->sym_class != SYM_CLASS_TYPE) return err_wrong_obj();
alloc_cardinal_type_pseudo_symbol(sym->ctx, context_word_size(sym->ctx), index_type);
return 0;
}
@@ -2195,9 +2197,7 @@ int get_symbol_length(const Symbol * sym, ContextAddress * length) {
ObjectInfo * obj = sym->obj;
assert(sym->magic == SYMBOL_MAGIC);
if (is_array_type_pseudo_symbol(sym)) {
- if (sym->base->sym_class == SYM_CLASS_FUNCTION) {
- return err_wrong_obj();
- }
+ if (sym->base->sym_class != SYM_CLASS_TYPE) return err_wrong_obj();
*length = sym->length == 0 ? 1 : sym->length;
return 0;
}
@@ -2240,9 +2240,7 @@ int get_symbol_lower_bound(const Symbol * sym, int64_t * value) {
ObjectInfo * obj = sym->obj;
assert(sym->magic == SYMBOL_MAGIC);
if (is_array_type_pseudo_symbol(sym)) {
- if (sym->base->sym_class == SYM_CLASS_FUNCTION) {
- return err_wrong_obj();
- }
+ if (sym->base->sym_class != SYM_CLASS_TYPE) return err_wrong_obj();
*value = 0;
return 0;
}
@@ -2301,6 +2299,17 @@ int get_symbol_children(const Symbol * sym, Symbol *** children, int * count) {
Symbol * y = NULL;
object2symbol(i, &x);
if (get_symbol_type(x, &y) < 0) return -1;
+ if (y == NULL && i->mTag == TAG_unspecified_parameters) {
+ y = alloc_symbol();
+ y->ctx = sym->ctx;
+ y->frame = STACK_NO_FRAME;
+ y->sym_class = SYM_CLASS_TYPE;
+ y->base = (Symbol *)x;
+ }
+ if (y == NULL) {
+ set_errno(ERR_INV_DWARF, "Invalid function arguments info");
+ return -1;
+ }
if (buf_len <= n) {
buf_len += 16;
buf = (Symbol **)tmp_realloc(buf, sizeof(Symbol *) * buf_len);
@@ -2349,116 +2358,6 @@ int get_symbol_children(const Symbol * sym, Symbol *** children, int * count) {
return 0;
}
-int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big_endian) {
- ObjectInfo * obj = sym->obj;
- assert(sym->magic == SYMBOL_MAGIC);
- if (is_constant_pseudo_symbol(sym)) {
- ContextAddress sym_size = 0;
- if (get_symbol_size(sym, &sym_size) < 0) return -1;
- *size = (size_t)sym_size;
- *big_endian = big_endian_host();
- *value = &constant_pseudo_symbols[(int)sym->length].value;
- if (*big_endian && *size < sizeof(ConstantValueType)) {
- *value = (char *)(*value) + (sizeof(ConstantValueType) - *size);
- }
- return 0;
- }
- if (is_array_type_pseudo_symbol(sym) || is_cardinal_type_pseudo_symbol(sym) || sym->var) {
- return err_wrong_obj();
- }
- if (unpack(sym) < 0) return -1;
- if (obj != NULL) {
- Trap trap;
- PropertyValue v;
- Symbol * s = NULL;
- if (set_trap(&trap)) {
- 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;
- }
- else if (trap.error != ERR_SYM_NOT_FOUND) {
- return -1;
- }
- if (set_trap(&trap)) {
- 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;
- }
- else if (trap.error != ERR_SYM_NOT_FOUND) {
- return -1;
- }
-#if SERVICE_StackTrace || ENABLE_ContextProxy
- if (obj->mTag == TAG_formal_parameter) {
- /* Search call site info */
- if (set_trap(&trap)) {
- RegisterDefinition * reg_def = get_PC_definition(sym_ctx);
- if (reg_def != NULL) {
- uint64_t addr = 0;
- ContextAddress rt_addr = 0;
- UnitAddressRange * range = NULL;
- Symbol * caller = NULL;
- StackFrame * info = NULL;
- if (get_frame_info(sym_ctx, get_prev_frame(sym_ctx, sym_frame), &info) < 0) exception(errno);
- if (read_reg_value(info, reg_def, &addr) < 0) exception(errno);
- range = elf_find_unit(sym_ctx, addr, addr, &rt_addr);
- if (range != NULL) find_by_addr_in_unit(
- get_dwarf_children(range->mUnit->mObject),
- 0, rt_addr - range->mAddr, addr, &caller);
- if (caller != NULL && caller->obj != NULL) {
- ObjectInfo * l = get_dwarf_children(caller->obj);
- while (l != NULL) {
- U8_T call_addr = 0;
- if (l->mTag == TAG_GNU_call_site && get_num_prop(l, AT_low_pc, &call_addr)) {
- call_addr += rt_addr - range->mAddr;
- if (call_addr == addr) {
- /*
- clear_trap(&trap);
- return 0;
- */
- }
- }
- l = l->mSibling;
- }
- }
- }
- exception(ERR_SYM_NOT_FOUND);
- }
- }
-#endif
- if (map_to_sym_table(obj, &s)) return get_symbol_value(s, value, size, big_endian);
- set_errno(ERR_OTHER, "No object location or value info found in DWARF data");
- return -1;
- }
- if (sym->tbl != NULL && sym->dimension == 0) {
- ELF_SymbolInfo info;
- unpack_elf_symbol_info(sym->tbl, sym->index, &info);
- switch (info.type) {
- case STT_OBJECT:
- case STT_FUNC:
- case STT_GNU_IFUNC:
- set_errno(ERR_OTHER, "Symbol represents an address");
- return -1;
- }
- if (info.sym_section->file->elf64) {
- static U8_T buf = 0;
- buf = info.value;
- *value = &buf;
- *size = 8;
- }
- else {
- static U4_T buf = 0;
- buf = (U4_T)info.value;
- *value = &buf;
- *size = 4;
- }
- *big_endian = big_endian_host();
- return 0;
- }
- return err_no_info();
-}
-
static int calc_member_offset(ObjectInfo * type, ObjectInfo * member, ContextAddress * offs) {
PropertyValue v;
ObjectInfo * obj = NULL;
@@ -2481,45 +2380,6 @@ static int calc_member_offset(ObjectInfo * type, ObjectInfo * member, ContextAdd
return 0;
}
-static int get_elf_symbol_address(const Symbol * sym, ContextAddress * address) {
- ELF_SymbolInfo info;
- assert(sym_ctx == sym->ctx);
- if (sym->dimension != 0) {
- /* @plt symbol */
- *address = sym->tbl->addr + sym->cardinal + sym->index * sym->dimension;
- return 0;
- }
- unpack_elf_symbol_info(sym->tbl, sym->index, &info);
- if (info.type == STT_GNU_IFUNC && info.name != NULL) {
- int error = 0;
- int found = 0;
- ELF_File * file = elf_list_first(sym_ctx, 0, ~(ContextAddress)0);
- if (file == NULL) error = errno;
- while (error == 0 && file != NULL) {
- ContextAddress got_addr = 0;
- if (elf_find_got_entry(file, info.name, &got_addr) < 0) {
- error = errno;
- }
- else if (got_addr != 0) {
- got_addr = elf_map_to_run_time_address(sym_ctx, file, NULL, got_addr);
- if (got_addr != 0 && elf_read_memory_word(sym_ctx, file, got_addr, address) == 0) {
- found = 1;
- break;
- }
- }
- file = elf_list_next(sym_ctx);
- if (file == NULL) error = errno;
- }
- elf_list_done(sym_ctx);
- if (found) return 0;
- if (error) {
- errno = error;
- return -1;
- }
- }
- return syminfo2address(sym_ctx, &info, address);
-}
-
static LocationCommands * location_cmds = NULL;
static LocationExpressionState * location_command_state = NULL;
@@ -2582,10 +2442,28 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
location_cmds = &info->value_cmds;
if (sym->has_address) {
+ info->big_endian = big_endian_host();
add_location_command(SFT_CMD_NUMBER)->args.num = sym->address;
return 0;
}
+ if (is_constant_pseudo_symbol(sym)) {
+ void * value = NULL;
+ ContextAddress size = 0;
+ LocationExpressionCommand * cmd = add_location_command(SFT_CMD_PIECE);
+
+ if (get_symbol_size(sym->base, &size) < 0) return -1;
+ info->big_endian = big_endian_host();
+ cmd->args.piece.bit_size = (unsigned)(size * 8);
+ cmd->args.piece.value = tmp_alloc((size_t)size);
+ value = &constant_pseudo_symbols[(int)sym->length].value;
+ if (big_endian_host() && size < sizeof(ConstantValueType)) {
+ value = (uint8_t *)value + (sizeof(ConstantValueType) - size);
+ }
+ memcpy(cmd->args.piece.value, value, (size_t)size);
+ return 0;
+ }
+
if (is_array_type_pseudo_symbol(sym) ||
is_cardinal_type_pseudo_symbol(sym) ||
is_constant_pseudo_symbol(sym)) {
@@ -2598,23 +2476,7 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
Trap trap;
PropertyValue v;
- if (obj->mType != NULL && obj->mType->mTag == TAG_string_type) {
- if (set_trap(&trap)) {
- U8_T n = 0;
- location_cmds = &info->length_cmds;
- read_dwarf_object_property(sym_ctx, sym_frame, obj->mType, AT_string_length, &v);
- add_dwarf_location_command(info, &v);
- clear_trap(&trap);
- if (get_num_prop(obj->mType, AT_byte_size, &n)) info->length_size = (ContextAddress)n;
- else if (get_num_prop(obj->mType, AT_bit_size, &n)) info->length_bits = (unsigned)n;
- }
- else if (errno != ERR_SYM_NOT_FOUND) {
- set_errno(errno, "Cannot read location expression");
- return -1;
- }
- }
-
- location_cmds = &info->value_cmds;
+ info->big_endian = obj->mCompUnit->mFile->big_endian;
if ((obj->mFlags & DOIF_external) == 0 && sym->var != NULL) {
/* The symbol represents a member of a class instance */
ContextAddress offs = 0;
@@ -2651,11 +2513,51 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
return -1;
}
}
+ if (obj->mTag != TAG_inlined_subroutine) {
+ if (set_trap(&trap)) {
+ LocationExpressionCommand * cmd = NULL;
+ read_dwarf_object_property(sym_ctx, sym_frame, obj, AT_const_value, &v);
+ assert(v.mObject == obj);
+ assert(v.mPieces == NULL);
+ assert(v.mForm != FORM_EXPRLOC);
+ if (v.mAddr != NULL) {
+ assert(v.mBigEndian == info->big_endian);
+ cmd = add_location_command(SFT_CMD_PIECE);
+ cmd->args.piece.bit_size = v.mSize * 8;
+ cmd->args.piece.value = v.mAddr;
+ }
+ else {
+ U1_T * bf = NULL;
+ U8_T val_size = 0;
+ U8_T bit_size = 0;
+ U1_T * p = (U1_T *)&v.mValue;
+ if (!get_object_size(obj, 0, &val_size, &bit_size)) {
+ str_exception(ERR_INV_DWARF, "Unknown object size");
+ }
+ assert(v.mForm != FORM_EXPR_VALUE);
+ if (val_size > sizeof(v.mValue)) str_exception(ERR_INV_DWARF, "Unknown object size");
+ bf = (U1_T *)tmp_alloc((size_t)val_size);
+ if (big_endian_host()) p += sizeof(v.mValue) - (size_t)val_size;
+ memcpy(bf, p, (size_t)val_size);
+ info->big_endian = big_endian_host();
+ if (bit_size % 8 != 0) bf[bit_size / 8] &= (1 << (bit_size % 8)) - 1;
+ cmd = add_location_command(SFT_CMD_PIECE);
+ cmd->args.piece.bit_size = (unsigned)(bit_size ? bit_size : val_size * 8);
+ cmd->args.piece.value = bf;
+ }
+ clear_trap(&trap);
+ return 0;
+ }
+ else if (trap.error != ERR_SYM_NOT_FOUND) {
+ 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_DATA2 :
case FORM_DATA4 :
case FORM_DATA8 :
case FORM_SDATA :
@@ -2668,9 +2570,13 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
case FORM_BLOCK2 :
case FORM_BLOCK4 :
case FORM_BLOCK :
+ case FORM_EXPRLOC :
add_location_command(SFT_CMD_ARG)->args.arg_no = 0;
add_dwarf_location_command(info, &v);
break;
+ default:
+ str_fmt_exception(ERR_OTHER, "Invalid AT_data_member_location form 0x%04x", v.mForm);
+ break;
}
info->args_cnt = 1;
clear_trap(&trap);
@@ -2682,6 +2588,44 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
return -1;
}
}
+#if SERVICE_StackTrace || ENABLE_ContextProxy
+ if (obj->mTag == TAG_formal_parameter) {
+ /* Search call site info */
+ if (set_trap(&trap)) {
+ RegisterDefinition * reg_def = get_PC_definition(sym_ctx);
+ if (reg_def != NULL) {
+ uint64_t addr = 0;
+ ContextAddress rt_addr = 0;
+ UnitAddressRange * range = NULL;
+ Symbol * caller = NULL;
+ StackFrame * info = NULL;
+ if (get_frame_info(sym_ctx, get_prev_frame(sym_ctx, sym_frame), &info) < 0) exception(errno);
+ if (read_reg_value(info, reg_def, &addr) < 0) exception(errno);
+ range = elf_find_unit(sym_ctx, addr, addr, &rt_addr);
+ if (range != NULL) find_by_addr_in_unit(
+ get_dwarf_children(range->mUnit->mObject),
+ 0, rt_addr - range->mAddr, addr, &caller);
+ if (caller != NULL && caller->obj != NULL) {
+ ObjectInfo * l = get_dwarf_children(caller->obj);
+ while (l != NULL) {
+ U8_T call_addr = 0;
+ if (l->mTag == TAG_GNU_call_site && get_num_prop(l, AT_low_pc, &call_addr)) {
+ call_addr += rt_addr - range->mAddr;
+ if (call_addr == addr) {
+ /*
+ clear_trap(&trap);
+ return 0;
+ */
+ }
+ }
+ l = l->mSibling;
+ }
+ }
+ }
+ exception(ERR_SYM_NOT_FOUND);
+ }
+ }
+#endif
{
U8_T addr = 0;
Symbol * s = NULL;
@@ -2692,14 +2636,15 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
return 0;
}
else if (errno != ERR_SYM_NOT_FOUND) {
- set_errno(errno, "Cannot read 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;
+ else if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
+ return -1;
+ }
if (map_to_sym_table(obj, &s)) return get_location_info(s, res);
set_errno(ERR_OTHER, "No object location info found in DWARF data");
return -1;
@@ -2707,13 +2652,73 @@ int get_location_info(const Symbol * sym, LocationInfo ** res) {
}
if (sym->tbl != NULL) {
- ContextAddress addr = 0;
- if (get_elf_symbol_address(sym, &addr) < 0) return -1;
- add_location_command(SFT_CMD_NUMBER)->args.num = addr;
+ LocationExpressionCommand * cmd = NULL;
+ ELF_SymbolInfo elf_sym_info;
+ ContextAddress address = 0;
+ info->big_endian = sym->tbl->file->big_endian;
+ if (sym->dimension != 0) {
+ /* @plt symbol */
+ address = sym->tbl->addr + sym->cardinal + sym->index * sym->dimension;
+ add_location_command(SFT_CMD_NUMBER)->args.num = address;
+ return 0;
+ }
+ unpack_elf_symbol_info(sym->tbl, sym->index, &elf_sym_info);
+ if (elf_sym_info.type == STT_GNU_IFUNC && elf_sym_info.name != NULL) {
+ int error = 0;
+ int found = 0;
+ ELF_File * file = elf_list_first(sym_ctx, 0, ~(ContextAddress)0);
+ if (file == NULL) error = errno;
+ while (error == 0 && file != NULL) {
+ ContextAddress got_addr = 0;
+ if (elf_find_got_entry(file, elf_sym_info.name, &got_addr) < 0) {
+ error = errno;
+ }
+ else if (got_addr != 0) {
+ got_addr = elf_map_to_run_time_address(sym_ctx, file, NULL, got_addr);
+ if (got_addr != 0 && elf_read_memory_word(sym_ctx, file, got_addr, &address) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ file = elf_list_next(sym_ctx);
+ if (file == NULL) error = errno;
+ }
+ elf_list_done(sym_ctx);
+ if (found) {
+ add_location_command(SFT_CMD_NUMBER)->args.num = address;
+ return 0;
+ }
+ if (error) {
+ errno = error;
+ return -1;
+ }
+ }
+ switch (elf_sym_info.type) {
+ case STT_OBJECT:
+ case STT_FUNC:
+ case STT_GNU_IFUNC:
+ if (syminfo2address(sym_ctx, &elf_sym_info, &address)) return -1;
+ add_location_command(SFT_CMD_NUMBER)->args.num = address;
+ return 0;
+ }
+ info->big_endian = big_endian_host();
+ cmd = add_location_command(SFT_CMD_PIECE);
+ if (elf_sym_info.sym_section->file->elf64) {
+ static U8_T buf = 0;
+ buf = elf_sym_info.value;
+ cmd->args.piece.bit_size = 64;
+ cmd->args.piece.value = &buf;
+ }
+ else {
+ static U4_T buf = 0;
+ buf = (U4_T)elf_sym_info.value;
+ cmd->args.piece.bit_size = 32;
+ cmd->args.piece.value = &buf;
+ }
return 0;
}
- set_errno(ERR_OTHER, "Symbol does not have a memory address");
+ set_errno(ERR_OTHER, "Symbol does not have a location information");
return -1;
}
@@ -2722,7 +2727,12 @@ int get_symbol_flags(const Symbol * sym, SYM_FLAGS * flags) {
ObjectInfo * obj = sym->obj;
*flags = 0;
assert(sym->magic == SYMBOL_MAGIC);
- if (sym->base || is_cardinal_type_pseudo_symbol(sym)) return 0;
+ if (sym->base || is_cardinal_type_pseudo_symbol(sym)) {
+ if (is_array_type_pseudo_symbol(sym) && sym->base->sym_class == SYM_CLASS_REFERENCE) {
+ *flags |= SYM_FLAG_VARARG;
+ }
+ return 0;
+ }
if (unpack(sym) < 0) return -1;
if (obj != NULL) {
if (obj->mFlags & DOIF_external) *flags |= SYM_FLAG_EXTERNAL;
diff --git a/agent/tcf/services/symbols_proxy.c b/agent/tcf/services/symbols_proxy.c
index 8ed779c1..0268a6d2 100644
--- a/agent/tcf/services/symbols_proxy.c
+++ b/agent/tcf/services/symbols_proxy.c
@@ -40,6 +40,10 @@
#define HASH_SIZE (4 * MEM_USAGE_FACTOR - 1)
+#define ACC_SIZE 1
+#define ACC_LENGTH 2
+#define ACC_OTHER 3
+
/* Symbols cahce, one per channel */
typedef struct SymbolsCache {
Channel * channel;
@@ -64,29 +68,20 @@ typedef struct SymInfoCache {
char * base_type_id;
char * index_type_id;
char * container_id;
- char * register_id;
char * name;
Context * update_owner;
int update_policy;
+ int degraded;
int sym_class;
int type_class;
int has_size;
- int has_address;
- int has_offset;
int has_length;
int has_lower_bound;
- int has_upper_bound;
int frame;
SYM_FLAGS flags;
- ContextAddress address;
ContextAddress size;
- ContextAddress offset;
ContextAddress length;
int64_t lower_bound;
- int64_t upper_bound;
- char * value;
- size_t value_size;
- int big_endian;
char ** children_ids;
int children_count;
ReplyHandlerInfo * pending_get_context;
@@ -118,6 +113,7 @@ typedef struct FindSymCache {
ErrorReport * error;
int update_policy;
Context * ctx;
+ int frame;
uint64_t ip;
uint64_t addr;
char * scope;
@@ -267,9 +263,7 @@ static void free_sym_info_cache(SymInfoCache * c) {
loc_free(c->base_type_id);
loc_free(c->index_type_id);
loc_free(c->container_id);
- loc_free(c->register_id);
loc_free(c->name);
- loc_free(c->value);
loc_free(c->children_ids);
if (c->update_owner != NULL) context_unlock(c->update_owner);
release_error_report(c->error_get_context);
@@ -344,7 +338,6 @@ static void free_location_info_cache(LocationInfoCache * c) {
context_unlock(c->ctx);
loc_free(c->sym_id);
free_location_commands(&c->info.value_cmds);
- free_location_commands(&c->info.length_cmds);
loc_free(c);
}
}
@@ -398,13 +391,7 @@ static void read_context_data(InputStream * inp, const char * name, void * args)
else if (strcmp(name, "Size") == 0) { s->size = json_read_long(inp); s->has_size = 1; }
else if (strcmp(name, "Length") == 0) { s->length = json_read_long(inp); s->has_length = 1; }
else if (strcmp(name, "LowerBound") == 0) { s->lower_bound = json_read_int64(inp); s->has_lower_bound = 1; }
- else if (strcmp(name, "UpperBound") == 0) { s->upper_bound = json_read_int64(inp); s->has_upper_bound = 1; }
- else if (strcmp(name, "Offset") == 0) { s->offset = json_read_long(inp); s->has_offset = 1; }
- else if (strcmp(name, "Address") == 0) { s->address = (ContextAddress)json_read_uint64(inp); s->has_address = 1; }
- else if (strcmp(name, "Register") == 0) s->register_id = json_read_alloc_string(inp);
else if (strcmp(name, "Flags") == 0) s->flags = json_read_ulong(inp);
- else if (strcmp(name, "Value") == 0) s->value = json_read_alloc_binary(inp, &s->value_size);
- else if (strcmp(name, "BigEndian") == 0) s->big_endian = json_read_boolean(inp);
else if (strcmp(name, "Frame") == 0) s->frame = (int)json_read_long(inp);
else json_skip_object(inp);
}
@@ -416,6 +403,7 @@ static void validate_context(Channel * c, void * args, int error) {
assert(s->error_get_context == NULL);
assert(s->update_owner == NULL);
assert(!s->done_context);
+ assert(!s->degraded);
if (set_trap(&trap)) {
s->pending_get_context = NULL;
s->done_context = 1;
@@ -439,7 +427,7 @@ static void validate_context(Channel * c, void * args, int error) {
if (s->disposed) free_sym_info_cache(s);
}
-static SymInfoCache * get_sym_info_cache(const Symbol * sym) {
+static SymInfoCache * get_sym_info_cache(const Symbol * sym, int acc_mode) {
Trap trap;
SymInfoCache * s = sym->cache;
assert(sym->magic == SYMBOL_MAGIC);
@@ -449,10 +437,43 @@ static SymInfoCache * get_sym_info_cache(const Symbol * sym) {
if (s->pending_get_context != NULL) {
cache_wait(&s->cache);
}
- else if (s->error_get_context != NULL) {
+ if (s->error_get_context != NULL) {
exception(set_error_report_errno(s->error_get_context));
}
- else if (!s->done_context) {
+ if (s->done_context && s->degraded) {
+ /* Symbol info is partially outdated */
+ int update = 0;
+ assert(s->update_owner != NULL);
+ assert(context_has_state(s->update_owner));
+ switch (acc_mode) {
+ case ACC_SIZE:
+ case ACC_LENGTH:
+ if (s->type_class != TYPE_CLASS_ARRAY) break;
+ update = 1;
+ break;
+ }
+ if (update) {
+ if (!s->update_owner->stopped) exception(ERR_IS_RUNNING);
+ s->degraded = 0;
+ s->done_context = 0;
+ s->has_size = 0;
+ s->has_length = 0;
+ s->has_lower_bound = 0;
+ context_unlock(s->update_owner);
+ loc_free(s->type_id);
+ loc_free(s->base_type_id);
+ loc_free(s->index_type_id);
+ loc_free(s->container_id);
+ loc_free(s->name);
+ s->update_owner = NULL;
+ s->type_id = NULL;
+ s->base_type_id = NULL;
+ s->index_type_id = NULL;
+ s->container_id = NULL;
+ s->name = NULL;
+ }
+ }
+ if (!s->done_context) {
Channel * c = cache_channel();
if (c == NULL || is_channel_closed(c)) exception(ERR_SYM_NOT_FOUND);
s->pending_get_context = protocol_send_command(c, SYMBOLS, "getContext", validate_context, s);
@@ -532,7 +553,7 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress addr, const cha
syms = get_symbols_cache();
for (l = syms->link_find_by_name[h].next; l != syms->link_find_by_name + h; l = l->next) {
FindSymCache * c = syms2find(l);
- if (c->ctx == ctx && c->ip == ip && strcmp(c->name, name) == 0) {
+ if (c->ctx == ctx && c->frame == frame && c->ip == ip && strcmp(c->name, name) == 0) {
f = c;
break;
}
@@ -570,9 +591,10 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress addr, const cha
f = (FindSymCache *)loc_alloc_zero(sizeof(FindSymCache));
list_add_first(&f->link_syms, syms->link_find_by_name + h);
context_lock(f->ctx = ctx);
+ f->frame = frame;
f->ip = ip;
f->name = loc_strdup(name);
- f->update_policy = ip ? UPDATE_ON_EXE_STATE_CHANGES : UPDATE_ON_MEMORY_MAP_CHANGES;
+ f->update_policy = UPDATE_ON_MEMORY_MAP_CHANGES;
f->pending = protocol_send_command(c, SYMBOLS, "findByName", validate_find, f);
if (frame != STACK_NO_FRAME) {
json_write_string(&c->out, frame2id(ctx, frame));
@@ -633,7 +655,7 @@ int find_symbol_by_addr(Context * ctx, int frame, ContextAddress addr, Symbol **
syms = get_symbols_cache();
for (l = syms->link_find_by_addr[h].next; l != syms->link_find_by_addr + h; l = l->next) {
FindSymCache * c = syms2find(l);
- if (c->ctx == ctx && c->ip == ip && c->addr == addr) {
+ if (c->ctx == ctx && c->frame == frame && c->ip == ip && c->addr == addr) {
f = c;
break;
}
@@ -644,6 +666,7 @@ int find_symbol_by_addr(Context * ctx, int frame, ContextAddress addr, Symbol **
f = (FindSymCache *)loc_alloc_zero(sizeof(FindSymCache));
list_add_first(&f->link_syms, syms->link_find_by_addr + h);
context_lock(f->ctx = ctx);
+ f->frame = frame;
f->ip = ip;
f->addr = addr;
f->update_policy = ip ? UPDATE_ON_EXE_STATE_CHANGES : UPDATE_ON_MEMORY_MAP_CHANGES;
@@ -703,7 +726,7 @@ int find_symbol_in_scope(Context * ctx, int frame, ContextAddress addr, Symbol *
syms = get_symbols_cache();
for (l = syms->link_find_in_scope[h].next; l != syms->link_find_in_scope + h; l = l->next) {
FindSymCache * c = syms2find(l);
- if (c->ctx == ctx && c->ip == ip && strcmp(c->name, name) == 0) {
+ if (c->ctx == ctx && c->frame == frame && c->ip == ip && strcmp(c->name, name) == 0) {
if (scope == NULL && c->scope == NULL) {
f = c;
break;
@@ -721,10 +744,11 @@ int find_symbol_in_scope(Context * ctx, int frame, ContextAddress addr, Symbol *
f = (FindSymCache *)loc_alloc_zero(sizeof(FindSymCache));
list_add_first(&f->link_syms, syms->link_find_in_scope + h);
context_lock(f->ctx = ctx);
+ f->frame = frame;
f->ip = ip;
if (scope != NULL) f->scope = loc_strdup(scope->cache->id);
f->name = loc_strdup(name);
- f->update_policy = ip ? UPDATE_ON_EXE_STATE_CHANGES : UPDATE_ON_MEMORY_MAP_CHANGES;
+ f->update_policy = UPDATE_ON_MEMORY_MAP_CHANGES;
f->pending = protocol_send_command(c, SYMBOLS, "findInScope", validate_find, f);
if (frame != STACK_NO_FRAME) {
json_write_string(&c->out, frame2id(ctx, frame));
@@ -796,7 +820,7 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * func,
syms = get_symbols_cache();
for (l = syms->link_list[h].next; l != syms->link_list + h; l = l->next) {
FindSymCache * c = syms2find(l);
- if (c->ctx == ctx && c->ip == ip) {
+ if (c->ctx == ctx && c->frame == frame && c->ip == ip) {
f = c;
break;
}
@@ -807,8 +831,9 @@ int enumerate_symbols(Context * ctx, int frame, EnumerateSymbolsCallBack * func,
f = (FindSymCache *)loc_alloc_zero(sizeof(FindSymCache));
list_add_first(&f->link_syms, syms->link_list + h);
context_lock(f->ctx = ctx);
+ f->frame = frame;
f->ip = ip;
- f->update_policy = ip ? UPDATE_ON_EXE_STATE_CHANGES : UPDATE_ON_MEMORY_MAP_CHANGES;
+ f->update_policy = UPDATE_ON_MEMORY_MAP_CHANGES;
f->pending = protocol_send_command(c, SYMBOLS, "list", validate_find, f);
if (frame != STACK_NO_FRAME) {
json_write_string(&c->out, frame2id(ctx, frame));
@@ -872,8 +897,6 @@ int id2symbol(const char * id, Symbol ** sym) {
char ctx_id[256];
if (sscanf(id, "@T.%X.%"SCNx64".%255s", &sym_class, &address, ctx_id) == 3) {
s->done_context = 1;
- s->has_address = 1;
- s->address = (ContextAddress)address;
s->sym_class = sym_class;
s->update_policy = UPDATE_ON_MEMORY_MAP_CHANGES;
s->update_owner = id2ctx(ctx_id);
@@ -890,14 +913,14 @@ int id2symbol(const char * id, Symbol ** sym) {
/*************** Functions for retrieving symbol properties ***************************************/
int get_symbol_class(const Symbol * sym, int * symbol_class) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
*symbol_class = c->sym_class;
return 0;
}
int get_symbol_type(const Symbol * sym, Symbol ** type) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
if (c->type_id && strcmp(c->type_id, c->id)) return id2symbol(c->type_id, type);
*type = (Symbol *)sym;
@@ -905,14 +928,14 @@ int get_symbol_type(const Symbol * sym, Symbol ** type) {
}
int get_symbol_type_class(const Symbol * sym, int * type_class) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
*type_class = c->type_class;
return 0;
}
int get_symbol_update_policy(const Symbol * sym, char ** id, int * policy) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
if (c->update_owner == NULL) {
errno = ERR_INV_CONTEXT;
@@ -924,35 +947,35 @@ int get_symbol_update_policy(const Symbol * sym, char ** id, int * policy) {
}
int get_symbol_name(const Symbol * sym, char ** name) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
*name = c->name;
return 0;
}
int get_symbol_base_type(const Symbol * sym, Symbol ** type) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
if (c->base_type_id) return id2symbol(c->base_type_id, type);
return 0;
}
int get_symbol_index_type(const Symbol * sym, Symbol ** type) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
if (c->index_type_id) return id2symbol(c->index_type_id, type);
return 0;
}
int get_symbol_container(const Symbol * sym, Symbol ** container) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
if (c->container_id) return id2symbol(c->container_id, container);
return 0;
}
int get_symbol_size(const Symbol * sym, ContextAddress * size) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_SIZE);
if (c == NULL) return -1;
if (!c->has_size) {
set_errno(ERR_OTHER, "Debug info not available");
@@ -963,22 +986,18 @@ int get_symbol_size(const Symbol * sym, ContextAddress * size) {
}
int get_symbol_length(const Symbol * sym, ContextAddress * length) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_LENGTH);
if (c == NULL) return -1;
if (c->has_length) {
*length = c->length;
return 0;
}
- if (c->has_lower_bound && c->has_upper_bound) {
- *length = (ContextAddress)(c->has_upper_bound - c->has_lower_bound + 1);
- return 0;
- }
errno = ERR_INV_CONTEXT;
return -1;
}
int get_symbol_lower_bound(const Symbol * sym, int64_t * lower_bound) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
if (!c->has_lower_bound) {
errno = ERR_INV_CONTEXT;
@@ -988,76 +1007,15 @@ int get_symbol_lower_bound(const Symbol * sym, int64_t * lower_bound) {
return 0;
}
-int get_symbol_offset(const Symbol * sym, ContextAddress * offset) {
- SymInfoCache * c = get_sym_info_cache(sym);
- if (c == NULL) return -1;
- if (!c->has_offset) {
- errno = ERR_INV_CONTEXT;
- return -1;
- }
- *offset = c->offset;
- return 0;
-}
-
-int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big_endian) {
- SymInfoCache * c = get_sym_info_cache(sym);
- if (c == NULL) return -1;
- if (c->sym_class == SYM_CLASS_REFERENCE) {
- if (!c->has_size) {
- set_errno(ERR_OTHER, "Symbol size is unknown");
- return -1;
- }
- if (c->has_address) {
- void * buf = tmp_alloc(c->size);
- if (context_read_mem(c->update_owner, c->address, buf, c->size) < 0) return -1;
- *value = buf;
- *size = c->size;
- *big_endian = (c->flags & SYM_FLAG_BIG_ENDIAN) != 0;
- return 0;
- }
- set_errno(ERR_OTHER, "Symbol location is unknown");
- return -1;
- }
- if (c->sym_class == SYM_CLASS_VALUE) {
- *value = c->value;
- *size = c->value_size;
- *big_endian = c->big_endian;
- return 0;
- }
- set_errno(ERR_OTHER, "Invalid symbol class");
- return -1;
-}
-
-int get_symbol_address(const Symbol * sym, ContextAddress * address) {
- SymInfoCache * c = get_sym_info_cache(sym);
- if (c == NULL) return -1;
- if (!c->has_address) {
- errno = ERR_INV_ADDRESS;
- return -1;
- }
- *address = c->address;
- return 0;
-}
-
-int get_symbol_register(const Symbol * sym, Context ** ctx, int * frame, RegisterDefinition ** reg) {
- SymInfoCache * c = get_sym_info_cache(sym);
- if (c == NULL) return -1;
- if (c->register_id == NULL) {
- errno = ERR_INV_CONTEXT;
- return -1;
- }
- return id2register(c->register_id, ctx, frame, reg);
-}
-
int get_symbol_flags(const Symbol * sym, SYM_FLAGS * flags) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
*flags = c->flags;
return 0;
}
int get_symbol_frame(const Symbol * sym, Context ** ctx, int * frame) {
- SymInfoCache * c = get_sym_info_cache(sym);
+ SymInfoCache * c = get_sym_info_cache(sym, ACC_OTHER);
if (c == NULL) return -1;
*ctx = c->update_owner;
*frame = c->frame;
@@ -1091,7 +1049,7 @@ static void validate_children(Channel * c, void * args, int error) {
int get_symbol_children(const Symbol * sym, Symbol *** children, int * count) {
Trap trap;
- SymInfoCache * s = get_sym_info_cache(sym);
+ SymInfoCache * s = get_sym_info_cache(sym, ACC_OTHER);
*children = NULL;
*count = 0;
if (s == NULL) return -1;
@@ -1152,7 +1110,7 @@ int get_array_symbol(const Symbol * sym, ContextAddress length, Symbol ** ptr) {
LINK * l;
Trap trap;
ArraySymCache * a = NULL;
- SymInfoCache * s = get_sym_info_cache(sym);
+ SymInfoCache * s = get_sym_info_cache(sym, ACC_OTHER);
if (s == NULL) return -1;
if (!set_trap(&trap)) return -1;
for (l = s->array_syms.next; l != &s->array_syms; l = l->next) {
@@ -1290,10 +1248,8 @@ static void read_location_attrs(InputStream * inp, const char * name, void * x)
if (strcmp(name, "ArgCnt") == 0) f->info.args_cnt = (unsigned)json_read_ulong(inp);
else if (strcmp(name, "CodeAddr") == 0) f->info.code_addr = (ContextAddress)json_read_uint64(inp);
else if (strcmp(name, "CodeSize") == 0) f->info.code_size = (ContextAddress)json_read_uint64(inp);
+ else if (strcmp(name, "BigEndian") == 0) f->info.big_endian = json_read_boolean(inp);
else if (strcmp(name, "ValueCmds") == 0) read_location_command_array(inp, &f->info.value_cmds);
- else if (strcmp(name, "LengthCmds") == 0) read_location_command_array(inp, &f->info.length_cmds);
- else if (strcmp(name, "LengthSize") == 0) f->info.length_size = (ContextAddress)json_read_uint64(inp);
- else if (strcmp(name, "LengthBits") == 0) f->info.length_bits = (unsigned)json_read_ulong(inp);
else json_skip_object(inp);
}
@@ -1333,7 +1289,7 @@ int get_location_info(const Symbol * sym, LocationInfo ** loc) {
Context * prs = NULL;
uint64_t ip = 0;
- sym_cache = get_sym_info_cache(sym);
+ sym_cache = get_sym_info_cache(sym, ACC_OTHER);
if (sym_cache == NULL) return -1;
/* Here we assume that symbol location info is valid for all threads in same memory space */
@@ -1373,6 +1329,19 @@ int get_location_info(const Symbol * sym, LocationInfo ** loc) {
context_lock(f->ctx = prs);
f->ip = ip;
f->sym_id = loc_strdup(sym_cache->id);
+#if ENABLE_RCBP_TEST
+ if (strncmp(f->sym_id, "@T.", 3) == 0) {
+ int sym_class = 0;
+ uint64_t address = 0;
+ char ctx_id[256];
+ if (sscanf(f->sym_id, "@T.%X.%"SCNx64".%255s", &sym_class, &address, ctx_id) == 3) {
+ location_cmds.cnt = 0;
+ f->info.value_cmds.cmds = (LocationExpressionCommand *)loc_alloc(location_cmds.cnt * sizeof(LocationExpressionCommand));
+ memcpy(f->info.value_cmds.cmds, location_cmds.cmds, location_cmds.cnt * sizeof(LocationExpressionCommand));
+ f->info.value_cmds.cnt = f->info.value_cmds.max = location_cmds.cnt;
+ }
+ }
+#endif
f->pending = protocol_send_command(c, SYMBOLS, "getLocationInfo", validate_location_info, f);
json_write_string(&c->out, f->sym_id);
write_stream(&c->out, 0);
@@ -1589,11 +1558,16 @@ static void flush_syms(Context * ctx, int mode) {
if (!c->done_context || c->error_get_context != NULL) {
free_sym_info_cache(c);
}
- else if (c->update_policy == 0 || c->update_owner == NULL || c->update_owner->exited) {
+ else if (c->update_owner == NULL || c->update_owner->exited) {
free_sym_info_cache(c);
}
else if ((mode & (1 << c->update_policy)) && ctx == c->update_owner) {
- free_sym_info_cache(c);
+ if (mode == (1 << UPDATE_ON_EXE_STATE_CHANGES)) {
+ c->degraded = 1;
+ }
+ else {
+ free_sym_info_cache(c);
+ }
}
}
l = syms->link_find_by_name[i].next;
diff --git a/agent/tcf/services/symbols_win32.c b/agent/tcf/services/symbols_win32.c
index 9ea27441..5efa7da3 100644
--- a/agent/tcf/services/symbols_win32.c
+++ b/agent/tcf/services/symbols_win32.c
@@ -709,59 +709,6 @@ int get_symbol_children(const Symbol * sym, Symbol *** children, int * count) {
return 0;
}
-int get_symbol_value(const Symbol * sym, void ** value, size_t * size, int * big_endian) {
- static VARIANT data;
- VARTYPE vt;
- void * data_addr = &data.bVal;
- size_t data_size = 0;
-
- assert(sym->magic == SYMBOL_MAGIC);
- if (sym->base || sym->info) {
- errno = ERR_INV_CONTEXT;
- return -1;
- }
- assert(data_addr == &data.lVal);
- if (get_type_info(sym, TI_GET_VALUE, &data) < 0) return -1;
-
- vt = data.vt;
- if (vt & VT_BYREF) {
- data_addr = *(void **)data_addr;
- vt &= ~VT_BYREF;
- }
-
- switch (vt) {
- /* VOID */ case 0: break;
- /* CHAR */ case VT_I1: data_size = 1; break;
- /* SHORT */ case VT_I2: data_size = 2; break;
- /* LONG */ case VT_I4: data_size = 4; break;
- /* LONGLONG */ case VT_I8: data_size = 8; break;
- /* INT */ case VT_INT: data_size = sizeof(int); break;
- /* BYTE */ case VT_UI1: data_size = 1; break;
- /* USHORT */ case VT_UI2: data_size = 2; break;
- /* ULONG */ case VT_UI4: data_size = 4; break;
- /* ULONGLONG */ case VT_UI8: data_size = 8; break;
- /* UINT */ case VT_UINT: data_size = sizeof(unsigned int); break;
- /* FLOAT */ case VT_R4: data_size = 4; break;
- /* DOUBLE */ case VT_R8: data_size = 8; break;
- /* VARIANT_BOOL */ case VT_BOOL: data_size = sizeof(BOOL); break;
- /* SCODE */ case VT_ERROR: data_size = sizeof(ERROR); break;
- /* CY */ case VT_CY: data_size = sizeof(CY); break;
- /* DATE */ case VT_DATE: data_size = sizeof(DATE); break;
- /* BSTR */ case VT_BSTR: data_size = sizeof(BSTR); break;
- /* IUnknown * */ case VT_UNKNOWN: data_size = sizeof(IUnknown *); break;
- /* IDispatch * */ case VT_DISPATCH: data_size = sizeof(IDispatch *); break;
- /* SAFEARRAY * */ case VT_ARRAY: data_size = sizeof(SAFEARRAY *); break;
- /* VARIANT */ case VT_VARIANT: data_size = sizeof(VARIANT); break;
- /* DECIMAL */ case VT_DECIMAL: data_size = sizeof(DECIMAL); break;
- }
-
- *size = data_size;
- *value = data_addr;
- *big_endian = 0;
-
- return 0;
-}
-
static RegisterDefinition * find_register(Context * ctx, const char * name) {
RegisterDefinition * defs = get_reg_definitions(ctx);
if (defs == NULL) return NULL;
@@ -1117,6 +1064,7 @@ static LocationExpressionCommand * add_location_command(int op) {
int get_location_info(const Symbol * sym, LocationInfo ** loc) {
DWORD dword = 0;
+ static VARIANT data;
SYMBOL_INFO * info = NULL;
assert(sym->magic == SYMBOL_MAGIC);
@@ -1178,6 +1126,53 @@ int get_location_info(const Symbol * sym, LocationInfo ** loc) {
return 0;
}
+ if (get_type_info(sym, TI_GET_VALUE, &data) == 0) {
+ VARTYPE vt;
+ void * data_addr = &data.bVal;
+ size_t data_size = 0;
+ LocationExpressionCommand * cmd = NULL;
+
+ assert(data_addr == &data.lVal);
+
+ vt = data.vt;
+ if (vt & VT_BYREF) {
+ data_addr = *(void **)data_addr;
+ vt &= ~VT_BYREF;
+ }
+
+ switch (vt) {
+ /* VOID */ case 0: break;
+ /* CHAR */ case VT_I1: data_size = 1; break;
+ /* SHORT */ case VT_I2: data_size = 2; break;
+ /* LONG */ case VT_I4: data_size = 4; break;
+ /* LONGLONG */ case VT_I8: data_size = 8; break;
+ /* INT */ case VT_INT: data_size = sizeof(int); break;
+ /* BYTE */ case VT_UI1: data_size = 1; break;
+ /* USHORT */ case VT_UI2: data_size = 2; break;
+ /* ULONG */ case VT_UI4: data_size = 4; break;
+ /* ULONGLONG */ case VT_UI8: data_size = 8; break;
+ /* UINT */ case VT_UINT: data_size = sizeof(unsigned int); break;
+ /* FLOAT */ case VT_R4: data_size = 4; break;
+ /* DOUBLE */ case VT_R8: data_size = 8; break;
+ /* VARIANT_BOOL */ case VT_BOOL: data_size = sizeof(BOOL); break;
+ /* SCODE */ case VT_ERROR: data_size = sizeof(ERROR); break;
+ /* CY */ case VT_CY: data_size = sizeof(CY); break;
+ /* DATE */ case VT_DATE: data_size = sizeof(DATE); break;
+ /* BSTR */ case VT_BSTR: data_size = sizeof(BSTR); break;
+ /* IUnknown * */ case VT_UNKNOWN: data_size = sizeof(IUnknown *); break;
+ /* IDispatch * */ case VT_DISPATCH: data_size = sizeof(IDispatch *); break;
+ /* SAFEARRAY * */ case VT_ARRAY: data_size = sizeof(SAFEARRAY *); break;
+ /* VARIANT */ case VT_VARIANT: data_size = sizeof(VARIANT); break;
+ /* DECIMAL */ case VT_DECIMAL: data_size = sizeof(DECIMAL); break;
+ }
+
+ cmd = add_location_command(SFT_CMD_PIECE);
+ cmd->args.piece.bit_size = data_size * 8;
+ cmd->args.piece.value = tmp_alloc(data_size);
+ memcpy(cmd->args.piece.value, data_addr, data_size);
+ return 0;
+ }
+
add_location_command(SFT_CMD_NUMBER)->args.num = info->Address;
return 0;
}
diff --git a/server/server.vcproj b/server/server.vcproj
index 7c2ccd82..a02b098b 100644
--- a/server/server.vcproj
+++ b/server/server.vcproj
@@ -495,6 +495,10 @@
>
</File>
<File
+ RelativePath="..\agent\tcf\services\symbols_common.c"
+ >
+ </File>
+ <File
RelativePath="..\agent\tcf\services\symbols_elf.c"
>
</File>
diff --git a/tests/test-dwarf/dwarf-test.vcproj b/tests/test-dwarf/dwarf-test.vcproj
index 69d51e24..e1426b4f 100644
--- a/tests/test-dwarf/dwarf-test.vcproj
+++ b/tests/test-dwarf/dwarf-test.vcproj
@@ -638,6 +638,10 @@
>
</File>
<File
+ RelativePath="..\..\agent\tcf\services\symbols_common.c"
+ >
+ </File>
+ <File
RelativePath="..\..\agent\tcf\services\symbols_elf.c"
>
</File>
diff --git a/tests/test-dwarf/tcf/backend/backend.c b/tests/test-dwarf/tcf/backend/backend.c
index cf3df0eb..815cab47 100644
--- a/tests/test-dwarf/tcf/backend/backend.c
+++ b/tests/test-dwarf/tcf/backend/backend.c
@@ -350,6 +350,148 @@ static int errcmp(int err, const char * msg) {
}
static void test(void * args);
+static void loc_var_func(void * args, Symbol * sym);
+
+static void test_enumeration_type(Symbol * type) {
+ int i;
+ int count = 0;
+ Symbol ** children = NULL;
+ Symbol * enum_type = type;
+ ContextAddress enum_type_size = 0;
+ for (i = 0;; i++) {
+ SYM_FLAGS enum_flags = 0;
+ if (get_symbol_flags(enum_type, &enum_flags) < 0) {
+ error_sym("get_symbol_flags", enum_type);
+ }
+ if ((enum_flags & SYM_FLAG_ENUM_TYPE) != 0) break;
+ if (get_symbol_type(enum_type, &enum_type) < 0) {
+ error_sym("get_symbol_type", enum_type);
+ }
+ if (i >= 1000) {
+ errno = ERR_OTHER;
+ error("Invalid original type for enumeration type class");
+ }
+ }
+ if (get_symbol_size(enum_type, &enum_type_size) < 0) {
+ error_sym("get_symbol_size", enum_type);
+ }
+ if (get_symbol_children(type, &children, &count) < 0) {
+ error_sym("get_symbol_children", type);
+ }
+ for (i = 0; i < count; i++) {
+ Symbol * child_type = NULL;
+ void * value = NULL;
+ size_t value_size = 0;
+ int big_endian = 0;
+ ContextAddress child_size = 0;
+ if (get_symbol_value(children[i], &value, &value_size, &big_endian) < 0) {
+ error_sym("get_symbol_value", children[i]);
+ }
+ if (get_symbol_type(children[i], &child_type) < 0) {
+ error_sym("get_symbol_type", children[i]);
+ }
+ if (symcmp(enum_type, child_type) != 0) {
+ errno = ERR_OTHER;
+ error("Invalid type of enum element");
+ }
+ if (get_symbol_size(children[i], &child_size) < 0) {
+ error_sym("get_symbol_size", children[i]);
+ }
+ if (enum_type_size != child_size) {
+ errno = ERR_OTHER;
+ error("Invalid size of enumeration constant");
+ }
+ if (value_size != child_size) {
+ errno = ERR_OTHER;
+ error("Invalid size of enumeration constant");
+ }
+ }
+}
+
+static void test_composite_type(Symbol * type) {
+ int i;
+ int count = 0;
+ Symbol ** children = NULL;
+ if (get_symbol_children(type, &children, &count) < 0) {
+ error_sym("get_symbol_children", type);
+ }
+ for (i = 0; i < count; i++) {
+ int member_class = 0;
+ ContextAddress offs = 0;
+ if (get_symbol_class(children[i], &member_class) < 0) {
+ error_sym("get_symbol_class", children[i]);
+ }
+ if (member_class == SYM_CLASS_REFERENCE) {
+ if (get_symbol_address(children[i], &offs) < 0) {
+ if (get_symbol_offset(children[i], &offs) < 0) {
+#if 0
+ int ok = 0;
+ int err = errno;
+ unsigned type_flags;
+ if (get_symbol_flags(children[i], &type_flags) < 0) {
+ error("get_symbol_flags");
+ }
+ if (type_flags & SYM_FLAG_EXTERNAL) ok = 1;
+ if (!ok) {
+ errno = err;
+ error("get_symbol_offset");
+ }
+#endif
+ }
+ else {
+ Value v;
+ uint64_t n = 0;
+ char * expr = (char *)tmp_alloc(512);
+ sprintf(expr, "&(((${%s} *)0)->${%s})", tmp_strdup(symbol2id(type)), tmp_strdup(symbol2id(children[i])));
+ if (evaluate_expression(elf_ctx, STACK_NO_FRAME, 0, expr, 0, &v) < 0) {
+ error("evaluate_expression");
+ }
+ if (value_to_unsigned(&v, &n) < 0) {
+ error("value_to_unsigned");
+ }
+ if (n != offs) {
+ errno = ERR_OTHER;
+ error("invalid result of evaluate_expression");
+ }
+ }
+ }
+ }
+ else if (member_class == SYM_CLASS_VALUE) {
+ void * value = NULL;
+ size_t value_size = 0;
+ int big_endian = 0;
+ if (get_symbol_value(children[i], &value, &value_size, &big_endian) < 0) {
+ error_sym("get_symbol_value", children[i]);
+ }
+ }
+ }
+}
+
+static void test_this_pointer(Symbol * base_type) {
+ int i;
+ int count = 0;
+ Symbol ** children = NULL;
+ if (get_symbol_children(base_type, &children, &count) < 0) {
+ error_sym("get_symbol_children", base_type);
+ }
+ for (i = 0; i < count; i++) {
+ int member_class = 0;
+ char * member_name = NULL;
+ if (get_symbol_class(children[i], &member_class) < 0) {
+ error_sym("get_symbol_class", children[i]);
+ }
+ if (get_symbol_name(children[i], &member_name) < 0) {
+ error_sym("get_symbol_name", children[i]);
+ }
+ if (member_name != NULL) {
+ Symbol * impl_this = NULL;
+ if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, pc, member_name, &impl_this) < 0) {
+ error_sym("find_symbol_by_name", children[i]);
+ }
+ loc_var_func(NULL, impl_this);
+ }
+ }
+}
static void loc_var_func(void * args, Symbol * sym) {
int frame = 0;
@@ -455,19 +597,18 @@ static void loc_var_func(void * args, Symbol * sym) {
}
}
}
- if (get_symbol_address(sym, &addr) < 0) {
- if ((get_symbol_register(sym, &ctx, &frame, &reg) < 0 || reg == NULL) &&
+ if (get_symbol_address(sym, &addr) < 0 &&
+ (get_symbol_register(sym, &ctx, &frame, &reg) < 0 || reg == NULL) &&
(get_symbol_value(sym, &value, &value_size, &value_big_endian) < 0 || value == NULL)) {
- int err = errno;
- if (errcmp(err, "No object location or value info found") == 0) return;
- if (errcmp(err, "No object location info found") == 0) return;
- if (errcmp(err, "Object is not available at this location") == 0) return;
- if (errcmp(err, "Division by zero in location") == 0) return;
- if (errcmp(err, "Cannot find loader debug") == 0) return;
- if (errcmp(err, "Cannot get TLS module ID") == 0) return;
- errno = err;
- error_sym("get_symbol_value", sym);
- }
+ int err = errno;
+ if (errcmp(err, "No object location or value info found") == 0) return;
+ if (errcmp(err, "No object location info found") == 0) return;
+ if (errcmp(err, "Object is not available at this location") == 0) return;
+ if (errcmp(err, "Division by zero in location") == 0) return;
+ if (errcmp(err, "Cannot find loader debug") == 0) return;
+ if (errcmp(err, "Cannot get TLS module ID") == 0) return;
+ errno = err;
+ error_sym("get_symbol_value", sym);
}
else if (get_location_info(sym, &loc_info) < 0) {
error_sym("get_location_info", sym);
@@ -482,25 +623,16 @@ static void loc_var_func(void * args, Symbol * sym) {
if (set_trap(&trap)) {
LocationExpressionState * state = evaluate_location_expression(elf_ctx, frame_info,
loc_info->value_cmds.cmds, loc_info->value_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);
+ if (state->stk_pos == 1) {
+ 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 (loc_info->length_cmds.cnt > 0) {
- if (set_trap(&trap)) {
- evaluate_location_expression(elf_ctx, frame_info,
- loc_info->length_cmds.cmds, loc_info->length_cmds.cnt, NULL, 0);
- clear_trap(&trap);
- }
- else {
- error("evaluate_location_expression");
- }
- }
}
if (get_symbol_class(sym, &symbol_class) < 0) {
error_sym("get_symbol_class", sym);
@@ -538,6 +670,7 @@ static void loc_var_func(void * args, Symbol * sym) {
Symbol * org_type = NULL;
Symbol * container = NULL;
int container_class = 0;
+ int base_type_class = 0;
if (get_symbol_class(type, &type_sym_class) < 0) {
error_sym("get_symbol_class", type);
}
@@ -621,14 +754,19 @@ static void loc_var_func(void * args, Symbol * sym) {
error_sym("get_symbol_base_type", type);
}
}
- else if (org_type != NULL) {
- Symbol * org_base_type = NULL;
- if (get_symbol_base_type(org_type, &org_base_type) < 0) {
- error_sym("get_symbol_base_type", org_type);
+ else {
+ if (get_symbol_type_class(base_type, &base_type_class) < 0) {
+ error_sym("get_symbol_type_class", base_type);
}
- if (symcmp(base_type, org_base_type) != 0) {
- errno = ERR_OTHER;
- error("Invalid base type of typedef");
+ if (org_type != NULL) {
+ Symbol * org_base_type = NULL;
+ if (get_symbol_base_type(org_type, &org_base_type) < 0) {
+ error_sym("get_symbol_base_type", org_type);
+ }
+ if (symcmp(base_type, org_base_type) != 0) {
+ errno = ERR_OTHER;
+ error("Invalid base type of typedef");
+ }
}
}
if (get_symbol_container(type, &container) < 0) {
@@ -715,111 +853,33 @@ static void loc_var_func(void * args, Symbol * sym) {
error("Invalid length of typedef");
}
}
- if (type_class == TYPE_CLASS_ARRAY) {
- if (get_symbol_lower_bound(type, &lower_bound) < 0) {
+ if (get_symbol_lower_bound(type, &lower_bound) < 0) {
+ if (type_class == TYPE_CLASS_ARRAY) {
error_sym("get_symbol_lower_bound", type);
}
}
- else if (type_class == TYPE_CLASS_ENUMERATION) {
- int i;
- int count = 0;
- Symbol ** children = NULL;
- Symbol * enum_type = type;
- for (i = 0;; i++) {
- SYM_FLAGS enum_flags = 0;
- if (get_symbol_flags(enum_type, &enum_flags) < 0) {
- error_sym("get_symbol_flags", enum_type);
- }
- if ((enum_flags & SYM_FLAG_ENUM_TYPE) != 0) break;
- if (get_symbol_type(enum_type, &enum_type) < 0) {
- error_sym("get_symbol_type", enum_type);
- }
- if (i >= 1000) {
- errno = ERR_OTHER;
- error("Invalid original type for enumeration type class");
- }
- }
- if (get_symbol_children(type, &children, &count) < 0) {
- error_sym("get_symbol_children", type);
+ else if (org_type != NULL) {
+ ContextAddress org_lower_bound = 0;
+ if (get_symbol_lower_bound(org_type, &org_lower_bound) < 0) {
+ error_sym("get_symbol_lower_bound", org_type);
}
- for (i = 0; i < count; i++) {
- Symbol * child_type = NULL;
- void * value = NULL;
- size_t value_size = 0;
- int big_endian = 0;
- if (get_symbol_value(children[i], &value, &value_size, &big_endian) < 0) {
- error_sym("get_symbol_value", children[i]);
- }
- if (get_symbol_type(children[i], &child_type) < 0) {
- error_sym("get_symbol_type", children[i]);
- }
- if (symcmp(enum_type, child_type) != 0) {
- errno = ERR_OTHER;
- error("Invalid type of enum element");
- }
+ if (lower_bound != org_lower_bound) {
+ errno = ERR_OTHER;
+ error("Invalid lower bound of typedef");
}
}
+ if (type_class == TYPE_CLASS_ENUMERATION) {
+ test_enumeration_type(type);
+ }
else if (type_class == TYPE_CLASS_COMPOSITE) {
- int i;
- int count = 0;
- Symbol ** children = NULL;
- if (get_symbol_children(type, &children, &count) < 0) {
- error_sym("get_symbol_children", type);
- }
- if (children != NULL) {
- Symbol ** buf = (Symbol **)tmp_alloc(sizeof(Symbol *) * count);
- memcpy(buf, children, sizeof(Symbol *) * count);
- children = buf;
- }
- for (i = 0; i < count; i++) {
- int member_class = 0;
- ContextAddress offs = 0;
- if (get_symbol_class(children[i], &member_class) < 0) {
- error_sym("get_symbol_class", children[i]);
- }
- if (member_class == SYM_CLASS_REFERENCE) {
- if (get_symbol_address(children[i], &offs) < 0) {
- if (get_symbol_offset(children[i], &offs) < 0) {
-#if 0
- int ok = 0;
- int err = errno;
- unsigned type_flags;
- if (get_symbol_flags(children[i], &type_flags) < 0) {
- error("get_symbol_flags");
- }
- if (type_flags & SYM_FLAG_EXTERNAL) ok = 1;
- if (!ok) {
- errno = err;
- error("get_symbol_offset");
- }
-#endif
- }
- else {
- Value v;
- uint64_t n = 0;
- char * expr = (char *)tmp_alloc(512);
- sprintf(expr, "&(((${%s} *)0)->${%s})", tmp_strdup(symbol2id(type)), tmp_strdup(symbol2id(children[i])));
- if (evaluate_expression(elf_ctx, STACK_NO_FRAME, 0, expr, 0, &v) < 0) {
- error("evaluate_expression");
- }
- if (value_to_unsigned(&v, &n) < 0) {
- error("value_to_unsigned");
- }
- if (n != offs) {
- errno = ERR_OTHER;
- error("invalid result of evaluate_expression");
- }
- }
- }
- }
- else if (member_class == SYM_CLASS_VALUE) {
- void * value = NULL;
- size_t value_size = 0;
- int big_endian = 0;
- if (get_symbol_value(children[i], &value, &value_size, &big_endian) < 0) {
- error_sym("get_symbol_value", children[i]);
- }
- }
+ test_composite_type(type);
+ }
+ else if (type_class == TYPE_CLASS_POINTER) {
+ if (base_type_class == TYPE_CLASS_COMPOSITE &&
+ (flags & SYM_FLAG_PARAMETER) && (flags & SYM_FLAG_ARTIFICIAL) &&
+ name != NULL && strcmp(name, "this") == 0) {
+ test_composite_type(base_type);
+ test_this_pointer(base_type);
}
}
}
@@ -880,27 +940,49 @@ static void next_pc(void) {
}
}
else {
- char * name = NULL;
- ContextAddress addr = 0;
- ContextAddress size = 0;
+ int i;
+ char * func_name = NULL;
+ ContextAddress func_addr = 0;
+ ContextAddress func_size = 0;
+ Symbol * func_type = NULL;
+ int func_children_count = 0;
+ Symbol ** func_children = NULL;
func_object = get_symbol_object(sym);
- if (get_symbol_name(sym, &name) < 0) {
- error("get_symbol_name");
+ if (get_symbol_name(sym, &func_name) < 0) {
+ error_sym("get_symbol_name", sym);
+ }
+ if (func_name != NULL) func_name = tmp_strdup(func_name);
+ if (get_symbol_address(sym, &func_addr) < 0) {
+ error_sym("get_symbol_address", sym);
+ }
+ if (get_symbol_size(sym, &func_size) < 0) {
+ error_sym("get_symbol_size", sym);
}
- if (name != NULL) name = tmp_strdup(name);
- if (get_symbol_address(sym, &addr) < 0) {
- error("get_symbol_address");
+ if (get_symbol_type(sym, &func_type) < 0) {
+ error_sym("get_symbol_type", sym);
}
- if (get_symbol_size(sym, &size) < 0) {
- error("get_symbol_size");
+ if (func_type != NULL) {
+ if (get_symbol_children(func_type, &func_children, &func_children_count) < 0) {
+ error_sym("get_symbol_children", func_type);
+ }
+ for (i = 0; i < func_children_count; i++) {
+ Symbol * arg_type = NULL;
+ ContextAddress arg_size = 0;
+ if (get_symbol_type(func_children[i], &arg_type) < 0) {
+ error_sym("get_symbol_type", func_children[i]);
+ }
+ if (get_symbol_size(func_children[i], &arg_size) < 0) {
+ error_sym("get_symbol_size", func_children[i]);
+ }
+ }
}
- if (pc < addr || pc >= addr + size) {
+ if (pc < func_addr || pc >= func_addr + func_size) {
errno = ERR_OTHER;
error("invalid symbol address");
}
- if (name != NULL) {
+ if (func_name != NULL) {
Symbol * fnd_sym = NULL;
- if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, name, &fnd_sym) < 0) {
+ if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, func_name, &fnd_sym) < 0) {
if (get_error_code(errno) != ERR_SYM_NOT_FOUND) {
error("find_symbol_by_name");
}
@@ -915,23 +997,23 @@ static void next_pc(void) {
errno = ERR_OTHER;
error_sym("invalid symbol name", fnd_sym);
}
- if (strcmp(fnd_name, name) != 0) {
+ if (strcmp(fnd_name, func_name) != 0) {
errno = ERR_OTHER;
error_sym("strcmp(name_buf, name)", fnd_sym);
}
if (get_symbol_address(fnd_sym, &fnd_addr) == 0) {
Value v;
SYM_FLAGS flags = 0;
- char * expr = (char *)tmp_alloc(strlen(name) + 16);
+ char * expr = (char *)tmp_alloc(strlen(func_name) + 16);
if (get_symbol_flags(fnd_sym, &flags) < 0) {
error_sym("get_symbol_flags", fnd_sym);
}
- sprintf(expr, "$\"%s\"", name);
+ sprintf(expr, "$\"%s\"", func_name);
if (evaluate_expression(elf_ctx, STACK_TOP_FRAME, 0, expr, 0, &v) < 0) {
error_sym("evaluate_expression", fnd_sym);
}
if (flags & SYM_FLAG_EXTERNAL) {
- if (find_symbol_by_name(elf_ctx, STACK_NO_FRAME, 0, name, &fnd_sym) < 0) {
+ if (find_symbol_by_name(elf_ctx, STACK_NO_FRAME, 0, func_name, &fnd_sym) < 0) {
error("find_symbol_by_name");
}
}

Back to the top