X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=libdw%2Flibdw_visit_scopes.c;h=487375dcc4a6c03aa2d0617c314a67c809332f60;hb=a286dd013ef8d46edf013efc0908822a59d8ac81;hp=ea0c6b473eb5abb293ed1d849ff5c499054aa8dd;hpb=18a667176dd196f7bc3a9cdf1cbd87d4c7b31c7f;p=platform%2Fupstream%2Felfutils.git diff --git a/libdw/libdw_visit_scopes.c b/libdw/libdw_visit_scopes.c index ea0c6b4..487375d 100644 --- a/libdw/libdw_visit_scopes.c +++ b/libdw/libdw_visit_scopes.c @@ -33,10 +33,9 @@ #include "libdwP.h" #include -enum die_class { ignore, match, match_inline, walk, imported }; -static enum die_class -classify_die (Dwarf_Die *die) +static bool +may_have_scopes (Dwarf_Die *die) { switch (INTUSE(dwarf_tag) (die)) { @@ -48,31 +47,21 @@ classify_die (Dwarf_Die *die) case DW_TAG_catch_block: case DW_TAG_try_block: case DW_TAG_entry_point: - return match; case DW_TAG_inlined_subroutine: - return match_inline; case DW_TAG_subprogram: - /* This might be a concrete out-of-line instance of an inline, in - which case it is not guaranteed to be owned by the right scope and - we will search for its origin as for DW_TAG_inlined_subroutine. */ - return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin) - ? match_inline : match); + return true; /* DIEs without addresses that can own DIEs with addresses. */ case DW_TAG_namespace: case DW_TAG_class_type: case DW_TAG_structure_type: - return walk; - - /* Special indirection required. */ - case DW_TAG_imported_unit: - return imported; + return true; /* Other DIEs we have no reason to descend. */ default: break; } - return ignore; + return false; } int @@ -84,10 +73,11 @@ __libdw_visit_scopes (depth, root, previsit, postvisit, arg) void *arg; { struct Dwarf_Die_Chain child; + int ret; child.parent = root; - if (INTUSE(dwarf_child) (&root->die, &child.die) != 0) - return -1; + if ((ret = INTUSE(dwarf_child) (&root->die, &child.die)) != 0) + return ret < 0 ? -1 : 0; // Having zero children is legal. inline int recurse (void) { @@ -95,63 +85,63 @@ __libdw_visit_scopes (depth, root, previsit, postvisit, arg) previsit, postvisit, arg); } - do - { - child.prune = false; - - if (previsit != NULL) - { - int result = (*previsit) (depth + 1, &child, arg); - if (result != DWARF_CB_OK) - return result; - } - - if (!child.prune) - switch (classify_die (&child.die)) + inline int walk_children () + { + do + { + /* For an imported unit, it is logically as if the children of + that unit are siblings of the other children. So don't do + a full recursion into the imported unit, but just walk the + children in place before moving to the next real child. */ + while (INTUSE(dwarf_tag) (&child.die) == DW_TAG_imported_unit) { - case match: - case match_inline: - case walk: - if (INTUSE(dwarf_haschildren) (&child.die)) + Dwarf_Die orig_child_die = child.die; + Dwarf_Attribute attr_mem; + Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die, + DW_AT_import, + &attr_mem); + if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL + && INTUSE(dwarf_child) (&child.die, &child.die) == 0) { - int result = recurse (); + int result = walk_children (); if (result != DWARF_CB_OK) return result; } - break; - - case imported: - { - /* This imports another compilation unit to appear - as part of this one, inside the current scope. - Recurse to search the referenced unit, but without - recording it as an inner scoping level. */ - - Dwarf_Attribute attr_mem; - Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die, - DW_AT_import, - &attr_mem); - if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL) - { - int result = recurse (); - if (result != DWARF_CB_OK) - return result; - } - } - break; - - default: - break; + + /* Any "real" children left? */ + if ((ret = INTUSE(dwarf_siblingof) (&orig_child_die, + &child.die)) != 0) + return ret < 0 ? -1 : 0; + }; + + child.prune = false; + + if (previsit != NULL) + { + int result = (*previsit) (depth + 1, &child, arg); + if (result != DWARF_CB_OK) + return result; } - if (postvisit != NULL) - { - int result = (*postvisit) (depth + 1, &child, arg); - if (result != DWARF_CB_OK) - return result; - } - } - while (INTUSE(dwarf_siblingof) (&child.die, &child.die) == 0); + if (!child.prune && may_have_scopes (&child.die) + && INTUSE(dwarf_haschildren) (&child.die)) + { + int result = recurse (); + if (result != DWARF_CB_OK) + return result; + } + + if (postvisit != NULL) + { + int result = (*postvisit) (depth + 1, &child, arg); + if (result != DWARF_CB_OK) + return result; + } + } + while ((ret = INTUSE(dwarf_siblingof) (&child.die, &child.die)) == 0); + + return ret < 0 ? -1 : 0; + } - return 0; + return walk_children (); }