]>
Commit | Line | Data |
---|---|---|
fdc82b33 TT |
1 | /* DWARF DIEs |
2 | ||
1d506c26 | 3 | Copyright (C) 1994-2024 Free Software Foundation, Inc. |
fdc82b33 TT |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "defs.h" | |
21 | #include "dwarf2/die.h" | |
22 | #include "dwarf2/stringify.h" | |
23 | ||
24 | /* See die.h. */ | |
25 | ||
26 | struct die_info * | |
27 | die_info::allocate (struct obstack *obstack, int num_attrs) | |
28 | { | |
29 | size_t size = sizeof (struct die_info); | |
30 | ||
31 | if (num_attrs > 1) | |
32 | size += (num_attrs - 1) * sizeof (struct attribute); | |
33 | ||
34 | struct die_info *die = (struct die_info *) obstack_alloc (obstack, size); | |
35 | memset (die, 0, size); | |
36 | return die; | |
37 | } | |
38 | ||
39 | /* See die.h. */ | |
40 | ||
41 | hashval_t | |
42 | die_info::hash (const void *item) | |
43 | { | |
44 | const struct die_info *die = (const struct die_info *) item; | |
45 | ||
46 | return to_underlying (die->sect_off); | |
47 | } | |
48 | ||
49 | /* See die.h. */ | |
50 | ||
51 | int | |
52 | die_info::eq (const void *item_lhs, const void *item_rhs) | |
53 | { | |
54 | const struct die_info *die_lhs = (const struct die_info *) item_lhs; | |
55 | const struct die_info *die_rhs = (const struct die_info *) item_rhs; | |
56 | ||
57 | return die_lhs->sect_off == die_rhs->sect_off; | |
58 | } | |
59 | ||
60 | static void | |
61 | dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) | |
62 | { | |
63 | unsigned int i; | |
64 | ||
65 | gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n", | |
66 | indent, "", | |
67 | dwarf_tag_name (die->tag), die->abbrev, | |
68 | sect_offset_str (die->sect_off)); | |
69 | ||
70 | if (die->parent != NULL) | |
71 | gdb_printf (f, "%*s parent at offset: %s\n", | |
72 | indent, "", | |
73 | sect_offset_str (die->parent->sect_off)); | |
74 | ||
75 | gdb_printf (f, "%*s has children: %s\n", | |
76 | indent, "", | |
77 | dwarf_bool_name (die->child != NULL)); | |
78 | ||
79 | gdb_printf (f, "%*s attributes:\n", indent, ""); | |
80 | ||
81 | for (i = 0; i < die->num_attrs; ++i) | |
82 | { | |
83 | gdb_printf (f, "%*s %s (%s) ", | |
84 | indent, "", | |
85 | dwarf_attr_name (die->attrs[i].name), | |
86 | dwarf_form_name (die->attrs[i].form)); | |
87 | ||
88 | switch (die->attrs[i].form) | |
89 | { | |
90 | case DW_FORM_addr: | |
91 | case DW_FORM_addrx: | |
92 | case DW_FORM_GNU_addr_index: | |
93 | gdb_printf (f, "address: "); | |
1e73d09f | 94 | gdb_puts (hex_string ((CORE_ADDR) die->attrs[i].as_address ()), f); |
fdc82b33 TT |
95 | break; |
96 | case DW_FORM_block2: | |
97 | case DW_FORM_block4: | |
98 | case DW_FORM_block: | |
99 | case DW_FORM_block1: | |
100 | gdb_printf (f, "block: size %s", | |
101 | pulongest (die->attrs[i].as_block ()->size)); | |
102 | break; | |
103 | case DW_FORM_exprloc: | |
104 | gdb_printf (f, "expression: size %s", | |
105 | pulongest (die->attrs[i].as_block ()->size)); | |
106 | break; | |
107 | case DW_FORM_data16: | |
108 | gdb_printf (f, "constant of 16 bytes"); | |
109 | break; | |
110 | case DW_FORM_ref_addr: | |
111 | gdb_printf (f, "ref address: "); | |
112 | gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); | |
113 | break; | |
114 | case DW_FORM_GNU_ref_alt: | |
115 | gdb_printf (f, "alt ref address: "); | |
116 | gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); | |
117 | break; | |
118 | case DW_FORM_ref1: | |
119 | case DW_FORM_ref2: | |
120 | case DW_FORM_ref4: | |
121 | case DW_FORM_ref8: | |
122 | case DW_FORM_ref_udata: | |
123 | gdb_printf (f, "constant ref: 0x%lx (adjusted)", | |
124 | (long) (die->attrs[i].as_unsigned ())); | |
125 | break; | |
126 | case DW_FORM_data1: | |
127 | case DW_FORM_data2: | |
128 | case DW_FORM_data4: | |
129 | case DW_FORM_data8: | |
130 | case DW_FORM_udata: | |
131 | gdb_printf (f, "constant: %s", | |
132 | pulongest (die->attrs[i].as_unsigned ())); | |
133 | break; | |
134 | case DW_FORM_sec_offset: | |
135 | gdb_printf (f, "section offset: %s", | |
136 | pulongest (die->attrs[i].as_unsigned ())); | |
137 | break; | |
138 | case DW_FORM_ref_sig8: | |
139 | gdb_printf (f, "signature: %s", | |
140 | hex_string (die->attrs[i].as_signature ())); | |
141 | break; | |
142 | case DW_FORM_string: | |
143 | case DW_FORM_strp: | |
144 | case DW_FORM_line_strp: | |
145 | case DW_FORM_strx: | |
146 | case DW_FORM_GNU_str_index: | |
147 | case DW_FORM_GNU_strp_alt: | |
148 | gdb_printf (f, "string: \"%s\" (%s canonicalized)", | |
149 | die->attrs[i].as_string () | |
150 | ? die->attrs[i].as_string () : "", | |
151 | die->attrs[i].canonical_string_p () ? "is" : "not"); | |
152 | break; | |
153 | case DW_FORM_flag: | |
154 | if (die->attrs[i].as_boolean ()) | |
155 | gdb_printf (f, "flag: TRUE"); | |
156 | else | |
157 | gdb_printf (f, "flag: FALSE"); | |
158 | break; | |
159 | case DW_FORM_flag_present: | |
160 | gdb_printf (f, "flag: TRUE"); | |
161 | break; | |
162 | case DW_FORM_indirect: | |
163 | /* The reader will have reduced the indirect form to | |
164 | the "base form" so this form should not occur. */ | |
165 | gdb_printf (f, | |
166 | "unexpected attribute form: DW_FORM_indirect"); | |
167 | break; | |
168 | case DW_FORM_sdata: | |
169 | case DW_FORM_implicit_const: | |
170 | gdb_printf (f, "constant: %s", | |
171 | plongest (die->attrs[i].as_signed ())); | |
172 | break; | |
173 | default: | |
174 | gdb_printf (f, "unsupported attribute form: %d.", | |
175 | die->attrs[i].form); | |
176 | break; | |
177 | } | |
178 | gdb_printf (f, "\n"); | |
179 | } | |
180 | } | |
181 | ||
182 | static void | |
183 | dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die) | |
184 | { | |
185 | int indent = level * 4; | |
186 | ||
187 | gdb_assert (die != NULL); | |
188 | ||
189 | if (level >= max_level) | |
190 | return; | |
191 | ||
192 | dump_die_shallow (f, indent, die); | |
193 | ||
194 | if (die->child != NULL) | |
195 | { | |
196 | gdb_printf (f, "%*s Children:", indent, ""); | |
197 | if (level + 1 < max_level) | |
198 | { | |
199 | gdb_printf (f, "\n"); | |
200 | dump_die_1 (f, level + 1, max_level, die->child); | |
201 | } | |
202 | else | |
203 | { | |
204 | gdb_printf (f, | |
205 | " [not printed, max nesting level reached]\n"); | |
206 | } | |
207 | } | |
208 | ||
209 | if (die->sibling != NULL && level > 0) | |
210 | { | |
211 | dump_die_1 (f, level, max_level, die->sibling); | |
212 | } | |
213 | } | |
214 | ||
215 | /* See die.h. */ | |
216 | ||
217 | void | |
218 | die_info::dump (int max_level) | |
219 | { | |
220 | dump_die_1 (gdb_stdlog, 0, max_level, this); | |
221 | } | |
222 | ||
223 | /* See die.h. */ | |
224 | ||
225 | void | |
226 | die_info::error_dump () | |
227 | { | |
228 | dump_die_shallow (gdb_stderr, 0, this); | |
229 | } |