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