Line data Source code
1 : /* Return DWARF attribute associated with a location expression op.
2 : Copyright (C) 2013, 2014 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 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 6 : return attr->cu->dbg->fake_loc_cu;
52 : }
53 : }
54 :
55 : int
56 10 : dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribute *result)
57 : {
58 10 : if (attr == NULL)
59 : return -1;
60 :
61 10 : switch (op->atom)
62 : {
63 : case DW_OP_implicit_value:
64 2 : result->code = DW_AT_const_value;
65 2 : result->form = DW_FORM_block;
66 2 : result->valp = (unsigned char *) (uintptr_t) op->number2;
67 4 : result->cu = attr_form_cu (attr);
68 2 : break;
69 :
70 : case DW_OP_GNU_entry_value:
71 6 : result->code = DW_AT_location;
72 6 : result->form = DW_FORM_exprloc;
73 6 : result->valp = (unsigned char *) (uintptr_t) op->number2;
74 12 : result->cu = attr_form_cu (attr);
75 6 : break;
76 :
77 : case DW_OP_GNU_const_type:
78 1 : result->code = DW_AT_const_value;
79 1 : result->form = DW_FORM_block1;
80 1 : result->valp = (unsigned char *) (uintptr_t) op->number2;
81 2 : result->cu = attr_form_cu (attr);
82 1 : break;
83 :
84 : case DW_OP_call2:
85 : case DW_OP_call4:
86 : case DW_OP_call_ref:
87 : {
88 : Dwarf_Die die;
89 0 : if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
90 0 : return -1;
91 0 : if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
92 : {
93 0 : __libdw_empty_loc_attr (result);
94 0 : return 0;
95 : }
96 : }
97 0 : break;
98 :
99 : case DW_OP_GNU_implicit_pointer:
100 : {
101 : Dwarf_Die die;
102 1 : if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
103 0 : return -1;
104 1 : if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
105 0 : && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
106 : {
107 0 : __libdw_empty_loc_attr (result);
108 0 : return 0;
109 : }
110 : }
111 1 : break;
112 :
113 : default:
114 0 : __libdw_seterrno (DWARF_E_INVALID_ACCESS);
115 0 : return -1;
116 : }
117 :
118 : return 0;
119 : }
|