resetting manifest requested domain to floor
[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       *next_off = (Dwarf_Off) -1l;
58       return 1;
59     }
60
61   /* This points into the .debug_frame section at the start of the entry.  */
62   const uint8_t *bytes = data->d_buf + off;
63   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   uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
69   size_t offset_size = 4;
70   if (length == DWARF3_LENGTH_64_BIT)
71     {
72       /* This is the 64-bit DWARF format.  */
73       offset_size = 8;
74       if (unlikely (limit - bytes < 8))
75         {
76         invalid:
77           __libdw_seterrno (DWARF_E_INVALID_DWARF);
78           return -1;
79         }
80       length = read_8ubyte_unaligned_inc (&dw, bytes);
81     }
82   if (unlikely ((uint64_t) (limit - bytes) < length)
83       || 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   *next_off = off + (2 * offset_size - 4) + length;
91
92   limit = bytes + length;
93
94   const uint8_t *const cie_pointer_start = bytes;
95   if (offset_size == 8)
96     entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
97   else
98     {
99       entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
100       /* Canonicalize the 32-bit CIE_ID value to 64 bits.  */
101       if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
102         entry->cie.CIE_id = DW_CIE_ID_64;
103     }
104   if (eh_frame_p)
105     {
106       /* Canonicalize the .eh_frame CIE pointer to .debug_frame format.  */
107       if (entry->cie.CIE_id == 0)
108         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           ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
114           if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
115               || unlikely (pos <= (ptrdiff_t) offset_size))
116             goto invalid;
117           entry->cie.CIE_id = pos - entry->cie.CIE_id;
118         }
119     }
120
121   if (entry->cie.CIE_id == DW_CIE_ID_64)
122     {
123       /* Read the version stamp.  Always an 8-bit value.  */
124       uint8_t version = *bytes++;
125
126       if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
127         goto invalid;
128
129       entry->cie.augmentation = (const char *) bytes;
130
131       bytes = memchr (bytes, '\0', limit - bytes);
132       if (unlikely (bytes == NULL))
133         goto invalid;
134       ++bytes;
135
136       /* The address size for CFI is implicit in the ELF class.  */
137       uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
138       uint_fast8_t segment_size = 0;
139       if (version >= 4)
140         {
141           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           if (unlikely (*bytes != address_size))
147             {
148               __libdw_seterrno (DWARF_E_VERSION);
149               return -1;
150             }
151           address_size = *bytes++;
152           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           if (unlikely (segment_size != 0))
156             {
157               __libdw_seterrno (DWARF_E_VERSION);
158               return -1;
159             }
160         }
161
162       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       if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
167         {
168           ap += 2;
169           bytes += address_size;
170         }
171
172       if (bytes >= limit)
173         goto invalid;
174       get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
175
176       if (bytes >= limit)
177         goto invalid;
178       get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
179
180       if (bytes >= limit)
181         goto invalid;
182
183       if (version >= 3)         /* DWARF 3+ */
184         get_uleb128 (entry->cie.return_address_register, bytes, limit);
185       else                      /* DWARF 2 */
186         entry->cie.return_address_register = *bytes++;
187
188       /* If we have sized augmentation data,
189          we don't need to grok it all.  */
190       entry->cie.fde_augmentation_data_size = 0;
191       bool sized_augmentation = *ap == 'z';
192       if (sized_augmentation)
193         {
194           if (bytes >= limit)
195             goto invalid;
196           get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
197           if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
198             goto invalid;
199           entry->cie.augmentation_data = bytes;
200           bytes += entry->cie.augmentation_data_size;
201         }
202       else
203         {
204           entry->cie.augmentation_data = bytes;
205
206           for (; *ap != '\0'; ++ap)
207             {
208               uint8_t encoding;
209               switch (*ap)
210                 {
211                 case 'L':               /* Skip LSDA pointer encoding byte.  */
212                 case 'R':               /* Skip FDE address encoding byte.  */
213                   encoding = *bytes++;
214                   entry->cie.fde_augmentation_data_size
215                     += encoded_value_size (data, e_ident, encoding, NULL);
216                   continue;
217                 case 'P':   /* Skip encoded personality routine pointer. */
218                   encoding = *bytes++;
219                   bytes += encoded_value_size (data, e_ident, encoding, bytes);
220                   continue;
221                 case 'S':               /* Skip signal-frame flag.  */
222                   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             = bytes - entry->cie.augmentation_data;
232         }
233
234       entry->cie.initial_instructions = bytes;
235       entry->cie.initial_instructions_end = limit;
236     }
237   else
238     {
239       entry->fde.start = bytes;
240       entry->fde.end = limit;
241     }
242
243   return 0;
244 }
245 INTDEF (dwarf_next_cfi)