1cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng/* Helper functions to descend DWARF scope trees. 2cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Copyright (C) 2005,2006,2007 Red Hat, Inc. 3cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng This file is part of Red Hat elfutils. 4cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 5cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is free software; you can redistribute it and/or modify 6cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng it under the terms of the GNU General Public License as published by the 7cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Free Software Foundation; version 2 of the License. 8cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 9cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is distributed in the hope that it will be useful, but 10cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng WITHOUT ANY WARRANTY; without even the implied warranty of 11cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng General Public License for more details. 13cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 14cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng You should have received a copy of the GNU General Public License along 15cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils; if not, write to the Free Software Foundation, 16cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 17cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 18cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng In addition, as a special exception, Red Hat, Inc. gives You the 19cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng additional right to link the code of Red Hat elfutils with code licensed 20cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng under an Open Source Initiative certified open source license 21cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng (http://www.opensource.org/licenses/index.php) and to distribute linked 22cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng combinations including the two. Non-GPL Code permitted under this 23cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exception must only link to the code of Red Hat elfutils through those 24cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng well defined interfaces identified in the file named EXCEPTION found in 25cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the source code files (the "Approved Interfaces"). The files of Non-GPL 26cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Code may instantiate templates or use macros or inline functions from 27cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the Approved Interfaces without causing the resulting work to be covered 28cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng by the GNU General Public License. Only Red Hat, Inc. may make changes 29cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng or additions to the list of Approved Interfaces. Red Hat's grant of 30cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng this exception is conditioned upon your not adding any new exceptions. 31cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If you wish to add a new Approved Interface or exception, please contact 32cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat. You must obey the GNU General Public License in all respects 33cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng for all of the Red Hat elfutils code and other code used in conjunction 34cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng with Red Hat elfutils except the Non-GPL Code covered by this exception. 35cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng If you modify this file, you may extend this exception to your version 36cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng of the file, but you are not obligated to do so. If you do not wish to 37cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng provide this exception without modification, you must delete this 38cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng exception statement from your version and license this file solely under 39cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng the GPL without exception. 40cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 41cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Red Hat elfutils is an included package of the Open Invention Network. 42cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng An included package of the Open Invention Network is a package for which 43cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Open Invention Network licensees cross-license their patents. No patent 44cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng license is granted, either expressly or impliedly, by designation as an 45cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng included package. Should you wish to participate in the Open Invention 46cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Network licensing program, please visit www.openinventionnetwork.com 47cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng <http://www.openinventionnetwork.com>. */ 48cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 49cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#ifdef HAVE_CONFIG_H 50cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng# include <config.h> 51cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#endif 52cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 53cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include "libdwP.h" 54cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng#include <dwarf.h> 55cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 56cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengenum die_class { ignore, match, match_inline, walk, imported }; 57cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 58cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengstatic enum die_class 59cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengclassify_die (Dwarf_Die *die) 60cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 61cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (INTUSE(dwarf_tag) (die)) 62cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 63cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* DIEs with addresses we can try to match. */ 64cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_compile_unit: 65cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_module: 66cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_lexical_block: 67cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_with_stmt: 68cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_catch_block: 69cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_try_block: 70cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_entry_point: 71cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return match; 72cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_inlined_subroutine: 73cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return match_inline; 74cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_subprogram: 75cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This might be a concrete out-of-line instance of an inline, in 76cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng which case it is not guaranteed to be owned by the right scope and 77cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng we will search for its origin as for DW_TAG_inlined_subroutine. */ 78cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin) 79cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng ? match_inline : match); 80cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 81cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* DIEs without addresses that can own DIEs with addresses. */ 82cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_namespace: 83cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_class_type: 84cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_structure_type: 85cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return walk; 86cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 87cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Special indirection required. */ 88cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case DW_TAG_imported_unit: 89cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return imported; 90cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 91cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* Other DIEs we have no reason to descend. */ 92cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 93cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 94cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 95cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return ignore; 96cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 97cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 98cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Chengint 99cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng__libdw_visit_scopes (depth, root, previsit, postvisit, arg) 100cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng unsigned int depth; 101cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Dwarf_Die_Chain *root; 102cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *); 103cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *); 104cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng void *arg; 105cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng{ 106cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng struct Dwarf_Die_Chain child; 107cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 108cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng child.parent = root; 109cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (INTUSE(dwarf_child) (&root->die, &child.die) != 0) 110cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return -1; 111cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 112cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng inline int recurse (void) 113cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 114cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return __libdw_visit_scopes (depth + 1, &child, 115cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng previsit, postvisit, arg); 116cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 117cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 118cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng do 119cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 120cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng child.prune = false; 121cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 122cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (previsit != NULL) 123cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 124cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int result = (*previsit) (depth + 1, &child, arg); 125cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (result != DWARF_CB_OK) 126cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 127cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 128cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 129cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (!child.prune) 130cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng switch (classify_die (&child.die)) 131cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 132cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case match: 133cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case match_inline: 134cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case walk: 135cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (INTUSE(dwarf_haschildren) (&child.die)) 136cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 137cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int result = recurse (); 138cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (result != DWARF_CB_OK) 139cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 140cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 141cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 142cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 143cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng case imported: 144cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 145cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng /* This imports another compilation unit to appear 146cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng as part of this one, inside the current scope. 147cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Recurse to search the referenced unit, but without 148cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng recording it as an inner scoping level. */ 149cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 150cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwarf_Attribute attr_mem; 151cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child.die, 152cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng DW_AT_import, 153cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng &attr_mem); 154cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (INTUSE(dwarf_formref_die) (attr, &child.die) != NULL) 155cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 156cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int result = recurse (); 157cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (result != DWARF_CB_OK) 158cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 159cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 160cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 161cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 162cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 163cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng default: 164cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng break; 165cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 166cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 167cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (postvisit != NULL) 168cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng { 169cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng int result = (*postvisit) (depth + 1, &child, arg); 170cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng if (result != DWARF_CB_OK) 171cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return result; 172cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 173cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng } 174cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng while (INTUSE(dwarf_siblingof) (&child.die, &child.die) == 0); 175cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng 176cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng return 0; 177cc6695e2684ce93cdf8bd2da63d55d2cf49ff076Ben Cheng} 178