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
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
173      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;
183
184      if (version >= 3)		/* DWARF 3+ */
185	get_uleb128 (entry->cie.return_address_register, bytes, limit);
186      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	{
195	  if (bytes >= limit)
196	    goto invalid;
197	  get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
198	  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)
247