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