xref: /netbsd-src/external/gpl3/gdb.old/dist/gdb/dwarf2/comp-unit-head.c (revision 8e33eff89e26cf71871ead62f0d5063e1313c33a)
1 /* DWARF 2 debugging format support for GDB.
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/comp-unit-head.h"
29 #include "dwarf2/leb.h"
30 #include "dwarf2/read.h"
31 #include "dwarf2/section.h"
32 #include "dwarf2/stringify.h"
33 
34 /* See comp-unit-head.h.  */
35 
36 const gdb_byte *
37 read_comp_unit_head (struct comp_unit_head *cu_header,
38 		     const gdb_byte *info_ptr,
39 		     struct dwarf2_section_info *section,
40 		     rcuh_kind section_kind)
41 {
42   int signed_addr;
43   unsigned int bytes_read;
44   const char *filename = section->get_file_name ();
45   bfd *abfd = section->get_bfd_owner ();
46 
47   cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
48   cu_header->initial_length_size = bytes_read;
49   cu_header->offset_size = (bytes_read == 4) ? 4 : 8;
50   info_ptr += bytes_read;
51   unsigned version = read_2_bytes (abfd, info_ptr);
52   if (version < 2 || version > 5)
53     error (_("Dwarf Error: wrong version in compilation unit header "
54 	   "(is %d, should be 2, 3, 4 or 5) [in module %s]"),
55 	   version, filename);
56   cu_header->version = version;
57   info_ptr += 2;
58   if (cu_header->version < 5)
59     switch (section_kind)
60       {
61       case rcuh_kind::COMPILE:
62 	cu_header->unit_type = DW_UT_compile;
63 	break;
64       case rcuh_kind::TYPE:
65 	cu_header->unit_type = DW_UT_type;
66 	break;
67       default:
68 	internal_error (_("read_comp_unit_head: invalid section_kind"));
69       }
70   else
71     {
72       cu_header->unit_type = static_cast<enum dwarf_unit_type>
73 						 (read_1_byte (abfd, info_ptr));
74       info_ptr += 1;
75       switch (cu_header->unit_type)
76 	{
77 	case DW_UT_compile:
78 	case DW_UT_partial:
79 	case DW_UT_skeleton:
80 	case DW_UT_split_compile:
81 	  if (section_kind != rcuh_kind::COMPILE)
82 	    error (_("Dwarf Error: wrong unit_type in compilation unit header "
83 		   "(is %s, should be %s) [in module %s]"),
84 		   dwarf_unit_type_name (cu_header->unit_type),
85 		   dwarf_unit_type_name (DW_UT_type), filename);
86 	  break;
87 	case DW_UT_type:
88 	case DW_UT_split_type:
89 	  section_kind = rcuh_kind::TYPE;
90 	  break;
91 	default:
92 	  error (_("Dwarf Error: wrong unit_type in compilation unit header "
93 		 "(is %#04x, should be one of: %s, %s, %s, %s or %s) "
94 		 "[in module %s]"), cu_header->unit_type,
95 		 dwarf_unit_type_name (DW_UT_compile),
96 		 dwarf_unit_type_name (DW_UT_skeleton),
97 		 dwarf_unit_type_name (DW_UT_split_compile),
98 		 dwarf_unit_type_name (DW_UT_type),
99 		 dwarf_unit_type_name (DW_UT_split_type), filename);
100 	}
101 
102       cu_header->addr_size = read_1_byte (abfd, info_ptr);
103       info_ptr += 1;
104     }
105   cu_header->abbrev_sect_off
106     = (sect_offset) cu_header->read_offset (abfd, info_ptr, &bytes_read);
107   info_ptr += bytes_read;
108   if (cu_header->version < 5)
109     {
110       cu_header->addr_size = read_1_byte (abfd, info_ptr);
111       info_ptr += 1;
112     }
113   signed_addr = bfd_get_sign_extend_vma (abfd);
114   if (signed_addr < 0)
115     internal_error (_("read_comp_unit_head: dwarf from non elf file"));
116   cu_header->signed_addr_p = signed_addr;
117 
118   bool header_has_signature = section_kind == rcuh_kind::TYPE
119     || cu_header->unit_type == DW_UT_skeleton
120     || cu_header->unit_type == DW_UT_split_compile;
121 
122   if (header_has_signature)
123     {
124       cu_header->signature = read_8_bytes (abfd, info_ptr);
125       info_ptr += 8;
126     }
127 
128   if (section_kind == rcuh_kind::TYPE)
129     {
130       LONGEST type_offset;
131       type_offset = cu_header->read_offset (abfd, info_ptr, &bytes_read);
132       info_ptr += bytes_read;
133       cu_header->type_cu_offset_in_tu = (cu_offset) type_offset;
134       if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset)
135 	error (_("Dwarf Error: Too big type_offset in compilation unit "
136 	       "header (is %s) [in module %s]"), plongest (type_offset),
137 	       filename);
138     }
139 
140   return info_ptr;
141 }
142 
143 /* Subroutine of read_and_check_comp_unit_head and
144    read_and_check_type_unit_head to simplify them.
145    Perform various error checking on the header.  */
146 
147 static void
148 error_check_comp_unit_head (dwarf2_per_objfile *per_objfile,
149 			    struct comp_unit_head *header,
150 			    struct dwarf2_section_info *section,
151 			    struct dwarf2_section_info *abbrev_section)
152 {
153   const char *filename = section->get_file_name ();
154 
155   if (to_underlying (header->abbrev_sect_off)
156       >= abbrev_section->get_size (per_objfile->objfile))
157     error (_("Dwarf Error: bad offset (%s) in compilation unit header "
158 	   "(offset %s + 6) [in module %s]"),
159 	   sect_offset_str (header->abbrev_sect_off),
160 	   sect_offset_str (header->sect_off),
161 	   filename);
162 
163   /* Cast to ULONGEST to use 64-bit arithmetic when possible to
164      avoid potential 32-bit overflow.  */
165   if (((ULONGEST) header->sect_off + header->get_length ())
166       > section->size)
167     error (_("Dwarf Error: bad length (0x%x) in compilation unit header "
168 	   "(offset %s + 0) [in module %s]"),
169 	   header->length, sect_offset_str (header->sect_off),
170 	   filename);
171 }
172 
173 /* See comp-unit-head.h.  */
174 
175 const gdb_byte *
176 read_and_check_comp_unit_head (dwarf2_per_objfile *per_objfile,
177 			       struct comp_unit_head *header,
178 			       struct dwarf2_section_info *section,
179 			       struct dwarf2_section_info *abbrev_section,
180 			       const gdb_byte *info_ptr,
181 			       rcuh_kind section_kind)
182 {
183   const gdb_byte *beg_of_comp_unit = info_ptr;
184 
185   header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer);
186 
187   info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind);
188 
189   header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit);
190 
191   error_check_comp_unit_head (per_objfile, header, section, abbrev_section);
192 
193   return info_ptr;
194 }
195 
196 CORE_ADDR
197 comp_unit_head::read_address (bfd *abfd, const gdb_byte *buf,
198 			      unsigned int *bytes_read) const
199 {
200   CORE_ADDR retval = 0;
201 
202   if (signed_addr_p)
203     {
204       switch (addr_size)
205 	{
206 	case 2:
207 	  retval = bfd_get_signed_16 (abfd, buf);
208 	  break;
209 	case 4:
210 	  retval = bfd_get_signed_32 (abfd, buf);
211 	  break;
212 	case 8:
213 	  retval = bfd_get_signed_64 (abfd, buf);
214 	  break;
215 	default:
216 	  internal_error (_("read_address: bad switch, signed [in module %s]"),
217 			  bfd_get_filename (abfd));
218 	}
219     }
220   else
221     {
222       switch (addr_size)
223 	{
224 	case 2:
225 	  retval = bfd_get_16 (abfd, buf);
226 	  break;
227 	case 4:
228 	  retval = bfd_get_32 (abfd, buf);
229 	  break;
230 	case 8:
231 	  retval = bfd_get_64 (abfd, buf);
232 	  break;
233 	default:
234 	  internal_error (_("read_address: bad switch, "
235 			    "unsigned [in module %s]"),
236 			  bfd_get_filename (abfd));
237 	}
238     }
239 
240   *bytes_read = addr_size;
241   return retval;
242 }
243