xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/dwarf2/abbrev.c (revision 6881a4007f077b54e5f51159c52b9b25f57deb0d)
1 /* DWARF 2 abbreviations
2 
3    Copyright (C) 1994-2023 Free Software Foundation, Inc.
4 
5    Adapted by Gary Funck (gary@intrepid.com), 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 }
321