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 44299400 : __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 44299400 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
50 44299400 : if (unlikely (abbrevp == DWARF_END_ABBREV))
51 : {
52 4395 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
53 4395 : return NULL;
54 : }
55 :
56 : /* Search the name attribute. Attribute has been checked when
57 : Dwarf_Abbrev was created, we can read unchecked. */
58 44295005 : const unsigned char *attrp = abbrevp->attrp;
59 : while (1)
60 : {
61 : /* Get attribute name and form. */
62 : unsigned int attr_name;
63 178128679 : get_uleb128_unchecked (attr_name, attrp);
64 :
65 : unsigned int attr_form;
66 178128679 : get_uleb128_unchecked (attr_form, attrp);
67 :
68 : /* We can stop if we found the attribute with value zero. */
69 178128679 : if (attr_name == 0 && attr_form == 0)
70 : break;
71 :
72 : /* Is this the name attribute? */
73 141404785 : if (attr_name == search_name && search_name != INVALID)
74 : {
75 7571111 : if (codep != NULL)
76 7571111 : *codep = attr_name;
77 7571111 : if (formp != NULL)
78 7571111 : *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 7571111 : if (attr_form == DW_FORM_implicit_const)
83 0 : return (unsigned char *) attrp;
84 : else
85 7571111 : return (unsigned char *) readp;
86 : }
87 :
88 : /* Skip over the rest of this attribute (if there is any). */
89 133833674 : if (attr_form != 0)
90 : {
91 133833674 : size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
92 133833674 : 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 133833674 : readp += len;
100 :
101 : // If the value is in the abbrev data, skip it.
102 133833674 : if (attr_form == DW_FORM_implicit_const)
103 : {
104 : int64_t attr_value __attribute__((__unused__));
105 913 : get_sleb128_unchecked (attr_value, attrp);
106 : }
107 : }
108 : }
109 :
110 : // XXX Do we need other values?
111 36723894 : if (codep != NULL)
112 31996102 : *codep = INVALID;
113 36723894 : if (formp != NULL)
114 31996102 : *formp = INVALID;
115 :
116 36723894 : return (unsigned char *) readp;
117 : }
118 :
119 :
120 : int
121 5763528 : dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
122 : {
123 : /* Ignore previous errors. */
124 5763528 : if (die == NULL)
125 : return -1;
126 :
127 : /* Find the abbreviation entry. */
128 5763528 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
129 5763528 : if (unlikely (abbrevp == DWARF_END_ABBREV))
130 : {
131 879 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
132 879 : return -1;
133 : }
134 :
135 : /* If there are no children, do not search. */
136 5762649 : if (! abbrevp->has_children)
137 : return 1;
138 :
139 : /* Skip past the last attribute. */
140 4727792 : void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
141 :
142 4727792 : if (addr == NULL)
143 : return -1;
144 :
145 : /* RESULT can be the same as DIE. So preserve what we need. */
146 4727792 : 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 4727792 : const unsigned char *code = addr;
152 4727792 : const unsigned char *endp = cu->endp;
153 : while (1)
154 : {
155 4727792 : if (unlikely (code >= endp)) /* Truncated section. */
156 : return 1;
157 4727792 : if (unlikely (*code == 0x80))
158 0 : ++code;
159 : else
160 : break;
161 0 : }
162 4727792 : 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 : memset (result, '\0', sizeof (Dwarf_Die));
168 :
169 : /* We have the address. */
170 4727792 : result->addr = addr;
171 :
172 : /* Same CU as the parent. */
173 4727792 : result->cu = cu;
174 :
175 4727792 : return 0;
176 : }
177 : INTDEF(dwarf_child)
|