]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/elftoolchain/libdwarf/dwarf_die.c
strings: capsicumize it
[FreeBSD/FreeBSD.git] / contrib / elftoolchain / libdwarf / dwarf_die.c
1 /*-
2  * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3  * Copyright (c) 2009,2011,2014 Kai Wang
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include "_libdwarf.h"
29
30 ELFTC_VCSID("$Id: dwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $");
31
32 int
33 dwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *error)
34 {
35         Dwarf_Debug dbg;
36         Dwarf_Section *ds;
37         Dwarf_CU cu;
38         int ret;
39
40         dbg = die != NULL ? die->die_dbg : NULL;
41
42         if (die == NULL || ret_die == NULL) {
43                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
44                 return (DW_DLV_ERROR);
45         }
46
47         if (die->die_ab->ab_children == DW_CHILDREN_no)
48                 return (DW_DLV_NO_ENTRY);
49
50         dbg = die->die_dbg;
51         cu = die->die_cu;
52         ds = cu->cu_is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
53         ret = _dwarf_die_parse(die->die_dbg, ds, cu, cu->cu_dwarf_size,
54             die->die_next_off, cu->cu_next_offset, ret_die, 0, error);
55
56         if (ret == DW_DLE_NO_ENTRY) {
57                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
58                 return (DW_DLV_NO_ENTRY);
59         } else if (ret != DW_DLE_NONE)
60                 return (DW_DLV_ERROR);
61
62         return (DW_DLV_OK);
63 }
64
65 int
66 dwarf_siblingof_b(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,
67     Dwarf_Bool is_info, Dwarf_Error *error)
68 {
69         Dwarf_CU cu;
70         Dwarf_Attribute at;
71         Dwarf_Section *ds;
72         uint64_t offset;
73         int ret, search_sibling;
74
75         if (dbg == NULL || ret_die == NULL) {
76                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
77                 return (DW_DLV_ERROR);
78         }
79
80         ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
81         cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
82
83         if (cu == NULL) {
84                 DWARF_SET_ERROR(dbg, error, DW_DLE_DIE_NO_CU_CONTEXT);
85                 return (DW_DLV_ERROR);
86         }
87
88         /* Application requests the first DIE in this CU. */
89         if (die == NULL)
90                 return (dwarf_offdie_b(dbg, cu->cu_1st_offset, is_info,
91                     ret_die, error));
92
93         /*
94          * Check if the `is_info' flag matches the debug section the
95          * DIE belongs to.
96          */
97         if (is_info != die->die_cu->cu_is_info) {
98                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
99                 return (DW_DLV_ERROR);
100         }
101
102         /*
103          * If the DIE doesn't have any children, its sibling sits next
104          * right to it.
105          */
106         search_sibling = 0;
107         if (die->die_ab->ab_children == DW_CHILDREN_no)
108                 offset = die->die_next_off;
109         else {
110                 /*
111                  * Look for DW_AT_sibling attribute for the offset of
112                  * its sibling.
113                  */
114                 if ((at = _dwarf_attr_find(die, DW_AT_sibling)) != NULL) {
115                         if (at->at_form != DW_FORM_ref_addr)
116                                 offset = at->u[0].u64 + cu->cu_offset;
117                         else
118                                 offset = at->u[0].u64;
119                 } else {
120                         offset = die->die_next_off;
121                         search_sibling = 1;
122                 }
123         }
124
125         ret = _dwarf_die_parse(die->die_dbg, ds, cu, cu->cu_dwarf_size, offset,
126             cu->cu_next_offset, ret_die, search_sibling, error);
127         
128         if (ret == DW_DLE_NO_ENTRY) {
129                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
130                 return (DW_DLV_NO_ENTRY);
131         } else if (ret != DW_DLE_NONE)
132                 return (DW_DLV_ERROR);
133
134         return (DW_DLV_OK);
135 }
136
137
138 int
139 dwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,
140     Dwarf_Error *error)
141 {
142
143         return (dwarf_siblingof_b(dbg, die, ret_die, 1, error));
144 }
145
146 static int
147 _dwarf_search_die_within_cu(Dwarf_Debug dbg, Dwarf_Section *s, Dwarf_CU cu,
148     Dwarf_Off offset, Dwarf_Die *ret_die, Dwarf_Error *error)
149 {
150
151         assert(dbg != NULL && cu != NULL && ret_die != NULL);
152
153         return (_dwarf_die_parse(dbg, s, cu, cu->cu_dwarf_size,
154             offset, cu->cu_next_offset, ret_die, 0, error));
155 }
156
157 int
158 dwarf_offdie_b(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Bool is_info,
159     Dwarf_Die *ret_die, Dwarf_Error *error)
160 {
161         Dwarf_Section *ds;
162         Dwarf_CU cu;
163         int ret;
164
165         if (dbg == NULL || ret_die == NULL) {
166                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
167                 return (DW_DLV_ERROR);
168         }
169
170         ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
171         cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
172
173         /* First search the current CU. */
174         if (cu != NULL) {
175                 if (offset > cu->cu_offset && offset < cu->cu_next_offset) {
176                         ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
177                             ret_die, error);
178                         if (ret == DW_DLE_NO_ENTRY) {
179                                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
180                                 return (DW_DLV_NO_ENTRY);
181                         } else if (ret != DW_DLE_NONE)
182                                 return (DW_DLV_ERROR);
183                         return (DW_DLV_OK);
184                 }
185         }
186
187         /* Search other CUs. */
188         ret = _dwarf_info_load(dbg, 1, is_info, error);
189         if (ret != DW_DLE_NONE)
190                 return (DW_DLV_ERROR);
191
192         if (is_info) {
193                 STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
194                         if (offset < cu->cu_offset ||
195                             offset > cu->cu_next_offset)
196                                 continue;
197                         ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
198                             ret_die, error);
199                         if (ret == DW_DLE_NO_ENTRY) {
200                                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
201                                 return (DW_DLV_NO_ENTRY);
202                         } else if (ret != DW_DLE_NONE)
203                                 return (DW_DLV_ERROR);
204                         return (DW_DLV_OK);
205                 }
206         } else {
207                 STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {
208                         if (offset < cu->cu_offset ||
209                             offset > cu->cu_next_offset)
210                                 continue;
211                         ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
212                             ret_die, error);
213                         if (ret == DW_DLE_NO_ENTRY) {
214                                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
215                                 return (DW_DLV_NO_ENTRY);
216                         } else if (ret != DW_DLE_NONE)
217                                 return (DW_DLV_ERROR);
218                         return (DW_DLV_OK);
219                 }
220         }
221
222         DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
223         return (DW_DLV_NO_ENTRY);
224 }
225
226 int
227 dwarf_offdie(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die *ret_die,
228     Dwarf_Error *error)
229 {
230
231         return (dwarf_offdie_b(dbg, offset, 1, ret_die, error));
232 }
233
234 int
235 dwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *error)
236 {
237         Dwarf_Debug dbg;
238
239         dbg = die != NULL ? die->die_dbg : NULL;
240
241         if (die == NULL || tag == NULL) {
242                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
243                 return (DW_DLV_ERROR);
244         }
245
246         assert(die->die_ab != NULL);
247
248         *tag = (Dwarf_Half) die->die_ab->ab_tag;
249
250         return (DW_DLV_OK);
251 }
252
253 int
254 dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)
255 {
256         Dwarf_Debug dbg;
257
258         dbg = die != NULL ? die->die_dbg : NULL;
259
260         if (die == NULL || ret_offset == NULL) {
261                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
262                 return (DW_DLV_ERROR);
263         }
264
265         *ret_offset = die->die_offset;
266
267         return (DW_DLV_OK);
268 }
269
270 int
271 dwarf_die_CU_offset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)
272 {
273         Dwarf_Debug dbg;
274         Dwarf_CU cu;
275
276         dbg = die != NULL ? die->die_dbg : NULL;
277
278         if (die == NULL || ret_offset == NULL) {
279                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
280                 return (DW_DLV_ERROR);
281         }
282
283         cu = die->die_cu;
284         assert(cu != NULL);
285
286         *ret_offset = die->die_offset - cu->cu_offset;
287
288         return (DW_DLV_OK);
289 }
290
291 int
292 dwarf_die_CU_offset_range(Dwarf_Die die, Dwarf_Off *cu_offset,
293     Dwarf_Off *cu_length, Dwarf_Error *error)
294 {
295         Dwarf_Debug dbg;
296         Dwarf_CU cu;
297
298         dbg = die != NULL ? die->die_dbg : NULL;
299
300         if (die == NULL || cu_offset == NULL || cu_length == NULL) {
301                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
302                 return (DW_DLV_ERROR);
303         }
304
305         cu = die->die_cu;
306         assert(cu != NULL);
307
308         *cu_offset = cu->cu_offset;
309         *cu_length = cu->cu_length + cu->cu_length_size;
310
311         return (DW_DLV_OK);
312 }
313
314 int
315 dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error *error)
316 {
317         Dwarf_Debug dbg;
318
319         dbg = die != NULL ? die->die_dbg : NULL;
320
321         if (die == NULL || ret_name == NULL) {
322                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
323                 return (DW_DLV_ERROR);
324         }
325
326         if (die->die_name == NULL) {
327                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
328                 return (DW_DLV_NO_ENTRY);
329         }
330
331         *ret_name = die->die_name;
332
333         return (DW_DLV_OK);
334 }
335
336 int
337 dwarf_die_abbrev_code(Dwarf_Die die)
338 {
339
340         assert(die != NULL);
341
342         return (die->die_abnum);
343 }
344
345 int
346 dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug dbg,
347     Dwarf_Off in_cu_header_offset, Dwarf_Bool is_info,
348     Dwarf_Off *out_cu_die_offset, Dwarf_Error *error)
349 {
350         Dwarf_CU cu;
351
352         if (dbg == NULL || out_cu_die_offset == NULL) {
353                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
354                 return (DW_DLV_ERROR);
355         }
356
357         if (is_info) {
358                 STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
359                         if (cu->cu_offset == in_cu_header_offset) {
360                                 *out_cu_die_offset = cu->cu_1st_offset;
361                                 break;
362                         }
363                 }
364         } else {
365                 STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {
366                         if (cu->cu_offset == in_cu_header_offset) {
367                                 *out_cu_die_offset = cu->cu_1st_offset;
368                                 break;
369                         }
370                 }
371         }
372
373         if (cu == NULL) {
374                 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
375                 return (DW_DLV_NO_ENTRY);
376         }
377
378         return (DW_DLV_OK);
379 }
380
381 int
382 dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
383     Dwarf_Off in_cu_header_offset, Dwarf_Off *out_cu_die_offset,
384     Dwarf_Error *error)
385 {
386
387         return (dwarf_get_cu_die_offset_given_cu_header_offset_b(dbg,
388             in_cu_header_offset, 1, out_cu_die_offset, error));
389 }
390
391 int
392 dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Half *addr_size,
393     Dwarf_Error *error)
394 {
395
396         if (dbg == NULL || addr_size == NULL) {
397                 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
398                 return (DW_DLV_ERROR);
399         }
400
401         *addr_size = dbg->dbg_pointer_size;
402
403         return (DW_DLV_OK);
404 }
405
406 Dwarf_Bool
407 dwarf_get_die_infotypes_flag(Dwarf_Die die)
408 {
409
410         assert(die != NULL);
411
412         return (die->die_cu->cu_is_info);
413 }