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

Generated by: LCOV version 1.13