libdwfl: Sanity check partial core file dyn data read.
[platform/upstream/elfutils.git] / libdw / dwarf_next_cfi.c
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 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   BYTE_ORDER_DUMMY (dw, e_ident);
49
50   /* If we reached the end before don't do anything.  */
51   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       || unlikely (off + 4 >= data->d_size))
56     {
57     done:
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
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   if (length == 0)
88     goto done;
89
90   if (unlikely ((uint64_t) (limit - bytes) < length)
91       || unlikely (length < offset_size + 1))
92     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   *next_off = off + (2 * offset_size - 4) + length;
99
100   limit = bytes + length;
101
102   const uint8_t *const cie_pointer_start = bytes;
103   if (offset_size == 8)
104     entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
105   else
106     {
107       entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
108       /* Canonicalize the 32-bit CIE_ID value to 64 bits.  */
109       if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
110         entry->cie.CIE_id = DW_CIE_ID_64;
111     }
112   if (eh_frame_p)
113     {
114       /* Canonicalize the .eh_frame CIE pointer to .debug_frame format.  */
115       if (entry->cie.CIE_id == 0)
116         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           ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
122           if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
123               || unlikely (pos <= (ptrdiff_t) offset_size))
124             goto invalid;
125           entry->cie.CIE_id = pos - entry->cie.CIE_id;
126         }
127     }
128
129   if (entry->cie.CIE_id == DW_CIE_ID_64)
130     {
131       /* Read the version stamp.  Always an 8-bit value.  */
132       uint8_t version = *bytes++;
133
134       if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
135         goto invalid;
136
137       entry->cie.augmentation = (const char *) bytes;
138
139       bytes = memchr (bytes, '\0', limit - bytes);
140       if (unlikely (bytes == NULL))
141         goto invalid;
142       ++bytes;
143
144       /* The address size for CFI is implicit in the ELF class.  */
145       uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
146       uint_fast8_t segment_size = 0;
147       if (version >= 4)
148         {
149           if (unlikely (limit - bytes < 5))
150             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           if (unlikely (*bytes != address_size))
155             {
156               __libdw_seterrno (DWARF_E_VERSION);
157               return -1;
158             }
159           address_size = *bytes++;
160           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           if (unlikely (segment_size != 0))
164             {
165               __libdw_seterrno (DWARF_E_VERSION);
166               return -1;
167             }
168         }
169
170       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       if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
175         {
176           ap += 2;
177           bytes += address_size;
178         }
179
180       if (bytes >= limit)
181         goto invalid;
182       get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
183
184       if (bytes >= limit)
185         goto invalid;
186       get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
187
188       if (bytes >= limit)
189         goto invalid;
190
191       if (version >= 3)         /* DWARF 3+ */
192         get_uleb128 (entry->cie.return_address_register, bytes, limit);
193       else                      /* DWARF 2 */
194         entry->cie.return_address_register = *bytes++;
195
196       /* If we have sized augmentation data,
197          we don't need to grok it all.  */
198       entry->cie.fde_augmentation_data_size = 0;
199       bool sized_augmentation = *ap == 'z';
200       if (sized_augmentation)
201         {
202           if (bytes >= limit)
203             goto invalid;
204           get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
205           if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
206             goto invalid;
207           entry->cie.augmentation_data = bytes;
208           bytes += entry->cie.augmentation_data_size;
209         }
210       else
211         {
212           entry->cie.augmentation_data = bytes;
213
214           for (; *ap != '\0'; ++ap)
215             {
216               uint8_t encoding;
217               switch (*ap)
218                 {
219                 case 'L':               /* Skip LSDA pointer encoding byte.  */
220                 case 'R':               /* Skip FDE address encoding byte.  */
221                   encoding = *bytes++;
222                   entry->cie.fde_augmentation_data_size
223                     += encoded_value_size (data, e_ident, encoding, NULL);
224                   continue;
225                 case 'P':   /* Skip encoded personality routine pointer. */
226                   encoding = *bytes++;
227                   bytes += encoded_value_size (data, e_ident, encoding, bytes);
228                   continue;
229                 case 'S':               /* Skip signal-frame flag.  */
230                   continue;
231                 default:
232                   /* Unknown augmentation string.  initial_instructions might
233                      actually start with some augmentation data.  */
234                   break;
235                 }
236               break;
237             }
238           entry->cie.augmentation_data_size
239             = bytes - entry->cie.augmentation_data;
240         }
241
242       entry->cie.initial_instructions = bytes;
243       entry->cie.initial_instructions_end = limit;
244     }
245   else
246     {
247       entry->fde.start = bytes;
248       entry->fde.end = limit;
249     }
250
251   return 0;
252 }
253 INTDEF (dwarf_next_cfi)