Coverage Report

Created: 2025-11-06 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/elfutils/libdw/dwarf_formstring.c
Line
Count
Source
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
dwarf_formstring (Dwarf_Attribute *attrp)
39
0
{
40
  /* Ignore earlier errors.  */
41
0
  if (attrp == NULL)
42
0
    return NULL;
43
44
  /* We found it.  Now determine where the string is stored.  */
45
0
  if (attrp->form == DW_FORM_string)
46
    /* A simple inlined string.  */
47
0
    return (const char *) attrp->valp;
48
49
0
  Dwarf_CU *cu = attrp->cu;
50
0
  Dwarf *dbg = cu->dbg;
51
0
  Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt
52
0
         || attrp->form == DW_FORM_strp_sup)
53
0
        ? INTUSE(dwarf_getalt) (dbg) : dbg);
54
55
0
  if (unlikely (dbg_ret == NULL))
56
0
    {
57
0
      __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
58
0
      return NULL;
59
0
    }
60
61
0
  Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
62
0
        ? dbg_ret->sectiondata[IDX_debug_line_str]
63
0
        : dbg_ret->sectiondata[IDX_debug_str]);
64
0
  size_t data_size = ((attrp->form == DW_FORM_line_strp)
65
0
          ? dbg_ret->string_section_size[STR_SCN_IDX_debug_line_str]
66
0
          : dbg_ret->string_section_size[STR_SCN_IDX_debug_str]);
67
0
  if (data == NULL)
68
0
    {
69
0
      __libdw_seterrno ((attrp->form == DW_FORM_line_strp)
70
0
      ? DWARF_E_NO_DEBUG_LINE_STR
71
0
      : DWARF_E_NO_DEBUG_STR);
72
0
      return NULL;
73
0
    }
74
75
0
  uint64_t off;
76
0
  if (attrp->form == DW_FORM_strp
77
0
      || attrp->form == DW_FORM_GNU_strp_alt
78
0
      || attrp->form == DW_FORM_strp_sup)
79
0
    {
80
0
      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
81
0
             attrp->valp, cu->offset_size, &off,
82
0
             IDX_debug_str, 1))
83
0
  return NULL;
84
0
    }
85
0
  else if (attrp->form == DW_FORM_line_strp)
86
0
    {
87
0
      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
88
0
             attrp->valp, cu->offset_size, &off,
89
0
             IDX_debug_line_str, 1))
90
0
  return NULL;
91
0
    }
92
0
  else
93
0
    {
94
0
      Dwarf_Word idx;
95
0
      const unsigned char *datap = attrp->valp;
96
0
      const unsigned char *endp = cu->endp;
97
0
      switch (attrp->form)
98
0
  {
99
0
  case DW_FORM_strx:
100
0
  case DW_FORM_GNU_str_index:
101
0
    if (datap >= endp)
102
0
      {
103
0
      invalid:
104
0
        __libdw_seterrno (DWARF_E_INVALID_DWARF);
105
0
        return NULL;
106
0
      }
107
0
    get_uleb128 (idx, datap, endp);
108
0
    break;
109
110
0
  case DW_FORM_strx1:
111
0
    if (datap >= endp - 1)
112
0
      goto invalid;
113
0
    idx = *datap;
114
0
    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
0
    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
0
    break;
133
134
0
  default:
135
0
    __libdw_seterrno (DWARF_E_NO_STRING);
136
0
    return NULL;
137
0
  }
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
0
      Dwarf_Off str_off = __libdw_cu_str_off_base (cu);
142
0
      if (str_off == (Dwarf_Off) -1)
143
0
  return NULL;
144
145
0
      if (dbg->sectiondata[IDX_debug_str_offsets] == NULL)
146
0
  {
147
0
    __libdw_seterrno (DWARF_E_NO_STR_OFFSETS);
148
0
    return NULL;
149
0
  }
150
151
      /* The section should at least contain room for one offset.  */
152
0
      int offset_size = cu->offset_size;
153
0
      if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size)
154
0
  {
155
0
  invalid_offset:
156
0
    __libdw_seterrno (DWARF_E_INVALID_OFFSET);
157
0
    return NULL;
158
0
  }
159
160
      /* And the base offset should be at least inside the section.  */
161
0
      if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size
162
0
         - offset_size))
163
0
  goto invalid_offset;
164
165
0
      size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size
166
0
      - offset_size - str_off) / offset_size;
167
0
      if (idx > max_idx)
168
0
  goto invalid_offset;
169
170
0
      datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf
171
0
         + str_off + (idx * offset_size));
172
0
      if (offset_size == 4)
173
0
  off = read_4ubyte_unaligned (dbg, datap);
174
0
      else
175
0
  off = read_8ubyte_unaligned (dbg, datap);
176
0
    }
177
178
0
  if (off >= data_size)
179
0
    goto invalid_offset;
180
181
0
  return (const char *) data->d_buf + off;
182
0
}
183
INTDEF(dwarf_formstring)