| /* DWARF 2 abbreviations |
| |
| Copyright (C) 1994-2021 Free Software Foundation, Inc. |
| |
| Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, |
| Inc. with support from Florida State University (under contract |
| with the Ada Joint Program Office), and Silicon Graphics, Inc. |
| Initial contribution by Brent Benson, Harris Computer Systems, Inc., |
| based on Fred Fish's (Cygnus Support) implementation of DWARF 1 |
| support. |
| |
| 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/read.h" |
| #include "dwarf2/abbrev.h" |
| #include "dwarf2/leb.h" |
| #include "bfd.h" |
| |
| /* Hash function for an abbrev. */ |
| |
| static hashval_t |
| hash_abbrev (const void *item) |
| { |
| const struct abbrev_info *info = (const struct abbrev_info *) item; |
| /* Warning: if you change this next line, you must also update the |
| other code in this class using the _with_hash functions. */ |
| return info->number; |
| } |
| |
| /* Comparison function for abbrevs. */ |
| |
| static int |
| eq_abbrev (const void *lhs, const void *rhs) |
| { |
| const struct abbrev_info *l_info = (const struct abbrev_info *) lhs; |
| const struct abbrev_info *r_info = (const struct abbrev_info *) rhs; |
| return l_info->number == r_info->number; |
| } |
| |
| /* Abbreviation tables. |
| |
| In DWARF version 2, the description of the debugging information is |
| stored in a separate .debug_abbrev section. Before we read any |
| dies from a section we read in all abbreviations and install them |
| in a hash table. */ |
| |
| abbrev_table::abbrev_table (sect_offset off) |
| : sect_off (off), |
| m_abbrevs (htab_create_alloc (20, hash_abbrev, eq_abbrev, |
| nullptr, xcalloc, xfree)) |
| { |
| } |
| |
| /* Add an abbreviation to the table. */ |
| |
| void |
| abbrev_table::add_abbrev (struct abbrev_info *abbrev) |
| { |
| void **slot = htab_find_slot_with_hash (m_abbrevs.get (), abbrev, |
| abbrev->number, INSERT); |
| *slot = abbrev; |
| } |
| |
| /* Read in an abbrev table. */ |
| |
| abbrev_table_up |
| abbrev_table::read (struct dwarf2_section_info *section, |
| sect_offset sect_off) |
| { |
| bfd *abfd = section->get_bfd_owner (); |
| const gdb_byte *abbrev_ptr; |
| struct abbrev_info *cur_abbrev; |
| |
| abbrev_table_up abbrev_table (new struct abbrev_table (sect_off)); |
| struct obstack *obstack = &abbrev_table->m_abbrev_obstack; |
| |
| /* Caller must ensure this. */ |
| gdb_assert (section->readin); |
| abbrev_ptr = section->buffer + to_underlying (sect_off); |
| |
| while (true) |
| { |
| unsigned int bytes_read; |
| /* Loop until we reach an abbrev number of 0. */ |
| unsigned int abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, |
| &bytes_read); |
| if (abbrev_number == 0) |
| break; |
| abbrev_ptr += bytes_read; |
| |
| /* Start without any attrs. */ |
| obstack_blank (obstack, offsetof (abbrev_info, attrs)); |
| cur_abbrev = (struct abbrev_info *) obstack_base (obstack); |
| |
| /* Read in abbrev header. */ |
| cur_abbrev->number = abbrev_number; |
| cur_abbrev->tag |
| = (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr, |
| &bytes_read); |
| abbrev_ptr += bytes_read; |
| cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr); |
| abbrev_ptr += 1; |
| |
| /* Now read in declarations. */ |
| int num_attrs = 0; |
| for (;;) |
| { |
| struct attr_abbrev cur_attr; |
| |
| cur_attr.name |
| = (enum dwarf_attribute) read_unsigned_leb128 (abfd, abbrev_ptr, |
| &bytes_read); |
| abbrev_ptr += bytes_read; |
| cur_attr.form |
| = (enum dwarf_form) read_unsigned_leb128 (abfd, abbrev_ptr, |
| &bytes_read); |
| abbrev_ptr += bytes_read; |
| if (cur_attr.form == DW_FORM_implicit_const) |
| { |
| cur_attr.implicit_const = read_signed_leb128 (abfd, abbrev_ptr, |
| &bytes_read); |
| abbrev_ptr += bytes_read; |
| } |
| else |
| cur_attr.implicit_const = -1; |
| |
| if (cur_attr.name == 0) |
| break; |
| |
| ++num_attrs; |
| obstack_grow (obstack, &cur_attr, sizeof (cur_attr)); |
| } |
| |
| cur_abbrev = (struct abbrev_info *) obstack_finish (obstack); |
| cur_abbrev->num_attrs = num_attrs; |
| abbrev_table->add_abbrev (cur_abbrev); |
| } |
| |
| return abbrev_table; |
| } |