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 (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}
245INTDEF (dwarf_next_cfi)
246