Branch data Line data Source code
1 : : /* Return DWARF attribute associated with a location expression op.
2 : : Copyright (C) 2013, 2014, 2017, 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 : : static Dwarf_CU *
37 : 78900 : attr_form_cu (Dwarf_Attribute *attr)
38 : : {
39 : : /* If the attribute has block/expr form the data comes from the
40 : : .debug_info from the same cu as the attr. Otherwise it comes from
41 : : the .debug_loc or .debug_loclists data section. */
42 [ + + ]: 78900 : switch (attr->form)
43 : : {
44 : 4386 : case DW_FORM_block1:
45 : : case DW_FORM_block2:
46 : : case DW_FORM_block4:
47 : : case DW_FORM_block:
48 : : case DW_FORM_exprloc:
49 : 4386 : return attr->cu;
50 : 74514 : default:
51 : 74514 : return (attr->cu->version < 5
52 : 36 : ? attr->cu->dbg->fake_loc_cu
53 [ + + ]: 74514 : : attr->cu->dbg->fake_loclists_cu);
54 : : }
55 : : }
56 : :
57 : : static unsigned char *
58 : 82 : addr_valp (Dwarf_CU *cu, Dwarf_Word index)
59 : : {
60 : 82 : Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
61 [ - + ]: 82 : if (debug_addr == NULL)
62 : : {
63 : 0 : __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
64 : 0 : return NULL;
65 : : }
66 : :
67 : 82 : Dwarf_Word offset = __libdw_cu_addr_base (cu) + (index * cu->address_size);
68 : 82 : return (unsigned char *) debug_addr->d_buf + offset;
69 : : }
70 : :
71 : : int
72 : 88274 : dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribute *result)
73 : : {
74 [ - + ]: 88274 : if (attr == NULL)
75 : : return -1;
76 : :
77 [ + + + + : 88274 : switch (op->atom)
+ - + - ]
78 : : {
79 : 1516 : case DW_OP_implicit_value:
80 : 1516 : result->code = DW_AT_const_value;
81 : 1516 : result->form = DW_FORM_block;
82 : 1516 : result->valp = (unsigned char *) (uintptr_t) op->number2;
83 : 1516 : result->cu = attr_form_cu (attr);
84 : 1516 : break;
85 : :
86 : 77382 : case DW_OP_entry_value:
87 : : case DW_OP_GNU_entry_value:
88 : 77382 : result->code = DW_AT_location;
89 : 77382 : result->form = DW_FORM_exprloc;
90 : 77382 : result->valp = (unsigned char *) (uintptr_t) op->number2;
91 : 77382 : result->cu = attr_form_cu (attr);
92 : 77382 : break;
93 : :
94 : 2 : case DW_OP_const_type:
95 : : case DW_OP_GNU_const_type:
96 : 2 : result->code = DW_AT_const_value;
97 : 2 : result->form = DW_FORM_block1;
98 : 2 : result->valp = (unsigned char *) (uintptr_t) op->number2;
99 : 2 : result->cu = attr_form_cu (attr);
100 : 2 : break;
101 : :
102 : 36 : case DW_OP_GNU_const_index:
103 : : case DW_OP_constx:
104 : 36 : result->code = DW_AT_const_value;
105 [ - + ]: 36 : if (attr->cu->address_size == 4)
106 : 0 : result->form = DW_FORM_data4;
107 : : else
108 : 36 : result->form = DW_FORM_data8;
109 : 36 : result->valp = addr_valp (attr->cu, op->number);
110 [ - + ]: 36 : if (result->valp == NULL)
111 : : return -1;
112 : 36 : result->cu = attr->cu->dbg->fake_addr_cu;
113 : 36 : break;
114 : :
115 : 46 : case DW_OP_GNU_addr_index:
116 : : case DW_OP_addrx:
117 : 46 : result->code = DW_AT_low_pc;
118 : 46 : result->form = DW_FORM_addr;
119 : 46 : result->valp = addr_valp (attr->cu, op->number);
120 [ - + ]: 46 : if (result->valp == NULL)
121 : : return -1;
122 : 46 : result->cu = attr->cu->dbg->fake_addr_cu;
123 : 46 : break;
124 : :
125 : 0 : case DW_OP_call2:
126 : : case DW_OP_call4:
127 : : case DW_OP_call_ref:
128 : : {
129 : 0 : Dwarf_Die die;
130 [ # # ]: 0 : if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
131 : 0 : return -1;
132 [ # # ]: 0 : if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
133 : : {
134 : 0 : __libdw_empty_loc_attr (result);
135 : 0 : return 0;
136 : : }
137 : : }
138 : 0 : break;
139 : :
140 : 9292 : case DW_OP_implicit_pointer:
141 : : case DW_OP_GNU_implicit_pointer:
142 : : case DW_OP_GNU_variable_value:
143 : : {
144 : 9292 : Dwarf_Die die;
145 [ + - ]: 9292 : if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
146 : 38 : return -1;
147 [ + + ]: 9292 : if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
148 [ + - ]: 38 : && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
149 : : {
150 : 38 : __libdw_empty_loc_attr (result);
151 : 38 : return 0;
152 : : }
153 : : }
154 : 9254 : break;
155 : :
156 : 0 : default:
157 : 0 : __libdw_seterrno (DWARF_E_INVALID_ACCESS);
158 : 0 : return -1;
159 : : }
160 : :
161 : : return 0;
162 : : }
|