Path: blob/main/contrib/elftoolchain/libdwarf/dwarf_die.c
39478 views
/*-1* Copyright (c) 2007 John Birrell ([email protected])2* Copyright (c) 2009,2011,2014 Kai Wang3* All rights reserved.4*5* Redistribution and use in source and binary forms, with or without6* modification, are permitted provided that the following conditions7* are met:8* 1. Redistributions of source code must retain the above copyright9* notice, this list of conditions and the following disclaimer.10* 2. Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND15* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE16* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE17* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE18* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL19* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS20* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)21* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT22* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY23* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF24* SUCH DAMAGE.25*/2627#include "_libdwarf.h"2829ELFTC_VCSID("$Id: dwarf_die.c 3039 2014-05-18 15:10:56Z kaiwang27 $");3031int32dwarf_child(Dwarf_Die die, Dwarf_Die *ret_die, Dwarf_Error *error)33{34Dwarf_Debug dbg;35Dwarf_Section *ds;36Dwarf_CU cu;37int ret;3839dbg = die != NULL ? die->die_dbg : NULL;4041if (die == NULL || ret_die == NULL) {42DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);43return (DW_DLV_ERROR);44}4546if (die->die_ab->ab_children == DW_CHILDREN_no)47return (DW_DLV_NO_ENTRY);4849dbg = die->die_dbg;50cu = die->die_cu;51ds = cu->cu_is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;52ret = _dwarf_die_parse(die->die_dbg, ds, cu, cu->cu_dwarf_size,53die->die_next_off, cu->cu_next_offset, ret_die, 0, error);5455if (ret == DW_DLE_NO_ENTRY) {56DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);57return (DW_DLV_NO_ENTRY);58} else if (ret != DW_DLE_NONE)59return (DW_DLV_ERROR);6061return (DW_DLV_OK);62}6364int65dwarf_siblingof_b(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,66Dwarf_Bool is_info, Dwarf_Error *error)67{68Dwarf_CU cu;69Dwarf_Attribute at;70Dwarf_Section *ds;71uint64_t offset;72int ret, search_sibling;7374if (dbg == NULL || ret_die == NULL) {75DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);76return (DW_DLV_ERROR);77}7879ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;80cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;8182if (cu == NULL) {83DWARF_SET_ERROR(dbg, error, DW_DLE_DIE_NO_CU_CONTEXT);84return (DW_DLV_ERROR);85}8687/* Application requests the first DIE in this CU. */88if (die == NULL)89return (dwarf_offdie_b(dbg, cu->cu_1st_offset, is_info,90ret_die, error));9192/*93* Check if the `is_info' flag matches the debug section the94* DIE belongs to.95*/96if (is_info != die->die_cu->cu_is_info) {97DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);98return (DW_DLV_ERROR);99}100101/*102* If the DIE doesn't have any children, its sibling sits next103* right to it.104*/105search_sibling = 0;106if (die->die_ab->ab_children == DW_CHILDREN_no)107offset = die->die_next_off;108else {109/*110* Look for DW_AT_sibling attribute for the offset of111* its sibling.112*/113if ((at = _dwarf_attr_find(die, DW_AT_sibling)) != NULL) {114if (at->at_form != DW_FORM_ref_addr)115offset = at->u[0].u64 + cu->cu_offset;116else117offset = at->u[0].u64;118} else {119offset = die->die_next_off;120search_sibling = 1;121}122}123124ret = _dwarf_die_parse(die->die_dbg, ds, cu, cu->cu_dwarf_size, offset,125cu->cu_next_offset, ret_die, search_sibling, error);126127if (ret == DW_DLE_NO_ENTRY) {128DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);129return (DW_DLV_NO_ENTRY);130} else if (ret != DW_DLE_NONE)131return (DW_DLV_ERROR);132133return (DW_DLV_OK);134}135136137int138dwarf_siblingof(Dwarf_Debug dbg, Dwarf_Die die, Dwarf_Die *ret_die,139Dwarf_Error *error)140{141142return (dwarf_siblingof_b(dbg, die, ret_die, 1, error));143}144145static int146_dwarf_search_die_within_cu(Dwarf_Debug dbg, Dwarf_Section *s, Dwarf_CU cu,147Dwarf_Off offset, Dwarf_Die *ret_die, Dwarf_Error *error)148{149150assert(dbg != NULL && cu != NULL && ret_die != NULL);151152return (_dwarf_die_parse(dbg, s, cu, cu->cu_dwarf_size,153offset, cu->cu_next_offset, ret_die, 0, error));154}155156int157dwarf_offdie_b(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Bool is_info,158Dwarf_Die *ret_die, Dwarf_Error *error)159{160Dwarf_Section *ds;161Dwarf_CU cu;162int ret;163164if (dbg == NULL || ret_die == NULL) {165DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);166return (DW_DLV_ERROR);167}168169ds = is_info ? dbg->dbg_info_sec : dbg->dbg_types_sec;170cu = is_info ? dbg->dbg_cu_current : dbg->dbg_tu_current;171172/* First search the current CU. */173if (cu != NULL) {174if (offset > cu->cu_offset && offset < cu->cu_next_offset) {175ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,176ret_die, error);177if (ret == DW_DLE_NO_ENTRY) {178DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);179return (DW_DLV_NO_ENTRY);180} else if (ret != DW_DLE_NONE)181return (DW_DLV_ERROR);182return (DW_DLV_OK);183}184}185186/* Search other CUs. */187ret = _dwarf_info_load(dbg, 1, is_info, error);188if (ret != DW_DLE_NONE)189return (DW_DLV_ERROR);190191if (is_info) {192STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {193if (offset < cu->cu_offset ||194offset > cu->cu_next_offset)195continue;196ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,197ret_die, error);198if (ret == DW_DLE_NO_ENTRY) {199DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);200return (DW_DLV_NO_ENTRY);201} else if (ret != DW_DLE_NONE)202return (DW_DLV_ERROR);203return (DW_DLV_OK);204}205} else {206STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {207if (offset < cu->cu_offset ||208offset > cu->cu_next_offset)209continue;210ret = _dwarf_search_die_within_cu(dbg, ds, cu, offset,211ret_die, error);212if (ret == DW_DLE_NO_ENTRY) {213DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);214return (DW_DLV_NO_ENTRY);215} else if (ret != DW_DLE_NONE)216return (DW_DLV_ERROR);217return (DW_DLV_OK);218}219}220221DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);222return (DW_DLV_NO_ENTRY);223}224225int226dwarf_offdie(Dwarf_Debug dbg, Dwarf_Off offset, Dwarf_Die *ret_die,227Dwarf_Error *error)228{229230return (dwarf_offdie_b(dbg, offset, 1, ret_die, error));231}232233int234dwarf_tag(Dwarf_Die die, Dwarf_Half *tag, Dwarf_Error *error)235{236Dwarf_Debug dbg;237238dbg = die != NULL ? die->die_dbg : NULL;239240if (die == NULL || tag == NULL) {241DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);242return (DW_DLV_ERROR);243}244245assert(die->die_ab != NULL);246247*tag = (Dwarf_Half) die->die_ab->ab_tag;248249return (DW_DLV_OK);250}251252int253dwarf_dieoffset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)254{255Dwarf_Debug dbg;256257dbg = die != NULL ? die->die_dbg : NULL;258259if (die == NULL || ret_offset == NULL) {260DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);261return (DW_DLV_ERROR);262}263264*ret_offset = die->die_offset;265266return (DW_DLV_OK);267}268269int270dwarf_die_CU_offset(Dwarf_Die die, Dwarf_Off *ret_offset, Dwarf_Error *error)271{272Dwarf_Debug dbg;273Dwarf_CU cu;274275dbg = die != NULL ? die->die_dbg : NULL;276277if (die == NULL || ret_offset == NULL) {278DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);279return (DW_DLV_ERROR);280}281282cu = die->die_cu;283assert(cu != NULL);284285*ret_offset = die->die_offset - cu->cu_offset;286287return (DW_DLV_OK);288}289290int291dwarf_die_CU_offset_range(Dwarf_Die die, Dwarf_Off *cu_offset,292Dwarf_Off *cu_length, Dwarf_Error *error)293{294Dwarf_Debug dbg;295Dwarf_CU cu;296297dbg = die != NULL ? die->die_dbg : NULL;298299if (die == NULL || cu_offset == NULL || cu_length == NULL) {300DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);301return (DW_DLV_ERROR);302}303304cu = die->die_cu;305assert(cu != NULL);306307*cu_offset = cu->cu_offset;308*cu_length = cu->cu_length + cu->cu_length_size;309310return (DW_DLV_OK);311}312313int314dwarf_diename(Dwarf_Die die, char **ret_name, Dwarf_Error *error)315{316Dwarf_Debug dbg;317318dbg = die != NULL ? die->die_dbg : NULL;319320if (die == NULL || ret_name == NULL) {321DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);322return (DW_DLV_ERROR);323}324325if (die->die_name == NULL) {326DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);327return (DW_DLV_NO_ENTRY);328}329330*ret_name = die->die_name;331332return (DW_DLV_OK);333}334335int336dwarf_die_abbrev_code(Dwarf_Die die)337{338339assert(die != NULL);340341return (die->die_abnum);342}343344int345dwarf_get_cu_die_offset_given_cu_header_offset_b(Dwarf_Debug dbg,346Dwarf_Off in_cu_header_offset, Dwarf_Bool is_info,347Dwarf_Off *out_cu_die_offset, Dwarf_Error *error)348{349Dwarf_CU cu;350351if (dbg == NULL || out_cu_die_offset == NULL) {352DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);353return (DW_DLV_ERROR);354}355356if (is_info) {357STAILQ_FOREACH(cu, &dbg->dbg_cu, cu_next) {358if (cu->cu_offset == in_cu_header_offset) {359*out_cu_die_offset = cu->cu_1st_offset;360break;361}362}363} else {364STAILQ_FOREACH(cu, &dbg->dbg_tu, cu_next) {365if (cu->cu_offset == in_cu_header_offset) {366*out_cu_die_offset = cu->cu_1st_offset;367break;368}369}370}371372if (cu == NULL) {373DWARF_SET_ERROR(dbg, error, DW_DLE_NO_ENTRY);374return (DW_DLV_NO_ENTRY);375}376377return (DW_DLV_OK);378}379380int381dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,382Dwarf_Off in_cu_header_offset, Dwarf_Off *out_cu_die_offset,383Dwarf_Error *error)384{385386return (dwarf_get_cu_die_offset_given_cu_header_offset_b(dbg,387in_cu_header_offset, 1, out_cu_die_offset, error));388}389390int391dwarf_get_address_size(Dwarf_Debug dbg, Dwarf_Half *addr_size,392Dwarf_Error *error)393{394395if (dbg == NULL || addr_size == NULL) {396DWARF_SET_ERROR(dbg, error, DW_DLE_ARGUMENT);397return (DW_DLV_ERROR);398}399400*addr_size = dbg->dbg_pointer_size;401402return (DW_DLV_OK);403}404405Dwarf_Bool406dwarf_get_die_infotypes_flag(Dwarf_Die die)407{408409assert(die != NULL);410411return (die->die_cu->cu_is_info);412}413414415