| /* DWARF 2 debugging format support for GDB. |
| |
| Copyright (C) 1994-2020 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 "dwarf2read.h" |
| #include "dwarf-index-cache.h" |
| #include "dwarf-index-common.h" |
| #include "bfd.h" |
| #include "elf-bfd.h" |
| #include "symtab.h" |
| #include "gdbtypes.h" |
| #include "objfiles.h" |
| #include "dwarf2.h" |
| #include "buildsym.h" |
| #include "demangle.h" |
| #include "gdb-demangle.h" |
| #include "filenames.h" /* for DOSish file names */ |
| #include "macrotab.h" |
| #include "language.h" |
| #include "complaints.h" |
| #include "dwarf2expr.h" |
| #include "dwarf2loc.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" |
| |
| /* 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; |
| |
| /* 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. */ |
| static 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; |
| |
| static const struct objfile_key<dwarf2_per_objfile> dwarf2_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; |
| |
| /* 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) 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 (); |
| |
| /* 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) const; |
| |
| /* Prevent deleting/destroying via a base class pointer. */ |
| protected: |
| ~mapped_index_base() = default; |
| }; |
| |
| /* 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 |
| { |
| /* A slot/bucket in the symbol table hash. */ |
| struct symbol_table_slot |
| { |
| const offset_type name; |
| const offset_type vec; |
| }; |
| |
| /* 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. */ |
| gdb::array_view<symbol_table_slot> symbol_table; |
| |
| /* A pointer to the constant pool. */ |
| const char *constant_pool = nullptr; |
| |
| bool symbol_name_slot_invalid (offset_type idx) const override |
| { |
| const auto &bucket = this->symbol_table[idx]; |
| return bucket.name == 0 && bucket.vec == 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) const override |
| { return this->constant_pool + MAYBE_SWAP (this->symbol_table[idx].name); } |
| |
| size_t symbol_name_count () const override |
| { return this->symbol_table.size (); } |
| }; |
| |
| /* A description of the mapped .debug_names. |
| Uninitialized map has CU_COUNT 0. */ |
| struct mapped_debug_names final : public mapped_index_base |
| { |
| mapped_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile_) |
| : dwarf2_per_objfile (dwarf2_per_objfile_) |
| {} |
| |
| struct dwarf2_per_objfile *dwarf2_per_objfile; |
| 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) const; |
| |
| /* Implementation of the mapped_index_base virtual interface, for |
| the name_components cache. */ |
| |
| const char *symbol_name_at (offset_type idx) const override |
| { return namei_to_name (idx); } |
| |
| 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. */ |
| |
| static 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_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 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_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 data in a compilation unit header, after target2host |
| translation, looks like this. */ |
| struct comp_unit_head |
| { |
| unsigned int length; |
| short version; |
| unsigned char addr_size; |
| unsigned char signed_addr_p; |
| sect_offset abbrev_sect_off; |
| |
| /* Size of file offsets; either 4 or 8. */ |
| unsigned int offset_size; |
| |
| /* Size of the length field; either 4 or 12. */ |
| unsigned int initial_length_size; |
| |
| enum dwarf_unit_type unit_type; |
| |
| /* Offset to the first byte of this compilation unit header in the |
| .debug_info section, for resolving relative reference dies. */ |
| sect_offset sect_off; |
| |
| /* Offset to first die in this cu from the start of the cu. |
| This will be the first byte following the compilation unit header. */ |
| cu_offset first_die_cu_offset; |
| |
| |
| /* 64-bit signature of this unit. For type units, it denotes the signature of |
| the type (DW_UT_type in DWARF 4, additionally DW_UT_split_type in DWARF 5). |
| Also used in DWARF 5, to denote the dwo id when the unit type is |
| DW_UT_skeleton or DW_UT_split_compile. */ |
| ULONGEST signature; |
| |
| /* For types, offset in the type's DIE of the type defined by this TU. */ |
| cu_offset type_cu_offset_in_tu; |
| }; |
| |
| /* Type used for delaying computation of method physnames. |
| See comments for compute_delayed_physnames. */ |
| struct delayed_method_info |
| { |
| /* The type to which the method is attached, i.e., its parent class. */ |
| struct type *type; |
| |
| /* The index of the method in the type's function fieldlists. */ |
| int fnfield_index; |
| |
| /* The index of the method in the fieldlist. */ |
| int index; |
| |
| /* The name of the DIE. */ |
| const char *name; |
| |
| /* The DIE associated with this method. */ |
| struct die_info *die; |
| }; |
| |
| /* Internal state when decoding a particular compilation unit. */ |
| struct dwarf2_cu |
| { |
| explicit dwarf2_cu (struct dwarf2_per_cu_data *per_cu); |
| ~dwarf2_cu (); |
| |
| DISABLE_COPY_AND_ASSIGN (dwarf2_cu); |
| |
| /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope. |
| Create the set of symtabs used by this TU, or if this TU is sharing |
| symtabs with another TU and the symtabs have already been created |
| then restore those symtabs in the line header. |
| We don't need the pc/line-number mapping for type units. */ |
| void setup_type_unit_groups (struct die_info *die); |
| |
| /* Start a symtab for DWARF. NAME, COMP_DIR, LOW_PC are passed to the |
| buildsym_compunit constructor. */ |
| struct compunit_symtab *start_symtab (const char *name, |
| const char *comp_dir, |
| CORE_ADDR low_pc); |
| |
| /* Reset the builder. */ |
| void reset_builder () { m_builder.reset (); } |
| |
| /* The header of the compilation unit. */ |
| struct comp_unit_head header {}; |
| |
| /* Base address of this compilation unit. */ |
| CORE_ADDR base_address = 0; |
| |
| /* Non-zero if base_address has been set. */ |
| int base_known = 0; |
| |
| /* The language we are debugging. */ |
| enum language language = language_unknown; |
| const struct language_defn *language_defn = nullptr; |
| |
| const char *producer = nullptr; |
| |
| private: |
| /* The symtab builder for this CU. This is only non-NULL when full |
| symbols are being read. */ |
| std::unique_ptr<buildsym_compunit> m_builder; |
| |
| public: |
| /* The generic symbol table building routines have separate lists for |
| file scope symbols and all all other scopes (local scopes). So |
| we need to select the right one to pass to add_symbol_to_list(). |
| We do it by keeping a pointer to the correct list in list_in_scope. |
| |
| FIXME: The original dwarf code just treated the file scope as the |
| first local scope, and all other local scopes as nested local |
| scopes, and worked fine. Check to see if we really need to |
| distinguish these in buildsym.c. */ |
| struct pending **list_in_scope = nullptr; |
| |
| /* Hash table holding all the loaded partial DIEs |
| with partial_die->offset.SECT_OFF as hash. */ |
| htab_t partial_dies = nullptr; |
| |
| /* Storage for things with the same lifetime as this read-in compilation |
| unit, including partial DIEs. */ |
| auto_obstack comp_unit_obstack; |
| |
| /* When multiple dwarf2_cu structures are living in memory, this field |
| chains them all together, so that they can be released efficiently. |
| We will probably also want a generation counter so that most-recently-used |
| compilation units are cached... */ |
| struct dwarf2_per_cu_data *read_in_chain = nullptr; |
| |
| /* Backlink to our per_cu entry. */ |
| struct dwarf2_per_cu_data *per_cu; |
| |
| /* How many compilation units ago was this CU last referenced? */ |
| int last_used = 0; |
| |
| /* A hash table of DIE cu_offset for following references with |
| die_info->offset.sect_off as hash. */ |
| htab_t die_hash = nullptr; |
| |
| /* Full DIEs if read in. */ |
| struct die_info *dies = nullptr; |
| |
| /* A set of pointers to dwarf2_per_cu_data objects for compilation |
| units referenced by this one. Only set during full symbol processing; |
| partial symbol tables do not have dependencies. */ |
| htab_t dependencies = nullptr; |
| |
| /* Header data from the line table, during full symbol processing. */ |
| struct line_header *line_header = nullptr; |
| /* Non-NULL if LINE_HEADER is owned by this DWARF_CU. Otherwise, |
| it's owned by dwarf2_per_objfile::line_header_hash. If non-NULL, |
| this is the DW_TAG_compile_unit die for this CU. We'll hold on |
| to the line header as long as this DIE is being processed. See |
| process_die_scope. */ |
| die_info *line_header_die_owner = nullptr; |
| |
| /* A list of methods which need to have physnames computed |
| after all type information has been read. */ |
| std::vector<delayed_method_info> method_list; |
| |
| /* To be copied to symtab->call_site_htab. */ |
| htab_t call_site_htab = nullptr; |
| |
| /* Non-NULL if this CU came from a DWO file. |
| There is an invariant here that is important to remember: |
| Except for attributes copied from the top level DIE in the "main" |
| (or "stub") file in preparation for reading the DWO file |
| (e.g., DW_AT_GNU_addr_base), we KISS: there is only *one* CU. |
| Either there isn't a DWO file (in which case this is NULL and the point |
| is moot), or there is and either we're not going to read it (in which |
| case this is NULL) or there is and we are reading it (in which case this |
| is non-NULL). */ |
| struct dwo_unit *dwo_unit = nullptr; |
| |
| /* The DW_AT_addr_base attribute if present, zero otherwise |
| (zero is a valid value though). |
| Note this value comes from the Fission stub CU/TU's DIE. */ |
| ULONGEST addr_base = 0; |
| |
| /* The DW_AT_ranges_base attribute if present, zero otherwise |
| (zero is a valid value though). |
| Note this value comes from the Fission stub CU/TU's DIE. |
| Also note that the value is zero in the non-DWO case so this value can |
| be used without needing to know whether DWO files are in use or not. |
| N.B. This does not apply to DW_AT_ranges appearing in |
| DW_TAG_compile_unit dies. This is a bit of a wart, consider if ever |
| DW_AT_ranges appeared in the DW_TAG_compile_unit of DWO DIEs: then |
| DW_AT_ranges_base *would* have to be applied, and we'd have to care |
| whether the DW_AT_ranges attribute came from the skeleton or DWO. */ |
| ULONGEST ranges_base = 0; |
| |
| /* When reading debug info generated by older versions of rustc, we |
| have to rewrite some union types to be struct types with a |
| variant part. This rewriting must be done after the CU is fully |
| read in, because otherwise at the point of rewriting some struct |
| type might not have been fully processed. So, we keep a list of |
| all such types here and process them after expansion. */ |
| std::vector<struct type *> rust_unions; |
| |
| /* Mark used when releasing cached dies. */ |
| bool mark : 1; |
| |
| /* This CU references .debug_loc. See the symtab->locations_valid field. |
| This test is imperfect as there may exist optimized debug code not using |
| any location list and still facing inlining issues if handled as |
| unoptimized code. For a future better test see GCC PR other/32998. */ |
| bool has_loclist : 1; |
| |
| /* These cache the results for producer_is_* fields. CHECKED_PRODUCER is true |
| if all the producer_is_* fields are valid. This information is cached |
| because profiling CU expansion showed excessive time spent in |
| producer_is_gxx_lt_4_6. */ |
| bool checked_producer : 1; |
| bool producer_is_gxx_lt_4_6 : 1; |
| bool producer_is_gcc_lt_4_3 : 1; |
| bool producer_is_icc : 1; |
| bool producer_is_icc_lt_14 : 1; |
| bool producer_is_codewarrior : 1; |
| |
| /* When true, the file that we're processing is known to have |
| debugging info for C++ namespaces. GCC 3.3.x did not produce |
| this information, but later versions do. */ |
| |
| bool processing_has_namespace_info : 1; |
| |
| struct partial_die_info *find_partial_die (sect_offset sect_off); |
| |
| /* If this CU was inherited by another CU (via specification, |
| abstract_origin, etc), this is the ancestor CU. */ |
| dwarf2_cu *ancestor; |
| |
| /* Get the buildsym_compunit for this CU. */ |
| buildsym_compunit *get_builder () |
| { |
| /* If this CU has a builder associated with it, use that. */ |
| if (m_builder != nullptr) |
| return m_builder.get (); |
| |
| /* Otherwise, search ancestors for a valid builder. */ |
| if (ancestor != nullptr) |
| return ancestor->get_builder (); |
| |
| return nullptr; |
| } |
| }; |
| |
| /* 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_objfile->type_unit_groups is a pointer to |
| an object of this type. */ |
| |
| struct type_unit_group |
| { |
| /* dwarf2read.c's main "handle" on a TU symtab. |
| To simplify things we create an artificial CU that "includes" all the |
| type units using this stmt_list so that the rest of the code still has |
| a "per_cu" handle on the symtab. |
| This PER_CU is recognized by having no section. */ |
| #define IS_TYPE_UNIT_GROUP(per_cu) ((per_cu)->section == NULL) |
| struct dwarf2_per_cu_data per_cu; |
| |
| /* 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; |
| |
| /* The compunit symtab. |
| Type units in a group needn't all be defined in the same source file, |
| so we create an essentially anonymous symtab as the compunit symtab. */ |
| struct compunit_symtab *compunit_symtab; |
| |
| /* The data used to construct the hash key. */ |
| struct stmt_list_hash hash; |
| |
| /* The number of symtabs from the line header. |
| The value here must match line_header.num_file_names. */ |
| unsigned int num_symtabs; |
| |
| /* The symbol tables for this TU (obtained from the files listed in |
| DW_AT_stmt_list). |
| WARNING: The order of entries here must match the order of entries |
| in the line header. After the first TU using this type_unit_group, the |
| line header for the subsequent TUs is recreated from this. This is done |
| because we need to use the same symtabs for each TU using the same |
| DW_AT_stmt_list value. Also note that symtabs may be repeated here, |
| there's no guarantee the line header doesn't have duplicate entries. */ |
| struct symtab **symtabs; |
| }; |
| |
| /* 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 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 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, 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_t cus {}; |
| |
| /* Table of TUs in the file. |
| Each element is a struct dwo_unit. */ |
| htab_t tus {}; |
| }; |
| |
| /* These sections are what may appear in a DWP file. */ |
| |
| struct dwp_sections |
| { |
| /* These are used by both DWP version 1 and 2. */ |
| 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 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 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 macinfo; |
| struct dwarf2_section_info macro; |
| 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. |
| 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_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 macinfo_offset; |
| bfd_size_type macinfo_size; |
| |
| bfd_size_type macro_offset; |
| bfd_size_type macro_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; |
| } 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_t loaded_cus {}; |
| htab_t 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 value of the DW_AT_comp_dir attribute. */ |
| const char *comp_dir; |
| |
| /* The abbreviation table to use when reading the DIEs. */ |
| struct abbrev_table *abbrev_table; |
| }; |
| |
| /* Type of function passed to init_cutu_and_read_dies, et.al. */ |
| typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader, |
| const gdb_byte *info_ptr, |
| struct die_info *comp_unit_die, |
| int has_children, |
| void *data); |
| |
| /* dir_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 and |
| later. */ |
| typedef int dir_index; |
| |
| /* file_name_index is 1-based in DWARF 4 and before, and is 0-based in DWARF 5 |
| and later. */ |
| typedef int file_name_index; |
| |
| struct file_entry |
| { |
| file_entry () = default; |
| |
| file_entry (const char *name_, dir_index d_index_, |
| unsigned int mod_time_, unsigned int length_) |
| : name (name_), |
| d_index (d_index_), |
| mod_time (mod_time_), |
| length (length_) |
| {} |
| |
| /* Return the include directory at D_INDEX stored in LH. Returns |
| NULL if D_INDEX is out of bounds. */ |
| const char *include_dir (const line_header *lh) const; |
| |
| /* The file name. Note this is an observing pointer. The memory is |
| owned by debug_line_buffer. */ |
| const char *name {}; |
| |
| /* The directory index (1-based). */ |
| dir_index d_index {}; |
| |
| unsigned int mod_time {}; |
| |
| unsigned int length {}; |
| |
| /* True if referenced by the Line Number Program. */ |
| bool included_p {}; |
| |
| /* The associated symbol table, if any. */ |
| struct symtab *symtab {}; |
| }; |
| |
| /* The line number information for a compilation unit (found in the |
| .debug_line section) begins with a "statement program header", |
| which contains the following information. */ |
| struct line_header |
| { |
| line_header () |
| : offset_in_dwz {} |
| {} |
| |
| /* Add an entry to the include directory table. */ |
| void add_include_dir (const char *include_dir); |
| |
| /* Add an entry to the file name table. */ |
| void add_file_name (const char *name, dir_index d_index, |
| unsigned int mod_time, unsigned int length); |
| |
| /* Return the include dir at INDEX (0-based in DWARF 5 and 1-based before). |
| Returns NULL if INDEX is out of bounds. */ |
| const char *include_dir_at (dir_index index) const |
| { |
| int vec_index; |
| if (version >= 5) |
| vec_index = index; |
| else |
| vec_index = index - 1; |
| if (vec_index < 0 || vec_index >= m_include_dirs.size ()) |
| return NULL; |
| return m_include_dirs[vec_index]; |
| } |
| |
| bool is_valid_file_index (int file_index) |
| { |
| if (version >= 5) |
| return 0 <= file_index && file_index < file_names_size (); |
| return 1 <= file_index && file_index <= file_names_size (); |
| } |
| |
| /* Return the file name at INDEX (0-based in DWARF 5 and 1-based before). |
| Returns NULL if INDEX is out of bounds. */ |
| file_entry *file_name_at (file_name_index index) |
| { |
| int vec_index; |
| if (version >= 5) |
| vec_index = index; |
| else |
| vec_index = index - 1; |
| if (vec_index < 0 || vec_index >= m_file_names.size ()) |
| return NULL; |
| return &m_file_names[vec_index]; |
| } |
| |
| /* The indexes are 0-based in DWARF 5 and 1-based in DWARF 4. Therefore, |
| this method should only be used to iterate through all file entries in an |
| index-agnostic manner. */ |
| std::vector<file_entry> &file_names () |
| { return m_file_names; } |
| |
| /* Offset of line number information in .debug_line section. */ |
| sect_offset sect_off {}; |
| |
| /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile. */ |
| unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class. */ |
| |
| unsigned int total_length {}; |
| unsigned short version {}; |
| unsigned int header_length {}; |
| unsigned char minimum_instruction_length {}; |
| unsigned char maximum_ops_per_instruction {}; |
| unsigned char default_is_stmt {}; |
| int line_base {}; |
| unsigned char line_range {}; |
| unsigned char opcode_base {}; |
| |
| /* standard_opcode_lengths[i] is the number of operands for the |
| standard opcode whose value is i. This means that |
| standard_opcode_lengths[0] is unused, and the last meaningful |
| element is standard_opcode_lengths[opcode_base - 1]. */ |
| std::unique_ptr<unsigned char[]> standard_opcode_lengths; |
| |
| int file_names_size () |
| { return m_file_names.size(); } |
| |
| /* The start and end of the statement program following this |
| header. These point into dwarf2_per_objfile->line_buffer. */ |
| const gdb_byte *statement_program_start {}, *statement_program_end {}; |
| |
| private: |
| /* The include_directories table. Note these are observing |
| pointers. The memory is owned by debug_line_buffer. */ |
| std::vector<const char *> m_include_dirs; |
| |
| /* The file_names table. This is private because the meaning of indexes |
| differs among DWARF versions (The first valid index is 1 in DWARF 4 and |
| before, and is 0 in DWARF 5 and later). So the client should use |
| file_name_at method for access. */ |
| std::vector<file_entry> m_file_names; |
| }; |
| |
| typedef std::unique_ptr<line_header> line_header_up; |
| |
| const char * |
| file_entry::include_dir (const line_header *lh) const |
| { |
| return lh->include_dir_at (d_index); |
| } |
| |
| /* 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, 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; |
| |
| /* 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); |
| |
| /* 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 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; |
| |
| /* The name of this DIE. Normally the value of DW_AT_name, but |
| sometimes a default name for unnamed DIEs. */ |
| const char *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 {}; |
| |
| /* If HAS_PC_INFO, the PC range associated with this DIE. */ |
| CORE_ADDR lowpc = 0; |
| CORE_ADDR highpc = 0; |
| |
| /* 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; |
| 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; |
| } |
| }; |
| |
| /* This data structure holds the information of an abbrev. */ |
| struct abbrev_info |
| { |
| unsigned int number; /* number identifying abbrev */ |
| enum dwarf_tag tag; /* dwarf tag */ |
| unsigned short has_children; /* boolean */ |
| unsigned short num_attrs; /* number of attributes */ |
| struct attr_abbrev *attrs; /* an array of attribute descriptions */ |
| struct abbrev_info *next; /* next in chain */ |
| }; |
| |
| struct attr_abbrev |
| { |
| ENUM_BITFIELD(dwarf_attribute) name : 16; |
| ENUM_BITFIELD(dwarf_form) form : 16; |
| |
| /* It is valid only if FORM is DW_FORM_implicit_const. */ |
| LONGEST implicit_const; |
| }; |
| |
| /* Size of abbrev_table.abbrev_hash_table. */ |
| #define ABBREV_HASH_SIZE 121 |
| |
| /* Top level data structure to contain an abbreviation table. */ |
| |
| struct abbrev_table |
| { |
| explicit abbrev_table (sect_offset off) |
| : sect_off (off) |
| { |
| m_abbrevs = |
| XOBNEWVEC (&abbrev_obstack, struct abbrev_info *, ABBREV_HASH_SIZE); |
| memset (m_abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *)); |
| } |
| |
| DISABLE_COPY_AND_ASSIGN (abbrev_table); |
| |
| /* Allocate space for a struct abbrev_info object in |
| ABBREV_TABLE. */ |
| struct abbrev_info *alloc_abbrev (); |
| |
| /* Add an abbreviation to the table. */ |
| void add_abbrev (unsigned int abbrev_number, struct abbrev_info *abbrev); |
| |
| /* Look up an abbrev in the table. |
| Returns NULL if the abbrev is not found. */ |
| |
| struct abbrev_info *lookup_abbrev (unsigned int abbrev_number); |
| |
| |
| /* Where the abbrev table came from. |
| This is used as a sanity check when the table is used. */ |
| const sect_offset sect_off; |
| |
| /* Storage for the abbrev table. */ |
| auto_obstack abbrev_obstack; |
| |
| private: |
| |
| /* Hash table of abbrevs. |
| This is an array of size ABBREV_HASH_SIZE allocated in abbrev_obstack. |
| It could be statically allocated, but the previous code didn't so we |
| don't either. */ |
| struct abbrev_info **m_abbrevs; |
| }; |
| |
| typedef std::unique_ptr<struct abbrev_table> abbrev_table_up; |
| |
| /* Attributes have a name and a value. */ |
| struct attribute |
| { |
| ENUM_BITFIELD(dwarf_attribute) name : 16; |
| ENUM_BITFIELD(dwarf_form) form : 15; |
| |
| /* Has DW_STRING already been updated by dwarf2_canonicalize_name? This |
| field should be in u.str (existing only for DW_STRING) but it is kept |
| here for better struct attribute alignment. */ |
| unsigned int string_is_canonical : 1; |
| |
| union |
| { |
| const char *str; |
| struct dwarf_block *blk; |
| ULONGEST unsnd; |
| LONGEST snd; |
| CORE_ADDR addr; |
| ULONGEST signature; |
| } |
| u; |
| }; |
| |
| /* This data structure holds a complete die structure. */ |
| struct die_info |
| { |
| /* DWARF-2 tag for this DIE. */ |
| ENUM_BITFIELD(dwarf_tag) tag : 16; |
| |
| /* Number of attributes */ |
| unsigned char num_attrs; |
| |
| /* True if we're presently building the full type name for the |
| type derived from this DIE. */ |
| unsigned char building_fullname : 1; |
| |
| /* True if this die is in process. PR 16581. */ |
| unsigned char in_process : 1; |
| |
| /* Abbrev number */ |
| unsigned int abbrev; |
| |
| /* Offset in .debug_info or .debug_types section. */ |
| sect_offset sect_off; |
| |
| /* The dies in a compilation unit form an n-ary tree. PARENT |
| points to this die's parent; CHILD points to the first child of |
| this node; and all the children of a given node are chained |
| together via their SIBLING fields. */ |
| struct die_info *child; /* Its first child, if any. */ |
| struct die_info *sibling; /* Its next sibling, if any. */ |
| struct die_info *parent; /* Its parent, if any. */ |
| |
| /* An array of attributes, with NUM_ATTRS elements. There may be |
| zero, but it's not common and zero-sized arrays are not |
| sufficiently portable C. */ |
| struct attribute attrs[1]; |
| }; |
| |
| /* Get at parts of an attribute structure. */ |
| |
| #define DW_STRING(attr) ((attr)->u.str) |
| #define DW_STRING_IS_CANONICAL(attr) ((attr)->string_is_canonical) |
| #define DW_UNSND(attr) ((attr)->u.unsnd) |
| #define DW_BLOCK(attr) ((attr)->u.blk) |
| #define DW_SND(attr) ((attr)->u.snd) |
| #define DW_ADDR(attr) ((attr)->u.addr) |
| #define DW_SIGNATURE(attr) ((attr)->u.signature) |
| |
| /* Blocks are a bunch of untyped bytes. */ |
| struct dwarf_block |
| { |
| size_t size; |
| |
| /* Valid only if SIZE is not zero. */ |
| const gdb_byte *data; |
| }; |
| |
| #ifndef ATTR_ALLOC_CHUNK |
| #define ATTR_ALLOC_CHUNK 4 |
| #endif |
| |
| /* Allocate fields for structs, unions and enums in this size. */ |
| #ifndef DW_FIELD_ALLOC_CHUNK |
| #define DW_FIELD_ALLOC_CHUNK 4 |
| #endif |
| |
| /* 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; |
| |
| /* When reading a variant or variant part, we track a bit more |
| information about the field, and store it in an object of this |
| type. */ |
| |
| struct variant_field |
| { |
| /* If we see a DW_TAG_variant, then this will be the discriminant |
| value. */ |
| ULONGEST discriminant_value; |
| /* If we see a DW_TAG_variant, then this will be set if this is the |
| default branch. */ |
| bool default_branch; |
| /* While reading a DW_TAG_variant_part, this will be set if this |
| field is the discriminant. */ |
| bool is_discriminant; |
| }; |
| |
| struct nextfield |
| { |
| int accessibility = 0; |
| int virtuality = 0; |
| /* Extra information to describe a variant or variant part. */ |
| struct variant_field variant {}; |
| 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; |
| |
| /* Number of fields (including baseclasses). */ |
| int nfields = 0; |
| |
| /* Set if the accessibility of one of the fields is not public. */ |
| int non_public_fields = 0; |
| |
| /* 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; |
| }; |
| |
| /* One item on the queue of compilation units to read in full symbols |
| for. */ |
| struct dwarf2_queue_item |
| { |
| struct dwarf2_per_cu_data *per_cu; |
| enum language pretend_language; |
| struct dwarf2_queue_item *next; |
| }; |
| |
| /* The current queue. */ |
| static struct dwarf2_queue_item *dwarf2_queue, *dwarf2_queue_tail; |
| |
| /* 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 const char *get_section_name (const struct dwarf2_section_info *); |
| |
| static const char *get_section_file_name (const struct dwarf2_section_info *); |
| |
| static void dwarf2_find_base_address (struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static struct partial_symtab *create_partial_symtab |
| (struct dwarf2_per_cu_data *per_cu, 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, |
| int has_children, void *data); |
| |
| static void dwarf2_build_psymtabs_hard |
| (struct dwarf2_per_objfile *dwarf2_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 void dwarf2_read_symtab (struct partial_symtab *, |
| struct objfile *); |
| |
| static void psymtab_to_symtab_1 (struct partial_symtab *); |
| |
| static abbrev_table_up abbrev_table_read_table |
| (struct dwarf2_per_objfile *dwarf2_per_objfile, struct dwarf2_section_info *, |
| sect_offset); |
| |
| 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 *, struct attr_abbrev *, |
| const gdb_byte *); |
| |
| static unsigned int read_1_byte (bfd *, const gdb_byte *); |
| |
| static int read_1_signed_byte (bfd *, const gdb_byte *); |
| |
| static unsigned int read_2_bytes (bfd *, const gdb_byte *); |
| |
| /* Read the next three bytes (little-endian order) as an unsigned integer. */ |
| static unsigned int read_3_bytes (bfd *, const gdb_byte *); |
| |
| static unsigned int read_4_bytes (bfd *, const gdb_byte *); |
| |
| static ULONGEST read_8_bytes (bfd *, const gdb_byte *); |
| |
| static CORE_ADDR read_address (bfd *, const gdb_byte *ptr, struct dwarf2_cu *, |
| unsigned int *); |
| |
| static LONGEST read_initial_length (bfd *, const gdb_byte *, unsigned int *); |
| |
| static LONGEST read_checked_initial_length_and_offset |
| (bfd *, const gdb_byte *, const struct comp_unit_head *, |
| unsigned int *, unsigned int *); |
| |
| static LONGEST read_offset (bfd *, const gdb_byte *, |
| const struct comp_unit_head *, |
| unsigned int *); |
| |
| static LONGEST read_offset_1 (bfd *, const gdb_byte *, unsigned int); |
| |
| static sect_offset read_abbrev_offset |
| (struct dwarf2_per_objfile *dwarf2_per_objfile, |
| struct dwarf2_section_info *, sect_offset); |
| |
| static const gdb_byte *read_n_bytes (bfd *, const gdb_byte *, unsigned int); |
| |
| static const char *read_direct_string (bfd *, const gdb_byte *, unsigned int *); |
| |
| static const char *read_indirect_string |
| (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *, |
| const struct comp_unit_head *, unsigned int *); |
| |
| static const char *read_indirect_line_string |
| (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *, |
| const struct comp_unit_head *, unsigned int *); |
| |
| static const char *read_indirect_string_at_offset |
| (struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *abfd, |
| LONGEST str_offset); |
| |
| static const char *read_indirect_string_from_dwz |
| (struct objfile *objfile, struct dwz_file *, LONGEST); |
| |
| static LONGEST read_signed_leb128 (bfd *, const gdb_byte *, unsigned int *); |
| |
| static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, |
| const gdb_byte *, |
| unsigned int *); |
| |
| static const char *read_str_index (const struct die_reader_specs *reader, |
| ULONGEST str_index); |
| |
| static void set_cu_language (unsigned int, struct dwarf2_cu *); |
| |
| static struct attribute *dwarf2_attr (struct die_info *, unsigned int, |
| struct dwarf2_cu *); |
| |
| static struct attribute *dwarf2_attr_no_follow (struct die_info *, |
| unsigned int); |
| |
| 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); |
| |
| static void dwarf_decode_lines (struct line_header *, const char *, |
| struct dwarf2_cu *, struct partial_symtab *, |
| 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 *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); |
| |
| static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, |
| struct dwarf2_cu *, struct partial_symtab *); |
| |
| /* 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 *, |
| struct partial_symtab *); |
| |
| 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 *); |
| |
| 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 *, int); |
| |
| static const gdb_byte *read_full_die (const struct die_reader_specs *, |
| struct die_info **, const gdb_byte *, |
| int *); |
| |
| static void process_die (struct die_info *, struct dwarf2_cu *); |
| |
| static const char *dwarf2_canonicalize_name (const char *, struct dwarf2_cu *, |
| struct obstack *); |
| |
| 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 const char *dwarf_tag_name (unsigned int); |
| |
| static const char *dwarf_attr_name (unsigned int); |
| |
| static const char *dwarf_unit_type_name (int unit_type); |
| |
| static const char *dwarf_form_name (unsigned int); |
| |
| static const char *dwarf_bool_name (unsigned int); |
| |
| static const char *dwarf_type_encoding_name (unsigned int); |
| |
| static struct die_info *sibling_die (struct die_info *); |
| |
| 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 sect_offset dwarf2_get_ref_die_offset (const struct attribute *); |
| |
| static LONGEST dwarf2_get_attr_constant_value (const struct attribute *, int); |
| |
| 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 (struct dwarf2_per_cu_data *per_cu); |
| |
| static void read_signatured_type (struct signatured_type *); |
| |
| 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 int attr_form_is_block (const struct attribute *); |
| |
| static int attr_form_is_section_offset (const struct attribute *); |
| |
| static int attr_form_is_constant (const struct attribute *); |
| |
| static int attr_form_is_ref (const struct attribute *); |
| |
| 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, |
| 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, |
| struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static void prepare_one_comp_unit (struct dwarf2_cu *cu, |
| struct die_info *comp_unit_die, |
| enum language pretend_language); |
| |
| static void age_cached_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static void free_one_cached_comp_unit (struct dwarf2_per_cu_data *); |
| |
| static struct type *set_die_type (struct die_info *, struct type *, |
| struct dwarf2_cu *); |
| |
| static void create_all_comp_units (struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static int create_all_type_units (struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static void load_full_comp_unit (struct dwarf2_per_cu_data *, bool, |
| enum language); |
| |
| static void process_full_comp_unit (struct dwarf2_per_cu_data *, |
| enum language); |
| |
| static void process_full_type_unit (struct dwarf2_per_cu_data *, |
| enum language); |
| |
| static void dwarf2_add_dependence (struct dwarf2_cu *, |
| struct dwarf2_per_cu_data *); |
| |
| static void dwarf2_mark (struct dwarf2_cu *); |
| |
| static void dwarf2_clear_marks (struct dwarf2_per_cu_data *); |
| |
| static struct type *get_die_type_at_offset (sect_offset, |
| struct dwarf2_per_cu_data *); |
| |
| static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu); |
| |
| static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, |
| enum language pretend_language); |
| |
| static void process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static struct type *dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu); |
| static struct type *dwarf2_per_cu_addr_sized_int_type |
| (struct dwarf2_per_cu_data *per_cu, bool unsigned_p); |
| static struct type *dwarf2_per_cu_int_type |
| (struct dwarf2_per_cu_data *per_cu, int size_in_bytes, |
| bool unsigned_p); |
| |
| /* 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: |
| dwarf2_queue_guard () = default; |
| |
| /* 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 () |
| { |
| struct dwarf2_queue_item *item, *last; |
| |
| item = dwarf2_queue; |
| while (item) |
| { |
| /* Anything still marked queued is likely to be in an |
| inconsistent state, so discard it. */ |
| if (item->per_cu->queued) |
| { |
| if (item->per_cu->cu != NULL) |
| free_one_cached_comp_unit (item->per_cu); |
| item->per_cu->queued = 0; |
| } |
| |
| last = item; |
| item = item->next; |
| xfree (last); |
| } |
| |
| dwarf2_queue = dwarf2_queue_tail = NULL; |
| } |
| }; |
| |
| /* 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, this points to COMP_DIR_STORAGE, otherwise, |
| points directly to the DW_AT_comp_dir string attribute owned by |
| the obstack that owns the DIE. */ |
| const char *comp_dir; |
| |
| /* If we needed to build a new string for comp_dir, this is what |
| owns the storage. */ |
| std::string comp_dir_storage; |
| }; |
| |
| static file_and_directory find_file_and_directory (struct die_info *die, |
| struct dwarf2_cu *cu); |
| |
| static char *file_full_name (int file, struct line_header *lh, |
| const char *comp_dir); |
| |
| /* Expected enum dwarf_unit_type for read_comp_unit_head. */ |
| enum class rcuh_kind { COMPILE, TYPE }; |
| |
| static const gdb_byte *read_and_check_comp_unit_head |
| (struct dwarf2_per_objfile* dwarf2_per_objfile, |
| struct comp_unit_head *header, |
| struct dwarf2_section_info *section, |
| struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr, |
| rcuh_kind section_kind); |
| |
| static void init_cutu_and_read_dies |
| (struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table, |
| int use_existing_cu, int keep, bool skip_partial, |
| die_reader_func_ftype *die_reader_func, void *data); |
| |
| static void init_cutu_and_read_dies_simple |
| (struct dwarf2_per_cu_data *this_cu, |
| die_reader_func_ftype *die_reader_func, void *data); |
| |
| static htab_t allocate_signatured_type_table (struct objfile *objfile); |
| |
| static htab_t allocate_dwo_unit_table (struct objfile *objfile); |
| |
| static struct dwo_unit *lookup_dwo_unit_in_dwp |
| (struct dwarf2_per_objfile *dwarf2_per_objfile, |
| struct dwp_file *dwp_file, const char *comp_dir, |
| ULONGEST signature, int is_debug_types); |
| |
| static struct dwp_file *get_dwp_file |
| (struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static struct dwo_unit *lookup_dwo_comp_unit |
| (struct dwarf2_per_cu_data *, const char *, const char *, ULONGEST); |
| |
| static struct dwo_unit *lookup_dwo_type_unit |
| (struct signatured_type *, const char *, const char *); |
| |
| static void queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *); |
| |
| /* A unique pointer to a dwo_file. */ |
| |
| typedef std::unique_ptr<struct dwo_file> dwo_file_up; |
| |
| static void process_cu_includes (struct dwarf2_per_objfile *dwarf2_per_objfile); |
| |
| static void check_producer (struct dwarf2_cu *cu); |
| |
| static void free_line_header_voidp (void *arg); |
| |
| /* Various complaints about symbol reading that don't abort the process. */ |
| |
| static void |
| dwarf2_statement_list_fits_in_line_number_section_complaint (void) |
| { |
| complaint (_("statement list doesn't fit in .debug_line section")); |
| } |
| |
| 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_section_buffer_overflow_complaint (struct dwarf2_section_info *section) |
| { |
| complaint (_("debug info runs off end of %s section" |
| " [in module %s]"), |
| get_section_name (section), |
| get_section_file_name (section)); |
| } |
| |
| static void |
| dwarf2_macro_malformed_definition_complaint (const char *arg1) |
| { |
| complaint (_("macro debug info contains a " |
| "malformed macro definition:\n`%s'"), |
| arg1); |
| } |
| |
| 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); |
| } |
| |
| |
| |
| /* Read the given attribute value as an address, taking the attribute's |
| form into account. */ |
| |
| static CORE_ADDR |
| attr_value_as_address (struct attribute *attr) |
| { |
| CORE_ADDR addr; |
| |
| if (attr->form != DW_FORM_addr && attr->form != DW_FORM_addrx |
| && attr->form != DW_FORM_GNU_addr_index) |
| { |
| /* Aside from a few clearly defined exceptions, attributes that |
| contain an address must always be in DW_FORM_addr form. |
| Unfortunately, some compilers happen to be violating this |
| requirement by encoding addresses using other forms, such |
| as DW_FORM_data4 for example. For those broken compilers, |
| we try to do our best, without any guarantee of success, |
| to interpret the address correctly. It would also be nice |
| to generate a complaint, but that would require us to maintain |
| a list of legitimate cases where a non-address form is allowed, |
| as well as update callers to pass in at least the CU's DWARF |
| version. This is more overhead than what we're willing to |
| expand for a pretty rare case. */ |
| addr = DW_UNSND (attr); |
| } |
| else |
| addr = DW_ADDR (attr); |
| |
| return addr; |
| } |
| |
| /* See declaration. */ |
| |
| dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_, |
| const dwarf2_debug_sections *names, |
| bool can_copy_) |
| : objfile (objfile_), |
| can_copy (can_copy_) |
| { |
| if (names == NULL) |
| names = &dwarf2_elf_names; |
| |
| bfd *obfd = objfile->obfd; |
| |
| for (asection *sec = obfd->sections; sec != NULL; sec = sec->next) |
| locate_sections (obfd, sec, *names); |
| } |
| |
| dwarf2_per_objfile::~dwarf2_per_objfile () |
| { |
| /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ |
| free_cached_comp_units (); |
| |
| if (quick_file_names_table) |
| htab_delete (quick_file_names_table); |
| |
| if (line_header_hash) |
| htab_delete (line_header_hash); |
| |
| for (dwarf2_per_cu_data *per_cu : all_comp_units) |
| per_cu->imported_symtabs_free (); |
| |
| for (signatured_type *sig_type : all_type_units) |
| sig_type->per_cu.imported_symtabs_free (); |
| |
| /* Everything else should be on the objfile obstack. */ |
| } |
| |
| /* See declaration. */ |
| |
| void |
| dwarf2_per_objfile::free_cached_comp_units () |
| { |
| dwarf2_per_cu_data *per_cu = read_in_chain; |
| dwarf2_per_cu_data **last_chain = &read_in_chain; |
| while (per_cu != NULL) |
| { |
| dwarf2_per_cu_data *next_cu = per_cu->cu->read_in_chain; |
| |
| delete per_cu->cu; |
| *last_chain = next_cu; |
| per_cu = next_cu; |
| } |
| } |
| |
| /* 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->free_cached_comp_units (); |
| } |
| |
| DISABLE_COPY_AND_ASSIGN (free_cached_comp_units); |
| |
| private: |
| |
| dwarf2_per_objfile *m_per_objfile; |
| }; |
| |
| /* 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; |
| |
| struct dwarf2_per_objfile *dwarf2_per_objfile |
| = get_dwarf2_per_objfile (objfile); |
| |
| if (dwarf2_per_objfile == NULL) |
| dwarf2_per_objfile = dwarf2_objfile_data_key.emplace (objfile, objfile, |
| names, |
| can_copy); |
| |
| return (!dwarf2_per_objfile->info.is_virtual |
| && dwarf2_per_objfile->info.s.section != NULL |
| && !dwarf2_per_objfile->abbrev.is_virtual |
| && dwarf2_per_objfile->abbrev.s.section != NULL); |
| } |
| |
| /* Return the containing section of virtual section SECTION. */ |
| |
| static struct dwarf2_section_info * |
| get_containing_section (const struct dwarf2_section_info *section) |
| { |
| gdb_assert (section->is_virtual); |
| return section->s.containing_section; |
| } |
| |
| /* Return the bfd owner of SECTION. */ |
| |
| static struct bfd * |
| get_section_bfd_owner (const struct dwarf2_section_info *section) |
| { |
| if (section->is_virtual) |
| { |
| section = get_containing_section (section); |
| gdb_assert (!section->is_virtual); |
| } |
| return section->s.section->owner; |
| } |
| |
| /* Return the bfd section of SECTION. |
| Returns NULL if the section is not present. */ |
| |
| static asection * |
| get_section_bfd_section (const struct dwarf2_section_info *section) |
| { |
| if (section->is_virtual) |
| { |
| section = get_containing_section (section); |
| gdb_assert (!section->is_virtual); |
| } |
| return section->s.section; |
| } |
| |
| /* Return the name of SECTION. */ |
| |
| static const char * |
| get_section_name (const struct dwarf2_section_info *section) |
| { |
| asection *sectp = get_section_bfd_section (section); |
| |
| gdb_assert (sectp != NULL); |
| return bfd_section_name (sectp); |
| } |
| |
| /* Return the name of the file SECTION is in. */ |
| |
| static const char * |
| get_section_file_name (const struct dwarf2_section_info *section) |
| { |
| bfd *abfd = get_section_bfd_owner (section); |
| |
| return bfd_get_filename (abfd); |
| } |
| |
| /* Return the id of SECTION. |
| Returns 0 if SECTION doesn't exist. */ |
| |
| static int |
| get_section_id (const struct dwarf2_section_info *section) |
| { |
| asection *sectp = get_section_bfd_section (section); |
| |
| if (sectp == NULL) |
| return 0; |
| return sectp->id; |
| } |
| |
| /* Return the flags of SECTION. |
| SECTION (or containing section if this is a virtual section) must exist. */ |
| |
| static int |
| get_section_flags (const struct dwarf2_section_info *section) |
| { |
| asection *sectp = get_section_bfd_section (section); |
| |
| gdb_assert (sectp != NULL); |
| return bfd_section_flags (sectp); |
| } |
| |
| /* When loading sections, we look either for uncompressed section or for |
| compressed section names. */ |
| |
| static int |
| section_is_p (const char *section_name, |
| const struct dwarf2_section_names *names) |
| { |
| if (names->normal != NULL |
| && strcmp (section_name, names->normal) == 0) |
| return 1; |
| if (names->compressed != NULL |
| && strcmp (section_name, names->compressed) == 0) |
| return 1; |
| return 0; |
| } |
| |
| /* See declaration. */ |
| |
| void |
| dwarf2_per_objfile::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 (section_is_p (sectp->name, &names.info)) |
| { |
| this->info.s.section = sectp; |
| this->info.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.abbrev)) |
| { |
| this->abbrev.s.section = sectp; |
| this->abbrev.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.line)) |
| { |
| this->line.s.section = sectp; |
| this->line.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.loc)) |
| { |
| this->loc.s.section = sectp; |
| this->loc.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.loclists)) |
| { |
| this->loclists.s.section = sectp; |
| this->loclists.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.macinfo)) |
| { |
| this->macinfo.s.section = sectp; |
| this->macinfo.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.macro)) |
| { |
| this->macro.s.section = sectp; |
| this->macro.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.str)) |
| { |
| this->str.s.section = sectp; |
| this->str.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.line_str)) |
| { |
| this->line_str.s.section = sectp; |
| this->line_str.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.addr)) |
| { |
| this->addr.s.section = sectp; |
| this->addr.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.frame)) |
| { |
| this->frame.s.section = sectp; |
| this->frame.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.eh_frame)) |
| { |
| this->eh_frame.s.section = sectp; |
| this->eh_frame.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.ranges)) |
| { |
| this->ranges.s.section = sectp; |
| this->ranges.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.rnglists)) |
| { |
| this->rnglists.s.section = sectp; |
| this->rnglists.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.types)) |
| { |
| 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 (section_is_p (sectp->name, &names.gdb_index)) |
| { |
| this->gdb_index.s.section = sectp; |
| this->gdb_index.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.debug_names)) |
| { |
| this->debug_names.s.section = sectp; |
| this->debug_names.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names.debug_aranges)) |
| { |
| 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; |
| } |
| |
| /* A helper function that decides whether a section is empty, |
| or not present. */ |
| |
| static int |
| dwarf2_section_empty_p (const struct dwarf2_section_info *section) |
| { |
| if (section->is_virtual) |
| return section->size == 0; |
| return section->s.section == NULL || section->size == 0; |
| } |
| |
| /* See dwarf2read.h. */ |
| |
| void |
| dwarf2_read_section (struct objfile *objfile, dwarf2_section_info *info) |
| { |
| asection *sectp; |
| bfd *abfd; |
| gdb_byte *buf, *retbuf; |
| |
| if (info->readin) |
| return; |
| info->buffer = NULL; |
| info->readin = true; |
| |
| if (dwarf2_section_empty_p (info)) |
| return; |
| |
| sectp = get_section_bfd_section (info); |
| |
| /* If this is a virtual section we need to read in the real one first. */ |
| if (info->is_virtual) |
| { |
| struct dwarf2_section_info *containing_section = |
| get_containing_section (info); |
| |
| gdb_assert (sectp != NULL); |
| if ((sectp->flags & SEC_RELOC) != 0) |
| { |
| error (_("Dwarf Error: DWP format V2 with relocations is not" |
| " supported in section %s [in module %s]"), |
| get_section_name (info), get_section_file_name (info)); |
| } |
| dwarf2_read_section (objfile, containing_section); |
| /* Other code should have already caught virtual sections that don't |
| fit. */ |
| gdb_assert (info->virtual_offset + info->size |
| <= containing_section->size); |
| /* If the real section is empty or there was a problem reading the |
| section we shouldn't get here. */ |
| gdb_assert (containing_section->buffer != NULL); |
| info->buffer = containing_section->buffer + info->virtual_offset; |
| return; |
| } |
| |
| /* If the section has relocations, we must read it ourselves. |
| Otherwise we attach it to the BFD. */ |
| if ((sectp->flags & SEC_RELOC) == 0) |
| { |
| info->buffer = gdb_bfd_map_section (sectp, &info->size); |
| return; |
| } |
| |
| buf = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack, info->size); |
| info->buffer = buf; |
| |
| /* When debugging .o files, we may need to apply relocations; see |
| http://sourceware.org/ml/gdb-patches/2002-04/msg00136.html . |
| We never compress sections in .o files, so we only need to |
| try this when the section is not compressed. */ |
| retbuf = symfile_relocate_debug_section (objfile, sectp, buf); |
| if (retbuf != NULL) |
| { |
| info->buffer = retbuf; |
| return; |
| } |
| |
| abfd = get_section_bfd_owner (info); |
| gdb_assert (abfd != NULL); |
| |
| if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0 |
| || bfd_bread (buf, info->size, abfd) != info->size) |
| { |
| error (_("Dwarf Error: Can't read DWARF data" |
| " in section %s [in module %s]"), |
| bfd_section_name (sectp), bfd_get_filename (abfd)); |
| } |
| } |
| |
| /* A helper function that returns the size of a section in a safe way. |
| If you are positive that the section has been read before using the |
| size, then it is safe to refer to the dwarf2_section_info object's |
| "size" field directly. In other cases, you must call this |
| function, because for compressed sections the size field is not set |
| correctly until the section has been read. */ |
| |
| static bfd_size_type |
| dwarf2_section_size (struct objfile *objfile, |
| struct dwarf2_section_info *info) |
| { |
| if (!info->readin) |
| dwarf2_read_section (objfile, info); |
| return info->size; |
| } |
| |
| /* 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) |
| { |
| struct dwarf2_per_objfile *data = dwarf2_objfile_data_key.get (objfile); |
| struct dwarf2_section_info *info; |
| |
| /* We may see an objfile without any DWARF, in which case we just |
| return nothing. */ |
| if (data == NULL) |
| { |
| *sectp = NULL; |
| *bufp = NULL; |
| *sizep = 0; |
| return; |
| } |
| switch (sect) |
| { |
| case DWARF2_DEBUG_FRAME: |
| info = &data->frame; |
| break; |
| case DWARF2_EH_FRAME: |
| info = &data->eh_frame; |
| break; |
| default: |
| gdb_assert_not_reached ("unexpected section"); |
| } |
| |
| dwarf2_read_section (objfile, info); |
| |
| *sectp = get_section_bfd_section (info); |
| *bufp = info->buffer; |
| *sizep = info->size; |
| } |
| |
| /* A helper function to find the sections for a .dwz file. */ |
| |
| static void |
| locate_dwz_sections (bfd *abfd, asection *sectp, void *arg) |
| { |
| struct dwz_file *dwz_file = (struct dwz_file *) arg; |
| |
| /* Note that we only support the standard ELF names, because .dwz |
| is ELF-only (at the time of writing). */ |
| if (section_is_p (sectp->name, &dwarf2_elf_names.abbrev)) |
| { |
| dwz_file->abbrev.s.section = sectp; |
| dwz_file->abbrev.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &dwarf2_elf_names.info)) |
| { |
| dwz_file->info.s.section = sectp; |
| dwz_file->info.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &dwarf2_elf_names.str)) |
| { |
| dwz_file->str.s.section = sectp; |
| dwz_file->str.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &dwarf2_elf_names.line)) |
| { |
| dwz_file->line.s.section = sectp; |
| dwz_file->line.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &dwarf2_elf_names.macro)) |
| { |
| dwz_file->macro.s.section = sectp; |
| dwz_file->macro.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &dwarf2_elf_names.gdb_index)) |
| { |
| dwz_file->gdb_index.s.section = sectp; |
| dwz_file->gdb_index.size = bfd_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &dwarf2_elf_names.debug_names)) |
| { |
| dwz_file->debug_names.s.section = sectp; |
| dwz_file->debug_names.size = bfd_section_size (sectp); |
| } |
| } |
| |
| /* See dwarf2read.h. */ |
| |
| struct dwz_file * |
| dwarf2_get_dwz_file (struct dwarf2_per_objfile *dwarf2_per_objfile) |
| { |
| const char *filename; |
| bfd_size_type buildid_len_arg; |
| size_t buildid_len; |
| bfd_byte *buildid; |
| |
| if (dwarf2_per_objfile->dwz_file != NULL) |
| return dwarf2_per_objfile->dwz_file.get (); |
| |
| bfd_set_error (bfd_error_no_error); |
| gdb::unique_xmalloc_ptr<char> data |
| (bfd_get_alt_debug_link_info (dwarf2_per_objfile->objfile->obfd, |
| &buildid_len_arg, &buildid)); |
| if (data == NULL) |
| { |
| if (bfd_get_error () == bfd_error_no_error) |
| return NULL; |
| error (_("could not read '.gnu_debugaltlink' section: %s"), |
| bfd_errmsg (bfd_get_error ())); |
| } |
| |
| gdb::unique_xmalloc_ptr<bfd_byte> buildid_holder (buildid); |
| |
| buildid_len = (size_t) buildid_len_arg; |
| |
| filename = data.get (); |
| |
| std::string abs_storage; |
| if (!IS_ABSOLUTE_PATH (filename)) |
| { |
| gdb::unique_xmalloc_ptr<char> abs |
| = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile)); |
| |
| abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename; |
| filename = abs_storage.c_str (); |
| } |
| |
| /* First try the file name given in the section. If that doesn't |
| work, try to use the build-id instead. */ |
| gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget, -1)); |
| if (dwz_bfd != NULL) |
| { |
| if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid)) |
| dwz_bfd.reset (nullptr); |
| } |
| |
| if (dwz_bfd == NULL) |
| dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid); |
| |
| if (dwz_bfd == NULL) |
| error (_("could not find '.gnu_debugaltlink' file for %s"), |
| objfile_name (dwarf2_per_objfile->objfile)); |
| |
| std::unique_ptr<struct dwz_file> result |
| (new struct dwz_file (std::move (dwz_bfd))); |
| |
| bfd_map_over_sections (result->dwz_bfd.get (), locate_dwz_sections, |
| result.get ()); |
| |
| gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, |
| result->dwz_bfd.get ()); |
| dwarf2_per_objfile->dwz_file = std::move (result); |
| return dwarf2_per_objfile->dwz_file.get (); |
| } |
| |
| /* DWARF quick_symbols_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 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->quick_file_names_table. */ |
| struct quick_file_names *file_names; |
| |
| /* The corresponding symbol table. This is NULL if symbols for this |
| CU have not yet been read. */ |
| struct compunit_symtab *compunit_symtab; |
| |
| /* 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 and found there isn't one. |
| There will be no point in trying to read it again next time. */ |
| unsigned int no_file_data : 1; |
| }; |
| |
| /* 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); |
| } |
| |
| /* Delete function for a quick_file_names. */ |
| |
| static void |
| delete_file_name_entry (void *e) |
| { |
| struct quick_file_names *file_data = (struct quick_file_names *) e; |
| int i; |
| |
| for (i = 0; i < file_data->num_file_names; ++i) |
| { |
| xfree ((void*) file_data->file_names[i]); |
| if (file_data->real_names) |
| xfree ((void*) file_data->real_names[i]); |
| } |
| |
| /* The space for the struct itself lives on objfile_obstack, |
| so we don't free it here. */ |
| } |
| |
| /* Create a quick_file_names hash table. */ |
| |
| static htab_t |
| create_quick_file_names_table (unsigned int nr_initial_entries) |
| { |
| return htab_create_alloc (nr_initial_entries, |
| hash_file_name_entry, eq_file_name_entry, |
| delete_file_name_entry, xcalloc, xfree); |
| } |
| |
| /* Read in PER_CU->CU. This function is unrelated to symtabs, symtab would |
| have to be created afterwards. You should call age_cached_comp_units after |
| processing PER_CU->CU. dw2_setup must have been already called. */ |
| |
| static void |
| load_cu (struct dwarf2_per_cu_data *per_cu, bool skip_partial) |
| { |
| if (per_cu->is_debug_types) |
| load_full_type_unit (per_cu); |
| else |
| load_full_comp_unit (per_cu, skip_partial, language_minimal); |
| |
| if (per_cu->cu == NULL) |
| return; /* Dummy CU. */ |
| |
| dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu); |
| } |
| |
| /* Read in the symbols for PER_CU. */ |
| |
| static void |
| dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu, bool skip_partial) |
| { |
| struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile; |
| |
| /* Skip type_unit_groups, reading the type units they contain |
| is handled elsewhere. */ |
| if (IS_TYPE_UNIT_GROUP (per_cu)) |
| 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; |
| |
| if (dwarf2_per_objfile->using_index |
| ? per_cu->v.quick->compunit_symtab == NULL |
| : (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin)) |
| { |
| queue_comp_unit (per_cu, language_minimal); |
| load_cu (per_cu, 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 |
| && per_cu->cu != NULL |
| && per_cu->cu->dwo_unit != NULL |
| && dwarf2_per_objfile->index_table != NULL |
| && dwarf2_per_objfile->index_table->version <= 7 |
| /* DWP files aren't supported yet. */ |
| && get_dwp_file (dwarf2_per_objfile) == NULL) |
| queue_and_load_all_dwo_tus (per_cu); |
| } |
| |
| process_queue (dwarf2_per_objfile); |
| |
| /* Age the cache, releasing compilation units that have not |
| been used recently. */ |
| age_cached_comp_units (dwarf2_per_objfile); |
| } |
| |
| /* Ensure that the symbols for PER_CU have been read in. OBJFILE is |