Branch data Line data Source code
1 : : /* Get attributes of the DIE. 2 : : Copyright (C) 2004, 2005, 2008, 2009, 2014, 2017 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2004. 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 : : 36 : : 37 : : ptrdiff_t 38 : 3310666 : dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *), 39 : : void *arg, ptrdiff_t offset) 40 : : { 41 [ - + ]: 3310666 : if (die == NULL) 42 : : return -1l; 43 : : 44 [ + - ]: 3310666 : if (unlikely (offset == 1)) 45 : : return 1; 46 : : 47 : 3310666 : const unsigned char *die_addr = NULL; 48 : : 49 : : /* Find the abbreviation entry. */ 50 : 3310666 : Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &die_addr); 51 : : 52 [ - + ]: 3310666 : if (unlikely (abbrevp == DWARF_END_ABBREV)) 53 : : { 54 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 55 : 0 : return -1l; 56 : : } 57 : : 58 : 3310666 : const unsigned char *endp = die->cu->endp; 59 : : 60 : : /* This is where the attributes start. */ 61 : 3310666 : const unsigned char *attrp = abbrevp->attrp; 62 : 3310666 : const unsigned char *const offset_attrp = abbrevp->attrp + offset; 63 : : 64 : : /* Go over the list of attributes. */ 65 : 28630498 : while (1) 66 : 12659916 : { 67 : : /* Get attribute name and form. Dwarf_Abbrev was checked when 68 : : created, so we can read unchecked. */ 69 : 15970582 : Dwarf_Attribute attr; 70 : 15970582 : const unsigned char *remembered_attrp = attrp; 71 : : 72 : 15970582 : get_uleb128_unchecked (attr.code, attrp); 73 : 15970582 : get_uleb128_unchecked (attr.form, attrp); 74 : : 75 : : /* We can stop if we found the attribute with value zero. */ 76 [ + + ]: 15970582 : if (attr.code == 0 && attr.form == 0) 77 : : /* Do not return 0 here - there would be no way to 78 : : distinguish this value from the attribute at offset 0. 79 : : Instead we return +1 which would never be a valid 80 : : offset of an attribute. */ 81 : 3310666 : return 1l; 82 : : 83 [ + + ]: 12659916 : if (attr.form == DW_FORM_indirect) 84 : : { 85 : 6 : get_uleb128 (attr.form, die_addr, endp); 86 [ - + ]: 6 : if (attr.form == DW_FORM_indirect || 87 : : attr.form == DW_FORM_implicit_const) 88 : : { 89 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 90 : 0 : return -1l; 91 : : } 92 : : } 93 : : 94 : : /* If we are not to OFFSET_ATTRP yet, we just have to skip 95 : : the values of the intervening attributes. */ 96 [ + - ]: 12659916 : if (remembered_attrp >= offset_attrp) 97 : : { 98 : : /* Fill in the rest. */ 99 [ + + ]: 12659916 : if (attr.form == DW_FORM_implicit_const) 100 : 614286 : attr.valp = (unsigned char *) attrp; 101 : : else 102 : 12045630 : attr.valp = (unsigned char *) die_addr; 103 : 12659916 : attr.cu = die->cu; 104 : : 105 : : /* Now call the callback function. */ 106 [ - + ]: 12659916 : if (callback (&attr, arg) != DWARF_CB_OK) 107 : : /* Return the offset of the start of the attribute, so that 108 : : dwarf_getattrs() can be restarted from this point if the 109 : : caller so desires. */ 110 : 0 : return remembered_attrp - abbrevp->attrp; 111 : : } 112 : : 113 : : /* Skip over the rest of this attribute (if there is any). */ 114 [ + - ]: 12659916 : if (attr.form != 0) 115 : : { 116 : 12659916 : size_t len = __libdw_form_val_len (die->cu, attr.form, die_addr); 117 [ + - ]: 12659916 : if (unlikely (len == (size_t) -1l)) 118 : : /* Something wrong with the file. */ 119 : : return -1l; 120 : : 121 : : // __libdw_form_val_len will have done a bounds check. 122 : 12659916 : die_addr += len; 123 : : 124 [ + + ]: 12659916 : if (attr.form == DW_FORM_implicit_const) 125 : : { 126 : 614286 : int64_t attr_value __attribute__((__unused__)); 127 : 614286 : get_sleb128_unchecked (attr_value, attrp); 128 : : } 129 : : } 130 : : } 131 : : /* NOTREACHED */ 132 : : }