Branch data Line data Source code
1 : : /* Return string associated with given attribute. 2 : : Copyright (C) 2003-2010, 2013, 2017, 2018 Red Hat, Inc. 3 : : This file is part of elfutils. 4 : : 5 : : This file is free software; you can redistribute it and/or modify 6 : : it under the terms of either 7 : : 8 : : * the GNU Lesser General Public License as published by the Free 9 : : Software Foundation; either version 3 of the License, or (at 10 : : your option) any later version 11 : : 12 : : or 13 : : 14 : : * the GNU General Public License as published by the Free 15 : : Software Foundation; either version 2 of the License, or (at 16 : : your option) any later version 17 : : 18 : : or both in parallel, as here. 19 : : 20 : : elfutils is distributed in the hope that it will be useful, but 21 : : WITHOUT ANY WARRANTY; without even the implied warranty of 22 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 : : General Public License for more details. 24 : : 25 : : You should have received copies of the GNU General Public License and 26 : : the GNU Lesser General Public License along with this program. If 27 : : not, see <http://www.gnu.org/licenses/>. */ 28 : : 29 : : #ifdef HAVE_CONFIG_H 30 : : # include <config.h> 31 : : #endif 32 : : 33 : : #include <dwarf.h> 34 : : #include "libdwP.h" 35 : : 36 : : 37 : : const char * 38 : 4228316 : dwarf_formstring (Dwarf_Attribute *attrp) 39 : : { 40 : : /* Ignore earlier errors. */ 41 [ + + ]: 4228316 : if (attrp == NULL) 42 : : return NULL; 43 : : 44 : : /* We found it. Now determine where the string is stored. */ 45 [ + + ]: 3786310 : if (attrp->form == DW_FORM_string) 46 : : /* A simple inlined string. */ 47 : 162176 : return (const char *) attrp->valp; 48 : : 49 : 3624134 : Dwarf_CU *cu = attrp->cu; 50 : 3624134 : Dwarf *dbg = cu->dbg; 51 : 7248268 : Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt 52 : 3624134 : || attrp->form == DW_FORM_strp_sup) 53 [ + + ]: 3624134 : ? INTUSE(dwarf_getalt) (dbg) : dbg); 54 : : 55 [ - + ]: 3624134 : if (unlikely (dbg_ret == NULL)) 56 : : { 57 : 0 : __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK); 58 : 0 : return NULL; 59 : : } 60 : : 61 : 7248268 : Elf_Data *data = ((attrp->form == DW_FORM_line_strp) 62 : : ? dbg_ret->sectiondata[IDX_debug_line_str] 63 [ + + ]: 3624134 : : dbg_ret->sectiondata[IDX_debug_str]); 64 : 7248268 : size_t data_size = ((attrp->form == DW_FORM_line_strp) 65 : : ? dbg_ret->string_section_size[STR_SCN_IDX_debug_line_str] 66 [ + + ]: 3624134 : : dbg_ret->string_section_size[STR_SCN_IDX_debug_str]); 67 [ - + ]: 3624134 : if (data == NULL) 68 : : { 69 [ # # ]: 0 : __libdw_seterrno ((attrp->form == DW_FORM_line_strp) 70 : : ? DWARF_E_NO_DEBUG_LINE_STR 71 : : : DWARF_E_NO_DEBUG_STR); 72 : 0 : return NULL; 73 : : } 74 : : 75 : 3624134 : uint64_t off; 76 : 3624134 : if (attrp->form == DW_FORM_strp 77 [ + + ]: 3624134 : || attrp->form == DW_FORM_GNU_strp_alt 78 [ - + ]: 1319612 : || attrp->form == DW_FORM_strp_sup) 79 : : { 80 [ - + ]: 2304522 : if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu), 81 : 2304522 : attrp->valp, cu->offset_size, &off, 82 : : IDX_debug_str, 1)) 83 : : return NULL; 84 : : } 85 [ + + ]: 1319612 : else if (attrp->form == DW_FORM_line_strp) 86 : : { 87 [ - + ]: 1316210 : if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu), 88 : 1316210 : attrp->valp, cu->offset_size, &off, 89 : : IDX_debug_line_str, 1)) 90 : : return NULL; 91 : : } 92 : : else 93 : : { 94 : 3402 : Dwarf_Word idx; 95 : 3402 : const unsigned char *datap = attrp->valp; 96 : 3402 : const unsigned char *endp = cu->endp; 97 [ + + - - : 3402 : switch (attrp->form) - - ] 98 : : { 99 : 3302 : case DW_FORM_strx: 100 : : case DW_FORM_GNU_str_index: 101 [ - + ]: 3302 : if (datap >= endp) 102 : : { 103 : 0 : invalid: 104 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 105 : 0 : return NULL; 106 : : } 107 : 3302 : get_uleb128 (idx, datap, endp); 108 : 3302 : break; 109 : : 110 : 100 : case DW_FORM_strx1: 111 [ - + ]: 100 : if (datap >= endp - 1) 112 : 0 : goto invalid; 113 : 100 : idx = *datap; 114 : 100 : break; 115 : : 116 : 0 : case DW_FORM_strx2: 117 [ # # ]: 0 : if (datap >= endp - 2) 118 : 0 : goto invalid; 119 [ # # ]: 0 : idx = read_2ubyte_unaligned (dbg, datap); 120 : : break; 121 : : 122 : 0 : case DW_FORM_strx3: 123 [ # # ]: 0 : if (datap >= endp - 3) 124 : 0 : goto invalid; 125 : 0 : idx = read_3ubyte_unaligned (dbg, datap); 126 : 0 : break; 127 : : 128 : 0 : case DW_FORM_strx4: 129 [ # # ]: 0 : if (datap >= endp - 4) 130 : 0 : goto invalid; 131 [ # # ]: 0 : idx = read_4ubyte_unaligned (dbg, datap); 132 : : break; 133 : : 134 : 0 : default: 135 : 0 : __libdw_seterrno (DWARF_E_NO_STRING); 136 : 0 : return NULL; 137 : : } 138 : : 139 : : /* So we got an index in the .debug_str_offsets. Lets see if it 140 : : is valid and we can get the actual .debug_str offset. */ 141 : 3402 : Dwarf_Off str_off = __libdw_cu_str_off_base (cu); 142 [ + - ]: 3402 : if (str_off == (Dwarf_Off) -1) 143 : : return NULL; 144 : : 145 [ - + ]: 3402 : if (dbg->sectiondata[IDX_debug_str_offsets] == NULL) 146 : : { 147 : 0 : __libdw_seterrno (DWARF_E_NO_STR_OFFSETS); 148 : 0 : return NULL; 149 : : } 150 : : 151 : : /* The section should at least contain room for one offset. */ 152 : 3402 : int offset_size = cu->offset_size; 153 [ - + ]: 3402 : if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size) 154 : : { 155 : 0 : invalid_offset: 156 : 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET); 157 : 0 : return NULL; 158 : : } 159 : : 160 : : /* And the base offset should be at least inside the section. */ 161 : 3402 : if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size 162 [ - + ]: 3402 : - offset_size)) 163 : 0 : goto invalid_offset; 164 : : 165 : 3402 : size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size 166 : 3402 : - offset_size - str_off) / offset_size; 167 [ - + ]: 3402 : if (idx > max_idx) 168 : 0 : goto invalid_offset; 169 : : 170 : 3402 : datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf 171 : 3402 : + str_off + (idx * offset_size)); 172 [ + - ]: 3402 : if (offset_size == 4) 173 [ - + ]: 3402 : off = read_4ubyte_unaligned (dbg, datap); 174 : : else 175 [ # # ]: 0 : off = read_8ubyte_unaligned (dbg, datap); 176 : : } 177 : : 178 [ - + ]: 3624134 : if (off >= data_size) 179 : 0 : goto invalid_offset; 180 : : 181 : 3624134 : return (const char *) data->d_buf + off; 182 : : } 183 : : INTDEF(dwarf_formstring)