Branch data Line data Source code
1 : : /* Advance to next CFI entry.
2 : : Copyright (C) 2009-2010, 2014 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 "cfi.h"
34 : : #include "encoded-value.h"
35 : :
36 : : #include <string.h>
37 : :
38 : :
39 : : int
40 : 64368 : dwarf_next_cfi (const unsigned char e_ident[],
41 : : Elf_Data *data,
42 : : bool eh_frame_p,
43 : : Dwarf_Off off,
44 : : Dwarf_Off *next_off,
45 : : Dwarf_CFI_Entry *entry)
46 : : {
47 : : /* Dummy struct for memory-access.h macros. */
48 : 64368 : BYTE_ORDER_DUMMY (dw, e_ident);
49 : :
50 : : /* If we reached the end before don't do anything. */
51 [ + + ]: 64368 : if (off == (Dwarf_Off) -1l
52 : : /* Make sure there is enough space in the .debug_frame section
53 : : for at least the initial word. We cannot test the rest since
54 : : we don't know yet whether this is a 64-bit object or not. */
55 [ + + ]: 64162 : || unlikely (off + 4 >= data->d_size))
56 : : {
57 : 284 : done:
58 : 286 : *next_off = (Dwarf_Off) -1l;
59 : 286 : return 1;
60 : : }
61 : :
62 : : /* This points into the .debug_frame section at the start of the entry. */
63 : 64084 : const uint8_t *bytes = data->d_buf + off;
64 : 64084 : const uint8_t *limit = data->d_buf + data->d_size;
65 : :
66 : : /* The format of a CFI entry is described in DWARF3 6.4.1:
67 : : */
68 : :
69 [ + + ]: 64084 : uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
70 : 64084 : size_t offset_size = 4;
71 [ - + ]: 64084 : if (length == DWARF3_LENGTH_64_BIT)
72 : : {
73 : : /* This is the 64-bit DWARF format. */
74 : 0 : offset_size = 8;
75 [ # # ]: 0 : if (unlikely (limit - bytes < 8))
76 : : {
77 : 0 : invalid:
78 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
79 : 0 : return -1;
80 : : }
81 [ # # ]: 0 : length = read_8ubyte_unaligned_inc (&dw, bytes);
82 : : }
83 : :
84 : : /* Not explicitly in the DWARF spec, but mentioned in the LSB exception
85 : : frames (.eh_frame) spec. If Length contains the value 0, then this
86 : : CIE shall be considered a terminator and processing shall end. */
87 [ + + ]: 64084 : if (length == 0)
88 : 2 : goto done;
89 : :
90 [ + - ]: 64082 : if (unlikely ((uint64_t) (limit - bytes) < length)
91 [ - + ]: 64082 : || unlikely (length < offset_size + 1))
92 : 0 : goto invalid;
93 : :
94 : : /* Now we know how large the entry is. Note the trick in the
95 : : computation. If the offset_size is 4 the '- 4' term undoes the
96 : : '2 *'. If offset_size is 8 this term computes the size of the
97 : : escape value plus the 8 byte offset. */
98 : 64082 : *next_off = off + (2 * offset_size - 4) + length;
99 : :
100 : 64082 : limit = bytes + length;
101 : :
102 : 64082 : const uint8_t *const cie_pointer_start = bytes;
103 [ - + ]: 64082 : if (offset_size == 8)
104 [ # # ]: 0 : entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
105 : : else
106 : : {
107 [ + + ]: 64082 : entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
108 : : /* Canonicalize the 32-bit CIE_ID value to 64 bits. */
109 [ + + + + ]: 64082 : if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
110 : 140 : entry->cie.CIE_id = DW_CIE_ID_64;
111 : : }
112 [ - + ]: 366 : if (eh_frame_p)
113 : : {
114 : : /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */
115 [ + + ]: 63716 : if (entry->cie.CIE_id == 0)
116 : 12732 : entry->cie.CIE_id = DW_CIE_ID_64;
117 : : else
118 : : {
119 : : /* In .eh_frame format, a CIE pointer is the distance from where
120 : : it appears back to the beginning of the CIE. */
121 : 50984 : ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
122 [ + - ]: 50984 : if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
123 [ - + ]: 50984 : || unlikely (pos <= (ptrdiff_t) offset_size))
124 : 0 : goto invalid;
125 : 50984 : entry->cie.CIE_id = pos - entry->cie.CIE_id;
126 : : }
127 : : }
128 : :
129 [ + + ]: 64082 : if (entry->cie.CIE_id == DW_CIE_ID_64)
130 : : {
131 : : /* Read the version stamp. Always an 8-bit value. */
132 : 12872 : uint8_t version = *bytes++;
133 : :
134 [ - + - - : 12872 : if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
- - ]
135 : 0 : goto invalid;
136 : :
137 : 12872 : entry->cie.augmentation = (const char *) bytes;
138 : :
139 : 12872 : bytes = memchr (bytes, '\0', limit - bytes);
140 [ - + ]: 12872 : if (unlikely (bytes == NULL))
141 : 0 : goto invalid;
142 : 12872 : ++bytes;
143 : :
144 : : /* The address size for CFI is implicit in the ELF class. */
145 [ + + ]: 12872 : uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
146 : 12872 : uint_fast8_t segment_size = 0;
147 [ - + ]: 12872 : if (version >= 4)
148 : : {
149 [ # # ]: 0 : if (unlikely (limit - bytes < 5))
150 : 0 : goto invalid;
151 : : /* XXX We don't actually support address_size not matching the class.
152 : : To do so, we'd have to return it here so that intern_new_cie
153 : : could use it choose a specific fde_encoding. */
154 [ # # ]: 0 : if (unlikely (*bytes != address_size))
155 : : {
156 : 0 : __libdw_seterrno (DWARF_E_VERSION);
157 : 0 : return -1;
158 : : }
159 : 0 : address_size = *bytes++;
160 : 0 : segment_size = *bytes++;
161 : : /* We don't actually support segment selectors. We'd have to
162 : : roll this into the fde_encoding bits or something. */
163 [ # # ]: 0 : if (unlikely (segment_size != 0))
164 : : {
165 : 0 : __libdw_seterrno (DWARF_E_VERSION);
166 : 0 : return -1;
167 : : }
168 : : }
169 : :
170 : 12872 : const char *ap = entry->cie.augmentation;
171 : :
172 : : /* g++ v2 "eh" has pointer immediately following augmentation string,
173 : : so it must be handled first. */
174 [ - + - - ]: 12872 : if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
175 : : {
176 : 0 : ap += 2;
177 : 0 : bytes += address_size;
178 : : }
179 : :
180 [ - + ]: 12872 : if (bytes >= limit)
181 : 0 : goto invalid;
182 : 12872 : get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
183 : :
184 [ - + ]: 12872 : if (bytes >= limit)
185 : 0 : goto invalid;
186 : 12872 : get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
187 : :
188 [ - + ]: 12872 : if (bytes >= limit)
189 : 0 : goto invalid;
190 : :
191 [ - + ]: 12872 : if (version >= 3) /* DWARF 3+ */
192 : 0 : get_uleb128 (entry->cie.return_address_register, bytes, limit);
193 : : else /* DWARF 2 */
194 : 12872 : entry->cie.return_address_register = *bytes++;
195 : :
196 : 12872 : entry->cie.fde_augmentation_data_size = 0;
197 : 12872 : entry->cie.augmentation_data = bytes;
198 : 12872 : bool sized_augmentation = *ap == 'z';
199 [ + + ]: 12872 : if (sized_augmentation)
200 : : {
201 : 12730 : ++ap;
202 [ - + ]: 12730 : if (bytes >= limit)
203 : 0 : goto invalid;
204 : 12730 : get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
205 [ - + ]: 12730 : if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
206 : 0 : goto invalid;
207 : 12730 : entry->cie.augmentation_data = bytes;
208 : : }
209 : :
210 [ + + ]: 25688 : for (; *ap != '\0'; ++ap)
211 : : {
212 : 12816 : uint8_t encoding;
213 [ + + + + : 12816 : switch (*ap)
- ]
214 : : {
215 : 44 : case 'L':
216 [ + - ]: 44 : if (sized_augmentation)
217 : : {
218 : : /* Skip LSDA pointer encoding byte. */
219 : 44 : encoding = *bytes++;
220 : 88 : entry->cie.fde_augmentation_data_size
221 : 44 : += encoded_value_size (data, e_ident, encoding, NULL);
222 : 44 : continue;
223 : : }
224 : : break;
225 : 12714 : case 'R':
226 [ + - ]: 12714 : if (sized_augmentation)
227 : : {
228 : : /* Skip FDE address encoding byte. */
229 : 12714 : bytes++;
230 : 12714 : continue;
231 : : }
232 : : break;
233 : 52 : case 'P':
234 [ + - ]: 52 : if (sized_augmentation)
235 : : {
236 : : /* Skip encoded personality routine pointer. */
237 : 52 : encoding = *bytes++;
238 : 52 : bytes += encoded_value_size (data, e_ident, encoding, bytes);
239 : 52 : continue;
240 : : }
241 : : break;
242 : 6 : case 'S':
243 [ + - ]: 6 : if (sized_augmentation)
244 : : /* Skip signal-frame flag. */
245 : 6 : continue;
246 : : break;
247 : : default:
248 : : /* Unknown augmentation string. initial_instructions might
249 : : actually start with some augmentation data. */
250 : : break;
251 : : }
252 : : break;
253 : : }
254 [ + + ]: 12872 : if (! sized_augmentation)
255 : 142 : entry->cie.augmentation_data_size = bytes - entry->cie.augmentation_data;
256 : : else
257 : : {
258 [ - + ]: 12730 : if (bytes > entry->cie.augmentation_data + entry->cie.augmentation_data_size)
259 : 0 : goto invalid;
260 : 12730 : bytes = entry->cie.augmentation_data + entry->cie.augmentation_data_size;
261 : : }
262 : :
263 : 12872 : entry->cie.initial_instructions = bytes;
264 : 12872 : entry->cie.initial_instructions_end = limit;
265 : : }
266 : : else
267 : : {
268 : 51210 : entry->fde.start = bytes;
269 : 51210 : entry->fde.end = limit;
270 : : }
271 : :
272 : : return 0;
273 : : }
274 : : INTDEF (dwarf_next_cfi)
|