diff options
author | Eugene Tarassov | 2012-09-27 05:55:04 +0000 |
---|---|---|
committer | Eugene Tarassov | 2012-09-27 05:55:04 +0000 |
commit | 38fa28ad6eef80effde72fcac433a546ab80097d (patch) | |
tree | bc4e606fbc397b1b8d27ddff81cdae36f143487d | |
parent | a45c62f3ae93762008d6e17d2985935643876b9e (diff) | |
download | org.eclipse.tcf.agent-38fa28ad6eef80effde72fcac433a546ab80097d.tar.gz org.eclipse.tcf.agent-38fa28ad6eef80effde72fcac433a546ab80097d.tar.xz org.eclipse.tcf.agent-38fa28ad6eef80effde72fcac433a546ab80097d.zip |
Bug 390309 - Unable to set function breakpoint on a fully qualified C++ name
-rw-r--r-- | agent/tcf/services/dwarfcache.c | 8 | ||||
-rw-r--r-- | agent/tcf/services/dwarfcache.h | 1 | ||||
-rw-r--r-- | agent/tcf/services/expressions.c | 14 | ||||
-rw-r--r-- | agent/tcf/services/symbols_elf.c | 207 |
4 files changed, 161 insertions, 69 deletions
diff --git a/agent/tcf/services/dwarfcache.c b/agent/tcf/services/dwarfcache.c index 8cfd6aba..7a2d29f0 100644 --- a/agent/tcf/services/dwarfcache.c +++ b/agent/tcf/services/dwarfcache.c @@ -614,6 +614,7 @@ static void read_object_info(U2_T Tag, U2_T Attr, U2_T Form) { case AT_low_pc: dio_ChkAddr(Form); Info->u.mCode.mLowPC = (ContextAddress)dio_gFormData; + Info->mFlags |= DOIF_low_pc; break; case AT_high_pc: dio_ChkAddr(Form); @@ -745,10 +746,15 @@ static void read_object_refs(void) { assert(ref.org->mTag != 0); if (ref.org->mFlags & DOIF_load_mark) str_fmt_exception(ERR_INV_DWARF, "Invalid forward reference at %x", (unsigned)ref.obj->mID); - if (ref.obj->mFlags & DOIF_specification) ref.org->mDefinition = ref.obj; if (ref.obj->mName == NULL) ref.obj->mName = ref.org->mName; if (ref.obj->mType == NULL) ref.obj->mType = ref.org->mType; ref.obj->mFlags |= ref.org->mFlags & ~(DOIF_children_loaded | DOIF_declaration | DOIF_specification); + if (ref.obj->mFlags & DOIF_specification) { + ref.org->mDefinition = ref.obj; + if ((ref.obj->mFlags & (DOIF_low_pc | DOIF_ranges)) == 0) { + ref.obj->mFlags |= ref.org->mFlags & DOIF_declaration; + } + } if (ref.obj->mFlags & DOIF_external) { ObjectInfo * cls = ref.org; while (cls->mParent != NULL && diff --git a/agent/tcf/services/dwarfcache.h b/agent/tcf/services/dwarfcache.h index 33739015..1f913b60 100644 --- a/agent/tcf/services/dwarfcache.h +++ b/agent/tcf/services/dwarfcache.h @@ -80,6 +80,7 @@ struct FileInfo { #define DOIF_find_mark 0x1000 #define DOIF_load_mark 0x2000 #define DOIF_pub_mark 0x4000 +#define DOIF_low_pc 0x8000 struct ObjectInfo { diff --git a/agent/tcf/services/expressions.c b/agent/tcf/services/expressions.c index 1ff0b921..dbfa3d6b 100644 --- a/agent/tcf/services/expressions.c +++ b/agent/tcf/services/expressions.c @@ -874,7 +874,9 @@ static int identifier(int mode, Value * scope, char * name, SYM_FLAGS flags, Val Symbol * nxt = NULL; while (find_next_symbol(&nxt) == 0) { SYM_FLAGS nxt_flags = (get_all_symbol_flags(nxt) ^ flags) & flag_mask; - if (flag_count(nxt_flags) < flag_count(sym_flags)) sym = nxt; + if (flag_count(nxt_flags) >= flag_count(sym_flags)) continue; + sym_flags = nxt_flags; + sym = nxt; } } return sym2value(mode, sym, v); @@ -901,10 +903,16 @@ static int qualified_name(int mode, Value * scope, SYM_FLAGS flags, Value * v) { memset(v, 0, sizeof(Value)); if (text_sy == SY_NAME) { if (mode != MODE_SKIP) { - sym_class = identifier(mode, scope, (char *)text_val.value, flags, v); + char * name = tmp_strdup((char *)text_val.value); + SYM_FLAGS f = flags; + next_sy(); + if (text_sy == SY_SCOPE) f |= SYM_FLAG_TYPE; + sym_class = identifier(mode, scope, name, f, v); if (sym_class < 0) error(ERR_INV_EXPRESSION, "Undefined identifier '%s'", text_val.value); } - next_sy(); + else { + next_sy(); + } } else if (text_sy == SY_ID) { if (mode != MODE_SKIP) { diff --git a/agent/tcf/services/symbols_elf.c b/agent/tcf/services/symbols_elf.c index 323a0515..cd25a97d 100644 --- a/agent/tcf/services/symbols_elf.c +++ b/agent/tcf/services/symbols_elf.c @@ -493,6 +493,68 @@ static int check_in_range(ObjectInfo * obj, ContextAddress rt_offs, ContextAddre return 0; } +static int cmp_object_profiles(ObjectInfo * x, ObjectInfo * y) { + if (x == y) return 1; + while (x != NULL) { + switch (x->mTag) { + case TAG_typedef: + case TAG_const_type: + case TAG_volatile_type: + x = x->mType; + continue; + } + break; + } + while (y != NULL) { + switch (y->mTag) { + case TAG_typedef: + case TAG_const_type: + case TAG_volatile_type: + y = y->mType; + continue; + } + break; + } + if (x == NULL || y == NULL) return 0; + if (x->mTag != y->mTag) return 0; + switch (x->mTag) { + case TAG_subprogram: + { + ObjectInfo * px = get_dwarf_children(x); + ObjectInfo * py = get_dwarf_children(y); + while (px != NULL && py != NULL) { + if (px->mTag != TAG_formal_parameter) { + px = px->mSibling; + continue; + } + if (py->mTag != TAG_formal_parameter) { + py = py->mSibling; + continue; + } + if (!cmp_object_profiles(px->mType, py->mType)) return 0; + px = px->mSibling; + py = py->mSibling; + } + if (px != NULL || py != NULL) return 0; + } + break; + case TAG_packed_type: + case TAG_const_type: + case TAG_volatile_type: + case TAG_restrict_type: + case TAG_shared_type: + case TAG_pointer_type: + case TAG_mod_pointer: + case TAG_string_type: + case TAG_array_type: + if (!cmp_object_profiles(x->mType, y->mType)) return 0; + break; + } + if (x->mName == y->mName) return 1; + if (x->mName == NULL || y->mName == NULL) return 0; + return strcmp(x->mName, y->mName) == 0; +} + static void add_to_find_symbol_buf(ObjectInfo * obj, Symbol * sym) { Symbol * p = NULL; Symbol * s = find_symbol_list; @@ -516,89 +578,104 @@ static void add_to_find_symbol_buf(ObjectInfo * obj, Symbol * sym) { else find_symbol_list = sym; } +static int pub_name_priority(ObjectInfo * obj) { + int p = 0; + if (obj->mFlags & DOIF_external) p += 2; + if (obj->mFlags & DOIF_declaration) p -= 4; + switch (obj->mTag) { + case TAG_class_type: + case TAG_structure_type: + case TAG_union_type: + case TAG_enumeration_type: + p -= 1; + break; + } + return p; +} + +static int pub_name_comparator(const void * x, const void * y) { + int px = pub_name_priority(*(ObjectInfo **)x); + int py = pub_name_priority(*(ObjectInfo **)y); + if (px > py) return -1; + if (px < py) return +1; + return 0; +} + static void find_by_name_in_pub_names(DWARFCache * cache, const char * name) { PubNamesTable * tbl = &cache->mPubNames; if (tbl->mHash != NULL) { - ObjectInfo * decl = NULL; - ObjectInfo * type = NULL; - ObjectInfo * other = NULL; + static ObjectInfo ** buf = NULL; + static unsigned buf_pos = 0; + static unsigned buf_max = 0; unsigned n = tbl->mHash[calc_symbol_name_hash(name) % tbl->mHashSize]; + buf_pos = 0; while (n != 0) { ObjectInfo * obj = tbl->mNext[n].mObject; - if (obj->mFlags & DOIF_external) { - if (cmp_symbol_names(obj->mName, name) == 0) { - add_to_find_symbol_buf(obj, NULL); - } - } - else if (obj->mFlags & DOIF_declaration) { - if (decl == NULL && cmp_symbol_names(obj->mName, name) == 0) decl = obj; - } - else { - switch (obj->mTag) { - case TAG_class_type: - case TAG_structure_type: - case TAG_union_type: - case TAG_enumeration_type: - if (type == NULL && cmp_symbol_names(obj->mName, name) == 0) type = obj; - break; - default: - if (other == NULL && cmp_symbol_names(obj->mName, name) == 0) other = obj; - break; + if (cmp_symbol_names(obj->mName, name) == 0) { + if (buf_pos >= buf_max) { + buf_max += 0x100; + buf = (ObjectInfo **)loc_realloc(buf, sizeof(ObjectInfo *) * buf_max); } + buf[buf_pos++] = obj; } n = tbl->mNext[n].mNext; } - if (other != NULL) { - add_to_find_symbol_buf(other, NULL); - } - if (type != NULL) { - add_to_find_symbol_buf(type, NULL); - } - if (decl != NULL) { - add_to_find_symbol_buf(decl, NULL); + if (buf_pos > 0) { + unsigned i; + qsort(buf, buf_pos, sizeof(ObjectInfo *), pub_name_comparator); + for (i = 0; i < buf_pos; i++) add_to_find_symbol_buf(buf[i], NULL); } } } /* If 'decl' represents a declaration, replace it with definition - if possible */ static ObjectInfo * find_definition(ObjectInfo * decl) { - int search_pub_names = 1; - if (decl == NULL) return NULL; - if ((decl->mFlags & DOIF_declaration) == 0) return decl; - if (decl->mDefinition != NULL) return decl->mDefinition; - if (decl->mName == NULL) return decl; - switch (decl->mTag) { - case TAG_structure_type: - case TAG_interface_type: - case TAG_union_type: - case TAG_class_type: - search_pub_names = 1; - break; - default: - search_pub_names = (decl->mFlags & DOIF_external) != 0; - break; - } - if (search_pub_names) { - Trap trap; - Symbol * def = NULL; - Symbol * list = find_symbol_list; - if (set_trap(&trap)) { - DWARFCache * cache = get_dwarf_cache(get_dwarf_file(decl->mCompUnit->mFile)); - find_symbol_list = NULL; - find_by_name_in_pub_names(cache, decl->mName); - while (find_symbol_list != NULL) { - Symbol * sym = find_symbol_list; - find_symbol_list = find_symbol_list->next; - if (sym->obj == NULL) continue; - if (sym->obj->mTag != decl->mTag) continue; - if (sym->obj->mFlags & DOIF_declaration) continue; - def = sym; - break; + while (decl != NULL) { + int search_pub_names = 0; + if (decl->mDefinition != NULL) { + decl = decl->mDefinition; + continue; + } + if (decl->mName == NULL) return decl; + if ((decl->mFlags & DOIF_declaration) == 0) return decl; + switch (decl->mTag) { + case TAG_structure_type: + case TAG_interface_type: + case TAG_union_type: + case TAG_class_type: + search_pub_names = 1; + break; + default: + search_pub_names = (decl->mFlags & DOIF_external) != 0; + break; + } + if (search_pub_names) { + Trap trap; + Symbol * def = NULL; + Symbol * list = find_symbol_list; + if (set_trap(&trap)) { + DWARFCache * cache = get_dwarf_cache(get_dwarf_file(decl->mCompUnit->mFile)); + find_symbol_list = NULL; + find_by_name_in_pub_names(cache, decl->mName); + while (find_symbol_list != NULL) { + Symbol * sym = find_symbol_list; + find_symbol_list = find_symbol_list->next; + if (sym->obj == NULL) continue; + if (sym->obj->mTag != decl->mTag) continue; + if (sym->obj->mFlags & DOIF_declaration) continue; + if (!cmp_object_profiles(decl, sym->obj)) continue; + def = sym; + break; + } + clear_trap(&trap); + } + find_symbol_list = list; + if (def != NULL) { + decl = def->obj; + continue; } - clear_trap(&trap); } - find_symbol_list = list; - if (def != NULL) return def->obj; + break; } return decl; } |