Branch data Line data Source code
1 : : /* Get abbreviation at given offset. 2 : : Copyright (C) 2003, 2004, 2005, 2006, 2014, 2017 Red Hat, Inc. 3 : : Copyright (C) 2025 Mark J. Wielaard <mark@klomp.org> 4 : : This file is part of elfutils. 5 : : Written by Ulrich Drepper <drepper@redhat.com>, 2003. 6 : : 7 : : This file is free software; you can redistribute it and/or modify 8 : : it under the terms of either 9 : : 10 : : * the GNU Lesser General Public License as published by the Free 11 : : Software Foundation; either version 3 of the License, or (at 12 : : your option) any later version 13 : : 14 : : or 15 : : 16 : : * the GNU General Public License as published by the Free 17 : : Software Foundation; either version 2 of the License, or (at 18 : : your option) any later version 19 : : 20 : : or both in parallel, as here. 21 : : 22 : : elfutils is distributed in the hope that it will be useful, but 23 : : WITHOUT ANY WARRANTY; without even the implied warranty of 24 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 25 : : General Public License for more details. 26 : : 27 : : You should have received copies of the GNU General Public License and 28 : : the GNU Lesser General Public License along with this program. If 29 : : not, see <http://www.gnu.org/licenses/>. */ 30 : : 31 : : #ifdef HAVE_CONFIG_H 32 : : # include <config.h> 33 : : #endif 34 : : 35 : : #include <dwarf.h> 36 : : #include "libdwP.h" 37 : : 38 : : 39 : : Dwarf_Abbrev * 40 : : internal_function 41 : 2762132 : __libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, Dwarf_Off offset, 42 : : size_t *lengthp) 43 : : { 44 : : /* Don't fail if there is not .debug_abbrev section. */ 45 [ - + ]: 2762132 : if (dbg->sectiondata[IDX_debug_abbrev] == NULL) 46 : : return NULL; 47 : : 48 [ - + ]: 2762132 : if (offset >= dbg->sectiondata[IDX_debug_abbrev]->d_size) 49 : : { 50 : 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET); 51 : 0 : return NULL; 52 : : } 53 : : 54 : 2762132 : const unsigned char *abbrevp 55 : 2762132 : = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset; 56 : : 57 [ + + ]: 2762132 : if (*abbrevp == '\0') 58 : : /* We are past the last entry. */ 59 : : return DWARF_END_ABBREV; 60 : : 61 : : /* 7.5.3 Abbreviations Tables 62 : : 63 : : [...] Each declaration begins with an unsigned LEB128 number 64 : : representing the abbreviation code itself. [...] The 65 : : abbreviation code is followed by another unsigned LEB128 66 : : number that encodes the entry's tag. [...] 67 : : 68 : : [...] Following the tag encoding is a 1-byte value that 69 : : determines whether a debugging information entry using this 70 : : abbreviation has child entries or not. [...] 71 : : 72 : : [...] Finally, the child encoding is followed by a series of 73 : : attribute specifications. Each attribute specification 74 : : consists of two parts. The first part is an unsigned LEB128 75 : : number representing the attribute's name. The second part is 76 : : an unsigned LEB128 number representing the attribute's form. */ 77 : 2758584 : const unsigned char *end = (dbg->sectiondata[IDX_debug_abbrev]->d_buf 78 : : + dbg->sectiondata[IDX_debug_abbrev]->d_size); 79 : 2758584 : const unsigned char *start_abbrevp = abbrevp; 80 : 2758584 : unsigned int code; 81 : : // We start off with abbrevp at offset, which is checked above. 82 : 2758584 : get_uleb128 (code, abbrevp, end); 83 : : 84 : : /* Check whether this code is already in the hash table. */ 85 : 2758584 : bool foundit = false; 86 : 2758584 : Dwarf_Abbrev *abb = NULL; 87 [ + + ]: 2758584 : if (cu == NULL 88 [ + + ]: 2597764 : || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code)) == NULL) 89 [ + + ]: 2758572 : abb = libdw_typed_alloc (dbg, Dwarf_Abbrev); 90 : : else 91 : : { 92 : 12 : foundit = true; 93 : : 94 [ - + ]: 12 : if (unlikely (abb->offset != offset)) 95 : : { 96 : : /* A duplicate abbrev code at a different offset, 97 : : that should never happen. */ 98 : 0 : invalid: 99 [ # # ]: 0 : if (! foundit) 100 : 0 : libdw_typed_unalloc (dbg, Dwarf_Abbrev); 101 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 102 : 0 : return NULL; 103 : : } 104 : : 105 : : /* If the caller doesn't need the length we are done. */ 106 [ - + ]: 12 : if (lengthp == NULL) 107 : 0 : goto out; 108 : : } 109 : : 110 : : /* If there is already a value in the hash table we are going to 111 : : overwrite its content. This must not be a problem, since the 112 : : content better be the same. */ 113 : 2758584 : abb->code = code; 114 [ - + ]: 2758584 : if (abbrevp >= end) 115 : 0 : goto invalid; 116 : 2758584 : get_uleb128 (abb->tag, abbrevp, end); 117 [ - + ]: 2758584 : if (abbrevp + 1 >= end) 118 : 0 : goto invalid; 119 : 2758584 : abb->has_children = *abbrevp++ == DW_CHILDREN_yes; 120 : 2758584 : abb->attrp = (unsigned char *) abbrevp; 121 : 2758584 : abb->offset = offset; 122 : : 123 : : /* Skip over all the attributes and check rest of the abbrev is valid. */ 124 : 15518120 : unsigned int attrname; 125 : 15518120 : unsigned int attrform; 126 : 15518120 : do 127 : : { 128 [ - + ]: 15518120 : if (abbrevp >= end) 129 : 0 : goto invalid; 130 : 15518120 : get_uleb128 (attrname, abbrevp, end); 131 [ - + ]: 15518120 : if (abbrevp >= end) 132 : 0 : goto invalid; 133 : 15518120 : get_uleb128 (attrform, abbrevp, end); 134 [ + + ]: 15518120 : if (attrform == DW_FORM_implicit_const) 135 : : { 136 : 1131870 : int64_t formval __attribute__((__unused__)); 137 [ - + ]: 1131870 : if (abbrevp >= end) 138 : 0 : goto invalid; 139 : 1131870 : get_sleb128 (formval, abbrevp, end); 140 : : } 141 : : } 142 [ + + ]: 15518120 : while (attrname != 0 || attrform != 0); 143 : : 144 : : /* Return the length to the caller if she asked for it. */ 145 [ + - ]: 2758584 : if (lengthp != NULL) 146 : 2758584 : *lengthp = abbrevp - start_abbrevp; 147 : : 148 : : /* Add the entry to the hash table. */ 149 [ + + ]: 2758584 : if (cu != NULL && ! foundit) 150 [ + - ]: 2597752 : if (Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb) == -1) 151 : : { 152 : : /* The entry was already in the table, remove the one we just 153 : : created and get the one already inserted. */ 154 : 0 : libdw_typed_unalloc (dbg, Dwarf_Abbrev); 155 : 0 : abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code); 156 : : } 157 : : 158 : 2758584 : out: 159 : : return abb; 160 : : } 161 : : 162 : : 163 : : Dwarf_Abbrev * 164 : 2520 : dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset, size_t *lengthp) 165 : : { 166 [ + - + + ]: 2520 : if (die == NULL || die->cu == NULL) 167 : : return NULL; 168 : : 169 : 150 : Dwarf_CU *cu = die->cu; 170 : 150 : Dwarf *dbg = cu->dbg; 171 : 150 : Dwarf_Off abbrev_offset = cu->orig_abbrev_offset; 172 : 150 : Elf_Data *data = dbg->sectiondata[IDX_debug_abbrev]; 173 [ - + ]: 150 : if (data == NULL) 174 : : return NULL; 175 : : 176 [ + + ]: 150 : if (offset >= data->d_size - abbrev_offset) 177 : : { 178 : 12 : __libdw_seterrno (DWARF_E_INVALID_OFFSET); 179 : 12 : return NULL; 180 : : } 181 : : 182 : 138 : return __libdw_getabbrev (dbg, cu, abbrev_offset + offset, lengthp); 183 : : }