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