1da0c48c4Sopenharmony_ci/* Return child of current DIE. 2da0c48c4Sopenharmony_ci Copyright (C) 2003-2011, 2014, 2017 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci Written by Ulrich Drepper <drepper@redhat.com>, 2003. 5da0c48c4Sopenharmony_ci 6da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 7da0c48c4Sopenharmony_ci it under the terms of either 8da0c48c4Sopenharmony_ci 9da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 10da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 11da0c48c4Sopenharmony_ci your option) any later version 12da0c48c4Sopenharmony_ci 13da0c48c4Sopenharmony_ci or 14da0c48c4Sopenharmony_ci 15da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 16da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 17da0c48c4Sopenharmony_ci your option) any later version 18da0c48c4Sopenharmony_ci 19da0c48c4Sopenharmony_ci or both in parallel, as here. 20da0c48c4Sopenharmony_ci 21da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 22da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 23da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24da0c48c4Sopenharmony_ci General Public License for more details. 25da0c48c4Sopenharmony_ci 26da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 27da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 28da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 29da0c48c4Sopenharmony_ci 30da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 31da0c48c4Sopenharmony_ci# include <config.h> 32da0c48c4Sopenharmony_ci#endif 33da0c48c4Sopenharmony_ci 34da0c48c4Sopenharmony_ci#include "libdwP.h" 35da0c48c4Sopenharmony_ci#include <string.h> 36da0c48c4Sopenharmony_ci 37da0c48c4Sopenharmony_ci/* Some arbitrary value not conflicting with any existing code. */ 38da0c48c4Sopenharmony_ci#define INVALID 0xffffe444 39da0c48c4Sopenharmony_ci 40da0c48c4Sopenharmony_ci 41da0c48c4Sopenharmony_ciunsigned char * 42da0c48c4Sopenharmony_ciinternal_function 43da0c48c4Sopenharmony_ci__libdw_find_attr (Dwarf_Die *die, unsigned int search_name, 44da0c48c4Sopenharmony_ci unsigned int *codep, unsigned int *formp) 45da0c48c4Sopenharmony_ci{ 46da0c48c4Sopenharmony_ci const unsigned char *readp = NULL; 47da0c48c4Sopenharmony_ci 48da0c48c4Sopenharmony_ci /* Find the abbreviation entry. */ 49da0c48c4Sopenharmony_ci Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp); 50da0c48c4Sopenharmony_ci if (unlikely (abbrevp == DWARF_END_ABBREV)) 51da0c48c4Sopenharmony_ci { 52da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_DWARF); 53da0c48c4Sopenharmony_ci return NULL; 54da0c48c4Sopenharmony_ci } 55da0c48c4Sopenharmony_ci 56da0c48c4Sopenharmony_ci const unsigned char *endp = die->cu->endp; 57da0c48c4Sopenharmony_ci 58da0c48c4Sopenharmony_ci /* Search the name attribute. Attribute has been checked when 59da0c48c4Sopenharmony_ci Dwarf_Abbrev was created, we can read unchecked. */ 60da0c48c4Sopenharmony_ci const unsigned char *attrp = abbrevp->attrp; 61da0c48c4Sopenharmony_ci while (1) 62da0c48c4Sopenharmony_ci { 63da0c48c4Sopenharmony_ci /* Get attribute name and form. */ 64da0c48c4Sopenharmony_ci unsigned int attr_name; 65da0c48c4Sopenharmony_ci get_uleb128_unchecked (attr_name, attrp); 66da0c48c4Sopenharmony_ci 67da0c48c4Sopenharmony_ci unsigned int attr_form; 68da0c48c4Sopenharmony_ci get_uleb128_unchecked (attr_form, attrp); 69da0c48c4Sopenharmony_ci 70da0c48c4Sopenharmony_ci /* We can stop if we found the attribute with value zero. */ 71da0c48c4Sopenharmony_ci if (attr_name == 0 && attr_form == 0) 72da0c48c4Sopenharmony_ci break; 73da0c48c4Sopenharmony_ci 74da0c48c4Sopenharmony_ci if (attr_form == DW_FORM_indirect) 75da0c48c4Sopenharmony_ci { 76da0c48c4Sopenharmony_ci get_uleb128 (attr_form, readp, endp); 77da0c48c4Sopenharmony_ci if (attr_form == DW_FORM_indirect || 78da0c48c4Sopenharmony_ci attr_form == DW_FORM_implicit_const) 79da0c48c4Sopenharmony_ci { 80da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_DWARF); 81da0c48c4Sopenharmony_ci return NULL; 82da0c48c4Sopenharmony_ci } 83da0c48c4Sopenharmony_ci } 84da0c48c4Sopenharmony_ci 85da0c48c4Sopenharmony_ci /* Is this the name attribute? */ 86da0c48c4Sopenharmony_ci if (attr_name == search_name && search_name != INVALID) 87da0c48c4Sopenharmony_ci { 88da0c48c4Sopenharmony_ci if (codep != NULL) 89da0c48c4Sopenharmony_ci *codep = attr_name; 90da0c48c4Sopenharmony_ci if (formp != NULL) 91da0c48c4Sopenharmony_ci *formp = attr_form; 92da0c48c4Sopenharmony_ci 93da0c48c4Sopenharmony_ci /* Normally the attribute data comes from the DIE/info, 94da0c48c4Sopenharmony_ci except for implicit_form, where it comes from the abbrev. */ 95da0c48c4Sopenharmony_ci if (attr_form == DW_FORM_implicit_const) 96da0c48c4Sopenharmony_ci return (unsigned char *) attrp; 97da0c48c4Sopenharmony_ci else 98da0c48c4Sopenharmony_ci return (unsigned char *) readp; 99da0c48c4Sopenharmony_ci } 100da0c48c4Sopenharmony_ci 101da0c48c4Sopenharmony_ci /* Skip over the rest of this attribute (if there is any). */ 102da0c48c4Sopenharmony_ci if (attr_form != 0) 103da0c48c4Sopenharmony_ci { 104da0c48c4Sopenharmony_ci size_t len = __libdw_form_val_len (die->cu, attr_form, readp); 105da0c48c4Sopenharmony_ci if (unlikely (len == (size_t) -1l)) 106da0c48c4Sopenharmony_ci { 107da0c48c4Sopenharmony_ci readp = NULL; 108da0c48c4Sopenharmony_ci break; 109da0c48c4Sopenharmony_ci } 110da0c48c4Sopenharmony_ci 111da0c48c4Sopenharmony_ci // __libdw_form_val_len will have done a bounds check. 112da0c48c4Sopenharmony_ci readp += len; 113da0c48c4Sopenharmony_ci 114da0c48c4Sopenharmony_ci // If the value is in the abbrev data, skip it. 115da0c48c4Sopenharmony_ci if (attr_form == DW_FORM_implicit_const) 116da0c48c4Sopenharmony_ci { 117da0c48c4Sopenharmony_ci int64_t attr_value __attribute__((__unused__)); 118da0c48c4Sopenharmony_ci get_sleb128_unchecked (attr_value, attrp); 119da0c48c4Sopenharmony_ci } 120da0c48c4Sopenharmony_ci } 121da0c48c4Sopenharmony_ci } 122da0c48c4Sopenharmony_ci 123da0c48c4Sopenharmony_ci // XXX Do we need other values? 124da0c48c4Sopenharmony_ci if (codep != NULL) 125da0c48c4Sopenharmony_ci *codep = INVALID; 126da0c48c4Sopenharmony_ci if (formp != NULL) 127da0c48c4Sopenharmony_ci *formp = INVALID; 128da0c48c4Sopenharmony_ci 129da0c48c4Sopenharmony_ci return (unsigned char *) readp; 130da0c48c4Sopenharmony_ci} 131da0c48c4Sopenharmony_ci 132da0c48c4Sopenharmony_ci 133da0c48c4Sopenharmony_ciint 134da0c48c4Sopenharmony_cidwarf_child (Dwarf_Die *die, Dwarf_Die *result) 135da0c48c4Sopenharmony_ci{ 136da0c48c4Sopenharmony_ci /* Ignore previous errors. */ 137da0c48c4Sopenharmony_ci if (die == NULL) 138da0c48c4Sopenharmony_ci return -1; 139da0c48c4Sopenharmony_ci 140da0c48c4Sopenharmony_ci /* Find the abbreviation entry. */ 141da0c48c4Sopenharmony_ci Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL); 142da0c48c4Sopenharmony_ci if (unlikely (abbrevp == DWARF_END_ABBREV)) 143da0c48c4Sopenharmony_ci { 144da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_DWARF); 145da0c48c4Sopenharmony_ci return -1; 146da0c48c4Sopenharmony_ci } 147da0c48c4Sopenharmony_ci 148da0c48c4Sopenharmony_ci /* If there are no children, do not search. */ 149da0c48c4Sopenharmony_ci if (! abbrevp->has_children) 150da0c48c4Sopenharmony_ci return 1; 151da0c48c4Sopenharmony_ci 152da0c48c4Sopenharmony_ci /* Skip past the last attribute. */ 153da0c48c4Sopenharmony_ci void *addr = __libdw_find_attr (die, INVALID, NULL, NULL); 154da0c48c4Sopenharmony_ci 155da0c48c4Sopenharmony_ci if (addr == NULL) 156da0c48c4Sopenharmony_ci return -1; 157da0c48c4Sopenharmony_ci 158da0c48c4Sopenharmony_ci /* RESULT can be the same as DIE. So preserve what we need. */ 159da0c48c4Sopenharmony_ci struct Dwarf_CU *cu = die->cu; 160da0c48c4Sopenharmony_ci 161da0c48c4Sopenharmony_ci /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3). 162da0c48c4Sopenharmony_ci So if this starts with ULEB128 of 0 (even with silly encoding of 0), 163da0c48c4Sopenharmony_ci it is a kosher null entry and we do not really have any children. */ 164da0c48c4Sopenharmony_ci const unsigned char *code = addr; 165da0c48c4Sopenharmony_ci const unsigned char *endp = cu->endp; 166da0c48c4Sopenharmony_ci while (1) 167da0c48c4Sopenharmony_ci { 168da0c48c4Sopenharmony_ci if (unlikely (code >= endp)) /* Truncated section. */ 169da0c48c4Sopenharmony_ci return 1; 170da0c48c4Sopenharmony_ci if (unlikely (*code == 0x80)) 171da0c48c4Sopenharmony_ci ++code; 172da0c48c4Sopenharmony_ci else 173da0c48c4Sopenharmony_ci break; 174da0c48c4Sopenharmony_ci } 175da0c48c4Sopenharmony_ci if (unlikely (*code == '\0')) 176da0c48c4Sopenharmony_ci return 1; 177da0c48c4Sopenharmony_ci 178da0c48c4Sopenharmony_ci /* Clear the entire DIE structure. This signals we have not yet 179da0c48c4Sopenharmony_ci determined any of the information. */ 180da0c48c4Sopenharmony_ci memset (result, '\0', sizeof (Dwarf_Die)); 181da0c48c4Sopenharmony_ci 182da0c48c4Sopenharmony_ci /* We have the address. */ 183da0c48c4Sopenharmony_ci result->addr = addr; 184da0c48c4Sopenharmony_ci 185da0c48c4Sopenharmony_ci /* Same CU as the parent. */ 186da0c48c4Sopenharmony_ci result->cu = cu; 187da0c48c4Sopenharmony_ci 188da0c48c4Sopenharmony_ci return 0; 189da0c48c4Sopenharmony_ci} 190da0c48c4Sopenharmony_ciINTDEF(dwarf_child) 191