Branch data 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 : 1564 : __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
39 : : {
40 : 1564 : Dwarf_Off addr_off = __libdw_cu_addr_base (cu);
41 [ - + ]: 1564 : if (addr_off == (Dwarf_Off) -1)
42 : : return -1;
43 : :
44 : 1564 : Dwarf *dbg = cu->dbg;
45 [ - + ]: 1564 : 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 : 1564 : int address_size = cu->address_size;
53 [ - + ]: 1564 : 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 : 1564 : if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size
61 [ - + ]: 1564 : - address_size))
62 : 0 : goto invalid_offset;
63 : :
64 : 1564 : idx *= address_size;
65 : 1564 : if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size
66 [ - + ]: 1564 : - address_size - addr_off))
67 : 0 : goto invalid_offset;
68 : :
69 : 1564 : const unsigned char *datap;
70 : 1564 : datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx;
71 [ + + ]: 1564 : if (address_size == 4)
72 [ - + ]: 40 : *addr = read_4ubyte_unaligned (dbg, datap);
73 : : else
74 [ - + ]: 1524 : *addr = read_8ubyte_unaligned (dbg, datap);
75 : :
76 : : return 0;
77 : : }
78 : :
79 : : int
80 : 1893622 : dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
81 : : {
82 [ + + ]: 1893622 : if (attr == NULL)
83 : : return -1;
84 : :
85 : 373844 : Dwarf_Word idx;
86 : 373844 : Dwarf_CU *cu = attr->cu;
87 : 373844 : Dwarf *dbg = cu->dbg;
88 : 373844 : const unsigned char *datap = attr->valp;
89 : 373844 : const unsigned char *endp = attr->cu->endp;
90 [ + + - - : 373844 : switch (attr->form)
- - + ]
91 : : {
92 : : /* There is one form that just encodes the whole address. */
93 : 309758 : case DW_FORM_addr:
94 [ - + ]: 309758 : if (__libdw_read_address (dbg, cu_sec_idx (cu), datap,
95 : 309758 : 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 : 508 : case DW_FORM_GNU_addr_index:
102 : : case DW_FORM_addrx:
103 [ - + ]: 508 : if (datap >= endp)
104 : : {
105 : 0 : invalid:
106 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
107 : 0 : return -1;
108 : : }
109 : 508 : get_uleb128 (idx, datap, endp);
110 : 508 : break;
111 : :
112 : 0 : case DW_FORM_addrx1:
113 [ # # ]: 0 : if (datap >= endp - 1)
114 : 0 : goto invalid;
115 : 0 : idx = *datap;
116 : 0 : break;
117 : :
118 : 0 : case DW_FORM_addrx2:
119 [ # # ]: 0 : if (datap >= endp - 2)
120 : 0 : 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 : 0 : 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 : 0 : goto invalid;
133 [ # # ]: 0 : idx = read_4ubyte_unaligned (dbg, datap);
134 : : break;
135 : :
136 : 63578 : default:
137 : 63578 : __libdw_seterrno (DWARF_E_NO_ADDR);
138 : 63578 : 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 [ - + ]: 508 : if (__libdw_addrx (cu, idx, return_addr) != 0)
144 : : return -1;
145 : :
146 : : return 0;
147 : : }
148 : : INTDEF(dwarf_formaddr)
|