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 41468033 : __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
44 : unsigned int *codep, unsigned int *formp)
45 : {
46 : const unsigned char *readp;
47 :
48 : /* Find the abbreviation entry. */
49 41468033 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
50 41468033 : if (unlikely (abbrevp == DWARF_END_ABBREV))
51 : {
52 4365 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
53 4365 : return NULL;
54 : }
55 :
56 : /* Search the name attribute. Attribute has been checked when
57 : Dwarf_Abbrev was created, we can read unchecked. */
58 41463668 : const unsigned char *attrp = abbrevp->attrp;
59 : while (1)
60 : {
61 : /* Get attribute name and form. */
62 : unsigned int attr_name;
63 167453984 : get_uleb128_unchecked (attr_name, attrp);
64 :
65 : unsigned int attr_form;
66 167453984 : get_uleb128_unchecked (attr_form, attrp);
67 :
68 : /* We can stop if we found the attribute with value zero. */
69 167453984 : if (attr_name == 0 && attr_form == 0)
70 : break;
71 :
72 : /* Is this the name attribute? */
73 133043115 : if (attr_name == search_name && search_name != INVALID)
74 : {
75 7052799 : if (codep != NULL)
76 7052799 : *codep = attr_name;
77 7052799 : if (formp != NULL)
78 7052799 : *formp = attr_form;
79 :
80 : /* Normally the attribute data comes from the DIE/info,
81 : except for implicit_form, where it comes from the abbrev. */
82 7052799 : if (attr_form == DW_FORM_implicit_const)
83 0 : return (unsigned char *) attrp;
84 : else
85 7052799 : return (unsigned char *) readp;
86 : }
87 :
88 : /* Skip over the rest of this attribute (if there is any). */
89 125990316 : if (attr_form != 0)
90 : {
91 125990316 : size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
92 125990316 : if (unlikely (len == (size_t) -1l))
93 : {
94 0 : readp = NULL;
95 0 : break;
96 : }
97 :
98 : // __libdw_form_val_len will have done a bounds check.
99 125990316 : readp += len;
100 :
101 : // If the value is in the abbrev data, skip it.
102 125990316 : if (attr_form == DW_FORM_implicit_const)
103 : {
104 : int64_t attr_value __attribute__((__unused__));
105 907 : get_sleb128_unchecked (attr_value, attrp);
106 : }
107 : }
108 : }
109 :
110 : // XXX Do we need other values?
111 34410869 : if (codep != NULL)
112 30098236 : *codep = INVALID;
113 34410869 : if (formp != NULL)
114 30098236 : *formp = INVALID;
115 :
116 34410869 : return (unsigned char *) readp;
117 : }
118 :
119 :
120 : int
121 5372164 : dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
122 : {
123 : /* Ignore previous errors. */
124 5372164 : if (die == NULL)
125 : return -1;
126 :
127 : /* Find the abbreviation entry. */
128 5372164 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
129 5372164 : if (unlikely (abbrevp == DWARF_END_ABBREV))
130 : {
131 873 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
132 873 : return -1;
133 : }
134 :
135 : /* If there are no children, do not search. */
136 5371291 : if (! abbrevp->has_children)
137 : return 1;
138 :
139 : /* Skip past the last attribute. */
140 4312633 : void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
141 :
142 4312633 : if (addr == NULL)
143 : return -1;
144 :
145 : /* RESULT can be the same as DIE. So preserve what we need. */
146 4312633 : struct Dwarf_CU *cu = die->cu;
147 :
148 : /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
149 : So if this starts with ULEB128 of 0 (even with silly encoding of 0),
150 : it is a kosher null entry and we do not really have any children. */
151 4312633 : const unsigned char *code = addr;
152 4312633 : const unsigned char *endp = cu->endp;
153 : while (1)
154 : {
155 4312637 : if (unlikely (code >= endp)) /* Truncated section. */
156 : return 1;
157 4312635 : if (unlikely (*code == 0x80))
158 2 : ++code;
159 : else
160 : break;
161 : }
162 4312633 : if (unlikely (*code == '\0'))
163 : return 1;
164 :
165 : /* Clear the entire DIE structure. This signals we have not yet
166 : determined any of the information. */
167 4312633 : memset (result, '\0', sizeof (Dwarf_Die));
168 :
169 : /* We have the address. */
170 4312633 : result->addr = addr;
171 :
172 : /* Same CU as the parent. */
173 4312633 : result->cu = cu;
174 :
175 4312633 : return 0;
176 : }
177 : INTDEF(dwarf_child)
|