| /* DWARF 2 debugging format support for GDB. |
| |
| 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/>. */ |
| |
| /* FIXME: Various die-reading functions need to be more careful with |
| reading off the end of the section. |
| E.g., load_partial_dies, read_partial_die. */ |
| |
| #include "defs.h" |
| #include "dwarf2/read.h" |
| #include "dwarf2/abbrev.h" |
| #include "dwarf2/attribute.h" |
| #include "dwarf2/comp-unit-head.h" |
| #include "dwarf2/cu.h" |
| #include "dwarf2/index-cache.h" |
| #include "dwarf2/index-common.h" |
| #include "dwarf2/leb.h" |
| #include "dwarf2/line-header.h" |
| #include "dwarf2/dwz.h" |
| #include "dwarf2/macro.h" |
| #include "dwarf2/die.h" |
| #include "dwarf2/sect-names.h" |
| #include "dwarf2/stringify.h" |
| #include "dwarf2/public.h" |
| #include "bfd.h" |
| #include "elf-bfd.h" |
| #include "symtab.h" |
| #include "gdbtypes.h" |
| #include "objfiles.h" |
| #include "dwarf2.h" |
| #include "demangle.h" |
| #include "gdb-demangle.h" |
| #include "filenames.h" /* for DOSish file names */ |
| #include "language.h" |
| #include "complaints.h" |
| #include "dwarf2/expr.h" |
| #include "dwarf2/loc.h" |
| #include "cp-support.h" |
| #include "hashtab.h" |
| #include "command.h" |
| #include "gdbcmd.h" |
| #include "block.h" |
| #include "addrmap.h" |
| #include "typeprint.h" |
| #include "psympriv.h" |
| #include "c-lang.h" |
| #include "go-lang.h" |
| #include "valprint.h" |
| #include "gdbcore.h" /* for gnutarget */ |
| #include "gdb/gdb-index.h" |
| #include "gdb_bfd.h" |
| #include "f-lang.h" |
| #include "source.h" |
| #include "build-id.h" |
| #include "namespace.h" |
| #include "gdbsupport/function-view.h" |
| #include "gdbsupport/gdb_optional.h" |
| #include "gdbsupport/underlying.h" |
| #include "gdbsupport/hash_enum.h" |
| #include "filename-seen-cache.h" |
| #include "producer.h" |
| #include <fcntl.h> |
| #include <algorithm> |
| #include <unordered_map> |
| #include "gdbsupport/selftest.h" |
| #include "rust-lang.h" |
| #include "gdbsupport/pathstuff.h" |
| #include "count-one-bits.h" |
| #include <unordered_set> |
| |
| /* When == 1, print basic high level tracing messages. |
| When > 1, be more verbose. |
| This is in contrast to the low level DIE reading of dwarf_die_debug. */ |
| static unsigned int dwarf_read_debug = 0; |
| |
| /* Print a "dwarf-read" debug statement if dwarf_read_debug is >= 1. */ |
| |
| #define dwarf_read_debug_printf(fmt, ...) \ |
| debug_prefixed_printf_cond (dwarf_read_debug >= 1, "dwarf-read", fmt, \ |
| ##__VA_ARGS__) |
| |
| /* Print a "dwarf-read" debug statement if dwarf_read_debug is >= 2. */ |
| |
| #define dwarf_read_debug_printf_v(fmt, ...) \ |
| debug_prefixed_printf_cond (dwarf_read_debug >= 2, "dwarf-read", fmt, \ |
| ##__VA_ARGS__) |
| |
| /* When non-zero, dump DIEs after they are read in. */ |
| static unsigned int dwarf_die_debug = 0; |
| |
| /* When non-zero, dump line number entries as they are read in. */ |
| unsigned int dwarf_line_debug = 0; |
| |
| /* When true, cross-check physname against demangler. */ |
| static bool check_physname = false; |
| |
| /* When true, do not reject deprecated .gdb_index sections. */ |
| static bool use_deprecated_index_sections = false; |
| |
| /* This is used to store the data that is always per objfile. */ |
| static const objfile_key<dwarf2_per_objfile> dwarf2_objfile_data_key; |
| |
| /* These are used to store the dwarf2_per_bfd objects. |
| |
| objfiles having the same BFD, which doesn't require relocations, are going to |
| share a dwarf2_per_bfd object, which is held in the _bfd_data_key version. |
| |
| Other objfiles are not going to share a dwarf2_per_bfd with any other |
| objfiles, so they'll have their own version kept in the _objfile_data_key |
| version. */ |
| static const struct bfd_key<dwarf2_per_bfd> dwarf2_per_bfd_bfd_data_key; |
| static const struct objfile_key<dwarf2_per_bfd> dwarf2_per_bfd_objfile_data_key; |
| |
| /* The "aclass" indices for various kinds of computed DWARF symbols. */ |
| |
| static int dwarf2_locexpr_index; |
| static int dwarf2_loclist_index; |
| static int dwarf2_locexpr_block_index; |
| static int dwarf2_loclist_block_index; |
| |
| /* Size of .debug_loclists section header for 32-bit DWARF format. */ |
| #define LOCLIST_HEADER_SIZE32 12 |
| |
| /* Size of .debug_loclists section header for 64-bit DWARF format. */ |
| #define LOCLIST_HEADER_SIZE64 20 |
| |
| /* Size of .debug_rnglists section header for 32-bit DWARF format. */ |
| #define RNGLIST_HEADER_SIZE32 12 |
| |
| /* Size of .debug_rnglists section header for 64-bit DWARF format. */ |
| #define RNGLIST_HEADER_SIZE64 20 |
| |
| /* An index into a (C++) symbol name component in a symbol name as |
| recorded in the mapped_index's symbol table. For each C++ symbol |
| in the symbol table, we record one entry for the start of each |
| component in the symbol in a table of name components, and then |
| sort the table, in order to be able to binary search symbol names, |
| ignoring leading namespaces, both completion and regular look up. |
| For example, for symbol "A::B::C", we'll have an entry that points |
| to "A::B::C", another that points to "B::C", and another for "C". |
| Note that function symbols in GDB index have no parameter |
| information, just the function/method names. You can convert a |
| name_component to a "const char *" using the |
| 'mapped_index::symbol_name_at(offset_type)' method. */ |
| |
| struct name_component |
| { |
| /* Offset in the symbol name where the component starts. Stored as |
| a (32-bit) offset instead of a pointer to save memory and improve |
| locality on 64-bit architectures. */ |
| offset_type name_offset; |
| |
| /* The symbol's index in the symbol and constant pool tables of a |
| mapped_index. */ |
| offset_type idx; |
| }; |
| |
| /* Base class containing bits shared by both .gdb_index and |
| .debug_name indexes. */ |
| |
| struct mapped_index_base |
| { |
| mapped_index_base () = default; |
| DISABLE_COPY_AND_ASSIGN (mapped_index_base); |
| |
| /* The name_component table (a sorted vector). See name_component's |
| description above. */ |
| std::vector<name_component> name_components; |
| |
| /* How NAME_COMPONENTS is sorted. */ |
| enum case_sensitivity name_components_casing; |
| |
| /* Return the number of names in the symbol table. */ |
| virtual size_t symbol_name_count () const = 0; |
| |
| /* Get the name of the symbol at IDX in the symbol table. */ |
| virtual const char *symbol_name_at |
| (offset_type idx, dwarf2_per_objfile *per_objfile) const = 0; |
| |
| /* Return whether the name at IDX in the symbol table should be |
| ignored. */ |
| virtual bool symbol_name_slot_invalid (offset_type idx) const |
| { |
| return false; |
| } |
| |
| /* Build the symbol name component sorted vector, if we haven't |
| yet. */ |
| void build_name_components (dwarf2_per_objfile *per_objfile); |
| |
| /* Returns the lower (inclusive) and upper (exclusive) bounds of the |
| possible matches for LN_NO_PARAMS in the name component |
| vector. */ |
| std::pair<std::vector<name_component>::const_iterator, |
| std::vector<name_component>::const_iterator> |
| find_name_components_bounds (const lookup_name_info &ln_no_params, |
| enum language lang, |
| dwarf2_per_objfile *per_objfile) const; |
| |
| /* Prevent deleting/destroying via a base class pointer. */ |
| protected: |
| ~mapped_index_base() = default; |
| }; |
| |
| /* This is a view into the index that converts from bytes to an |
| offset_type, and allows indexing. Unaligned bytes are specifically |
| allowed here, and handled via unpacking. */ |
| |
| class offset_view |
| { |
| public: |
| offset_view () = default; |
| |
| explicit offset_view (gdb::array_view<const gdb_byte> bytes) |
| : m_bytes (bytes) |
| { |
| } |
| |
| /* Extract the INDEXth offset_type from the array. */ |
| offset_type operator[] (size_t index) const |
| { |
| const gdb_byte *bytes = &m_bytes[index * sizeof (offset_type)]; |
| return (offset_type) extract_unsigned_integer (bytes, |
| sizeof (offset_type), |
| BFD_ENDIAN_LITTLE); |
| } |
| |
| /* Return the number of offset_types in this array. */ |
| size_t size () const |
| { |
| return m_bytes.size () / sizeof (offset_type); |
| } |
| |
| /* Return true if this view is empty. */ |
| bool empty () const |
| { |
| return m_bytes.empty (); |
| } |
| |
| private: |
| /* The underlying bytes. */ |
| gdb::array_view<const gdb_byte> m_bytes; |
| }; |
| |
| /* A description of the mapped index. The file format is described in |
| a comment by the code that writes the index. */ |
| struct mapped_index final : public mapped_index_base |
| { |
| /* Index data format version. */ |
| int version = 0; |
| |
| /* The address table data. */ |
| gdb::array_view<const gdb_byte> address_table; |
| |
| /* The symbol table, implemented as a hash table. */ |
| offset_view symbol_table; |
| |
| /* A pointer to the constant pool. */ |
| gdb::array_view<const gdb_byte> constant_pool; |
| |
| /* Return the index into the constant pool of the name of the IDXth |
| symbol in the symbol table. */ |
| offset_type symbol_name_index (offset_type idx) const |
| { |
| return symbol_table[2 * idx]; |
| } |
| |
| /* Return the index into the constant pool of the CU vector of the |
| IDXth symbol in the symbol table. */ |
| offset_type symbol_vec_index (offset_type idx) const |
| { |
| return symbol_table[2 * idx + 1]; |
| } |
| |
| bool symbol_name_slot_invalid (offset_type idx) const override |
| { |
| return (symbol_name_index (idx) == 0 |
| && symbol_vec_index (idx) == 0); |
| } |
| |
| /* Convenience method to get at the name of the symbol at IDX in the |
| symbol table. */ |
| const char *symbol_name_at |
| (offset_type idx, dwarf2_per_objfile *per_objfile) const override |
| { |
| return (const char *) (this->constant_pool.data () |
| + symbol_name_index (idx)); |
| } |
| |
| size_t symbol_name_count () const override |
| { return this->symbol_table.size () / 2; } |
| }; |
| |
| /* A description of the mapped .debug_names. |
| Uninitialized map has CU_COUNT 0. */ |
| struct mapped_debug_names final : public mapped_index_base |
| { |
| bfd_endian dwarf5_byte_order; |
| bool dwarf5_is_dwarf64; |
| bool augmentation_is_gdb; |
| uint8_t offset_size; |
| uint32_t cu_count = 0; |
| uint32_t tu_count, bucket_count, name_count; |
| const gdb_byte *cu_table_reordered, *tu_table_reordered; |
| const uint32_t *bucket_table_reordered, *hash_table_reordered; |
| const gdb_byte *name_table_string_offs_reordered; |
| const gdb_byte *name_table_entry_offs_reordered; |
| const gdb_byte *entry_pool; |
| |
| struct index_val |
| { |
| ULONGEST dwarf_tag; |
| struct attr |
| { |
| /* Attribute name DW_IDX_*. */ |
| ULONGEST dw_idx; |
| |
| /* Attribute form DW_FORM_*. */ |
| ULONGEST form; |
| |
| /* Value if FORM is DW_FORM_implicit_const. */ |
| LONGEST implicit_const; |
| }; |
| std::vector<attr> attr_vec; |
| }; |
| |
| std::unordered_map<ULONGEST, index_val> abbrev_map; |
| |
| const char *namei_to_name |
| (uint32_t namei, dwarf2_per_objfile *per_objfile) const; |
| |
| /* Implementation of the mapped_index_base virtual interface, for |
| the name_components cache. */ |
| |
| const char *symbol_name_at |
| (offset_type idx, dwarf2_per_objfile *per_objfile) const override |
| { return namei_to_name (idx, per_objfile); } |
| |
| size_t symbol_name_count () const override |
| { return this->name_count; } |
| }; |
| |
| /* See dwarf2read.h. */ |
| |
| dwarf2_per_objfile * |
| get_dwarf2_per_objfile (struct objfile *objfile) |
| { |
| return dwarf2_objfile_data_key.get (objfile); |
| } |
| |
| /* Default names of the debugging sections. */ |
| |
| /* Note that if the debugging section has been compressed, it might |
| have a name like .zdebug_info. */ |
| |
| const struct dwarf2_debug_sections dwarf2_elf_names = |
| { |
| { ".debug_info", ".zdebug_info" }, |
| { ".debug_abbrev", ".zdebug_abbrev" }, |
| { ".debug_line", ".zdebug_line" }, |
| { ".debug_loc", ".zdebug_loc" }, |
| { ".debug_loclists", ".zdebug_loclists" }, |
| { ".debug_macinfo", ".zdebug_macinfo" }, |
| { ".debug_macro", ".zdebug_macro" }, |
| { ".debug_str", ".zdebug_str" }, |
| { ".debug_str_offsets", ".zdebug_str_offsets" }, |
| { ".debug_line_str", ".zdebug_line_str" }, |
| { ".debug_ranges", ".zdebug_ranges" }, |
| { ".debug_rnglists", ".zdebug_rnglists" }, |
| { ".debug_types", ".zdebug_types" }, |
| { ".debug_addr", ".zdebug_addr" }, |
| { ".debug_frame", ".zdebug_frame" }, |
| { ".eh_frame", NULL }, |
| { ".gdb_index", ".zgdb_index" }, |
| { ".debug_names", ".zdebug_names" }, |
| { ".debug_aranges", ".zdebug_aranges" }, |
| 23 |
| }; |
| |
| /* List of DWO/DWP sections. */ |
| |
| static const struct dwop_section_names |
| { |
| struct dwarf2_section_names abbrev_dwo; |
| struct dwarf2_section_names info_dwo; |
| struct dwarf2_section_names line_dwo; |
| struct dwarf2_section_names loc_dwo; |
| struct dwarf2_section_names loclists_dwo; |
| struct dwarf2_section_names macinfo_dwo; |
| struct dwarf2_section_names macro_dwo; |
| struct dwarf2_section_names rnglists_dwo; |
| struct dwarf2_section_names str_dwo; |
| struct dwarf2_section_names str_offsets_dwo; |
| struct dwarf2_section_names types_dwo; |
| struct dwarf2_section_names cu_index; |
| struct dwarf2_section_names tu_index; |
| } |
| dwop_section_names = |
| { |
| { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo" }, |
| { ".debug_info.dwo", ".zdebug_info.dwo" }, |
| { ".debug_line.dwo", ".zdebug_line.dwo" }, |
| { ".debug_loc.dwo", ".zdebug_loc.dwo" }, |
| { ".debug_loclists.dwo", ".zdebug_loclists.dwo" }, |
| { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" }, |
| { ".debug_macro.dwo", ".zdebug_macro.dwo" }, |
| { ".debug_rnglists.dwo", ".zdebug_rnglists.dwo" }, |
| { ".debug_str.dwo", ".zdebug_str.dwo" }, |
| { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" }, |
| { ".debug_types.dwo", ".zdebug_types.dwo" }, |
| { ".debug_cu_index", ".zdebug_cu_index" }, |
| { ".debug_tu_index", ".zdebug_tu_index" }, |
| }; |
| |
| /* local data types */ |
| |
| /* The location list and range list sections (.debug_loclists & .debug_rnglists) |
| begin with a header, which contains the following information. */ |
| struct loclists_rnglists_header |
| { |
| /* A 4-byte or 12-byte length containing the length of the |
| set of entries for this compilation unit, not including the |
| length field itself. */ |
| unsigned int length; |
| |
| /* A 2-byte version identifier. */ |
| short version; |
| |
| /* A 1-byte unsigned integer containing the size in bytes of an address on |
| the target system. */ |
| unsigned char addr_size; |
| |
| /* A 1-byte unsigned integer containing the size in bytes of a segment selector |
| on the target system. */ |
| unsigned char segment_collector_size; |
| |
| /* A 4-byte count of the number of offsets that follow the header. */ |
| unsigned int offset_entry_count; |
| }; |
| |
| /* A struct that can be used as a hash key for tables based on DW_AT_stmt_list. |
| This includes type_unit_group and quick_file_names. */ |
| |
| struct stmt_list_hash |
| { |
| /* The DWO unit this table is from or NULL if there is none. */ |
| struct dwo_unit *dwo_unit; |
| |
| /* Offset in .debug_line or .debug_line.dwo. */ |
| sect_offset line_sect_off; |
| }; |
| |
| /* Each element of dwarf2_per_bfd->type_unit_groups is a pointer to |
| an object of this type. This contains elements of type unit groups |
| that can be shared across objfiles. The non-shareable parts are in |
| type_unit_group_unshareable. */ |
| |
| struct type_unit_group : public dwarf2_per_cu_data |
| { |
| /* The TUs that share this DW_AT_stmt_list entry. |
| This is added to while parsing type units to build partial symtabs, |
| and is deleted afterwards and not used again. */ |
| std::vector<signatured_type *> *tus = nullptr; |
| |
| /* The data used to construct the hash key. */ |
| struct stmt_list_hash hash {}; |
| }; |
| |
| /* These sections are what may appear in a (real or virtual) DWO file. */ |
| |
| struct dwo_sections |
| { |
| struct dwarf2_section_info abbrev; |
| struct dwarf2_section_info line; |
| struct dwarf2_section_info loc; |
| struct dwarf2_section_info loclists; |
| struct dwarf2_section_info macinfo; |
| struct dwarf2_section_info macro; |
| struct dwarf2_section_info rnglists; |
| struct dwarf2_section_info str; |
| struct dwarf2_section_info str_offsets; |
| /* In the case of a virtual DWO file, these two are unused. */ |
| struct dwarf2_section_info info; |
| std::vector<dwarf2_section_info> types; |
| }; |
| |
| /* CUs/TUs in DWP/DWO files. */ |
| |
| struct dwo_unit |
| { |
| /* Backlink to the containing struct dwo_file. */ |
| struct dwo_file *dwo_file; |
| |
| /* The "id" that distinguishes this CU/TU. |
| .debug_info calls this "dwo_id", .debug_types calls this "signature". |
| Since signatures came first, we stick with it for consistency. */ |
| ULONGEST signature; |
| |
| /* The section this CU/TU lives in, in the DWO file. */ |
| struct dwarf2_section_info *section; |
| |
| /* Same as dwarf2_per_cu_data:{sect_off,length} but in the DWO section. */ |
| sect_offset sect_off; |
| unsigned int length; |
| |
| /* For types, offset in the type's DIE of the type defined by this TU. */ |
| cu_offset type_offset_in_tu; |
| }; |
| |
| /* include/dwarf2.h defines the DWP section codes. |
| It defines a max value but it doesn't define a min value, which we |
| use for error checking, so provide one. */ |
| |
| enum dwp_v2_section_ids |
| { |
| DW_SECT_MIN = 1 |
| }; |
| |
| /* Data for one DWO file. |
| |
| This includes virtual DWO files (a virtual DWO file is a DWO file as it |
| appears in a DWP file). DWP files don't really have DWO files per se - |
| comdat folding of types "loses" the DWO file they came from, and from |
| a high level view DWP files appear to contain a mass of random types. |
| However, to maintain consistency with the non-DWP case we pretend DWP |
| files contain virtual DWO files, and we assign each TU with one virtual |
| DWO file (generally based on the line and abbrev section offsets - |
| a heuristic that seems to work in practice). */ |
| |
| struct dwo_file |
| { |
| dwo_file () = default; |
| DISABLE_COPY_AND_ASSIGN (dwo_file); |
| |
| /* The DW_AT_GNU_dwo_name or DW_AT_dwo_name attribute. |
| For virtual DWO files the name is constructed from the section offsets |
| of abbrev,line,loc,str_offsets so that we combine virtual DWO files |
| from related CU+TUs. */ |
| const char *dwo_name = nullptr; |
| |
| /* The DW_AT_comp_dir attribute. */ |
| const char *comp_dir = nullptr; |
| |
| /* The bfd, when the file is open. Otherwise this is NULL. |
| This is unused(NULL) for virtual DWO files where we use dwp_file.dbfd. */ |
| gdb_bfd_ref_ptr dbfd; |
| |
| /* The sections that make up this DWO file. |
| Remember that for virtual DWO files in DWP V2 or DWP V5, these are virtual |
| sections (for lack of a better name). */ |
| struct dwo_sections sections {}; |
| |
| /* The CUs in the file. |
| Each element is a struct dwo_unit. Multiple CUs per DWO are supported as |
| an extension to handle LLVM's Link Time Optimization output (where |
| multiple source files may be compiled into a single object/dwo pair). */ |
| htab_up cus; |
| |
| /* Table of TUs in the file. |
| Each element is a struct dwo_unit. */ |
| htab_up tus; |
| }; |
| |
| /* These sections are what may appear in a DWP file. */ |
| |
| struct dwp_sections |
| { |
| /* These are used by all DWP versions (1, 2 and 5). */ |
| struct dwarf2_section_info str; |
| struct dwarf2_section_info cu_index; |
| struct dwarf2_section_info tu_index; |
| |
| /* These are only used by DWP version 2 and version 5 files. |
| In DWP version 1 the .debug_info.dwo, .debug_types.dwo, and other |
| sections are referenced by section number, and are not recorded here. |
| In DWP version 2 or 5 there is at most one copy of all these sections, |
| each section being (effectively) comprised of the concatenation of all of |
| the individual sections that exist in the version 1 format. |
| To keep the code simple we treat each of these concatenated pieces as a |
| section itself (a virtual section?). */ |
| struct dwarf2_section_info abbrev; |
| struct dwarf2_section_info info; |
| struct dwarf2_section_info line; |
| struct dwarf2_section_info loc; |
| struct dwarf2_section_info loclists; |
| struct dwarf2_section_info macinfo; |
| struct dwarf2_section_info macro; |
| struct dwarf2_section_info rnglists; |
| struct dwarf2_section_info str_offsets; |
| struct dwarf2_section_info types; |
| }; |
| |
| /* These sections are what may appear in a virtual DWO file in DWP version 1. |
| A virtual DWO file is a DWO file as it appears in a DWP file. */ |
| |
| struct virtual_v1_dwo_sections |
| { |
| struct dwarf2_section_info abbrev; |
| struct dwarf2_section_info line; |
| struct dwarf2_section_info loc; |
| struct dwarf2_section_info macinfo; |
| struct dwarf2_section_info macro; |
| struct dwarf2_section_info str_offsets; |
| /* Each DWP hash table entry records one CU or one TU. |
| That is recorded here, and copied to dwo_unit.section. */ |
| struct dwarf2_section_info info_or_types; |
| }; |
| |
| /* Similar to virtual_v1_dwo_sections, but for DWP version 2 or 5. |
| In version 2, the sections of the DWO files are concatenated together |
| and stored in one section of that name. Thus each ELF section contains |
| several "virtual" sections. */ |
| |
| struct virtual_v2_or_v5_dwo_sections |
| { |
| bfd_size_type abbrev_offset; |
| bfd_size_type abbrev_size; |
| |
| bfd_size_type line_offset; |
| bfd_size_type line_size; |
| |
| bfd_size_type loc_offset; |
| bfd_size_type loc_size; |
| |
| bfd_size_type loclists_offset; |
| bfd_size_type loclists_size; |
| |
| bfd_size_type macinfo_offset; |
| bfd_size_type macinfo_size; |
| |
| bfd_size_type macro_offset; |
| bfd_size_type macro_size; |
| |
| bfd_size_type rnglists_offset; |
| bfd_size_type rnglists_size; |
| |
| bfd_size_type str_offsets_offset; |
| bfd_size_type str_offsets_size; |
| |
| /* Each DWP hash table entry records one CU or one TU. |
| That is recorded here, and copied to dwo_unit.section. */ |
| bfd_size_type info_or_types_offset; |
| bfd_size_type info_or_types_size; |
| }; |
| |
| /* Contents of DWP hash tables. */ |
| |
| struct dwp_hash_table |
| { |
| uint32_t version, nr_columns; |
| uint32_t nr_units, nr_slots; |
| const gdb_byte *hash_table, *unit_table; |
| union |
| { |
| struct |
| { |
| const gdb_byte *indices; |
| } v1; |
| struct |
| { |
| /* This is indexed by column number and gives the id of the section |
| in that column. */ |
| #define MAX_NR_V2_DWO_SECTIONS \ |
| (1 /* .debug_info or .debug_types */ \ |
| + 1 /* .debug_abbrev */ \ |
| + 1 /* .debug_line */ \ |
| + 1 /* .debug_loc */ \ |
| + 1 /* .debug_str_offsets */ \ |
| + 1 /* .debug_macro or .debug_macinfo */) |
| int section_ids[MAX_NR_V2_DWO_SECTIONS]; |
| const gdb_byte *offsets; |
| const gdb_byte *sizes; |
| } v2; |
| struct |
| { |
| /* This is indexed by column number and gives the id of the section |
| in that column. */ |
| #define MAX_NR_V5_DWO_SECTIONS \ |
| (1 /* .debug_info */ \ |
| + 1 /* .debug_abbrev */ \ |
| + 1 /* .debug_line */ \ |
| + 1 /* .debug_loclists */ \ |
| + 1 /* .debug_str_offsets */ \ |
| + 1 /* .debug_macro */ \ |
| + 1 /* .debug_rnglists */) |
| int section_ids[MAX_NR_V5_DWO_SECTIONS]; |
| const gdb_byte *offsets; |
| const gdb_byte *sizes; |
| } v5; |
| } section_pool; |
| }; |
| |
| /* Data for one DWP file. */ |
| |
| struct dwp_file |
| { |
| dwp_file (const char *name_, gdb_bfd_ref_ptr &&abfd) |
| : name (name_), |
| dbfd (std::move (abfd)) |
| { |
| } |
| |
| /* Name of the file. */ |
| const char *name; |
| |
| /* File format version. */ |
| int version = 0; |
| |
| /* The bfd. */ |
| gdb_bfd_ref_ptr dbfd; |
| |
| /* Section info for this file. */ |
| struct dwp_sections sections {}; |
| |
| /* Table of CUs in the file. */ |
| const struct dwp_hash_table *cus = nullptr; |
| |
| /* Table of TUs in the file. */ |
| const struct dwp_hash_table *tus = nullptr; |
| |
| /* Tables of loaded CUs/TUs. Each entry is a struct dwo_unit *. */ |
| htab_up loaded_cus; |
| htab_up loaded_tus; |
| |
| /* Table to map ELF section numbers to their sections. |
| This is only needed for the DWP V1 file format. */ |
| unsigned int num_sections = 0; |
| asection **elf_sections = nullptr; |
| }; |
| |
| /* Struct used to pass misc. parameters to read_die_and_children, et |
| al. which are used for both .debug_info and .debug_types dies. |
| All parameters here are unchanging for the life of the call. This |
| struct exists to abstract away the constant parameters of die reading. */ |
| |
| struct die_reader_specs |
| { |
| /* The bfd of die_section. */ |
| bfd *abfd; |
| |
| /* The CU of the DIE we are parsing. */ |
| struct dwarf2_cu *cu; |
| |
| /* Non-NULL if reading a DWO file (including one packaged into a DWP). */ |
| struct dwo_file *dwo_file; |
| |
| /* The section the die comes from. |
| This is either .debug_info or .debug_types, or the .dwo variants. */ |
| struct dwarf2_section_info *die_section; |
| |
| /* die_section->buffer. */ |
| const gdb_byte *buffer; |
| |
| /* The end of the buffer. */ |
| const gdb_byte *buffer_end; |
| |
| /* The abbreviation table to use when reading the DIEs. */ |
| struct abbrev_table *abbrev_table; |
| }; |
| |
| /* A subclass of die_reader_specs that holds storage and has complex |
| constructor and destructor behavior. */ |
| |
| class cutu_reader : public die_reader_specs |
| { |
| public: |
| |
| cutu_reader (dwarf2_per_cu_data *this_cu, |
| dwarf2_per_objfile *per_objfile, |
| struct abbrev_table *abbrev_table, |
| dwarf2_cu *existing_cu, |
| bool skip_partial); |
| |
| explicit cutu_reader (struct dwarf2_per_cu_data *this_cu, |
| dwarf2_per_objfile *per_objfile, |
| struct dwarf2_cu *parent_cu = nullptr, |
| struct dwo_file *dwo_file = nullptr); |
| |
| DISABLE_COPY_AND_ASSIGN (cutu_reader); |
| |
| const gdb_byte *info_ptr = nullptr; |
| struct die_info *comp_unit_die = nullptr; |
| bool dummy_p = false; |
| |
| /* Release the new CU, putting it on the chain. This cannot be done |
| for dummy CUs. */ |
| void keep (); |
| |
| private: |
| void init_tu_and_read_dwo_dies (dwarf2_per_cu_data *this_cu, |
| dwarf2_per_objfile *per_objfile, |
| dwarf2_cu *existing_cu); |
| |
| struct dwarf2_per_cu_data *m_this_cu; |
| std::unique_ptr<dwarf2_cu> m_new_cu; |
| |
| /* The ordinary abbreviation table. */ |
| abbrev_table_up m_abbrev_table_holder; |
| |
| /* The DWO abbreviation table. */ |
| abbrev_table_up m_dwo_abbrev_table; |
| }; |
| |
| /* When we construct a partial symbol table entry we only |
| need this much information. */ |
| struct partial_die_info : public allocate_on_obstack |
| { |
| partial_die_info (sect_offset sect_off, const struct abbrev_info *abbrev); |
| |
| /* Disable assign but still keep copy ctor, which is needed |
| load_partial_dies. */ |
| partial_die_info& operator=(const partial_die_info& rhs) = delete; |
| partial_die_info (const partial_die_info &) = default; |
| |
| /* Adjust the partial die before generating a symbol for it. This |
| function may set the is_external flag or change the DIE's |
| name. */ |
| void fixup (struct dwarf2_cu *cu); |
| |
| /* Read a minimal amount of information into the minimal die |
| structure. */ |
| const gdb_byte *read (const struct die_reader_specs *reader, |
| const struct abbrev_info &abbrev, |
| const gdb_byte *info_ptr); |
| |
| /* Compute the name of this partial DIE. This memoizes the |
| result, so it is safe to call multiple times. */ |
| const char *name (dwarf2_cu *cu); |
| |
| /* Offset of this DIE. */ |
| const sect_offset sect_off; |
| |
| /* DWARF-2 tag for this DIE. */ |
| const ENUM_BITFIELD(dwarf_tag) tag : 16; |
| |
| /* Assorted flags describing the data found in this DIE. */ |
| const unsigned int has_children : 1; |
| |
| unsigned int is_external : 1; |
| unsigned int is_declaration : 1; |
| unsigned int has_type : 1; |
| unsigned int has_specification : 1; |
| unsigned int has_pc_info : 1; |
| unsigned int has_range_info : 1; |
| unsigned int may_be_inlined : 1; |
| |
| /* This DIE has been marked DW_AT_main_subprogram. */ |
| unsigned int main_subprogram : 1; |
| |
| /* Flag set if the SCOPE field of this structure has been |
| computed. */ |
| unsigned int scope_set : 1; |
| |
| /* Flag set if the DIE has a byte_size attribute. */ |
| unsigned int has_byte_size : 1; |
| |
| /* Flag set if the DIE has a DW_AT_const_value attribute. */ |
| unsigned int has_const_value : 1; |
| |
| /* Flag set if any of the DIE's children are template arguments. */ |
| unsigned int has_template_arguments : 1; |
| |
| /* Flag set if fixup has been called on this die. */ |
| unsigned int fixup_called : 1; |
| |
| /* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */ |
| unsigned int is_dwz : 1; |
| |
| /* Flag set if spec_offset uses DW_FORM_GNU_ref_alt. */ |
| unsigned int spec_is_dwz : 1; |
| |
| unsigned int canonical_name : 1; |
| |
| /* The name of this DIE. Normally the value of DW_AT_name, but |
| sometimes a default name for unnamed DIEs. */ |
| const char *raw_name = nullptr; |
| |
| /* The linkage name, if present. */ |
| const char *linkage_name = nullptr; |
| |
| /* The scope to prepend to our children. This is generally |
| allocated on the comp_unit_obstack, so will disappear |
| when this compilation unit leaves the cache. */ |
| const char *scope = nullptr; |
| |
| /* Some data associated with the partial DIE. The tag determines |
| which field is live. */ |
| union |
| { |
| /* The location description associated with this DIE, if any. */ |
| struct dwarf_block *locdesc; |
| /* The offset of an import, for DW_TAG_imported_unit. */ |
| sect_offset sect_off; |
| } d {}; |
| |
| union |
| { |
| /* If HAS_PC_INFO, the PC range associated with this DIE. */ |
| struct |
| { |
| CORE_ADDR lowpc; |
| CORE_ADDR highpc; |
| }; |
| /* If HAS_RANGE_INFO, the ranges offset associated with this DIE. */ |
| ULONGEST ranges_offset; |
| }; |
| |
| /* Pointer into the info_buffer (or types_buffer) pointing at the target of |
| DW_AT_sibling, if any. */ |
| /* NOTE: This member isn't strictly necessary, partial_die_info::read |
| could return DW_AT_sibling values to its caller load_partial_dies. */ |
| const gdb_byte *sibling = nullptr; |
| |
| /* If HAS_SPECIFICATION, the offset of the DIE referred to by |
| DW_AT_specification (or DW_AT_abstract_origin or |
| DW_AT_extension). */ |
| sect_offset spec_offset {}; |
| |
| /* Pointers to this DIE's parent, first child, and next sibling, |
| if any. */ |
| struct partial_die_info *die_parent = nullptr; |
| struct partial_die_info *die_child = nullptr; |
| struct partial_die_info *die_sibling = nullptr; |
| |
| friend struct partial_die_info * |
| dwarf2_cu::find_partial_die (sect_offset sect_off); |
| |
| private: |
| /* Only need to do look up in dwarf2_cu::find_partial_die. */ |
| partial_die_info (sect_offset sect_off) |
| : partial_die_info (sect_off, DW_TAG_padding, 0) |
| { |
| } |
| |
| partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_, |
| int has_children_) |
| : sect_off (sect_off_), tag (tag_), has_children (has_children_) |
| { |
| is_external = 0; |
| is_declaration = 0; |
| has_type = 0; |
| has_specification = 0; |
| has_pc_info = 0; |
| has_range_info = 0; |
| may_be_inlined = 0; |
| main_subprogram = 0; |
| scope_set = 0; |
| has_byte_size = 0; |
| has_const_value = 0; |
| has_template_arguments = 0; |
| fixup_called = 0; |
| is_dwz = 0; |
| spec_is_dwz = 0; |
| canonical_name = 0; |
| /* Don't set these using NSDMI (Non-static data member initialisation), |
| because g++-4.8 will error out. */ |
| lowpc = 0; |
| highpc = 0; |
| } |
| }; |
| |
| /* FIXME: We might want to set this from BFD via bfd_arch_bits_per_byte, |
| but this would require a corresponding change in unpack_field_as_long |
| and friends. */ |
| static int bits_per_byte = 8; |
| |
| struct variant_part_builder; |
| |
| /* When reading a variant, we track a bit more information about the |
| field, and store it in an object of this type. */ |
| |
| struct variant_field |
| { |
| int first_field = -1; |
| int last_field = -1; |
| |
| /* A variant can contain other variant parts. */ |
| std::vector<variant_part_builder> variant_parts; |
| |
| /* If we see a DW_TAG_variant, then this will be set if this is the |
| default branch. */ |
| bool default_branch = false; |
| /* If we see a DW_AT_discr_value, then this will be the discriminant |
| value. */ |
| ULONGEST discriminant_value = 0; |
| /* If we see a DW_AT_discr_list, then this is a pointer to the list |
| data. */ |
| struct dwarf_block *discr_list_data = nullptr; |
| }; |
| |
| /* This represents a DW_TAG_variant_part. */ |
| |
| struct variant_part_builder |
| { |
| /* The offset of the discriminant field. */ |
| sect_offset discriminant_offset {}; |
| |
| /* Variants that are direct children of this variant part. */ |
| std::vector<variant_field> variants; |
| |
| /* True if we're currently reading a variant. */ |
| bool processing_variant = false; |
| }; |
| |
| struct nextfield |
| { |
| int accessibility = 0; |
| int virtuality = 0; |
| /* Variant parts need to find the discriminant, which is a DIE |
| reference. We track the section offset of each field to make |
| this link. */ |
| sect_offset offset; |
| struct field field {}; |
| }; |
| |
| struct fnfieldlist |
| { |
| const char *name = nullptr; |
| std::vector<struct fn_field> fnfields; |
| }; |
| |
| /* The routines that read and process dies for a C struct or C++ class |
| pass lists of data member fields and lists of member function fields |
| in an instance of a field_info structure, as defined below. */ |
| struct field_info |
| { |
| /* List of data member and baseclasses fields. */ |
| std::vector<struct nextfield> fields; |
| std::vector<struct nextfield> baseclasses; |
| |
| /* Set if the accessibility of one of the fields is not public. */ |
| bool non_public_fields = false; |
| |
| /* Member function fieldlist array, contains name of possibly overloaded |
| member function, number of overloaded member functions and a pointer |
| to the head of the member function field chain. */ |
| std::vector<struct fnfieldlist> fnfieldlists; |
| |
| /* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of |
| a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */ |
| std::vector<struct decl_field> typedef_field_list; |
| |
| /* Nested types defined by this class and the number of elements in this |
| list. */ |
| std::vector<struct decl_field> nested_types_list; |
| |
| /* If non-null, this is the variant part we are currently |
| reading. */ |
| variant_part_builder *current_variant_part = nullptr; |
| /* This holds all the top-level variant parts attached to the type |
| we're reading. */ |
| std::vector<variant_part_builder> variant_parts; |
| |
| /* Return the total number of fields (including baseclasses). */ |
| int nfields () const |
| { |
| return fields.size () + baseclasses.size (); |
| } |
| }; |
| |
| /* Loaded secondary compilation units are kept in memory until they |
| have not been referenced for the processing of this many |
| compilation units. Set this to zero to disable caching. Cache |
| sizes of up to at least twenty will improve startup time for |
| typical inter-CU-reference binaries, at an obvious memory cost. */ |
| static int dwarf_max_cache_age = 5; |
| static void |
| show_dwarf_max_cache_age (struct ui_file *file, int from_tty, |
| struct cmd_list_element *c, const char *value) |
| { |
| fprintf_filtered (file, _("The upper bound on the age of cached " |
| "DWARF compilation units is %s.\n"), |
| value); |
| } |
| |
| /* local function prototypes */ |
| |
| static void dwarf2_find_base_address (struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static dwarf2_psymtab *create_partial_symtab |
| (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, |
| const char *name); |
| |
| static void build_type_psymtabs_reader (const struct die_reader_specs *reader, |
| const gdb_byte *info_ptr, |
| struct die_info *type_unit_die); |
| |
| static void dwarf2_build_psymtabs_hard (dwarf2_per_objfile *per_objfile); |
| |
| static void scan_partial_symbols (struct partial_die_info *, |
| CORE_ADDR *, CORE_ADDR *, |
| int, struct dwarf2_cu *); |
| |
| static void add_partial_symbol (struct partial_die_info *, |
| struct dwarf2_cu *); |
| |
| static void add_partial_namespace (struct partial_die_info *pdi, |
| CORE_ADDR *lowpc, CORE_ADDR *highpc, |
| int set_addrmap, struct dwarf2_cu *cu); |
| |
| static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc, |
| CORE_ADDR *highpc, int set_addrmap, |
| struct dwarf2_cu *cu); |
| |
| static void add_partial_enumeration (struct partial_die_info *enum_pdi, |
| struct dwarf2_cu *cu); |
| |
| static void add_partial_subprogram (struct partial_die_info *pdi, |
| CORE_ADDR *lowpc, CORE_ADDR *highpc, |
| int need_pc, struct dwarf2_cu *cu); |
| |
| static unsigned int peek_abbrev_code (bfd *, const gdb_byte *); |
| |
| static struct partial_die_info *load_partial_dies |
| (const struct die_reader_specs *, const gdb_byte *, int); |
| |
| /* A pair of partial_die_info and compilation unit. */ |
| struct cu_partial_die_info |
| { |
| /* The compilation unit of the partial_die_info. */ |
| struct dwarf2_cu *cu; |
| /* A partial_die_info. */ |
| struct partial_die_info *pdi; |
| |
| cu_partial_die_info (struct dwarf2_cu *cu, struct partial_die_info *pdi) |
| : cu (cu), |
| pdi (pdi) |
| { /* Nothing. */ } |
| |
| private: |
| cu_partial_die_info () = delete; |
| }; |
| |
| static const struct cu_partial_die_info find_partial_die (sect_offset, int, |
| struct dwarf2_cu *); |
| |
| static const gdb_byte *read_attribute (const struct die_reader_specs *, |
| struct attribute *, |
| const struct attr_abbrev *, |
| const gdb_byte *); |
| |
| static void read_attribute_reprocess (const struct die_reader_specs *reader, |
| struct attribute *attr, dwarf_tag tag); |
| |
| static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index); |
| |
| static sect_offset read_abbrev_offset (dwarf2_per_objfile *per_objfile, |
| dwarf2_section_info *, sect_offset); |
| |
| static const char *read_indirect_string |
| (dwarf2_per_objfile *per_objfile, bfd *, const gdb_byte *, |
| const struct comp_unit_head *, unsigned int *); |
| |
| static const char *read_indirect_string_at_offset |
| (dwarf2_per_objfile *per_objfile, LONGEST str_offset); |
| |
| static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, |
| const gdb_byte *, |
| unsigned int *); |
| |
| static const char *read_dwo_str_index (const struct die_reader_specs *reader, |
| ULONGEST str_index); |
| |
| static const char *read_stub_str_index (struct dwarf2_cu *cu, |
| ULONGEST str_index); |
| |
| static struct attribute *dwarf2_attr (struct die_info *, unsigned int, |
| struct dwarf2_cu *); |
| |
| static const char *dwarf2_string_attr (struct die_info *die, unsigned int name, |
| struct dwarf2_cu *cu); |
| |
| static const char *dwarf2_dwo_name (struct die_info *die, struct dwarf2_cu *cu); |
| |
| static int dwarf2_flag_true_p (struct die_info *die, unsigned name, |
| struct dwarf2_cu *cu); |
| |
| static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu); |
| |
| static struct die_info *die_specification (struct die_info *die, |
| struct dwarf2_cu **); |
| |
| static line_header_up dwarf_decode_line_header (sect_offset sect_off, |
| struct dwarf2_cu *cu); |
| |
| struct file_and_directory; |
| static void dwarf_decode_lines (struct line_header *, |
| const file_and_directory &, |
| struct dwarf2_cu *, dwarf2_psymtab *, |
| CORE_ADDR, int decode_mapping); |
| |
| static void dwarf2_start_subfile (struct dwarf2_cu *, const char *, |
| const char *); |
| |
| static struct symbol *new_symbol (struct die_info *, struct type *, |
| struct dwarf2_cu *, struct symbol * = NULL); |
| |
| static void dwarf2_const_value (const struct attribute *, struct symbol *, |
| struct dwarf2_cu *); |
| |
| static void dwarf2_const_value_attr (const struct attribute *attr, |
| struct type *type, |
| const char *name, |
| struct obstack *obstack, |
| struct dwarf2_cu *cu, LONGEST *value, |
| const gdb_byte **bytes, |
| struct dwarf2_locexpr_baton **baton); |
| |
| static struct type *read_subrange_index_type (struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static struct type *die_type (struct die_info *, struct dwarf2_cu *); |
| |
| static int need_gnat_info (struct dwarf2_cu *); |
| |
| static struct type *die_descriptive_type (struct die_info *, |
| struct dwarf2_cu *); |
| |
| static void set_descriptive_type (struct type *, struct die_info *, |
| struct dwarf2_cu *); |
| |
| static struct type *die_containing_type (struct die_info *, |
| struct dwarf2_cu *); |
| |
| static struct type *lookup_die_type (struct die_info *, const struct attribute *, |
| struct dwarf2_cu *); |
| |
| static struct type *read_type_die (struct die_info *, struct dwarf2_cu *); |
| |
| static struct type *read_type_die_1 (struct die_info *, struct dwarf2_cu *); |
| |
| static const char *determine_prefix (struct die_info *die, struct dwarf2_cu *); |
| |
| static char *typename_concat (struct obstack *obs, const char *prefix, |
| const char *suffix, int physname, |
| struct dwarf2_cu *cu); |
| |
| static void read_file_scope (struct die_info *, struct dwarf2_cu *); |
| |
| static void read_type_unit_scope (struct die_info *, struct dwarf2_cu *); |
| |
| static void read_func_scope (struct die_info *, struct dwarf2_cu *); |
| |
| static void read_lexical_block_scope (struct die_info *, struct dwarf2_cu *); |
| |
| static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu); |
| |
| static void read_variable (struct die_info *die, struct dwarf2_cu *cu); |
| |
| /* Return the .debug_loclists section to use for cu. */ |
| static struct dwarf2_section_info *cu_debug_loc_section (struct dwarf2_cu *cu); |
| |
| /* Return the .debug_rnglists section to use for cu. */ |
| static struct dwarf2_section_info *cu_debug_rnglists_section |
| (struct dwarf2_cu *cu, dwarf_tag tag); |
| |
| /* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return |
| values. Keep the items ordered with increasing constraints compliance. */ |
| enum pc_bounds_kind |
| { |
| /* No attribute DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges was found. */ |
| PC_BOUNDS_NOT_PRESENT, |
| |
| /* Some of the attributes DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges |
| were present but they do not form a valid range of PC addresses. */ |
| PC_BOUNDS_INVALID, |
| |
| /* Discontiguous range was found - that is DW_AT_ranges was found. */ |
| PC_BOUNDS_RANGES, |
| |
| /* Contiguous range was found - DW_AT_low_pc and DW_AT_high_pc were found. */ |
| PC_BOUNDS_HIGH_LOW, |
| }; |
| |
| static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *, |
| CORE_ADDR *, CORE_ADDR *, |
| struct dwarf2_cu *, |
| dwarf2_psymtab *); |
| |
| static void get_scope_pc_bounds (struct die_info *, |
| CORE_ADDR *, CORE_ADDR *, |
| struct dwarf2_cu *); |
| |
| static void dwarf2_record_block_ranges (struct die_info *, struct block *, |
| CORE_ADDR, struct dwarf2_cu *); |
| |
| static void dwarf2_add_field (struct field_info *, struct die_info *, |
| struct dwarf2_cu *); |
| |
| static void dwarf2_attach_fields_to_type (struct field_info *, |
| struct type *, struct dwarf2_cu *); |
| |
| static void dwarf2_add_member_fn (struct field_info *, |
| struct die_info *, struct type *, |
| struct dwarf2_cu *); |
| |
| static void dwarf2_attach_fn_fields_to_type (struct field_info *, |
| struct type *, |
| struct dwarf2_cu *); |
| |
| static void process_structure_scope (struct die_info *, struct dwarf2_cu *); |
| |
| static void read_common_block (struct die_info *, struct dwarf2_cu *); |
| |
| static void read_namespace (struct die_info *die, struct dwarf2_cu *); |
| |
| static void read_module (struct die_info *die, struct dwarf2_cu *cu); |
| |
| static struct using_direct **using_directives (struct dwarf2_cu *cu); |
| |
| static void read_import_statement (struct die_info *die, struct dwarf2_cu *); |
| |
| static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu); |
| |
| static struct type *read_module_type (struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static const char *namespace_name (struct die_info *die, |
| int *is_anonymous, struct dwarf2_cu *); |
| |
| static void process_enumeration_scope (struct die_info *, struct dwarf2_cu *); |
| |
| static CORE_ADDR decode_locdesc (struct dwarf_block *, struct dwarf2_cu *, |
| bool * = nullptr); |
| |
| static enum dwarf_array_dim_ordering read_array_order (struct die_info *, |
| struct dwarf2_cu *); |
| |
| static struct die_info *read_die_and_siblings_1 |
| (const struct die_reader_specs *, const gdb_byte *, const gdb_byte **, |
| struct die_info *); |
| |
| static struct die_info *read_die_and_siblings (const struct die_reader_specs *, |
| const gdb_byte *info_ptr, |
| const gdb_byte **new_info_ptr, |
| struct die_info *parent); |
| |
| static const gdb_byte *read_full_die_1 (const struct die_reader_specs *, |
| struct die_info **, const gdb_byte *, |
| int); |
| |
| static const gdb_byte *read_full_die (const struct die_reader_specs *, |
| struct die_info **, const gdb_byte *); |
| |
| static void process_die (struct die_info *, struct dwarf2_cu *); |
| |
| static const char *dwarf2_canonicalize_name (const char *, struct dwarf2_cu *, |
| struct objfile *); |
| |
| static const char *dwarf2_name (struct die_info *die, struct dwarf2_cu *); |
| |
| static const char *dwarf2_full_name (const char *name, |
| struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static const char *dwarf2_physname (const char *name, struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| 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 die_info *follow_die_ref_or_sig (struct die_info *, |
| const struct attribute *, |
| struct dwarf2_cu **); |
| |
| static struct die_info *follow_die_ref (struct die_info *, |
| const struct attribute *, |
| struct dwarf2_cu **); |
| |
| static struct die_info *follow_die_sig (struct die_info *, |
| const struct attribute *, |
| struct dwarf2_cu **); |
| |
| static struct type *get_signatured_type (struct die_info *, ULONGEST, |
| struct dwarf2_cu *); |
| |
| static struct type *get_DW_AT_signature_type (struct die_info *, |
| const struct attribute *, |
| struct dwarf2_cu *); |
| |
| static void load_full_type_unit (dwarf2_per_cu_data *per_cu, |
| dwarf2_per_objfile *per_objfile); |
| |
| static void read_signatured_type (signatured_type *sig_type, |
| dwarf2_per_objfile *per_objfile); |
| |
| static int attr_to_dynamic_prop (const struct attribute *attr, |
| struct die_info *die, struct dwarf2_cu *cu, |
| struct dynamic_prop *prop, struct type *type); |
| |
| /* memory allocation interface */ |
| |
| 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, |
| struct dwarf2_loclist_baton *baton, |
| const struct attribute *attr); |
| |
| static void dwarf2_symbol_mark_computed (const struct attribute *attr, |
| struct symbol *sym, |
| struct dwarf2_cu *cu, |
| int is_block); |
| |
| static const gdb_byte *skip_one_die (const struct die_reader_specs *reader, |
| const gdb_byte *info_ptr, |
| const struct abbrev_info *abbrev); |
| |
| static hashval_t partial_die_hash (const void *item); |
| |
| static int partial_die_eq (const void *item_lhs, const void *item_rhs); |
| |
| static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit |
| (sect_offset sect_off, unsigned int offset_in_dwz, |
| dwarf2_per_objfile *per_objfile); |
| |
| static void prepare_one_comp_unit (struct dwarf2_cu *cu, |
| struct die_info *comp_unit_die, |
| enum language pretend_language); |
| |
| static struct type *set_die_type (struct die_info *, struct type *, |
| struct dwarf2_cu *, bool = false); |
| |
| static void create_all_comp_units (dwarf2_per_objfile *per_objfile); |
| |
| static void load_full_comp_unit (dwarf2_per_cu_data *per_cu, |
| dwarf2_per_objfile *per_objfile, |
| dwarf2_cu *existing_cu, |
| bool skip_partial, |
| enum language pretend_language); |
| |
| static void process_full_comp_unit (dwarf2_cu *cu, |
| enum language pretend_language); |
| |
| static void process_full_type_unit (dwarf2_cu *cu, |
| enum language pretend_language); |
| |
| static struct type *get_die_type_at_offset (sect_offset, |
| dwarf2_per_cu_data *per_cu, |
| dwarf2_per_objfile *per_objfile); |
| |
| static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); |
| |
| static void queue_comp_unit (dwarf2_per_cu_data *per_cu, |
| dwarf2_per_objfile *per_objfile, |
| enum language pretend_language); |
| |
| static void process_queue (dwarf2_per_objfile *per_objfile); |
| |
| /* Class, the destructor of which frees all allocated queue entries. This |
| will only have work to do if an error was thrown while processing the |
| dwarf. If no error was thrown then the queue entries should have all |
| been processed, and freed, as we went along. */ |
| |
| class dwarf2_queue_guard |
| { |
| public: |
| explicit dwarf2_queue_guard (dwarf2_per_objfile *per_objfile) |
| : m_per_objfile (per_objfile) |
| { |
| gdb_assert (!m_per_objfile->per_bfd->queue.has_value ()); |
| |
| m_per_objfile->per_bfd->queue.emplace (); |
| } |
| |
| /* Free any entries remaining on the queue. There should only be |
| entries left if we hit an error while processing the dwarf. */ |
| ~dwarf2_queue_guard () |
| { |
| gdb_assert (m_per_objfile->per_bfd->queue.has_value ()); |
| |
| m_per_objfile->per_bfd->queue.reset (); |
| } |
| |
| DISABLE_COPY_AND_ASSIGN (dwarf2_queue_guard); |
| |
| private: |
| dwarf2_per_objfile *m_per_objfile; |
| }; |
| |
| dwarf2_queue_item::~dwarf2_queue_item () |
| { |
| /* Anything still marked queued is likely to be in an |
| inconsistent state, so discard it. */ |
| if (per_cu->queued) |
| { |
| per_objfile->remove_cu (per_cu); |
| per_cu->queued = 0; |
| } |
| } |
| |
| /* See dwarf2/read.h. */ |
| |
| void |
| dwarf2_per_cu_data_deleter::operator() (dwarf2_per_cu_data *data) |
| { |
| if (data->is_debug_types) |
| delete static_cast<signatured_type *> (data); |
| else |
| delete data; |
| } |
| |
| /* The return type of find_file_and_directory. Note, the enclosed |
| string pointers are only valid while this object is valid. */ |
| |
| struct file_and_directory |
| { |
| /* The filename. This is never NULL. */ |
| const char *name; |
| |
| /* The compilation directory. NULL if not known. If we needed to |
| compute a new string, it will be stored in the per-BFD string |
| bcache; otherwise, points directly to the DW_AT_comp_dir string |
| attribute owned by the obstack that owns the DIE. */ |
| const char *comp_dir; |
| }; |
| |
| static file_and_directory find_file_and_directory (struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static const char *compute_include_file_name |
| (const struct line_header *lh, |
| const file_entry &fe, |
| const file_and_directory &cu_info, |
| gdb::unique_xmalloc_ptr<char> *name_holder); |
| |
| static htab_up allocate_signatured_type_table (); |
| |
| static htab_up allocate_dwo_unit_table (); |
| |
| static struct dwo_unit *lookup_dwo_unit_in_dwp |
| (dwarf2_per_objfile *per_objfile, struct dwp_file *dwp_file, |
| const char *comp_dir, ULONGEST signature, int is_debug_types); |
| |
| static struct dwp_file *get_dwp_file (dwarf2_per_objfile *per_objfile); |
| |
| static struct dwo_unit *lookup_dwo_comp_unit |
| (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir, |
| ULONGEST signature); |
| |
| static struct dwo_unit *lookup_dwo_type_unit |
| (dwarf2_cu *cu, const char *dwo_name, const char *comp_dir); |
| |
| static void queue_and_load_all_dwo_tus (dwarf2_cu *cu); |
| |
| /* A unique pointer to a dwo_file. */ |
| |
| typedef std::unique_ptr<struct dwo_file> dwo_file_up; |
| |
| static void process_cu_includes (dwarf2_per_objfile *per_objfile); |
| |
| static void check_producer (struct dwarf2_cu *cu); |
| |
| /* Various complaints about symbol reading that don't abort the process. */ |
| |
| static void |
| dwarf2_debug_line_missing_file_complaint (void) |
| { |
| complaint (_(".debug_line section has line data without a file")); |
| } |
| |
| static void |
| dwarf2_debug_line_missing_end_sequence_complaint (void) |
| { |
| complaint (_(".debug_line section has line " |
| "program sequence without an end")); |
| } |
| |
| static void |
| dwarf2_complex_location_expr_complaint (void) |
| { |
| complaint (_("location expression too complex")); |
| } |
| |
| static void |
| dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2, |
| int arg3) |
| { |
| complaint (_("const value length mismatch for '%s', got %d, expected %d"), |
| arg1, arg2, arg3); |
| } |
| |
| static void |
| dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2) |
| { |
| complaint (_("invalid attribute class or form for '%s' in '%s'"), |
| arg1, arg2); |
| } |
| |
| /* Hash function for line_header_hash. */ |
| |
| static hashval_t |
| line_header_hash (const struct line_header *ofs) |
| { |
| return to_underlying (ofs->sect_off) ^ ofs->offset_in_dwz; |
| } |
| |
| /* Hash function for htab_create_alloc_ex for line_header_hash. */ |
| |
| static hashval_t |
| line_header_hash_voidp (const void *item) |
| { |
| const struct line_header *ofs = (const struct line_header *) item; |
| |
| return line_header_hash (ofs); |
| } |
| |
| /* Equality function for line_header_hash. */ |
| |
| static int |
| line_header_eq_voidp (const void *item_lhs, const void *item_rhs) |
| { |
| const struct line_header *ofs_lhs = (const struct line_header *) item_lhs; |
| const struct line_header *ofs_rhs = (const struct line_header *) item_rhs; |
| |
| return (ofs_lhs->sect_off == ofs_rhs->sect_off |
| && ofs_lhs->offset_in_dwz == ofs_rhs->offset_in_dwz); |
| } |
| |
| |
| |
| /* An iterator for all_comp_units that is based on index. This |
| approach makes it possible to iterate over all_comp_units safely, |
| when some caller in the loop may add new units. */ |
| |
| class all_comp_units_iterator |
| { |
| public: |
| |
| all_comp_units_iterator (dwarf2_per_bfd *per_bfd, bool start) |
| : m_per_bfd (per_bfd), |
| m_index (start ? 0 : per_bfd->all_comp_units.size ()) |
| { |
| } |
| |
| all_comp_units_iterator &operator++ () |
| { |
| ++m_index; |
| return *this; |
| } |
| |
| dwarf2_per_cu_data *operator* () const |
| { |
| return m_per_bfd->get_cu (m_index); |
| } |
| |
| bool operator== (const all_comp_units_iterator &other) const |
| { |
| return m_index == other.m_index; |
| } |
| |
| |
| bool operator!= (const all_comp_units_iterator &other) const |
| { |
| return m_index != other.m_index; |
| } |
| |
| private: |
| |
| dwarf2_per_bfd *m_per_bfd; |
| size_t m_index; |
| }; |
| |
| /* A range adapter for the all_comp_units_iterator. */ |
| class all_comp_units_range |
| { |
| public: |
| |
| all_comp_units_range (dwarf2_per_bfd *per_bfd) |
| : m_per_bfd (per_bfd) |
| { |
| } |
| |
| all_comp_units_iterator begin () |
| { |
| return all_comp_units_iterator (m_per_bfd, true); |
| } |
| |
| all_comp_units_iterator end () |
| { |
| return all_comp_units_iterator (m_per_bfd, false); |
| } |
| |
| private: |
| |
| dwarf2_per_bfd *m_per_bfd; |
| }; |
| |
| /* See declaration. */ |
| |
| dwarf2_per_bfd::dwarf2_per_bfd (bfd *obfd, const dwarf2_debug_sections *names, |
| bool can_copy_) |
| : obfd (obfd), |
| can_copy (can_copy_) |
| { |
| if (names == NULL) |
| names = &dwarf2_elf_names; |
| |
| for (asection *sec = obfd->sections; sec != NULL; sec = sec->next) |
| locate_sections (obfd, sec, *names); |
| } |
| |
| dwarf2_per_bfd::~dwarf2_per_bfd () |
| { |
| for (auto &per_cu : all_comp_units) |
| { |
| per_cu->imported_symtabs_free (); |
| per_cu->free_cached_file_names (); |
| } |
| |
| /* Everything else should be on this->obstack. */ |
| } |
| |
| /* See read.h. */ |
| |
| void |
| dwarf2_per_objfile::remove_all_cus () |
| { |
| gdb_assert (!this->per_bfd->queue.has_value ()); |
| |
| for (auto pair : m_dwarf2_cus) |
| delete pair.second; |
| |
| m_dwarf2_cus.clear (); |
| } |
| |
| /* A helper class that calls free_cached_comp_units on |
| destruction. */ |
| |
| class free_cached_comp_units |
| { |
| public: |
| |
| explicit free_cached_comp_units (dwarf2_per_objfile *per_objfile) |
| : m_per_objfile (per_objfile) |
| { |
| } |
| |
| ~free_cached_comp_units () |
| { |
| m_per_objfile->remove_all_cus (); |
| } |
| |
| DISABLE_COPY_AND_ASSIGN (free_cached_comp_units); |
| |
| private: |
| |
| dwarf2_per_objfile *m_per_objfile; |
| }; |
| |
| /* See read.h. */ |
| |
| bool |
| dwarf2_per_objfile::symtab_set_p (const dwarf2_per_cu_data *per_cu) const |
| { |
| if (per_cu->index < this->m_symtabs.size ()) |
| return this->m_symtabs[per_cu->index] != nullptr; |
| return false; |
| } |
| |
| /* See read.h. */ |
| |
| compunit_symtab * |
| dwarf2_per_objfile::get_symtab (const dwarf2_per_cu_data *per_cu) const |
| { |
| if (per_cu->index < this->m_symtabs.size ()) |
| return this->m_symtabs[per_cu->index]; |
| return nullptr; |
| } |
| |
| /* See read.h. */ |
| |
| void |
| dwarf2_per_objfile::set_symtab (const dwarf2_per_cu_data *per_cu, |
| compunit_symtab *symtab) |
| { |
| if (per_cu->index >= this->m_symtabs.size ()) |
| this->m_symtabs.resize (per_cu->index + 1); |
| gdb_assert (this->m_symtabs[per_cu->index] == nullptr); |
| this->m_symtabs[per_cu->index] = symtab; |
| } |
| |
| /* Try to locate the sections we need for DWARF 2 debugging |
| information and return true if we have enough to do something. |
| NAMES points to the dwarf2 section names, or is NULL if the standard |
| ELF names are used. CAN_COPY is true for formats where symbol |
| interposition is possible and so symbol values must follow copy |
| relocation rules. */ |
| |
| int |
| dwarf2_has_info (struct objfile *objfile, |
| const struct dwarf2_debug_sections *names, |
| bool can_copy) |
| { |
| if (objfile->flags & OBJF_READNEVER) |
| return 0; |
| |
| dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); |
| |
| if (per_objfile == NULL) |
| { |
| dwarf2_per_bfd *per_bfd; |
| |
| /* We can share a "dwarf2_per_bfd" with other objfiles if the |
| BFD doesn't require relocations. |
| |
| We don't share with objfiles for which -readnow was requested, |
| because it would complicate things when loading the same BFD with |
| -readnow and then without -readnow. */ |
| if (!gdb_bfd_requires_relocations (objfile->obfd) |
| && (objfile->flags & OBJF_READNOW) == 0) |
| { |
| /* See if one has been created for this BFD yet. */ |
| per_bfd = dwarf2_per_bfd_bfd_data_key.get (objfile->obfd); |
| |
| if (per_bfd == nullptr) |
| { |
| /* No, create it now. */ |
| per_bfd = new dwarf2_per_bfd (objfile->obfd, names, can_copy); |
| dwarf2_per_bfd_bfd_data_key.set (objfile->obfd, per_bfd); |
| } |
| } |
| else |
| { |
| /* No sharing possible, create one specifically for this objfile. */ |
| per_bfd = new dwarf2_per_bfd (objfile->obfd, names, can_copy); |
| dwarf2_per_bfd_objfile_data_key.set (objfile, per_bfd); |
| } |
| |
| per_objfile = dwarf2_objfile_data_key.emplace (objfile, objfile, per_bfd); |
| } |
| |
| return (!per_objfile->per_bfd->info.is_virtual |
| && per_objfile->per_bfd->info.s.section != NULL |
| && !per_objfile->per_bfd->abbrev.is_virtual |
| && per_objfile->per_bfd->abbrev.s.section != NULL); |
| } |
| |
| /* See declaration. */ |
| |
| void |
| dwarf2_per_bfd::locate_sections (bfd *abfd, asection *sectp, |
| const dwarf2_debug_sections &names) |
| { |
| flagword aflag = bfd_section_flags (sectp); |
| |
| if ((aflag & SEC_HAS_CONTENTS) == 0) |
| { |
| } |
| else if (elf_section_data (sectp)->this_hdr.sh_size |
| > bfd_get_file_size (abfd)) |
| { |
| bfd_size_type size = elf_section_data (sectp)->this_hdr.sh_size; |
| warning (_("Discarding section %s which has a section size (%s" |
| ") larger than the file size [in module %s]"), |
| bfd_section_name (sectp), phex_nz (size, sizeof (size)), |
| bfd_get_filename (abfd)); |
| } |
| else if (names.info.matches (sectp->name)) |
| { |
| this->info.s.section = sectp; |
| this->info.size = bfd_section_size (sectp); |
| } |
| else if (names.abbrev.matches (sectp->name)) |
| { |
| this->abbrev.s.section = sectp; |
| this->abbrev.size = bfd_section_size (sectp); |
| } |
| else if (names.line.matches (sectp->name)) |
| { |
| this->line.s.section = sectp; |
| this->line.size = bfd_section_size (sectp); |
| } |
| else if (names.loc.matches (sectp->name)) |
| { |
| this->loc.s.section = sectp; |
| this->loc.size = bfd_section_size (sectp); |
| } |
| else if (names.loclists.matches (sectp->name)) |
| { |
| this->loclists.s.section = sectp; |
| this->loclists.size = bfd_section_size (sectp); |
| } |
| else if (names.macinfo.matches (sectp->name)) |
| { |
| this->macinfo.s.section = sectp; |
| this->macinfo.size = bfd_section_size (sectp); |
| } |
| else if (names.macro.matches (sectp->name)) |
| { |
| this->macro.s.section = sectp; |
| this->macro.size = bfd_section_size (sectp); |
| } |
| else if (names.str.matches (sectp->name)) |
| { |
| this->str.s.section = sectp; |
| this->str.size = bfd_section_size (sectp); |
| } |
| else if (names.str_offsets.matches (sectp->name)) |
| { |
| this->str_offsets.s.section = sectp; |
| this->str_offsets.size = bfd_section_size (sectp); |
| } |
| else if (names.line_str.matches (sectp->name)) |
| { |
| this->line_str.s.section = sectp; |
| this->line_str.size = bfd_section_size (sectp); |
| } |
| else if (names.addr.matches (sectp->name)) |
| { |
| this->addr.s.section = sectp; |
| this->addr.size = bfd_section_size (sectp); |
| } |
| else if (names.frame.matches (sectp->name)) |
| { |
| this->frame.s.section = sectp; |
| this->frame.size = bfd_section_size (sectp); |
| } |
| else if (names.eh_frame.matches (sectp->name)) |
| { |
| this->eh_frame.s.section = sectp; |
| this->eh_frame.size = bfd_section_size (sectp); |
| } |
| else if (names.ranges.matches (sectp->name)) |
| { |
| this->ranges.s.section = sectp; |
| this->ranges.size = bfd_section_size (sectp); |
| } |
| else if (names.rnglists.matches (sectp->name)) |
| { |
| this->rnglists.s.section = sectp; |
| this->rnglists.size = bfd_section_size (sectp); |
| } |
| else if (names.types.matches (sectp->name)) |
| { |
| struct dwarf2_section_info type_section; |
| |
| memset (&type_section, 0, sizeof (type_section)); |
| type_section.s.section = sectp; |
| type_section.size = bfd_section_size (sectp); |
| |
| this->types.push_back (type_section); |
| } |
| else if (names.gdb_index.matches (sectp->name)) |
| { |
| this->gdb_index.s.section = sectp; |
| this->gdb_index.size = bfd_section_size (sectp); |
| } |
| else if (names.debug_names.matches (sectp->name)) |
| { |
| this->debug_names.s.section = sectp; |
| this->debug_names.size = bfd_section_size (sectp); |
| } |
| else if (names.debug_aranges.matches (sectp->name)) |
| { |
| this->debug_aranges.s.section = sectp; |
| this->debug_aranges.size = bfd_section_size (sectp); |
| } |
| |
| if ((bfd_section_flags (sectp) & (SEC_LOAD | SEC_ALLOC)) |
| && bfd_section_vma (sectp) == 0) |
| this->has_section_at_zero = true; |
| } |
| |
| /* Fill in SECTP, BUFP and SIZEP with section info, given OBJFILE and |
| SECTION_NAME. */ |
| |
| void |
| dwarf2_get_section_info (struct objfile *objfile, |
| enum dwarf2_section_enum sect, |
| asection **sectp, const gdb_byte **bufp, |
| bfd_size_type *sizep) |
| { |
| dwarf2_per_objfile *per_objfile = get_dwarf2_per_objfile (objfile); |
| struct dwarf2_section_info *info; |
| |
| /* We may see an objfile without any DWARF, in which case we just |
| return nothing. */ |
| if (per_objfile == NULL) |
| { |
| *sectp = NULL; |
| *bufp = NULL; |
| *sizep = 0; |
| return; |
| } |
| switch (sect) |
| { |
| case DWARF2_DEBUG_FRAME: |
| info = &per_objfile->per_bfd->frame; |
| break; |
| case DWARF2_EH_FRAME: |
| info = &per_objfile->per_bfd->eh_frame; |
| break; |
| default: |
| gdb_assert_not_reached ("unexpected section"); |
| } |
| |
| info->read (objfile); |
| |
| *sectp = info->get_bfd_section (); |
| *bufp = info->buffer; |
| *sizep = info->size; |
| } |
| |
| |
| /* DWARF quick_symbol_functions support. */ |
| |
| /* TUs can share .debug_line entries, and there can be a lot more TUs than |
| unique line tables, so we maintain a separate table of all .debug_line |
| derived entries to support the sharing. |
| All the quick functions need is the list of file names. We discard the |
| line_header when we're done and don't need to record it here. */ |
| struct quick_file_names |
| { |
| /* The data used to construct the hash key. */ |
| struct stmt_list_hash hash; |
| |
| /* The number of entries in file_names, real_names. */ |
| unsigned int num_file_names; |
| |
| /* The CU directory, as given by DW_AT_comp_dir. May be |
| nullptr. */ |
| const char *comp_dir; |
| |
| /* The file names from the line table, after being run through |
| file_full_name. */ |
| const char **file_names; |
| |
| /* The file names from the line table after being run through |
| gdb_realpath. These are computed lazily. */ |
| const char **real_names; |
| }; |
| |
| /* When using the index (and thus not using psymtabs), each CU has an |
| object of this type. This is used to hold information needed by |
| the various "quick" methods. */ |
| struct dwarf2_per_cu_quick_data |
| { |
| /* The file table. This can be NULL if there was no file table |
| or it's currently not read in. |
| NOTE: This points into dwarf2_per_objfile->per_bfd->quick_file_names_table. */ |
| struct quick_file_names *file_names; |
| |
| /* A temporary mark bit used when iterating over all CUs in |
| expand_symtabs_matching. */ |
| unsigned int mark : 1; |
| |
| /* True if we've tried to read the file table. There will be no |
| point in trying to read it again next time. */ |
| bool files_read : 1; |
| }; |
| |
| /* A subclass of psymbol_functions that arranges to read the DWARF |
| partial symbols when needed. */ |
| struct lazy_dwarf_reader : public psymbol_functions |
| { |
| using psymbol_functions::psymbol_functions; |
| |
| bool can_lazily_read_symbols () override |
| { |
| return true; |
| } |
| |
| void read_partial_symbols (struct objfile *objfile) override |
| { |
| if (dwarf2_has_info (objfile, nullptr)) |
| dwarf2_build_psymtabs (objfile, this); |
| } |
| }; |
| |
| static quick_symbol_functions_up |
| make_lazy_dwarf_reader () |
| { |
| return quick_symbol_functions_up (new lazy_dwarf_reader); |
| } |
| |
| struct dwarf2_base_index_functions : public quick_symbol_functions |
| { |
| bool has_symbols (struct objfile *objfile) override; |
| |
| bool has_unexpanded_symtabs (struct objfile *objfile) override; |
| |
| struct symtab *find_last_source_symtab (struct objfile *objfile) override; |
| |
| void forget_cached_source_info (struct objfile *objfile) override; |
| |
| enum language lookup_global_symbol_language (struct objfile *objfile, |
| const char *name, |
| domain_enum domain, |
| bool *symbol_found_p) override |
| { |
| *symbol_found_p = false; |
| return language_unknown; |
| } |
| |
| void print_stats (struct objfile *objfile, bool print_bcache) override; |
| |
| void expand_all_symtabs (struct objfile *objfile) override; |
| |
| struct compunit_symtab *find_pc_sect_compunit_symtab |
| (struct objfile *objfile, struct bound_minimal_symbol msymbol, |
| CORE_ADDR pc, struct obj_section *section, int warn_if_readin) override; |
| |
| struct compunit_symtab *find_compunit_symtab_by_address |
| (struct objfile *objfile, CORE_ADDR address) override |
| { |
| return nullptr; |
| } |
| |
| void map_symbol_filenames (struct objfile *objfile, |
| gdb::function_view<symbol_filename_ftype> fun, |
| bool need_fullname) override; |
| }; |
| |
| struct dwarf2_gdb_index : public dwarf2_base_index_functions |
| { |
| void dump (struct objfile *objfile) override; |
| |
| void expand_matching_symbols |
| (struct objfile *, |
| const lookup_name_info &lookup_name, |
| domain_enum domain, |
| int global, |
| symbol_compare_ftype *ordered_compare) override; |
| |
| bool expand_symtabs_matching |
| (struct objfile *objfile, |
| gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, |
| const lookup_name_info *lookup_name, |
| gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher, |
| gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, |
| block_search_flags search_flags, |
| domain_enum domain, |
| enum search_domain kind) override; |
| }; |
| |
| struct dwarf2_debug_names_index : public dwarf2_base_index_functions |
| { |
| void dump (struct objfile *objfile) override; |
| |
| void expand_matching_symbols |
| (struct objfile *, |
| const lookup_name_info &lookup_name, |
| domain_enum domain, |
| int global, |
| symbol_compare_ftype *ordered_compare) override; |
| |
| bool expand_symtabs_matching |
| (struct objfile *objfile, |
| gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher, |
| const lookup_name_info *lookup_name, |
| gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher, |
| gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify, |
| block_search_flags search_flags, |
| domain_enum domain, |
| enum search_domain kind) override; |
| }; |
| |
| static quick_symbol_functions_up |
| make_dwarf_gdb_index () |
| { |
| return quick_symbol_functions_up (new dwarf2_gdb_index); |
| } |
| |
| static quick_symbol_functions_up |
| make_dwarf_debug_names () |
| { |
| return quick_symbol_functions_up (new dwarf2_debug_names_index); |
| } |
| |
| /* Utility hash function for a stmt_list_hash. */ |
| |
| static hashval_t |
| hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash) |
| { |
| hashval_t v = 0; |
| |
| if (stmt_list_hash->dwo_unit != NULL) |
| v += (uintptr_t) stmt_list_hash->dwo_unit->dwo_file; |
| v += to_underlying (stmt_list_hash->line_sect_off); |
| return v; |
| } |
| |
| /* Utility equality function for a stmt_list_hash. */ |
| |
| static int |
| eq_stmt_list_entry (const struct stmt_list_hash *lhs, |
| const struct stmt_list_hash *rhs) |
| { |
| if ((lhs->dwo_unit != NULL) != (rhs->dwo_unit != NULL)) |
| return 0; |
| if (lhs->dwo_unit != NULL |
| && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file) |
| return 0; |
| |
| return lhs->line_sect_off == rhs->line_sect_off; |
| } |
| |
| /* Hash function for a quick_file_names. */ |
| |
| static hashval_t |
| hash_file_name_entry (const void *e) |
| { |
| const struct quick_file_names *file_data |
| = (const struct quick_file_names *) e; |
| |
| return hash_stmt_list_entry (&file_data->hash); |
| } |
| |
| /* Equality function for a quick_file_names. */ |
| |
| static int |
| eq_file_name_entry (const void *a, const void *b) |
| { |
| const struct quick_file_names *ea = (const struct quick_file_names *) a; |
| const struct quick_file_names *eb = (const struct quick_file_names *) b; |
| |
| return eq_stmt_list_entry (&ea->hash, &eb->hash); |
| } |
| |
| /* Create a quick_file_names hash table. */ |
| |
| static htab_up |
| create_quick_file_names_table (unsigned int nr_initial_entries) |
| { |
| return htab_up (htab_create_alloc (nr_initial_entries, |
| hash_file_name_entry, eq_file_name_entry, |
| nullptr, xcalloc, xfree)); |
| } |
| |
| /* Read in CU (dwarf2_cu object) for PER_CU in the context of PER_OBJFILE. This |
| function is unrelated to symtabs, symtab would have to be created afterwards. |
| You should call age_cached_comp_units after processing the CU. */ |
| |
| static dwarf2_cu * |
| load_cu (dwarf2_per_cu_data *per_cu, dwarf2_per_objfile *per_objfile, |
| bool skip_partial) |
| { |
| if (per_cu->is_debug_types) |
| load_full_type_unit (per_cu, per_objfile); |
| else |
| load_full_comp_unit (per_cu, per_objfile, per_objfile->get_cu (per_cu), |
| skip_partial, language_minimal); |
| |
| dwarf2_cu *cu = per_objfile->get_cu (per_cu); |
| if (cu == nullptr) |
| return nullptr; /* Dummy CU. */ |
| |
| dwarf2_find_base_address (cu->dies, cu); |
| |
| return cu; |
| } |
| |
| /* Read in the symbols for PER_CU in the context of PER_OBJFILE. */ |
| |
| static void |
| dw2_do_instantiate_symtab (dwarf2_per_cu_data *per_cu, |
| dwarf2_per_objfile *per_objfile, bool skip_partial) |
| { |
| /* Skip type_unit_groups, reading the type units they contain |
| is handled elsewhere. */ |
| if (per_cu->type_unit_group_p ()) |
| return; |
| |
| { |
| /* The destructor of dwarf2_queue_guard frees any entries left on |
| the queue. After this point we're guaranteed to leave this function |
| with the dwarf queue empty. */ |
| dwarf2_queue_guard q_guard (per_objfile); |
| |
| if (!per_objfile->symtab_set_p (per_cu)) |
| { |
| queue_comp_unit (per_cu, per_objfile, language_minimal); |
| dwarf2_cu *cu = load_cu (per_cu, per_objfile, skip_partial); |
| |
| /* If we just loaded a CU from a DWO, and we're working with an index |
| that may badly handle TUs, load all the TUs in that DWO as well. |
| http://sourceware.org/bugzilla/show_bug.cgi?id=15021 */ |
| if (!per_cu->is_debug_types |
| && cu != NULL |
| && cu->dwo_unit != NULL |
| && per_objfile->per_bfd->index_table != NULL |
| && per_objfile->per_bfd->index_table->version <= 7 |
| /* DWP files aren't supported yet. */ |
| && get_dwp_file (per_objfile) == NULL) |
| queue_and_load_all_dwo_tus (cu); |
| } |
| |
| process_queue (per_objfile); |
| } |
| |
| /* Age the cache, releasing compilation units that have not |
| been used recently. */ |
| per_objfile->age_comp_units (); |
| } |
| |
| /* Ensure that the symbols for PER_CU have been read in. DWARF2_PER_OBJFILE is |
| the per-objfile for which this symtab is instantiated. |
| |
| Returns the resulting symbol table. */ |
| |
| static struct compunit_symtab * |
| dw2_instantiate_symtab (dwarf2_per_cu_data *per_cu, |
| dwarf2_per_objfile *per_objfile, |
| bool skip_partial) |
| { |
| gdb_assert (per_objfile->per_bfd->using_index); |
| |
| if (!per_objfile->symtab_set_p (per_cu)) |
| { |
| free_cached_comp_units freer (per_objfile); |
| scoped_restore decrementer = increment_reading_symtab (); |
| dw2_do_instantiate_symtab (per_cu, per_objfile, skip_partial); |
| process_cu_includes (per_objfile); |
| } |
| |
| return per_objfile->get_symtab (per_cu); |
| } |
| |
| /* See read.h. */ |
| |
| dwarf2_per_cu_data_up |
| dwarf2_per_bfd::allocate_per_cu () |
| { |
| dwarf2_per_cu_data_up result (new dwarf2_per_cu_data); |
| result->per_bfd = this; |
| result->index = all_comp_units.size (); |
| return result; |
| } |
| |
| /* See read.h. */ |
| |
| signatured_type_up |
| dwarf2_per_bfd::allocate_signatured_type (ULONGEST signature) |
| { |
| signatured_type_up result (new signatured_type (signature)); |
| result->per_bfd = this; |
| result->index = all_comp_units.size (); |
| result->is_debug_types = true; |
| tu_stats.nr_tus++; |
| return result; |
| } |
| |
| /* Return a new dwarf2_per_cu_data allocated on the per-bfd |
| obstack, and constructed with the specified field values. */ |
| |
| static dwarf2_per_cu_data_up |
| create_cu_from_index_list (dwarf2_per_bfd *per_bfd, |
| struct dwarf2_section_info *section, |
| int is_dwz, |
| sect_offset sect_off, ULONGEST length) |
| { |
| dwarf2_per_cu_data_up the_cu = per_bfd->allocate_per_cu (); |
| the_cu->sect_off = sect_off; |
| the_cu->length = length; |
| the_cu->section = section; |
| the_cu->v.quick = OBSTACK_ZALLOC (&per_bfd->obstack, |
| struct dwarf2_per_cu_quick_data); |
| the_cu->is_dwz = is_dwz; |
| return the_cu; |
| } |
| |
| /* A helper for create_cus_from_index that handles a given list of |
| CUs. */ |
| |
| static void |
| create_cus_from_index_list (dwarf2_per_bfd *per_bfd, |
| const gdb_byte *cu_list, offset_type n_elements, |
| struct dwarf2_section_info *section, |
| int is_dwz) |
| { |
| for (offset_type i = 0; i < n_elements; i += 2) |
| { |
| gdb_static_assert (sizeof (ULONGEST) >= 8); |
| |
| sect_offset sect_off |
| = (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE); |
| ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); |
| cu_list += 2 * 8; |
| |
| dwarf2_per_cu_data_up per_cu |
| = create_cu_from_index_list (per_bfd, section, is_dwz, sect_off, |
| length); |
| per_bfd->all_comp_units.push_back (std::move (per_cu)); |
| } |
| } |
| |
| /* Read the CU list from the mapped index, and use it to create all |
| the CU objects for PER_BFD. */ |
| |
| static void |
| create_cus_from_index (dwarf2_per_bfd *per_bfd, |
| const gdb_byte *cu_list, offset_type cu_list_elements, |
| const gdb_byte *dwz_list, offset_type dwz_elements) |
| { |
| gdb_assert (per_bfd->all_comp_units.empty ()); |
| per_bfd->all_comp_units.reserve ((cu_list_elements + dwz_elements) / 2); |
| |
| create_cus_from_index_list (per_bfd, cu_list, cu_list_elements, |
| &per_bfd->info, 0); |
| |
| if (dwz_elements == 0) |
| return; |
| |
| dwz_file *dwz = dwarf2_get_dwz_file (per_bfd); |
| create_cus_from_index_list (per_bfd, dwz_list, dwz_elements, |
| &dwz->info, 1); |
| } |
| |
| /* Create the signatured type hash table from the index. */ |
| |
| static void |
| create_signatured_type_table_from_index |
| (dwarf2_per_bfd *per_bfd, struct dwarf2_section_info *section, |
| const gdb_byte *bytes, offset_type elements) |
| { |
| htab_up sig_types_hash = allocate_signatured_type_table (); |
| |
| for (offset_type i = 0; i < elements; i += 3) |
| { |
| signatured_type_up sig_type; |
| ULONGEST signature; |
| void **slot; |
| cu_offset type_offset_in_tu; |
| |
| gdb_static_assert (sizeof (ULONGEST) >= 8); |
| sect_offset sect_off |
| = (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); |
| type_offset_in_tu |
| = (cu_offset) extract_unsigned_integer (bytes + 8, 8, |
| BFD_ENDIAN_LITTLE); |
| signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE); |
| bytes += 3 * 8; |
| |
| sig_type = per_bfd->allocate_signatured_type (signature); |
| sig_type->type_offset_in_tu = type_offset_in_tu; |
| sig_type->section = section; |
| sig_type->sect_off = sect_off; |
| sig_type->v.quick |
| = OBSTACK_ZALLOC (&per_bfd->obstack, |
| struct dwarf2_per_cu_quick_data); |
| |
| slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT); |
| *slot = sig_type.get (); |
| |
| per_bfd->all_comp_units.emplace_back (sig_type.release ()); |
| } |
| |
| per_bfd->signatured_types = std::move (sig_types_hash); |
| } |
| |
| /* Create the signatured type hash table from .debug_names. */ |
| |
| static void |
| create_signatured_type_table_from_debug_names |
| (dwarf2_per_objfile *per_objfile, |
| const mapped_debug_names &map, |
| struct dwarf2_section_info *section, |
| struct dwarf2_section_info *abbrev_section) |
| { |
| struct objfile *objfile = per_objfile->objfile; |
| |
| section->read (objfile); |
| abbrev_section->read (objfile); |
| |
| htab_up sig_types_hash = allocate_signatured_type_table (); |
| |
| for (uint32_t i = 0; i < map.tu_count; ++i) |
| { |
| signatured_type_up sig_type; |
| void **slot; |
| |
| sect_offset sect_off |
| = (sect_offset) (extract_unsigned_integer |
| (map.tu_table_reordered + i * map.offset_size, |
| map.offset_size, |
| map.dwarf5_byte_order)); |
| |
| comp_unit_head cu_header; |
| read_and_check_comp_unit_head (per_objfile, &cu_header, section, |
| abbrev_section, |
| section->buffer + to_underlying (sect_off), |
| rcuh_kind::TYPE); |
| |
| sig_type = per_objfile->per_bfd->allocate_signatured_type |
| (cu_header.signature); |
| sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu; |
| sig_type->section = section; |
| sig_type->sect_off = sect_off; |
| sig_type->v.quick |
| = OBSTACK_ZALLOC (&per_objfile->per_bfd->obstack, |
| struct dwarf2_per_cu_quick_data); |
| |
| slot = htab_find_slot (sig_types_hash.get (), sig_type.get (), INSERT); |
| *slot = sig_type.get (); |
| |
| per_objfile->per_bfd->all_comp_units.emplace_back (sig_type.release ()); |
| } |
| |
| per_objfile->per_bfd->signatured_types = std::move (sig_types_hash); |
| } |
| |
| /* Read the address map data from the mapped index, and use it to |
| populate the psymtabs_addrmap. */ |
| |
| static void |
| create_addrmap_from_index (dwarf2_per_objfile *per_objfile, |
| struct mapped_index *index) |
| { |
| struct objfile *objfile = per_objfile->objfile; |
| dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; |
| struct gdbarch *gdbarch = objfile->arch (); |
| const gdb_byte *iter, *end; |
| struct addrmap *mutable_map; |
| CORE_ADDR baseaddr; |
| |
| auto_obstack temp_obstack; |
| |
| mutable_map = addrmap_create_mutable (&temp_obstack); |
| |
| iter = index->address_table.data (); |
| end = iter + index->address_table.size (); |
| |
| baseaddr = objfile->text_section_offset (); |
| |
| while (iter < end) |
| { |
| ULONGEST hi, lo, cu_index; |
| lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); |
| iter += 8; |
| hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); |
| iter += 8; |
| cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); |
| iter += 4; |
| |
| if (lo > hi) |
| { |
| complaint (_(".gdb_index address table has invalid range (%s - %s)"), |
| hex_string (lo), hex_string (hi)); |
| continue; |
| } |
| |
| if (cu_index >= per_bfd->all_comp_units.size ()) |
| { |
| complaint (_(".gdb_index address table has invalid CU number %u"), |
| (unsigned) cu_index); |
| continue; |
| } |
| |
| lo = gdbarch_adjust_dwarf2_addr (gdbarch, lo + baseaddr) - baseaddr; |
| hi = gdbarch_adjust_dwarf2_addr (gdbarch, hi + baseaddr) - baseaddr; |
| addrmap_set_empty (mutable_map, lo, hi - 1, |
| per_bfd->get_cu (cu_index)); |
| } |
| |
| per_bfd->index_addrmap = addrmap_create_fixed (mutable_map, |
| &per_bfd->obstack); |
| } |
| |
| /* Read the address map data from DWARF-5 .debug_aranges, and use it to |
| populate the psymtabs_addrmap. */ |
| |
| static void |
| create_addrmap_from_aranges (dwarf2_per_objfile *per_objfile, |
| struct dwarf2_section_info *section) |
| { |
| struct objfile *objfile = per_objfile->objfile; |
| bfd *abfd = objfile->obfd; |
| struct gdbarch *gdbarch = objfile->arch (); |
| const CORE_ADDR baseaddr = objfile->text_section_offset (); |
| dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; |
| |
| auto_obstack temp_obstack; |
| addrmap *mutable_map = addrmap_create_mutable (&temp_obstack); |
| |
| std::unordered_map<sect_offset, |
| dwarf2_per_cu_data *, |
| gdb::hash_enum<sect_offset>> |
| debug_info_offset_to_per_cu; |
| for (const auto &per_cu : per_bfd->all_comp_units) |
| { |
| /* A TU will not need aranges, and skipping them here is an easy |
| way of ignoring .debug_types -- and possibly seeing a |
| duplicate section offset -- entirely. */ |
| if (per_cu->is_debug_types) |
| continue; |
| |
| const auto insertpair |
| = debug_info_offset_to_per_cu.emplace (per_cu->sect_off, |
| per_cu.get ()); |
| if (!insertpair.second) |
| { |
| warning (_("Section .debug_aranges in %s has duplicate " |
| "debug_info_offset %s, ignoring .debug_aranges."), |
| objfile_name (objfile), sect_offset_str (per_cu->sect_off)); |
| return; |
| } |
| } |
| |
| section->read (objfile); |
| |
| const bfd_endian dwarf5_byte_order = gdbarch_byte_order (gdbarch); |
| |
| const gdb_byte *addr = section->buffer; |
| |
| while (addr < section->buffer + section->size) |
| { |
| const gdb_byte *const entry_addr = addr; |
| unsigned int bytes_read; |
| |
| const LONGEST entry_length = read_initial_length (abfd, addr, |
| &bytes_read); |
| addr += bytes_read; |
| |
| const gdb_byte *const entry_end = addr + entry_length; |
| const bool dwarf5_is_dwarf64 = bytes_read != 4; |
| const uint8_t offset_size = dwarf5_is_dwarf64 ? 8 : 4; |
| if (addr + entry_length > section->buffer + section->size) |
| { |
| warning (_("Section .debug_aranges in %s entry at offset %s " |
| "length %s exceeds section length %s, " |
| "ignoring .debug_aranges."), |
| objfile_name (objfile), |
| plongest (entry_addr - section->buffer), |
| plongest (bytes_read + entry_length), |
| pulongest (section->size)); |
| return; |
| } |
| |
| /* The version number. */ |
| const uint16_t version = read_2_bytes (abfd, addr); |
| addr += 2; |
| if (version != 2) |
| { |
| warning (_("Section .debug_aranges in %s entry at offset %s " |
| "has unsupported version %d, ignoring .debug_aranges."), |
| objfile_name (objfile), |
| plongest (entry_addr - section->buffer), version); |
| return; |
| } |
| |
| const uint64_t debug_info_offset |
| = extract_unsigned_integer (addr, offset_size, dwarf5_byte_order); |
| addr += offset_size; |
| const auto per_cu_it |
| = debug_info_offset_to_per_cu.find (sect_offset (debug_info_offset)); |
| if (per_cu_it == debug_info_offset_to_per_cu.cend ()) |
| { |
| warning (_("Section .debug_aranges in %s entry at offset %s " |
| "debug_info_offset %s does not exists, " |
| "ignoring .debug_aranges."), |
| objfile_name (objfile), |
| plongest (entry_addr - section->buffer), |
| pulongest (debug_info_offset)); |
| return; |
| } |
| dwarf2_per_cu_data *const per_cu = per_cu_it->second; |
| |
| const uint8_t address_size = *addr++; |
| if (address_size < 1 || address_size > 8) |
| { |
| warning (_("Section .debug_aranges in %s entry at offset %s " |
| "address_size %u is invalid, ignoring .debug_aranges."), |
| objfile_name (objfile), |
| plongest (entry_addr - section->buffer), address_size); |
| return; |
| } |
| |
| const uint8_t segment_selector_size = *addr++; |
| if (segment_selector_size != 0) |
| { |
| warning (_("Section .debug_aranges in %s entry at offset %s " |
| "segment_selector_size %u is not supported, " |
| "ignoring .debug_aranges."), |
| objfile_name (objfile), |
| plongest (entry_addr - section->buffer), |
| segment_selector_size); |
| return; |
| } |
| |
| /* Must pad to an alignment boundary that is twice the address |
| size. It is undocumented by the DWARF standard but GCC does |
| use it. However, not every compiler does this. We can see |
| whether it has happened by looking at the total length of the |
| contents of the aranges for this CU -- it if isn't a multiple |
| of twice the address size, then we skip any leftover |
| bytes. */ |
| addr += (entry_end - addr) % (2 * address_size); |
| |
| for (;;) |
| { |
| if (addr + 2 * address_size > entry_end) |
| { |
| warning (_("Section .debug_aranges in %s entry at offset %s " |
| "address list is not properly terminated, " |
| "ignoring .debug_aranges."), |
| objfile_name (objfile), |
| plongest (entry_addr - section->buffer)); |
| return; |
| } |
| ULONGEST start = extract_unsigned_integer (addr, address_size, |
| dwarf5_byte_order); |
| addr += address_size; |
| ULONGEST length = extract_unsigned_integer (addr, address_size, |
| dwarf5_byte_order); |
| addr += address_size; |
| if (start == 0 && length == 0) |
| break; |
| if (start == 0 && !per_bfd->has_section_at_zero) |
| { |
| /* Symbol was eliminated due to a COMDAT group. */ |
| continue; |
| } |
| ULONGEST end = start + length; |
| start = (gdbarch_adjust_dwarf2_addr (gdbarch, start + baseaddr) |
| - baseaddr); |
| end = (gdbarch_adjust_dwarf2_addr (gdbarch, end + baseaddr) |
| - baseaddr); |
| addrmap_set_empty (mutable_map, start, end - 1, per_cu); |
| } |
| } |
| |
| per_bfd->index_addrmap = addrmap_create_fixed (mutable_map, |
| &per_bfd->obstack); |
| } |
| |
| /* A helper function that reads the .gdb_index from BUFFER and fills |
| in MAP. FILENAME is the name of the file containing the data; |
| it is used for error reporting. DEPRECATED_OK is true if it is |
| ok to use deprecated sections. |
| |
| CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are |
| out parameters that are filled in with information about the CU and |
| TU lists in the section. |
| |
| Returns true if all went well, false otherwise. */ |
| |
| static bool |
| read_gdb_index_from_buffer (const char *filename, |
| bool deprecated_ok, |
| gdb::array_view<const gdb_byte> buffer, |
| struct mapped_index *map, |
| const gdb_byte **cu_list, |
| offset_type *cu_list_elements, |
| const gdb_byte **types_list, |
| offset_type *types_list_elements) |
| { |
| const gdb_byte *addr = &buffer[0]; |
| offset_view metadata (buffer); |
| |
| /* Version check. */ |
| offset_type version = metadata[0]; |
| /* Versions earlier than 3 emitted every copy of a psymbol. This |
| causes the index to behave very poorly for certain requests. Version 3 |
| contained incomplete addrmap. So, it seems better to just ignore such |
| indices. */ |
| if (version < 4) |
| { |
| static int warning_printed = 0; |
| if (!warning_printed) |
| { |
| warning (_("Skipping obsolete .gdb_index section in %s."), |
| filename); |
| warning_printed = 1; |
| } |
| return 0; |
| } |
| /* Index version 4 uses a different hash function than index version |
| 5 and later. |
| |
| Versions earlier than 6 did not emit psymbols for inlined |
| functions. Using these files will cause GDB not to be able to |
| set breakpoints on inlined functions by name, so we ignore these |
| indices unless the user has done |
| "set use-deprecated-index-sections on". */ |
| if (version < 6 && !deprecated_ok) |
| { |
| static int warning_printed = 0; |
| if (!warning_printed) |
| { |
| warning (_("\ |
| Skipping deprecated .gdb_index section in %s.\n\ |
| Do \"set use-deprecated-index-sections on\" before the file is read\n\ |
| to use the section anyway."), |
| filename); |
| warning_printed = 1; |
| } |
| return 0; |
| } |
| /* Version 7 indices generated by gold refer to the CU for a symbol instead |
| of the TU (for symbols coming from TUs), |
| http://sourceware.org/bugzilla/show_bug.cgi?id=15021. |
| Plus gold-generated indices can have duplicate entries for global symbols, |
| http://sourceware.org/bugzilla/show_bug.cgi?id=15646. |
| These are just performance bugs, and we can't distinguish gdb-generated |
| indices from gold-generated ones, so issue no warning here. */ |
| |
| /* Indexes with higher version than the one supported by GDB may be no |
| longer backward compatible. */ |
| if (version > 8) |
| return 0; |
| |
| map->version = version; |
| |
| int i = 1; |
| *cu_list = addr + metadata[i]; |
| *cu_list_elements = (metadata[i + 1] - metadata[i]) / 8; |
| ++i; |
| |
| *types_list = addr + metadata[i]; |
| *types_list_elements = (metadata[i + 1] - metadata[i]) / 8; |
| ++i; |
| |
| const gdb_byte *address_table = addr + metadata[i]; |
| const gdb_byte *address_table_end = addr + metadata[i + 1]; |
| map->address_table |
| = gdb::array_view<const gdb_byte> (address_table, address_table_end); |
| ++i; |
| |
| const gdb_byte *symbol_table = addr + metadata[i]; |
| const gdb_byte *symbol_table_end = addr + metadata[i + 1]; |
| map->symbol_table |
| = offset_view (gdb::array_view<const gdb_byte> (symbol_table, |
| symbol_table_end)); |
| |
| ++i; |
| map->constant_pool = buffer.slice (metadata[i]); |
| |
| if (map->constant_pool.empty () && !map->symbol_table.empty ()) |
| { |
| /* An empty constant pool implies that all symbol table entries are |
| empty. Make map->symbol_table.empty () == true. */ |
| map->symbol_table |
| = offset_view (gdb::array_view<const gdb_byte> (symbol_table, |
| symbol_table)); |
| } |
| |
| return 1; |
| } |
| |
| /* Callback types for dwarf2_read_gdb_index. */ |
| |
| typedef gdb::function_view |
| <gdb::array_view<const gdb_byte>(objfile *, dwarf2_per_bfd *)> |
| get_gdb_index_contents_ftype; |
| typedef gdb::function_view |
| <gdb::array_view<const gdb_byte>(objfile *, dwz_file *)> |
| get_gdb_index_contents_dwz_ftype; |
| |
| /* Read .gdb_index. If everything went ok, initialize the "quick" |
| elements of all the CUs and return 1. Otherwise, return 0. */ |
| |
| static int |
| dwarf2_read_gdb_index |
| (dwarf2_per_objfile *per_objfile, |
| get_gdb_index_contents_ftype get_gdb_index_contents, |
| get_gdb_index_contents_dwz_ftype get_gdb_index_contents_dwz) |
| { |
| const gdb_byte *cu_list, *types_list, *dwz_list = NULL; |
| offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0; |
| struct dwz_file *dwz; |
| struct objfile *objfile = per_objfile->objfile; |
| dwarf2_per_bfd *per_bfd = per_objfile->per_bfd; |
| |
| gdb::array_view<const gdb_byte> main_index_contents |
| = get_gdb_index_contents (objfile, per_bfd); |
| |
| if (main_index_contents.empty ()) |
| return 0; |
|