diff options
author | Eugene Tarassov | 2012-04-25 15:01:05 +0000 |
---|---|---|
committer | Eugene Tarassov | 2012-04-25 15:01:05 +0000 |
commit | 16a9c044ef5f3ff650dc8b29e4c63a3d7cbb96ee (patch) | |
tree | d1b4647d1c90321204934093b6923e8380cfc7ab | |
parent | 69dc4424c5bad8cd4b521e43b5b377aaf9283e43 (diff) | |
download | org.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.vcproj | 4 | ||||
-rw-r--r-- | agent/tcf/services/dwarfcache.c | 1 | ||||
-rw-r--r-- | agent/tcf/services/dwarfecomp.c | 47 | ||||
-rw-r--r-- | agent/tcf/services/dwarfexpr.c | 354 | ||||
-rw-r--r-- | agent/tcf/services/dwarfexpr.h | 3 | ||||
-rw-r--r-- | agent/tcf/services/expressions.c | 26 | ||||
-rw-r--r-- | agent/tcf/services/symbols.c | 137 | ||||
-rw-r--r-- | agent/tcf/services/symbols.h | 4 | ||||
-rw-r--r-- | agent/tcf/services/symbols_common.c | 118 | ||||
-rw-r--r-- | agent/tcf/services/symbols_elf.c | 394 | ||||
-rw-r--r-- | agent/tcf/services/symbols_proxy.c | 208 | ||||
-rw-r--r-- | agent/tcf/services/symbols_win32.c | 101 | ||||
-rw-r--r-- | server/server.vcproj | 4 | ||||
-rw-r--r-- | tests/test-dwarf/dwarf-test.vcproj | 4 | ||||
-rw-r--r-- | tests/test-dwarf/tcf/backend/backend.c | 378 |
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(§ion); - 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, ®) < 0 || reg == NULL) && + if (get_symbol_address(sym, &addr) < 0 && + (get_symbol_register(sym, &ctx, &frame, ®) < 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"); } } |