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