Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEugene Tarassov2014-10-24 20:25:31 +0000
committerEugene Tarassov2014-10-25 00:13:39 +0000
commit8e8ce8d10223f7d46ebe72808aac64b0d6c40af3 (patch)
treeddf071fdfbfc5b80a2ed576af0a8199a56150065
parent0fdde513a6b1c36eb7cc64479b3c1817c7664e6e (diff)
downloadorg.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.c115
-rw-r--r--agent/tcf/services/dwarfcache.h5
-rw-r--r--agent/tcf/services/dwarfio.c8
-rw-r--r--agent/tcf/services/dwarfio.h4
-rw-r--r--agent/tcf/services/symbols_elf.c9
-rw-r--r--tests/test-dwarf/tcf/backend/backend.c32
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;

Back to the top