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 : 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 : switch (attr->form)
43 : {
44 : 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 : return attr->cu;
50 : default:
51 55082 : return (attr->cu->version < 5
52 27523 : ? attr->cu->dbg->fake_loc_cu
53 18 : : attr->cu->dbg->fake_loclists_cu);
54 : }
55 : }
56 :
57 : static unsigned char *
58 37 : addr_valp (Dwarf_CU *cu, Dwarf_Word index)
59 : {
60 37 : Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
61 37 : if (debug_addr == NULL)
62 : {
63 0 : __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
64 0 : return NULL;
65 : }
66 :
67 37 : Dwarf_Word offset = __libdw_cu_addr_base (cu) + (index * cu->address_size);
68 37 : return (unsigned char *) debug_addr->d_buf + offset;
69 : }
70 :
71 : int
72 93636 : dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribute *result)
73 : {
74 35436 : if (attr == NULL)
75 : return -1;
76 :
77 35436 : switch (op->atom)
78 : {
79 : case DW_OP_implicit_value:
80 604 : result->code = DW_AT_const_value;
81 604 : result->form = DW_FORM_block;
82 604 : result->valp = (unsigned char *) (uintptr_t) op->number2;
83 1812 : result->cu = attr_form_cu (attr);
84 604 : break;
85 :
86 : case DW_OP_entry_value:
87 : case DW_OP_GNU_entry_value:
88 28492 : result->code = DW_AT_location;
89 28492 : result->form = DW_FORM_exprloc;
90 28492 : result->valp = (unsigned char *) (uintptr_t) op->number2;
91 85476 : result->cu = attr_form_cu (attr);
92 28492 : break;
93 :
94 : case DW_OP_const_type:
95 : case DW_OP_GNU_const_type:
96 4 : result->code = DW_AT_const_value;
97 4 : result->form = DW_FORM_block1;
98 4 : result->valp = (unsigned char *) (uintptr_t) op->number2;
99 12 : result->cu = attr_form_cu (attr);
100 4 : break;
101 :
102 : case DW_OP_GNU_const_index:
103 : case DW_OP_constx:
104 18 : result->code = DW_AT_const_value;
105 18 : if (attr->cu->address_size == 4)
106 0 : result->form = DW_FORM_data4;
107 : else
108 18 : result->form = DW_FORM_data8;
109 18 : result->valp = addr_valp (attr->cu, op->number);
110 18 : if (result->valp == NULL)
111 : return -1;
112 18 : result->cu = attr->cu->dbg->fake_addr_cu;
113 18 : break;
114 :
115 : case DW_OP_GNU_addr_index:
116 : case DW_OP_addrx:
117 19 : result->code = DW_AT_low_pc;
118 19 : result->form = DW_FORM_addr;
119 19 : result->valp = addr_valp (attr->cu, op->number);
120 19 : if (result->valp == NULL)
121 : return -1;
122 19 : result->cu = attr->cu->dbg->fake_addr_cu;
123 19 : break;
124 :
125 : case DW_OP_call2:
126 : case DW_OP_call4:
127 : case DW_OP_call_ref:
128 : {
129 : 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 : case DW_OP_implicit_pointer:
141 : case DW_OP_GNU_implicit_pointer:
142 : case DW_OP_GNU_variable_value:
143 : {
144 : Dwarf_Die die;
145 6299 : if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
146 18 : return -1;
147 6299 : if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
148 18 : && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
149 : {
150 18 : __libdw_empty_loc_attr (result);
151 18 : return 0;
152 : }
153 : }
154 6281 : break;
155 :
156 : default:
157 0 : __libdw_seterrno (DWARF_E_INVALID_ACCESS);
158 0 : return -1;
159 : }
160 :
161 : return 0;
162 : }
|