1 /* Helper functions to descend DWARF scope trees.
2 Copyright (C) 2005,2006,2007 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
18 or both in parallel, as here.
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
36 enum die_class { ignore, match, match_inline, walk, imported };
39 classify_die (Dwarf_Die *die)
41 switch (INTUSE(dwarf_tag) (die))
43 /* DIEs with addresses we can try to match. */
44 case DW_TAG_compile_unit:
46 case DW_TAG_lexical_block:
47 case DW_TAG_with_stmt:
48 case DW_TAG_catch_block:
49 case DW_TAG_try_block:
50 case DW_TAG_entry_point:
52 case DW_TAG_inlined_subroutine:
54 case DW_TAG_subprogram:
55 /* This might be a concrete out-of-line instance of an inline, in
56 which case it is not guaranteed to be owned by the right scope and
57 we will search for its origin as for DW_TAG_inlined_subroutine. */
58 return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin)
59 ? match_inline : match);
61 /* DIEs without addresses that can own DIEs with addresses. */
62 case DW_TAG_namespace:
63 case DW_TAG_class_type:
64 case DW_TAG_structure_type:
67 /* Special indirection required. */
68 case DW_TAG_imported_unit:
71 /* Other DIEs we have no reason to descend. */
79 __libdw_visit_scopes (depth, root, previsit, postvisit, arg)
81 struct Dwarf_Die_Chain *root;
82 int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
83 int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
86 struct Dwarf_Die_Chain child;
89 if (INTUSE(dwarf_child) (&root->die, &child.die) != 0)
92 inline int recurse (void)
94 return __libdw_visit_scopes (depth + 1, &child,
95 previsit, postvisit, arg);
102 if (previsit != NULL)
104 int result = (*previsit) (depth + 1, &child, arg);
105 if (result != DWARF_CB_OK)
110 switch (classify_die (&child.die))
115 if (INTUSE(dwarf_haschildren) (&child.die))
117 int result = recurse ();
118 if (result != DWARF_CB_OK)
125 /* This imports another compilation unit to appear
126 as part of this one, inside the current scope.
127 Recurse to search the referenced unit, but without
128 recording it as an inner scoping level. */
130 Dwarf_Attribute attr_mem;
131 Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die,
134 if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL)
136 int result = recurse ();
137 if (result != DWARF_CB_OK)
147 if (postvisit != NULL)
149 int result = (*postvisit) (depth + 1, &child, arg);
150 if (result != DWARF_CB_OK)
154 while (INTUSE(dwarf_siblingof) (&child.die, &child.die) == 0);