xref: /aosp_15_r20/external/elfutils/libdw/dwarf_child.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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