| /* DWARF 2 debugging format support for GDB. |
| |
| Copyright (C) 1994-2016 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 "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 "expression.h" |
| #include "filenames.h" /* for DOSish file names */ |
| #include "macrotab.h" |
| #include "language.h" |
| #include "complaints.h" |
| #include "bcache.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 "jv-lang.h" |
| #include "psympriv.h" |
| #include <sys/stat.h> |
| #include "completer.h" |
| #include "vec.h" |
| #include "c-lang.h" |
| #include "go-lang.h" |
| #include "valprint.h" |
| #include "gdbcore.h" /* for gnutarget */ |
| #include "gdb/gdb-index.h" |
| #include <ctype.h> |
| #include "gdb_bfd.h" |
| #include "f-lang.h" |
| #include "source.h" |
| #include "filestuff.h" |
| #include "build-id.h" |
| #include "namespace.h" |
| |
| #include <fcntl.h> |
| #include <sys/types.h> |
| |
| typedef struct symbol *symbolp; |
| DEF_VEC_P (symbolp); |
| |
| /* 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 non-zero, cross-check physname against demangler. */ |
| static int check_physname = 0; |
| |
| /* When non-zero, do not reject deprecated .gdb_index sections. */ |
| static int use_deprecated_index_sections = 0; |
| |
| static const struct objfile_data *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; |
| |
| /* A descriptor for dwarf sections. |
| |
| S.ASECTION, SIZE are typically initialized when the objfile is first |
| scanned. BUFFER, READIN are filled in later when the section is read. |
| If the section contained compressed data then SIZE is updated to record |
| the uncompressed size of the section. |
| |
| DWP file format V2 introduces a wrinkle that is easiest to handle by |
| creating the concept of virtual sections contained within a real section. |
| In DWP V2 the sections of the input DWO files are concatenated together |
| into one section, but section offsets are kept relative to the original |
| input section. |
| If this is a virtual dwp-v2 section, S.CONTAINING_SECTION is a backlink to |
| the real section this "virtual" section is contained in, and BUFFER,SIZE |
| describe the virtual section. */ |
| |
| struct dwarf2_section_info |
| { |
| union |
| { |
| /* If this is a real section, the bfd section. */ |
| asection *section; |
| /* If this is a virtual section, pointer to the containing ("real") |
| section. */ |
| struct dwarf2_section_info *containing_section; |
| } s; |
| /* Pointer to section data, only valid if readin. */ |
| const gdb_byte *buffer; |
| /* The size of the section, real or virtual. */ |
| bfd_size_type size; |
| /* If this is a virtual section, the offset in the real section. |
| Only valid if is_virtual. */ |
| bfd_size_type virtual_offset; |
| /* True if we have tried to read this section. */ |
| char readin; |
| /* True if this is a virtual section, False otherwise. |
| This specifies which of s.section and s.containing_section to use. */ |
| char is_virtual; |
| }; |
| |
| typedef struct dwarf2_section_info dwarf2_section_info_def; |
| DEF_VEC_O (dwarf2_section_info_def); |
| |
| /* All offsets in the index are of this type. It must be |
| architecture-independent. */ |
| typedef uint32_t offset_type; |
| |
| DEF_VEC_I (offset_type); |
| |
| /* Ensure only legit values are used. */ |
| #define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \ |
| do { \ |
| gdb_assert ((unsigned int) (value) <= 1); \ |
| GDB_INDEX_SYMBOL_STATIC_SET_VALUE((cu_index), (value)); \ |
| } while (0) |
| |
| /* Ensure only legit values are used. */ |
| #define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \ |
| do { \ |
| gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \ |
| && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \ |
| GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \ |
| } while (0) |
| |
| /* Ensure we don't use more than the alloted nuber of bits for the CU. */ |
| #define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value) \ |
| do { \ |
| gdb_assert (((value) & ~GDB_INDEX_CU_MASK) == 0); \ |
| GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \ |
| } while (0) |
| |
| /* A description of the mapped index. The file format is described in |
| a comment by the code that writes the index. */ |
| struct mapped_index |
| { |
| /* Index data format version. */ |
| int version; |
| |
| /* The total length of the buffer. */ |
| off_t total_size; |
| |
| /* A pointer to the address table data. */ |
| const gdb_byte *address_table; |
| |
| /* Size of the address table data in bytes. */ |
| offset_type address_table_size; |
| |
| /* The symbol table, implemented as a hash table. */ |
| const offset_type *symbol_table; |
| |
| /* Size in slots, each slot is 2 offset_types. */ |
| offset_type symbol_table_slots; |
| |
| /* A pointer to the constant pool. */ |
| const char *constant_pool; |
| }; |
| |
| typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr; |
| DEF_VEC_P (dwarf2_per_cu_ptr); |
| |
| struct tu_stats |
| { |
| int nr_uniq_abbrev_tables; |
| int nr_symtabs; |
| int nr_symtab_sharers; |
| int nr_stmt_less_type_units; |
| int nr_all_type_units_reallocs; |
| }; |
| |
| /* Collection of data recorded per objfile. |
| This hangs off of dwarf2_objfile_data_key. */ |
| |
| struct dwarf2_per_objfile |
| { |
| struct dwarf2_section_info info; |
| 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; |
| struct dwarf2_section_info ranges; |
| struct dwarf2_section_info addr; |
| struct dwarf2_section_info frame; |
| struct dwarf2_section_info eh_frame; |
| struct dwarf2_section_info gdb_index; |
| |
| VEC (dwarf2_section_info_def) *types; |
| |
| /* Back link. */ |
| struct objfile *objfile; |
| |
| /* Table of all the compilation units. This is used to locate |
| the target compilation unit of a particular reference. */ |
| struct dwarf2_per_cu_data **all_comp_units; |
| |
| /* The number of compilation units in ALL_COMP_UNITS. */ |
| int n_comp_units; |
| |
| /* The number of .debug_types-related CUs. */ |
| int n_type_units; |
| |
| /* The number of elements allocated in all_type_units. |
| If there are skeleton-less TUs, we add them to all_type_units lazily. */ |
| int n_allocated_type_units; |
| |
| /* The .debug_types-related CUs (TUs). |
| This is stored in malloc space because we may realloc it. */ |
| struct signatured_type **all_type_units; |
| |
| /* Table of struct type_unit_group objects. |
| The hash key is the DW_AT_stmt_list value. */ |
| htab_t type_unit_groups; |
| |
| /* A table mapping .debug_types signatures to its signatured_type entry. |
| This is NULL if the .debug_types section hasn't been read in yet. */ |
| htab_t signatured_types; |
| |
| /* Type unit statistics, to see how well the scaling improvements |
| are doing. */ |
| struct tu_stats tu_stats; |
| |
| /* A chain of compilation units that are currently read in, so that |
| they can be freed later. */ |
| struct dwarf2_per_cu_data *read_in_chain; |
| |
| /* A table mapping DW_AT_dwo_name values to struct dwo_file objects. |
| This is NULL if the table hasn't been allocated yet. */ |
| htab_t dwo_files; |
| |
| /* Non-zero if we've check for whether there is a DWP file. */ |
| int dwp_checked; |
| |
| /* The DWP file if there is one, or NULL. */ |
| struct dwp_file *dwp_file; |
| |
| /* The shared '.dwz' file, if one exists. This is used when the |
| original data was compressed using 'dwz -m'. */ |
| struct dwz_file *dwz_file; |
| |
| /* A flag indicating wether this objfile has a section loaded at a |
| VMA of 0. */ |
| int has_section_at_zero; |
| |
| /* True if we are using the mapped index, |
| or we are faking it for OBJF_READNOW's sake. */ |
| unsigned char using_index; |
| |
| /* The mapped index, or NULL if .gdb_index is missing or not being used. */ |
| struct mapped_index *index_table; |
| |
| /* When using index_table, this keeps track of all quick_file_names entries. |
| TUs typically share line table entries with a CU, so we maintain a |
| separate table of all line table entries to support the sharing. |
| Note that while there can be way more TUs than CUs, we've already |
| sorted all the TUs into "type unit groups", grouped by their |
| DW_AT_stmt_list value. Therefore the only sharing done here is with a |
| CU and its associated TU group if there is one. */ |
| htab_t quick_file_names_table; |
| |
| /* Set during partial symbol reading, to prevent queueing of full |
| symbols. */ |
| int reading_partial_symbols; |
| |
| /* Table mapping type DIEs to their struct type *. |
| This is NULL if not allocated yet. |
| The mapping is done via (CU/TU + DIE offset) -> type. */ |
| htab_t die_type_hash; |
| |
| /* The CUs we recently read. */ |
| VEC (dwarf2_per_cu_ptr) *just_read_cus; |
| |
| /* Table containing line_header indexed by offset and offset_in_dwz. */ |
| htab_t line_header_hash; |
| }; |
| |
| static struct dwarf2_per_objfile *dwarf2_per_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_macinfo", ".zdebug_macinfo" }, |
| { ".debug_macro", ".zdebug_macro" }, |
| { ".debug_str", ".zdebug_str" }, |
| { ".debug_ranges", ".zdebug_ranges" }, |
| { ".debug_types", ".zdebug_types" }, |
| { ".debug_addr", ".zdebug_addr" }, |
| { ".debug_frame", ".zdebug_frame" }, |
| { ".eh_frame", NULL }, |
| { ".gdb_index", ".zgdb_index" }, |
| 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 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_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_offset; |
| |
| /* 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; |
| |
| /* Offset to the first byte of this compilation unit header in the |
| .debug_info section, for resolving relative reference dies. */ |
| sect_offset offset; |
| |
| /* 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_offset; |
| }; |
| |
| /* 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; |
| }; |
| |
| typedef struct delayed_method_info delayed_method_info; |
| DEF_VEC_O (delayed_method_info); |
| |
| /* Internal state when decoding a particular compilation unit. */ |
| struct dwarf2_cu |
| { |
| /* The objfile containing this compilation unit. */ |
| struct objfile *objfile; |
| |
| /* The header of the compilation unit. */ |
| struct comp_unit_head header; |
| |
| /* Base address of this compilation unit. */ |
| CORE_ADDR base_address; |
| |
| /* Non-zero if base_address has been set. */ |
| int base_known; |
| |
| /* The language we are debugging. */ |
| enum language language; |
| const struct language_defn *language_defn; |
| |
| const char *producer; |
| |
| /* 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; |
| |
| /* The abbrev table for this CU. |
| Normally this points to the abbrev table in the objfile. |
| But if DWO_UNIT is non-NULL this is the abbrev table in the DWO file. */ |
| struct abbrev_table *abbrev_table; |
| |
| /* Hash table holding all the loaded partial DIEs |
| with partial_die->offset.SECT_OFF as hash. */ |
| htab_t partial_dies; |
| |
| /* Storage for things with the same lifetime as this read-in compilation |
| unit, including partial DIEs. */ |
| struct 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; |
| |
| /* 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; |
| |
| /* A hash table of DIE cu_offset for following references with |
| die_info->offset.sect_off as hash. */ |
| htab_t die_hash; |
| |
| /* Full DIEs if read in. */ |
| struct die_info *dies; |
| |
| /* 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; |
| |
| /* Header data from the line table, during full symbol processing. */ |
| struct line_header *line_header; |
| |
| /* A list of methods which need to have physnames computed |
| after all type information has been read. */ |
| VEC (delayed_method_info) *method_list; |
| |
| /* To be copied to symtab->call_site_htab. */ |
| htab_t call_site_htab; |
| |
| /* 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; |
| |
| /* 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; |
| |
| /* 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; |
| |
| /* Mark used when releasing cached dies. */ |
| unsigned int 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. */ |
| unsigned int has_loclist : 1; |
| |
| /* These cache the results for producer_is_* fields. CHECKED_PRODUCER is set |
| 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. */ |
| unsigned int checked_producer : 1; |
| unsigned int producer_is_gxx_lt_4_6 : 1; |
| unsigned int producer_is_gcc_lt_4_3 : 1; |
| unsigned int producer_is_icc : 1; |
| |
| /* When set, 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. */ |
| |
| unsigned int processing_has_namespace_info : 1; |
| }; |
| |
| /* Persistent data held for a compilation unit, even when not |
| processing it. We put a pointer to this structure in the |
| read_symtab_private field of the psymtab. */ |
| |
| struct dwarf2_per_cu_data |
| { |
| /* The start offset and length of this compilation unit. |
| NOTE: Unlike comp_unit_head.length, this length includes |
| initial_length_size. |
| If the DIE refers to a DWO file, this is always of the original die, |
| not the DWO file. */ |
| sect_offset offset; |
| unsigned int length; |
| |
| /* Flag indicating this compilation unit will be read in before |
| any of the current compilation units are processed. */ |
| unsigned int queued : 1; |
| |
| /* This flag will be set when reading partial DIEs if we need to load |
| absolutely all DIEs for this compilation unit, instead of just the ones |
| we think are interesting. It gets set if we look for a DIE in the |
| hash table and don't find it. */ |
| unsigned int load_all_dies : 1; |
| |
| /* Non-zero if this CU is from .debug_types. |
| Struct dwarf2_per_cu_data is contained in struct signatured_type iff |
| this is non-zero. */ |
| unsigned int is_debug_types : 1; |
| |
| /* Non-zero if this CU is from the .dwz file. */ |
| unsigned int is_dwz : 1; |
| |
| /* Non-zero if reading a TU directly from a DWO file, bypassing the stub. |
| This flag is only valid if is_debug_types is true. |
| We can't read a CU directly from a DWO file: There are required |
| attributes in the stub. */ |
| unsigned int reading_dwo_directly : 1; |
| |
| /* Non-zero if the TU has been read. |
| This is used to assist the "Stay in DWO Optimization" for Fission: |
| When reading a DWO, it's faster to read TUs from the DWO instead of |
| fetching them from random other DWOs (due to comdat folding). |
| If the TU has already been read, the optimization is unnecessary |
| (and unwise - we don't want to change where gdb thinks the TU lives |
| "midflight"). |
| This flag is only valid if is_debug_types is true. */ |
| unsigned int tu_read : 1; |
| |
| /* The section this CU/TU lives in. |
| If the DIE refers to a DWO file, this is always the original die, |
| not the DWO file. */ |
| struct dwarf2_section_info *section; |
| |
| /* Set to non-NULL iff this CU is currently loaded. When it gets freed out |
| of the CU cache it gets reset to NULL again. This is left as NULL for |
| dummy CUs (a CU header, but nothing else). */ |
| struct dwarf2_cu *cu; |
| |
| /* The corresponding objfile. |
| Normally we can get the objfile from dwarf2_per_objfile. |
| However we can enter this file with just a "per_cu" handle. */ |
| struct objfile *objfile; |
| |
| /* When dwarf2_per_objfile->using_index is true, the 'quick' field |
| is active. Otherwise, the 'psymtab' field is active. */ |
| union |
| { |
| /* The partial symbol table associated with this compilation unit, |
| or NULL for unread partial units. */ |
| struct partial_symtab *psymtab; |
| |
| /* Data needed by the "quick" functions. */ |
| struct dwarf2_per_cu_quick_data *quick; |
| } v; |
| |
| /* The CUs we import using DW_TAG_imported_unit. This is filled in |
| while reading psymtabs, used to compute the psymtab dependencies, |
| and then cleared. Then it is filled in again while reading full |
| symbols, and only deleted when the objfile is destroyed. |
| |
| This is also used to work around a difference between the way gold |
| generates .gdb_index version <=7 and the way gdb does. Arguably this |
| is a gold bug. For symbols coming from TUs, gold records in the index |
| the CU that includes the TU instead of the TU itself. This breaks |
| dw2_lookup_symbol: It assumes that if the index says symbol X lives |
| in CU/TU Y, then one need only expand Y and a subsequent lookup in Y |
| will find X. Alas TUs live in their own symtab, so after expanding CU Y |
| we need to look in TU Z to find X. Fortunately, this is akin to |
| DW_TAG_imported_unit, so we just use the same mechanism: For |
| .gdb_index version <=7 this also records the TUs that the CU referred |
| to. Concurrently with this change gdb was modified to emit version 8 |
| indices so we only pay a price for gold generated indices. |
| http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */ |
| VEC (dwarf2_per_cu_ptr) *imported_symtabs; |
| }; |
| |
| /* Entry in the signatured_types hash table. */ |
| |
| struct signatured_type |
| { |
| /* The "per_cu" object of this type. |
| This struct is used iff per_cu.is_debug_types. |
| N.B.: This is the first member so that it's easy to convert pointers |
| between them. */ |
| struct dwarf2_per_cu_data per_cu; |
| |
| /* The type's signature. */ |
| ULONGEST signature; |
| |
| /* Offset in the TU of the type's DIE, as read from the TU header. |
| If this TU is a DWO stub and the definition lives in a DWO file |
| (specified by DW_AT_GNU_dwo_name), this value is unusable. */ |
| cu_offset type_offset_in_tu; |
| |
| /* Offset in the section of the type's DIE. |
| If the definition lives in a DWO file, this is the offset in the |
| .debug_types.dwo section. |
| The value is zero until the actual value is known. |
| Zero is otherwise not a valid section offset. */ |
| sect_offset type_offset_in_section; |
| |
| /* Type units are grouped by their DW_AT_stmt_list entry so that they |
| can share them. This points to the containing symtab. */ |
| struct type_unit_group *type_unit_group; |
| |
| /* The type. |
| The first time we encounter this type we fully read it in and install it |
| in the symbol tables. Subsequent times we only need the type. */ |
| struct type *type; |
| |
| /* Containing DWO unit. |
| This field is valid iff per_cu.reading_dwo_directly. */ |
| struct dwo_unit *dwo_unit; |
| }; |
| |
| typedef struct signatured_type *sig_type_ptr; |
| DEF_VEC_P (sig_type_ptr); |
| |
| /* 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_offset; |
| }; |
| |
| /* 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. */ |
| VEC (sig_type_ptr) *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 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; |
| VEC (dwarf2_section_info_def) *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:{offset,length} but in the DWO section. */ |
| sect_offset offset; |
| 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 |
| { |
| /* 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; |
| |
| /* The DW_AT_comp_dir attribute. */ |
| const char *comp_dir; |
| |
| /* 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. */ |
| bfd *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 CU in the file. |
| We only support one because having more than one requires hacking the |
| dwo_name of each to match, which is highly unlikely to happen. |
| Doing this means all TUs can share comp_dir: We also assume that |
| DW_AT_comp_dir across all TUs in a DWO file will be identical. */ |
| struct dwo_unit *cu; |
| |
| /* 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 |
| { |
| /* Name of the file. */ |
| const char *name; |
| |
| /* File format version. */ |
| int version; |
| |
| /* The bfd. */ |
| bfd *dbfd; |
| |
| /* Section info for this file. */ |
| struct dwp_sections sections; |
| |
| /* Table of CUs in the file. */ |
| const struct dwp_hash_table *cus; |
| |
| /* Table of TUs in the file. */ |
| const struct dwp_hash_table *tus; |
| |
| /* 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; |
| asection **elf_sections; |
| }; |
| |
| /* This represents a '.dwz' file. */ |
| |
| struct dwz_file |
| { |
| /* A dwz file can only contain a few sections. */ |
| struct dwarf2_section_info abbrev; |
| struct dwarf2_section_info info; |
| struct dwarf2_section_info str; |
| struct dwarf2_section_info line; |
| struct dwarf2_section_info macro; |
| struct dwarf2_section_info gdb_index; |
| |
| /* The dwz's BFD. */ |
| bfd *dwz_bfd; |
| }; |
| |
| /* 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; |
| }; |
| |
| /* 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); |
| |
| struct file_entry |
| { |
| const char *name; |
| unsigned int dir_index; |
| unsigned int mod_time; |
| unsigned int length; |
| /* Non-zero if referenced by the Line Number Program. */ |
| int 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 |
| { |
| /* Offset of line number information in .debug_line section. */ |
| sect_offset offset; |
| |
| /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile. */ |
| unsigned offset_in_dwz : 1; |
| |
| 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]. */ |
| unsigned char *standard_opcode_lengths; |
| |
| /* The include_directories table. NOTE! These strings are not |
| allocated with xmalloc; instead, they are pointers into |
| debug_line_buffer. If you try to free them, `free' will get |
| indigestion. */ |
| unsigned int num_include_dirs, include_dirs_size; |
| const char **include_dirs; |
| |
| /* The file_names table. NOTE! These strings are not allocated |
| with xmalloc; instead, they are pointers into debug_line_buffer. |
| Don't try to free them directly. */ |
| unsigned int num_file_names, file_names_size; |
| struct file_entry *file_names; |
| |
| /* 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; |
| }; |
| |
| /* When we construct a partial symbol table entry we only |
| need this much information. */ |
| struct partial_die_info |
| { |
| /* Offset of this DIE. */ |
| sect_offset offset; |
| |
| /* DWARF-2 tag for this DIE. */ |
| ENUM_BITFIELD(dwarf_tag) tag : 16; |
| |
| /* Assorted flags describing the data found in this DIE. */ |
| 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; |
| |
| /* 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_partial_die 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; |
| |
| /* The linkage name, if present. */ |
| const char *linkage_name; |
| |
| /* 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; |
| |
| /* 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 offset; |
| } d; |
| |
| /* If HAS_PC_INFO, the PC range associated with this DIE. */ |
| CORE_ADDR lowpc; |
| CORE_ADDR highpc; |
| |
| /* 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, read_partial_die could |
| return DW_AT_sibling values to its caller load_partial_dies. */ |
| const gdb_byte *sibling; |
| |
| /* 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, *die_child, *die_sibling; |
| }; |
| |
| /* 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; |
| }; |
| |
| /* Size of abbrev_table.abbrev_hash_table. */ |
| #define ABBREV_HASH_SIZE 121 |
| |
| /* Top level data structure to contain an abbreviation table. */ |
| |
| struct abbrev_table |
| { |
| /* Where the abbrev table came from. |
| This is used as a sanity check when the table is used. */ |
| sect_offset offset; |
| |
| /* Storage for the abbrev table. */ |
| struct obstack abbrev_obstack; |
| |
| /* 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 **abbrevs; |
| }; |
| |
| /* 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 offset; |
| |
| /* 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; |
| |
| struct nextfield |
| { |
| struct nextfield *next; |
| int accessibility; |
| int virtuality; |
| struct field field; |
| }; |
| |
| struct nextfnfield |
| { |
| struct nextfnfield *next; |
| struct fn_field fnfield; |
| }; |
| |
| struct fnfieldlist |
| { |
| const char *name; |
| int length; |
| struct nextfnfield *head; |
| }; |
| |
| struct typedef_field_list |
| { |
| struct typedef_field field; |
| struct typedef_field_list *next; |
| }; |
| |
| /* 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. */ |
| struct nextfield *fields, *baseclasses; |
| |
| /* Number of fields (including baseclasses). */ |
| int nfields; |
| |
| /* Number of baseclasses. */ |
| int nbaseclasses; |
| |
| /* Set if the accesibility of one of the fields is not public. */ |
| int non_public_fields; |
| |
| /* Member function fields array, entries are allocated in the order they |
| are encountered in the object file. */ |
| struct nextfnfield *fnfields; |
| |
| /* 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. */ |
| struct fnfieldlist *fnfieldlists; |
| |
| /* Number of entries in the fnfieldlists array. */ |
| int nfnfields; |
| |
| /* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of |
| a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */ |
| struct typedef_field_list *typedef_field_list; |
| unsigned typedef_field_list_count; |
| }; |
| |
| /* 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_locate_sections (bfd *, asection *, void *); |
| |
| 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 dwarf2_build_psymtabs_hard (struct 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 struct abbrev_info *abbrev_table_lookup_abbrev |
| (const struct abbrev_table *, unsigned int); |
| |
| static struct abbrev_table *abbrev_table_read_table |
| (struct dwarf2_section_info *, sect_offset); |
| |
| static void abbrev_table_free (struct abbrev_table *); |
| |
| static void abbrev_table_free_cleanup (void *); |
| |
| static void dwarf2_read_abbrevs (struct dwarf2_cu *, |
| struct dwarf2_section_info *); |
| |
| static void dwarf2_free_abbrev_table (void *); |
| |
| 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); |
| |
| static const gdb_byte *read_partial_die (const struct die_reader_specs *, |
| struct partial_die_info *, |
| struct abbrev_info *, |
| unsigned int, |
| const gdb_byte *); |
| |
| static struct partial_die_info *find_partial_die (sect_offset, int, |
| struct dwarf2_cu *); |
| |
| static void fixup_partial_die (struct partial_die_info *, |
| 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 *); |
| |
| 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_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 (bfd *, const gdb_byte *, |
| const struct comp_unit_head *, |
| unsigned int *); |
| |
| static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST); |
| |
| static ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *); |
| |
| 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 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 void free_line_header (struct line_header *lh); |
| |
| static struct line_header *dwarf_decode_line_header (unsigned int offset, |
| 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 (const char *, const char *); |
| |
| static struct compunit_symtab *dwarf2_start_symtab (struct dwarf2_cu *, |
| const char *, const char *, |
| CORE_ADDR); |
| |
| static struct symbol *new_symbol (struct die_info *, struct type *, |
| struct dwarf2_cu *); |
| |
| static struct symbol *new_symbol_full (struct die_info *, struct type *, |
| struct dwarf2_cu *, struct symbol *); |
| |
| 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 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 (enum language); |
| |
| 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_form_name (unsigned int); |
| |
| static 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); |
| |
| /* 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 void free_stack_comp_unit (void *); |
| |
| 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 offset, unsigned int offset_in_dwz, struct objfile *objfile); |
| |
| static void init_one_comp_unit (struct dwarf2_cu *cu, |
| struct dwarf2_per_cu_data *per_cu); |
| |
| static void prepare_one_comp_unit (struct dwarf2_cu *cu, |
| struct die_info *comp_unit_die, |
| enum language pretend_language); |
| |
| static void free_heap_comp_unit (void *); |
| |
| static void free_cached_comp_units (void *); |
| |
| static void age_cached_comp_units (void); |
| |
| 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 objfile *); |
| |
| static int create_all_type_units (struct objfile *); |
| |
| static void load_full_comp_unit (struct dwarf2_per_cu_data *, |
| 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 dwarf2_release_queue (void *dummy); |
| |
| static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, |
| enum language pretend_language); |
| |
| static void process_queue (void); |
| |
| static void find_file_and_directory (struct die_info *die, |
| struct dwarf2_cu *cu, |
| const char **name, const char **comp_dir); |
| |
| static char *file_full_name (int file, struct line_header *lh, |
| const char *comp_dir); |
| |
| static const gdb_byte *read_and_check_comp_unit_head |
| (struct comp_unit_head *header, |
| struct dwarf2_section_info *section, |
| struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr, |
| int is_debug_types_section); |
| |
| 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, |
| 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 dwp_file *dwp_file, const char *comp_dir, |
| ULONGEST signature, int is_debug_types); |
| |
| static struct dwp_file *get_dwp_file (void); |
| |
| 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 *); |
| |
| static void free_dwo_file_cleanup (void *); |
| |
| static void process_cu_includes (void); |
| |
| 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 (&symfile_complaints, |
| _("statement list doesn't fit in .debug_line section")); |
| } |
| |
| static void |
| dwarf2_debug_line_missing_file_complaint (void) |
| { |
| complaint (&symfile_complaints, |
| _(".debug_line section has line data without a file")); |
| } |
| |
| static void |
| dwarf2_debug_line_missing_end_sequence_complaint (void) |
| { |
| complaint (&symfile_complaints, |
| _(".debug_line section has line " |
| "program sequence without an end")); |
| } |
| |
| static void |
| dwarf2_complex_location_expr_complaint (void) |
| { |
| complaint (&symfile_complaints, _("location expression too complex")); |
| } |
| |
| static void |
| dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2, |
| int arg3) |
| { |
| complaint (&symfile_complaints, |
| _("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 (&symfile_complaints, |
| _("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 (&symfile_complaints, |
| _("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 (&symfile_complaints, |
| _("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 ofs->offset.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->offset.sect_off == ofs_rhs->offset.sect_off |
| && ofs_lhs->offset_in_dwz == ofs_rhs->offset_in_dwz); |
| } |
| |
| |
| #if WORDS_BIGENDIAN |
| |
| /* Convert VALUE between big- and little-endian. */ |
| static offset_type |
| byte_swap (offset_type value) |
| { |
| offset_type result; |
| |
| result = (value & 0xff) << 24; |
| result |= (value & 0xff00) << 8; |
| result |= (value & 0xff0000) >> 8; |
| result |= (value & 0xff000000) >> 24; |
| return result; |
| } |
| |
| #define MAYBE_SWAP(V) byte_swap (V) |
| |
| #else |
| #define MAYBE_SWAP(V) (V) |
| #endif /* WORDS_BIGENDIAN */ |
| |
| /* 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_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; |
| } |
| |
| /* The suffix for an index file. */ |
| #define INDEX_SUFFIX ".gdb-index" |
| |
| /* 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. */ |
| |
| int |
| dwarf2_has_info (struct objfile *objfile, |
| const struct dwarf2_debug_sections *names) |
| { |
| dwarf2_per_objfile = ((struct dwarf2_per_objfile *) |
| objfile_data (objfile, dwarf2_objfile_data_key)); |
| if (!dwarf2_per_objfile) |
| { |
| /* Initialize per-objfile state. */ |
| struct dwarf2_per_objfile *data |
| = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_objfile); |
| |
| memset (data, 0, sizeof (*data)); |
| set_objfile_data (objfile, dwarf2_objfile_data_key, data); |
| dwarf2_per_objfile = data; |
| |
| bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, |
| (void *) names); |
| dwarf2_per_objfile->objfile = objfile; |
| } |
| 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 (get_section_bfd_owner (section), 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_get_section_flags (sectp->owner, 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; |
| } |
| |
| /* This function is mapped across the sections and remembers the |
| offset and size of each of the debugging sections we are interested |
| in. */ |
| |
| static void |
| dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames) |
| { |
| const struct dwarf2_debug_sections *names; |
| flagword aflag = bfd_get_section_flags (abfd, sectp); |
| |
| if (vnames == NULL) |
| names = &dwarf2_elf_names; |
| else |
| names = (const struct dwarf2_debug_sections *) vnames; |
| |
| if ((aflag & SEC_HAS_CONTENTS) == 0) |
| { |
| } |
| else if (section_is_p (sectp->name, &names->info)) |
| { |
| dwarf2_per_objfile->info.s.section = sectp; |
| dwarf2_per_objfile->info.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->abbrev)) |
| { |
| dwarf2_per_objfile->abbrev.s.section = sectp; |
| dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->line)) |
| { |
| dwarf2_per_objfile->line.s.section = sectp; |
| dwarf2_per_objfile->line.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->loc)) |
| { |
| dwarf2_per_objfile->loc.s.section = sectp; |
| dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->macinfo)) |
| { |
| dwarf2_per_objfile->macinfo.s.section = sectp; |
| dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->macro)) |
| { |
| dwarf2_per_objfile->macro.s.section = sectp; |
| dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->str)) |
| { |
| dwarf2_per_objfile->str.s.section = sectp; |
| dwarf2_per_objfile->str.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->addr)) |
| { |
| dwarf2_per_objfile->addr.s.section = sectp; |
| dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->frame)) |
| { |
| dwarf2_per_objfile->frame.s.section = sectp; |
| dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->eh_frame)) |
| { |
| dwarf2_per_objfile->eh_frame.s.section = sectp; |
| dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp); |
| } |
| else if (section_is_p (sectp->name, &names->ranges)) |
| { |
| dwarf2_per_objfile->ranges.s.section = sectp; |
| dwarf2_per_objfile->ranges.size = bfd_get_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_get_section_size (sectp); |
| |
| VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types, |
| &type_section); |
| } |
| else if (section_is_p (sectp->name, &names->gdb_index)) |
| { |
| dwarf2_per_objfile->gdb_index.s.section = sectp; |
| dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp); |
| } |
| |
| if ((bfd_get_section_flags (abfd, sectp) & (SEC_LOAD | SEC_ALLOC)) |
| && bfd_section_vma (abfd, sectp) == 0) |
| dwarf2_per_objfile->has_section_at_zero = 1; |
| } |
| |
| /* 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; |
| } |
| |
| /* Read the contents of the section INFO. |
| OBJFILE is the main object file, but not necessarily the file where |
| the section comes from. E.g., for DWO files the bfd of INFO is the bfd |
| of the DWO file. |
| If the section is compressed, uncompress it before returning. */ |
| |
| static void |
| dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) |
| { |
| asection *sectp; |
| bfd *abfd; |
| gdb_byte *buf, *retbuf; |
| |
| if (info->readin) |
| return; |
| info->buffer = NULL; |
| info->readin = 1; |
| |
| 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 (abfd, 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 |
| = (struct dwarf2_per_objfile *) objfile_data (objfile, |
| dwarf2_objfile_data_key); |
| 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_get_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_get_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_get_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_get_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_get_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_get_section_size (sectp); |
| } |
| } |
| |
| /* Open the separate '.dwz' debug file, if needed. Return NULL if |
| there is no .gnu_debugaltlink section in the file. Error if there |
| is such a section but the file cannot be found. */ |
| |
| static struct dwz_file * |
| dwarf2_get_dwz_file (void) |
| { |
| bfd *dwz_bfd; |
| char *data; |
| struct cleanup *cleanup; |
| const char *filename; |
| struct dwz_file *result; |
| 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; |
| |
| bfd_set_error (bfd_error_no_error); |
| 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 ())); |
| } |
| cleanup = make_cleanup (xfree, data); |
| make_cleanup (xfree, buildid); |
| |
| buildid_len = (size_t) buildid_len_arg; |
| |
| filename = (const char *) data; |
| if (!IS_ABSOLUTE_PATH (filename)) |
| { |
| char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile)); |
| char *rel; |
| |
| make_cleanup (xfree, abs); |
| abs = ldirname (abs); |
| make_cleanup (xfree, abs); |
| |
| rel = concat (abs, SLASH_STRING, filename, (char *) NULL); |
| make_cleanup (xfree, rel); |
| filename = rel; |
| } |
| |
| /* First try the file name given in the section. If that doesn't |
| work, try to use the build-id instead. */ |
| dwz_bfd = gdb_bfd_open (filename, gnutarget, -1); |
| if (dwz_bfd != NULL) |
| { |
| if (!build_id_verify (dwz_bfd, buildid_len, buildid)) |
| { |
| gdb_bfd_unref (dwz_bfd); |
| dwz_bfd = NULL; |
| } |
| } |
| |
| 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)); |
| |
| result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack, |
| struct dwz_file); |
| result->dwz_bfd = dwz_bfd; |
| |
| bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result); |
| |
| do_cleanups (cleanup); |
| |
| gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd); |
| dwarf2_per_objfile->dwz_file = result; |
| return result; |
| } |
| |
| /* 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 += stmt_list_hash->line_offset.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_offset.sect_off == rhs->line_offset.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) |
| { |
| if (per_cu->is_debug_types) |
| load_full_type_unit (per_cu); |
| else |
| load_full_comp_unit (per_cu, 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) |
| { |
| struct cleanup *back_to; |
| |
| /* Skip type_unit_groups, reading the type units they contain |
| is handled elsewhere. */ |
| if (IS_TYPE_UNIT_GROUP (per_cu)) |
| return; |
| |
| back_to = make_cleanup (dwarf2_release_queue, NULL); |
| |
| 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); |
| |
| /* 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 () == NULL) |
| queue_and_load_all_dwo_tus (per_cu); |
| } |
| |
| process_queue (); |
| |
| /* Age the cache, releasing compilation units that have not |
| been used recently. */ |
| age_cached_comp_units (); |
| |
| do_cleanups (back_to); |
| } |
| |
| /* Ensure that the symbols for PER_CU have been read in. OBJFILE is |
| the objfile from which this CU came. Returns the resulting symbol |
| table. */ |
| |
| static struct compunit_symtab * |
| dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu) |
| { |
| gdb_assert (dwarf2_per_objfile->using_index); |
| if (!per_cu->v.quick->compunit_symtab) |
| { |
| struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL); |
| increment_reading_symtab (); |
| dw2_do_instantiate_symtab (per_cu); |
| process_cu_includes (); |
| do_cleanups (back_to); |
| } |
| |
| return per_cu->v.quick->compunit_symtab; |
| } |
| |
| /* Return the CU/TU given its index. |
| |
| This is intended for loops like: |
| |
| for (i = 0; i < (dwarf2_per_objfile->n_comp_units |
| + dwarf2_per_objfile->n_type_units); ++i) |
| { |
| struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i); |
| |
| ...; |
| } |
| */ |
| |
| static struct dwarf2_per_cu_data * |
| dw2_get_cutu (int index) |
| { |
| if (index >= dwarf2_per_objfile->n_comp_units) |
| { |
| index -= dwarf2_per_objfile->n_comp_units; |
| gdb_assert (index < dwarf2_per_objfile->n_type_units); |
| return &dwarf2_per_objfile->all_type_units[index]->per_cu; |
| } |
| |
| return dwarf2_per_objfile->all_comp_units[index]; |
| } |
| |
| /* Return the CU given its index. |
| This differs from dw2_get_cutu in that it's for when you know INDEX |
| refers to a CU. */ |
| |
| static struct dwarf2_per_cu_data * |
| dw2_get_cu (int index) |
| { |
| gdb_assert (index >= 0 && index < dwarf2_per_objfile->n_comp_units); |
| |
| return dwarf2_per_objfile->all_comp_units[index]; |
| } |
| |
| /* A helper for create_cus_from_index that handles a given list of |
| CUs. */ |
| |
| static void |
| create_cus_from_index_list (struct objfile *objfile, |
| const gdb_byte *cu_list, offset_type n_elements, |
| struct dwarf2_section_info *section, |
| int is_dwz, |
| int base_offset) |
| { |
| offset_type i; |
| |
| for (i = 0; i < n_elements; i += 2) |
| { |
| struct dwarf2_per_cu_data *the_cu; |
| ULONGEST offset, length; |
| |
| gdb_static_assert (sizeof (ULONGEST) >= 8); |
| offset = extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE); |
| length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); |
| cu_list += 2 * 8; |
| |
| the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack, |
| struct dwarf2_per_cu_data); |
| the_cu->offset.sect_off = offset; |
| the_cu->length = length; |
| the_cu->objfile = objfile; |
| the_cu->section = section; |
| the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack, |
| struct dwarf2_per_cu_quick_data); |
| the_cu->is_dwz = is_dwz; |
| dwarf2_per_objfile->all_comp_units[base_offset + i / 2] = the_cu; |
| } |
| } |
| |
| /* Read the CU list from the mapped index, and use it to create all |
| the CU objects for this objfile. */ |
| |
| static void |
| create_cus_from_index (struct objfile *objfile, |
| const gdb_byte *cu_list, offset_type cu_list_elements, |
| const gdb_byte *dwz_list, offset_type dwz_elements) |
| { |
| struct dwz_file *dwz; |
| |
| dwarf2_per_objfile->n_comp_units = (cu_list_elements + dwz_elements) / 2; |
| dwarf2_per_objfile->all_comp_units = |
| XOBNEWVEC (&objfile->objfile_obstack, struct dwarf2_per_cu_data *, |
| dwarf2_per_objfile->n_comp_units); |
| |
| create_cus_from_index_list (objfile, cu_list, cu_list_elements, |
| &dwarf2_per_objfile->info, 0, 0); |
| |
| if (dwz_elements == 0) |
| return; |
| |
| dwz = dwarf2_get_dwz_file (); |
| create_cus_from_index_list (objfile, dwz_list, dwz_elements, &dwz->info, 1, |
| cu_list_elements / 2); |
| } |
| |
| /* Create the signatured type hash table from the index. */ |
| |
| static void |
| create_signatured_type_table_from_index (struct objfile *objfile, |
| struct dwarf2_section_info *section, |
| const gdb_byte *bytes, |
| offset_type elements) |
| { |
| offset_type i; |
| htab_t sig_types_hash; |
| |
| dwarf2_per_objfile->n_type_units |
| = dwarf2_per_objfile->n_allocated_type_units |
| = elements / 3; |
| dwarf2_per_objfile->all_type_units = |
| XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units); |
| |
| sig_types_hash = allocate_signatured_type_table (objfile); |
| |
| for (i = 0; i < elements; i += 3) |
| { |
| struct signatured_type *sig_type; |
| ULONGEST offset, type_offset_in_tu, signature; |
| void **slot; |
| |
| gdb_static_assert (sizeof (ULONGEST) >= 8); |
| offset = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); |
| type_offset_in_tu = extract_unsigned_integer (bytes + 8, 8, |
| BFD_ENDIAN_LITTLE); |
| signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE); |
| bytes += 3 * 8; |
| |
| sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack, |
| struct signatured_type); |
| sig_type->signature = signature; |
| sig_type->type_offset_in_tu.cu_off = type_offset_in_tu; |
| sig_type->per_cu.is_debug_types = 1; |
| sig_type->per_cu.section = section; |
| sig_type->per_cu.offset.sect_off = offset; |
| sig_type->per_cu.objfile = objfile; |
| sig_type->per_cu.v.quick |
| = OBSTACK_ZALLOC (&objfile->objfile_obstack, |
| struct dwarf2_per_cu_quick_data); |
| |
| slot = htab_find_slot (sig_types_hash, sig_type, INSERT); |
| *slot = sig_type; |
| |
| dwarf2_per_objfile->all_type_units[i / 3] = sig_type; |
| } |
| |
| dwarf2_per_objfile->signatured_types = sig_types_hash; |
| } |
| |
| /* Read the address map data from the mapped index, and use it to |
| populate the objfile's psymtabs_addrmap. */ |
| |
| static void |
| create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index) |
| { |
| struct gdbarch *gdbarch = get_objfile_arch (objfile); |
| const gdb_byte *iter, *end; |
| struct obstack temp_obstack; |
| struct addrmap *mutable_map; |
| struct cleanup *cleanup; |
| CORE_ADDR baseaddr; |
| |
| obstack_init (&temp_obstack); |
| cleanup = make_cleanup_obstack_free (&temp_obstack); |
| mutable_map = addrmap_create_mutable (&temp_obstack); |
| |
| iter = index->address_table; |
| end = iter + index->address_table_size; |
| |
| baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); |
| |
| while (iter < end) |
| { |
| ULONGEST hi, lo, cu_index; |
| lo = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); |
| iter += 8; |
| hi = extract_unsigned_integer (iter, 8, BFD_ENDIAN_LITTLE); |
| iter += 8; |
| cu_index = extract_unsigned_integer (iter, 4, BFD_ENDIAN_LITTLE); |
| iter += 4; |
| |
| if (lo > hi) |
| { |
| complaint (&symfile_complaints, |
| _(".gdb_index address table has invalid range (%s - %s)"), |
| hex_string (lo), hex_string (hi)); |
| continue; |
| } |
| |
| if (cu_index >= dwarf2_per_objfile->n_comp_units) |
| { |
| complaint (&symfile_complaints, |
| _(".gdb_index address table has invalid CU number %u"), |
| (unsigned) cu_index); |
| continue; |
| } |
| |
| lo = |