1*7304104dSAndroid Build Coastguard Worker /* Return child of current DIE.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2003-2011, 2014, 2017 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2003.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of either
8*7304104dSAndroid Build Coastguard Worker
9*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker your option) any later version
12*7304104dSAndroid Build Coastguard Worker
13*7304104dSAndroid Build Coastguard Worker or
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker your option) any later version
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker
21*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24*7304104dSAndroid Build Coastguard Worker General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker
26*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
28*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker
34*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
35*7304104dSAndroid Build Coastguard Worker #include <string.h>
36*7304104dSAndroid Build Coastguard Worker
37*7304104dSAndroid Build Coastguard Worker /* Some arbitrary value not conflicting with any existing code. */
38*7304104dSAndroid Build Coastguard Worker #define INVALID 0xffffe444
39*7304104dSAndroid Build Coastguard Worker
40*7304104dSAndroid Build Coastguard Worker
41*7304104dSAndroid Build Coastguard Worker unsigned char *
42*7304104dSAndroid Build Coastguard Worker internal_function
__libdw_find_attr(Dwarf_Die * die,unsigned int search_name,unsigned int * codep,unsigned int * formp)43*7304104dSAndroid Build Coastguard Worker __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
44*7304104dSAndroid Build Coastguard Worker unsigned int *codep, unsigned int *formp)
45*7304104dSAndroid Build Coastguard Worker {
46*7304104dSAndroid Build Coastguard Worker const unsigned char *readp = NULL;
47*7304104dSAndroid Build Coastguard Worker
48*7304104dSAndroid Build Coastguard Worker /* Find the abbreviation entry. */
49*7304104dSAndroid Build Coastguard Worker Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
50*7304104dSAndroid Build Coastguard Worker if (unlikely (abbrevp == DWARF_END_ABBREV))
51*7304104dSAndroid Build Coastguard Worker {
52*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
53*7304104dSAndroid Build Coastguard Worker return NULL;
54*7304104dSAndroid Build Coastguard Worker }
55*7304104dSAndroid Build Coastguard Worker
56*7304104dSAndroid Build Coastguard Worker const unsigned char *endp = die->cu->endp;
57*7304104dSAndroid Build Coastguard Worker
58*7304104dSAndroid Build Coastguard Worker /* Search the name attribute. Attribute has been checked when
59*7304104dSAndroid Build Coastguard Worker Dwarf_Abbrev was created, we can read unchecked. */
60*7304104dSAndroid Build Coastguard Worker const unsigned char *attrp = abbrevp->attrp;
61*7304104dSAndroid Build Coastguard Worker while (1)
62*7304104dSAndroid Build Coastguard Worker {
63*7304104dSAndroid Build Coastguard Worker /* Get attribute name and form. */
64*7304104dSAndroid Build Coastguard Worker unsigned int attr_name;
65*7304104dSAndroid Build Coastguard Worker get_uleb128_unchecked (attr_name, attrp);
66*7304104dSAndroid Build Coastguard Worker
67*7304104dSAndroid Build Coastguard Worker unsigned int attr_form;
68*7304104dSAndroid Build Coastguard Worker get_uleb128_unchecked (attr_form, attrp);
69*7304104dSAndroid Build Coastguard Worker
70*7304104dSAndroid Build Coastguard Worker /* We can stop if we found the attribute with value zero. */
71*7304104dSAndroid Build Coastguard Worker if (attr_name == 0 && attr_form == 0)
72*7304104dSAndroid Build Coastguard Worker break;
73*7304104dSAndroid Build Coastguard Worker
74*7304104dSAndroid Build Coastguard Worker if (attr_form == DW_FORM_indirect)
75*7304104dSAndroid Build Coastguard Worker {
76*7304104dSAndroid Build Coastguard Worker if (readp >= endp)
77*7304104dSAndroid Build Coastguard Worker goto invalid;
78*7304104dSAndroid Build Coastguard Worker get_uleb128 (attr_form, readp, endp);
79*7304104dSAndroid Build Coastguard Worker if (attr_form == DW_FORM_indirect ||
80*7304104dSAndroid Build Coastguard Worker attr_form == DW_FORM_implicit_const)
81*7304104dSAndroid Build Coastguard Worker {
82*7304104dSAndroid Build Coastguard Worker invalid:
83*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
84*7304104dSAndroid Build Coastguard Worker return NULL;
85*7304104dSAndroid Build Coastguard Worker }
86*7304104dSAndroid Build Coastguard Worker }
87*7304104dSAndroid Build Coastguard Worker
88*7304104dSAndroid Build Coastguard Worker /* Is this the name attribute? */
89*7304104dSAndroid Build Coastguard Worker if (attr_name == search_name && search_name != INVALID)
90*7304104dSAndroid Build Coastguard Worker {
91*7304104dSAndroid Build Coastguard Worker if (codep != NULL)
92*7304104dSAndroid Build Coastguard Worker *codep = attr_name;
93*7304104dSAndroid Build Coastguard Worker if (formp != NULL)
94*7304104dSAndroid Build Coastguard Worker *formp = attr_form;
95*7304104dSAndroid Build Coastguard Worker
96*7304104dSAndroid Build Coastguard Worker /* Normally the attribute data comes from the DIE/info,
97*7304104dSAndroid Build Coastguard Worker except for implicit_form, where it comes from the abbrev. */
98*7304104dSAndroid Build Coastguard Worker if (attr_form == DW_FORM_implicit_const)
99*7304104dSAndroid Build Coastguard Worker return (unsigned char *) attrp;
100*7304104dSAndroid Build Coastguard Worker else
101*7304104dSAndroid Build Coastguard Worker return (unsigned char *) readp;
102*7304104dSAndroid Build Coastguard Worker }
103*7304104dSAndroid Build Coastguard Worker
104*7304104dSAndroid Build Coastguard Worker /* Skip over the rest of this attribute (if there is any). */
105*7304104dSAndroid Build Coastguard Worker if (attr_form != 0)
106*7304104dSAndroid Build Coastguard Worker {
107*7304104dSAndroid Build Coastguard Worker size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
108*7304104dSAndroid Build Coastguard Worker if (unlikely (len == (size_t) -1l))
109*7304104dSAndroid Build Coastguard Worker {
110*7304104dSAndroid Build Coastguard Worker readp = NULL;
111*7304104dSAndroid Build Coastguard Worker break;
112*7304104dSAndroid Build Coastguard Worker }
113*7304104dSAndroid Build Coastguard Worker
114*7304104dSAndroid Build Coastguard Worker // __libdw_form_val_len will have done a bounds check.
115*7304104dSAndroid Build Coastguard Worker readp += len;
116*7304104dSAndroid Build Coastguard Worker
117*7304104dSAndroid Build Coastguard Worker // If the value is in the abbrev data, skip it.
118*7304104dSAndroid Build Coastguard Worker if (attr_form == DW_FORM_implicit_const)
119*7304104dSAndroid Build Coastguard Worker {
120*7304104dSAndroid Build Coastguard Worker int64_t attr_value __attribute__((__unused__));
121*7304104dSAndroid Build Coastguard Worker get_sleb128_unchecked (attr_value, attrp);
122*7304104dSAndroid Build Coastguard Worker }
123*7304104dSAndroid Build Coastguard Worker }
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker
126*7304104dSAndroid Build Coastguard Worker // XXX Do we need other values?
127*7304104dSAndroid Build Coastguard Worker if (codep != NULL)
128*7304104dSAndroid Build Coastguard Worker *codep = INVALID;
129*7304104dSAndroid Build Coastguard Worker if (formp != NULL)
130*7304104dSAndroid Build Coastguard Worker *formp = INVALID;
131*7304104dSAndroid Build Coastguard Worker
132*7304104dSAndroid Build Coastguard Worker return (unsigned char *) readp;
133*7304104dSAndroid Build Coastguard Worker }
134*7304104dSAndroid Build Coastguard Worker
135*7304104dSAndroid Build Coastguard Worker
136*7304104dSAndroid Build Coastguard Worker int
dwarf_child(Dwarf_Die * die,Dwarf_Die * result)137*7304104dSAndroid Build Coastguard Worker dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
138*7304104dSAndroid Build Coastguard Worker {
139*7304104dSAndroid Build Coastguard Worker /* Ignore previous errors. */
140*7304104dSAndroid Build Coastguard Worker if (die == NULL)
141*7304104dSAndroid Build Coastguard Worker return -1;
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker /* Find the abbreviation entry. */
144*7304104dSAndroid Build Coastguard Worker Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
145*7304104dSAndroid Build Coastguard Worker if (unlikely (abbrevp == DWARF_END_ABBREV))
146*7304104dSAndroid Build Coastguard Worker {
147*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
148*7304104dSAndroid Build Coastguard Worker return -1;
149*7304104dSAndroid Build Coastguard Worker }
150*7304104dSAndroid Build Coastguard Worker
151*7304104dSAndroid Build Coastguard Worker /* If there are no children, do not search. */
152*7304104dSAndroid Build Coastguard Worker if (! abbrevp->has_children)
153*7304104dSAndroid Build Coastguard Worker return 1;
154*7304104dSAndroid Build Coastguard Worker
155*7304104dSAndroid Build Coastguard Worker /* Skip past the last attribute. */
156*7304104dSAndroid Build Coastguard Worker void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
157*7304104dSAndroid Build Coastguard Worker
158*7304104dSAndroid Build Coastguard Worker if (addr == NULL)
159*7304104dSAndroid Build Coastguard Worker return -1;
160*7304104dSAndroid Build Coastguard Worker
161*7304104dSAndroid Build Coastguard Worker /* RESULT can be the same as DIE. So preserve what we need. */
162*7304104dSAndroid Build Coastguard Worker struct Dwarf_CU *cu = die->cu;
163*7304104dSAndroid Build Coastguard Worker
164*7304104dSAndroid Build Coastguard Worker /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
165*7304104dSAndroid Build Coastguard Worker So if this starts with ULEB128 of 0 (even with silly encoding of 0),
166*7304104dSAndroid Build Coastguard Worker it is a kosher null entry and we do not really have any children. */
167*7304104dSAndroid Build Coastguard Worker const unsigned char *code = addr;
168*7304104dSAndroid Build Coastguard Worker const unsigned char *endp = cu->endp;
169*7304104dSAndroid Build Coastguard Worker while (1)
170*7304104dSAndroid Build Coastguard Worker {
171*7304104dSAndroid Build Coastguard Worker if (unlikely (code >= endp)) /* Truncated section. */
172*7304104dSAndroid Build Coastguard Worker return 1;
173*7304104dSAndroid Build Coastguard Worker if (unlikely (*code == 0x80))
174*7304104dSAndroid Build Coastguard Worker ++code;
175*7304104dSAndroid Build Coastguard Worker else
176*7304104dSAndroid Build Coastguard Worker break;
177*7304104dSAndroid Build Coastguard Worker }
178*7304104dSAndroid Build Coastguard Worker if (unlikely (*code == '\0'))
179*7304104dSAndroid Build Coastguard Worker return 1;
180*7304104dSAndroid Build Coastguard Worker
181*7304104dSAndroid Build Coastguard Worker /* Clear the entire DIE structure. This signals we have not yet
182*7304104dSAndroid Build Coastguard Worker determined any of the information. */
183*7304104dSAndroid Build Coastguard Worker memset (result, '\0', sizeof (Dwarf_Die));
184*7304104dSAndroid Build Coastguard Worker
185*7304104dSAndroid Build Coastguard Worker /* We have the address. */
186*7304104dSAndroid Build Coastguard Worker result->addr = addr;
187*7304104dSAndroid Build Coastguard Worker
188*7304104dSAndroid Build Coastguard Worker /* Same CU as the parent. */
189*7304104dSAndroid Build Coastguard Worker result->cu = cu;
190*7304104dSAndroid Build Coastguard Worker
191*7304104dSAndroid Build Coastguard Worker return 0;
192*7304104dSAndroid Build Coastguard Worker }
193*7304104dSAndroid Build Coastguard Worker INTDEF(dwarf_child)
194