Branch data Line data Source code
1 : : /* Return child of current DIE.
2 : : Copyright (C) 2003-2011, 2014, 2017 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2003.
5 : :
6 : : This file is free software; you can redistribute it and/or modify
7 : : it under the terms of either
8 : :
9 : : * the GNU Lesser General Public License as published by the Free
10 : : Software Foundation; either version 3 of the License, or (at
11 : : your option) any later version
12 : :
13 : : or
14 : :
15 : : * the GNU General Public License as published by the Free
16 : : Software Foundation; either version 2 of the License, or (at
17 : : your option) any later version
18 : :
19 : : or both in parallel, as here.
20 : :
21 : : elfutils is distributed in the hope that it will be useful, but
22 : : WITHOUT ANY WARRANTY; without even the implied warranty of
23 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 : : General Public License for more details.
25 : :
26 : : You should have received copies of the GNU General Public License and
27 : : the GNU Lesser General Public License along with this program. If
28 : : not, see <http://www.gnu.org/licenses/>. */
29 : :
30 : : #ifdef HAVE_CONFIG_H
31 : : # include <config.h>
32 : : #endif
33 : :
34 : : #include "libdwP.h"
35 : : #include <string.h>
36 : :
37 : : /* Some arbitrary value not conflicting with any existing code. */
38 : : #define INVALID 0xffffe444
39 : :
40 : :
41 : : unsigned char *
42 : : internal_function
43 : 47219862 : __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
44 : : unsigned int *codep, unsigned int *formp)
45 : : {
46 : 47219862 : const unsigned char *readp = NULL;
47 : :
48 : : /* Find the abbreviation entry. */
49 : 47219862 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
50 [ + + ]: 47219862 : if (unlikely (abbrevp == DWARF_END_ABBREV))
51 : : {
52 : 12110 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
53 : 12110 : return NULL;
54 : : }
55 : :
56 : 47207752 : const unsigned char *endp = die->cu->endp;
57 : :
58 : : /* Search the name attribute. Attribute has been checked when
59 : : Dwarf_Abbrev was created, we can read unchecked. */
60 : 47207752 : const unsigned char *attrp = abbrevp->attrp;
61 : 233389666 : while (1)
62 : : {
63 : : /* Get attribute name and form. */
64 : 233389666 : unsigned int attr_name;
65 : 233389666 : get_uleb128_unchecked (attr_name, attrp);
66 : :
67 : 233389666 : unsigned int attr_form;
68 : 233389666 : get_uleb128_unchecked (attr_form, attrp);
69 : :
70 : : /* We can stop if we found the attribute with value zero. */
71 [ + + ]: 233389666 : if (attr_name == 0 && attr_form == 0)
72 : : break;
73 : :
74 [ + + ]: 193926066 : if (attr_form == DW_FORM_indirect)
75 : : {
76 [ - + ]: 34 : if (readp >= endp)
77 : 0 : goto invalid;
78 : 34 : get_uleb128 (attr_form, readp, endp);
79 : 34 : if (attr_form == DW_FORM_indirect ||
80 [ - + ]: 34 : attr_form == DW_FORM_implicit_const)
81 : : {
82 : 0 : invalid:
83 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
84 : 0 : return NULL;
85 : : }
86 : : }
87 : :
88 : : /* Is this the name attribute? */
89 [ + + ]: 193926066 : if (attr_name == search_name && search_name != INVALID)
90 : : {
91 [ + - ]: 7744152 : if (codep != NULL)
92 : 7744152 : *codep = attr_name;
93 [ + - ]: 7744152 : if (formp != NULL)
94 : 7744152 : *formp = attr_form;
95 : :
96 : : /* Normally the attribute data comes from the DIE/info,
97 : : except for implicit_form, where it comes from the abbrev. */
98 [ + + ]: 7744152 : if (attr_form == DW_FORM_implicit_const)
99 : 39592 : return (unsigned char *) attrp;
100 : : else
101 : 7704560 : return (unsigned char *) readp;
102 : : }
103 : :
104 : : /* Skip over the rest of this attribute (if there is any). */
105 [ - + ]: 186181914 : if (attr_form != 0)
106 : : {
107 : 186181914 : size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
108 [ - + ]: 186181914 : if (unlikely (len == (size_t) -1l))
109 : : {
110 : 0 : readp = NULL;
111 : 0 : break;
112 : : }
113 : :
114 : : // __libdw_form_val_len will have done a bounds check.
115 : 186181914 : readp += len;
116 : :
117 : : // If the value is in the abbrev data, skip it.
118 [ + + ]: 186181914 : if (attr_form == DW_FORM_implicit_const)
119 : : {
120 : 11013564 : int64_t attr_value __attribute__((__unused__));
121 : 11013564 : get_sleb128_unchecked (attr_value, attrp);
122 : : }
123 : : }
124 : : }
125 : :
126 : : // XXX Do we need other values?
127 [ + + ]: 39463600 : if (codep != NULL)
128 : 35655596 : *codep = INVALID;
129 [ + + ]: 39463600 : if (formp != NULL)
130 : 35655596 : *formp = INVALID;
131 : :
132 : 39463600 : return (unsigned char *) readp;
133 : : }
134 : :
135 : :
136 : : int
137 : 6851920 : dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
138 : : {
139 : : /* Ignore previous errors. */
140 [ - + ]: 6851920 : if (die == NULL)
141 : : return -1;
142 : :
143 : : /* Find the abbreviation entry. */
144 : 6851920 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
145 [ + + ]: 6851920 : if (unlikely (abbrevp == DWARF_END_ABBREV))
146 : : {
147 : 2422 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
148 : 2422 : return -1;
149 : : }
150 : :
151 : : /* If there are no children, do not search. */
152 [ + + ]: 6849498 : if (! abbrevp->has_children)
153 : : return 1;
154 : :
155 : : /* Skip past the last attribute. */
156 : 3808004 : void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
157 : :
158 [ - + ]: 3808004 : if (addr == NULL)
159 : : return -1;
160 : :
161 : : /* RESULT can be the same as DIE. So preserve what we need. */
162 : 3808004 : struct Dwarf_CU *cu = die->cu;
163 : :
164 : : /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
165 : : So if this starts with ULEB128 of 0 (even with silly encoding of 0),
166 : : it is a kosher null entry and we do not really have any children. */
167 : 3808004 : const unsigned char *code = addr;
168 : 3808004 : const unsigned char *endp = cu->endp;
169 : 3808012 : while (1)
170 : : {
171 [ - + ]: 3808008 : if (unlikely (code >= endp)) /* Truncated section. */
172 : : return 1;
173 [ + + ]: 3808008 : if (unlikely (*code == 0x80))
174 : 4 : ++code;
175 : : else
176 : : break;
177 : : }
178 [ - + ]: 3808004 : if (unlikely (*code == '\0'))
179 : : return 1;
180 : :
181 : : /* Clear the entire DIE structure. This signals we have not yet
182 : : determined any of the information. */
183 : 3808004 : memset (result, '\0', sizeof (Dwarf_Die));
184 : :
185 : : /* We have the address. */
186 : 3808004 : result->addr = addr;
187 : :
188 : : /* Same CU as the parent. */
189 : 3808004 : result->cu = cu;
190 : :
191 : 3808004 : return 0;
192 : : }
193 : : INTDEF(dwarf_child)
|