blob: b5af49e3e355ec5cd3c07d9c3592743d88064e12 [file] [log] [blame]
Ben Cheng25b3c042013-11-20 14:45:36 -08001/* Advance to next CFI entry.
Elliott Hughes03333822015-02-18 22:19:45 -08002 Copyright (C) 2009-2010, 2014 Red Hat, Inc.
3 This file is part of elfutils.
Ben Cheng25b3c042013-11-20 14:45:36 -08004
Elliott Hughes03333822015-02-18 22:19:45 -08005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Ben Cheng25b3c042013-11-20 14:45:36 -08007
Elliott Hughes03333822015-02-18 22:19:45 -08008 * 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
Ben Cheng25b3c042013-11-20 14:45:36 -080021 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
Elliott Hughes03333822015-02-18 22:19:45 -080025 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/>. */
Ben Cheng25b3c042013-11-20 14:45:36 -080028
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
39int
40dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
41 const unsigned char e_ident[];
42 Elf_Data *data;
43 bool eh_frame_p;
44 Dwarf_Off off;
45 Dwarf_Off *next_off;
46 Dwarf_CFI_Entry *entry;
47{
48 /* Dummy struct for memory-access.h macros. */
49 BYTE_ORDER_DUMMY (dw, e_ident);
50
51 /* If we reached the end before don't do anything. */
52 if (off == (Dwarf_Off) -1l
53 /* Make sure there is enough space in the .debug_frame section
54 for at least the initial word. We cannot test the rest since
55 we don't know yet whether this is a 64-bit object or not. */
56 || unlikely (off + 4 >= data->d_size))
57 {
58 *next_off = (Dwarf_Off) -1l;
59 return 1;
60 }
61
62 /* This points into the .debug_frame section at the start of the entry. */
63 const uint8_t *bytes = data->d_buf + off;
64 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 uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
70 size_t offset_size = 4;
71 if (length == DWARF3_LENGTH_64_BIT)
72 {
73 /* This is the 64-bit DWARF format. */
74 offset_size = 8;
75 if (unlikely (limit - bytes < 8))
76 {
77 invalid:
78 __libdw_seterrno (DWARF_E_INVALID_DWARF);
79 return -1;
80 }
81 length = read_8ubyte_unaligned_inc (&dw, bytes);
82 }
83 if (unlikely ((uint64_t) (limit - bytes) < length)
84 || unlikely (length < offset_size + 1))
85 goto invalid;
86
87 /* Now we know how large the entry is. Note the trick in the
88 computation. If the offset_size is 4 the '- 4' term undoes the
89 '2 *'. If offset_size is 8 this term computes the size of the
90 escape value plus the 8 byte offset. */
91 *next_off = off + (2 * offset_size - 4) + length;
92
93 limit = bytes + length;
94
95 const uint8_t *const cie_pointer_start = bytes;
96 if (offset_size == 8)
97 entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
98 else
99 {
100 entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
101 /* Canonicalize the 32-bit CIE_ID value to 64 bits. */
102 if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
103 entry->cie.CIE_id = DW_CIE_ID_64;
104 }
105 if (eh_frame_p)
106 {
107 /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */
108 if (entry->cie.CIE_id == 0)
109 entry->cie.CIE_id = DW_CIE_ID_64;
110 else
111 {
112 /* In .eh_frame format, a CIE pointer is the distance from where
113 it appears back to the beginning of the CIE. */
114 ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
115 if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
116 || unlikely (pos <= (ptrdiff_t) offset_size))
117 goto invalid;
118 entry->cie.CIE_id = pos - entry->cie.CIE_id;
119 }
120 }
121
122 if (entry->cie.CIE_id == DW_CIE_ID_64)
123 {
124 /* Read the version stamp. Always an 8-bit value. */
125 uint8_t version = *bytes++;
126
127 if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
128 goto invalid;
129
130 entry->cie.augmentation = (const char *) bytes;
131
132 bytes = memchr (bytes, '\0', limit - bytes);
133 if (unlikely (bytes == NULL))
134 goto invalid;
135 ++bytes;
136
137 /* The address size for CFI is implicit in the ELF class. */
138 uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
139 uint_fast8_t segment_size = 0;
140 if (version >= 4)
141 {
142 if (unlikely (limit - bytes < 5))
143 goto invalid;
144 /* XXX We don't actually support address_size not matching the class.
145 To do so, we'd have to return it here so that intern_new_cie
146 could use it choose a specific fde_encoding. */
147 if (unlikely (*bytes != address_size))
148 {
149 __libdw_seterrno (DWARF_E_VERSION);
150 return -1;
151 }
152 address_size = *bytes++;
153 segment_size = *bytes++;
154 /* We don't actually support segment selectors. We'd have to
155 roll this into the fde_encoding bits or something. */
156 if (unlikely (segment_size != 0))
157 {
158 __libdw_seterrno (DWARF_E_VERSION);
159 return -1;
160 }
161 }
162
163 const char *ap = entry->cie.augmentation;
164
165 /* g++ v2 "eh" has pointer immediately following augmentation string,
166 so it must be handled first. */
167 if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
168 {
169 ap += 2;
170 bytes += address_size;
171 }
172
Elliott Hughes03333822015-02-18 22:19:45 -0800173 if (bytes >= limit)
174 goto invalid;
175 get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
176
177 if (bytes >= limit)
178 goto invalid;
179 get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
180
181 if (bytes >= limit)
182 goto invalid;
Ben Cheng25b3c042013-11-20 14:45:36 -0800183
184 if (version >= 3) /* DWARF 3+ */
Elliott Hughes03333822015-02-18 22:19:45 -0800185 get_uleb128 (entry->cie.return_address_register, bytes, limit);
Ben Cheng25b3c042013-11-20 14:45:36 -0800186 else /* DWARF 2 */
187 entry->cie.return_address_register = *bytes++;
188
189 /* If we have sized augmentation data,
190 we don't need to grok it all. */
191 entry->cie.fde_augmentation_data_size = 0;
192 bool sized_augmentation = *ap == 'z';
193 if (sized_augmentation)
194 {
Elliott Hughes03333822015-02-18 22:19:45 -0800195 if (bytes >= limit)
196 goto invalid;
197 get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
Ben Cheng25b3c042013-11-20 14:45:36 -0800198 if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
199 goto invalid;
200 entry->cie.augmentation_data = bytes;
201 bytes += entry->cie.augmentation_data_size;
202 }
203 else
204 {
205 entry->cie.augmentation_data = bytes;
206
207 for (; *ap != '\0'; ++ap)
208 {
209 uint8_t encoding;
210 switch (*ap)
211 {
212 case 'L': /* Skip LSDA pointer encoding byte. */
213 case 'R': /* Skip FDE address encoding byte. */
214 encoding = *bytes++;
215 entry->cie.fde_augmentation_data_size
216 += encoded_value_size (data, e_ident, encoding, NULL);
217 continue;
218 case 'P': /* Skip encoded personality routine pointer. */
219 encoding = *bytes++;
220 bytes += encoded_value_size (data, e_ident, encoding, bytes);
221 continue;
222 case 'S': /* Skip signal-frame flag. */
223 continue;
224 default:
225 /* Unknown augmentation string. initial_instructions might
226 actually start with some augmentation data. */
227 break;
228 }
229 break;
230 }
231 entry->cie.augmentation_data_size
232 = bytes - entry->cie.augmentation_data;
233 }
234
235 entry->cie.initial_instructions = bytes;
236 entry->cie.initial_instructions_end = limit;
237 }
238 else
239 {
240 entry->fde.start = bytes;
241 entry->fde.end = limit;
242 }
243
244 return 0;
245}
246INTDEF (dwarf_next_cfi)