1 /* DWARF 2 abbreviations
2 
3    Copyright (C) 1994-2021 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
hash_abbrev(const void * item)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
eq_abbrev(const void * lhs,const void * rhs)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 
abbrev_table(sect_offset off)61 abbrev_table::abbrev_table (sect_offset off)
62   : sect_off (off),
63     m_abbrevs (htab_create_alloc (20, hash_abbrev, eq_abbrev,
64 				  nullptr, xcalloc, xfree))
65 {
66 }
67 
68 /* Add an abbreviation to the table.  */
69 
70 void
add_abbrev(struct abbrev_info * abbrev)71 abbrev_table::add_abbrev (struct abbrev_info *abbrev)
72 {
73   void **slot = htab_find_slot_with_hash (m_abbrevs.get (), abbrev,
74 					  abbrev->number, INSERT);
75   *slot = abbrev;
76 }
77 
78 /* Read in an abbrev table.  */
79 
80 abbrev_table_up
read(struct dwarf2_section_info * section,sect_offset sect_off)81 abbrev_table::read (struct dwarf2_section_info *section,
82 		    sect_offset sect_off)
83 {
84   bfd *abfd = section->get_bfd_owner ();
85   const gdb_byte *abbrev_ptr;
86   struct abbrev_info *cur_abbrev;
87 
88   abbrev_table_up abbrev_table (new struct abbrev_table (sect_off));
89   struct obstack *obstack = &abbrev_table->m_abbrev_obstack;
90 
91   /* Caller must ensure this.  */
92   gdb_assert (section->readin);
93   abbrev_ptr = section->buffer + to_underlying (sect_off);
94 
95   while (true)
96     {
97       unsigned int bytes_read;
98       /* Loop until we reach an abbrev number of 0.  */
99       unsigned int abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr,
100 							 &bytes_read);
101       if (abbrev_number == 0)
102 	break;
103       abbrev_ptr += bytes_read;
104 
105       /* Start without any attrs.  */
106       obstack_blank (obstack, offsetof (abbrev_info, attrs));
107       cur_abbrev = (struct abbrev_info *) obstack_base (obstack);
108 
109       /* Read in abbrev header.  */
110       cur_abbrev->number = abbrev_number;
111       cur_abbrev->tag
112 	= (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr,
113 						 &bytes_read);
114       abbrev_ptr += bytes_read;
115       cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
116       abbrev_ptr += 1;
117 
118       /* Now read in declarations.  */
119       int num_attrs = 0;
120       for (;;)
121 	{
122 	  struct attr_abbrev cur_attr;
123 
124 	  cur_attr.name
125 	    = (enum dwarf_attribute) read_unsigned_leb128 (abfd, abbrev_ptr,
126 							   &bytes_read);
127 	  abbrev_ptr += bytes_read;
128 	  cur_attr.form
129 	    = (enum dwarf_form) read_unsigned_leb128 (abfd, abbrev_ptr,
130 						      &bytes_read);
131 	  abbrev_ptr += bytes_read;
132 	  if (cur_attr.form == DW_FORM_implicit_const)
133 	    {
134 	      cur_attr.implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
135 							    &bytes_read);
136 	      abbrev_ptr += bytes_read;
137 	    }
138 	  else
139 	    cur_attr.implicit_const = -1;
140 
141 	  if (cur_attr.name == 0)
142 	    break;
143 
144 	  ++num_attrs;
145 	  obstack_grow (obstack, &cur_attr, sizeof (cur_attr));
146 	}
147 
148       cur_abbrev = (struct abbrev_info *) obstack_finish (obstack);
149       cur_abbrev->num_attrs = num_attrs;
150       abbrev_table->add_abbrev (cur_abbrev);
151     }
152 
153   return abbrev_table;
154 }
155