Branch data Line data Source code
1 : : /* Look up the DIE in a reference-form attribute.
2 : : Copyright (C) 2005-2010 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 : 595462 : dwarf_formref_die (attr, result)
40 : : Dwarf_Attribute *attr;
41 : : Dwarf_Die *result;
42 : : {
43 [ + - ]: 595462 : if (attr == NULL)
44 : : return NULL;
45 : :
46 : 595462 : struct Dwarf_CU *cu = attr->cu;
47 : :
48 : : Dwarf_Off offset;
49 [ + + ]: 595462 : if (attr->form == DW_FORM_ref_addr || attr->form == DW_FORM_GNU_ref_alt)
50 : : {
51 : : /* This has an absolute offset. */
52 : :
53 [ - + ]: 13 : uint8_t ref_size = (cu->version == 2
54 : : ? cu->address_size
55 : : : cu->offset_size);
56 : :
57 : 13 : Dwarf *dbg_ret = (attr->form == DW_FORM_GNU_ref_alt
58 [ + - ]: 13 : ? cu->dbg->alt_dwarf : cu->dbg);
59 : :
60 [ - + ]: 13 : if (dbg_ret == NULL)
61 : : {
62 : 0 : __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
63 : : return NULL;
64 : : }
65 : :
66 [ + - ]: 13 : if (__libdw_read_offset (cu->dbg, dbg_ret, IDX_debug_info, attr->valp,
67 : : ref_size, &offset, IDX_debug_info, 0))
68 : : return NULL;
69 : :
70 : 13 : return INTUSE(dwarf_offdie) (dbg_ret, offset, result);
71 : : }
72 : :
73 : : Elf_Data *data;
74 [ + + ]: 595449 : if (attr->form == DW_FORM_ref_sig8)
75 : : {
76 : : /* This doesn't have an offset, but instead a value we
77 : : have to match in the .debug_types type unit headers. */
78 : :
79 [ - + ]: 1 : uint64_t sig = read_8ubyte_unaligned (cu->dbg, attr->valp);
80 : 1 : cu = Dwarf_Sig8_Hash_find (&cu->dbg->sig8_hash, sig, NULL);
81 [ + - ]: 1 : if (cu == NULL)
82 : : /* Not seen before. We have to scan through the type units. */
83 : : do
84 : : {
85 : 1 : cu = __libdw_intern_next_unit (attr->cu->dbg, true);
86 [ - + ]: 1 : if (cu == NULL)
87 : : {
88 [ # # ]: 0 : __libdw_seterrno (INTUSE(dwarf_errno) ()
89 : : ?: DWARF_E_INVALID_REFERENCE);
90 : : return NULL;
91 : : }
92 : 1 : Dwarf_Sig8_Hash_insert (&cu->dbg->sig8_hash, cu->type_sig8, cu);
93 : : }
94 [ - + ]: 1 : while (cu->type_sig8 != sig);
95 : :
96 : 1 : data = cu->dbg->sectiondata[IDX_debug_types];
97 : 1 : offset = cu->type_offset;
98 : : }
99 : : else
100 : : {
101 : : /* Other forms produce an offset from the CU. */
102 [ + - ]: 595448 : if (unlikely (__libdw_formref (attr, &offset) != 0))
103 : : return NULL;
104 : :
105 : 595448 : data = cu_data (cu);
106 : : }
107 : :
108 [ - + ]: 595449 : if (unlikely (data->d_size - cu->start <= offset))
109 : : {
110 : 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
111 : : return NULL;
112 : : }
113 : :
114 : 595449 : memset (result, '\0', sizeof (Dwarf_Die));
115 : 595449 : result->addr = (char *) data->d_buf + cu->start + offset;
116 : 595462 : result->cu = cu;
117 : : return result;
118 : : }
119 : 595448 : INTDEF (dwarf_formref_die)
|