]> Git Repo - binutils.git/blob - gdb/dwarf2/abbrev.c
Automatic date update in version.in
[binutils.git] / gdb / dwarf2 / abbrev.c
1 /* DWARF 2 abbreviations
2
3    Copyright (C) 1994-2022 Free Software Foundation, Inc.
4
5    Adapted by Gary Funck ([email protected]), Intrepid Technology,
6    Inc.  with support from Florida State University (under contract
7    with the Ada Joint Program Office), and Silicon Graphics, Inc.
8    Initial contribution by Brent Benson, Harris Computer Systems, Inc.,
9    based on Fred Fish's (Cygnus Support) implementation of DWARF 1
10    support.
11
12    This file is part of GDB.
13
14    This program is free software; you can redistribute it and/or modify
15    it under the terms of the GNU General Public License as published by
16    the Free Software Foundation; either version 3 of the License, or
17    (at your option) any later version.
18
19    This program is distributed in the hope that it will be useful,
20    but WITHOUT ANY WARRANTY; without even the implied warranty of
21    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22    GNU General Public License for more details.
23
24    You should have received a copy of the GNU General Public License
25    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
26
27 #include "defs.h"
28 #include "dwarf2/read.h"
29 #include "dwarf2/abbrev.h"
30 #include "dwarf2/leb.h"
31 #include "bfd.h"
32
33 /* Hash function for an abbrev.  */
34
35 static hashval_t
36 hash_abbrev (const void *item)
37 {
38   const struct abbrev_info *info = (const struct abbrev_info *) item;
39   /* Warning: if you change this next line, you must also update the
40      other code in this class using the _with_hash functions.  */
41   return info->number;
42 }
43
44 /* Comparison function for abbrevs.  */
45
46 static int
47 eq_abbrev (const void *lhs, const void *rhs)
48 {
49   const struct abbrev_info *l_info = (const struct abbrev_info *) lhs;
50   const struct abbrev_info *r_info = (const struct abbrev_info *) rhs;
51   return l_info->number == r_info->number;
52 }
53
54 /* Abbreviation tables.
55
56    In DWARF version 2, the description of the debugging information is
57    stored in a separate .debug_abbrev section.  Before we read any
58    dies from a section we read in all abbreviations and install them
59    in a hash table.  */
60
61 abbrev_table::abbrev_table (sect_offset off, struct dwarf2_section_info *sect)
62   : sect_off (off),
63     section (sect),
64     m_abbrevs (htab_create_alloc (20, hash_abbrev, eq_abbrev,
65                                   nullptr, xcalloc, xfree))
66 {
67 }
68
69 /* Add an abbreviation to the table.  */
70
71 void
72 abbrev_table::add_abbrev (struct abbrev_info *abbrev)
73 {
74   void **slot = htab_find_slot_with_hash (m_abbrevs.get (), abbrev,
75                                           abbrev->number, INSERT);
76   *slot = abbrev;
77 }
78
79 /* Helper function that returns true if a DIE with the given tag might
80    plausibly be indexed.  */
81
82 static bool
83 tag_interesting_for_index (dwarf_tag tag)
84 {
85   switch (tag)
86     {
87     case DW_TAG_array_type:
88     case DW_TAG_base_type:
89     case DW_TAG_class_type:
90     case DW_TAG_constant:
91     case DW_TAG_enumeration_type:
92     case DW_TAG_enumerator:
93     case DW_TAG_imported_declaration:
94     case DW_TAG_imported_unit:
95     case DW_TAG_inlined_subroutine:
96     case DW_TAG_interface_type:
97     case DW_TAG_module:
98     case DW_TAG_namespace:
99     case DW_TAG_ptr_to_member_type:
100     case DW_TAG_set_type:
101     case DW_TAG_string_type:
102     case DW_TAG_structure_type:
103     case DW_TAG_subprogram:
104     case DW_TAG_subrange_type:
105     case DW_TAG_generic_subrange:
106     case DW_TAG_subroutine_type:
107     case DW_TAG_typedef:
108     case DW_TAG_union_type:
109     case DW_TAG_unspecified_type:
110     case DW_TAG_variable:
111       return true;
112     }
113
114   return false;
115 }
116
117 /* Read in an abbrev table.  */
118
119 abbrev_table_up
120 abbrev_table::read (struct dwarf2_section_info *section,
121                     sect_offset sect_off)
122 {
123   bfd *abfd = section->get_bfd_owner ();
124   const gdb_byte *abbrev_ptr;
125   struct abbrev_info *cur_abbrev;
126
127   abbrev_table_up abbrev_table (new struct abbrev_table (sect_off, section));
128   struct obstack *obstack = &abbrev_table->m_abbrev_obstack;
129
130   /* Caller must ensure this.  */
131   gdb_assert (section->readin);
132   abbrev_ptr = section->buffer + to_underlying (sect_off);
133
134   while (true)
135     {
136       unsigned int bytes_read;
137       /* Loop until we reach an abbrev number of 0.  */
138       unsigned int abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr,
139                                                          &bytes_read);
140       if (abbrev_number == 0)
141         break;
142       abbrev_ptr += bytes_read;
143
144       /* Start without any attrs.  */
145       obstack_blank (obstack, offsetof (abbrev_info, attrs));
146       cur_abbrev = (struct abbrev_info *) obstack_base (obstack);
147
148       /* Read in abbrev header.  */
149       cur_abbrev->number = abbrev_number;
150       cur_abbrev->tag
151         = (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr,
152                                                  &bytes_read);
153       abbrev_ptr += bytes_read;
154       cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
155       abbrev_ptr += 1;
156
157       unsigned int size = 0;
158       unsigned int sibling_offset = -1;
159       bool is_csize = true;
160
161       bool has_hardcoded_declaration = false;
162       bool has_specification_or_origin = false;
163       bool has_name = false;
164       bool has_linkage_name = false;
165       bool has_location = false;
166       bool has_external = false;
167
168       /* Now read in declarations.  */
169       int num_attrs = 0;
170       for (;;)
171         {
172           struct attr_abbrev cur_attr;
173
174           cur_attr.name
175             = (enum dwarf_attribute) read_unsigned_leb128 (abfd, abbrev_ptr,
176                                                            &bytes_read);
177           abbrev_ptr += bytes_read;
178           cur_attr.form
179             = (enum dwarf_form) read_unsigned_leb128 (abfd, abbrev_ptr,
180                                                       &bytes_read);
181           abbrev_ptr += bytes_read;
182           if (cur_attr.form == DW_FORM_implicit_const)
183             {
184               cur_attr.implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
185                                                             &bytes_read);
186               abbrev_ptr += bytes_read;
187             }
188           else
189             cur_attr.implicit_const = -1;
190
191           if (cur_attr.name == 0)
192             break;
193
194           switch (cur_attr.name)
195             {
196             case DW_AT_declaration:
197               if (cur_attr.form == DW_FORM_flag_present)
198                 has_hardcoded_declaration = true;
199               break;
200
201             case DW_AT_external:
202               has_external = true;
203               break;
204
205             case DW_AT_specification:
206             case DW_AT_abstract_origin:
207             case DW_AT_extension:
208               has_specification_or_origin = true;
209               break;
210
211             case DW_AT_name:
212               has_name = true;
213               break;
214
215             case DW_AT_MIPS_linkage_name:
216             case DW_AT_linkage_name:
217               has_linkage_name = true;
218               break;
219
220             case DW_AT_const_value:
221             case DW_AT_location:
222               has_location = true;
223               break;
224
225             case DW_AT_sibling:
226               if (is_csize && cur_attr.form == DW_FORM_ref4)
227                 sibling_offset = size;
228               break;
229             }
230
231           switch (cur_attr.form)
232             {
233             case DW_FORM_data1:
234             case DW_FORM_ref1:
235             case DW_FORM_flag:
236             case DW_FORM_strx1:
237               size += 1;
238               break;
239             case DW_FORM_flag_present:
240             case DW_FORM_implicit_const:
241               break;
242             case DW_FORM_data2:
243             case DW_FORM_ref2:
244             case DW_FORM_strx2:
245               size += 2;
246               break;
247             case DW_FORM_strx3:
248               size += 3;
249               break;
250             case DW_FORM_data4:
251             case DW_FORM_ref4:
252             case DW_FORM_strx4:
253               size += 4;
254               break;
255             case DW_FORM_data8:
256             case DW_FORM_ref8:
257             case DW_FORM_ref_sig8:
258               size += 8;
259               break;
260             case DW_FORM_data16:
261               size += 16;
262               break;
263
264             default:
265               is_csize = false;
266               break;
267             }
268
269           ++num_attrs;
270           obstack_grow (obstack, &cur_attr, sizeof (cur_attr));
271         }
272
273       cur_abbrev = (struct abbrev_info *) obstack_finish (obstack);
274       cur_abbrev->num_attrs = num_attrs;
275
276       if (!has_name && !has_linkage_name && !has_specification_or_origin)
277         {
278           /* Some anonymous DIEs are worth examining.  */
279           cur_abbrev->interesting
280             = (cur_abbrev->tag == DW_TAG_namespace
281                || cur_abbrev->tag == DW_TAG_enumeration_type);
282         }
283       else if ((cur_abbrev->tag == DW_TAG_structure_type
284                 || cur_abbrev->tag == DW_TAG_class_type
285                 || cur_abbrev->tag == DW_TAG_union_type)
286                && cur_abbrev->has_children)
287         {
288           /* We have to record this as interesting, regardless of how
289              DW_AT_declaration is set, so that any subsequent
290              DW_AT_specification pointing at a child of this will get
291              the correct scope.  */
292           cur_abbrev->interesting = true;
293         }
294       else if (has_hardcoded_declaration
295                && (cur_abbrev->tag != DW_TAG_variable || !has_external))
296         cur_abbrev->interesting = false;
297       else if (!tag_interesting_for_index (cur_abbrev->tag))
298         cur_abbrev->interesting = false;
299       else if (!has_location && !has_specification_or_origin && !has_external
300                && cur_abbrev->tag == DW_TAG_variable)
301         cur_abbrev->interesting = false;
302       else
303         cur_abbrev->interesting = true;
304
305       /* If there are no children, and the abbrev has a constant size,
306          then we don't care about the sibling offset, because it's
307          simple to just skip the entire DIE without reading a sibling
308          offset.  */
309       if ((!cur_abbrev->has_children && is_csize)
310           /* Overflow.  */
311           || sibling_offset != (unsigned short) sibling_offset)
312         sibling_offset = -1;
313       cur_abbrev->size_if_constant = is_csize ? size : 0;
314       cur_abbrev->sibling_offset = sibling_offset;
315
316       abbrev_table->add_abbrev (cur_abbrev);
317     }
318
319   return abbrev_table;
320 }
This page took 0.042449 seconds and 4 git commands to generate.