/src/binutils-gdb/binutils/dwarf.h
Line | Count | Source |
1 | | /* dwarf.h - DWARF support header file |
2 | | Copyright (C) 2005-2026 Free Software Foundation, Inc. |
3 | | |
4 | | This file is part of GNU Binutils. |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License as published by |
8 | | the Free Software Foundation; either version 3 of the License, or |
9 | | (at your option) any later version. |
10 | | |
11 | | This program is distributed in the hope that it will be useful, |
12 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
14 | | GNU General Public License for more details. |
15 | | |
16 | | You should have received a copy of the GNU General Public License |
17 | | along with this program; if not, write to the Free Software |
18 | | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | | MA 02110-1301, USA. */ |
20 | | |
21 | | #include "dwarf2.h" /* for enum dwarf_unit_type */ |
22 | | |
23 | | /* Structure found in the .debug_line section. */ |
24 | | typedef struct |
25 | | { |
26 | | uint64_t li_length; |
27 | | uint16_t li_version; |
28 | | uint8_t li_address_size; |
29 | | uint8_t li_segment_size; |
30 | | uint64_t li_prologue_length; |
31 | | uint8_t li_min_insn_length; |
32 | | uint8_t li_max_ops_per_insn; |
33 | | uint8_t li_default_is_stmt; |
34 | | int8_t li_line_base; |
35 | | uint8_t li_line_range; |
36 | | uint8_t li_opcode_base; |
37 | | /* Not part of the header. 4 for 32-bit dwarf, 8 for 64-bit. */ |
38 | | unsigned int li_offset_size; |
39 | | } |
40 | | DWARF2_Internal_LineInfo; |
41 | | |
42 | | /* Structure found in .debug_pubnames section. */ |
43 | | typedef struct |
44 | | { |
45 | | uint64_t pn_length; |
46 | | unsigned short pn_version; |
47 | | uint64_t pn_offset; |
48 | | uint64_t pn_size; |
49 | | } |
50 | | DWARF2_Internal_PubNames; |
51 | | |
52 | | /* Structure found in .debug_info section. */ |
53 | | typedef struct |
54 | | { |
55 | | uint64_t cu_length; |
56 | | unsigned short cu_version; |
57 | | uint64_t cu_abbrev_offset; |
58 | | unsigned char cu_pointer_size; |
59 | | enum dwarf_unit_type cu_unit_type; |
60 | | } |
61 | | DWARF2_Internal_CompUnit; |
62 | | |
63 | | /* Structure found in .debug_aranges section. */ |
64 | | typedef struct |
65 | | { |
66 | | uint64_t ar_length; |
67 | | unsigned short ar_version; |
68 | | uint64_t ar_info_offset; |
69 | | unsigned char ar_address_size; |
70 | | unsigned char ar_segment_size; |
71 | | } |
72 | | DWARF2_Internal_ARange; |
73 | | |
74 | | /* Forward declaration. */ |
75 | | typedef struct generic_type generic_type; |
76 | | typedef struct base_type base_type; |
77 | | typedef struct type_def type_def; |
78 | | typedef struct enum_constant enum_constant; |
79 | | typedef struct enum_type enum_type; |
80 | | typedef struct subrange_type subrange_type; |
81 | | typedef struct tab_type tab_type; |
82 | | typedef struct member_type member_type; |
83 | | typedef struct member_parent member_parent; |
84 | | typedef struct type_ptr type_ptr; |
85 | | typedef struct type_ref type_ref; |
86 | | typedef struct variable_type variable_type; |
87 | | |
88 | | /* Structure used to optimize insertion of element in linked list. */ |
89 | | struct base_type_l { base_type *head; base_type *tail; }; |
90 | | struct type_def_l { type_def *head; type_def *tail; }; |
91 | | struct enum_type_l { enum_type* head; enum_type* tail; }; |
92 | | struct tab_type_l { tab_type *head; tab_type *tail; }; |
93 | | struct type_ptr_l { type_ptr *head; type_ptr *tail; }; |
94 | | struct type_ref_l { type_ref *head; type_ref *tail; }; |
95 | | struct member_parent_l { member_parent *head; member_parent *tail; }; |
96 | | struct variable_type_l { variable_type *head; variable_type *tail; }; |
97 | | |
98 | | enum field_type |
99 | | { |
100 | | NO_TYPE, |
101 | | BASE_TYPE, |
102 | | TYPE_DEF, |
103 | | ENUM_TYPE, |
104 | | TAB_TYPE, |
105 | | MEMBER_PARENT, |
106 | | MEMBER_TYPE, |
107 | | TYPE_PTR, |
108 | | TYPE_REF, |
109 | | VARIABLE_TYPE |
110 | | }; |
111 | | |
112 | | enum size_type |
113 | | { |
114 | | UNSIGNED_S, |
115 | | SIGNED_S |
116 | | }; |
117 | | |
118 | | /* Structure used to abstract all structure below. */ |
119 | | struct generic_type |
120 | | { |
121 | | union |
122 | | { |
123 | | base_type *base_type; |
124 | | type_def *type_def; |
125 | | enum_type *enum_type; |
126 | | tab_type *tab_type; |
127 | | member_parent *member_parent; |
128 | | member_type *member_type; |
129 | | type_ptr *type_ptr; |
130 | | type_ref *type_ref; |
131 | | variable_type *variable_type; |
132 | | } die_type; |
133 | | enum field_type field_type; |
134 | | }; |
135 | | |
136 | | /* Structure used to hold DW_TAG_base_type. */ |
137 | | struct base_type |
138 | | { |
139 | | uint64_t die_offset; |
140 | | union |
141 | | { |
142 | | uint64_t usize; |
143 | | int64_t ssize; |
144 | | } size; |
145 | | const char *name; |
146 | | struct base_type *next; |
147 | | enum field_type field_type; |
148 | | enum size_type size_type; |
149 | | }; |
150 | | |
151 | | /* Structure used to hold DW_TAG_typedef. */ |
152 | | struct type_def |
153 | | { |
154 | | generic_type ptr_type; |
155 | | uint64_t die_offset; |
156 | | /* This field holds the offset of the underlying DIE type in the DWARF info |
157 | | section. */ |
158 | | uint64_t ptr_die_offset; |
159 | | const char *name; |
160 | | struct type_def *next; |
161 | | enum field_type field_type; |
162 | | }; |
163 | | |
164 | | /* Structure used to hold DW_TAG_enumerator. */ |
165 | | struct enum_constant |
166 | | { |
167 | | uint64_t die_offset; |
168 | | uint64_t value; |
169 | | const char *name; |
170 | | struct enum_constant *next; |
171 | | }; |
172 | | |
173 | | /* Structure used to hold DW_TAG_enumeration. */ |
174 | | struct enum_type |
175 | | { |
176 | | uint64_t die_offset; |
177 | | union |
178 | | { |
179 | | uint64_t usize; |
180 | | int64_t ssize; |
181 | | } size; |
182 | | const char *name; |
183 | | struct enum_constant *enum_const_head; |
184 | | struct enum_constant *enum_const_tail; |
185 | | struct enum_type *next; |
186 | | enum field_type field_type; |
187 | | enum size_type size_type; |
188 | | }; |
189 | | |
190 | | /* Structure used to hold DW_TAG_subrange_type. */ |
191 | | struct subrange_type |
192 | | { |
193 | | uint64_t die_offset; |
194 | | union |
195 | | { |
196 | | uint64_t usize; |
197 | | int64_t ssize; |
198 | | } size; |
199 | | struct subrange_type *next; |
200 | | enum size_type size_type; |
201 | | }; |
202 | | |
203 | | /* Structure used to hold DW_TAG_array_type. */ |
204 | | struct tab_type |
205 | | { |
206 | | generic_type ptr_type; |
207 | | uint64_t die_offset; |
208 | | /* This field holds the offset of the underlying DIE type in the DWARF info |
209 | | section. */ |
210 | | uint64_t ptr_die_offset; |
211 | | subrange_type *subrange_head; |
212 | | subrange_type *subrange_tail; |
213 | | struct tab_type *next; |
214 | | enum field_type field_type; |
215 | | }; |
216 | | |
217 | | /* Structure used to hold DW_TAG_member. */ |
218 | | struct member_type |
219 | | { |
220 | | generic_type ptr_type; |
221 | | uint64_t die_offset; |
222 | | /* This field holds the offset of the underlying DIE type in the DWARF info |
223 | | section. */ |
224 | | uint64_t ptr_die_offset; |
225 | | int64_t member_offset; |
226 | | const char *name; |
227 | | struct member_type *next; |
228 | | enum field_type field_type; |
229 | | }; |
230 | | |
231 | | /* Structure used to hold either DW_TAG_structure_type or DW_TAG_union_type. */ |
232 | | struct member_parent |
233 | | { |
234 | | uint64_t die_offset; |
235 | | union |
236 | | { |
237 | | uint64_t usize; |
238 | | int64_t ssize; |
239 | | } size; |
240 | | const char *name; |
241 | | member_type *member_head; |
242 | | member_type *member_tail; |
243 | | struct member_parent *next; |
244 | | enum size_type size_type; |
245 | | enum field_type field_type; |
246 | | enum |
247 | | { |
248 | | UNION_TYPE, |
249 | | STRUCT_TYPE |
250 | | } type; |
251 | | /* This field is set to true if the current DIE has DW_AT_declaration. When |
252 | | this attribute is present the stucture/union is either incomplete, |
253 | | non-defining or in a separate entity. */ |
254 | | bool is_declaration; |
255 | | /* This field exists to avoid linking indefinitively nested structure. It is |
256 | | set to true when the underlying type is known (linked). */ |
257 | | bool linked; |
258 | | /* This field exists to avoid displaying indefinitvely nested structure. It |
259 | | is set to true when informations from member_parent are displayed. */ |
260 | | bool displayed; |
261 | | }; |
262 | | |
263 | | /* Structure used to hold DW_TAG_pointer_type. */ |
264 | | struct type_ptr |
265 | | { |
266 | | generic_type ptr_type; |
267 | | uint64_t die_offset; |
268 | | /* This field holds the offset of the underlying DIE type in the DWARF info |
269 | | section. */ |
270 | | uint64_t ptr_die_offset; |
271 | | union |
272 | | { |
273 | | uint64_t usize; |
274 | | int64_t ssize; |
275 | | } size; |
276 | | struct type_ptr *next; |
277 | | enum field_type field_type; |
278 | | enum size_type size_type; |
279 | | }; |
280 | | |
281 | | /* Structure used to hold either DW_TAG_const_type or DW_TAG_volatile_type. */ |
282 | | struct type_ref |
283 | | { |
284 | | generic_type ptr_type; |
285 | | uint64_t die_offset; |
286 | | /* This field holds the offset of the underlying DIE type in the DWARF info |
287 | | section. */ |
288 | | uint64_t ptr_die_offset; |
289 | | struct type_ref *next; |
290 | | enum |
291 | | { |
292 | | CONST_TYPE, |
293 | | VOLATILE_TYPE |
294 | | } type; |
295 | | enum field_type field_type; |
296 | | }; |
297 | | |
298 | | /* Structure used to hold either DW_TAG_variable_type. */ |
299 | | struct variable_type |
300 | | { |
301 | | generic_type ptr_type; |
302 | | uint64_t die_offset; |
303 | | /* This field holds the offset of the underlying DIE type in the DWARF info |
304 | | section. */ |
305 | | uint64_t ptr_die_offset; |
306 | | /* This field holds the value in DW_AT_location when the operaion is |
307 | | DW_OP_addr. It represents the location within the virtual address space of |
308 | | the program. */ |
309 | | uint64_t location_addr; |
310 | | /* This field holds the total size of the variable. */ |
311 | | uint64_t total_size; |
312 | | const char *name; |
313 | | struct variable_type *next; |
314 | | enum field_type field_type; |
315 | | /* This field is set to true if DW_AT_location is present with DW_OP_addr |
316 | | operand. */ |
317 | | bool has_location_addr; |
318 | | /* This field is set to true if DW_AT_specification is present. It represents |
319 | | an incomplete, non-defining, or separate declaration corresponding to a |
320 | | declaration. */ |
321 | | bool is_specification; |
322 | | /* This field is set to true if DW_AT_abstract_origin is present. It |
323 | | represents an inlined instances of inline subprograms. */ |
324 | | bool is_abstract_origin; |
325 | | }; |
326 | | |
327 | | /* N.B. The order here must match the order in debug_displays. */ |
328 | | |
329 | | enum dwarf_section_display_enum |
330 | | { |
331 | | abbrev = 0, |
332 | | aranges, |
333 | | frame, |
334 | | info, |
335 | | line, |
336 | | pubnames, |
337 | | gnu_pubnames, |
338 | | eh_frame, |
339 | | eh_frame_hdr, |
340 | | macinfo, |
341 | | macro, |
342 | | str, |
343 | | line_str, |
344 | | loc, |
345 | | loclists, |
346 | | loclists_dwo, |
347 | | pubtypes, |
348 | | gnu_pubtypes, |
349 | | ranges, |
350 | | rnglists, |
351 | | rnglists_dwo, |
352 | | static_func, |
353 | | static_vars, |
354 | | types, |
355 | | weaknames, |
356 | | gdb_index, |
357 | | debug_names, |
358 | | sframe, |
359 | | trace_info, |
360 | | trace_abbrev, |
361 | | trace_aranges, |
362 | | info_dwo, |
363 | | abbrev_dwo, |
364 | | types_dwo, |
365 | | line_dwo, |
366 | | loc_dwo, |
367 | | macro_dwo, |
368 | | macinfo_dwo, |
369 | | str_dwo, |
370 | | str_index, |
371 | | str_index_dwo, |
372 | | debug_addr, |
373 | | dwp_cu_index, |
374 | | dwp_tu_index, |
375 | | gnu_debuglink, |
376 | | gnu_debugaltlink, |
377 | | debug_sup, |
378 | | separate_debug_str, |
379 | | note_gnu_build_id, |
380 | | debug_variable_info, |
381 | | max |
382 | | }; |
383 | | |
384 | | struct dwarf_section |
385 | | { |
386 | | /* A debug section has a different name when it's stored compressed |
387 | | or not. XCOFF DWARF section also have a special name. |
388 | | COMPRESSED_NAME, UNCOMPRESSED_NAME and XCOFF_NAME are the three |
389 | | possibilities. NAME is set to whichever one is used for this |
390 | | input file, as determined by load_debug_section(). */ |
391 | | const char * uncompressed_name; |
392 | | const char * compressed_name; |
393 | | const char * xcoff_name; |
394 | | const char * name; |
395 | | /* If non-NULL then FILENAME is the name of the separate debug info |
396 | | file containing the section. */ |
397 | | const char * filename; |
398 | | unsigned char * start; |
399 | | uint64_t address; |
400 | | uint64_t size; |
401 | | enum dwarf_section_display_enum abbrev_sec; |
402 | | /* Used by clients to help them implement the reloc_at callback. */ |
403 | | void * reloc_info; |
404 | | uint64_t num_relocs; |
405 | | }; |
406 | | |
407 | | /* A structure containing the name of a debug section |
408 | | and a pointer to a function that can decode it. */ |
409 | | struct dwarf_section_display |
410 | | { |
411 | | struct dwarf_section section; |
412 | | int (*display) (struct dwarf_section *, void *); |
413 | | int *enabled; |
414 | | bool relocate; |
415 | | }; |
416 | | |
417 | | extern struct dwarf_section_display debug_displays []; |
418 | | |
419 | | /* This structure records the information that |
420 | | we extract from the.debug_info section. */ |
421 | | typedef struct |
422 | | { |
423 | | unsigned int pointer_size; |
424 | | unsigned int offset_size; |
425 | | int dwarf_version; |
426 | | uint64_t cu_offset; |
427 | | uint64_t base_address; |
428 | | /* This field is filled in when reading the attribute DW_AT_GNU_addr_base and |
429 | | is used with the form DW_FORM_GNU_addr_index. */ |
430 | | uint64_t addr_base; |
431 | | /* This field is filled in when reading the attribute DW_AT_GNU_ranges_base and |
432 | | is used when calculating ranges. */ |
433 | | uint64_t ranges_base; |
434 | | /* This is an array of offsets to the location list table. */ |
435 | | uint64_t * loc_offsets; |
436 | | /* This is an array of offsets to the location view table. */ |
437 | | uint64_t * loc_views; |
438 | | int * have_frame_base; |
439 | | |
440 | | /* Information for associating location lists with CUs. */ |
441 | | unsigned int num_loc_offsets; |
442 | | unsigned int max_loc_offsets; |
443 | | unsigned int num_loc_views; |
444 | | uint64_t loclists_base; |
445 | | |
446 | | /* List of .debug_ranges offsets seen in this .debug_info. */ |
447 | | uint64_t * range_lists; |
448 | | unsigned int num_range_lists; |
449 | | unsigned int max_range_lists; |
450 | | uint64_t rnglists_base; |
451 | | uint64_t str_offsets_base; |
452 | | } |
453 | | debug_info; |
454 | | |
455 | | typedef struct separate_info |
456 | | { |
457 | | void * handle; /* The pointer returned by open_debug_file(). */ |
458 | | const char * filename; |
459 | | struct separate_info * next; |
460 | | } separate_info; |
461 | | |
462 | | extern separate_info * first_separate_info; |
463 | | |
464 | | extern unsigned int eh_addr_size; |
465 | | extern const char * separate_debug_info_dir; |
466 | | |
467 | | extern int do_debug_info; |
468 | | extern int do_debug_abbrevs; |
469 | | extern int do_debug_lines; |
470 | | extern int do_debug_pubnames; |
471 | | extern int do_debug_pubtypes; |
472 | | extern int do_debug_aranges; |
473 | | extern int do_debug_ranges; |
474 | | extern int do_debug_frames; |
475 | | extern int do_debug_frames_interp; |
476 | | extern int do_debug_macinfo; |
477 | | extern int do_debug_str; |
478 | | extern int do_debug_str_offsets; |
479 | | extern int do_debug_loc; |
480 | | extern int do_gdb_index; |
481 | | extern int do_trace_info; |
482 | | extern int do_trace_abbrevs; |
483 | | extern int do_trace_aranges; |
484 | | extern int do_debug_addr; |
485 | | extern int do_debug_cu_index; |
486 | | extern int do_wide; |
487 | | extern int do_debug_links; |
488 | | extern int do_follow_links; |
489 | | #ifdef HAVE_LIBDEBUGINFOD |
490 | | extern int use_debuginfod; |
491 | | #endif |
492 | | extern bool do_checks; |
493 | | |
494 | | extern int dwarf_cutoff_level; |
495 | | extern unsigned long dwarf_start_die; |
496 | | |
497 | | extern int dwarf_check; |
498 | | |
499 | | extern void init_dwarf_by_elf_machine_code (unsigned int); |
500 | | extern void init_dwarf_by_bfd_arch_and_mach (enum bfd_architecture arch, |
501 | | unsigned long mach); |
502 | | |
503 | | extern bool load_debug_section (enum dwarf_section_display_enum, void *); |
504 | | extern void free_debug_section (enum dwarf_section_display_enum); |
505 | | extern bool load_separate_debug_files (void *, const char *); |
506 | | extern void close_debug_file (void *); |
507 | | extern void *open_debug_file (const char *); |
508 | | extern void resolve_and_display_variable_info (void); |
509 | | |
510 | | extern void free_debug_memory (void); |
511 | | extern void free_mapping_info_struct (void); |
512 | | |
513 | | extern int dwarf_select_sections_by_names (const char *); |
514 | | extern int dwarf_select_sections_by_letters (const char *); |
515 | | extern void dwarf_select_sections_all (void); |
516 | | |
517 | | extern unsigned int * find_cu_tu_set (void *, unsigned int); |
518 | | |
519 | | extern void * cmalloc (uint64_t, size_t); |
520 | | extern void * xcalloc2 (uint64_t, size_t); |
521 | | extern void * xcmalloc (uint64_t, size_t); |
522 | | extern void * xcrealloc (void *, uint64_t, size_t); |
523 | | |
524 | | /* A callback into the client. Returns TRUE if there is a |
525 | | relocation against the given debug section at the given |
526 | | offset. */ |
527 | | extern bool reloc_at (struct dwarf_section *, uint64_t); |
528 | | |
529 | | extern uint64_t read_leb128 (const unsigned char *, const unsigned char *const, |
530 | | bool, unsigned int *, int *); |
531 | | |
532 | | #if HAVE_LIBDEBUGINFOD |
533 | | extern unsigned char * get_build_id (void *); |
534 | | #endif |
535 | | |
536 | | static inline void |
537 | | report_leb_status (int status) |
538 | 2.83M | { |
539 | 2.83M | if ((status & 1) != 0) |
540 | 1.69k | error (_("end of data encountered whilst reading LEB\n")); |
541 | 2.83M | else if ((status & 2) != 0) |
542 | 25.5k | error (_("read LEB value is too large to store in destination variable\n")); |
543 | 2.83M | } Unexecuted instantiation: fuzz_objdump.c:report_leb_status dwarf.c:report_leb_status Line | Count | Source | 538 | 1.91M | { | 539 | 1.91M | if ((status & 1) != 0) | 540 | 443 | error (_("end of data encountered whilst reading LEB\n")); | 541 | 1.91M | else if ((status & 2) != 0) | 542 | 6.06k | error (_("read LEB value is too large to store in destination variable\n")); | 543 | 1.91M | } |
fuzz_readelf.c:report_leb_status Line | Count | Source | 538 | 919k | { | 539 | 919k | if ((status & 1) != 0) | 540 | 1.25k | error (_("end of data encountered whilst reading LEB\n")); | 541 | 918k | else if ((status & 2) != 0) | 542 | 19.4k | error (_("read LEB value is too large to store in destination variable\n")); | 543 | 919k | } |
Unexecuted instantiation: fuzz_dwarf.c:report_leb_status |
544 | | |
545 | | #define SKIP_ULEB(start, end) \ |
546 | 19.3k | do \ |
547 | 19.3k | { \ |
548 | 19.3k | unsigned int _len; \ |
549 | 19.3k | read_leb128 (start, end, false, &_len, NULL); \ |
550 | 19.3k | start += _len; \ |
551 | 19.3k | } \ |
552 | 19.3k | while (0) |
553 | | |
554 | | #define SKIP_SLEB(start, end) \ |
555 | 847 | do \ |
556 | 847 | { \ |
557 | 847 | unsigned int _len; \ |
558 | 847 | read_leb128 (start, end, true, &_len, NULL); \ |
559 | 847 | start += _len; \ |
560 | 847 | } \ |
561 | 847 | while (0) |
562 | | |
563 | | #define READ_ULEB(var, start, end) \ |
564 | 2.83M | do \ |
565 | 2.83M | { \ |
566 | 2.83M | uint64_t _val; \ |
567 | 2.83M | unsigned int _len; \ |
568 | 2.83M | int _status; \ |
569 | 2.83M | \ |
570 | 2.83M | _val = read_leb128 (start, end, false, &_len, &_status); \ |
571 | 2.83M | start += _len; \ |
572 | 2.83M | (var) = _val; \ |
573 | 2.83M | if ((var) != _val) \ |
574 | 2.83M | _status |= 2; \ |
575 | 2.83M | report_leb_status (_status); \ |
576 | 2.83M | } \ |
577 | 2.83M | while (0) |
578 | | |
579 | | #define READ_SLEB(var, start, end) \ |
580 | 5.57k | do \ |
581 | 5.57k | { \ |
582 | 5.57k | int64_t _val; \ |
583 | 5.57k | unsigned int _len; \ |
584 | 5.57k | int _status; \ |
585 | 5.57k | \ |
586 | 5.57k | _val = read_leb128 (start, end, true, &_len, &_status); \ |
587 | 5.57k | start += _len; \ |
588 | 5.57k | (var) = _val; \ |
589 | 5.57k | if ((var) != _val) \ |
590 | 5.57k | _status |= 2; \ |
591 | 5.57k | report_leb_status (_status); \ |
592 | 5.57k | } \ |
593 | 5.57k | while (0) |