Branch data Line data Source code
1 : : /* Return DIE associated with a location expression op.
2 : : Copyright (C) 2013, 2017 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 : : int
37 : 15133 : dwarf_getlocation_die (Dwarf_Attribute *attr, const Dwarf_Op *op,
38 : : Dwarf_Die *result)
39 : : {
40 [ + - ]: 15133 : if (attr == NULL)
41 : : return -1;
42 : :
43 : 15133 : Dwarf_Off dieoff;
44 [ + + + - : 15133 : switch (op->atom)
- ]
45 : : {
46 : 14970 : case DW_OP_implicit_pointer:
47 : : case DW_OP_GNU_implicit_pointer:
48 : : case DW_OP_call_ref:
49 : : case DW_OP_GNU_variable_value:
50 : 14970 : dieoff = op->number;
51 : 14970 : break;
52 : :
53 : 162 : case DW_OP_GNU_parameter_ref:
54 : : case DW_OP_convert:
55 : : case DW_OP_GNU_convert:
56 : : case DW_OP_reinterpret:
57 : : case DW_OP_GNU_reinterpret:
58 : : case DW_OP_const_type:
59 : : case DW_OP_GNU_const_type:
60 : : case DW_OP_call2:
61 : : case DW_OP_call4:
62 [ - + ]: 162 : if (op->number > (attr->cu->end - attr->cu->start))
63 : : {
64 : 0 : invalid_offset:
65 : 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET);
66 : 0 : return -1;
67 : : }
68 : 162 : dieoff = attr->cu->start + op->number;
69 : 162 : break;
70 : :
71 : 1 : case DW_OP_regval_type:
72 : : case DW_OP_GNU_regval_type:
73 : : case DW_OP_deref_type:
74 : : case DW_OP_GNU_deref_type:
75 [ - + ]: 1 : if (op->number2 > (attr->cu->end - attr->cu->start))
76 : : goto invalid_offset;
77 : 1 : dieoff = attr->cu->start + op->number2;
78 : 1 : break;
79 : :
80 : 0 : case DW_OP_xderef_type:
81 : 0 : dieoff = op->number2;
82 : 0 : break;
83 : :
84 : 0 : default:
85 : 0 : __libdw_seterrno (DWARF_E_INVALID_ACCESS);
86 : 0 : return -1;
87 : : }
88 : :
89 [ - + ]: 15133 : if (__libdw_offdie (attr->cu->dbg, dieoff, result,
90 [ + - ][ + - ]: 15133 : ISV4TU(attr->cu)) == NULL)
91 : 0 : return -1;
92 : :
93 : : return 0;
94 : : }
95 : : INTDEF(dwarf_getlocation_die);
|