• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
__libdw_addrx(Dwarf_CU * cu,Dwarf_Word idx,Dwarf_Addr * addr)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
dwarf_formaddr(Dwarf_Attribute * attr,Dwarf_Addr * return_addr)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