blob: 248338eb2339d8e13fd107e327e1c3103be3826a [file] [log] [blame]
Brian Silverman86497922018-02-10 19:28:39 -05001/* 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
41unsigned char *
42internal_function
43__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 Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
50 if (unlikely (abbrevp == DWARF_END_ABBREV))
51 {
52 __libdw_seterrno (DWARF_E_INVALID_DWARF);
53 return NULL;
54 }
55
56 /* Search the name attribute. Attribute has been checked when
57 Dwarf_Abbrev was created, we can read unchecked. */
58 const unsigned char *attrp = abbrevp->attrp;
59 while (1)
60 {
61 /* Get attribute name and form. */
62 unsigned int attr_name;
63 get_uleb128_unchecked (attr_name, attrp);
64
65 unsigned int attr_form;
66 get_uleb128_unchecked (attr_form, attrp);
67
68 /* We can stop if we found the attribute with value zero. */
69 if (attr_name == 0 && attr_form == 0)
70 break;
71
72 /* Is this the name attribute? */
73 if (attr_name == search_name && search_name != INVALID)
74 {
75 if (codep != NULL)
76 *codep = attr_name;
77 if (formp != NULL)
78 *formp = attr_form;
79
80 return (unsigned char *) readp;
81 }
82
83 /* Skip over the rest of this attribute (if there is any). */
84 if (attr_form != 0)
85 {
86 size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
87 if (unlikely (len == (size_t) -1l))
88 {
89 readp = NULL;
90 break;
91 }
92
93 // __libdw_form_val_len will have done a bounds check.
94 readp += len;
95 }
96 }
97
98 // XXX Do we need other values?
99 if (codep != NULL)
100 *codep = INVALID;
101 if (formp != NULL)
102 *formp = INVALID;
103
104 return (unsigned char *) readp;
105}
106
107
108int
109dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
110{
111 /* Ignore previous errors. */
112 if (die == NULL)
113 return -1;
114
115 /* Find the abbreviation entry. */
116 Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
117 if (unlikely (abbrevp == DWARF_END_ABBREV))
118 {
119 __libdw_seterrno (DWARF_E_INVALID_DWARF);
120 return -1;
121 }
122
123 /* If there are no children, do not search. */
124 if (! abbrevp->has_children)
125 return 1;
126
127 /* Skip past the last attribute. */
128 void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
129
130 if (addr == NULL)
131 return -1;
132
133 /* RESULT can be the same as DIE. So preserve what we need. */
134 struct Dwarf_CU *cu = die->cu;
135
136 /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
137 So if this starts with ULEB128 of 0 (even with silly encoding of 0),
138 it is a kosher null entry and we do not really have any children. */
139 const unsigned char *code = addr;
140 const unsigned char *endp = cu->endp;
141 while (1)
142 {
143 if (unlikely (code >= endp)) /* Truncated section. */
144 return 1;
145 if (unlikely (*code == 0x80))
146 ++code;
147 else
148 break;
149 }
150 if (unlikely (*code == '\0'))
151 return 1;
152
153 /* Clear the entire DIE structure. This signals we have not yet
154 determined any of the information. */
155 memset (result, '\0', sizeof (Dwarf_Die));
156
157 /* We have the address. */
158 result->addr = addr;
159
160 /* Same CU as the parent. */
161 result->cu = cu;
162
163 return 0;
164}
165INTDEF(dwarf_child)