LCOV - code coverage report
Current view: top level - libdw - dwarf_next_cfi.c (source / functions) Hit Total Coverage
Test: elfutils-0.172 Lines: 61 91 67.0 %
Date: 2018-06-11 22:52:14 Functions: 1 1 100.0 %
Legend: Lines: hit not hit

          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       17646 : 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       17646 :   BYTE_ORDER_DUMMY (dw, e_ident);
      49             : 
      50             :   /* If we reached the end before don't do anything.  */
      51       17646 :   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       17549 :       || unlikely (off + 4 >= data->d_size))
      56             :     {
      57         117 :       *next_off = (Dwarf_Off) -1l;
      58         117 :       return 1;
      59             :     }
      60             : 
      61             :   /* This points into the .debug_frame section at the start of the entry.  */
      62       17529 :   const uint8_t *bytes = data->d_buf + off;
      63       17529 :   const uint8_t *limit = data->d_buf + data->d_size;
      64             : 
      65             :   /* The format of a CFI entry is described in DWARF3 6.4.1:
      66             :    */
      67             : 
      68       21975 :   uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
      69       17529 :   size_t offset_size = 4;
      70       17529 :   if (length == DWARF3_LENGTH_64_BIT)
      71             :     {
      72             :       /* This is the 64-bit DWARF format.  */
      73           0 :       offset_size = 8;
      74           0 :       if (unlikely (limit - bytes < 8))
      75             :         {
      76           0 :         invalid:
      77           0 :           __libdw_seterrno (DWARF_E_INVALID_DWARF);
      78           0 :           return -1;
      79             :         }
      80           0 :       length = read_8ubyte_unaligned_inc (&dw, bytes);
      81             :     }
      82       17529 :   if (unlikely ((uint64_t) (limit - bytes) < length)
      83       17529 :       || unlikely (length < offset_size + 1))
      84             :     goto invalid;
      85             : 
      86             :   /* Now we know how large the entry is.  Note the trick in the
      87             :      computation.  If the offset_size is 4 the '- 4' term undoes the
      88             :      '2 *'.  If offset_size is 8 this term computes the size of the
      89             :      escape value plus the 8 byte offset.  */
      90       17529 :   *next_off = off + (2 * offset_size - 4) + length;
      91             : 
      92       17529 :   limit = bytes + length;
      93             : 
      94       17529 :   const uint8_t *const cie_pointer_start = bytes;
      95       17529 :   if (offset_size == 8)
      96           0 :     entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
      97             :   else
      98             :     {
      99       21975 :       entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
     100             :       /* Canonicalize the 32-bit CIE_ID value to 64 bits.  */
     101       17529 :       if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
     102          31 :         entry->cie.CIE_id = DW_CIE_ID_64;
     103             :     }
     104       17529 :   if (eh_frame_p)
     105             :     {
     106             :       /* Canonicalize the .eh_frame CIE pointer to .debug_frame format.  */
     107       17414 :       if (entry->cie.CIE_id == 0)
     108         129 :         entry->cie.CIE_id = DW_CIE_ID_64;
     109             :       else
     110             :         {
     111             :           /* In .eh_frame format, a CIE pointer is the distance from where
     112             :              it appears back to the beginning of the CIE.  */
     113       17285 :           ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
     114       17285 :           if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
     115       17285 :               || unlikely (pos <= (ptrdiff_t) offset_size))
     116             :             goto invalid;
     117       17285 :           entry->cie.CIE_id = pos - entry->cie.CIE_id;
     118             :         }
     119             :     }
     120             : 
     121       17529 :   if (entry->cie.CIE_id == DW_CIE_ID_64)
     122             :     {
     123             :       /* Read the version stamp.  Always an 8-bit value.  */
     124         160 :       uint8_t version = *bytes++;
     125             : 
     126         160 :       if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
     127             :         goto invalid;
     128             : 
     129         160 :       entry->cie.augmentation = (const char *) bytes;
     130             : 
     131         160 :       bytes = memchr (bytes, '\0', limit - bytes);
     132         160 :       if (unlikely (bytes == NULL))
     133             :         goto invalid;
     134         160 :       ++bytes;
     135             : 
     136             :       /* The address size for CFI is implicit in the ELF class.  */
     137         160 :       uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
     138         160 :       uint_fast8_t segment_size = 0;
     139         160 :       if (version >= 4)
     140             :         {
     141           0 :           if (unlikely (limit - bytes < 5))
     142             :             goto invalid;
     143             :           /* XXX We don't actually support address_size not matching the class.
     144             :              To do so, we'd have to return it here so that intern_new_cie
     145             :              could use it choose a specific fde_encoding.  */
     146           0 :           if (unlikely (*bytes != address_size))
     147             :             {
     148           0 :               __libdw_seterrno (DWARF_E_VERSION);
     149           0 :               return -1;
     150             :             }
     151           0 :           address_size = *bytes++;
     152           0 :           segment_size = *bytes++;
     153             :           /* We don't actually support segment selectors.  We'd have to
     154             :              roll this into the fde_encoding bits or something.  */
     155           0 :           if (unlikely (segment_size != 0))
     156             :             {
     157           0 :               __libdw_seterrno (DWARF_E_VERSION);
     158           0 :               return -1;
     159             :             }
     160             :         }
     161             : 
     162         160 :       const char *ap = entry->cie.augmentation;
     163             : 
     164             :       /* g++ v2 "eh" has pointer immediately following augmentation string,
     165             :          so it must be handled first.  */
     166         160 :       if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
     167             :         {
     168           0 :           ap += 2;
     169           0 :           bytes += address_size;
     170             :         }
     171             : 
     172         160 :       if (bytes >= limit)
     173             :         goto invalid;
     174         160 :       get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
     175             : 
     176         160 :       if (bytes >= limit)
     177             :         goto invalid;
     178         160 :       get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
     179             : 
     180         160 :       if (bytes >= limit)
     181             :         goto invalid;
     182             : 
     183         160 :       if (version >= 3)              /* DWARF 3+ */
     184           0 :         get_uleb128 (entry->cie.return_address_register, bytes, limit);
     185             :       else                      /* DWARF 2 */
     186         160 :         entry->cie.return_address_register = *bytes++;
     187             : 
     188             :       /* If we have sized augmentation data,
     189             :          we don't need to grok it all.  */
     190         160 :       entry->cie.fde_augmentation_data_size = 0;
     191         160 :       bool sized_augmentation = *ap == 'z';
     192         160 :       if (sized_augmentation)
     193             :         {
     194         129 :           if (bytes >= limit)
     195             :             goto invalid;
     196         129 :           get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
     197         129 :           if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
     198             :             goto invalid;
     199         129 :           entry->cie.augmentation_data = bytes;
     200         129 :           bytes += entry->cie.augmentation_data_size;
     201             :         }
     202             :       else
     203             :         {
     204          31 :           entry->cie.augmentation_data = bytes;
     205             : 
     206          31 :           for (; *ap != '\0'; ++ap)
     207             :             {
     208             :               uint8_t encoding;
     209           0 :               switch (*ap)
     210             :                 {
     211           0 :                 case 'L':               /* Skip LSDA pointer encoding byte.  */
     212             :                 case 'R':               /* Skip FDE address encoding byte.  */
     213           0 :                   encoding = *bytes++;
     214             :                   entry->cie.fde_augmentation_data_size
     215           0 :                     += encoded_value_size (data, e_ident, encoding, NULL);
     216           0 :                   continue;
     217           0 :                 case 'P':   /* Skip encoded personality routine pointer. */
     218           0 :                   encoding = *bytes++;
     219           0 :                   bytes += encoded_value_size (data, e_ident, encoding, bytes);
     220           0 :                   continue;
     221           0 :                 case 'S':               /* Skip signal-frame flag.  */
     222           0 :                   continue;
     223             :                 default:
     224             :                   /* Unknown augmentation string.  initial_instructions might
     225             :                      actually start with some augmentation data.  */
     226             :                   break;
     227             :                 }
     228             :               break;
     229             :             }
     230             :           entry->cie.augmentation_data_size
     231          31 :             = bytes - entry->cie.augmentation_data;
     232             :         }
     233             : 
     234         160 :       entry->cie.initial_instructions = bytes;
     235         160 :       entry->cie.initial_instructions_end = limit;
     236             :     }
     237             :   else
     238             :     {
     239       17369 :       entry->fde.start = bytes;
     240       17369 :       entry->fde.end = limit;
     241             :     }
     242             : 
     243             :   return 0;
     244             : }
     245             : INTDEF (dwarf_next_cfi)

Generated by: LCOV version 1.13