Branch data Line data Source code
1 : : /* Look up the DIE in a reference-form attribute. 2 : : Copyright (C) 2005-2010, 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 <string.h> 34 : : #include "libdwP.h" 35 : : #include <dwarf.h> 36 : : 37 : : 38 : : Dwarf_Die * 39 : 1112298 : dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *result) 40 : : { 41 [ + + ]: 1112298 : if (attr == NULL) 42 : : return NULL; 43 : : 44 : 949380 : struct Dwarf_CU *cu = attr->cu; 45 : : 46 : 949380 : Dwarf_Off offset; 47 [ + + ]: 949380 : if (attr->form == DW_FORM_ref_addr || attr->form == DW_FORM_GNU_ref_alt 48 [ + - - + ]: 949305 : || attr->form == DW_FORM_ref_sup4 || attr->form == DW_FORM_ref_sup8) 49 : : { 50 : : /* This has an absolute offset. */ 51 : : 52 : 75 : uint8_t ref_size; 53 [ - + - - ]: 75 : if (cu->version == 2 && attr->form == DW_FORM_ref_addr) 54 : 0 : ref_size = cu->address_size; 55 [ + - ]: 75 : else if (attr->form == DW_FORM_ref_sup4) 56 : : ref_size = 4; 57 [ + - ]: 75 : else if (attr->form == DW_FORM_ref_sup8) 58 : : ref_size = 8; 59 : : else 60 : 75 : ref_size = cu->offset_size; 61 : : 62 : 150 : Dwarf *dbg_ret = (attr->form == DW_FORM_GNU_ref_alt 63 [ + + ]: 75 : ? INTUSE(dwarf_getalt) (cu->dbg) : cu->dbg); 64 : : 65 [ - + ]: 75 : if (dbg_ret == NULL) 66 : : { 67 : 0 : __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK); 68 : 0 : return NULL; 69 : : } 70 : : 71 [ + - ]: 75 : if (__libdw_read_offset (cu->dbg, dbg_ret, IDX_debug_info, attr->valp, 72 : : ref_size, &offset, IDX_debug_info, 0)) 73 : : return NULL; 74 : : 75 : 75 : return INTUSE(dwarf_offdie) (dbg_ret, offset, result); 76 : : } 77 : : 78 : 949305 : const unsigned char *datap; 79 : 949305 : size_t size; 80 [ + + ]: 949305 : if (attr->form == DW_FORM_ref_sig8) 81 : : { 82 : : /* This doesn't have an offset, but instead a value we 83 : : have to match in the type unit headers. */ 84 : : 85 [ - + ]: 6 : uint64_t sig = read_8ubyte_unaligned (cu->dbg, attr->valp); 86 : 6 : cu = Dwarf_Sig8_Hash_find (&cu->dbg->sig8_hash, sig); 87 [ + + ]: 6 : if (cu == NULL) 88 : : { 89 : : /* Not seen before. We have to scan through the type units. 90 : : Since DWARFv5 these can (also) be found in .debug_info, 91 : : so scan that first. */ 92 : : bool scan_debug_types = false; 93 : 2 : do 94 : : { 95 : 2 : cu = __libdw_intern_next_unit (attr->cu->dbg, scan_debug_types); 96 [ + + ]: 2 : if (cu == NULL) 97 : : { 98 [ - + ]: 1 : if (scan_debug_types == false) 99 : : scan_debug_types = true; 100 : : else 101 : : { 102 [ # # ]: 0 : __libdw_seterrno (INTUSE(dwarf_errno) () 103 : : ?: DWARF_E_INVALID_REFERENCE); 104 : 0 : return NULL; 105 : : } 106 : : } 107 : : } 108 [ + + - + ]: 2 : while (cu == NULL || cu->unit_id8 != sig); 109 : : } 110 : : 111 : 6 : int secid = cu_sec_idx (cu); 112 : 6 : datap = cu->dbg->sectiondata[secid]->d_buf; 113 : 6 : size = cu->dbg->sectiondata[secid]->d_size; 114 : 6 : offset = cu->start + cu->subdie_offset; 115 : : } 116 : : else 117 : : { 118 : : /* Other forms produce an offset from the CU. */ 119 [ + - ]: 949299 : if (unlikely (__libdw_formref (attr, &offset) != 0)) 120 : : return NULL; 121 : : 122 : 949299 : datap = cu->startp; 123 : 949299 : size = cu->endp - cu->startp; 124 : : } 125 : : 126 [ - + ]: 949305 : if (unlikely (offset >= size)) 127 : : { 128 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF); 129 : 0 : return NULL; 130 : : } 131 : : 132 : 949305 : memset (result, '\0', sizeof (Dwarf_Die)); 133 : 949305 : result->addr = (char *) datap + offset; 134 : 949305 : result->cu = cu; 135 : 949305 : return result; 136 : : } 137 : : INTDEF (dwarf_formref_die)