Home | History | Annotate | Download | only in libdw
      1 /* Return unsigned constant represented by attribute.
      2    Copyright (C) 2003-2012, 2014 Red Hat, Inc.
      3    This file is part of elfutils.
      4    Written by Ulrich Drepper <drepper (at) redhat.com>, 2003.
      5 
      6    This file is free software; you can redistribute it and/or modify
      7    it under the terms of either
      8 
      9      * the GNU Lesser General Public License as published by the Free
     10        Software Foundation; either version 3 of the License, or (at
     11        your option) any later version
     12 
     13    or
     14 
     15      * the GNU General Public License as published by the Free
     16        Software Foundation; either version 2 of the License, or (at
     17        your option) any later version
     18 
     19    or both in parallel, as here.
     20 
     21    elfutils is distributed in the hope that it will be useful, but
     22    WITHOUT ANY WARRANTY; without even the implied warranty of
     23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24    General Public License for more details.
     25 
     26    You should have received copies of the GNU General Public License and
     27    the GNU Lesser General Public License along with this program.  If
     28    not, see <http://www.gnu.org/licenses/>.  */
     29 
     30 #ifdef HAVE_CONFIG_H
     31 # include <config.h>
     32 #endif
     33 
     34 #include <dwarf.h>
     35 #include "libdwP.h"
     36 
     37 internal_function unsigned char *
     38 __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
     39 		 int err_nodata, unsigned char **endpp,
     40 		 Dwarf_Off *offsetp)
     41 {
     42   if (attr == NULL)
     43     return NULL;
     44 
     45   const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
     46   if (unlikely (d == NULL))
     47     {
     48       __libdw_seterrno (err_nodata);
     49       return NULL;
     50     }
     51 
     52   Dwarf_Word offset;
     53   if (attr->form == DW_FORM_sec_offset)
     54     {
     55       if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
     56 			       cu_sec_idx (attr->cu), attr->valp,
     57 			       attr->cu->offset_size, &offset, sec_index, 0))
     58 	return NULL;
     59     }
     60   else if (attr->cu->version > 3)
     61     goto invalid;
     62   else
     63     switch (attr->form)
     64       {
     65       case DW_FORM_data4:
     66       case DW_FORM_data8:
     67 	if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
     68 				 cu_sec_idx (attr->cu),
     69 				 attr->valp,
     70 				 attr->form == DW_FORM_data4 ? 4 : 8,
     71 				 &offset, sec_index, 0))
     72 	  return NULL;
     73 	break;
     74 
     75       default:
     76 	if (INTUSE(dwarf_formudata) (attr, &offset))
     77 	  return NULL;
     78       };
     79 
     80   unsigned char *readp = d->d_buf + offset;
     81   unsigned char *endp = d->d_buf + d->d_size;
     82   if (unlikely (readp >= endp))
     83     {
     84     invalid:
     85       __libdw_seterrno (DWARF_E_INVALID_DWARF);
     86       return NULL;
     87     }
     88 
     89   if (endpp != NULL)
     90     *endpp = endp;
     91   if (offsetp != NULL)
     92     *offsetp = offset;
     93   return readp;
     94 }
     95 
     96 int
     97 dwarf_formudata (attr, return_uval)
     98      Dwarf_Attribute *attr;
     99      Dwarf_Word *return_uval;
    100 {
    101   if (attr == NULL)
    102     return -1;
    103 
    104   const unsigned char *datap = attr->valp;
    105   const unsigned char *endp = attr->cu->endp;
    106 
    107   switch (attr->form)
    108     {
    109     case DW_FORM_data1:
    110       if (datap + 1 > endp)
    111 	{
    112 	invalid:
    113 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
    114 	  return -1;
    115 	}
    116       *return_uval = *attr->valp;
    117       break;
    118 
    119     case DW_FORM_data2:
    120       if (datap + 2 > endp)
    121 	goto invalid;
    122       *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
    123       break;
    124 
    125     case DW_FORM_data4:
    126     case DW_FORM_data8:
    127     case DW_FORM_sec_offset:
    128       /* Before DWARF4 data4 and data8 are pure constants unless the
    129 	 attribute also allows offsets (*ptr classes), since DWARF4
    130 	 they are always just constants (start_scope is special though,
    131 	 since it only could express a rangelist since DWARF4).  */
    132       if (attr->form == DW_FORM_sec_offset
    133 	  || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
    134 	{
    135 	  switch (attr->code)
    136 	    {
    137 	    case DW_AT_data_member_location:
    138 	    case DW_AT_frame_base:
    139 	    case DW_AT_location:
    140 	    case DW_AT_return_addr:
    141 	    case DW_AT_segment:
    142 	    case DW_AT_static_link:
    143 	    case DW_AT_string_length:
    144 	    case DW_AT_use_location:
    145 	    case DW_AT_vtable_elem_location:
    146 	      /* loclistptr */
    147 	      if (__libdw_formptr (attr, IDX_debug_loc,
    148 				   DWARF_E_NO_LOCLIST, NULL,
    149 				   return_uval) == NULL)
    150 		return -1;
    151 	      break;
    152 
    153 	    case DW_AT_macro_info:
    154 	      /* macptr into .debug_macinfo */
    155 	      if (__libdw_formptr (attr, IDX_debug_macinfo,
    156 				   DWARF_E_NO_ENTRY, NULL,
    157 				   return_uval) == NULL)
    158 		return -1;
    159 	      break;
    160 
    161 	    case DW_AT_GNU_macros:
    162 	      /* macptr into .debug_macro */
    163 	      if (__libdw_formptr (attr, IDX_debug_macro,
    164 				   DWARF_E_NO_ENTRY, NULL,
    165 				   return_uval) == NULL)
    166 		return -1;
    167 	      break;
    168 
    169 	    case DW_AT_ranges:
    170 	    case DW_AT_start_scope:
    171 	      /* rangelistptr */
    172 	      if (__libdw_formptr (attr, IDX_debug_ranges,
    173 				   DWARF_E_NO_DEBUG_RANGES, NULL,
    174 				   return_uval) == NULL)
    175 		return -1;
    176 	      break;
    177 
    178 	    case DW_AT_stmt_list:
    179 	      /* lineptr */
    180 	      if (__libdw_formptr (attr, IDX_debug_line,
    181 				   DWARF_E_NO_DEBUG_LINE, NULL,
    182 				   return_uval) == NULL)
    183 		return -1;
    184 	      break;
    185 
    186 	    default:
    187 	      /* sec_offset can only be used by one of the above attrs.  */
    188 	      if (attr->form == DW_FORM_sec_offset)
    189 		{
    190 		  __libdw_seterrno (DWARF_E_INVALID_DWARF);
    191 		  return -1;
    192 		}
    193 
    194 	      /* Not one of the special attributes, just a constant.  */
    195 	      if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
    196 					attr->valp,
    197 					attr->form == DW_FORM_data4 ? 4 : 8,
    198 					return_uval))
    199 		return -1;
    200 	      break;
    201 	    }
    202 	}
    203       else
    204 	{
    205 	  /* We are dealing with a constant data4 or data8.  */
    206 	  if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
    207 				    attr->valp,
    208 				    attr->form == DW_FORM_data4 ? 4 : 8,
    209 				    return_uval))
    210 	    return -1;
    211 	}
    212       break;
    213 
    214     case DW_FORM_sdata:
    215       if (datap + 1 > endp)
    216 	goto invalid;
    217       get_sleb128 (*return_uval, datap, endp);
    218       break;
    219 
    220     case DW_FORM_udata:
    221       if (datap + 1 > endp)
    222 	goto invalid;
    223       get_uleb128 (*return_uval, datap, endp);
    224       break;
    225 
    226     default:
    227       __libdw_seterrno (DWARF_E_NO_CONSTANT);
    228       return -1;
    229     }
    230 
    231   return 0;
    232 }
    233 INTDEF(dwarf_formudata)
    234