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 : 14934 : dwarf_getlocation_die (Dwarf_Attribute *attr, const Dwarf_Op *op, 38 : : Dwarf_Die *result) 39 : : { 40 [ - + ]: 14934 : if (attr == NULL) 41 : : return -1; 42 : : 43 : 14934 : Dwarf_Off dieoff; 44 [ + + + - : 14934 : switch (op->atom) - ] 45 : : { 46 : 14504 : 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 : 14504 : dieoff = op->number; 51 : 14504 : break; 52 : : 53 : 428 : 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 [ - + ]: 428 : 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 : 428 : dieoff = attr->cu->start + op->number; 69 : 428 : break; 70 : : 71 : 2 : 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 [ - + ]: 2 : if (op->number2 > (attr->cu->end - attr->cu->start)) 76 : 0 : goto invalid_offset; 77 : 2 : dieoff = attr->cu->start + op->number2; 78 : 2 : 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 [ - + ]: 14934 : if (__libdw_offdie (attr->cu->dbg, dieoff, result, 90 [ + + + - ]: 14934 : ISV4TU(attr->cu)) == NULL) 91 : : return -1; 92 : : 93 : : return 0; 94 : : } 95 : : INTDEF(dwarf_getlocation_die);