1 /* Return vhild of current DIE.
2 Copyright (C) 2003, 2004 Red Hat, Inc.
3 Written by Ulrich Drepper <drepper@redhat.com>, 2003.
4
5 This program is Open Source software; you can redistribute it and/or
6 modify it under the terms of the Open Software License version 1.0 as
7 published by the Open Source Initiative.
8
9 You should have received a copy of the Open Software License along
10 with this program; if not, you may obtain a copy of the Open Software
11 License version 1.0 from http://www.opensource.org/licenses/osl.php or
12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
13 3001 King Ranch Road, Ukiah, CA 95482. */
14
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
18
19 #include "libdwP.h"
20 #include <string.h>
21
22 /* Some arbitrary value not conflicting with any existing code. */
23 #define INVALID 0xffffe444
24
25
26 unsigned char *
27 internal_function_def
__libdw_find_attr(Dwarf_Die * die,unsigned int search_name,unsigned int * codep,unsigned int * formp)28 __libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
29 unsigned int *codep, unsigned int *formp)
30 {
31 Dwarf *dbg = die->cu->dbg;
32 unsigned char *readp = (unsigned char *) die->addr;
33
34 /* First we have to get the abbreviation code so that we can decode
35 the data in the DIE. */
36 unsigned int abbrev_code;
37 get_uleb128 (abbrev_code, readp);
38
39 /* Find the abbreviation entry. */
40 Dwarf_Abbrev *abbrevp = die->abbrev;
41 if (abbrevp == NULL)
42 {
43 abbrevp = __libdw_findabbrev (die->cu, abbrev_code);
44 die->abbrev = abbrevp ?: (Dwarf_Abbrev *) -1l;
45 }
46 if (unlikely (die->abbrev == (Dwarf_Abbrev *) -1l))
47 {
48 __libdw_seterrno (DWARF_E_INVALID_DWARF);
49 return NULL;
50 }
51
52 /* Search the name attribute. */
53 unsigned char *const endp
54 = ((unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf
55 + dbg->sectiondata[IDX_debug_abbrev]->d_size);
56
57 unsigned char *attrp = die->abbrev->attrp;
58 while (1)
59 {
60 /* Are we still in bounds? This test needs to be refined. */
61 if (unlikely (attrp + 1 >= endp))
62 {
63 __libdw_seterrno (DWARF_E_INVALID_DWARF);
64 return NULL;
65 }
66
67 /* Get attribute name and form.
68
69 XXX We don't check whether this reads beyond the end of the
70 section. */
71 unsigned int attr_name;
72 get_uleb128 (attr_name, attrp);
73 unsigned int attr_form;
74 get_uleb128 (attr_form, attrp);
75
76 /* We can stop if we found the attribute with value zero. */
77 if (attr_name == 0 && attr_form == 0)
78 break;
79
80 /* Is this the name attribute? */
81 if (attr_name == search_name && search_name != INVALID)
82 {
83 if (codep != NULL)
84 *codep = attr_name;
85 if (formp != NULL)
86 *formp = attr_form;
87
88 return readp;
89 }
90
91 /* Skip over the rest of this attribute (if there is any). */
92 if (attr_form != 0)
93 {
94 size_t len = __libdw_form_val_len (dbg, die->cu, attr_form, readp);
95
96 if (unlikely (len == (size_t) -1l))
97 {
98 readp = NULL;
99 break;
100 }
101
102 // XXX We need better boundary checks.
103 readp += len;
104 }
105 }
106
107 // XXX Do we need other values?
108 if (codep != NULL)
109 *codep = INVALID;
110 if (formp != NULL)
111 *formp = INVALID;
112
113 return readp;
114 }
115
116
117 int
dwarf_child(die,result)118 dwarf_child (die, result)
119 Dwarf_Die *die;
120 Dwarf_Die *result;
121 {
122 /* Ignore previous errors. */
123 if (die == NULL)
124 return -1;
125
126 /* Skip past the last attribute. */
127 void *addr = NULL;
128
129 /* If we already know there are no children do not search. */
130 if (die->abbrev != (Dwarf_Abbrev *) -1
131 && (die->abbrev == NULL || die->abbrev->has_children))
132 addr = __libdw_find_attr (die, INVALID, NULL, NULL);
133 if (die->abbrev == (Dwarf_Abbrev *) -1l)
134 return -1;
135
136 /* Make sure the DIE really has children. */
137 if (! die->abbrev->has_children)
138 /* There cannot be any children. */
139 return 1;
140
141 if (addr == NULL)
142 return -1;
143
144 /* RESULT can be the same as DIE. So preserve what we need. */
145 struct Dwarf_CU *cu = die->cu;
146
147 /* Clear the entire DIE structure. This signals we have not yet
148 determined any of the information. */
149 memset (result, '\0', sizeof (Dwarf_Die));
150
151 /* We have the address. */
152 result->addr = addr;
153
154 /* Same CU as the parent. */
155 result->cu = cu;
156
157 return 0;
158 }
159