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 17646 : 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 17646 : BYTE_ORDER_DUMMY (dw, e_ident);
49 :
50 : /* If we reached the end before don't do anything. */
51 17646 : 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 17549 : || unlikely (off + 4 >= data->d_size))
56 : {
57 117 : *next_off = (Dwarf_Off) -1l;
58 117 : return 1;
59 : }
60 :
61 : /* This points into the .debug_frame section at the start of the entry. */
62 17529 : const uint8_t *bytes = data->d_buf + off;
63 17529 : const uint8_t *limit = data->d_buf + data->d_size;
64 :
65 : /* The format of a CFI entry is described in DWARF3 6.4.1:
66 : */
67 :
68 21975 : uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
69 17529 : size_t offset_size = 4;
70 17529 : if (length == DWARF3_LENGTH_64_BIT)
71 : {
72 : /* This is the 64-bit DWARF format. */
73 0 : offset_size = 8;
74 0 : if (unlikely (limit - bytes < 8))
75 : {
76 0 : invalid:
77 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
78 0 : return -1;
79 : }
80 0 : length = read_8ubyte_unaligned_inc (&dw, bytes);
81 : }
82 17529 : if (unlikely ((uint64_t) (limit - bytes) < length)
83 17529 : || unlikely (length < offset_size + 1))
84 : goto invalid;
85 :
86 : /* Now we know how large the entry is. Note the trick in the
87 : computation. If the offset_size is 4 the '- 4' term undoes the
88 : '2 *'. If offset_size is 8 this term computes the size of the
89 : escape value plus the 8 byte offset. */
90 17529 : *next_off = off + (2 * offset_size - 4) + length;
91 :
92 17529 : limit = bytes + length;
93 :
94 17529 : const uint8_t *const cie_pointer_start = bytes;
95 17529 : if (offset_size == 8)
96 0 : entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
97 : else
98 : {
99 21975 : entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
100 : /* Canonicalize the 32-bit CIE_ID value to 64 bits. */
101 17529 : if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
102 31 : entry->cie.CIE_id = DW_CIE_ID_64;
103 : }
104 17529 : if (eh_frame_p)
105 : {
106 : /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */
107 17414 : if (entry->cie.CIE_id == 0)
108 129 : entry->cie.CIE_id = DW_CIE_ID_64;
109 : else
110 : {
111 : /* In .eh_frame format, a CIE pointer is the distance from where
112 : it appears back to the beginning of the CIE. */
113 17285 : ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
114 17285 : if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
115 17285 : || unlikely (pos <= (ptrdiff_t) offset_size))
116 : goto invalid;
117 17285 : entry->cie.CIE_id = pos - entry->cie.CIE_id;
118 : }
119 : }
120 :
121 17529 : if (entry->cie.CIE_id == DW_CIE_ID_64)
122 : {
123 : /* Read the version stamp. Always an 8-bit value. */
124 160 : uint8_t version = *bytes++;
125 :
126 160 : if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
127 : goto invalid;
128 :
129 160 : entry->cie.augmentation = (const char *) bytes;
130 :
131 160 : bytes = memchr (bytes, '\0', limit - bytes);
132 160 : if (unlikely (bytes == NULL))
133 : goto invalid;
134 160 : ++bytes;
135 :
136 : /* The address size for CFI is implicit in the ELF class. */
137 160 : uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
138 160 : uint_fast8_t segment_size = 0;
139 160 : if (version >= 4)
140 : {
141 0 : if (unlikely (limit - bytes < 5))
142 : goto invalid;
143 : /* XXX We don't actually support address_size not matching the class.
144 : To do so, we'd have to return it here so that intern_new_cie
145 : could use it choose a specific fde_encoding. */
146 0 : if (unlikely (*bytes != address_size))
147 : {
148 0 : __libdw_seterrno (DWARF_E_VERSION);
149 0 : return -1;
150 : }
151 0 : address_size = *bytes++;
152 0 : segment_size = *bytes++;
153 : /* We don't actually support segment selectors. We'd have to
154 : roll this into the fde_encoding bits or something. */
155 0 : if (unlikely (segment_size != 0))
156 : {
157 0 : __libdw_seterrno (DWARF_E_VERSION);
158 0 : return -1;
159 : }
160 : }
161 :
162 160 : const char *ap = entry->cie.augmentation;
163 :
164 : /* g++ v2 "eh" has pointer immediately following augmentation string,
165 : so it must be handled first. */
166 160 : if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
167 : {
168 0 : ap += 2;
169 0 : bytes += address_size;
170 : }
171 :
172 160 : if (bytes >= limit)
173 : goto invalid;
174 160 : get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
175 :
176 160 : if (bytes >= limit)
177 : goto invalid;
178 160 : get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
179 :
180 160 : if (bytes >= limit)
181 : goto invalid;
182 :
183 160 : if (version >= 3) /* DWARF 3+ */
184 0 : get_uleb128 (entry->cie.return_address_register, bytes, limit);
185 : else /* DWARF 2 */
186 160 : entry->cie.return_address_register = *bytes++;
187 :
188 : /* If we have sized augmentation data,
189 : we don't need to grok it all. */
190 160 : entry->cie.fde_augmentation_data_size = 0;
191 160 : bool sized_augmentation = *ap == 'z';
192 160 : if (sized_augmentation)
193 : {
194 129 : if (bytes >= limit)
195 : goto invalid;
196 129 : get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
197 129 : if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
198 : goto invalid;
199 129 : entry->cie.augmentation_data = bytes;
200 129 : bytes += entry->cie.augmentation_data_size;
201 : }
202 : else
203 : {
204 31 : entry->cie.augmentation_data = bytes;
205 :
206 31 : for (; *ap != '\0'; ++ap)
207 : {
208 : uint8_t encoding;
209 0 : switch (*ap)
210 : {
211 0 : case 'L': /* Skip LSDA pointer encoding byte. */
212 : case 'R': /* Skip FDE address encoding byte. */
213 0 : encoding = *bytes++;
214 : entry->cie.fde_augmentation_data_size
215 0 : += encoded_value_size (data, e_ident, encoding, NULL);
216 0 : continue;
217 0 : case 'P': /* Skip encoded personality routine pointer. */
218 0 : encoding = *bytes++;
219 0 : bytes += encoded_value_size (data, e_ident, encoding, bytes);
220 0 : continue;
221 0 : case 'S': /* Skip signal-frame flag. */
222 0 : continue;
223 : default:
224 : /* Unknown augmentation string. initial_instructions might
225 : actually start with some augmentation data. */
226 : break;
227 : }
228 : break;
229 : }
230 : entry->cie.augmentation_data_size
231 31 : = bytes - entry->cie.augmentation_data;
232 : }
233 :
234 160 : entry->cie.initial_instructions = bytes;
235 160 : entry->cie.initial_instructions_end = limit;
236 : }
237 : else
238 : {
239 17369 : entry->fde.start = bytes;
240 17369 : entry->fde.end = limit;
241 : }
242 :
243 : return 0;
244 : }
245 : INTDEF (dwarf_next_cfi)
|