--- /dev/null
+/* 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);
+}
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 *);
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,
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. */
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
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,
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;
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;
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;
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)
{
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));
}
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),
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,
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);
-}
-
\f
/* Macro support. */