Line data Source code
1 : /* Return child of current DIE.
2 : Copyright (C) 2003-2011, 2014 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 3711746 : __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
44 : unsigned int *codep, unsigned int *formp)
45 : {
46 3711746 : Dwarf *dbg = die->cu->dbg;
47 : const unsigned char *readp;
48 :
49 : /* Find the abbreviation entry. */
50 3711746 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
51 3711746 : if (unlikely (abbrevp == DWARF_END_ABBREV))
52 : {
53 : invalid_dwarf:
54 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
55 0 : return NULL;
56 : }
57 :
58 : /* Search the name attribute. */
59 3711746 : unsigned char *const endp
60 3711746 : = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
61 3711746 : + dbg->sectiondata[IDX_debug_abbrev]->d_size);
62 :
63 3711746 : const unsigned char *attrp = abbrevp->attrp;
64 : while (1)
65 : {
66 : /* Get attribute name and form. */
67 15560500 : if (unlikely (attrp >= endp))
68 : goto invalid_dwarf;
69 : unsigned int attr_name;
70 15560500 : get_uleb128 (attr_name, attrp, endp);
71 :
72 15560500 : if (unlikely (attrp >= endp))
73 : goto invalid_dwarf;
74 : unsigned int attr_form;
75 15560500 : get_uleb128 (attr_form, attrp, endp);
76 :
77 : /* We can stop if we found the attribute with value zero. */
78 15560500 : if (attr_name == 0 && attr_form == 0)
79 : break;
80 :
81 : /* Is this the name attribute? */
82 12990693 : if (attr_name == search_name && search_name != INVALID)
83 : {
84 1141939 : if (codep != NULL)
85 1141939 : *codep = attr_name;
86 1141939 : if (formp != NULL)
87 1141939 : *formp = attr_form;
88 :
89 1141939 : return (unsigned char *) readp;
90 : }
91 :
92 : /* Skip over the rest of this attribute (if there is any). */
93 11848754 : if (attr_form != 0)
94 : {
95 11848754 : size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
96 11848754 : if (unlikely (len == (size_t) -1l))
97 : {
98 0 : readp = NULL;
99 0 : break;
100 : }
101 :
102 : // __libdw_form_val_len will have done a bounds check.
103 11848754 : readp += len;
104 : }
105 : }
106 :
107 : // XXX Do we need other values?
108 2569807 : if (codep != NULL)
109 2386900 : *codep = INVALID;
110 2569807 : if (formp != NULL)
111 2386900 : *formp = INVALID;
112 :
113 2569807 : return (unsigned char *) readp;
114 : }
115 :
116 :
117 : int
118 864690 : dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
119 : {
120 : /* Ignore previous errors. */
121 864690 : if (die == NULL)
122 : return -1;
123 :
124 : /* Find the abbreviation entry. */
125 864690 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
126 864690 : if (unlikely (abbrevp == DWARF_END_ABBREV))
127 : {
128 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
129 0 : return -1;
130 : }
131 :
132 : /* If there are no children, do not search. */
133 864690 : if (! abbrevp->has_children)
134 : return 1;
135 :
136 : /* Skip past the last attribute. */
137 182907 : void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
138 :
139 182907 : if (addr == NULL)
140 : return -1;
141 :
142 : /* RESULT can be the same as DIE. So preserve what we need. */
143 182907 : struct Dwarf_CU *cu = die->cu;
144 :
145 : /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
146 : So if this starts with ULEB128 of 0 (even with silly encoding of 0),
147 : it is a kosher null entry and we do not really have any children. */
148 182907 : const unsigned char *code = addr;
149 182907 : const unsigned char *endp = cu->endp;
150 : while (1)
151 : {
152 182907 : if (unlikely (code >= endp)) /* Truncated section. */
153 : return 1;
154 182907 : if (unlikely (*code == 0x80))
155 0 : ++code;
156 : else
157 : break;
158 : }
159 182907 : if (unlikely (*code == '\0'))
160 : return 1;
161 :
162 : /* Clear the entire DIE structure. This signals we have not yet
163 : determined any of the information. */
164 182907 : memset (result, '\0', sizeof (Dwarf_Die));
165 :
166 : /* We have the address. */
167 182907 : result->addr = addr;
168 :
169 : /* Same CU as the parent. */
170 182907 : result->cu = cu;
171 :
172 182907 : return 0;
173 : }
174 : INTDEF(dwarf_child)
|