summaryrefslogtreecommitdiffstats
path: root/src/libdw/dwarf_next_cfi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdw/dwarf_next_cfi.c')
-rw-r--r--src/libdw/dwarf_next_cfi.c246
1 files changed, 0 insertions, 246 deletions
diff --git a/src/libdw/dwarf_next_cfi.c b/src/libdw/dwarf_next_cfi.c
deleted file mode 100644
index b5af49e3..00000000
--- a/src/libdw/dwarf_next_cfi.c
+++ /dev/null
@@ -1,246 +0,0 @@
-/* Advance to next CFI entry.
- Copyright (C) 2009-2010, 2014 Red Hat, Inc.
- This file is part of elfutils.
-
- This file is free software; you can redistribute it and/or modify
- it under the terms of either
-
- * the GNU Lesser General Public License as published by the Free
- Software Foundation; either version 3 of the License, or (at
- your option) any later version
-
- or
-
- * the GNU General Public License as published by the Free
- Software Foundation; either version 2 of the License, or (at
- your option) any later version
-
- or both in parallel, as here.
-
- elfutils is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received copies of the GNU General Public License and
- the GNU Lesser General Public License along with this program. If
- not, see <http://www.gnu.org/licenses/>. */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include "cfi.h"
-#include "encoded-value.h"
-
-#include <string.h>
-
-
-int
-dwarf_next_cfi (e_ident, data, eh_frame_p, off, next_off, entry)
- const unsigned char e_ident[];
- Elf_Data *data;
- bool eh_frame_p;
- Dwarf_Off off;
- Dwarf_Off *next_off;
- Dwarf_CFI_Entry *entry;
-{
- /* Dummy struct for memory-access.h macros. */
- BYTE_ORDER_DUMMY (dw, e_ident);
-
- /* If we reached the end before don't do anything. */
- if (off == (Dwarf_Off) -1l
- /* Make sure there is enough space in the .debug_frame section
- for at least the initial word. We cannot test the rest since
- we don't know yet whether this is a 64-bit object or not. */
- || unlikely (off + 4 >= data->d_size))
- {
- *next_off = (Dwarf_Off) -1l;
- return 1;
- }
-
- /* This points into the .debug_frame section at the start of the entry. */
- const uint8_t *bytes = data->d_buf + off;
- const uint8_t *limit = data->d_buf + data->d_size;
-
- /* The format of a CFI entry is described in DWARF3 6.4.1:
- */
-
- uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
- size_t offset_size = 4;
- if (length == DWARF3_LENGTH_64_BIT)
- {
- /* This is the 64-bit DWARF format. */
- offset_size = 8;
- if (unlikely (limit - bytes < 8))
- {
- invalid:
- __libdw_seterrno (DWARF_E_INVALID_DWARF);
- return -1;
- }
- length = read_8ubyte_unaligned_inc (&dw, bytes);
- }
- if (unlikely ((uint64_t) (limit - bytes) < length)
- || unlikely (length < offset_size + 1))
- goto invalid;
-
- /* Now we know how large the entry is. Note the trick in the
- computation. If the offset_size is 4 the '- 4' term undoes the
- '2 *'. If offset_size is 8 this term computes the size of the
- escape value plus the 8 byte offset. */
- *next_off = off + (2 * offset_size - 4) + length;
-
- limit = bytes + length;
-
- const uint8_t *const cie_pointer_start = bytes;
- if (offset_size == 8)
- entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
- else
- {
- entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
- /* Canonicalize the 32-bit CIE_ID value to 64 bits. */
- if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
- entry->cie.CIE_id = DW_CIE_ID_64;
- }
- if (eh_frame_p)
- {
- /* Canonicalize the .eh_frame CIE pointer to .debug_frame format. */
- if (entry->cie.CIE_id == 0)
- entry->cie.CIE_id = DW_CIE_ID_64;
- else
- {
- /* In .eh_frame format, a CIE pointer is the distance from where
- it appears back to the beginning of the CIE. */
- ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
- if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
- || unlikely (pos <= (ptrdiff_t) offset_size))
- goto invalid;
- entry->cie.CIE_id = pos - entry->cie.CIE_id;
- }
- }
-
- if (entry->cie.CIE_id == DW_CIE_ID_64)
- {
- /* Read the version stamp. Always an 8-bit value. */
- uint8_t version = *bytes++;
-
- if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
- goto invalid;
-
- entry->cie.augmentation = (const char *) bytes;
-
- bytes = memchr (bytes, '\0', limit - bytes);
- if (unlikely (bytes == NULL))
- goto invalid;
- ++bytes;
-
- /* The address size for CFI is implicit in the ELF class. */
- uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
- uint_fast8_t segment_size = 0;
- if (version >= 4)
- {
- if (unlikely (limit - bytes < 5))
- goto invalid;
- /* XXX We don't actually support address_size not matching the class.
- To do so, we'd have to return it here so that intern_new_cie
- could use it choose a specific fde_encoding. */
- if (unlikely (*bytes != address_size))
- {
- __libdw_seterrno (DWARF_E_VERSION);
- return -1;
- }
- address_size = *bytes++;
- segment_size = *bytes++;
- /* We don't actually support segment selectors. We'd have to
- roll this into the fde_encoding bits or something. */
- if (unlikely (segment_size != 0))
- {
- __libdw_seterrno (DWARF_E_VERSION);
- return -1;
- }
- }
-
- const char *ap = entry->cie.augmentation;
-
- /* g++ v2 "eh" has pointer immediately following augmentation string,
- so it must be handled first. */
- if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
- {
- ap += 2;
- bytes += address_size;
- }
-
- if (bytes >= limit)
- goto invalid;
- get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
-
- if (bytes >= limit)
- goto invalid;
- get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
-
- if (bytes >= limit)
- goto invalid;
-
- if (version >= 3) /* DWARF 3+ */
- get_uleb128 (entry->cie.return_address_register, bytes, limit);
- else /* DWARF 2 */
- entry->cie.return_address_register = *bytes++;
-
- /* If we have sized augmentation data,
- we don't need to grok it all. */
- entry->cie.fde_augmentation_data_size = 0;
- bool sized_augmentation = *ap == 'z';
- if (sized_augmentation)
- {
- if (bytes >= limit)
- goto invalid;
- get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
- if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
- goto invalid;
- entry->cie.augmentation_data = bytes;
- bytes += entry->cie.augmentation_data_size;
- }
- else
- {
- entry->cie.augmentation_data = bytes;
-
- for (; *ap != '\0'; ++ap)
- {
- uint8_t encoding;
- switch (*ap)
- {
- case 'L': /* Skip LSDA pointer encoding byte. */
- case 'R': /* Skip FDE address encoding byte. */
- encoding = *bytes++;
- entry->cie.fde_augmentation_data_size
- += encoded_value_size (data, e_ident, encoding, NULL);
- continue;
- case 'P': /* Skip encoded personality routine pointer. */
- encoding = *bytes++;
- bytes += encoded_value_size (data, e_ident, encoding, bytes);
- continue;
- case 'S': /* Skip signal-frame flag. */
- continue;
- default:
- /* Unknown augmentation string. initial_instructions might
- actually start with some augmentation data. */
- break;
- }
- break;
- }
- entry->cie.augmentation_data_size
- = bytes - entry->cie.augmentation_data;
- }
-
- entry->cie.initial_instructions = bytes;
- entry->cie.initial_instructions_end = limit;
- }
- else
- {
- entry->fde.start = bytes;
- entry->fde.end = limit;
- }
-
- return 0;
-}
-INTDEF (dwarf_next_cfi)