Branch data Line data Source code
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 : 30578 : 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 : 30578 : BYTE_ORDER_DUMMY (dw, e_ident); 49 : : 50 : : /* If we reached the end before don't do anything. */ 51 [ + + ]: 30578 : 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 [ + + ]: 30475 : || unlikely (off + 4 >= data->d_size)) 56 : : { 57 : 142 : done: 58 : 143 : *next_off = (Dwarf_Off) -1l; 59 : 143 : return 1; 60 : : } 61 : : 62 : : /* This points into the .debug_frame section at the start of the entry. */ 63 : 30436 : const uint8_t *bytes = data->d_buf + off; 64 : 30436 : 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 [ + + ]: 30436 : uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes); 70 : 30436 : size_t offset_size = 4; 71 [ - + ]: 30436 : if (length == DWARF3_LENGTH_64_BIT) 72 : : { 73 : : /* This is the 64-bit DWARF format. */ 74 : 0 : offset_size = 8; 75 [ # # ]: 0 : if (unlikely (limit - bytes < 8)) 76 : : { 77 : 0 : invalid: 78 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 79 : 0 : return -1; 80 : : } 81 [ # # ]: 0 : 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 [ + + ]: 30436 : if (length == 0) 88 : 1 : goto done; 89 : : 90 [ + - ]: 30435 : if (unlikely ((uint64_t) (limit - bytes) < length) 91 [ - + ]: 30435 : || unlikely (length < offset_size + 1)) 92 : 0 : 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 : 30435 : *next_off = off + (2 * offset_size - 4) + length; 99 : : 100 : 30435 : limit = bytes + length; 101 : : 102 : 30435 : const uint8_t *const cie_pointer_start = bytes; 103 [ - + ]: 30435 : if (offset_size == 8) 104 [ # # ]: 0 : entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes); 105 : : else 106 : : { 107 [ + + ]: 30435 : entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes); 108 : : /* Canonicalize the 32-bit CIE_ID value to 64 bits. */ 109 [ + + + + ]: 30435 : if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32) 110 : 70 : entry->cie.CIE_id = DW_CIE_ID_64; 111 : : } 112 [ - + ]: 183 : if (eh_frame_p) 113 : : { 114 : : /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */ 115 [ + + ]: 30252 : if (entry->cie.CIE_id == 0) 116 : 5555 : 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 : 24697 : ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf; 122 [ + - ]: 24697 : if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos) 123 [ - + ]: 24697 : || unlikely (pos <= (ptrdiff_t) offset_size)) 124 : 0 : goto invalid; 125 : 24697 : entry->cie.CIE_id = pos - entry->cie.CIE_id; 126 : : } 127 : : } 128 : : 129 [ + + ]: 30435 : if (entry->cie.CIE_id == DW_CIE_ID_64) 130 : : { 131 : : /* Read the version stamp. Always an 8-bit value. */ 132 : 5625 : uint8_t version = *bytes++; 133 : : 134 [ - + - - : 5625 : if (version != 1 && (unlikely (version < 3) || unlikely (version > 4))) - - ] 135 : 0 : goto invalid; 136 : : 137 : 5625 : entry->cie.augmentation = (const char *) bytes; 138 : : 139 : 5625 : bytes = memchr (bytes, '\0', limit - bytes); 140 [ - + ]: 5625 : if (unlikely (bytes == NULL)) 141 : 0 : goto invalid; 142 : 5625 : ++bytes; 143 : : 144 : : /* The address size for CFI is implicit in the ELF class. */ 145 [ + + ]: 5625 : uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 146 : 5625 : uint_fast8_t segment_size = 0; 147 [ - + ]: 5625 : if (version >= 4) 148 : : { 149 [ # # ]: 0 : if (unlikely (limit - bytes < 5)) 150 : 0 : 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 [ # # ]: 0 : if (unlikely (*bytes != address_size)) 155 : : { 156 : 0 : __libdw_seterrno (DWARF_E_VERSION); 157 : 0 : return -1; 158 : : } 159 : 0 : address_size = *bytes++; 160 : 0 : 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 [ # # ]: 0 : if (unlikely (segment_size != 0)) 164 : : { 165 : 0 : __libdw_seterrno (DWARF_E_VERSION); 166 : 0 : return -1; 167 : : } 168 : : } 169 : : 170 : 5625 : 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 [ - + - - ]: 5625 : if (unlikely (ap[0] == 'e' && ap[1] == 'h')) 175 : : { 176 : 0 : ap += 2; 177 : 0 : bytes += address_size; 178 : : } 179 : : 180 [ - + ]: 5625 : if (bytes >= limit) 181 : 0 : goto invalid; 182 : 5625 : get_uleb128 (entry->cie.code_alignment_factor, bytes, limit); 183 : : 184 [ - + ]: 5625 : if (bytes >= limit) 185 : 0 : goto invalid; 186 : 5625 : get_sleb128 (entry->cie.data_alignment_factor, bytes, limit); 187 : : 188 [ - + ]: 5625 : if (bytes >= limit) 189 : 0 : goto invalid; 190 : : 191 [ - + ]: 5625 : if (version >= 3) /* DWARF 3+ */ 192 : 0 : get_uleb128 (entry->cie.return_address_register, bytes, limit); 193 : : else /* DWARF 2 */ 194 : 5625 : entry->cie.return_address_register = *bytes++; 195 : : 196 : 5625 : entry->cie.fde_augmentation_data_size = 0; 197 : 5625 : entry->cie.augmentation_data = bytes; 198 : 5625 : bool sized_augmentation = *ap == 'z'; 199 [ + + ]: 5625 : if (sized_augmentation) 200 : : { 201 : 5554 : ++ap; 202 [ - + ]: 5554 : if (bytes >= limit) 203 : 0 : goto invalid; 204 : 5554 : get_uleb128 (entry->cie.augmentation_data_size, bytes, limit); 205 [ - + ]: 5554 : if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size) 206 : 0 : goto invalid; 207 : 5554 : entry->cie.augmentation_data = bytes; 208 : : } 209 : : 210 [ + + ]: 11222 : for (; *ap != '\0'; ++ap) 211 : : { 212 : 5597 : uint8_t encoding; 213 [ + + + + : 5597 : switch (*ap) - ] 214 : : { 215 : 22 : case 'L': 216 [ + - ]: 22 : if (sized_augmentation) 217 : : { 218 : : /* Skip LSDA pointer encoding byte. */ 219 : 22 : encoding = *bytes++; 220 : 44 : entry->cie.fde_augmentation_data_size 221 : 22 : += encoded_value_size (data, e_ident, encoding, NULL); 222 : 22 : continue; 223 : : } 224 : : break; 225 : 5546 : case 'R': 226 [ + - ]: 5546 : if (sized_augmentation) 227 : : { 228 : : /* Skip FDE address encoding byte. */ 229 : 5546 : bytes++; 230 : 5546 : continue; 231 : : } 232 : : break; 233 : 26 : case 'P': 234 [ + - ]: 26 : if (sized_augmentation) 235 : : { 236 : : /* Skip encoded personality routine pointer. */ 237 : 26 : encoding = *bytes++; 238 : 26 : bytes += encoded_value_size (data, e_ident, encoding, bytes); 239 : 26 : continue; 240 : : } 241 : : break; 242 : 3 : case 'S': 243 [ + - ]: 3 : if (sized_augmentation) 244 : : /* Skip signal-frame flag. */ 245 : 3 : 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 [ + + ]: 5625 : if (! sized_augmentation) 255 : 71 : entry->cie.augmentation_data_size = bytes - entry->cie.augmentation_data; 256 : : else 257 : : { 258 [ - + ]: 5554 : if (bytes > entry->cie.augmentation_data + entry->cie.augmentation_data_size) 259 : 0 : goto invalid; 260 : 5554 : bytes = entry->cie.augmentation_data + entry->cie.augmentation_data_size; 261 : : } 262 : : 263 : 5625 : entry->cie.initial_instructions = bytes; 264 : 5625 : entry->cie.initial_instructions_end = limit; 265 : : } 266 : : else 267 : : { 268 : 24810 : entry->fde.start = bytes; 269 : 24810 : entry->fde.end = limit; 270 : : } 271 : : 272 : : return 0; 273 : : } 274 : : INTDEF (dwarf_next_cfi)