Coverage Report

Created: 2025-07-18 06:06

/src/elfutils/libdw/encoded-value.h
Line
Count
Source (jump to first uncovered line)
1
/* DW_EH_PE_* support for libdw unwinder.
2
   Copyright (C) 2009-2010, 2014, 2015 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
#ifndef _ENCODED_VALUE_H
30
#define _ENCODED_VALUE_H 1
31
32
#include <dwarf.h>
33
#include <stdlib.h>
34
#include "libdwP.h"
35
#include "common.h"
36
37
38
/* Returns zero if the value is omitted, the encoding is unknown or
39
   the (leb128) size cannot be determined.  */
40
static size_t __attribute__ ((unused))
41
encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
42
        uint8_t encoding, const uint8_t *p)
43
0
{
44
0
  if (encoding == DW_EH_PE_omit)
45
0
    return 0;
46
47
0
  switch (encoding & 0x07)
48
0
    {
49
0
    case DW_EH_PE_udata2:
50
0
      return 2;
51
0
    case DW_EH_PE_udata4:
52
0
      return 4;
53
0
    case DW_EH_PE_udata8:
54
0
      return 8;
55
56
0
    case DW_EH_PE_absptr:
57
0
      return e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
58
59
0
    case DW_EH_PE_uleb128:
60
0
      if (p != NULL)
61
0
  {
62
0
    const uint8_t *end = p;
63
0
    while (end < (uint8_t *) data->d_buf + data->d_size)
64
0
      if (*end++ & 0x80u)
65
0
        return end - p;
66
0
  }
67
0
      return 0;
68
69
0
    default:
70
0
      return 0;
71
0
    }
72
0
}
Unexecuted instantiation: fde.c:encoded_value_size
Unexecuted instantiation: cfi.c:encoded_value_size
Unexecuted instantiation: dwarf_getcfi_elf.c:encoded_value_size
Unexecuted instantiation: dwarf_next_cfi.c:encoded_value_size
Unexecuted instantiation: cie.c:encoded_value_size
73
74
/* Returns zero when value was read successfully, minus one otherwise.  */
75
static inline int __attribute__ ((unused))
76
__libdw_cfi_read_address_inc (const Dwarf_CFI *cache,
77
            const unsigned char **addrp,
78
            int width, Dwarf_Addr *ret)
79
0
{
80
0
  width = width ?: cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
81
82
0
  if (cache->dbg != NULL)
83
0
    return __libdw_read_address_inc (cache->dbg, IDX_debug_frame,
84
0
             addrp, width, ret);
85
86
  /* Only .debug_frame might have relocation to consider.
87
     Read plain values from .eh_frame data.  */
88
89
0
  const unsigned char *endp = cache->data->d.d_buf + cache->data->d.d_size;
90
0
  Dwarf eh_dbg = { .other_byte_order = MY_ELFDATA != cache->e_ident[EI_DATA] };
91
92
0
  if (width == 4)
93
0
    {
94
0
      if (unlikely (*addrp + 4 > endp))
95
0
  {
96
0
  invalid_data:
97
0
    __libdw_seterrno (DWARF_E_INVALID_CFI);
98
0
    return -1;
99
0
  }
100
0
      *ret = read_4ubyte_unaligned_inc (&eh_dbg, *addrp);
101
0
    }
102
0
  else
103
0
    {
104
0
      if (unlikely (*addrp + 8 > endp))
105
0
  goto invalid_data;
106
0
      *ret = read_8ubyte_unaligned_inc (&eh_dbg, *addrp);
107
0
    }
108
0
  return 0;
109
0
}
Unexecuted instantiation: fde.c:__libdw_cfi_read_address_inc
Unexecuted instantiation: cfi.c:__libdw_cfi_read_address_inc
Unexecuted instantiation: dwarf_getcfi_elf.c:__libdw_cfi_read_address_inc
Unexecuted instantiation: dwarf_next_cfi.c:__libdw_cfi_read_address_inc
Unexecuted instantiation: cie.c:__libdw_cfi_read_address_inc
110
111
/* Returns true on error, false otherwise. */
112
static bool __attribute__ ((unused))
113
read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding,
114
        const uint8_t **p, Dwarf_Addr *result)
