1 /* Advance to next CFI entry. 2 Copyright (C) 2009-2010 Red Hat, Inc. 3 This file is part of Red Hat elfutils. 4 5 Red Hat elfutils is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by the 7 Free Software Foundation; version 2 of the License. 8 9 Red Hat elfutils is distributed in the hope that it will be useful, but 10 WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along 15 with Red Hat elfutils; if not, write to the Free Software Foundation, 16 Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA. 17 18 In addition, as a special exception, Red Hat, Inc. gives You the 19 additional right to link the code of Red Hat elfutils with code licensed 20 under any Open Source Initiative certified open source license 21 (http://www.opensource.org/licenses/index.php) which requires the 22 distribution of source code with any binary distribution and to 23 distribute linked combinations of the two. Non-GPL Code permitted under 24 this exception must only link to the code of Red Hat elfutils through 25 those well defined interfaces identified in the file named EXCEPTION 26 found in the source code files (the "Approved Interfaces"). The files 27 of Non-GPL Code may instantiate templates or use macros or inline 28 functions from the Approved Interfaces without causing the resulting 29 work to be covered by the GNU General Public License. Only Red Hat, 30 Inc. may make changes or additions to the list of Approved Interfaces. 31 Red Hat's grant of this exception is conditioned upon your not adding 32 any new exceptions. If you wish to add a new Approved Interface or 33 exception, please contact Red Hat. You must obey the GNU General Public 34 License in all respects for all of the Red Hat elfutils code and other 35 code used in conjunction with Red Hat elfutils except the Non-GPL Code 36 covered by this exception. If you modify this file, you may extend this 37 exception to your version of the file, but you are not obligated to do 38 so. If you do not wish to provide this exception without modification, 39 you must delete this exception statement from your version and license 40 this file solely under the GPL without exception. 41 42 Red Hat elfutils is an included package of the Open Invention Network. 43 An included package of the Open Invention Network is a package for which 44 Open Invention Network licensees cross-license their patents. No patent 45 license is granted, either expressly or impliedly, by designation as an 46 included package. Should you wish to participate in the Open Invention 47 Network licensing program, please visit www.openinventionnetwork.com 48 <http://www.openinventionnetwork.com>. */ 49 50 #ifdef HAVE_CONFIG_H 51 # include <config.h> 52 #endif 53 54 #include "cfi.h" 55 #include "encoded-value.h" 56 57 #include <string.h> 58 59 60 int 61 dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry) 62 const unsigned char e_ident[]; 63 Elf_Data *data; 64 bool eh_frame_p; 65 Dwarf_Off off; 66 Dwarf_Off *next_off; 67 Dwarf_CFI_Entry *entry; 68 { 69 /* Dummy struct for memory-access.h macros. */ 70 BYTE_ORDER_DUMMY (dw, e_ident); 71 72 /* If we reached the end before don't do anything. */ 73 if (off == (Dwarf_Off) -1l 74 /* Make sure there is enough space in the .debug_frame section 75 for at least the initial word. We cannot test the rest since 76 we don't know yet whether this is a 64-bit object or not. */ 77 || unlikely (off + 4 >= data->d_size)) 78 { 79 *next_off = (Dwarf_Off) -1l; 80 return 1; 81 } 82 83 /* This points into the .debug_frame section at the start of the entry. */ 84 const uint8_t *bytes = data->d_buf + off; 85 const uint8_t *limit = data->d_buf + data->d_size; 86 87 /* The format of a CFI entry is described in DWARF3 6.4.1: 88 */ 89 90 uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes); 91 size_t offset_size = 4; 92 if (length == DWARF3_LENGTH_64_BIT) 93 { 94 /* This is the 64-bit DWARF format. */ 95 offset_size = 8; 96 if (unlikely (limit - bytes < 8)) 97 { 98 invalid: 99 __libdw_seterrno (DWARF_E_INVALID_DWARF); 100 return -1; 101 } 102 length = read_8ubyte_unaligned_inc (&dw, bytes); 103 } 104 if (unlikely ((uint64_t) (limit - bytes) < length) 105 || unlikely (length < offset_size + 1)) 106 goto invalid; 107 108 /* Now we know how large the entry is. Note the trick in the 109 computation. If the offset_size is 4 the '- 4' term undoes the 110 '2 *'. If offset_size is 8 this term computes the size of the 111 escape value plus the 8 byte offset. */ 112 *next_off = off + (2 * offset_size - 4) + length; 113 114 limit = bytes + length; 115 116 const uint8_t *const cie_pointer_start = bytes; 117 if (offset_size == 8) 118 entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes); 119 else 120 { 121 entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes); 122 /* Canonicalize the 32-bit CIE_ID value to 64 bits. */ 123 if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32) 124 entry->cie.CIE_id = DW_CIE_ID_64; 125 } 126 if (eh_frame_p) 127 { 128 /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */ 129 if (entry->cie.CIE_id == 0) 130 entry->cie.CIE_id = DW_CIE_ID_64; 131 else 132 { 133 /* In .eh_frame format, a CIE pointer is the distance from where 134 it appears back to the beginning of the CIE. */ 135 ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf; 136 if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos) 137 || unlikely (pos <= (ptrdiff_t) offset_size)) 138 goto invalid; 139 entry->cie.CIE_id = pos - entry->cie.CIE_id; 140 } 141 } 142 143 if (entry->cie.CIE_id == DW_CIE_ID_64) 144 { 145 /* Read the version stamp. Always an 8-bit value. */ 146 uint8_t version = *bytes++; 147 148 if (version != 1 && (unlikely (version < 3) || unlikely (version > 4))) 149 goto invalid; 150 151 entry->cie.augmentation = (const char *) bytes; 152 153 bytes = memchr (bytes, '\0', limit - bytes); 154 if (unlikely (bytes == NULL)) 155 goto invalid; 156 ++bytes; 157 158 /* The address size for CFI is implicit in the ELF class. */ 159 uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 160 uint_fast8_t segment_size = 0; 161 if (version >= 4) 162 { 163 if (unlikely (limit - bytes < 5)) 164 goto invalid; 165 /* XXX We don't actually support address_size not matching the class. 166 To do so, we'd have to return it here so that intern_new_cie 167 could use it choose a specific fde_encoding. */ 168 if (unlikely (*bytes != address_size)) 169 { 170 __libdw_seterrno (DWARF_E_VERSION); 171 return -1; 172 } 173 address_size = *bytes++; 174 segment_size = *bytes++; 175 /* We don't actually support segment selectors. We'd have to 176 roll this into the fde_encoding bits or something. */ 177 if (unlikely (segment_size != 0)) 178 { 179 __libdw_seterrno (DWARF_E_VERSION); 180 return -1; 181 } 182 } 183 184 const char *ap = entry->cie.augmentation; 185 186 /* g++ v2 "eh" has pointer immediately following augmentation string, 187 so it must be handled first. */ 188 if (unlikely (ap[0] == 'e' && ap[1] == 'h')) 189 { 190 ap += 2; 191 bytes += address_size; 192 } 193 194 get_uleb128 (entry->cie.code_alignment_factor, bytes); 195 get_sleb128 (entry->cie.data_alignment_factor, bytes); 196 197 if (version >= 3) /* DWARF 3+ */ 198 get_uleb128 (entry->cie.return_address_register, bytes); 199 else /* DWARF 2 */ 200 entry->cie.return_address_register = *bytes++; 201 202 /* If we have sized augmentation data, 203 we don't need to grok it all. */ 204 entry->cie.fde_augmentation_data_size = 0; 205 bool sized_augmentation = *ap == 'z'; 206 if (sized_augmentation) 207 { 208 get_uleb128 (entry->cie.augmentation_data_size, bytes); 209 if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size) 210 goto invalid; 211 entry->cie.augmentation_data = bytes; 212 bytes += entry->cie.augmentation_data_size; 213 } 214 else 215 { 216 entry->cie.augmentation_data = bytes; 217 218 for (; *ap != '\0'; ++ap) 219 { 220 uint8_t encoding; 221 switch (*ap) 222 { 223 case 'L': /* Skip LSDA pointer encoding byte. */ 224 case 'R': /* Skip FDE address encoding byte. */ 225 encoding = *bytes++; 226 entry->cie.fde_augmentation_data_size 227 += encoded_value_size (data, e_ident, encoding, NULL); 228 continue; 229 case 'P': /* Skip encoded personality routine pointer. */ 230 encoding = *bytes++; 231 bytes += encoded_value_size (data, e_ident, encoding, bytes); 232 continue; 233 case 'S': /* Skip signal-frame flag. */ 234 continue; 235 default: 236 /* Unknown augmentation string. initial_instructions might 237 actually start with some augmentation data. */ 238 break; 239 } 240 break; 241 } 242 entry->cie.augmentation_data_size 243 = bytes - entry->cie.augmentation_data; 244 } 245 246 entry->cie.initial_instructions = bytes; 247 entry->cie.initial_instructions_end = limit; 248 } 249 else 250 { 251 entry->fde.start = bytes; 252 entry->fde.end = limit; 253 } 254 255 return 0; 256 } 257 INTDEF (dwarf_next_cfi) 258