2 * Copyright (c) 2007 John Birrell (jb@freebsd.org)
3 * Copyright (c) 2009,2011,2014 Kai Wang
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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
28 #include "_libdwarf.h"
30 ELFTC_VCSID("$Id: dwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $");
33 dwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *error)
40 dbg = die != NULL ? die->die_dbg : NULL;
42 if (die == NULL || ret_die == NULL) {
43 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
44 return (DW_DLV_ERROR);
47 if (die->die_ab->ab_children == DW_CHILDREN_no)
48 return (DW_DLV_NO_ENTRY);
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);
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);
66 dwarf_siblingof_b(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,
67 Dwarf_Bool is_info, Dwarf_Error *error)
73 int ret, search_sibling;
75 if (dbg == NULL || ret_die == NULL) {
76 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
77 return (DW_DLV_ERROR);
80 ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
81 cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
84 DWARF_SET_ERROR(dbg, error, DW_DLE_DIE_NO_CU_CONTEXT);
85 return (DW_DLV_ERROR);
88 /* Application requests the first DIE in this CU. */
90 return (dwarf_offdie_b(dbg, cu->cu_1st_offset, is_info,
94 * Check if the `is_info' flag matches the debug section the
97 if (is_info != die->die_cu->cu_is_info) {
98 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
99 return (DW_DLV_ERROR);
103 * If the DIE doesn't have any children, its sibling sits next
107 if (die->die_ab->ab_children == DW_CHILDREN_no)
108 offset = die->die_next_off;
111 * Look for DW_AT_sibling attribute for the offset of
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;
118 offset = at->u[0].u64;
120 offset = die->die_next_off;
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);
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);
139 dwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,
143 return (dwarf_siblingof_b(dbg, die, ret_die, 1, error));
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)
151 assert(dbg != NULL && cu != NULL && ret_die != NULL);
153 return (_dwarf_die_parse(dbg, s, cu, cu->cu_dwarf_size,
154 offset, cu->cu_next_offset, ret_die, 0, error));
158 dwarf_offdie_b(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Bool is_info,
159 Dwarf_Die *ret_die, Dwarf_Error *error)
165 if (dbg == NULL || ret_die == NULL) {
166 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
167 return (DW_DLV_ERROR);
170 ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;
171 cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;
173 /* First search the current CU. */
175 if (offset > cu->cu_offset && offset < cu->cu_next_offset) {
176 ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
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);
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);
193 STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {
194 if (offset < cu->cu_offset ||
195 offset > cu->cu_next_offset)
197 ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
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);
207 STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {
208 if (offset < cu->cu_offset ||
209 offset > cu->cu_next_offset)
211 ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,
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);
222 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
223 return (DW_DLV_NO_ENTRY);
227 dwarf_offdie(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die *ret_die,
231 return (dwarf_offdie_b(dbg, offset, 1, ret_die, error));
235 dwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *error)
239 dbg = die != NULL ? die->die_dbg : NULL;
241 if (die == NULL || tag == NULL) {
242 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
243 return (DW_DLV_ERROR);
246 assert(die->die_ab != NULL);
248 *tag = (Dwarf_Half) die->die_ab->ab_tag;
254 dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)
258 dbg = die != NULL ? die->die_dbg : NULL;
260 if (die == NULL || ret_offset == NULL) {
261 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
262 return (DW_DLV_ERROR);
265 *ret_offset = die->die_offset;
271 dwarf_die_CU_offset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)
276 dbg = die != NULL ? die->die_dbg : NULL;
278 if (die == NULL || ret_offset == NULL) {
279 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
280 return (DW_DLV_ERROR);
286 *ret_offset = die->die_offset - cu->cu_offset;
292 dwarf_die_CU_offset_range(Dwarf_Die die, Dwarf_Off *cu_offset,
293 Dwarf_Off *cu_length, Dwarf_Error *error)
298 dbg = die != NULL ? die->die_dbg : NULL;
300 if (die == NULL || cu_offset == NULL || cu_length == NULL) {
301 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
302 return (DW_DLV_ERROR);
308 *cu_offset = cu->cu_offset;
309 *cu_length = cu->cu_length + cu->cu_length_size;
315 dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error *error)
319 dbg = die != NULL ? die->die_dbg : NULL;
321 if (die == NULL || ret_name == NULL) {
322 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
323 return (DW_DLV_ERROR);
326 if (die->die_name == NULL) {
327 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
328 return (DW_DLV_NO_ENTRY);
331 *ret_name = die->die_name;
337 dwarf_die_abbrev_code(Dwarf_Die die)
342 return (die->die_abnum);
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)
352 if (dbg == NULL || out_cu_die_offset == NULL) {
353 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
354 return (DW_DLV_ERROR);
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;
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;
374 DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);
375 return (DW_DLV_NO_ENTRY);
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,
387 return (dwarf_get_cu_die_offset_given_cu_header_offset_b(dbg,
388 in_cu_header_offset, 1, out_cu_die_offset, error));
392 dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Half *addr_size,
396 if (dbg == NULL || addr_size == NULL) {
397 DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);
398 return (DW_DLV_ERROR);
401 *addr_size = dbg->dbg_pointer_size;
407 dwarf_get_die_infotypes_flag(Dwarf_Die die)
412 return (die->die_cu->cu_is_info);