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 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 entry->cie.fde_augmentation_data_size = 0; 197 entry->cie.augmentation_data = bytes; 198 bool sized_augmentation = *ap == 'z'; 199 if (sized_augmentation) 200 { 201 ++ap; 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 } 209 210 for (; *ap != '\0'; ++ap) 211 { 212 uint8_t encoding; 213 switch (*ap) 214 { 215 case 'L': 216 if (sized_augmentation) 217 { 218 /* Skip LSDA pointer encoding byte. */ 219 encoding = *bytes++; 220 entry->cie.fde_augmentation_data_size 221 += encoded_value_size (data, e_ident, encoding, NULL); 222 continue; 223 } 224 break; 225 case 'R': 226 if (sized_augmentation) 227 { 228 /* Skip FDE address encoding byte. */ 229 encoding = *bytes++; 230 continue; 231 } 232 break; 233 case 'P': 234 if (sized_augmentation) 235 { 236 /* Skip encoded personality routine pointer. */ 237 encoding = *bytes++; 238 bytes += encoded_value_size (data, e_ident, encoding, bytes); 239 continue; 240 } 241 break; 242 case 'S': 243 if (sized_augmentation) 244 /* Skip signal-frame flag. */ 245 continue; 246 break; 247 default: 248 /* Unknown augmentation string. initial_instructions might 249 actually start with some augmentation data. */ 250 break; 251 } 252 break; 253 } 254 if (! sized_augmentation) 255 entry->cie.augmentation_data_size = bytes - entry->cie.augmentation_data; 256 else 257 { 258 if (bytes > entry->cie.augmentation_data + entry->cie.augmentation_data_size) 259 goto invalid; 260 bytes = entry->cie.augmentation_data + entry->cie.augmentation_data_size; 261 } 262 263 entry->cie.initial_instructions = bytes; 264 entry->cie.initial_instructions_end = limit; 265 } 266 else 267 { 268 entry->fde.start = bytes; 269 entry->fde.end = limit; 270 } 271 272 return 0; 273} 274INTDEF (dwarf_next_cfi) 275