diff options
author | Eugene Tarassov | 2014-10-24 20:25:31 +0000 |
---|---|---|
committer | Eugene Tarassov | 2014-10-25 00:13:39 +0000 |
commit | 8e8ce8d10223f7d46ebe72808aac64b0d6c40af3 (patch) | |
tree | ddf071fdfbfc5b80a2ed576af0a8199a56150065 | |
parent | 0fdde513a6b1c36eb7cc64479b3c1817c7664e6e (diff) | |
download | org.eclipse.tcf.agent-8e8ce8d10223f7d46ebe72808aac64b0d6c40af3.tar.gz org.eclipse.tcf.agent-8e8ce8d10223f7d46ebe72808aac64b0d6c40af3.tar.xz org.eclipse.tcf.agent-8e8ce8d10223f7d46ebe72808aac64b0d6c40af3.zip |
TCF Agent: added support for .debug_types section in DWARF 4
-rw-r--r-- | agent/tcf/services/dwarfcache.c | 115 | ||||
-rw-r--r-- | agent/tcf/services/dwarfcache.h | 5 | ||||
-rw-r--r-- | agent/tcf/services/dwarfio.c | 8 | ||||
-rw-r--r-- | agent/tcf/services/dwarfio.h | 4 | ||||
-rw-r--r-- | agent/tcf/services/symbols_elf.c | 9 | ||||
-rw-r--r-- | tests/test-dwarf/tcf/backend/backend.c | 32 |
6 files changed, 158 insertions, 15 deletions
diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c index 3525612d..d5a00903 100644 --- a/agent/tcf/services/dwarfcache.c +++ b/agent/tcf/services/dwarfcache.c @@ -110,6 +110,12 @@ static CompUnit * add_comp_unit(ContextAddress ID) { ObjectInfo * Info = add_object_info(ID); if (Info->mCompUnit == NULL) { CompUnit * Unit = (CompUnit *)loc_alloc_zero(sizeof(CompUnit)); + Unit->mFile = sCache->mFile; + Unit->mRegIdScope.big_endian = sCache->mFile->big_endian; + Unit->mRegIdScope.machine = sCache->mFile->machine; + Unit->mRegIdScope.os_abi = sCache->mFile->os_abi; + Unit->mRegIdScope.elf64 = sCache->mFile->elf64; + Unit->mRegIdScope.id_type = REGNUM_DWARF; Unit->mObject = Info; Info->mCompUnit = Unit; } @@ -143,6 +149,44 @@ static CompUnit * find_comp_unit(ELF_Section * Section, ContextAddress ObjID) { return NULL; } +static void add_type_unit(CompUnit * Unit) { + unsigned Hash = (unsigned)(Unit->mDesc.mTypeSignature % sCache->mTypeUnitHashSize); + assert(Unit->mDesc.mTypeOffset != 0); + Unit->mNextTypeUnit = sCache->mTypeUnitHash[Hash]; + sCache->mTypeUnitHash[Hash] = Unit; +} + +static CompUnit * find_type_unit(U8_T Signature) { + unsigned Hash = (unsigned)(Signature % sCache->mTypeUnitHashSize); + CompUnit * Unit = sCache->mTypeUnitHash[Hash]; + while (Unit != NULL) { + if (Unit->mDesc.mTypeSignature == Signature) return Unit; + Unit = Unit->mNextTypeUnit; + } + return NULL; +} + +static void read_type_unit_header(U2_T Tag, U2_T Attr, U2_T Form) { + if (Attr == 0) { + if (Form) { + assert(sParentObject == NULL); + if (Tag != TAG_type_unit) str_exception(ERR_INV_DWARF, "Invalid .debug_types section"); + sCompUnit = add_comp_unit((ContextAddress)(sDebugSection->addr + dio_gEntryPos)); + } + else { + if (find_type_unit(sUnitDesc.mTypeSignature) != NULL) { + str_exception(ERR_INV_DWARF, "Invalid .debug_types section"); + } + sCompUnit->mDesc = sUnitDesc; + add_type_unit(sCompUnit); + add_object_info((ContextAddress)(sDebugSection->addr + sUnitDesc.mUnitOffs + sUnitDesc.mTypeOffset)); + sCompUnit = NULL; + assert(sUnitDesc.mUnitSize > 0); + dio_SetPos(sUnitDesc.mUnitOffs + sUnitDesc.mUnitSize); + } + } +} + static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form); static void read_object_refs(ELF_Section * Section); @@ -480,16 +524,11 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { switch (Attr) { case 0: if (Form) { + /* Initialization: executed before debug entry processing */ high_pc_offs = 0; - if (Tag == TAG_compile_unit || Tag == TAG_partial_unit) { + if (Tag == TAG_compile_unit || Tag == TAG_partial_unit || Tag == TAG_type_unit) { CompUnit * Unit = add_comp_unit((ContextAddress)(sDebugSection->addr + dio_gEntryPos)); assert(sParentObject == NULL); - Unit->mFile = sCache->mFile; - Unit->mRegIdScope.big_endian = sCache->mFile->big_endian; - Unit->mRegIdScope.machine = sCache->mFile->machine; - Unit->mRegIdScope.os_abi = sCache->mFile->os_abi; - Unit->mRegIdScope.elf64 = sCache->mFile->elf64; - Unit->mRegIdScope.id_type = REGNUM_DWARF; Info = Unit->mObject; assert(Info->mTag == 0); sCompUnit = Unit; @@ -506,6 +545,7 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { assert(Info->mTag == Tag); assert(Tag != TAG_compile_unit); assert(Tag != TAG_partial_unit); + assert(Tag != TAG_type_unit); assert(Info->mCompUnit == sCompUnit); return; } @@ -513,12 +553,14 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { Info->mCompUnit = sCompUnit; } else { + /* Finalization: executed after debug entry processing */ if (high_pc_offs && !(Info->mFlags & DOIF_ranges) && (Info->mFlags & DOIF_low_pc)) { Info->u.mCode.mHighPC.mAddr += Info->u.mCode.mLowPC; } switch (Tag) { case TAG_compile_unit: case TAG_partial_unit: + case TAG_type_unit: { ObjectHashTable * HashTable = sCache->mObjectHashTable + sDebugSection->index; assert(HashTable->mCompUnitsIndex == NULL); @@ -565,6 +607,7 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { else if (sParentObject != NULL) sParentObject->mChildren = Info; else if (Tag == TAG_compile_unit) sCache->mObjectHashTable[sDebugSection->index].mCompUnits = Info; else if (Tag == TAG_partial_unit) sCache->mObjectHashTable[sDebugSection->index].mCompUnits = Info; + else if (Tag == TAG_type_unit) sCache->mObjectHashTable[sDebugSection->index].mCompUnits = Info; sPrevSibling = Info; if (Skip && Sibling != 0) { dio_SetPos(Sibling); @@ -614,6 +657,16 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { Info->mType = find_alt_object_info((ContextAddress)dio_gFormData); break; } + if (Form == FORM_REF_SIG8) { + CompUnit * Unit = find_type_unit(dio_gFormData); + if (Unit != NULL) { + ContextAddress ID = (ContextAddress)(Unit->mDesc.mSection->addr + + Unit->mDesc.mUnitOffs + Unit->mDesc.mTypeOffset); + Info->mType = find_loaded_object(Unit->mDesc.mSection, ID); + } + if (Info->mType == NULL) str_exception(ERR_INV_DWARF, "Invalid type unit reference"); + break; + } dio_ChkRef(Form); Info->mType = add_object_info((ContextAddress)dio_gFormData); add_object_reference(Info->mType, NULL); @@ -753,7 +806,7 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { } break; } - if (Tag == TAG_compile_unit || Tag == TAG_partial_unit) { + if (Tag == TAG_compile_unit || Tag == TAG_partial_unit || Tag == TAG_type_unit) { CompUnit * Unit = Info->mCompUnit; switch (Attr) { case AT_low_pc: @@ -1151,6 +1204,15 @@ static void create_pub_names(unsigned idx) { if ((obj->mFlags & DOIF_pub_mark) == 0 && obj->mDefinition == NULL && obj->mName != NULL) { add_pub_name(tbl, obj); } + if (obj->mTag == TAG_enumeration_type) { + ObjectInfo * n = get_dwarf_children(obj); + while (n != NULL) { + if ((n->mFlags & DOIF_pub_mark) == 0 && n->mName != NULL) { + add_pub_name(tbl, n); + } + n = n->mSibling; + } + } obj = obj->mSibling; } if ((unit->mFlags & DOIF_pub_mark) == 0 && unit->mName != NULL) { @@ -1189,6 +1251,12 @@ static void load_debug_info_section(ELF_Section * sec) { if (set_trap(&trap)) { assert(HashTable->mCompUnitsIndexSize == 0); assert(HashTable->mCompUnitsIndex == NULL); + if (strcmp(sec->name, ".debug_types") == 0) { + while (dio_GetPos() < sec->size) { + dio_ReadUnit(&sUnitDesc, read_type_unit_header); + } + dio_SetPos(0); + } while (dio_GetPos() < sec->size) { dio_ReadUnit(&sUnitDesc, read_object_info); } @@ -1205,7 +1273,7 @@ static void load_debug_info_section(ELF_Section * sec) { ObjectInfo * unit = sCache->mObjectHashTable[sec->index].mCompUnits; HashTable->mCompUnitsIndex = (CompUnit **)loc_alloc(sizeof(CompUnit *) * HashTable->mCompUnitsIndexSize); while (unit != NULL) { - assert(unit->mTag == TAG_compile_unit || unit->mTag == TAG_partial_unit); + assert(unit->mTag == TAG_compile_unit || unit->mTag == TAG_partial_unit || unit->mTag == TAG_type_unit); HashTable->mCompUnitsIndex[i++] = unit->mCompUnit; unit = unit->mSibling; } @@ -1222,6 +1290,33 @@ static void load_debug_sections(void) { FrameInfoIndex * frame_info_d = NULL; FrameInfoIndex * frame_info_e = NULL; ELF_File * file = sCache->mFile; + U8_T debug_types_size = 0; + + for (idx = 1; idx < file->section_cnt; idx++) { + ELF_Section * sec = file->sections + idx; + if (sec->size == 0) continue; + if (sec->name == NULL) continue; + if (sec->type == SHT_NOBITS) continue; + if (strcmp(sec->name, ".debug_types") == 0) { + debug_types_size += sec->size; + } + } + + if (debug_types_size > 0) { + sCache->mTypeUnitHashSize = (unsigned)(debug_types_size / 101); + if (sCache->mTypeUnitHashSize < 239) sCache->mTypeUnitHashSize = 239; + sCache->mTypeUnitHash = (CompUnit **)loc_alloc_zero(sizeof(CompUnit *) * sCache->mTypeUnitHashSize); + } + + for (idx = 1; idx < file->section_cnt; idx++) { + ELF_Section * sec = file->sections + idx; + if (sec->size == 0) continue; + if (sec->name == NULL) continue; + if (sec->type == SHT_NOBITS) continue; + if (strcmp(sec->name, ".debug_types") == 0) { + load_debug_info_section(sec); + } + } for (idx = 1; idx < file->section_cnt; idx++) { ELF_Section * sec = file->sections + idx; @@ -1353,6 +1448,7 @@ ObjectInfo * get_dwarf_parent(ObjectInfo * obj) { if (obj->mParent != NULL) return obj->mParent; if (obj->mTag == TAG_compile_unit) return NULL; if (obj->mTag == TAG_partial_unit) return NULL; + if (obj->mTag == TAG_type_unit) return NULL; x = get_dwarf_children(obj->mCompUnit->mObject); while (x != NULL && x->mID < obj->mID) { if (x->mSibling == NULL || x->mSibling->mID > obj->mID) { @@ -1781,6 +1877,7 @@ static void free_dwarf_cache(ELF_File * file) { loc_free(Cache->mPubNames.mHash); loc_free(Cache->mPubNames.mNext); loc_free(Cache->mFileInfoHash); + loc_free(Cache->mTypeUnitHash); loc_free(Cache); file->dwarf_dt_cache = NULL; } diff --git a/agent/tcf/services/dwarfcache.h b/agent/tcf/services/dwarfcache.h index ea020eab..5ad0e616 100644 --- a/agent/tcf/services/dwarfcache.h +++ b/agent/tcf/services/dwarfcache.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2012 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2014 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. @@ -214,6 +214,7 @@ struct CompUnit { U1_T mLineInfoLoaded; CompUnit * mBaseTypes; + CompUnit * mNextTypeUnit; }; /* Address range of a compilation unit. A unit can occupy multiple address ranges. */ @@ -263,6 +264,8 @@ struct DWARFCache { unsigned mFileInfoHashSize; FileInfo ** mFileInfoHash; int mLineInfoLoaded; + CompUnit ** mTypeUnitHash; + unsigned mTypeUnitHashSize; }; /* Return DWARF cache for given file, create and populate the cache if needed, throw an exception if error */ diff --git a/agent/tcf/services/dwarfio.c b/agent/tcf/services/dwarfio.c index 9e545172..735aeb9a 100644 --- a/agent/tcf/services/dwarfio.c +++ b/agent/tcf/services/dwarfio.c @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2012 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2014 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. @@ -564,7 +564,7 @@ int dio_ReadEntry(DIO_EntryCallBack CallBack, U2_T TargetAttr) { } } if (Attr != 0 && Form != 0) dio_ReadAttribute(Attr, Form); - if (Tag == TAG_compile_unit || Tag == TAG_partial_unit) { + if (Tag == TAG_compile_unit || Tag == TAG_partial_unit || Tag == TAG_type_unit) { if (Attr == AT_sibling && sUnit->mUnitSize == 0) { dio_ChkRef(Form); assert(sUnit->mVersion == 1); @@ -604,6 +604,10 @@ void dio_ReadUnit(DIO_UnitDescriptor * Unit, DIO_EntryCallBack CallBack) { sUnit->mVersion = dio_ReadU2(); sUnit->mAbbrevTableOffs = dio_ReadAddressX(&Sect, sUnit->m64bit ? 8 : 4); sUnit->mAddressSize = dio_ReadU1(); + if (strcmp(sSection->name, ".debug_types") == 0) { + sUnit->mTypeSignature = dio_ReadU8(); + sUnit->mTypeOffset = sUnit->m64bit ? dio_ReadU8() : dio_ReadU4(); + } dio_FindAbbrevTable(); } else { diff --git a/agent/tcf/services/dwarfio.h b/agent/tcf/services/dwarfio.h index a889fc5b..60fd13b5 100644 --- a/agent/tcf/services/dwarfio.h +++ b/agent/tcf/services/dwarfio.h @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2012 Wind River Systems, Inc. and others. + * Copyright (c) 2006, 2014 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. @@ -35,6 +35,8 @@ typedef struct DIO_UnitDescriptor { U8_T mUnitOffs; U8_T mUnitSize; U8_T mAbbrevTableOffs; + U8_T mTypeSignature; + U8_T mTypeOffset; struct DIO_Abbreviation ** mAbbrevTable; U4_T mAbbrevTableSize; } DIO_UnitDescriptor; diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c index 95ab1769..19fa57e1 100644 --- a/agent/tcf/services/symbols_elf.c +++ b/agent/tcf/services/symbols_elf.c @@ -107,6 +107,8 @@ static struct ConstantPseudoSymbol { } constant_pseudo_symbols[] = { { "false", "bool", 0 }, { "true", "bool", 1 }, + { "false", "boolean", 0 }, + { "true", "boolean", 1 }, { NULL }, }; @@ -1283,9 +1285,14 @@ int find_symbol_by_name(Context * ctx, int frame, ContextAddress ip, const char Trap trap; Symbol * type = NULL; Symbol * list = find_symbol_list; + const char * type_name = constant_pseudo_symbols[i].type; if (set_trap(&trap)) { find_symbol_list = NULL; - find_in_dwarf(constant_pseudo_symbols[i].type); + find_in_dwarf(type_name); + if (curr_file != NULL) { + DWARFCache * cache = get_dwarf_cache(get_dwarf_file(curr_file)); + find_by_name_in_pub_names(cache, type_name); + } sort_find_symbol_buf(); type = find_symbol_list; clear_trap(&trap); diff --git a/tests/test-dwarf/tcf/backend/backend.c b/tests/test-dwarf/tcf/backend/backend.c index db0316d9..30b63ef6 100644 --- a/tests/test-dwarf/tcf/backend/backend.c +++ b/tests/test-dwarf/tcf/backend/backend.c @@ -415,6 +415,10 @@ static void test_enumeration_type(Symbol * type) { Symbol ** children = NULL; Symbol * enum_type = type; ContextAddress enum_type_size = 0; + char * type_name = NULL; + Symbol * find_sym = NULL; + int visible = 0; + for (i = 0;; i++) { SYM_FLAGS enum_flags = 0; if (get_symbol_flags(enum_type, &enum_flags) < 0) { @@ -436,12 +440,19 @@ static void test_enumeration_type(Symbol * type) { if (get_symbol_children(type, &children, &count) < 0) { error_sym("get_symbol_children", type); } + if (get_symbol_name(type, &type_name) < 0) { + error_sym("get_symbol_name", type); + } + if (type_name != NULL && find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, type_name, &find_sym) == 0) { + visible = symcmp(type, find_sym) == 0; + } 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; + char * name = NULL; if (get_symbol_value(children[i], &value, &value_size, &big_endian) < 0) { error_sym("get_symbol_value", children[i]); } @@ -463,6 +474,21 @@ static void test_enumeration_type(Symbol * type) { errno = ERR_OTHER; error("Invalid size of enumeration constant"); } + if (get_symbol_name(children[i], &name) < 0) { + error_sym("get_symbol_name", children[i]); + } + if (visible && name != NULL && get_symbol_object(children[i]) != NULL) { + if (find_symbol_by_name(elf_ctx, STACK_TOP_FRAME, 0, name, &find_sym) < 0) { + error_sym("find_symbol_by_name", children[i]); + } +#if 0 + /* TODO: better enum const search */ + if (symcmp(children[i], find_sym) != 0) { + errno = ERR_OTHER; + error_sym("find_symbol_by_name", children[i]); + } +#endif + } } } @@ -1242,6 +1268,7 @@ static void test_public_names(void) { DWARFCache * cache = get_dwarf_cache(get_dwarf_file(elf_file)); unsigned n = 0; unsigned m = 0; + time_t time_start = time(0); while (n < cache->mPubNames.mCnt) { ObjectInfo * obj = cache->mPubNames.mNext[n++].mObject; if (obj != NULL) { @@ -1277,7 +1304,10 @@ static void test_public_names(void) { loc_var_func(NULL, sym1); } } - if ((n % 100) == 0) tmp_gc(); + if ((n % 100) == 0) { + tmp_gc(); + if (time(0) - time_start >= 120) break; + } } for (m = 1; m < elf_file->section_cnt; m++) { ELF_Section * tbl = elf_file->sections + m; |