Home | History | Annotate | Download | only in libdw
      1 /* Return address represented by attribute.
      2    Copyright (C) 2003-2010, 2018 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 <dwarf.h>
     34 #include "libdwP.h"
     35 
     36 
     37 int
     38 __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
     39 {
     40   Dwarf_Off addr_off = __libdw_cu_addr_base (cu);
     41   if (addr_off == (Dwarf_Off) -1)
     42     return -1;
     43 
     44   Dwarf *dbg = cu->dbg;
     45   if (dbg->sectiondata[IDX_debug_addr] == NULL)
     46     {
     47       __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
     48       return -1;
     49     }
     50 
     51   /* The section should at least contain room for one address.  */
     52   int address_size = cu->address_size;
     53   if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size)
     54     {
     55     invalid_offset:
     56       __libdw_seterrno (DWARF_E_INVALID_OFFSET);
     57       return -1;
     58     }
     59 
     60   if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size
     61 		  - address_size))
     62     goto invalid_offset;
     63 
     64   idx *= address_size;
     65   if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size
     66 	     - address_size - addr_off))
     67     goto invalid_offset;
     68 
     69   const unsigned char *datap;
     70   datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx;
     71   if (address_size == 4)
     72     *addr = read_4ubyte_unaligned (dbg, datap);
     73   else
     74     *addr = read_8ubyte_unaligned (dbg, datap);
     75 
     76   return 0;
     77 }
     78 
     79 int
     80 dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
     81 {
     82   if (attr == NULL)
     83     return -1;
     84 
     85   Dwarf_Word idx;
     86   Dwarf_CU *cu = attr->cu;
     87   Dwarf *dbg = cu->dbg;
     88   const unsigned char *datap = attr->valp;
     89   const unsigned char *endp = attr->cu->endp;
     90   switch (attr->form)
     91     {
     92       /* There is one form that just encodes the whole address.  */
     93       case DW_FORM_addr:
     94 	if (__libdw_read_address (dbg, cu_sec_idx (cu), datap,
     95 				  cu->address_size, return_addr))
     96 	  return -1;
     97 	return 0;
     98 
     99       /* All others encode an index into the .debug_addr section where
    100 	 the address can be found.  */
    101       case DW_FORM_GNU_addr_index:
    102       case DW_FORM_addrx:
    103 	if (datap >= endp)
    104 	  {
    105 	  invalid:
    106 	    __libdw_seterrno (DWARF_E_INVALID_DWARF);
    107 	    return -1;
    108 	  }
    109 	get_uleb128 (idx, datap, endp);
    110 	break;
    111 
    112       case DW_FORM_addrx1:
    113 	if (datap >= endp - 1)
    114 	  goto invalid;
    115 	idx = *datap;
    116 	break;
    117 
    118       case DW_FORM_addrx2:
    119 	if (datap >= endp - 2)
    120 	  goto invalid;
    121 	idx = read_2ubyte_unaligned (dbg, datap);
    122 	break;
    123 
    124       case DW_FORM_addrx3:
    125 	if (datap >= endp - 3)
    126 	  goto invalid;
    127 	idx = read_3ubyte_unaligned (dbg, datap);
    128 	break;
    129 
    130       case DW_FORM_addrx4:
    131 	if (datap >= endp - 4)
    132 	  goto invalid;
    133 	idx = read_4ubyte_unaligned (dbg, datap);
    134 	break;
    135 
    136       default:
    137 	__libdw_seterrno (DWARF_E_NO_ADDR);
    138 	return -1;
    139     }
    140 
    141   /* So we got an index.  Lets see if it is valid and we can get the actual
    142      address.  */
    143   if (__libdw_addrx (cu, idx, return_addr) != 0)
    144     return -1;
    145 
    146   return 0;
    147 }
    148 INTDEF(dwarf_formaddr)
    149