115
0
{
116
0
  *result = 0;
117
0
  switch (encoding & 0x70)
118
0
    {
119
0
    case DW_EH_PE_absptr:
120
0
      break;
121
0
    case DW_EH_PE_pcrel:
122
0
      *result = (cache->frame_vaddr
123
0
     + (*p - (const uint8_t *) cache->data->d.d_buf));
124
0
      break;
125
0
    case DW_EH_PE_textrel:
126
      // ia64: segrel
127
0
      *result = cache->textrel;
128
0
      break;
129
0
    case DW_EH_PE_datarel:
130
      // i386: GOTOFF
131
      // ia64: gprel
132
0
      *result = cache->datarel;
133
0
      break;
134
0
    case DW_EH_PE_funcrel:  /* XXX */
135
0
      break;
136
0
    case DW_EH_PE_aligned:
137
0
      {
138
0
  const size_t size = encoded_value_size (&cache->data->d,
139
0
            cache->e_ident,
140
0
            encoding, *p);
141
0
  if (unlikely (size == 0))
142
0
    return true;
143
0
  size_t align = ((cache->frame_vaddr
144
0
       + (*p - (const uint8_t *) cache->data->d.d_buf))
145
0
      & (size - 1));
146
0
  if (align != 0)
147
0
    *p += size - align;
148
0
  break;
149
0
      }
150
151
0
    default:
152
0
      __libdw_seterrno (DWARF_E_INVALID_CFI);
153
0
      return true;
154
0
    }
155
156
0
  Dwarf_Addr value = 0;
157
0
  const unsigned char *endp = cache->data->d.d_buf + cache->data->d.d_size;
158
0
  switch (encoding & 0x0f)
159
0
    {
160
0
    case DW_EH_PE_udata2:
161
0
      if (unlikely (*p + 2 > endp))
162
0
  {
163
0
  invalid_data:
164
0
    __libdw_seterrno (DWARF_E_INVALID_CFI);
165
0
    return true;
166
0
  }
167
0
      value = read_2ubyte_unaligned_inc (cache, *p);
168
0
      break;
169
170
0
    case DW_EH_PE_sdata2:
171
0
      if (unlikely (*p + 2 > endp))
172
0
  goto invalid_data;
173
0
      value = read_2sbyte_unaligned_inc (cache, *p);
174
0
      break;
175
176
0
    case DW_EH_PE_udata4:
177
0
      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 4, &value) != 0))
178
0
  return true;
179
0
      break;
180
181
0
    case DW_EH_PE_sdata4:
182
0
      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 4, &value) != 0))
183
0
  return true;
184
0
      value = (Dwarf_Sword) (Elf32_Sword) value; /* Sign-extend.  */
185
0
      break;
186
187
0
    case DW_EH_PE_udata8:
188
0
    case DW_EH_PE_sdata8:
189
0
      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 8, &value) != 0))
190
0
  return true;
191
0
      break;
192
193
0
    case DW_EH_PE_absptr:
194
0
      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 0, &value) != 0))
195
0
  return true;
196
0
      break;
197
198
0
    case DW_EH_PE_uleb128:
199
0
      if (*p >= endp)
200
0
  goto invalid_data;
201
0
      get_uleb128 (value, *p, endp);
202
0
      break;
203
204
0
    case DW_EH_PE_sleb128:
205
0
      if (*p >= endp)
206
0
  goto invalid_data;
207
0
      get_sleb128 (value, *p, endp);
208
0
      break;
209
210
0
    default:
211
0
      __libdw_seterrno (DWARF_E_INVALID_CFI);
212
0
      return true;
213
0
    }
214
215
0
  *result += value;
216
217
0
  if (encoding & DW_EH_PE_indirect)
218
0
    {
219
0
      if (unlikely (*result < cache->frame_vaddr))
220
0
  return true;
221
0
      *result -= cache->frame_vaddr;
222
0
      size_t ptrsize = encoded_value_size (NULL, cache->e_ident,
223
0
             DW_EH_PE_absptr, NULL);
224
0
      if (unlikely (cache->data->d.d_size < ptrsize
225
0
        || *result > (cache->data->d.d_size - ptrsize)))
226
0
  return true;
227
0
      const uint8_t *ptr = cache->data->d.d_buf + *result;
228
0
      if (unlikely (__libdw_cfi_read_address_inc (cache, &ptr, 0, result)
229
0
        != 0))
230
0
  return true;
231
0
    }
232
233
0
  return false;
234
0
}
Unexecuted instantiation: fde.c:read_encoded_value
Unexecuted instantiation: cfi.c:read_encoded_value
Unexecuted instantiation: dwarf_getcfi_elf.c:read_encoded_value
Unexecuted instantiation: dwarf_next_cfi.c:read_encoded_value
Unexecuted instantiation: cie.c:read_encoded_value
235
236
#endif  /* encoded-value.h */