source: rtems-tools/rtemstoolkit/elftoolchain/libdwarf/dwarf_die.c @ 4bb3996

5
Last change on this file since 4bb3996 was 4bb3996, checked in by Chris Johns <chrisj@…>, on 04/30/18 at 05:34:48

rtemstoolkit: Add libdwarf from elftoolchain.

The code is taken from:

https://svn.code.sf.net/p/elftoolchain/code/trunk

Update #3417

  • Property mode set to 100644
File size: 9.8 KB
Line 
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
30ELFTC_VCSID("$Id: dwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $");
31
32int
33dwarf_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
65int
66dwarf_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
138int
139dwarf_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
146static 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
157int
158dwarf_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
226int
227dwarf_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
234int
235dwarf_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
253int
254dwarf_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
270int
271dwarf_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
291int
292dwarf_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
314int
315dwarf_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
336int
337dwarf_die_abbrev_code(Dwarf_Die die)
338{
339
340        assert(die != NULL);
341
342        return (die->die_abnum);
343}
344
345int
346dwarf_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
381int
382dwarf_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
391int
392dwarf_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
406Dwarf_Bool
407dwarf_get_die_infotypes_flag(Dwarf_Die die)
408{
409
410        assert(die != NULL);
411
412        return (die->die_cu->cu_is_info);
413}
Note: See TracBrowser for help on using the repository browser.