From fdc82b33c455b049d4739ef0959f458263197a33 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Thu, 26 Jan 2023 21:13:20 -0700 Subject: [PATCH] Move some code from dwarf2/read.c to die.c This patch introduces a new file, dwarf2/die.c, and moves some DIE-related code out of dwarf2/read.c and into this new file. This is just a small part of the long-term project to split up read.c. (According to 'wc', dwarf2/read.c is the largest file in gdb by around 8000 LOC.) Regression tested on x86-64 Fedora 36. --- gdb/Makefile.in | 1 + gdb/dwarf2/die.c | 229 +++++++++++++++++++++++++++++++++++++++++++ gdb/dwarf2/die.h | 21 ++++ gdb/dwarf2/read.c | 239 +++------------------------------------------ gdb/gdb-gdb.gdb.in | 4 +- 5 files changed, 264 insertions(+), 230 deletions(-) create mode 100644 gdb/dwarf2/die.c diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 049a14fe40a..dac5a66e9ad 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1069,6 +1069,7 @@ COMMON_SFILES = \ dwarf2/comp-unit-head.c \ dwarf2/cooked-index.c \ dwarf2/cu.c \ + dwarf2/die.c \ dwarf2/dwz.c \ dwarf2/expr.c \ dwarf2/frame-tailcall.c \ diff --git a/gdb/dwarf2/die.c b/gdb/dwarf2/die.c new file mode 100644 index 00000000000..d409d24d7f6 --- /dev/null +++ b/gdb/dwarf2/die.c @@ -0,0 +1,229 @@ +/* DWARF DIEs + + Copyright (C) 1994-2023 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" +#include "dwarf2/die.h" +#include "dwarf2/stringify.h" + +/* See die.h. */ + +struct die_info * +die_info::allocate (struct obstack *obstack, int num_attrs) +{ + size_t size = sizeof (struct die_info); + + if (num_attrs > 1) + size += (num_attrs - 1) * sizeof (struct attribute); + + struct die_info *die = (struct die_info *) obstack_alloc (obstack, size); + memset (die, 0, size); + return die; +} + +/* See die.h. */ + +hashval_t +die_info::hash (const void *item) +{ + const struct die_info *die = (const struct die_info *) item; + + return to_underlying (die->sect_off); +} + +/* See die.h. */ + +int +die_info::eq (const void *item_lhs, const void *item_rhs) +{ + const struct die_info *die_lhs = (const struct die_info *) item_lhs; + const struct die_info *die_rhs = (const struct die_info *) item_rhs; + + return die_lhs->sect_off == die_rhs->sect_off; +} + +static void +dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) +{ + unsigned int i; + + gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n", + indent, "", + dwarf_tag_name (die->tag), die->abbrev, + sect_offset_str (die->sect_off)); + + if (die->parent != NULL) + gdb_printf (f, "%*s parent at offset: %s\n", + indent, "", + sect_offset_str (die->parent->sect_off)); + + gdb_printf (f, "%*s has children: %s\n", + indent, "", + dwarf_bool_name (die->child != NULL)); + + gdb_printf (f, "%*s attributes:\n", indent, ""); + + for (i = 0; i < die->num_attrs; ++i) + { + gdb_printf (f, "%*s %s (%s) ", + indent, "", + dwarf_attr_name (die->attrs[i].name), + dwarf_form_name (die->attrs[i].form)); + + switch (die->attrs[i].form) + { + case DW_FORM_addr: + case DW_FORM_addrx: + case DW_FORM_GNU_addr_index: + gdb_printf (f, "address: "); + gdb_puts (hex_string (die->attrs[i].as_address ()), f); + break; + case DW_FORM_block2: + case DW_FORM_block4: + case DW_FORM_block: + case DW_FORM_block1: + gdb_printf (f, "block: size %s", + pulongest (die->attrs[i].as_block ()->size)); + break; + case DW_FORM_exprloc: + gdb_printf (f, "expression: size %s", + pulongest (die->attrs[i].as_block ()->size)); + break; + case DW_FORM_data16: + gdb_printf (f, "constant of 16 bytes"); + break; + case DW_FORM_ref_addr: + gdb_printf (f, "ref address: "); + gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); + break; + case DW_FORM_GNU_ref_alt: + gdb_printf (f, "alt ref address: "); + gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); + break; + case DW_FORM_ref1: + case DW_FORM_ref2: + case DW_FORM_ref4: + case DW_FORM_ref8: + case DW_FORM_ref_udata: + gdb_printf (f, "constant ref: 0x%lx (adjusted)", + (long) (die->attrs[i].as_unsigned ())); + break; + case DW_FORM_data1: + case DW_FORM_data2: + case DW_FORM_data4: + case DW_FORM_data8: + case DW_FORM_udata: + gdb_printf (f, "constant: %s", + pulongest (die->attrs[i].as_unsigned ())); + break; + case DW_FORM_sec_offset: + gdb_printf (f, "section offset: %s", + pulongest (die->attrs[i].as_unsigned ())); + break; + case DW_FORM_ref_sig8: + gdb_printf (f, "signature: %s", + hex_string (die->attrs[i].as_signature ())); + break; + case DW_FORM_string: + case DW_FORM_strp: + case DW_FORM_line_strp: + case DW_FORM_strx: + case DW_FORM_GNU_str_index: + case DW_FORM_GNU_strp_alt: + gdb_printf (f, "string: \"%s\" (%s canonicalized)", + die->attrs[i].as_string () + ? die->attrs[i].as_string () : "", + die->attrs[i].canonical_string_p () ? "is" : "not"); + break; + case DW_FORM_flag: + if (die->attrs[i].as_boolean ()) + gdb_printf (f, "flag: TRUE"); + else + gdb_printf (f, "flag: FALSE"); + break; + case DW_FORM_flag_present: + gdb_printf (f, "flag: TRUE"); + break; + case DW_FORM_indirect: + /* The reader will have reduced the indirect form to + the "base form" so this form should not occur. */ + gdb_printf (f, + "unexpected attribute form: DW_FORM_indirect"); + break; + case DW_FORM_sdata: + case DW_FORM_implicit_const: + gdb_printf (f, "constant: %s", + plongest (die->attrs[i].as_signed ())); + break; + default: + gdb_printf (f, "unsupported attribute form: %d.", + die->attrs[i].form); + break; + } + gdb_printf (f, "\n"); + } +} + +static void +dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die) +{ + int indent = level * 4; + + gdb_assert (die != NULL); + + if (level >= max_level) + return; + + dump_die_shallow (f, indent, die); + + if (die->child != NULL) + { + gdb_printf (f, "%*s Children:", indent, ""); + if (level + 1 < max_level) + { + gdb_printf (f, "\n"); + dump_die_1 (f, level + 1, max_level, die->child); + } + else + { + gdb_printf (f, + " [not printed, max nesting level reached]\n"); + } + } + + if (die->sibling != NULL && level > 0) + { + dump_die_1 (f, level, max_level, die->sibling); + } +} + +/* See die.h. */ + +void +die_info::dump (int max_level) +{ + dump_die_1 (gdb_stdlog, 0, max_level, this); +} + +/* See die.h. */ + +void +die_info::error_dump () +{ + dump_die_shallow (gdb_stderr, 0, this); +} diff --git a/gdb/dwarf2/die.h b/gdb/dwarf2/die.h index ae46514c859..cdee46996d6 100644 --- a/gdb/dwarf2/die.h +++ b/gdb/dwarf2/die.h @@ -21,10 +21,31 @@ #define GDB_DWARF2_DIE_H #include "complaints.h" +#include "dwarf2/attribute.h" /* This data structure holds a complete die structure. */ struct die_info { + /* Allocate a new die_info on OBSTACK. NUM_ATTRS is the number of + attributes that are needed. */ + static die_info *allocate (struct obstack *obstack, int num_attrs); + + /* Trivial hash function for die_info: the hash value of a DIE is + its offset in .debug_info for this objfile. */ + static hashval_t hash (const void *item); + + /* Trivial comparison function for die_info structures: two DIEs + are equal if they have the same offset. */ + static int eq (const void *item_lhs, const void *item_rhs); + + /* Dump this DIE and any children to MAX_LEVEL. They are written to + gdb_stdlog. Note this is called from the pdie user command in + gdb-gdb.gdb. */ + void dump (int max_level); + + /* Shallowly dump this DIE to gdb_stderr. */ + void error_dump (); + /* Return the named attribute or NULL if not there, but do not follow DW_AT_specification, etc. */ struct attribute *attr (dwarf_attribute name) diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index fb5aa7b8e5b..ce6c01ac771 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -1127,15 +1127,6 @@ static const char *dwarf2_physname (const char *name, struct die_info *die, static struct die_info *dwarf2_extension (struct die_info *die, struct dwarf2_cu **); -static void dump_die_shallow (struct ui_file *, int indent, struct die_info *); - -static void dump_die_for_error (struct die_info *); - -static void dump_die_1 (struct ui_file *, int level, int max_level, - struct die_info *); - -/*static*/ void dump_die (struct die_info *, int max_level); - static void store_in_ref_table (struct die_info *, struct dwarf2_cu *); @@ -1172,8 +1163,6 @@ static int attr_to_dynamic_prop (const struct attribute *attr, static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *); -static struct die_info *dwarf_alloc_die (struct dwarf2_cu *, int); - static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int, int); static void fill_in_loclist_baton (struct dwarf2_cu *cu, @@ -6065,7 +6054,7 @@ read_cutu_die_from_dwo (dwarf2_cu *cu, section->get_name (), (unsigned) (begin_info_ptr - section->buffer), bfd_get_filename (abfd)); - dump_die (comp_unit_die, dwarf_die_debug); + comp_unit_die->dump (dwarf_die_debug); } /* Skip dummy compilation units. */ @@ -7687,29 +7676,6 @@ process_queue (dwarf2_per_objfile *per_objfile) objfile_name (per_objfile->objfile)); } -/* Trivial hash function for die_info: the hash value of a DIE - is its offset in .debug_info for this objfile. */ - -static hashval_t -die_hash (const void *item) -{ - const struct die_info *die = (const struct die_info *) item; - - return to_underlying (die->sect_off); -} - -/* Trivial comparison function for die_info structures: two DIEs - are equal if they have the same offset. */ - -static int -die_eq (const void *item_lhs, const void *item_rhs) -{ - const struct die_info *die_lhs = (const struct die_info *) item_lhs; - const struct die_info *die_rhs = (const struct die_info *) item_rhs; - - return die_lhs->sect_off == die_rhs->sect_off; -} - /* Load the DIEs associated with PER_CU into memory. In some cases, the caller, while reading partial symbols, will need to load @@ -7736,8 +7702,8 @@ load_full_comp_unit (dwarf2_per_cu_data *this_cu, gdb_assert (cu->die_hash == NULL); cu->die_hash = htab_create_alloc_ex (cu->header.get_length_without_initial () / 12, - die_hash, - die_eq, + die_info::hash, + die_info::eq, NULL, &cu->comp_unit_obstack, hashtab_obstack_allocate, @@ -17884,7 +17850,7 @@ read_die_and_siblings (const struct die_reader_specs *reader, reader->die_section->get_name (), (unsigned) (info_ptr - reader->die_section->buffer), bfd_get_filename (reader->abfd)); - dump_die (die, dwarf_die_debug); + die->dump (dwarf_die_debug); } return die; @@ -17923,7 +17889,8 @@ read_full_die_1 (const struct die_reader_specs *reader, abbrev_number, bfd_get_filename (abfd)); - die = dwarf_alloc_die (cu, abbrev->num_attrs + num_extra_attrs); + die = die_info::allocate (&cu->comp_unit_obstack, + abbrev->num_attrs + num_extra_attrs); die->sect_off = sect_off; die->tag = abbrev->tag; die->abbrev = abbrev_number; @@ -17990,7 +17957,7 @@ read_full_die (const struct die_reader_specs *reader, reader->die_section->get_name (), (unsigned) (info_ptr - reader->die_section->buffer), bfd_get_filename (reader->abfd)); - dump_die (*diep, dwarf_die_debug); + (*diep)->dump (dwarf_die_debug); } return result; @@ -22192,176 +22159,6 @@ dwarf2_extension (struct die_info *die, struct dwarf2_cu **ext_cu) return follow_die_ref (die, attr, ext_cu); } -static void -dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) -{ - unsigned int i; - - gdb_printf (f, "%*sDie: %s (abbrev %d, offset %s)\n", - indent, "", - dwarf_tag_name (die->tag), die->abbrev, - sect_offset_str (die->sect_off)); - - if (die->parent != NULL) - gdb_printf (f, "%*s parent at offset: %s\n", - indent, "", - sect_offset_str (die->parent->sect_off)); - - gdb_printf (f, "%*s has children: %s\n", - indent, "", - dwarf_bool_name (die->child != NULL)); - - gdb_printf (f, "%*s attributes:\n", indent, ""); - - for (i = 0; i < die->num_attrs; ++i) - { - gdb_printf (f, "%*s %s (%s) ", - indent, "", - dwarf_attr_name (die->attrs[i].name), - dwarf_form_name (die->attrs[i].form)); - - switch (die->attrs[i].form) - { - case DW_FORM_addr: - case DW_FORM_addrx: - case DW_FORM_GNU_addr_index: - gdb_printf (f, "address: "); - gdb_puts (hex_string (die->attrs[i].as_address ()), f); - break; - case DW_FORM_block2: - case DW_FORM_block4: - case DW_FORM_block: - case DW_FORM_block1: - gdb_printf (f, "block: size %s", - pulongest (die->attrs[i].as_block ()->size)); - break; - case DW_FORM_exprloc: - gdb_printf (f, "expression: size %s", - pulongest (die->attrs[i].as_block ()->size)); - break; - case DW_FORM_data16: - gdb_printf (f, "constant of 16 bytes"); - break; - case DW_FORM_ref_addr: - gdb_printf (f, "ref address: "); - gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); - break; - case DW_FORM_GNU_ref_alt: - gdb_printf (f, "alt ref address: "); - gdb_puts (hex_string (die->attrs[i].as_unsigned ()), f); - break; - case DW_FORM_ref1: - case DW_FORM_ref2: - case DW_FORM_ref4: - case DW_FORM_ref8: - case DW_FORM_ref_udata: - gdb_printf (f, "constant ref: 0x%lx (adjusted)", - (long) (die->attrs[i].as_unsigned ())); - break; - case DW_FORM_data1: - case DW_FORM_data2: - case DW_FORM_data4: - case DW_FORM_data8: - case DW_FORM_udata: - gdb_printf (f, "constant: %s", - pulongest (die->attrs[i].as_unsigned ())); - break; - case DW_FORM_sec_offset: - gdb_printf (f, "section offset: %s", - pulongest (die->attrs[i].as_unsigned ())); - break; - case DW_FORM_ref_sig8: - gdb_printf (f, "signature: %s", - hex_string (die->attrs[i].as_signature ())); - break; - case DW_FORM_string: - case DW_FORM_strp: - case DW_FORM_line_strp: - case DW_FORM_strx: - case DW_FORM_GNU_str_index: - case DW_FORM_GNU_strp_alt: - gdb_printf (f, "string: \"%s\" (%s canonicalized)", - die->attrs[i].as_string () - ? die->attrs[i].as_string () : "", - die->attrs[i].canonical_string_p () ? "is" : "not"); - break; - case DW_FORM_flag: - if (die->attrs[i].as_boolean ()) - gdb_printf (f, "flag: TRUE"); - else - gdb_printf (f, "flag: FALSE"); - break; - case DW_FORM_flag_present: - gdb_printf (f, "flag: TRUE"); - break; - case DW_FORM_indirect: - /* The reader will have reduced the indirect form to - the "base form" so this form should not occur. */ - gdb_printf (f, - "unexpected attribute form: DW_FORM_indirect"); - break; - case DW_FORM_sdata: - case DW_FORM_implicit_const: - gdb_printf (f, "constant: %s", - plongest (die->attrs[i].as_signed ())); - break; - default: - gdb_printf (f, "unsupported attribute form: %d.", - die->attrs[i].form); - break; - } - gdb_printf (f, "\n"); - } -} - -static void -dump_die_for_error (struct die_info *die) -{ - dump_die_shallow (gdb_stderr, 0, die); -} - -static void -dump_die_1 (struct ui_file *f, int level, int max_level, struct die_info *die) -{ - int indent = level * 4; - - gdb_assert (die != NULL); - - if (level >= max_level) - return; - - dump_die_shallow (f, indent, die); - - if (die->child != NULL) - { - gdb_printf (f, "%*s Children:", indent, ""); - if (level + 1 < max_level) - { - gdb_printf (f, "\n"); - dump_die_1 (f, level + 1, max_level, die->child); - } - else - { - gdb_printf (f, - " [not printed, max nesting level reached]\n"); - } - } - - if (die->sibling != NULL && level > 0) - { - dump_die_1 (f, level, max_level, die->sibling); - } -} - -/* This is called from the pdie macro in gdbinit.in. - It's not static so gcc will keep a copy callable from gdb. */ - -void -dump_die (struct die_info *die, int max_level) -{ - dump_die_1 (gdb_stdlog, 0, max_level, die); -} - static void store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu) { @@ -22390,7 +22187,7 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr, die = follow_die_sig (src_die, attr, ref_cu); else { - dump_die_for_error (src_die); + src_die->error_dump (); error (_("Dwarf Error: Expected reference attribute [in module %s]"), objfile_name ((*ref_cu)->per_objfile->objfile)); } @@ -22889,7 +22686,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr, die = follow_die_sig_1 (src_die, sig_type, ref_cu); if (die == NULL) { - dump_die_for_error (src_die); + src_die->error_dump (); error (_("Dwarf Error: Problem reading signatured DIE %s referenced" " from DIE at %s [in module %s]"), hex_string (signature), sect_offset_str (src_die->sect_off), @@ -23032,8 +22829,8 @@ read_signatured_type (signatured_type *sig_type, gdb_assert (cu->die_hash == NULL); cu->die_hash = htab_create_alloc_ex (cu->header.get_length_without_initial () / 12, - die_hash, - die_eq, + die_info::hash, + die_info::eq, NULL, &cu->comp_unit_obstack, hashtab_obstack_allocate, @@ -23349,20 +23146,6 @@ dwarf_alloc_block (struct dwarf2_cu *cu) return XOBNEW (&cu->comp_unit_obstack, struct dwarf_block); } -static struct die_info * -dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs) -{ - struct die_info *die; - size_t size = sizeof (struct die_info); - - if (num_attrs > 1) - size += (num_attrs - 1) * sizeof (struct attribute); - - die = (struct die_info *) obstack_alloc (&cu->comp_unit_obstack, size); - memset (die, 0, sizeof (struct die_info)); - return (die); -} - /* Macro support. */ diff --git a/gdb/gdb-gdb.gdb.in b/gdb/gdb-gdb.gdb.in index b9fd457d069..d5d533a0a2e 100644 --- a/gdb/gdb-gdb.gdb.in +++ b/gdb/gdb-gdb.gdb.in @@ -23,10 +23,10 @@ set prompt (top-gdb) define pdie if $argc == 1 - call dump_die ($arg0, 1) + call $arg0->dump (1) else if $argc == 2 - call dump_die ($arg0, $arg1) + call $arg0->dump ($arg1) else printf "Syntax: pdie die [depth]\n" end -- 2.30.2