LCOV - code coverage report
Current view: top level - libdw - dwarf_next_cfi.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 61 87 70.1 %
Date: 2017-01-05 09:15:16 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        8771 : 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        8771 :   BYTE_ORDER_DUMMY (dw, e_ident);
      49             : 
      50             :   /* If we reached the end before don't do anything.  */
      51        8771 :   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        8743 :       || unlikely (off + 4 >= data->d_size))
      56             :     {
      57          38 :       *next_off = (Dwarf_Off) -1l;
      58          38 :       return 1;
      59             :     }
      60             : 
      61             :   /* This points into the .debug_frame section at the start of the entry.  */
      62        8733 :   const uint8_t *bytes = data->d_buf + off;
      63        8733 :   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       13192 :   uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
      69        8733 :   size_t offset_size = 4;
      70        8733 :   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             :         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        8733 :   if (unlikely ((uint64_t) (limit - bytes) < length)
      83        8733 :       || 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        8733 :   *next_off = off + (2 * offset_size - 4) + length;
      91             : 
      92        8733 :   limit = bytes + length;
      93             : 
      94        8733 :   const uint8_t *const cie_pointer_start = bytes;
      95        8733 :   if (offset_size == 8)
      96           0 :     entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
      97             :   else
      98             :     {
      99       13192 :       entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
     100             :       /* Canonicalize the 32-bit CIE_ID value to 64 bits.  */
     101        8733 :       if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
     102          14 :         entry->cie.CIE_id = DW_CIE_ID_64;
     103             :     }
     104        8733 :   if (eh_frame_p)
     105             :     {
     106             :       /* Canonicalize the .eh_frame CIE pointer to .debug_frame format.  */
     107        8691 :       if (entry->cie.CIE_id == 0)
     108          77 :         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        8614 :           ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
     114        8614 :           if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
     115        8614 :               || unlikely (pos <= (ptrdiff_t) offset_size))
     116             :             goto invalid;
     117        8614 :           entry->cie.CIE_id = pos - entry->cie.CIE_id;
     118             :         }
     119             :     }
     120             : 
     121        8733 :   if (entry->cie.CIE_id == DW_CIE_ID_64)
     122             :     {
     123             :       /* Read the version stamp.  Always an 8-bit value.  */
     124          91 :       uint8_t version = *bytes++;
     125             : 
     126          91 :       if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
     127             :         goto invalid;
     128             : 
     129          91 :       entry->cie.augmentation = (const char *) bytes;
     130             : 
     131          91 :       bytes = memchr (bytes, '\0', limit - bytes);
     132          91 :       if (unlikely (bytes == NULL))
     133             :         goto invalid;
     134          91 :       ++bytes;
     135             : 
     136             :       /* The address size for CFI is implicit in the ELF class.  */
     137          91 :       uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
     138          91 :       uint_fast8_t segment_size = 0;
     139          91 :       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          91 :       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          91 :       if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
     167             :         {
     168           0 :           ap += 2;
     169           0 :           bytes += address_size;
     170             :         }
     171             : 
     172          91 :       if (bytes >= limit)
     173             :         goto invalid;
     174          91 :       get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
     175             : 
     176          91 :       if (bytes >= limit)
     177             :         goto invalid;
     178          91 :       get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
     179             : 
     180          91 :       if (bytes >= limit)
     181             :         goto invalid;
     182             : 
     183          91 :       if (version >= 3)              /* DWARF 3+ */
     184           0 :         get_uleb128 (entry->cie.return_address_register, bytes, limit);
     185             :       else                      /* DWARF 2 */
     186          91 :         entry->cie.return_address_register = *bytes++;
     187             : 
     188             :       /* If we have sized augmentation data,
     189             :          we don't need to grok it all.  */
     190          91 :       entry->cie.fde_augmentation_data_size = 0;
     191          91 :       bool sized_augmentation = *ap == 'z';
     192          91 :       if (sized_augmentation)
     193             :         {
     194          77 :           if (bytes >= limit)
     195             :             goto invalid;
     196          77 :           get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
     197          77 :           if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
     198             :             goto invalid;
     199          77 :           entry->cie.augmentation_data = bytes;
     200          77 :           bytes += entry->cie.augmentation_data_size;
     201             :         }
     202             :       else
     203             :         {
     204          14 :           entry->cie.augmentation_data = bytes;
     205             : 
     206          14 :           for (; *ap != '\0'; ++ap)
     207             :             {
     208             :               uint8_t encoding;
     209           0 :               switch (*ap)
     210             :                 {
     211             :                 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             :                 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             :                 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          14 :             = bytes - entry->cie.augmentation_data;
     232             :         }
     233             : 
     234          91 :       entry->cie.initial_instructions = bytes;
     235          91 :       entry->cie.initial_instructions_end = limit;
     236             :     }
     237             :   else
     238             :     {
     239        8642 :       entry->fde.start = bytes;
     240        8642 :       entry->fde.end = limit;
     241             :     }
     242             : 
     243             :   return 0;
     244             : }
     245             : INTDEF (dwarf_next_cfi)

Generated by: LCOV version 1.12