Branch data Line data Source code
1 : : /* Helper functions to descend DWARF scope trees.
2 : : Copyright (C) 2005,2006,2007 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
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
11 : :
12 : : or
13 : :
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
17 : :
18 : : or both in parallel, as here.
19 : :
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.
24 : :
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/>. */
28 : :
29 : : #ifdef HAVE_CONFIG_H
30 : : # include <config.h>
31 : : #endif
32 : :
33 : : #include "libdwP.h"
34 : : #include <dwarf.h>
35 : :
36 : : enum die_class { ignore, match, match_inline, walk, imported };
37 : :
38 : : static enum die_class
39 : 12 : classify_die (Dwarf_Die *die)
40 : : {
41 [ + + - - : 12 : switch (INTUSE(dwarf_tag) (die))
+ - ]
42 : : {
43 : : /* DIEs with addresses we can try to match. */
44 : : case DW_TAG_compile_unit:
45 : : case DW_TAG_module:
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:
51 : : return match;
52 : : case DW_TAG_inlined_subroutine:
53 : 2 : return match_inline;
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 [ + + ]: 3 : return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin)
59 : : ? match_inline : match);
60 : :
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:
65 : 0 : return walk;
66 : :
67 : : /* Special indirection required. */
68 : : case DW_TAG_imported_unit:
69 : 0 : return imported;
70 : :
71 : : /* Other DIEs we have no reason to descend. */
72 : : default:
73 : : break;
74 : : }
75 : 12 : return ignore;
76 : : }
77 : :
78 : : int
79 : 10 : __libdw_visit_scopes (depth, root, previsit, postvisit, arg)
80 : : unsigned int depth;
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 *);
84 : : void *arg;
85 : : {
86 : : struct Dwarf_Die_Chain child;
87 : :
88 : 10 : child.parent = root;
89 [ + - ]: 10 : if (INTUSE(dwarf_child) (&root->die, &child.die) != 0)
90 : : return -1;
91 : :
92 : 5 : inline int recurse (void)
93 : : {
94 : 5 : return __libdw_visit_scopes (depth + 1, &child,
95 : : previsit, postvisit, arg);
96 : : }
97 : :
98 : : do
99 : : {
100 : 23 : child.prune = false;
101 : :
102 [ + - ]: 23 : if (previsit != NULL)
103 : : {
104 : 23 : int result = (*previsit) (depth + 1, &child, arg);
105 [ + + ]: 23 : if (result != DWARF_CB_OK)
106 : : return result;
107 : : }
108 : :
109 [ + + ]: 21 : if (!child.prune)
110 [ + - + ]: 12 : switch (classify_die (&child.die))
111 : : {
112 : : case match:
113 : : case match_inline:
114 : : case walk:
115 [ + - ]: 5 : if (INTUSE(dwarf_haschildren) (&child.die))
116 : : {
117 : 5 : int result = recurse ();
118 [ + - ]: 5 : if (result != DWARF_CB_OK)
119 : : return result;
120 : : }
121 : : break;
122 : :
123 : : case imported:
124 : : {
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. */
129 : :
130 : : Dwarf_Attribute attr_mem;
131 : 0 : Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die,
132 : : DW_AT_import,
133 : : &attr_mem);
134 [ # # ]: 0 : if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL)
135 : : {
136 : 0 : int result = recurse ();
137 [ # # ]: 0 : if (result != DWARF_CB_OK)
138 : : return result;
139 : : }
140 : : }
141 : 0 : break;
142 : :
143 : : default:
144 : : break;
145 : : }
146 : :
147 [ + + ]: 21 : if (postvisit != NULL)
148 : : {
149 : 12 : int result = (*postvisit) (depth + 1, &child, arg);
150 [ + + ]: 12 : if (result != DWARF_CB_OK)
151 : : return result;
152 : : }
153 : : }
154 [ + + ]: 23 : while (INTUSE(dwarf_siblingof) (&child.die, &child.die) == 0);
155 : :
156 : : return 0;
157 : : }
|