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.
This commit is contained in:
Tom Tromey 2023-01-26 21:13:20 -07:00
parent 8282ad74c3
commit fdc82b33c4
5 changed files with 264 additions and 230 deletions

View file

@ -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 \

229
gdb/dwarf2/die.c Normal file
View file

@ -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 <http://www.gnu.org/licenses/>. */
#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);
}

View file

@ -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)

View file

@ -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. */

View file

@ -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