1da0c48c4Sopenharmony_ci/* Advance to next CFI entry. 2da0c48c4Sopenharmony_ci Copyright (C) 2009-2010, 2014 Red Hat, Inc. 3da0c48c4Sopenharmony_ci This file is part of elfutils. 4da0c48c4Sopenharmony_ci 5da0c48c4Sopenharmony_ci This file is free software; you can redistribute it and/or modify 6da0c48c4Sopenharmony_ci it under the terms of either 7da0c48c4Sopenharmony_ci 8da0c48c4Sopenharmony_ci * the GNU Lesser General Public License as published by the Free 9da0c48c4Sopenharmony_ci Software Foundation; either version 3 of the License, or (at 10da0c48c4Sopenharmony_ci your option) any later version 11da0c48c4Sopenharmony_ci 12da0c48c4Sopenharmony_ci or 13da0c48c4Sopenharmony_ci 14da0c48c4Sopenharmony_ci * the GNU General Public License as published by the Free 15da0c48c4Sopenharmony_ci Software Foundation; either version 2 of the License, or (at 16da0c48c4Sopenharmony_ci your option) any later version 17da0c48c4Sopenharmony_ci 18da0c48c4Sopenharmony_ci or both in parallel, as here. 19da0c48c4Sopenharmony_ci 20da0c48c4Sopenharmony_ci elfutils is distributed in the hope that it will be useful, but 21da0c48c4Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 22da0c48c4Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23da0c48c4Sopenharmony_ci General Public License for more details. 24da0c48c4Sopenharmony_ci 25da0c48c4Sopenharmony_ci You should have received copies of the GNU General Public License and 26da0c48c4Sopenharmony_ci the GNU Lesser General Public License along with this program. If 27da0c48c4Sopenharmony_ci not, see <http://www.gnu.org/licenses/>. */ 28da0c48c4Sopenharmony_ci 29da0c48c4Sopenharmony_ci#ifdef HAVE_CONFIG_H 30da0c48c4Sopenharmony_ci# include <config.h> 31da0c48c4Sopenharmony_ci#endif 32da0c48c4Sopenharmony_ci 33da0c48c4Sopenharmony_ci#include "cfi.h" 34da0c48c4Sopenharmony_ci#include "encoded-value.h" 35da0c48c4Sopenharmony_ci 36da0c48c4Sopenharmony_ci#include <string.h> 37da0c48c4Sopenharmony_ci 38da0c48c4Sopenharmony_ci 39da0c48c4Sopenharmony_ciint 40da0c48c4Sopenharmony_cidwarf_next_cfi (const unsigned char e_ident[], 41da0c48c4Sopenharmony_ci Elf_Data *data, 42da0c48c4Sopenharmony_ci bool eh_frame_p, 43da0c48c4Sopenharmony_ci Dwarf_Off off, 44da0c48c4Sopenharmony_ci Dwarf_Off *next_off, 45da0c48c4Sopenharmony_ci Dwarf_CFI_Entry *entry) 46da0c48c4Sopenharmony_ci{ 47da0c48c4Sopenharmony_ci /* Dummy struct for memory-access.h macros. */ 48da0c48c4Sopenharmony_ci BYTE_ORDER_DUMMY (dw, e_ident); 49da0c48c4Sopenharmony_ci 50da0c48c4Sopenharmony_ci /* If we reached the end before don't do anything. */ 51da0c48c4Sopenharmony_ci if (off == (Dwarf_Off) -1l 52da0c48c4Sopenharmony_ci /* Make sure there is enough space in the .debug_frame section 53da0c48c4Sopenharmony_ci for at least the initial word. We cannot test the rest since 54da0c48c4Sopenharmony_ci we don't know yet whether this is a 64-bit object or not. */ 55da0c48c4Sopenharmony_ci || unlikely (off + 4 >= data->d_size)) 56da0c48c4Sopenharmony_ci { 57da0c48c4Sopenharmony_ci done: 58da0c48c4Sopenharmony_ci *next_off = (Dwarf_Off) -1l; 59da0c48c4Sopenharmony_ci return 1; 60da0c48c4Sopenharmony_ci } 61da0c48c4Sopenharmony_ci 62da0c48c4Sopenharmony_ci /* This points into the .debug_frame section at the start of the entry. */ 63da0c48c4Sopenharmony_ci const uint8_t *bytes = data->d_buf + off; 64da0c48c4Sopenharmony_ci const uint8_t *limit = data->d_buf + data->d_size; 65da0c48c4Sopenharmony_ci 66da0c48c4Sopenharmony_ci /* The format of a CFI entry is described in DWARF3 6.4.1: 67da0c48c4Sopenharmony_ci */ 68da0c48c4Sopenharmony_ci 69da0c48c4Sopenharmony_ci uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes); 70da0c48c4Sopenharmony_ci size_t offset_size = 4; 71da0c48c4Sopenharmony_ci if (length == DWARF3_LENGTH_64_BIT) 72da0c48c4Sopenharmony_ci { 73da0c48c4Sopenharmony_ci /* This is the 64-bit DWARF format. */ 74da0c48c4Sopenharmony_ci offset_size = 8; 75da0c48c4Sopenharmony_ci if (unlikely (limit - bytes < 8)) 76da0c48c4Sopenharmony_ci { 77da0c48c4Sopenharmony_ci invalid: 78da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_INVALID_DWARF); 79da0c48c4Sopenharmony_ci return -1; 80da0c48c4Sopenharmony_ci } 81da0c48c4Sopenharmony_ci length = read_8ubyte_unaligned_inc (&dw, bytes); 82da0c48c4Sopenharmony_ci } 83da0c48c4Sopenharmony_ci 84da0c48c4Sopenharmony_ci /* Not explicitly in the DWARF spec, but mentioned in the LSB exception 85da0c48c4Sopenharmony_ci frames (.eh_frame) spec. If Length contains the value 0, then this 86da0c48c4Sopenharmony_ci CIE shall be considered a terminator and processing shall end. */ 87da0c48c4Sopenharmony_ci if (length == 0) 88da0c48c4Sopenharmony_ci goto done; 89da0c48c4Sopenharmony_ci 90da0c48c4Sopenharmony_ci if (unlikely ((uint64_t) (limit - bytes) < length) 91da0c48c4Sopenharmony_ci || unlikely (length < offset_size + 1)) 92da0c48c4Sopenharmony_ci goto invalid; 93da0c48c4Sopenharmony_ci 94da0c48c4Sopenharmony_ci /* Now we know how large the entry is. Note the trick in the 95da0c48c4Sopenharmony_ci computation. If the offset_size is 4 the '- 4' term undoes the 96da0c48c4Sopenharmony_ci '2 *'. If offset_size is 8 this term computes the size of the 97da0c48c4Sopenharmony_ci escape value plus the 8 byte offset. */ 98da0c48c4Sopenharmony_ci *next_off = off + (2 * offset_size - 4) + length; 99da0c48c4Sopenharmony_ci 100da0c48c4Sopenharmony_ci limit = bytes + length; 101da0c48c4Sopenharmony_ci 102da0c48c4Sopenharmony_ci const uint8_t *const cie_pointer_start = bytes; 103da0c48c4Sopenharmony_ci if (offset_size == 8) 104da0c48c4Sopenharmony_ci entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes); 105da0c48c4Sopenharmony_ci else 106da0c48c4Sopenharmony_ci { 107da0c48c4Sopenharmony_ci entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes); 108da0c48c4Sopenharmony_ci /* Canonicalize the 32-bit CIE_ID value to 64 bits. */ 109da0c48c4Sopenharmony_ci if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32) 110da0c48c4Sopenharmony_ci entry->cie.CIE_id = DW_CIE_ID_64; 111da0c48c4Sopenharmony_ci } 112da0c48c4Sopenharmony_ci if (eh_frame_p) 113da0c48c4Sopenharmony_ci { 114da0c48c4Sopenharmony_ci /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */ 115da0c48c4Sopenharmony_ci if (entry->cie.CIE_id == 0) 116da0c48c4Sopenharmony_ci entry->cie.CIE_id = DW_CIE_ID_64; 117da0c48c4Sopenharmony_ci else 118da0c48c4Sopenharmony_ci { 119da0c48c4Sopenharmony_ci /* In .eh_frame format, a CIE pointer is the distance from where 120da0c48c4Sopenharmony_ci it appears back to the beginning of the CIE. */ 121da0c48c4Sopenharmony_ci ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf; 122da0c48c4Sopenharmony_ci if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos) 123da0c48c4Sopenharmony_ci || unlikely (pos <= (ptrdiff_t) offset_size)) 124da0c48c4Sopenharmony_ci goto invalid; 125da0c48c4Sopenharmony_ci entry->cie.CIE_id = pos - entry->cie.CIE_id; 126da0c48c4Sopenharmony_ci } 127da0c48c4Sopenharmony_ci } 128da0c48c4Sopenharmony_ci 129da0c48c4Sopenharmony_ci if (entry->cie.CIE_id == DW_CIE_ID_64) 130da0c48c4Sopenharmony_ci { 131da0c48c4Sopenharmony_ci /* Read the version stamp. Always an 8-bit value. */ 132da0c48c4Sopenharmony_ci uint8_t version = *bytes++; 133da0c48c4Sopenharmony_ci 134da0c48c4Sopenharmony_ci if (version != 1 && (unlikely (version < 3) || unlikely (version > 4))) 135da0c48c4Sopenharmony_ci goto invalid; 136da0c48c4Sopenharmony_ci 137da0c48c4Sopenharmony_ci entry->cie.augmentation = (const char *) bytes; 138da0c48c4Sopenharmony_ci 139da0c48c4Sopenharmony_ci bytes = memchr (bytes, '\0', limit - bytes); 140da0c48c4Sopenharmony_ci if (unlikely (bytes == NULL)) 141da0c48c4Sopenharmony_ci goto invalid; 142da0c48c4Sopenharmony_ci ++bytes; 143da0c48c4Sopenharmony_ci 144da0c48c4Sopenharmony_ci /* The address size for CFI is implicit in the ELF class. */ 145da0c48c4Sopenharmony_ci uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 146da0c48c4Sopenharmony_ci uint_fast8_t segment_size = 0; 147da0c48c4Sopenharmony_ci if (version >= 4) 148da0c48c4Sopenharmony_ci { 149da0c48c4Sopenharmony_ci if (unlikely (limit - bytes < 5)) 150da0c48c4Sopenharmony_ci goto invalid; 151da0c48c4Sopenharmony_ci /* XXX We don't actually support address_size not matching the class. 152da0c48c4Sopenharmony_ci To do so, we'd have to return it here so that intern_new_cie 153da0c48c4Sopenharmony_ci could use it choose a specific fde_encoding. */ 154da0c48c4Sopenharmony_ci if (unlikely (*bytes != address_size)) 155da0c48c4Sopenharmony_ci { 156da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_VERSION); 157da0c48c4Sopenharmony_ci return -1; 158da0c48c4Sopenharmony_ci } 159da0c48c4Sopenharmony_ci address_size = *bytes++; 160da0c48c4Sopenharmony_ci segment_size = *bytes++; 161da0c48c4Sopenharmony_ci /* We don't actually support segment selectors. We'd have to 162da0c48c4Sopenharmony_ci roll this into the fde_encoding bits or something. */ 163da0c48c4Sopenharmony_ci if (unlikely (segment_size != 0)) 164da0c48c4Sopenharmony_ci { 165da0c48c4Sopenharmony_ci __libdw_seterrno (DWARF_E_VERSION); 166da0c48c4Sopenharmony_ci return -1; 167da0c48c4Sopenharmony_ci } 168da0c48c4Sopenharmony_ci } 169da0c48c4Sopenharmony_ci 170da0c48c4Sopenharmony_ci const char *ap = entry->cie.augmentation; 171da0c48c4Sopenharmony_ci 172da0c48c4Sopenharmony_ci /* g++ v2 "eh" has pointer immediately following augmentation string, 173da0c48c4Sopenharmony_ci so it must be handled first. */ 174da0c48c4Sopenharmony_ci if (unlikely (ap[0] == 'e' && ap[1] == 'h')) 175da0c48c4Sopenharmony_ci { 176da0c48c4Sopenharmony_ci ap += 2; 177da0c48c4Sopenharmony_ci bytes += address_size; 178da0c48c4Sopenharmony_ci } 179da0c48c4Sopenharmony_ci 180da0c48c4Sopenharmony_ci if (bytes >= limit) 181da0c48c4Sopenharmony_ci goto invalid; 182da0c48c4Sopenharmony_ci get_uleb128 (entry->cie.code_alignment_factor, bytes, limit); 183da0c48c4Sopenharmony_ci 184da0c48c4Sopenharmony_ci if (bytes >= limit) 185da0c48c4Sopenharmony_ci goto invalid; 186da0c48c4Sopenharmony_ci get_sleb128 (entry->cie.data_alignment_factor, bytes, limit); 187da0c48c4Sopenharmony_ci 188da0c48c4Sopenharmony_ci if (bytes >= limit) 189da0c48c4Sopenharmony_ci goto invalid; 190da0c48c4Sopenharmony_ci 191da0c48c4Sopenharmony_ci if (version >= 3) /* DWARF 3+ */ 192da0c48c4Sopenharmony_ci get_uleb128 (entry->cie.return_address_register, bytes, limit); 193da0c48c4Sopenharmony_ci else /* DWARF 2 */ 194da0c48c4Sopenharmony_ci entry->cie.return_address_register = *bytes++; 195da0c48c4Sopenharmony_ci 196da0c48c4Sopenharmony_ci entry->cie.fde_augmentation_data_size = 0; 197da0c48c4Sopenharmony_ci entry->cie.augmentation_data = bytes; 198da0c48c4Sopenharmony_ci bool sized_augmentation = *ap == 'z'; 199da0c48c4Sopenharmony_ci if (sized_augmentation) 200da0c48c4Sopenharmony_ci { 201da0c48c4Sopenharmony_ci ++ap; 202da0c48c4Sopenharmony_ci if (bytes >= limit) 203da0c48c4Sopenharmony_ci goto invalid; 204da0c48c4Sopenharmony_ci get_uleb128 (entry->cie.augmentation_data_size, bytes, limit); 205da0c48c4Sopenharmony_ci if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size) 206da0c48c4Sopenharmony_ci goto invalid; 207da0c48c4Sopenharmony_ci entry->cie.augmentation_data = bytes; 208da0c48c4Sopenharmony_ci } 209da0c48c4Sopenharmony_ci 210da0c48c4Sopenharmony_ci for (; *ap != '\0'; ++ap) 211da0c48c4Sopenharmony_ci { 212da0c48c4Sopenharmony_ci uint8_t encoding; 213da0c48c4Sopenharmony_ci switch (*ap) 214da0c48c4Sopenharmony_ci { 215da0c48c4Sopenharmony_ci case 'L': 216da0c48c4Sopenharmony_ci if (sized_augmentation) 217da0c48c4Sopenharmony_ci { 218da0c48c4Sopenharmony_ci /* Skip LSDA pointer encoding byte. */ 219da0c48c4Sopenharmony_ci encoding = *bytes++; 220da0c48c4Sopenharmony_ci entry->cie.fde_augmentation_data_size 221da0c48c4Sopenharmony_ci += encoded_value_size (data, e_ident, encoding, NULL); 222da0c48c4Sopenharmony_ci continue; 223da0c48c4Sopenharmony_ci } 224da0c48c4Sopenharmony_ci break; 225da0c48c4Sopenharmony_ci case 'R': 226da0c48c4Sopenharmony_ci if (sized_augmentation) 227da0c48c4Sopenharmony_ci { 228da0c48c4Sopenharmony_ci /* Skip FDE address encoding byte. */ 229da0c48c4Sopenharmony_ci encoding = *bytes++; 230da0c48c4Sopenharmony_ci continue; 231da0c48c4Sopenharmony_ci } 232da0c48c4Sopenharmony_ci break; 233da0c48c4Sopenharmony_ci case 'P': 234da0c48c4Sopenharmony_ci if (sized_augmentation) 235da0c48c4Sopenharmony_ci { 236da0c48c4Sopenharmony_ci /* Skip encoded personality routine pointer. */ 237da0c48c4Sopenharmony_ci encoding = *bytes++; 238da0c48c4Sopenharmony_ci bytes += encoded_value_size (data, e_ident, encoding, bytes); 239da0c48c4Sopenharmony_ci continue; 240da0c48c4Sopenharmony_ci } 241da0c48c4Sopenharmony_ci break; 242da0c48c4Sopenharmony_ci case 'S': 243da0c48c4Sopenharmony_ci if (sized_augmentation) 244da0c48c4Sopenharmony_ci /* Skip signal-frame flag. */ 245da0c48c4Sopenharmony_ci continue; 246da0c48c4Sopenharmony_ci break; 247da0c48c4Sopenharmony_ci default: 248da0c48c4Sopenharmony_ci /* Unknown augmentation string. initial_instructions might 249da0c48c4Sopenharmony_ci actually start with some augmentation data. */ 250da0c48c4Sopenharmony_ci break; 251da0c48c4Sopenharmony_ci } 252da0c48c4Sopenharmony_ci break; 253da0c48c4Sopenharmony_ci } 254da0c48c4Sopenharmony_ci if (! sized_augmentation) 255da0c48c4Sopenharmony_ci entry->cie.augmentation_data_size = bytes - entry->cie.augmentation_data; 256da0c48c4Sopenharmony_ci else 257da0c48c4Sopenharmony_ci { 258da0c48c4Sopenharmony_ci if (bytes > entry->cie.augmentation_data + entry->cie.augmentation_data_size) 259da0c48c4Sopenharmony_ci goto invalid; 260da0c48c4Sopenharmony_ci bytes = entry->cie.augmentation_data + entry->cie.augmentation_data_size; 261da0c48c4Sopenharmony_ci } 262da0c48c4Sopenharmony_ci 263da0c48c4Sopenharmony_ci entry->cie.initial_instructions = bytes; 264da0c48c4Sopenharmony_ci entry->cie.initial_instructions_end = limit; 265da0c48c4Sopenharmony_ci } 266da0c48c4Sopenharmony_ci else 267da0c48c4Sopenharmony_ci { 268da0c48c4Sopenharmony_ci entry->fde.start = bytes; 269da0c48c4Sopenharmony_ci entry->fde.end = limit; 270da0c48c4Sopenharmony_ci } 271da0c48c4Sopenharmony_ci 272da0c48c4Sopenharmony_ci return 0; 273da0c48c4Sopenharmony_ci} 274da0c48c4Sopenharmony_ciINTDEF (dwarf_next_cfi) 275