/* 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); }