| Index: gdb/dwarf2read.c
|
| diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
|
| index 48b8c08ae63204384fbe563ec2b5626a715945c2..1c7dfc54fbcf122d7bc584ebc68e6d442d3962e1 100644
|
| --- a/gdb/dwarf2read.c
|
| +++ b/gdb/dwarf2read.c
|
| @@ -1,6 +1,6 @@
|
| /* DWARF 2 debugging format support for GDB.
|
|
|
| - Copyright (C) 1994-2012 Free Software Foundation, Inc.
|
| + Copyright (C) 1994-2013 Free Software Foundation, Inc.
|
|
|
| Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
|
| Inc. with support from Florida State University (under contract
|
| @@ -30,6 +30,7 @@
|
|
|
| #include "defs.h"
|
| #include "bfd.h"
|
| +#include "elf-bfd.h"
|
| #include "symtab.h"
|
| #include "gdbtypes.h"
|
| #include "objfiles.h"
|
| @@ -55,7 +56,7 @@
|
| #include "jv-lang.h"
|
| #include "psympriv.h"
|
| #include "exceptions.h"
|
| -#include "gdb_stat.h"
|
| +#include <sys/stat.h>
|
| #include "completer.h"
|
| #include "vec.h"
|
| #include "c-lang.h"
|
| @@ -64,30 +65,27 @@
|
| #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 <fcntl.h>
|
| -#include "gdb_string.h"
|
| +#include <string.h>
|
| #include "gdb_assert.h"
|
| #include <sys/types.h>
|
| -#ifdef HAVE_ZLIB_H
|
| -#include <zlib.h>
|
| -#endif
|
| -#ifdef HAVE_MMAP
|
| -#include <sys/mman.h>
|
| -#ifndef MAP_FAILED
|
| -#define MAP_FAILED ((void *) -1)
|
| -#endif
|
| -#endif
|
|
|
| typedef struct symbol *symbolp;
|
| DEF_VEC_P (symbolp);
|
|
|
| -/* When non-zero, print basic high level tracing messages.
|
| +/* When == 1, print basic high level tracing messages.
|
| + When > 1, be more verbose.
|
| This is in contrast to the low level DIE reading of dwarf2_die_debug. */
|
| -static int dwarf2_read_debug = 0;
|
| +static unsigned int dwarf2_read_debug = 0;
|
|
|
| /* When non-zero, dump DIEs after they are read in. */
|
| -static int dwarf2_die_debug = 0;
|
| +static unsigned int dwarf2_die_debug = 0;
|
|
|
| /* When non-zero, cross-check physname against demangler. */
|
| static int check_physname = 0;
|
| @@ -95,27 +93,53 @@ static int check_physname = 0;
|
| /* When non-zero, do not reject deprecated .gdb_index sections. */
|
| static int use_deprecated_index_sections = 0;
|
|
|
| -static int pagesize;
|
| +static const struct objfile_data *dwarf2_objfile_data_key;
|
| +
|
| +/* The "aclass" indices for various kinds of computed DWARF symbols. */
|
|
|
| -/* 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. */
|
| +static int dwarf2_locexpr_index;
|
| +static int dwarf2_loclist_index;
|
| +static int dwarf2_locexpr_block_index;
|
| +static int dwarf2_loclist_block_index;
|
|
|
| -static int processing_has_namespace_info;
|
| +/* A descriptor for dwarf sections.
|
|
|
| -static const struct objfile_data *dwarf2_objfile_data_key;
|
| + 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
|
| {
|
| - asection *asection;
|
| - gdb_byte *buffer;
|
| + union
|
| + {
|
| + /* If this is a real section, the bfd section. */
|
| + asection *asection;
|
| + /* 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;
|
| - /* Not NULL if the section was actually mmapped. */
|
| - void *map_addr;
|
| - /* Page aligned size of mmapped area. */
|
| - bfd_size_type map_len;
|
| + /* 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. */
|
| - int readin;
|
| + char readin;
|
| + /* True if this is a virtual section, False otherwise.
|
| + This specifies which of s.asection and s.containing_section to use. */
|
| + char is_virtual;
|
| };
|
|
|
| typedef struct dwarf2_section_info dwarf2_section_info_def;
|
| @@ -211,7 +235,8 @@ struct dwarf2_per_objfile
|
| /* The number of .debug_types-related CUs. */
|
| int n_type_units;
|
|
|
| - /* The .debug_types-related CUs (TUs). */
|
| + /* The .debug_types-related CUs (TUs).
|
| + This is stored in malloc space because we may realloc it. */
|
| struct signatured_type **all_type_units;
|
|
|
| /* The number of entries in all_type_unit_groups. */
|
| @@ -247,6 +272,16 @@ struct dwarf2_per_objfile
|
| 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;
|
| @@ -259,9 +294,12 @@ struct dwarf2_per_objfile
|
| struct mapped_index *index_table;
|
|
|
| /* When using index_table, this keeps track of all quick_file_names entries.
|
| - TUs can share line table entries with CUs or other TUs, and there can be
|
| - a lot more TUs than unique line tables, so we maintain a separate table
|
| - of all line table entries to support the sharing. */
|
| + 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
|
| @@ -270,7 +308,7 @@ struct dwarf2_per_objfile
|
|
|
| /* Table mapping type DIEs to their struct type *.
|
| This is NULL if not allocated yet.
|
| - The mapping is done via (CU/TU signature + DIE offset) -> type. */
|
| + The mapping is done via (CU/TU + DIE offset) -> type. */
|
| htab_t die_type_hash;
|
|
|
| /* The CUs we recently read. */
|
| @@ -302,9 +340,9 @@ static const struct dwarf2_debug_sections dwarf2_elf_names =
|
| 23
|
| };
|
|
|
| -/* List of DWO sections. */
|
| +/* List of DWO/DWP sections. */
|
|
|
| -static const struct dwo_section_names
|
| +static const struct dwop_section_names
|
| {
|
| struct dwarf2_section_names abbrev_dwo;
|
| struct dwarf2_section_names info_dwo;
|
| @@ -315,8 +353,10 @@ static const struct dwo_section_names
|
| 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;
|
| }
|
| -dwo_section_names =
|
| +dwop_section_names =
|
| {
|
| { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo" },
|
| { ".debug_info.dwo", ".zdebug_info.dwo" },
|
| @@ -327,6 +367,8 @@ dwo_section_names =
|
| { ".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 */
|
| @@ -430,7 +472,7 @@ struct dwarf2_cu
|
| compilation units are cached... */
|
| struct dwarf2_per_cu_data *read_in_chain;
|
|
|
| - /* Backchain to our per_cu entry if the tree has been built. */
|
| + /* Backlink to our per_cu entry. */
|
| struct dwarf2_per_cu_data *per_cu;
|
|
|
| /* How many compilation units ago was this CU last referenced? */
|
| @@ -478,7 +520,12 @@ struct dwarf2_cu
|
| (zero is a valid value though).
|
| Note this value comes from the 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. */
|
| + 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. */
|
| @@ -490,13 +537,20 @@ struct dwarf2_cu
|
| unoptimized code. For a future better test see GCC PR other/32998. */
|
| unsigned int has_loclist : 1;
|
|
|
| - /* These cache the results for producer_is_gxx_lt_4_6 and producer_is_icc.
|
| - CHECKED_PRODUCER is set if both PRODUCER_IS_GXX_LT_4_6 and PRODUCER_IS_ICC
|
| - are valid. This information is cached because profiling CU expansion
|
| - showed excessive time spent in producer_is_gxx_lt_4_6. */
|
| + /* 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
|
| @@ -505,15 +559,13 @@ struct dwarf2_cu
|
|
|
| struct dwarf2_per_cu_data
|
| {
|
| - /* The start offset and length of this compilation unit. 2**29-1
|
| - bytes should suffice to store the length of any compilation unit
|
| - - if it doesn't, GDB will fall over anyway.
|
| + /* 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 : 29;
|
| + unsigned int length;
|
|
|
| /* Flag indicating this compilation unit will be read in before
|
| any of the current compilation units are processed. */
|
| @@ -525,13 +577,34 @@ struct dwarf2_per_cu_data
|
| hash table and don't find it. */
|
| unsigned int load_all_dies : 1;
|
|
|
| - /* Non-zero if this CU is from .debug_types. */
|
| + /* 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 *info_or_types_section;
|
| + 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. */
|
| @@ -554,19 +627,25 @@ struct dwarf2_per_cu_data
|
| struct dwarf2_per_cu_quick_data *quick;
|
| } v;
|
|
|
| - union
|
| - {
|
| - /* 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. */
|
| - VEC (dwarf2_per_cu_ptr) *imported_symtabs;
|
| -
|
| - /* Type units are grouped by their DW_AT_stmt_list entry so that they
|
| - can share them. If this is a TU, this points to the containing
|
| - symtab. */
|
| - struct type_unit_group *type_unit_group;
|
| - } s;
|
| + /* 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. */
|
| @@ -574,6 +653,7 @@ struct dwarf2_per_cu_data
|
| 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;
|
| @@ -582,7 +662,8 @@ struct signatured_type
|
| ULONGEST signature;
|
|
|
| /* Offset in the TU of the type's DIE, as read from the TU header.
|
| - If the definition lives in a DWO file, this value is unusable. */
|
| + 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.
|
| @@ -591,8 +672,24 @@ struct signatured_type
|
| 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. */
|
|
|
| @@ -610,26 +707,18 @@ struct stmt_list_hash
|
|
|
| struct type_unit_group
|
| {
|
| - /* dwarf2read.c's main "handle" on the symtab.
|
| + /* 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)->info_or_types_section == NULL)
|
| +#define IS_TYPE_UNIT_GROUP(per_cu) ((per_cu)->section == NULL)
|
| struct dwarf2_per_cu_data per_cu;
|
|
|
| - union
|
| - {
|
| - /* 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 (dwarf2_per_cu_ptr) *tus;
|
| -
|
| - /* When reading the line table in "quick" functions, we need a real TU.
|
| - Any will do, we know they all share the same DW_AT_stmt_list entry.
|
| - For simplicity's sake, we pick the first one. */
|
| - struct dwarf2_per_cu_data *first_tu;
|
| - } t;
|
| + /* 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 primary symtab.
|
| Type units in a group needn't all be defined in the same source file,
|
| @@ -654,22 +743,23 @@ struct type_unit_group
|
| struct symtab **symtabs;
|
| };
|
|
|
| -/* These sections are what may appear in a "dwo" file. */
|
| +/* 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 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;
|
| 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;
|
| };
|
|
|
| -/* Common bits of DWO CUs/TUs. */
|
| +/* CUs/TUs in DWP/DWO files. */
|
|
|
| struct dwo_unit
|
| {
|
| @@ -682,9 +772,9 @@ struct dwo_unit
|
| ULONGEST signature;
|
|
|
| /* The section this CU/TU lives in, in the DWO file. */
|
| - struct dwarf2_section_info *info_or_types_section;
|
| + struct dwarf2_section_info *section;
|
|
|
| - /* Same as dwarf2_per_cu_data:{offset,length} but for the DWO section. */
|
| + /* Same as dwarf2_per_cu_data:{offset,length} but in the DWO section. */
|
| sect_offset offset;
|
| unsigned int length;
|
|
|
| @@ -692,29 +782,211 @@ struct dwo_unit
|
| cu_offset type_offset_in_tu;
|
| };
|
|
|
| -/* Data for one DWO file. */
|
| +/* 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.
|
| - We don't manage space for this, it's an 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 bfd, when the file is open. Otherwise this is NULL. */
|
| - bfd *dwo_bfd;
|
| + /* The DW_AT_comp_dir attribute. */
|
| + const char *comp_dir;
|
|
|
| - /* Section info for this file. */
|
| + /* 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;
|
|
|
| - /* Table of CUs in the file.
|
| - Each element is a struct dwo_unit. */
|
| - htab_t cus;
|
| + /* 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
|
| @@ -722,13 +994,13 @@ struct dwo_file
|
|
|
| struct die_reader_specs
|
| {
|
| - /* die_section->asection->owner. */
|
| + /* 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. */
|
| + /* Non-NULL if reading a DWO file (including one packaged into a DWP). */
|
| struct dwo_file *dwo_file;
|
|
|
| /* The section the die comes from.
|
| @@ -736,15 +1008,18 @@ struct die_reader_specs
|
| struct dwarf2_section_info *die_section;
|
|
|
| /* die_section->buffer. */
|
| - gdb_byte *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,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| struct die_info *comp_unit_die,
|
| int has_children,
|
| void *data);
|
| @@ -775,7 +1050,7 @@ struct line_header
|
| debug_line_buffer. If you try to free them, `free' will get
|
| indigestion. */
|
| unsigned int num_include_dirs, include_dirs_size;
|
| - char **include_dirs;
|
| + const char **include_dirs;
|
|
|
| /* The file_names table. NOTE! These strings are not allocated
|
| with xmalloc; instead, they are pointers into debug_line_buffer.
|
| @@ -783,7 +1058,7 @@ struct line_header
|
| unsigned int num_file_names, file_names_size;
|
| struct file_entry
|
| {
|
| - char *name;
|
| + const char *name;
|
| unsigned int dir_index;
|
| unsigned int mod_time;
|
| unsigned int length;
|
| @@ -793,7 +1068,7 @@ struct line_header
|
|
|
| /* The start and end of the statement program following this
|
| header. These point into dwarf2_per_objfile->line_buffer. */
|
| - gdb_byte *statement_program_start, *statement_program_end;
|
| + const gdb_byte *statement_program_start, *statement_program_end;
|
| };
|
|
|
| /* When we construct a partial symbol table entry we only
|
| @@ -828,9 +1103,15 @@ struct partial_die_info
|
| /* 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. */
|
| - char *name;
|
| + const char *name;
|
|
|
| /* The linkage name, if present. */
|
| const char *linkage_name;
|
| @@ -838,7 +1119,7 @@ struct partial_die_info
|
| /* 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. */
|
| - char *scope;
|
| + const char *scope;
|
|
|
| /* Some data associated with the partial DIE. The tag determines
|
| which field is live. */
|
| @@ -858,7 +1139,7 @@ struct partial_die_info
|
| 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. */
|
| - gdb_byte *sibling;
|
| + const gdb_byte *sibling;
|
|
|
| /* If HAS_SPECIFICATION, the offset of the DIE referred to by
|
| DW_AT_specification (or DW_AT_abstract_origin or
|
| @@ -921,12 +1202,12 @@ struct attribute
|
|
|
| union
|
| {
|
| - char *str;
|
| + const char *str;
|
| struct dwarf_block *blk;
|
| ULONGEST unsnd;
|
| LONGEST snd;
|
| CORE_ADDR addr;
|
| - struct signatured_type *signatured_type;
|
| + ULONGEST signature;
|
| }
|
| u;
|
| };
|
| @@ -972,15 +1253,15 @@ struct die_info
|
| #define DW_BLOCK(attr) ((attr)->u.blk)
|
| #define DW_SND(attr) ((attr)->u.snd)
|
| #define DW_ADDR(attr) ((attr)->u.addr)
|
| -#define DW_SIGNATURED_TYPE(attr) ((attr)->u.signatured_type)
|
| +#define DW_SIGNATURE(attr) ((attr)->u.signature)
|
|
|
| /* Blocks are a bunch of untyped bytes. */
|
| struct dwarf_block
|
| {
|
| - unsigned int size;
|
| + size_t size;
|
|
|
| /* Valid only if SIZE is not zero. */
|
| - gdb_byte *data;
|
| + const gdb_byte *data;
|
| };
|
|
|
| #ifndef ATTR_ALLOC_CHUNK
|
| @@ -1035,7 +1316,7 @@ struct field_info
|
| to the head of the member function field chain. */
|
| struct fnfieldlist
|
| {
|
| - char *name;
|
| + const char *name;
|
| int length;
|
| struct nextfnfield *head;
|
| }
|
| @@ -1081,84 +1362,21 @@ show_dwarf2_max_cache_age (struct ui_file *file, int from_tty,
|
| "dwarf2 compilation units is %s.\n"),
|
| value);
|
| }
|
| +
|
| +/* local function prototypes */
|
|
|
| +static const char *get_section_name (const struct dwarf2_section_info *);
|
|
|
| -/* 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]"),
|
| - section->asection->name,
|
| - bfd_get_filename (section->asection->owner));
|
| -}
|
| -
|
| -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);
|
| -}
|
| -
|
| -/* local function prototypes */
|
| +static const char *get_section_file_name (const struct dwarf2_section_info *);
|
|
|
| static void dwarf2_locate_sections (bfd *, asection *, void *);
|
|
|
| -static void dwarf2_create_include_psymtab (char *, struct partial_symtab *,
|
| - struct objfile *);
|
| -
|
| 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 *,
|
| @@ -1183,7 +1401,8 @@ 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_psymtab_to_symtab (struct partial_symtab *);
|
| +static void dwarf2_read_symtab (struct partial_symtab *,
|
| + struct objfile *);
|
|
|
| static void psymtab_to_symtab_1 (struct partial_symtab *);
|
|
|
| @@ -1202,71 +1421,75 @@ static void dwarf2_read_abbrevs (struct dwarf2_cu *,
|
|
|
| static void dwarf2_free_abbrev_table (void *);
|
|
|
| -static unsigned int peek_abbrev_code (bfd *, gdb_byte *);
|
| +static unsigned int peek_abbrev_code (bfd *, const gdb_byte *);
|
|
|
| static struct partial_die_info *load_partial_dies
|
| - (const struct die_reader_specs *, gdb_byte *, int);
|
| + (const struct die_reader_specs *, const gdb_byte *, int);
|
|
|
| -static gdb_byte *read_partial_die (const struct die_reader_specs *,
|
| - struct partial_die_info *,
|
| - struct abbrev_info *,
|
| - unsigned int,
|
| - gdb_byte *);
|
| +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,
|
| +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 gdb_byte *read_attribute (const struct die_reader_specs *,
|
| - struct attribute *, struct attr_abbrev *,
|
| - gdb_byte *);
|
| +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 *, gdb_byte *);
|
| +static unsigned int read_1_byte (bfd *, const gdb_byte *);
|
|
|
| -static int read_1_signed_byte (bfd *, gdb_byte *);
|
| +static int read_1_signed_byte (bfd *, const gdb_byte *);
|
|
|
| -static unsigned int read_2_bytes (bfd *, gdb_byte *);
|
| +static unsigned int read_2_bytes (bfd *, const gdb_byte *);
|
|
|
| -static unsigned int read_4_bytes (bfd *, gdb_byte *);
|
| +static unsigned int read_4_bytes (bfd *, const gdb_byte *);
|
|
|
| -static ULONGEST read_8_bytes (bfd *, gdb_byte *);
|
| +static ULONGEST read_8_bytes (bfd *, const gdb_byte *);
|
|
|
| -static CORE_ADDR read_address (bfd *, gdb_byte *ptr, struct dwarf2_cu *,
|
| +static CORE_ADDR read_address (bfd *, const gdb_byte *ptr, struct dwarf2_cu *,
|
| unsigned int *);
|
|
|
| -static LONGEST read_initial_length (bfd *, gdb_byte *, unsigned int *);
|
| +static LONGEST read_initial_length (bfd *, const gdb_byte *, unsigned int *);
|
|
|
| static LONGEST read_checked_initial_length_and_offset
|
| - (bfd *, gdb_byte *, const struct comp_unit_head *,
|
| + (bfd *, const gdb_byte *, const struct comp_unit_head *,
|
| unsigned int *, unsigned int *);
|
|
|
| -static LONGEST read_offset (bfd *, gdb_byte *, const struct comp_unit_head *,
|
| +static LONGEST read_offset (bfd *, const gdb_byte *,
|
| + const struct comp_unit_head *,
|
| unsigned int *);
|
|
|
| -static LONGEST read_offset_1 (bfd *, gdb_byte *, 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 gdb_byte *read_n_bytes (bfd *, gdb_byte *, unsigned int);
|
| +static const gdb_byte *read_n_bytes (bfd *, const gdb_byte *, unsigned int);
|
|
|
| -static char *read_direct_string (bfd *, gdb_byte *, unsigned int *);
|
| +static const char *read_direct_string (bfd *, const gdb_byte *, unsigned int *);
|
|
|
| -static char *read_indirect_string (bfd *, gdb_byte *,
|
| - const struct comp_unit_head *,
|
| - unsigned int *);
|
| +static const char *read_indirect_string (bfd *, const gdb_byte *,
|
| + const struct comp_unit_head *,
|
| + unsigned int *);
|
|
|
| -static ULONGEST read_unsigned_leb128 (bfd *, gdb_byte *, unsigned int *);
|
| +static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
|
|
|
| -static LONGEST read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
|
| +static ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *);
|
|
|
| -static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, gdb_byte *,
|
| +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 char *read_str_index (const struct die_reader_specs *reader,
|
| - struct dwarf2_cu *cu, ULONGEST str_index);
|
| +static const char *read_str_index (const struct die_reader_specs *reader,
|
| + struct dwarf2_cu *cu, ULONGEST str_index);
|
|
|
| static void set_cu_language (unsigned int, struct dwarf2_cu *);
|
|
|
| @@ -1286,9 +1509,6 @@ static struct die_info *die_specification (struct die_info *die,
|
|
|
| static void free_line_header (struct line_header *lh);
|
|
|
| -static void add_file_name (struct line_header *, char *, unsigned int,
|
| - unsigned int, unsigned int);
|
| -
|
| static struct line_header *dwarf_decode_line_header (unsigned int offset,
|
| struct dwarf2_cu *cu);
|
|
|
| @@ -1296,10 +1516,10 @@ static void dwarf_decode_lines (struct line_header *, const char *,
|
| struct dwarf2_cu *, struct partial_symtab *,
|
| int);
|
|
|
| -static void dwarf2_start_subfile (char *, const char *, const char *);
|
| +static void dwarf2_start_subfile (const char *, const char *, const char *);
|
|
|
| static void dwarf2_start_symtab (struct dwarf2_cu *,
|
| - char *, char *, CORE_ADDR);
|
| + const char *, const char *, CORE_ADDR);
|
|
|
| static struct symbol *new_symbol (struct die_info *, struct type *,
|
| struct dwarf2_cu *);
|
| @@ -1307,15 +1527,15 @@ static struct symbol *new_symbol (struct die_info *, struct type *,
|
| static struct symbol *new_symbol_full (struct die_info *, struct type *,
|
| struct dwarf2_cu *, struct symbol *);
|
|
|
| -static void dwarf2_const_value (struct attribute *, struct symbol *,
|
| +static void dwarf2_const_value (const struct attribute *, struct symbol *,
|
| struct dwarf2_cu *);
|
|
|
| -static void dwarf2_const_value_attr (struct attribute *attr,
|
| +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,
|
| - gdb_byte **bytes,
|
| + const gdb_byte **bytes,
|
| struct dwarf2_locexpr_baton **baton);
|
|
|
| static struct type *die_type (struct die_info *, struct dwarf2_cu *);
|
| @@ -1331,7 +1551,7 @@ static void set_descriptive_type (struct type *, struct die_info *,
|
| static struct type *die_containing_type (struct die_info *,
|
| struct dwarf2_cu *);
|
|
|
| -static struct type *lookup_die_type (struct die_info *, struct attribute *,
|
| +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 *);
|
| @@ -1392,6 +1612,8 @@ static void read_module (struct die_info *die, struct dwarf2_cu *cu);
|
|
|
| static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
|
|
|
| +static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
|
| +
|
| static struct type *read_module_type (struct die_info *die,
|
| struct dwarf2_cu *cu);
|
|
|
| @@ -1405,33 +1627,37 @@ 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_children (const struct die_reader_specs *,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| - struct die_info *parent);
|
| +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 *,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| + const gdb_byte *info_ptr,
|
| + const gdb_byte **new_info_ptr,
|
| struct die_info *parent);
|
|
|
| -static gdb_byte *read_full_die_1 (const struct die_reader_specs *,
|
| - struct die_info **, gdb_byte *, int *, int);
|
| +static const gdb_byte *read_full_die_1 (const struct die_reader_specs *,
|
| + struct die_info **, const gdb_byte *,
|
| + int *, int);
|
|
|
| -static gdb_byte *read_full_die (const struct die_reader_specs *,
|
| - struct die_info **, gdb_byte *, 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 char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *,
|
| - struct obstack *);
|
| +static const char *dwarf2_canonicalize_name (const char *, struct dwarf2_cu *,
|
| + struct obstack *);
|
|
|
| -static char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
|
| +static const char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
|
|
|
| -static const char *dwarf2_full_name (char *name,
|
| +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 **);
|
|
|
| @@ -1459,34 +1685,35 @@ static void dump_die_1 (struct ui_file *, int level, int max_level,
|
| static void store_in_ref_table (struct die_info *,
|
| struct dwarf2_cu *);
|
|
|
| -static int is_ref_attr (struct attribute *);
|
| +static sect_offset dwarf2_get_ref_die_offset (const struct attribute *);
|
|
|
| -static sect_offset dwarf2_get_ref_die_offset (struct attribute *);
|
| -
|
| -static LONGEST dwarf2_get_attr_constant_value (struct attribute *, int);
|
| +static LONGEST dwarf2_get_attr_constant_value (const struct attribute *, int);
|
|
|
| static struct die_info *follow_die_ref_or_sig (struct die_info *,
|
| - struct attribute *,
|
| + const struct attribute *,
|
| struct dwarf2_cu **);
|
|
|
| static struct die_info *follow_die_ref (struct die_info *,
|
| - struct attribute *,
|
| + const struct attribute *,
|
| struct dwarf2_cu **);
|
|
|
| static struct die_info *follow_die_sig (struct die_info *,
|
| - struct attribute *,
|
| + const struct attribute *,
|
| struct dwarf2_cu **);
|
|
|
| -static struct signatured_type *lookup_signatured_type_at_offset
|
| - (struct objfile *objfile,
|
| - struct dwarf2_section_info *section, sect_offset offset);
|
| +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 struct type_unit_group *get_type_unit_group
|
| - (struct dwarf2_cu *, struct attribute *);
|
| + (struct dwarf2_cu *, const struct attribute *);
|
|
|
| static void build_type_unit_groups (die_reader_func_ftype *, void *);
|
|
|
| @@ -1497,25 +1724,28 @@ 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,
|
| - char *, int);
|
| + const char *, int);
|
| +
|
| +static int attr_form_is_block (const struct attribute *);
|
|
|
| -static int attr_form_is_block (struct attribute *);
|
| +static int attr_form_is_section_offset (const struct attribute *);
|
|
|
| -static int attr_form_is_section_offset (struct attribute *);
|
| +static int attr_form_is_constant (const struct attribute *);
|
|
|
| -static int attr_form_is_constant (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,
|
| - struct attribute *attr);
|
| + const struct attribute *attr);
|
|
|
| -static void dwarf2_symbol_mark_computed (struct attribute *attr,
|
| +static void dwarf2_symbol_mark_computed (const struct attribute *attr,
|
| struct symbol *sym,
|
| - struct dwarf2_cu *cu);
|
| + struct dwarf2_cu *cu,
|
| + int is_block);
|
|
|
| -static gdb_byte *skip_one_die (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - struct abbrev_info *abbrev);
|
| +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 *);
|
|
|
| @@ -1524,7 +1754,7 @@ 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, struct objfile *objfile);
|
| + (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);
|
| @@ -1565,7 +1795,7 @@ 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 *per_cu);
|
| + struct dwarf2_per_cu_data *);
|
|
|
| static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
|
|
|
| @@ -1574,19 +1804,21 @@ static void dwarf2_release_queue (void *dummy);
|
| static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| enum language pretend_language);
|
|
|
| -static int maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
|
| - 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,
|
| - char **name, char **comp_dir);
|
| + 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,
|
| @@ -1600,60 +1832,131 @@ 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 *, char *, const char *, ULONGEST);
|
| + (struct dwarf2_per_cu_data *, const char *, const char *, ULONGEST);
|
|
|
| static struct dwo_unit *lookup_dwo_type_unit
|
| - (struct signatured_type *, char *, const char *);
|
| + (struct signatured_type *, const char *, const char *);
|
|
|
| -static void free_dwo_file_cleanup (void *);
|
| +static void queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *);
|
|
|
| -static void munmap_section_buffer (struct dwarf2_section_info *);
|
| +static void free_dwo_file_cleanup (void *);
|
|
|
| static void process_cu_includes (void);
|
|
|
| -#if WORDS_BIGENDIAN
|
| +static void check_producer (struct dwarf2_cu *cu);
|
| +
|
| +/* Various complaints about symbol reading that don't abort the process. */
|
|
|
| -/* Convert VALUE between big- and little-endian. */
|
| -static offset_type
|
| -byte_swap (offset_type value)
|
| +static void
|
| +dwarf2_statement_list_fits_in_line_number_section_complaint (void)
|
| {
|
| - offset_type result;
|
| -
|
| - result = (value & 0xff) << 24;
|
| - result |= (value & 0xff00) << 8;
|
| - result |= (value & 0xff0000) >> 8;
|
| - result |= (value & 0xff000000) >> 24;
|
| - return result;
|
| + complaint (&symfile_complaints,
|
| + _("statement list doesn't fit in .debug_line section"));
|
| }
|
|
|
| -#define MAYBE_SWAP(V) byte_swap (V)
|
| -
|
| -#else
|
| -#define MAYBE_SWAP(V) (V)
|
| -#endif /* WORDS_BIGENDIAN */
|
| -
|
| -/* The suffix for an index file. */
|
| -#define INDEX_SUFFIX ".gdb-index"
|
| +static void
|
| +dwarf2_debug_line_missing_file_complaint (void)
|
| +{
|
| + complaint (&symfile_complaints,
|
| + _(".debug_line section has line data without a file"));
|
| +}
|
|
|
| -static const char *dwarf2_physname (char *name, struct die_info *die,
|
| - struct dwarf2_cu *cu);
|
| +static void
|
| +dwarf2_debug_line_missing_end_sequence_complaint (void)
|
| +{
|
| + complaint (&symfile_complaints,
|
| + _(".debug_line section has line "
|
| + "program sequence without an end"));
|
| +}
|
|
|
| -/* 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. */
|
| +static void
|
| +dwarf2_complex_location_expr_complaint (void)
|
| +{
|
| + complaint (&symfile_complaints, _("location expression too complex"));
|
| +}
|
|
|
| -int
|
| -dwarf2_has_info (struct objfile *objfile,
|
| - const struct dwarf2_debug_sections *names)
|
| +static void
|
| +dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
|
| + int arg3)
|
| {
|
| - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
|
| - if (!dwarf2_per_objfile)
|
| - {
|
| - /* Initialize per-objfile state. */
|
| - struct dwarf2_per_objfile *data
|
| - = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
|
| + 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);
|
| +}
|
| +
|
| +#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 */
|
| +
|
| +/* 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 = objfile_data (objfile, dwarf2_objfile_data_key);
|
| + if (!dwarf2_per_objfile)
|
| + {
|
| + /* Initialize per-objfile state. */
|
| + struct dwarf2_per_objfile *data
|
| + = obstack_alloc (&objfile->objfile_obstack, sizeof (*data));
|
|
|
| memset (data, 0, sizeof (*data));
|
| set_objfile_data (objfile, dwarf2_objfile_data_key, data);
|
| @@ -1663,8 +1966,92 @@ dwarf2_has_info (struct objfile *objfile,
|
| (void *) names);
|
| dwarf2_per_objfile->objfile = objfile;
|
| }
|
| - return (dwarf2_per_objfile->info.asection != NULL
|
| - && dwarf2_per_objfile->abbrev.asection != NULL);
|
| + return (!dwarf2_per_objfile->info.is_virtual
|
| + && dwarf2_per_objfile->info.s.asection != NULL
|
| + && !dwarf2_per_objfile->abbrev.is_virtual
|
| + && dwarf2_per_objfile->abbrev.s.asection != 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.asection->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.asection;
|
| +}
|
| +
|
| +/* 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
|
| @@ -1703,57 +2090,57 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| }
|
| else if (section_is_p (sectp->name, &names->info))
|
| {
|
| - dwarf2_per_objfile->info.asection = sectp;
|
| + dwarf2_per_objfile->info.s.asection = sectp;
|
| dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->abbrev))
|
| {
|
| - dwarf2_per_objfile->abbrev.asection = sectp;
|
| + dwarf2_per_objfile->abbrev.s.asection = sectp;
|
| dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->line))
|
| {
|
| - dwarf2_per_objfile->line.asection = sectp;
|
| + dwarf2_per_objfile->line.s.asection = sectp;
|
| dwarf2_per_objfile->line.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->loc))
|
| {
|
| - dwarf2_per_objfile->loc.asection = sectp;
|
| + dwarf2_per_objfile->loc.s.asection = sectp;
|
| dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->macinfo))
|
| {
|
| - dwarf2_per_objfile->macinfo.asection = sectp;
|
| + dwarf2_per_objfile->macinfo.s.asection = sectp;
|
| dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->macro))
|
| {
|
| - dwarf2_per_objfile->macro.asection = sectp;
|
| + dwarf2_per_objfile->macro.s.asection = sectp;
|
| dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->str))
|
| {
|
| - dwarf2_per_objfile->str.asection = sectp;
|
| + dwarf2_per_objfile->str.s.asection = sectp;
|
| dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->addr))
|
| {
|
| - dwarf2_per_objfile->addr.asection = sectp;
|
| + dwarf2_per_objfile->addr.s.asection = sectp;
|
| dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->frame))
|
| {
|
| - dwarf2_per_objfile->frame.asection = sectp;
|
| + dwarf2_per_objfile->frame.s.asection = 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.asection = sectp;
|
| + dwarf2_per_objfile->eh_frame.s.asection = 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.asection = sectp;
|
| + dwarf2_per_objfile->ranges.s.asection = sectp;
|
| dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->types))
|
| @@ -1761,7 +2148,7 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| struct dwarf2_section_info type_section;
|
|
|
| memset (&type_section, 0, sizeof (type_section));
|
| - type_section.asection = sectp;
|
| + type_section.s.asection = sectp;
|
| type_section.size = bfd_get_section_size (sectp);
|
|
|
| VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types,
|
| @@ -1769,7 +2156,7 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| }
|
| else if (section_is_p (sectp->name, &names->gdb_index))
|
| {
|
| - dwarf2_per_objfile->gdb_index.asection = sectp;
|
| + dwarf2_per_objfile->gdb_index.s.asection = sectp;
|
| dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
|
| }
|
|
|
| @@ -1778,161 +2165,75 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| dwarf2_per_objfile->has_section_at_zero = 1;
|
| }
|
|
|
| -/* Decompress a section that was compressed using zlib. Store the
|
| - decompressed buffer, and its size, in OUTBUF and OUTSIZE. */
|
| -
|
| -static void
|
| -zlib_decompress_section (struct objfile *objfile, asection *sectp,
|
| - gdb_byte **outbuf, bfd_size_type *outsize)
|
| -{
|
| - bfd *abfd = sectp->owner;
|
| -#ifndef HAVE_ZLIB_H
|
| - error (_("Support for zlib-compressed DWARF data (from '%s') "
|
| - "is disabled in this copy of GDB"),
|
| - bfd_get_filename (abfd));
|
| -#else
|
| - bfd_size_type compressed_size = bfd_get_section_size (sectp);
|
| - gdb_byte *compressed_buffer = xmalloc (compressed_size);
|
| - struct cleanup *cleanup = make_cleanup (xfree, compressed_buffer);
|
| - bfd_size_type uncompressed_size;
|
| - gdb_byte *uncompressed_buffer;
|
| - z_stream strm;
|
| - int rc;
|
| - int header_size = 12;
|
| -
|
| - if (bfd_seek (abfd, sectp->filepos, SEEK_SET) != 0
|
| - || bfd_bread (compressed_buffer,
|
| - compressed_size, abfd) != compressed_size)
|
| - error (_("Dwarf Error: Can't read DWARF data from '%s'"),
|
| - bfd_get_filename (abfd));
|
| -
|
| - /* Read the zlib header. In this case, it should be "ZLIB" followed
|
| - by the uncompressed section size, 8 bytes in big-endian order. */
|
| - if (compressed_size < header_size
|
| - || strncmp (compressed_buffer, "ZLIB", 4) != 0)
|
| - error (_("Dwarf Error: Corrupt DWARF ZLIB header from '%s'"),
|
| - bfd_get_filename (abfd));
|
| - uncompressed_size = compressed_buffer[4]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[5]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[6]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[7]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[8]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[9]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[10]; uncompressed_size <<= 8;
|
| - uncompressed_size += compressed_buffer[11];
|
| -
|
| - /* It is possible the section consists of several compressed
|
| - buffers concatenated together, so we uncompress in a loop. */
|
| - strm.zalloc = NULL;
|
| - strm.zfree = NULL;
|
| - strm.opaque = NULL;
|
| - strm.avail_in = compressed_size - header_size;
|
| - strm.next_in = (Bytef*) compressed_buffer + header_size;
|
| - strm.avail_out = uncompressed_size;
|
| - uncompressed_buffer = obstack_alloc (&objfile->objfile_obstack,
|
| - uncompressed_size);
|
| - rc = inflateInit (&strm);
|
| - while (strm.avail_in > 0)
|
| - {
|
| - if (rc != Z_OK)
|
| - error (_("Dwarf Error: setting up DWARF uncompression in '%s': %d"),
|
| - bfd_get_filename (abfd), rc);
|
| - strm.next_out = ((Bytef*) uncompressed_buffer
|
| - + (uncompressed_size - strm.avail_out));
|
| - rc = inflate (&strm, Z_FINISH);
|
| - if (rc != Z_STREAM_END)
|
| - error (_("Dwarf Error: zlib error uncompressing from '%s': %d"),
|
| - bfd_get_filename (abfd), rc);
|
| - rc = inflateReset (&strm);
|
| - }
|
| - rc = inflateEnd (&strm);
|
| - if (rc != Z_OK
|
| - || strm.avail_out != 0)
|
| - error (_("Dwarf Error: concluding DWARF uncompression in '%s': %d"),
|
| - bfd_get_filename (abfd), rc);
|
| -
|
| - do_cleanups (cleanup);
|
| - *outbuf = uncompressed_buffer;
|
| - *outsize = uncompressed_size;
|
| -#endif
|
| -}
|
| -
|
| /* A helper function that decides whether a section is empty,
|
| or not present. */
|
|
|
| static int
|
| -dwarf2_section_empty_p (struct dwarf2_section_info *info)
|
| +dwarf2_section_empty_p (const struct dwarf2_section_info *section)
|
| {
|
| - return info->asection == NULL || info->size == 0;
|
| + if (section->is_virtual)
|
| + return section->size == 0;
|
| + return section->s.asection == 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 INFO->asection->owner
|
| - is the bfd of the DWO file.
|
| + 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 = info->asection;
|
| + asection *sectp;
|
| bfd *abfd;
|
| gdb_byte *buf, *retbuf;
|
| - unsigned char header[4];
|
|
|
| if (info->readin)
|
| return;
|
| info->buffer = NULL;
|
| - info->map_addr = NULL;
|
| info->readin = 1;
|
|
|
| if (dwarf2_section_empty_p (info))
|
| return;
|
|
|
| - /* Note that ABFD may not be from OBJFILE, e.g. a DWO section. */
|
| - abfd = sectp->owner;
|
| -
|
| - /* Check if the file has a 4-byte header indicating compression. */
|
| - if (info->size > sizeof (header)
|
| - && bfd_seek (abfd, sectp->filepos, SEEK_SET) == 0
|
| - && bfd_bread (header, sizeof (header), abfd) == sizeof (header))
|
| - {
|
| - /* Upon decompression, update the buffer and its size. */
|
| - if (strncmp (header, "ZLIB", sizeof (header)) == 0)
|
| - {
|
| - zlib_decompress_section (objfile, sectp, &info->buffer,
|
| - &info->size);
|
| - return;
|
| - }
|
| - }
|
| -
|
| -#ifdef HAVE_MMAP
|
| - if (pagesize == 0)
|
| - pagesize = getpagesize ();
|
| + sectp = get_section_bfd_section (info);
|
|
|
| - /* Only try to mmap sections which are large enough: we don't want to
|
| - waste space due to fragmentation. Also, only try mmap for sections
|
| - without relocations. */
|
| -
|
| - if (info->size > 4 * pagesize && (sectp->flags & SEC_RELOC) == 0)
|
| + /* If this is a virtual section we need to read in the real one first. */
|
| + if (info->is_virtual)
|
| {
|
| - info->buffer = bfd_mmap (abfd, 0, info->size, PROT_READ,
|
| - MAP_PRIVATE, sectp->filepos,
|
| - &info->map_addr, &info->map_len);
|
| + struct dwarf2_section_info *containing_section =
|
| + get_containing_section (info);
|
|
|
| - if ((caddr_t)info->buffer != MAP_FAILED)
|
| + gdb_assert (sectp != NULL);
|
| + if ((sectp->flags & SEC_RELOC) != 0)
|
| {
|
| -#if HAVE_POSIX_MADVISE
|
| - posix_madvise (info->map_addr, info->map_len, POSIX_MADV_WILLNEED);
|
| -#endif
|
| - return;
|
| + 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;
|
| }
|
| -#endif
|
|
|
| - /* If we get here, we are a normal, not-compressed section. */
|
| - info->buffer = buf
|
| - = obstack_alloc (&objfile->objfile_obstack, info->size);
|
| + buf = 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 .
|
| @@ -1945,10 +2246,16 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
|
| 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 from '%s'"),
|
| - bfd_get_filename (abfd));
|
| + {
|
| + 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.
|
| @@ -1973,7 +2280,7 @@ dwarf2_section_size (struct objfile *objfile,
|
| void
|
| dwarf2_get_section_info (struct objfile *objfile,
|
| enum dwarf2_section_enum sect,
|
| - asection **sectp, gdb_byte **bufp,
|
| + asection **sectp, const gdb_byte **bufp,
|
| bfd_size_type *sizep)
|
| {
|
| struct dwarf2_per_objfile *data
|
| @@ -2003,11 +2310,131 @@ dwarf2_get_section_info (struct objfile *objfile,
|
|
|
| dwarf2_read_section (objfile, info);
|
|
|
| - *sectp = info->asection;
|
| + *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 = 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.asection = 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.asection = 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.asection = 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.asection = 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.asection = 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.asection = 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);
|
| +
|
| + dwarf2_per_objfile->dwz_file = result;
|
| + return result;
|
| +}
|
|
|
| /* DWARF quick_symbols_functions support. */
|
|
|
| @@ -2171,6 +2598,17 @@ dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| 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->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 ();
|
| @@ -2255,53 +2693,26 @@ dw2_get_primary_cu (int index)
|
| return dwarf2_per_objfile->all_comp_units[index];
|
| }
|
|
|
| -/* A helper function that knows how to read a 64-bit value in a way
|
| - that doesn't make gdb die. Returns 1 if the conversion went ok, 0
|
| - otherwise. */
|
| -
|
| -static int
|
| -extract_cu_value (const char *bytes, ULONGEST *result)
|
| -{
|
| - if (sizeof (ULONGEST) < 8)
|
| - {
|
| - int i;
|
| -
|
| - /* Ignore the upper 4 bytes if they are all zero. */
|
| - for (i = 0; i < 4; ++i)
|
| - if (bytes[i + 4] != 0)
|
| - return 0;
|
| -
|
| - *result = extract_unsigned_integer (bytes, 4, BFD_ENDIAN_LITTLE);
|
| - }
|
| - else
|
| - *result = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE);
|
| - return 1;
|
| -}
|
| -
|
| -/* Read the CU list from the mapped index, and use it to create all
|
| - the CU objects for this objfile. Return 0 if something went wrong,
|
| - 1 if everything went ok. */
|
| +/* A helper for create_cus_from_index that handles a given list of
|
| + CUs. */
|
|
|
| -static int
|
| -create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list,
|
| - offset_type cu_list_elements)
|
| +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;
|
|
|
| - dwarf2_per_objfile->n_comp_units = cu_list_elements / 2;
|
| - dwarf2_per_objfile->all_comp_units
|
| - = obstack_alloc (&objfile->objfile_obstack,
|
| - dwarf2_per_objfile->n_comp_units
|
| - * sizeof (struct dwarf2_per_cu_data *));
|
| -
|
| - for (i = 0; i < cu_list_elements; i += 2)
|
| + for (i = 0; i < n_elements; i += 2)
|
| {
|
| struct dwarf2_per_cu_data *the_cu;
|
| ULONGEST offset, length;
|
|
|
| - if (!extract_cu_value (cu_list, &offset)
|
| - || !extract_cu_value (cu_list + 8, &length))
|
| - return 0;
|
| + 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,
|
| @@ -2309,18 +2720,44 @@ create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list,
|
| the_cu->offset.sect_off = offset;
|
| the_cu->length = length;
|
| the_cu->objfile = objfile;
|
| - the_cu->info_or_types_section = &dwarf2_per_objfile->info;
|
| + the_cu->section = section;
|
| the_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| struct dwarf2_per_cu_quick_data);
|
| - dwarf2_per_objfile->all_comp_units[i / 2] = the_cu;
|
| + the_cu->is_dwz = is_dwz;
|
| + dwarf2_per_objfile->all_comp_units[base_offset + i / 2] = the_cu;
|
| }
|
| +}
|
|
|
| - return 1;
|
| +/* 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
|
| + = obstack_alloc (&objfile->objfile_obstack,
|
| + dwarf2_per_objfile->n_comp_units
|
| + * sizeof (struct dwarf2_per_cu_data *));
|
| +
|
| + 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 int
|
| +static void
|
| create_signatured_type_table_from_index (struct objfile *objfile,
|
| struct dwarf2_section_info *section,
|
| const gdb_byte *bytes,
|
| @@ -2331,9 +2768,8 @@ create_signatured_type_table_from_index (struct objfile *objfile,
|
|
|
| dwarf2_per_objfile->n_type_units = elements / 3;
|
| dwarf2_per_objfile->all_type_units
|
| - = obstack_alloc (&objfile->objfile_obstack,
|
| - dwarf2_per_objfile->n_type_units
|
| - * sizeof (struct signatured_type *));
|
| + = xmalloc (dwarf2_per_objfile->n_type_units
|
| + * sizeof (struct signatured_type *));
|
|
|
| sig_types_hash = allocate_signatured_type_table (objfile);
|
|
|
| @@ -2343,9 +2779,10 @@ create_signatured_type_table_from_index (struct objfile *objfile,
|
| ULONGEST offset, type_offset_in_tu, signature;
|
| void **slot;
|
|
|
| - if (!extract_cu_value (bytes, &offset)
|
| - || !extract_cu_value (bytes + 8, &type_offset_in_tu))
|
| - return 0;
|
| + 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;
|
|
|
| @@ -2354,7 +2791,7 @@ create_signatured_type_table_from_index (struct objfile *objfile,
|
| 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.info_or_types_section = section;
|
| + 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
|
| @@ -2368,8 +2805,6 @@ create_signatured_type_table_from_index (struct objfile *objfile,
|
| }
|
|
|
| dwarf2_per_objfile->signatured_types = sig_types_hash;
|
| -
|
| - return 1;
|
| }
|
|
|
| /* Read the address map data from the mapped index, and use it to
|
| @@ -2402,7 +2837,23 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index)
|
| 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;
|
| + }
|
| +
|
| addrmap_set_empty (mutable_map, lo + baseaddr, hi + baseaddr - 1,
|
| dw2_get_cu (cu_index));
|
| }
|
| @@ -2507,33 +2958,44 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
|
| }
|
| }
|
|
|
| -/* Read the index file. If everything went ok, initialize the "quick"
|
| - elements of all the CUs and return 1. Otherwise, return 0. */
|
| +/* A helper function that reads the .gdb_index from SECTION and fills
|
| + in MAP. FILENAME is the name of the file containing the section;
|
| + it is used for error reporting. DEPRECATED_OK is nonzero if it is
|
| + ok to use deprecated sections.
|
| +
|
| + CU_LIST, CU_LIST_ELEMENTS, TYPES_LIST, and TYPES_LIST_ELEMENTS are
|
| + out parameters that are filled in with information about the CU and
|
| + TU lists in the section.
|
| +
|
| + Returns 1 if all went well, 0 otherwise. */
|
|
|
| static int
|
| -dwarf2_read_index (struct objfile *objfile)
|
| -{
|
| - char *addr;
|
| - struct mapped_index *map;
|
| +read_index_from_section (struct objfile *objfile,
|
| + const char *filename,
|
| + int deprecated_ok,
|
| + struct dwarf2_section_info *section,
|
| + struct mapped_index *map,
|
| + const gdb_byte **cu_list,
|
| + offset_type *cu_list_elements,
|
| + const gdb_byte **types_list,
|
| + offset_type *types_list_elements)
|
| +{
|
| + const gdb_byte *addr;
|
| + offset_type version;
|
| offset_type *metadata;
|
| - const gdb_byte *cu_list;
|
| - const gdb_byte *types_list = NULL;
|
| - offset_type version, cu_list_elements;
|
| - offset_type types_list_elements = 0;
|
| int i;
|
|
|
| - if (dwarf2_section_empty_p (&dwarf2_per_objfile->gdb_index))
|
| + if (dwarf2_section_empty_p (section))
|
| return 0;
|
|
|
| /* Older elfutils strip versions could keep the section in the main
|
| executable while splitting it for the separate debug info file. */
|
| - if ((bfd_get_file_flags (dwarf2_per_objfile->gdb_index.asection)
|
| - & SEC_HAS_CONTENTS) == 0)
|
| + if ((get_section_flags (section) & SEC_HAS_CONTENTS) == 0)
|
| return 0;
|
|
|
| - dwarf2_read_section (objfile, &dwarf2_per_objfile->gdb_index);
|
| + dwarf2_read_section (objfile, section);
|
|
|
| - addr = dwarf2_per_objfile->gdb_index.buffer;
|
| + addr = section->buffer;
|
| /* Version check. */
|
| version = MAYBE_SWAP (*(offset_type *) addr);
|
| /* Versions earlier than 3 emitted every copy of a psymbol. This
|
| @@ -2546,7 +3008,7 @@ dwarf2_read_index (struct objfile *objfile)
|
| if (!warning_printed)
|
| {
|
| warning (_("Skipping obsolete .gdb_index section in %s."),
|
| - objfile->name);
|
| + filename);
|
| warning_printed = 1;
|
| }
|
| return 0;
|
| @@ -2559,7 +3021,7 @@ dwarf2_read_index (struct objfile *objfile)
|
| set breakpoints on inlined functions by name, so we ignore these
|
| indices unless the user has done
|
| "set use-deprecated-index-sections on". */
|
| - if (version < 6 && !use_deprecated_index_sections)
|
| + if (version < 6 && !deprecated_ok)
|
| {
|
| static int warning_printed = 0;
|
| if (!warning_printed)
|
| @@ -2568,32 +3030,39 @@ dwarf2_read_index (struct objfile *objfile)
|
| Skipping deprecated .gdb_index section in %s.\n\
|
| Do \"set use-deprecated-index-sections on\" before the file is read\n\
|
| to use the section anyway."),
|
| - objfile->name);
|
| + filename);
|
| warning_printed = 1;
|
| }
|
| return 0;
|
| }
|
| + /* Version 7 indices generated by gold refer to the CU for a symbol instead
|
| + of the TU (for symbols coming from TUs),
|
| + http://sourceware.org/bugzilla/show_bug.cgi?id=15021.
|
| + Plus gold-generated indices can have duplicate entries for global symbols,
|
| + http://sourceware.org/bugzilla/show_bug.cgi?id=15646.
|
| + These are just performance bugs, and we can't distinguish gdb-generated
|
| + indices from gold-generated ones, so issue no warning here. */
|
| +
|
| /* Indexes with higher version than the one supported by GDB may be no
|
| longer backward compatible. */
|
| - if (version > 7)
|
| + if (version > 8)
|
| return 0;
|
|
|
| - map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
|
| map->version = version;
|
| - map->total_size = dwarf2_per_objfile->gdb_index.size;
|
| + map->total_size = section->size;
|
|
|
| metadata = (offset_type *) (addr + sizeof (offset_type));
|
|
|
| i = 0;
|
| - cu_list = addr + MAYBE_SWAP (metadata[i]);
|
| - cu_list_elements = ((MAYBE_SWAP (metadata[i + 1]) - MAYBE_SWAP (metadata[i]))
|
| - / 8);
|
| + *cu_list = addr + MAYBE_SWAP (metadata[i]);
|
| + *cu_list_elements = ((MAYBE_SWAP (metadata[i + 1]) - MAYBE_SWAP (metadata[i]))
|
| + / 8);
|
| ++i;
|
|
|
| - types_list = addr + MAYBE_SWAP (metadata[i]);
|
| - types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
|
| - - MAYBE_SWAP (metadata[i]))
|
| - / 8);
|
| + *types_list = addr + MAYBE_SWAP (metadata[i]);
|
| + *types_list_elements = ((MAYBE_SWAP (metadata[i + 1])
|
| + - MAYBE_SWAP (metadata[i]))
|
| + / 8);
|
| ++i;
|
|
|
| map->address_table = addr + MAYBE_SWAP (metadata[i]);
|
| @@ -2607,16 +3076,60 @@ to use the section anyway."),
|
| / (2 * sizeof (offset_type)));
|
| ++i;
|
|
|
| - map->constant_pool = addr + MAYBE_SWAP (metadata[i]);
|
| + map->constant_pool = (char *) (addr + MAYBE_SWAP (metadata[i]));
|
|
|
| - /* Don't use the index if it's empty. */
|
| - if (map->symbol_table_slots == 0)
|
| - return 0;
|
| + return 1;
|
| +}
|
|
|
| - if (!create_cus_from_index (objfile, cu_list, cu_list_elements))
|
| - return 0;
|
|
|
| - if (types_list_elements)
|
| +/* Read the index file. If everything went ok, initialize the "quick"
|
| + elements of all the CUs and return 1. Otherwise, return 0. */
|
| +
|
| +static int
|
| +dwarf2_read_index (struct objfile *objfile)
|
| +{
|
| + struct mapped_index local_map, *map;
|
| + const gdb_byte *cu_list, *types_list, *dwz_list = NULL;
|
| + offset_type cu_list_elements, types_list_elements, dwz_list_elements = 0;
|
| + struct dwz_file *dwz;
|
| +
|
| + if (!read_index_from_section (objfile, objfile_name (objfile),
|
| + use_deprecated_index_sections,
|
| + &dwarf2_per_objfile->gdb_index, &local_map,
|
| + &cu_list, &cu_list_elements,
|
| + &types_list, &types_list_elements))
|
| + return 0;
|
| +
|
| + /* Don't use the index if it's empty. */
|
| + if (local_map.symbol_table_slots == 0)
|
| + return 0;
|
| +
|
| + /* If there is a .dwz file, read it so we can get its CU list as
|
| + well. */
|
| + dwz = dwarf2_get_dwz_file ();
|
| + if (dwz != NULL)
|
| + {
|
| + struct mapped_index dwz_map;
|
| + const gdb_byte *dwz_types_ignore;
|
| + offset_type dwz_types_elements_ignore;
|
| +
|
| + if (!read_index_from_section (objfile, bfd_get_filename (dwz->dwz_bfd),
|
| + 1,
|
| + &dwz->gdb_index, &dwz_map,
|
| + &dwz_list, &dwz_list_elements,
|
| + &dwz_types_ignore,
|
| + &dwz_types_elements_ignore))
|
| + {
|
| + warning (_("could not read '.gdb_index' section from %s; skipping"),
|
| + bfd_get_filename (dwz->dwz_bfd));
|
| + return 0;
|
| + }
|
| + }
|
| +
|
| + create_cus_from_index (objfile, cu_list, cu_list_elements, dwz_list,
|
| + dwz_list_elements);
|
| +
|
| + if (types_list_elements)
|
| {
|
| struct dwarf2_section_info *section;
|
|
|
| @@ -2628,13 +3141,14 @@ to use the section anyway."),
|
| section = VEC_index (dwarf2_section_info_def,
|
| dwarf2_per_objfile->types, 0);
|
|
|
| - if (!create_signatured_type_table_from_index (objfile, section,
|
| - types_list,
|
| - types_list_elements))
|
| - return 0;
|
| + create_signatured_type_table_from_index (objfile, section, types_list,
|
| + types_list_elements);
|
| }
|
|
|
| - create_addrmap_from_index (objfile, map);
|
| + create_addrmap_from_index (objfile, &local_map);
|
| +
|
| + map = obstack_alloc (&objfile->objfile_obstack, sizeof (struct mapped_index));
|
| + *map = local_map;
|
|
|
| dwarf2_per_objfile->index_table = map;
|
| dwarf2_per_objfile->using_index = 1;
|
| @@ -2654,45 +3168,11 @@ dw2_setup (struct objfile *objfile)
|
| gdb_assert (dwarf2_per_objfile);
|
| }
|
|
|
| -/* Reader function for dw2_build_type_unit_groups. */
|
| -
|
| -static void
|
| -dw2_build_type_unit_groups_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - struct die_info *type_unit_die,
|
| - int has_children,
|
| - void *data)
|
| -{
|
| - struct dwarf2_cu *cu = reader->cu;
|
| - struct attribute *attr;
|
| - struct type_unit_group *tu_group;
|
| -
|
| - gdb_assert (data == NULL);
|
| -
|
| - if (! has_children)
|
| - return;
|
| -
|
| - attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
|
| - /* Call this for its side-effect of creating the associated
|
| - struct type_unit_group if it doesn't already exist. */
|
| - tu_group = get_type_unit_group (cu, attr);
|
| -}
|
| -
|
| -/* Build dwarf2_per_objfile->type_unit_groups.
|
| - This function may be called multiple times. */
|
| -
|
| -static void
|
| -dw2_build_type_unit_groups (void)
|
| -{
|
| - if (dwarf2_per_objfile->type_unit_groups == NULL)
|
| - build_type_unit_groups (dw2_build_type_unit_groups_reader, NULL);
|
| -}
|
| -
|
| /* die_reader_func for dw2_get_file_names. */
|
|
|
| static void
|
| dw2_get_file_names_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| struct die_info *comp_unit_die,
|
| int has_children,
|
| void *data)
|
| @@ -2704,11 +3184,13 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
|
| struct line_header *lh;
|
| struct attribute *attr;
|
| int i;
|
| - char *name, *comp_dir;
|
| + const char *name, *comp_dir;
|
| void **slot;
|
| struct quick_file_names *qfn;
|
| unsigned int line_offset;
|
|
|
| + gdb_assert (! this_cu->is_debug_types);
|
| +
|
| /* Our callers never want to match partial units -- instead they
|
| will match the enclosing full CU. */
|
| if (comp_unit_die->tag == DW_TAG_partial_unit)
|
| @@ -2717,18 +3199,7 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
|
| return;
|
| }
|
|
|
| - /* If we're reading the line header for TUs, store it in the "per_cu"
|
| - for tu_group. */
|
| - if (this_cu->is_debug_types)
|
| - {
|
| - struct type_unit_group *tu_group = data;
|
| -
|
| - gdb_assert (tu_group != NULL);
|
| - lh_cu = &tu_group->per_cu;
|
| - }
|
| - else
|
| - lh_cu = this_cu;
|
| -
|
| + lh_cu = this_cu;
|
| lh = NULL;
|
| slot = NULL;
|
| line_offset = 0;
|
| @@ -2784,12 +3255,12 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader,
|
| table for THIS_CU. */
|
|
|
| static struct quick_file_names *
|
| -dw2_get_file_names (struct objfile *objfile,
|
| - struct dwarf2_per_cu_data *this_cu)
|
| +dw2_get_file_names (struct dwarf2_per_cu_data *this_cu)
|
| {
|
| - /* For TUs this should only be called on the parent group. */
|
| - if (this_cu->is_debug_types)
|
| - gdb_assert (IS_TYPE_UNIT_GROUP (this_cu));
|
| + /* This should never be called for TUs. */
|
| + gdb_assert (! this_cu->is_debug_types);
|
| + /* Nor type unit groups. */
|
| + gdb_assert (! IS_TYPE_UNIT_GROUP (this_cu));
|
|
|
| if (this_cu->v.quick->file_names != NULL)
|
| return this_cu->v.quick->file_names;
|
| @@ -2797,19 +3268,7 @@ dw2_get_file_names (struct objfile *objfile,
|
| if (this_cu->v.quick->no_file_data)
|
| return NULL;
|
|
|
| - /* If DWO files are in use, we can still find the DW_AT_stmt_list attribute
|
| - in the stub for CUs, there's is no need to lookup the DWO file.
|
| - However, that's not the case for TUs where DW_AT_stmt_list lives in the
|
| - DWO file. */
|
| - if (this_cu->is_debug_types)
|
| - {
|
| - struct type_unit_group *tu_group = this_cu->s.type_unit_group;
|
| -
|
| - init_cutu_and_read_dies (tu_group->t.first_tu, NULL, 0, 0,
|
| - dw2_get_file_names_reader, tu_group);
|
| - }
|
| - else
|
| - init_cutu_and_read_dies_simple (this_cu, dw2_get_file_names_reader, NULL);
|
| + init_cutu_and_read_dies_simple (this_cu, dw2_get_file_names_reader, NULL);
|
|
|
| if (this_cu->v.quick->no_file_data)
|
| return NULL;
|
| @@ -2825,7 +3284,7 @@ dw2_get_real_path (struct objfile *objfile,
|
| {
|
| if (qfn->real_names == NULL)
|
| qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
|
| - qfn->num_file_names, sizeof (char *));
|
| + qfn->num_file_names, char *);
|
|
|
| if (qfn->real_names[index] == NULL)
|
| qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
|
| @@ -2879,8 +3338,7 @@ dw2_forget_cached_source_info (struct objfile *objfile)
|
| static int
|
| dw2_map_expand_apply (struct objfile *objfile,
|
| struct dwarf2_per_cu_data *per_cu,
|
| - const char *name,
|
| - const char *full_path, const char *real_path,
|
| + const char *name, const char *real_path,
|
| int (*callback) (struct symtab *, void *),
|
| void *data)
|
| {
|
| @@ -2894,7 +3352,7 @@ dw2_map_expand_apply (struct objfile *objfile,
|
| all of them. */
|
| dw2_instantiate_symtab (per_cu);
|
|
|
| - return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
|
| + return iterate_over_some_symtabs (name, real_path, callback, data,
|
| objfile->symtabs, last_made);
|
| }
|
|
|
| @@ -2902,21 +3360,19 @@ dw2_map_expand_apply (struct objfile *objfile,
|
|
|
| static int
|
| dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| - const char *full_path, const char *real_path,
|
| + const char *real_path,
|
| int (*callback) (struct symtab *, void *),
|
| void *data)
|
| {
|
| int i;
|
| const char *name_basename = lbasename (name);
|
| - int name_len = strlen (name);
|
| - int is_abs = IS_ABSOLUTE_PATH (name);
|
|
|
| dw2_setup (objfile);
|
|
|
| - dw2_build_type_unit_groups ();
|
| + /* The rule is CUs specify all the files, including those used by
|
| + any TU, so there's no need to scan TUs here. */
|
|
|
| - for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
|
| {
|
| int j;
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| @@ -2926,22 +3382,21 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| if (per_cu->v.quick->symtab)
|
| continue;
|
|
|
| - file_data = dw2_get_file_names (objfile, per_cu);
|
| + file_data = dw2_get_file_names (per_cu);
|
| if (file_data == NULL)
|
| continue;
|
|
|
| for (j = 0; j < file_data->num_file_names; ++j)
|
| {
|
| const char *this_name = file_data->file_names[j];
|
| + const char *this_real_name;
|
|
|
| - if (FILENAME_CMP (name, this_name) == 0
|
| - || (!is_abs && compare_filenames_for_search (this_name,
|
| - name, name_len)))
|
| + if (compare_filenames_for_search (this_name, name))
|
| {
|
| - if (dw2_map_expand_apply (objfile, per_cu,
|
| - name, full_path, real_path,
|
| + if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
|
| callback, data))
|
| return 1;
|
| + continue;
|
| }
|
|
|
| /* Before we invoke realpath, which can get expensive when many
|
| @@ -2950,39 +3405,26 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| && FILENAME_CMP (lbasename (this_name), name_basename) != 0)
|
| continue;
|
|
|
| - if (full_path != NULL)
|
| + this_real_name = dw2_get_real_path (objfile, file_data, j);
|
| + if (compare_filenames_for_search (this_real_name, name))
|
| {
|
| - const char *this_real_name = dw2_get_real_path (objfile,
|
| - file_data, j);
|
| -
|
| - if (this_real_name != NULL
|
| - && (FILENAME_CMP (full_path, this_real_name) == 0
|
| - || (!is_abs
|
| - && compare_filenames_for_search (this_real_name,
|
| - name, name_len))))
|
| - {
|
| - if (dw2_map_expand_apply (objfile, per_cu,
|
| - name, full_path, real_path,
|
| - callback, data))
|
| - return 1;
|
| - }
|
| + if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
|
| + callback, data))
|
| + return 1;
|
| + continue;
|
| }
|
|
|
| if (real_path != NULL)
|
| {
|
| - const char *this_real_name = dw2_get_real_path (objfile,
|
| - file_data, j);
|
| -
|
| + gdb_assert (IS_ABSOLUTE_PATH (real_path));
|
| + gdb_assert (IS_ABSOLUTE_PATH (name));
|
| if (this_real_name != NULL
|
| - && (FILENAME_CMP (real_path, this_real_name) == 0
|
| - || (!is_abs
|
| - && compare_filenames_for_search (this_real_name,
|
| - name, name_len))))
|
| + && FILENAME_CMP (real_path, this_real_name) == 0)
|
| {
|
| - if (dw2_map_expand_apply (objfile, per_cu,
|
| - name, full_path, real_path,
|
| + if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
|
| callback, data))
|
| return 1;
|
| + continue;
|
| }
|
| }
|
| }
|
| @@ -2991,122 +3433,241 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| return 0;
|
| }
|
|
|
| -static struct symtab *
|
| -dw2_lookup_symbol (struct objfile *objfile, int block_index,
|
| - const char *name, domain_enum domain)
|
| +/* Struct used to manage iterating over all CUs looking for a symbol. */
|
| +
|
| +struct dw2_symtab_iterator
|
| {
|
| - /* We do all the work in the pre_expand_symtabs_matching hook
|
| - instead. */
|
| - return NULL;
|
| -}
|
| + /* The internalized form of .gdb_index. */
|
| + struct mapped_index *index;
|
| + /* If non-zero, only look for symbols that match BLOCK_INDEX. */
|
| + int want_specific_block;
|
| + /* One of GLOBAL_BLOCK or STATIC_BLOCK.
|
| + Unused if !WANT_SPECIFIC_BLOCK. */
|
| + int block_index;
|
| + /* The kind of symbol we're looking for. */
|
| + domain_enum domain;
|
| + /* The list of CUs from the index entry of the symbol,
|
| + or NULL if not found. */
|
| + offset_type *vec;
|
| + /* The next element in VEC to look at. */
|
| + int next;
|
| + /* The number of elements in VEC, or zero if there is no match. */
|
| + int length;
|
| + /* Have we seen a global version of the symbol?
|
| + If so we can ignore all further global instances.
|
| + This is to work around gold/15646, inefficient gold-generated
|
| + indices. */
|
| + int global_seen;
|
| +};
|
|
|
| -/* A helper function that expands all symtabs that hold an object
|
| - named NAME. If WANT_SPECIFIC_BLOCK is non-zero, only look for
|
| - symbols in block BLOCK_KIND. */
|
| +/* Initialize the index symtab iterator ITER.
|
| + If WANT_SPECIFIC_BLOCK is non-zero, only look for symbols
|
| + in block BLOCK_INDEX. Otherwise BLOCK_INDEX is ignored. */
|
|
|
| static void
|
| -dw2_do_expand_symtabs_matching (struct objfile *objfile,
|
| - int want_specific_block,
|
| - enum block_enum block_kind,
|
| - const char *name, domain_enum domain)
|
| +dw2_symtab_iter_init (struct dw2_symtab_iterator *iter,
|
| + struct mapped_index *index,
|
| + int want_specific_block,
|
| + int block_index,
|
| + domain_enum domain,
|
| + const char *name)
|
| +{
|
| + iter->index = index;
|
| + iter->want_specific_block = want_specific_block;
|
| + iter->block_index = block_index;
|
| + iter->domain = domain;
|
| + iter->next = 0;
|
| + iter->global_seen = 0;
|
| +
|
| + if (find_slot_in_mapped_hash (index, name, &iter->vec))
|
| + iter->length = MAYBE_SWAP (*iter->vec);
|
| + else
|
| + {
|
| + iter->vec = NULL;
|
| + iter->length = 0;
|
| + }
|
| +}
|
| +
|
| +/* Return the next matching CU or NULL if there are no more. */
|
| +
|
| +static struct dwarf2_per_cu_data *
|
| +dw2_symtab_iter_next (struct dw2_symtab_iterator *iter)
|
| +{
|
| + for ( ; iter->next < iter->length; ++iter->next)
|
| + {
|
| + offset_type cu_index_and_attrs =
|
| + MAYBE_SWAP (iter->vec[iter->next + 1]);
|
| + offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
| + struct dwarf2_per_cu_data *per_cu;
|
| + int want_static = iter->block_index != GLOBAL_BLOCK;
|
| + /* This value is only valid for index versions >= 7. */
|
| + int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
| + gdb_index_symbol_kind symbol_kind =
|
| + GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
| + /* Only check the symbol attributes if they're present.
|
| + Indices prior to version 7 don't record them,
|
| + and indices >= 7 may elide them for certain symbols
|
| + (gold does this). */
|
| + int attrs_valid =
|
| + (iter->index->version >= 7
|
| + && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
|
| +
|
| + /* Don't crash on bad data. */
|
| + if (cu_index >= (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_units))
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _(".gdb_index entry has bad CU index"
|
| + " [in module %s]"),
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| + continue;
|
| + }
|
| +
|
| + per_cu = dw2_get_cu (cu_index);
|
| +
|
| + /* Skip if already read in. */
|
| + if (per_cu->v.quick->symtab)
|
| + continue;
|
| +
|
| + /* Check static vs global. */
|
| + if (attrs_valid)
|
| + {
|
| + if (iter->want_specific_block
|
| + && want_static != is_static)
|
| + continue;
|
| + /* Work around gold/15646. */
|
| + if (!is_static && iter->global_seen)
|
| + continue;
|
| + if (!is_static)
|
| + iter->global_seen = 1;
|
| + }
|
| +
|
| + /* Only check the symbol's kind if it has one. */
|
| + if (attrs_valid)
|
| + {
|
| + switch (iter->domain)
|
| + {
|
| + case VAR_DOMAIN:
|
| + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
|
| + && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
|
| + /* Some types are also in VAR_DOMAIN. */
|
| + && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
| + continue;
|
| + break;
|
| + case STRUCT_DOMAIN:
|
| + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
| + continue;
|
| + break;
|
| + case LABEL_DOMAIN:
|
| + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
| + continue;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + ++iter->next;
|
| + return per_cu;
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| +static struct symtab *
|
| +dw2_lookup_symbol (struct objfile *objfile, int block_index,
|
| + const char *name, domain_enum domain)
|
| {
|
| + struct symtab *stab_best = NULL;
|
| struct mapped_index *index;
|
|
|
| dw2_setup (objfile);
|
|
|
| index = dwarf2_per_objfile->index_table;
|
|
|
| - /* index_table is NULL if OBJF_READNOW. */
|
| + /* index is NULL if OBJF_READNOW. */
|
| if (index)
|
| {
|
| - offset_type *vec;
|
| + struct dw2_symtab_iterator iter;
|
| + struct dwarf2_per_cu_data *per_cu;
|
|
|
| - if (find_slot_in_mapped_hash (index, name, &vec))
|
| + dw2_symtab_iter_init (&iter, index, 1, block_index, domain, name);
|
| +
|
| + while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
|
| {
|
| - offset_type i, len = MAYBE_SWAP (*vec);
|
| - for (i = 0; i < len; ++i)
|
| + struct symbol *sym = NULL;
|
| + struct symtab *stab = dw2_instantiate_symtab (per_cu);
|
| +
|
| + /* Some caution must be observed with overloaded functions
|
| + and methods, since the index will not contain any overload
|
| + information (but NAME might contain it). */
|
| + if (stab->primary)
|
| {
|
| - offset_type cu_index_and_attrs = MAYBE_SWAP (vec[i + 1]);
|
| - offset_type cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
| - struct dwarf2_per_cu_data *per_cu = dw2_get_cu (cu_index);
|
| - int want_static = block_kind != GLOBAL_BLOCK;
|
| - /* This value is only valid for index versions >= 7. */
|
| - int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
| - gdb_index_symbol_kind symbol_kind =
|
| - GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
| -
|
| - if (want_specific_block
|
| - && index->version >= 7
|
| - && want_static != is_static)
|
| - continue;
|
| + struct blockvector *bv = BLOCKVECTOR (stab);
|
| + struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
|
|
|
| - /* Only check the symbol's kind if it has one.
|
| - Indices prior to version 7 don't record it. */
|
| - if (index->version >= 7)
|
| - {
|
| - switch (domain)
|
| - {
|
| - case VAR_DOMAIN:
|
| - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE
|
| - && symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION
|
| - /* Some types are also in VAR_DOMAIN. */
|
| - && symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
| - continue;
|
| - break;
|
| - case STRUCT_DOMAIN:
|
| - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
| - continue;
|
| - break;
|
| - case LABEL_DOMAIN:
|
| - if (symbol_kind != GDB_INDEX_SYMBOL_KIND_OTHER)
|
| - continue;
|
| - break;
|
| - default:
|
| - break;
|
| - }
|
| - }
|
| + sym = lookup_block_symbol (block, name, domain);
|
| + }
|
|
|
| - dw2_instantiate_symtab (per_cu);
|
| + if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
|
| + {
|
| + if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
|
| + return stab;
|
| +
|
| + stab_best = stab;
|
| }
|
| +
|
| + /* Keep looking through other CUs. */
|
| }
|
| }
|
| -}
|
|
|
| -static void
|
| -dw2_pre_expand_symtabs_matching (struct objfile *objfile,
|
| - enum block_enum block_kind, const char *name,
|
| - domain_enum domain)
|
| -{
|
| - dw2_do_expand_symtabs_matching (objfile, 1, block_kind, name, domain);
|
| + return stab_best;
|
| }
|
|
|
| static void
|
| dw2_print_stats (struct objfile *objfile)
|
| {
|
| - int i, count;
|
| + int i, total, count;
|
|
|
| dw2_setup (objfile);
|
| + total = dwarf2_per_objfile->n_comp_units + dwarf2_per_objfile->n_type_units;
|
| count = 0;
|
| - for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_units); ++i)
|
| + for (i = 0; i < total; ++i)
|
| {
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| if (!per_cu->v.quick->symtab)
|
| ++count;
|
| }
|
| + printf_filtered (_(" Number of read CUs: %d\n"), total - count);
|
| printf_filtered (_(" Number of unread CUs: %d\n"), count);
|
| }
|
|
|
| +/* This dumps minimal information about the index.
|
| + It is called via "mt print objfiles".
|
| + One use is to verify .gdb_index has been loaded by the
|
| + gdb.dwarf2/gdb-index.exp testcase. */
|
| +
|
| static void
|
| dw2_dump (struct objfile *objfile)
|
| {
|
| - /* Nothing worth printing. */
|
| + dw2_setup (objfile);
|
| + gdb_assert (dwarf2_per_objfile->using_index);
|
| + printf_filtered (".gdb_index:");
|
| + if (dwarf2_per_objfile->index_table != NULL)
|
| + {
|
| + printf_filtered (" version %d\n",
|
| + dwarf2_per_objfile->index_table->version);
|
| + }
|
| + else
|
| + printf_filtered (" faked for \"readnow\"\n");
|
| + printf_filtered ("\n");
|
| }
|
|
|
| static void
|
| -dw2_relocate (struct objfile *objfile, struct section_offsets *new_offsets,
|
| - struct section_offsets *delta)
|
| +dw2_relocate (struct objfile *objfile,
|
| + const struct section_offsets *new_offsets,
|
| + const struct section_offsets *delta)
|
| {
|
| /* There's nothing to relocate here. */
|
| }
|
| @@ -3115,9 +3676,25 @@ static void
|
| dw2_expand_symtabs_for_function (struct objfile *objfile,
|
| const char *func_name)
|
| {
|
| - /* Note: It doesn't matter what we pass for block_kind here. */
|
| - dw2_do_expand_symtabs_matching (objfile, 0, GLOBAL_BLOCK, func_name,
|
| - VAR_DOMAIN);
|
| + struct mapped_index *index;
|
| +
|
| + dw2_setup (objfile);
|
| +
|
| + index = dwarf2_per_objfile->index_table;
|
| +
|
| + /* index is NULL if OBJF_READNOW. */
|
| + if (index)
|
| + {
|
| + struct dw2_symtab_iterator iter;
|
| + struct dwarf2_per_cu_data *per_cu;
|
| +
|
| + /* Note: It doesn't matter what we pass for block_index here. */
|
| + dw2_symtab_iter_init (&iter, index, 0, GLOBAL_BLOCK, VAR_DOMAIN,
|
| + func_name);
|
| +
|
| + while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
|
| + dw2_instantiate_symtab (per_cu);
|
| + }
|
| }
|
|
|
| static void
|
| @@ -3137,8 +3714,8 @@ dw2_expand_all_symtabs (struct objfile *objfile)
|
| }
|
|
|
| static void
|
| -dw2_expand_symtabs_with_filename (struct objfile *objfile,
|
| - const char *filename)
|
| +dw2_expand_symtabs_with_fullname (struct objfile *objfile,
|
| + const char *fullname)
|
| {
|
| int i;
|
|
|
| @@ -3159,14 +3736,15 @@ dw2_expand_symtabs_with_filename (struct objfile *objfile,
|
| if (per_cu->v.quick->symtab)
|
| continue;
|
|
|
| - file_data = dw2_get_file_names (objfile, per_cu);
|
| + file_data = dw2_get_file_names (per_cu);
|
| if (file_data == NULL)
|
| continue;
|
|
|
| for (j = 0; j < file_data->num_file_names; ++j)
|
| {
|
| - const char *this_name = file_data->file_names[j];
|
| - if (FILENAME_CMP (this_name, filename) == 0)
|
| + const char *this_fullname = file_data->file_names[j];
|
| +
|
| + if (filename_cmp (this_fullname, fullname) == 0)
|
| {
|
| dw2_instantiate_symtab (per_cu);
|
| break;
|
| @@ -3175,77 +3753,10 @@ dw2_expand_symtabs_with_filename (struct objfile *objfile,
|
| }
|
| }
|
|
|
| -/* A helper function for dw2_find_symbol_file that finds the primary
|
| - file name for a given CU. This is a die_reader_func. */
|
| -
|
| -static void
|
| -dw2_get_primary_filename_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - struct die_info *comp_unit_die,
|
| - int has_children,
|
| - void *data)
|
| -{
|
| - const char **result_ptr = data;
|
| - struct dwarf2_cu *cu = reader->cu;
|
| - struct attribute *attr;
|
| -
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu);
|
| - if (attr == NULL)
|
| - *result_ptr = NULL;
|
| - else
|
| - *result_ptr = DW_STRING (attr);
|
| -}
|
| -
|
| -static const char *
|
| -dw2_find_symbol_file (struct objfile *objfile, const char *name)
|
| -{
|
| - struct dwarf2_per_cu_data *per_cu;
|
| - offset_type *vec;
|
| - struct quick_file_names *file_data;
|
| - const char *filename;
|
| -
|
| - dw2_setup (objfile);
|
| -
|
| - /* index_table is NULL if OBJF_READNOW. */
|
| - if (!dwarf2_per_objfile->index_table)
|
| - {
|
| - struct symtab *s;
|
| -
|
| - ALL_OBJFILE_PRIMARY_SYMTABS (objfile, s)
|
| - {
|
| - struct blockvector *bv = BLOCKVECTOR (s);
|
| - const struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
|
| - struct symbol *sym = lookup_block_symbol (block, name, VAR_DOMAIN);
|
| -
|
| - if (sym)
|
| - return sym->symtab->filename;
|
| - }
|
| - return NULL;
|
| - }
|
| -
|
| - if (!find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
|
| - name, &vec))
|
| - return NULL;
|
| -
|
| - /* Note that this just looks at the very first one named NAME -- but
|
| - actually we are looking for a function. find_main_filename
|
| - should be rewritten so that it doesn't require a custom hook. It
|
| - could just use the ordinary symbol tables. */
|
| - /* vec[0] is the length, which must always be >0. */
|
| - per_cu = dw2_get_cu (GDB_INDEX_CU_VALUE (MAYBE_SWAP (vec[1])));
|
| -
|
| - if (per_cu->v.quick->symtab != NULL)
|
| - return per_cu->v.quick->symtab->filename;
|
| -
|
| - init_cutu_and_read_dies (per_cu, NULL, 0, 0,
|
| - dw2_get_primary_filename_reader, &filename);
|
| -
|
| - return filename;
|
| -}
|
| -
|
| static void
|
| -dw2_map_matching_symbols (const char * name, domain_enum namespace,
|
| - struct objfile *objfile, int global,
|
| +dw2_map_matching_symbols (struct objfile *objfile,
|
| + const char * name, domain_enum namespace,
|
| + int global,
|
| int (*callback) (struct block *,
|
| struct symbol *, void *),
|
| void *data, symbol_compare_ftype *match,
|
| @@ -3259,7 +3770,7 @@ dw2_map_matching_symbols (const char * name, domain_enum namespace,
|
| static void
|
| dw2_expand_symtabs_matching
|
| (struct objfile *objfile,
|
| - int (*file_matcher) (const char *, void *),
|
| + int (*file_matcher) (const char *, void *, int basenames),
|
| int (*name_matcher) (const char *, void *),
|
| enum search_domain kind,
|
| void *data)
|
| @@ -3280,8 +3791,6 @@ dw2_expand_symtabs_matching
|
| struct cleanup *cleanup;
|
| htab_t visited_found, visited_not_found;
|
|
|
| - dw2_build_type_unit_groups ();
|
| -
|
| visited_found = htab_create_alloc (10,
|
| htab_hash_pointer, htab_eq_pointer,
|
| NULL, xcalloc, xfree);
|
| @@ -3291,8 +3800,10 @@ dw2_expand_symtabs_matching
|
| NULL, xcalloc, xfree);
|
| make_cleanup_htab_delete (visited_not_found);
|
|
|
| - for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| + /* The rule is CUs specify all the files, including those used by
|
| + any TU, so there's no need to scan TUs here. */
|
| +
|
| + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
|
| {
|
| int j;
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| @@ -3305,7 +3816,7 @@ dw2_expand_symtabs_matching
|
| if (per_cu->v.quick->symtab)
|
| continue;
|
|
|
| - file_data = dw2_get_file_names (objfile, per_cu);
|
| + file_data = dw2_get_file_names (per_cu);
|
| if (file_data == NULL)
|
| continue;
|
|
|
| @@ -3319,7 +3830,23 @@ dw2_expand_symtabs_matching
|
|
|
| for (j = 0; j < file_data->num_file_names; ++j)
|
| {
|
| - if (file_matcher (file_data->file_names[j], data))
|
| + const char *this_real_name;
|
| +
|
| + if (file_matcher (file_data->file_names[j], data, 0))
|
| + {
|
| + per_cu->v.quick->mark = 1;
|
| + break;
|
| + }
|
| +
|
| + /* Before we invoke realpath, which can get expensive when many
|
| + files are involved, do a quick comparison of the basenames. */
|
| + if (!basenames_may_differ
|
| + && !file_matcher (lbasename (file_data->file_names[j]),
|
| + data, 1))
|
| + continue;
|
| +
|
| + this_real_name = dw2_get_real_path (objfile, file_data, j);
|
| + if (file_matcher (this_real_name, data, 0))
|
| {
|
| per_cu->v.quick->mark = 1;
|
| break;
|
| @@ -3341,6 +3868,7 @@ dw2_expand_symtabs_matching
|
| offset_type idx = 2 * iter;
|
| const char *name;
|
| offset_type *vec, vec_len, vec_idx;
|
| + int global_seen = 0;
|
|
|
| if (index->symbol_table[idx] == 0 && index->symbol_table[idx + 1] == 0)
|
| continue;
|
| @@ -3359,18 +3887,30 @@ dw2_expand_symtabs_matching
|
| {
|
| struct dwarf2_per_cu_data *per_cu;
|
| offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
|
| + /* This value is only valid for index versions >= 7. */
|
| + int is_static = GDB_INDEX_SYMBOL_STATIC_VALUE (cu_index_and_attrs);
|
| gdb_index_symbol_kind symbol_kind =
|
| GDB_INDEX_SYMBOL_KIND_VALUE (cu_index_and_attrs);
|
| int cu_index = GDB_INDEX_CU_VALUE (cu_index_and_attrs);
|
| + /* Only check the symbol attributes if they're present.
|
| + Indices prior to version 7 don't record them,
|
| + and indices >= 7 may elide them for certain symbols
|
| + (gold does this). */
|
| + int attrs_valid =
|
| + (index->version >= 7
|
| + && symbol_kind != GDB_INDEX_SYMBOL_KIND_NONE);
|
| +
|
| + /* Work around gold/15646. */
|
| + if (attrs_valid)
|
| + {
|
| + if (!is_static && global_seen)
|
| + continue;
|
| + if (!is_static)
|
| + global_seen = 1;
|
| + }
|
|
|
| - /* Don't crash on bad data. */
|
| - if (cu_index >= (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_units))
|
| - continue;
|
| -
|
| - /* Only check the symbol's kind if it has one.
|
| - Indices prior to version 7 don't record it. */
|
| - if (index->version >= 7)
|
| + /* Only check the symbol's kind if it has one. */
|
| + if (attrs_valid)
|
| {
|
| switch (kind)
|
| {
|
| @@ -3391,6 +3931,16 @@ dw2_expand_symtabs_matching
|
| }
|
| }
|
|
|
| + /* Don't crash on bad data. */
|
| + if (cu_index >= (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_units))
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _(".gdb_index entry has bad CU index"
|
| + " [in module %s]"), objfile_name (objfile));
|
| + continue;
|
| + }
|
| +
|
| per_cu = dw2_get_cu (cu_index);
|
| if (file_matcher == NULL || per_cu->v.quick->mark)
|
| dw2_instantiate_symtab (per_cu);
|
| @@ -3465,11 +4015,11 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
|
| cleanup = make_cleanup_htab_delete (visited);
|
| dw2_setup (objfile);
|
|
|
| - dw2_build_type_unit_groups ();
|
| + /* The rule is CUs specify all the files, including those used by
|
| + any TU, so there's no need to scan TUs here.
|
| + We can ignore file names coming from already-expanded CUs. */
|
|
|
| - /* We can ignore file names coming from already-expanded CUs. */
|
| - for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_units); ++i)
|
| + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
|
| {
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| @@ -3482,8 +4032,7 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
|
| }
|
| }
|
|
|
| - for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
|
| {
|
| int j;
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| @@ -3494,7 +4043,7 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
|
| if (per_cu->v.quick->symtab)
|
| continue;
|
|
|
| - file_data = dw2_get_file_names (objfile, per_cu);
|
| + file_data = dw2_get_file_names (per_cu);
|
| if (file_data == NULL)
|
| continue;
|
|
|
| @@ -3534,14 +4083,12 @@ const struct quick_symbol_functions dwarf2_gdb_index_functions =
|
| dw2_forget_cached_source_info,
|
| dw2_map_symtabs_matching_filename,
|
| dw2_lookup_symbol,
|
| - dw2_pre_expand_symtabs_matching,
|
| dw2_print_stats,
|
| dw2_dump,
|
| dw2_relocate,
|
| dw2_expand_symtabs_for_function,
|
| dw2_expand_all_symtabs,
|
| - dw2_expand_symtabs_with_filename,
|
| - dw2_find_symbol_file,
|
| + dw2_expand_symtabs_with_fullname,
|
| dw2_map_matching_symbols,
|
| dw2_expand_symtabs_matching,
|
| dw2_find_pc_sect_symtab,
|
| @@ -3596,12 +4143,25 @@ dwarf2_initialize_objfile (struct objfile *objfile)
|
| void
|
| dwarf2_build_psymtabs (struct objfile *objfile)
|
| {
|
| + volatile struct gdb_exception except;
|
| +
|
| if (objfile->global_psymbols.size == 0 && objfile->static_psymbols.size == 0)
|
| {
|
| init_psymbol_list (objfile, 1024);
|
| }
|
|
|
| - dwarf2_build_psymtabs_hard (objfile);
|
| + TRY_CATCH (except, RETURN_MASK_ERROR)
|
| + {
|
| + /* This isn't really ideal: all the data we allocate on the
|
| + objfile's obstack is still uselessly kept around. However,
|
| + freeing it seems unsafe. */
|
| + struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile);
|
| +
|
| + dwarf2_build_psymtabs_hard (objfile);
|
| + discard_cleanups (cleanups);
|
| + }
|
| + if (except.reason < 0)
|
| + exception_print (gdb_stderr, except);
|
| }
|
|
|
| /* Return the total length of the CU described by HEADER. */
|
| @@ -3658,9 +4218,9 @@ dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu)
|
| NOTE: This leaves members offset, first_die_offset to be filled in
|
| by the caller. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_comp_unit_head (struct comp_unit_head *cu_header,
|
| - gdb_byte *info_ptr, bfd *abfd)
|
| + const gdb_byte *info_ptr, bfd *abfd)
|
| {
|
| int signed_addr;
|
| unsigned int bytes_read;
|
| @@ -3685,6 +4245,22 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
|
| return info_ptr;
|
| }
|
|
|
| +/* Helper function that returns the proper abbrev section for
|
| + THIS_CU. */
|
| +
|
| +static struct dwarf2_section_info *
|
| +get_abbrev_section_for_cu (struct dwarf2_per_cu_data *this_cu)
|
| +{
|
| + struct dwarf2_section_info *abbrev;
|
| +
|
| + if (this_cu->is_dwz)
|
| + abbrev = &dwarf2_get_dwz_file ()->abbrev;
|
| + else
|
| + abbrev = &dwarf2_per_objfile->abbrev;
|
| +
|
| + return abbrev;
|
| +}
|
| +
|
| /* Subroutine of read_and_check_comp_unit_head and
|
| read_and_check_type_unit_head to simplify them.
|
| Perform various error checking on the header. */
|
| @@ -3694,8 +4270,8 @@ error_check_comp_unit_head (struct comp_unit_head *header,
|
| struct dwarf2_section_info *section,
|
| struct dwarf2_section_info *abbrev_section)
|
| {
|
| - bfd *abfd = section->asection->owner;
|
| - const char *filename = bfd_get_filename (abfd);
|
| + bfd *abfd = get_section_bfd_owner (section);
|
| + const char *filename = get_section_file_name (section);
|
|
|
| if (header->version != 2 && header->version != 3 && header->version != 4)
|
| error (_("Dwarf Error: wrong version in compilation unit header "
|
| @@ -3703,8 +4279,7 @@ error_check_comp_unit_head (struct comp_unit_head *header,
|
| filename);
|
|
|
| if (header->abbrev_offset.sect_off
|
| - >= dwarf2_section_size (dwarf2_per_objfile->objfile,
|
| - &dwarf2_per_objfile->abbrev))
|
| + >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
|
| error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
|
| "(offset 0x%lx + 6) [in module %s]"),
|
| (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
|
| @@ -3724,15 +4299,15 @@ error_check_comp_unit_head (struct comp_unit_head *header,
|
| The contents of the header are stored in HEADER.
|
| The result is a pointer to the start of the first DIE. */
|
|
|
| -static gdb_byte *
|
| +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,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| int is_debug_types_section)
|
| {
|
| - gdb_byte *beg_of_comp_unit = info_ptr;
|
| - bfd *abfd = section->asection->owner;
|
| + const gdb_byte *beg_of_comp_unit = info_ptr;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
|
|
| header->offset.sect_off = beg_of_comp_unit - section->buffer;
|
|
|
| @@ -3753,16 +4328,16 @@ read_and_check_comp_unit_head (struct comp_unit_head *header,
|
| /* Read in the types comp unit header information from .debug_types entry at
|
| types_ptr. The result is a pointer to one past the end of the header. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_and_check_type_unit_head (struct comp_unit_head *header,
|
| struct dwarf2_section_info *section,
|
| struct dwarf2_section_info *abbrev_section,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| ULONGEST *signature,
|
| cu_offset *type_offset_in_tu)
|
| {
|
| - gdb_byte *beg_of_comp_unit = info_ptr;
|
| - bfd *abfd = section->asection->owner;
|
| + const gdb_byte *beg_of_comp_unit = info_ptr;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
|
|
| header->offset.sect_off = beg_of_comp_unit - section->buffer;
|
|
|
| @@ -3791,8 +4366,8 @@ static sect_offset
|
| read_abbrev_offset (struct dwarf2_section_info *section,
|
| sect_offset offset)
|
| {
|
| - bfd *abfd = section->asection->owner;
|
| - gdb_byte *info_ptr;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
| + const gdb_byte *info_ptr;
|
| unsigned int length, initial_length_size, offset_size;
|
| sect_offset abbrev_offset;
|
|
|
| @@ -3809,11 +4384,17 @@ read_abbrev_offset (struct dwarf2_section_info *section,
|
| partial symtab as being an include of PST. */
|
|
|
| static void
|
| -dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst,
|
| +dwarf2_create_include_psymtab (const char *name, struct partial_symtab *pst,
|
| struct objfile *objfile)
|
| {
|
| struct partial_symtab *subpst = allocate_psymtab (name, objfile);
|
|
|
| + if (!IS_ABSOLUTE_PATH (subpst->filename))
|
| + {
|
| + /* It shares objfile->objfile_obstack. */
|
| + subpst->dirname = pst->dirname;
|
| + }
|
| +
|
| subpst->section_offsets = pst->section_offsets;
|
| subpst->textlow = 0;
|
| subpst->texthigh = 0;
|
| @@ -3908,10 +4489,14 @@ add_signatured_type_cu_to_table (void **slot, void *datum)
|
| return 1;
|
| }
|
|
|
| -/* Create the hash table of all entries in the .debug_types section.
|
| - DWO_FILE is a pointer to the DWO file for .debug_types.dwo, NULL otherwise.
|
| - The result is a pointer to the hash table or NULL if there are
|
| - no types. */
|
| +/* Create the hash table of all entries in the .debug_types
|
| + (or .debug_types.dwo) section(s).
|
| + If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
|
| + otherwise it is NULL.
|
| +
|
| + The result is a pointer to the hash table or NULL if there are no types.
|
| +
|
| + Note: This function processes DWO files only, not DWP files. */
|
|
|
| static htab_t
|
| create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| @@ -3933,14 +4518,14 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| if (dwarf2_read_debug)
|
| fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n",
|
| dwo_file ? ".dwo" : "",
|
| - bfd_get_filename (abbrev_section->asection->owner));
|
| + get_section_file_name (abbrev_section));
|
|
|
| for (ix = 0;
|
| VEC_iterate (dwarf2_section_info_def, types, ix, section);
|
| ++ix)
|
| {
|
| bfd *abfd;
|
| - gdb_byte *info_ptr, *end_ptr;
|
| + const gdb_byte *info_ptr, *end_ptr;
|
|
|
| dwarf2_read_section (objfile, section);
|
| info_ptr = section->buffer;
|
| @@ -3949,16 +4534,8 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| continue;
|
|
|
| /* We can't set abfd until now because the section may be empty or
|
| - not present, in which case section->asection will be NULL. */
|
| - abfd = section->asection->owner;
|
| -
|
| - if (types_htab == NULL)
|
| - {
|
| - if (dwo_file)
|
| - types_htab = allocate_dwo_unit_table (objfile);
|
| - else
|
| - types_htab = allocate_signatured_type_table (objfile);
|
| - }
|
| + not present, in which case the bfd is unknown. */
|
| + abfd = get_section_bfd_owner (section);
|
|
|
| /* We don't use init_cutu_and_read_dies_simple, or some such, here
|
| because we don't need to read any dies: the signature is in the
|
| @@ -3973,7 +4550,7 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| struct signatured_type *sig_type;
|
| struct dwo_unit *dwo_tu;
|
| void **slot;
|
| - gdb_byte *ptr = info_ptr;
|
| + const gdb_byte *ptr = info_ptr;
|
| struct comp_unit_head header;
|
| unsigned int length;
|
|
|
| @@ -3996,6 +4573,14 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| continue;
|
| }
|
|
|
| + if (types_htab == NULL)
|
| + {
|
| + if (dwo_file)
|
| + types_htab = allocate_dwo_unit_table (objfile);
|
| + else
|
| + types_htab = allocate_signatured_type_table (objfile);
|
| + }
|
| +
|
| if (dwo_file)
|
| {
|
| sig_type = NULL;
|
| @@ -4004,7 +4589,7 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| dwo_tu->dwo_file = dwo_file;
|
| dwo_tu->signature = signature;
|
| dwo_tu->type_offset_in_tu = type_offset_in_tu;
|
| - dwo_tu->info_or_types_section = section;
|
| + dwo_tu->section = section;
|
| dwo_tu->offset = offset;
|
| dwo_tu->length = length;
|
| }
|
| @@ -4019,7 +4604,7 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| sig_type->type_offset_in_tu = type_offset_in_tu;
|
| sig_type->per_cu.objfile = objfile;
|
| sig_type->per_cu.is_debug_types = 1;
|
| - sig_type->per_cu.info_or_types_section = section;
|
| + sig_type->per_cu.section = section;
|
| sig_type->per_cu.offset = offset;
|
| sig_type->per_cu.length = length;
|
| }
|
| @@ -4046,17 +4631,17 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| }
|
|
|
| complaint (&symfile_complaints,
|
| - _("debug type entry at offset 0x%x is duplicate to the "
|
| - "entry at offset 0x%x, signature 0x%s"),
|
| + _("debug type entry at offset 0x%x is duplicate to"
|
| + " the entry at offset 0x%x, signature %s"),
|
| offset.sect_off, dup_offset.sect_off,
|
| - phex (signature, sizeof (signature)));
|
| + hex_string (signature));
|
| }
|
| *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
|
|
|
| - if (dwarf2_read_debug)
|
| - fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n",
|
| + if (dwarf2_read_debug > 1)
|
| + fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
|
| offset.sect_off,
|
| - phex (signature, sizeof (signature)));
|
| + hex_string (signature));
|
|
|
| info_ptr += length;
|
| }
|
| @@ -4087,9 +4672,8 @@ create_all_type_units (struct objfile *objfile)
|
|
|
| dwarf2_per_objfile->n_type_units = htab_elements (types_htab);
|
| dwarf2_per_objfile->all_type_units
|
| - = obstack_alloc (&objfile->objfile_obstack,
|
| - dwarf2_per_objfile->n_type_units
|
| - * sizeof (struct signatured_type *));
|
| + = xmalloc (dwarf2_per_objfile->n_type_units
|
| + * sizeof (struct signatured_type *));
|
| iter = &dwarf2_per_objfile->all_type_units[0];
|
| htab_traverse_noresize (types_htab, add_signatured_type_cu_to_table, &iter);
|
| gdb_assert (iter - &dwarf2_per_objfile->all_type_units[0]
|
| @@ -4098,24 +4682,205 @@ create_all_type_units (struct objfile *objfile)
|
| return 1;
|
| }
|
|
|
| -/* Lookup a signature based type for DW_FORM_ref_sig8.
|
| - Returns NULL if signature SIG is not present in the table. */
|
| +/* Subroutine of lookup_dwo_signatured_type and lookup_dwp_signatured_type.
|
| + Fill in SIG_ENTRY with DWO_ENTRY. */
|
| +
|
| +static void
|
| +fill_in_sig_entry_from_dwo_entry (struct objfile *objfile,
|
| + struct signatured_type *sig_entry,
|
| + struct dwo_unit *dwo_entry)
|
| +{
|
| + /* Make sure we're not clobbering something we don't expect to. */
|
| + gdb_assert (! sig_entry->per_cu.queued);
|
| + gdb_assert (sig_entry->per_cu.cu == NULL);
|
| + gdb_assert (sig_entry->per_cu.v.quick != NULL);
|
| + gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
|
| + gdb_assert (sig_entry->signature == dwo_entry->signature);
|
| + gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
|
| + gdb_assert (sig_entry->type_unit_group == NULL);
|
| + gdb_assert (sig_entry->dwo_unit == NULL);
|
| +
|
| + sig_entry->per_cu.section = dwo_entry->section;
|
| + sig_entry->per_cu.offset = dwo_entry->offset;
|
| + sig_entry->per_cu.length = dwo_entry->length;
|
| + sig_entry->per_cu.reading_dwo_directly = 1;
|
| + sig_entry->per_cu.objfile = objfile;
|
| + sig_entry->type_offset_in_tu = dwo_entry->type_offset_in_tu;
|
| + sig_entry->dwo_unit = dwo_entry;
|
| +}
|
| +
|
| +/* Subroutine of lookup_signatured_type.
|
| + If we haven't read the TU yet, create the signatured_type data structure
|
| + for a TU to be read in directly from a DWO file, bypassing the stub.
|
| + This is the "Stay in DWO Optimization": When there is no DWP file and we're
|
| + using .gdb_index, then when reading a CU we want to stay in the DWO file
|
| + containing that CU. Otherwise we could end up reading several other DWO
|
| + files (due to comdat folding) to process the transitive closure of all the
|
| + mentioned TUs, and that can be slow. The current DWO file will have every
|
| + type signature that it needs.
|
| + We only do this for .gdb_index because in the psymtab case we already have
|
| + to read all the DWOs to build the type unit groups. */
|
|
|
| static struct signatured_type *
|
| -lookup_signatured_type (ULONGEST sig)
|
| +lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
|
| {
|
| - struct signatured_type find_entry, *entry;
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwo_file *dwo_file;
|
| + struct dwo_unit find_dwo_entry, *dwo_entry;
|
| + struct signatured_type find_sig_entry, *sig_entry;
|
| +
|
| + gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
|
| +
|
| + /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
|
| + dwo_unit of the TU itself. */
|
| + dwo_file = cu->dwo_unit->dwo_file;
|
| +
|
| + /* We only ever need to read in one copy of a signatured type.
|
| + Just use the global signatured_types array. If this is the first time
|
| + we're reading this type, replace the recorded data from .gdb_index with
|
| + this TU. */
|
|
|
| if (dwarf2_per_objfile->signatured_types == NULL)
|
| + return NULL;
|
| + find_sig_entry.signature = sig;
|
| + sig_entry = htab_find (dwarf2_per_objfile->signatured_types, &find_sig_entry);
|
| + if (sig_entry == NULL)
|
| + return NULL;
|
| +
|
| + /* We can get here with the TU already read, *or* in the process of being
|
| + read. Don't reassign it if that's the case. Also note that if the TU is
|
| + already being read, it may not have come from a DWO, the program may be
|
| + a mix of Fission-compiled code and non-Fission-compiled code. */
|
| + /* Have we already tried to read this TU? */
|
| + if (sig_entry->per_cu.tu_read)
|
| + return sig_entry;
|
| +
|
| + /* Ok, this is the first time we're reading this TU. */
|
| + if (dwo_file->tus == NULL)
|
| + return NULL;
|
| + find_dwo_entry.signature = sig;
|
| + dwo_entry = htab_find (dwo_file->tus, &find_dwo_entry);
|
| + if (dwo_entry == NULL)
|
| + return NULL;
|
| +
|
| + fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
|
| + sig_entry->per_cu.tu_read = 1;
|
| + return sig_entry;
|
| +}
|
| +
|
| +/* Subroutine of lookup_dwp_signatured_type.
|
| + Add an entry for signature SIG to dwarf2_per_objfile->signatured_types. */
|
| +
|
| +static struct signatured_type *
|
| +add_type_unit (ULONGEST sig)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + int n_type_units = dwarf2_per_objfile->n_type_units;
|
| + struct signatured_type *sig_type;
|
| + void **slot;
|
| +
|
| + ++n_type_units;
|
| + dwarf2_per_objfile->all_type_units =
|
| + xrealloc (dwarf2_per_objfile->all_type_units,
|
| + n_type_units * sizeof (struct signatured_type *));
|
| + dwarf2_per_objfile->n_type_units = n_type_units;
|
| + sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + struct signatured_type);
|
| + dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
|
| + sig_type->signature = sig;
|
| + sig_type->per_cu.is_debug_types = 1;
|
| + sig_type->per_cu.v.quick =
|
| + OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + struct dwarf2_per_cu_quick_data);
|
| + slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
|
| + sig_type, INSERT);
|
| + gdb_assert (*slot == NULL);
|
| + *slot = sig_type;
|
| + /* The rest of sig_type must be filled in by the caller. */
|
| + return sig_type;
|
| +}
|
| +
|
| +/* Subroutine of lookup_signatured_type.
|
| + Look up the type for signature SIG, and if we can't find SIG in .gdb_index
|
| + then try the DWP file.
|
| + Normally this "can't happen", but if there's a bug in signature
|
| + generation and/or the DWP file is built incorrectly, it can happen.
|
| + Using the type directly from the DWP file means we don't have the stub
|
| + which has some useful attributes (e.g., DW_AT_comp_dir), but they're
|
| + not critical. [Eventually the stub may go away for type units anyway.] */
|
| +
|
| +static struct signatured_type *
|
| +lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwp_file *dwp_file = get_dwp_file ();
|
| + struct dwo_unit *dwo_entry;
|
| + struct signatured_type find_sig_entry, *sig_entry;
|
| +
|
| + gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
|
| + gdb_assert (dwp_file != NULL);
|
| +
|
| + if (dwarf2_per_objfile->signatured_types != NULL)
|
| {
|
| - complaint (&symfile_complaints,
|
| - _("missing `.debug_types' section for DW_FORM_ref_sig8 die"));
|
| - return NULL;
|
| + find_sig_entry.signature = sig;
|
| + sig_entry = htab_find (dwarf2_per_objfile->signatured_types,
|
| + &find_sig_entry);
|
| + if (sig_entry != NULL)
|
| + return sig_entry;
|
| + }
|
| +
|
| + /* This is the "shouldn't happen" case.
|
| + Try the DWP file and hope for the best. */
|
| + if (dwp_file->tus == NULL)
|
| + return NULL;
|
| + dwo_entry = lookup_dwo_unit_in_dwp (dwp_file, NULL,
|
| + sig, 1 /* is_debug_types */);
|
| + if (dwo_entry == NULL)
|
| + return NULL;
|
| +
|
| + sig_entry = add_type_unit (sig);
|
| + fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
|
| +
|
| + /* The caller will signal a complaint if we return NULL.
|
| + Here we don't return NULL but we still want to complain. */
|
| + complaint (&symfile_complaints,
|
| + _("Bad type signature %s referenced by %s at 0x%x,"
|
| + " coping by using copy in DWP [in module %s]"),
|
| + hex_string (sig),
|
| + cu->per_cu->is_debug_types ? "TU" : "CU",
|
| + cu->per_cu->offset.sect_off,
|
| + objfile_name (objfile));
|
| +
|
| + return sig_entry;
|
| +}
|
| +
|
| +/* Lookup a signature based type for DW_FORM_ref_sig8.
|
| + Returns NULL if signature SIG is not present in the table.
|
| + It is up to the caller to complain about this. */
|
| +
|
| +static struct signatured_type *
|
| +lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
|
| +{
|
| + if (cu->dwo_unit
|
| + && dwarf2_per_objfile->using_index)
|
| + {
|
| + /* We're in a DWO/DWP file, and we're using .gdb_index.
|
| + These cases require special processing. */
|
| + if (get_dwp_file () == NULL)
|
| + return lookup_dwo_signatured_type (cu, sig);
|
| + else
|
| + return lookup_dwp_signatured_type (cu, sig);
|
| }
|
| + else
|
| + {
|
| + struct signatured_type find_entry, *entry;
|
|
|
| - find_entry.signature = sig;
|
| - entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
|
| - return entry;
|
| + if (dwarf2_per_objfile->signatured_types == NULL)
|
| + return NULL;
|
| + find_entry.signature = sig;
|
| + entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
|
| + return entry;
|
| + }
|
| }
|
|
|
| /* Low level DIE reading support. */
|
| @@ -4129,12 +4894,349 @@ init_cu_die_reader (struct die_reader_specs *reader,
|
| struct dwo_file *dwo_file)
|
| {
|
| gdb_assert (section->readin && section->buffer != NULL);
|
| - reader->abfd = section->asection->owner;
|
| + reader->abfd = get_section_bfd_owner (section);
|
| reader->cu = cu;
|
| reader->dwo_file = dwo_file;
|
| reader->die_section = section;
|
| reader->buffer = section->buffer;
|
| reader->buffer_end = section->buffer + section->size;
|
| + reader->comp_dir = NULL;
|
| +}
|
| +
|
| +/* Subroutine of init_cutu_and_read_dies to simplify it.
|
| + Read in the rest of a CU/TU top level DIE from DWO_UNIT.
|
| + There's just a lot of work to do, and init_cutu_and_read_dies is big enough
|
| + already.
|
| +
|
| + STUB_COMP_UNIT_DIE is for the stub DIE, we copy over certain attributes
|
| + from it to the DIE in the DWO. If NULL we are skipping the stub.
|
| + STUB_COMP_DIR is similar to STUB_COMP_UNIT_DIE: When reading a TU directly
|
| + from the DWO file, bypassing the stub, it contains the DW_AT_comp_dir
|
| + attribute of the referencing CU. Exactly one of STUB_COMP_UNIT_DIE and
|
| + COMP_DIR must be non-NULL.
|
| + *RESULT_READER,*RESULT_INFO_PTR,*RESULT_COMP_UNIT_DIE,*RESULT_HAS_CHILDREN
|
| + are filled in with the info of the DIE from the DWO file.
|
| + ABBREV_TABLE_PROVIDED is non-zero if the caller of init_cutu_and_read_dies
|
| + provided an abbrev table to use.
|
| + The result is non-zero if a valid (non-dummy) DIE was found. */
|
| +
|
| +static int
|
| +read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu,
|
| + struct dwo_unit *dwo_unit,
|
| + int abbrev_table_provided,
|
| + struct die_info *stub_comp_unit_die,
|
| + const char *stub_comp_dir,
|
| + struct die_reader_specs *result_reader,
|
| + const gdb_byte **result_info_ptr,
|
| + struct die_info **result_comp_unit_die,
|
| + int *result_has_children)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_cu *cu = this_cu->cu;
|
| + struct dwarf2_section_info *section;
|
| + bfd *abfd;
|
| + const gdb_byte *begin_info_ptr, *info_ptr;
|
| + const char *comp_dir_string;
|
| + ULONGEST signature; /* Or dwo_id. */
|
| + struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
|
| + int i,num_extra_attrs;
|
| + struct dwarf2_section_info *dwo_abbrev_section;
|
| + struct attribute *attr;
|
| + struct attribute comp_dir_attr;
|
| + struct die_info *comp_unit_die;
|
| +
|
| + /* Both can't be provided. */
|
| + gdb_assert (! (stub_comp_unit_die && stub_comp_dir));
|
| +
|
| + /* These attributes aren't processed until later:
|
| + DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
|
| + However, the attribute is found in the stub which we won't have later.
|
| + In order to not impose this complication on the rest of the code,
|
| + we read them here and copy them to the DWO CU/TU die. */
|
| +
|
| + stmt_list = NULL;
|
| + low_pc = NULL;
|
| + high_pc = NULL;
|
| + ranges = NULL;
|
| + comp_dir = NULL;
|
| +
|
| + if (stub_comp_unit_die != NULL)
|
| + {
|
| + /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
|
| + DWO file. */
|
| + if (! this_cu->is_debug_types)
|
| + stmt_list = dwarf2_attr (stub_comp_unit_die, DW_AT_stmt_list, cu);
|
| + low_pc = dwarf2_attr (stub_comp_unit_die, DW_AT_low_pc, cu);
|
| + high_pc = dwarf2_attr (stub_comp_unit_die, DW_AT_high_pc, cu);
|
| + ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
|
| + comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
|
| +
|
| + /* There should be a DW_AT_addr_base attribute here (if needed).
|
| + We need the value before we can process DW_FORM_GNU_addr_index. */
|
| + cu->addr_base = 0;
|
| + attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_addr_base, cu);
|
| + if (attr)
|
| + cu->addr_base = DW_UNSND (attr);
|
| +
|
| + /* There should be a DW_AT_ranges_base attribute here (if needed).
|
| + We need the value before we can process DW_AT_ranges. */
|
| + cu->ranges_base = 0;
|
| + attr = dwarf2_attr (stub_comp_unit_die, DW_AT_GNU_ranges_base, cu);
|
| + if (attr)
|
| + cu->ranges_base = DW_UNSND (attr);
|
| + }
|
| + else if (stub_comp_dir != NULL)
|
| + {
|
| + /* Reconstruct the comp_dir attribute to simplify the code below. */
|
| + comp_dir = (struct attribute *)
|
| + obstack_alloc (&cu->comp_unit_obstack, sizeof (*comp_dir));
|
| + comp_dir->name = DW_AT_comp_dir;
|
| + comp_dir->form = DW_FORM_string;
|
| + DW_STRING_IS_CANONICAL (comp_dir) = 0;
|
| + DW_STRING (comp_dir) = stub_comp_dir;
|
| + }
|
| +
|
| + /* Set up for reading the DWO CU/TU. */
|
| + cu->dwo_unit = dwo_unit;
|
| + section = dwo_unit->section;
|
| + dwarf2_read_section (objfile, section);
|
| + abfd = get_section_bfd_owner (section);
|
| + begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
|
| + dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
|
| + init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file);
|
| +
|
| + if (this_cu->is_debug_types)
|
| + {
|
| + ULONGEST header_signature;
|
| + cu_offset type_offset_in_tu;
|
| + struct signatured_type *sig_type = (struct signatured_type *) this_cu;
|
| +
|
| + info_ptr = read_and_check_type_unit_head (&cu->header, section,
|
| + dwo_abbrev_section,
|
| + info_ptr,
|
| + &header_signature,
|
| + &type_offset_in_tu);
|
| + /* This is not an assert because it can be caused by bad debug info. */
|
| + if (sig_type->signature != header_signature)
|
| + {
|
| + error (_("Dwarf Error: signature mismatch %s vs %s while reading"
|
| + " TU at offset 0x%x [in module %s]"),
|
| + hex_string (sig_type->signature),
|
| + hex_string (header_signature),
|
| + dwo_unit->offset.sect_off,
|
| + bfd_get_filename (abfd));
|
| + }
|
| + gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
|
| + /* For DWOs coming from DWP files, we don't know the CU length
|
| + nor the type's offset in the TU until now. */
|
| + dwo_unit->length = get_cu_length (&cu->header);
|
| + dwo_unit->type_offset_in_tu = type_offset_in_tu;
|
| +
|
| + /* Establish the type offset that can be used to lookup the type.
|
| + For DWO files, we don't know it until now. */
|
| + sig_type->type_offset_in_section.sect_off =
|
| + dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
|
| + }
|
| + else
|
| + {
|
| + info_ptr = read_and_check_comp_unit_head (&cu->header, section,
|
| + dwo_abbrev_section,
|
| + info_ptr, 0);
|
| + gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
|
| + /* For DWOs coming from DWP files, we don't know the CU length
|
| + until now. */
|
| + dwo_unit->length = get_cu_length (&cu->header);
|
| + }
|
| +
|
| + /* Replace the CU's original abbrev table with the DWO's.
|
| + Reminder: We can't read the abbrev table until we've read the header. */
|
| + if (abbrev_table_provided)
|
| + {
|
| + /* Don't free the provided abbrev table, the caller of
|
| + init_cutu_and_read_dies owns it. */
|
| + dwarf2_read_abbrevs (cu, dwo_abbrev_section);
|
| + /* Ensure the DWO abbrev table gets freed. */
|
| + make_cleanup (dwarf2_free_abbrev_table, cu);
|
| + }
|
| + else
|
| + {
|
| + dwarf2_free_abbrev_table (cu);
|
| + dwarf2_read_abbrevs (cu, dwo_abbrev_section);
|
| + /* Leave any existing abbrev table cleanup as is. */
|
| + }
|
| +
|
| + /* Read in the die, but leave space to copy over the attributes
|
| + from the stub. This has the benefit of simplifying the rest of
|
| + the code - all the work to maintain the illusion of a single
|
| + DW_TAG_{compile,type}_unit DIE is done here. */
|
| + num_extra_attrs = ((stmt_list != NULL)
|
| + + (low_pc != NULL)
|
| + + (high_pc != NULL)
|
| + + (ranges != NULL)
|
| + + (comp_dir != NULL));
|
| + info_ptr = read_full_die_1 (result_reader, result_comp_unit_die, info_ptr,
|
| + result_has_children, num_extra_attrs);
|
| +
|
| + /* Copy over the attributes from the stub to the DIE we just read in. */
|
| + comp_unit_die = *result_comp_unit_die;
|
| + i = comp_unit_die->num_attrs;
|
| + if (stmt_list != NULL)
|
| + comp_unit_die->attrs[i++] = *stmt_list;
|
| + if (low_pc != NULL)
|
| + comp_unit_die->attrs[i++] = *low_pc;
|
| + if (high_pc != NULL)
|
| + comp_unit_die->attrs[i++] = *high_pc;
|
| + if (ranges != NULL)
|
| + comp_unit_die->attrs[i++] = *ranges;
|
| + if (comp_dir != NULL)
|
| + comp_unit_die->attrs[i++] = *comp_dir;
|
| + comp_unit_die->num_attrs += num_extra_attrs;
|
| +
|
| + if (dwarf2_die_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Read die from %s@0x%x of %s:\n",
|
| + get_section_name (section),
|
| + (unsigned) (begin_info_ptr - section->buffer),
|
| + bfd_get_filename (abfd));
|
| + dump_die (comp_unit_die, dwarf2_die_debug);
|
| + }
|
| +
|
| + /* Save the comp_dir attribute. If there is no DWP file then we'll read
|
| + TUs by skipping the stub and going directly to the entry in the DWO file.
|
| + However, skipping the stub means we won't get DW_AT_comp_dir, so we have
|
| + to get it via circuitous means. Blech. */
|
| + if (comp_dir != NULL)
|
| + result_reader->comp_dir = DW_STRING (comp_dir);
|
| +
|
| + /* Skip dummy compilation units. */
|
| + if (info_ptr >= begin_info_ptr + dwo_unit->length
|
| + || peek_abbrev_code (abfd, info_ptr) == 0)
|
| + return 0;
|
| +
|
| + *result_info_ptr = info_ptr;
|
| + return 1;
|
| +}
|
| +
|
| +/* Subroutine of init_cutu_and_read_dies to simplify it.
|
| + Look up the DWO unit specified by COMP_UNIT_DIE of THIS_CU.
|
| + Returns NULL if the specified DWO unit cannot be found. */
|
| +
|
| +static struct dwo_unit *
|
| +lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu,
|
| + struct die_info *comp_unit_die)
|
| +{
|
| + struct dwarf2_cu *cu = this_cu->cu;
|
| + struct attribute *attr;
|
| + ULONGEST signature;
|
| + struct dwo_unit *dwo_unit;
|
| + const char *comp_dir, *dwo_name;
|
| +
|
| + gdb_assert (cu != NULL);
|
| +
|
| + /* Yeah, we look dwo_name up again, but it simplifies the code. */
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
|
| + gdb_assert (attr != NULL);
|
| + dwo_name = DW_STRING (attr);
|
| + comp_dir = NULL;
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
|
| + if (attr)
|
| + comp_dir = DW_STRING (attr);
|
| +
|
| + if (this_cu->is_debug_types)
|
| + {
|
| + struct signatured_type *sig_type;
|
| +
|
| + /* Since this_cu is the first member of struct signatured_type,
|
| + we can go from a pointer to one to a pointer to the other. */
|
| + sig_type = (struct signatured_type *) this_cu;
|
| + signature = sig_type->signature;
|
| + dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir);
|
| + }
|
| + else
|
| + {
|
| + struct attribute *attr;
|
| +
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
|
| + if (! attr)
|
| + error (_("Dwarf Error: missing dwo_id for dwo_name %s"
|
| + " [in module %s]"),
|
| + dwo_name, objfile_name (this_cu->objfile));
|
| + signature = DW_UNSND (attr);
|
| + dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
|
| + signature);
|
| + }
|
| +
|
| + return dwo_unit;
|
| +}
|
| +
|
| +/* Subroutine of init_cutu_and_read_dies to simplify it.
|
| + Read a TU directly from a DWO file, bypassing the stub. */
|
| +
|
| +static void
|
| +init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, int keep,
|
| + die_reader_func_ftype *die_reader_func,
|
| + void *data)
|
| +{
|
| + struct dwarf2_cu *cu;
|
| + struct signatured_type *sig_type;
|
| + struct cleanup *cleanups, *free_cu_cleanup;
|
| + struct die_reader_specs reader;
|
| + const gdb_byte *info_ptr;
|
| + struct die_info *comp_unit_die;
|
| + int has_children;
|
| +
|
| + /* Verify we can do the following downcast, and that we have the
|
| + data we need. */
|
| + gdb_assert (this_cu->is_debug_types && this_cu->reading_dwo_directly);
|
| + sig_type = (struct signatured_type *) this_cu;
|
| + gdb_assert (sig_type->dwo_unit != NULL);
|
| +
|
| + cleanups = make_cleanup (null_cleanup, NULL);
|
| +
|
| + gdb_assert (this_cu->cu == NULL);
|
| + cu = xmalloc (sizeof (*cu));
|
| + init_one_comp_unit (cu, this_cu);
|
| + /* If an error occurs while loading, release our storage. */
|
| + free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
|
| +
|
| + if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
|
| + 0 /* abbrev_table_provided */,
|
| + NULL /* stub_comp_unit_die */,
|
| + sig_type->dwo_unit->dwo_file->comp_dir,
|
| + &reader, &info_ptr,
|
| + &comp_unit_die, &has_children) == 0)
|
| + {
|
| + /* Dummy die. */
|
| + do_cleanups (cleanups);
|
| + return;
|
| + }
|
| +
|
| + /* All the "real" work is done here. */
|
| + die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
|
| +
|
| + /* This duplicates some code in init_cutu_and_read_dies,
|
| + but the alternative is making the latter more complex.
|
| + This function is only for the special case of using DWO files directly:
|
| + no point in overly complicating the general case just to handle this. */
|
| + if (keep)
|
| + {
|
| + /* We've successfully allocated this compilation unit. Let our
|
| + caller clean it up when finished with it. */
|
| + discard_cleanups (free_cu_cleanup);
|
| +
|
| + /* We can only discard free_cu_cleanup and all subsequent cleanups.
|
| + So we have to manually free the abbrev table. */
|
| + dwarf2_free_abbrev_table (cu);
|
| +
|
| + /* Link this CU into read_in_chain. */
|
| + this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
|
| + dwarf2_per_objfile->read_in_chain = this_cu;
|
| + }
|
| + else
|
| + do_cleanups (free_cu_cleanup);
|
| +
|
| + do_cleanups (cleanups);
|
| }
|
|
|
| /* Initialize a CU (or TU) and read its DIEs.
|
| @@ -4161,10 +5263,10 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
| void *data)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - struct dwarf2_section_info *section = this_cu->info_or_types_section;
|
| - bfd *abfd = section->asection->owner;
|
| + struct dwarf2_section_info *section = this_cu->section;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
| struct dwarf2_cu *cu;
|
| - gdb_byte *begin_info_ptr, *info_ptr;
|
| + const gdb_byte *begin_info_ptr, *info_ptr;
|
| struct die_reader_specs reader;
|
| struct die_info *comp_unit_die;
|
| int has_children;
|
| @@ -4174,7 +5276,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
| struct dwarf2_section_info *abbrev_section;
|
| /* Non-zero if CU currently points to a DWO file and we need to
|
| reread it. When this happens we need to reread the skeleton die
|
| - before we can reread the DWO file. */
|
| + before we can reread the DWO file (this only applies to CUs, not TUs). */
|
| int rereading_dwo_cu = 0;
|
|
|
| if (dwarf2_die_debug)
|
| @@ -4185,13 +5287,26 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
| if (use_existing_cu)
|
| gdb_assert (keep);
|
|
|
| + /* If we're reading a TU directly from a DWO file, including a virtual DWO
|
| + file (instead of going through the stub), short-circuit all of this. */
|
| + if (this_cu->reading_dwo_directly)
|
| + {
|
| + /* Narrow down the scope of possibilities to have to understand. */
|
| + gdb_assert (this_cu->is_debug_types);
|
| + gdb_assert (abbrev_table == NULL);
|
| + gdb_assert (!use_existing_cu);
|
| + init_tu_and_read_dwo_dies (this_cu, keep, die_reader_func, data);
|
| + return;
|
| + }
|
| +
|
| cleanups = make_cleanup (null_cleanup, NULL);
|
|
|
| /* This is cheap if the section is already read in. */
|
| dwarf2_read_section (objfile, section);
|
|
|
| begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
|
| - abbrev_section = &dwarf2_per_objfile->abbrev;
|
| +
|
| + abbrev_section = get_abbrev_section_for_cu (this_cu);
|
|
|
| if (use_existing_cu && this_cu->cu != NULL)
|
| {
|
| @@ -4218,6 +5333,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
| free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
|
| }
|
|
|
| + /* Get the header. */
|
| if (cu->header.first_die_offset.cu_off != 0 && ! rereading_dwo_cu)
|
| {
|
| /* We already have the header, there's no need to read it in again. */
|
| @@ -4297,170 +5413,52 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
| init_cu_die_reader (&reader, cu, section, NULL);
|
| info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
|
|
|
| - /* If we have a DWO stub, process it and then read in the DWO file.
|
| - Note that if USE_EXISTING_OK != 0, and THIS_CU->cu already contains
|
| - a DWO CU, that this test will fail. */
|
| + /* If we are in a DWO stub, process it and then read in the "real" CU/TU
|
| + from the DWO file.
|
| + Note that if USE_EXISTING_OK != 0, and THIS_CU->cu already contains a
|
| + DWO CU, that this test will fail (the attribute will not be present). */
|
| attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu);
|
| if (attr)
|
| {
|
| - char *dwo_name = DW_STRING (attr);
|
| - const char *comp_dir_string;
|
| struct dwo_unit *dwo_unit;
|
| - ULONGEST signature; /* Or dwo_id. */
|
| - struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
|
| - int i,num_extra_attrs;
|
| - struct dwarf2_section_info *dwo_abbrev_section;
|
| + struct die_info *dwo_comp_unit_die;
|
|
|
| if (has_children)
|
| - error (_("Dwarf Error: compilation unit with DW_AT_GNU_dwo_name"
|
| - " has children (offset 0x%x) [in module %s]"),
|
| - this_cu->offset.sect_off, bfd_get_filename (abfd));
|
| -
|
| - /* These attributes aren't processed until later:
|
| - DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
|
| - However, the attribute is found in the stub which we won't have later.
|
| - In order to not impose this complication on the rest of the code,
|
| - we read them here and copy them to the DWO CU/TU die. */
|
| -
|
| - /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
|
| - DWO file. */
|
| - stmt_list = NULL;
|
| - if (! this_cu->is_debug_types)
|
| - stmt_list = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
|
| - low_pc = dwarf2_attr (comp_unit_die, DW_AT_low_pc, cu);
|
| - high_pc = dwarf2_attr (comp_unit_die, DW_AT_high_pc, cu);
|
| - ranges = dwarf2_attr (comp_unit_die, DW_AT_ranges, cu);
|
| - comp_dir = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
|
| -
|
| - /* There should be a DW_AT_addr_base attribute here (if needed).
|
| - We need the value before we can process DW_FORM_GNU_addr_index. */
|
| - cu->addr_base = 0;
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_addr_base, cu);
|
| - if (attr)
|
| - cu->addr_base = DW_UNSND (attr);
|
| -
|
| - /* There should be a DW_AT_ranges_base attribute here (if needed).
|
| - We need the value before we can process DW_AT_ranges. */
|
| - cu->ranges_base = 0;
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_ranges_base, cu);
|
| - if (attr)
|
| - cu->ranges_base = DW_UNSND (attr);
|
| -
|
| - if (this_cu->is_debug_types)
|
| - {
|
| - gdb_assert (sig_type != NULL);
|
| - signature = sig_type->signature;
|
| - }
|
| - else
|
| - {
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
|
| - if (! attr)
|
| - error (_("Dwarf Error: missing dwo_id [in module %s]"),
|
| - dwo_name);
|
| - signature = DW_UNSND (attr);
|
| - }
|
| -
|
| - /* We may need the comp_dir in order to find the DWO file. */
|
| - comp_dir_string = NULL;
|
| - if (comp_dir)
|
| - comp_dir_string = DW_STRING (comp_dir);
|
| -
|
| - if (this_cu->is_debug_types)
|
| - dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir_string);
|
| - else
|
| - dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir_string,
|
| - signature);
|
| -
|
| - if (dwo_unit == NULL)
|
| - {
|
| - error (_("Dwarf Error: CU at offset 0x%x references unknown DWO"
|
| - " with ID %s [in module %s]"),
|
| - this_cu->offset.sect_off,
|
| - phex (signature, sizeof (signature)),
|
| - objfile->name);
|
| - }
|
| -
|
| - /* Set up for reading the DWO CU/TU. */
|
| - cu->dwo_unit = dwo_unit;
|
| - section = dwo_unit->info_or_types_section;
|
| - begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off;
|
| - dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev;
|
| - init_cu_die_reader (&reader, cu, section, dwo_unit->dwo_file);
|
| -
|
| - if (this_cu->is_debug_types)
|
| - {
|
| - ULONGEST signature;
|
| -
|
| - info_ptr = read_and_check_type_unit_head (&cu->header, section,
|
| - dwo_abbrev_section,
|
| - info_ptr,
|
| - &signature, NULL);
|
| - gdb_assert (sig_type->signature == signature);
|
| - gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
|
| - gdb_assert (dwo_unit->length == get_cu_length (&cu->header));
|
| -
|
| - /* Establish the type offset that can be used to lookup the type.
|
| - For DWO files, we don't know it until now. */
|
| - sig_type->type_offset_in_section.sect_off =
|
| - dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off;
|
| - }
|
| - else
|
| {
|
| - info_ptr = read_and_check_comp_unit_head (&cu->header, section,
|
| - dwo_abbrev_section,
|
| - info_ptr, 0);
|
| - gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
|
| - gdb_assert (dwo_unit->length == get_cu_length (&cu->header));
|
| + complaint (&symfile_complaints,
|
| + _("compilation unit with DW_AT_GNU_dwo_name"
|
| + " has children (offset 0x%x) [in module %s]"),
|
| + this_cu->offset.sect_off, bfd_get_filename (abfd));
|
| }
|
| -
|
| - /* Discard the original CU's abbrev table, and read the DWO's. */
|
| - if (abbrev_table == NULL)
|
| + dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
|
| + if (dwo_unit != NULL)
|
| {
|
| - dwarf2_free_abbrev_table (cu);
|
| - dwarf2_read_abbrevs (cu, dwo_abbrev_section);
|
| + if (read_cutu_die_from_dwo (this_cu, dwo_unit,
|
| + abbrev_table != NULL,
|
| + comp_unit_die, NULL,
|
| + &reader, &info_ptr,
|
| + &dwo_comp_unit_die, &has_children) == 0)
|
| + {
|
| + /* Dummy die. */
|
| + do_cleanups (cleanups);
|
| + return;
|
| + }
|
| + comp_unit_die = dwo_comp_unit_die;
|
| }
|
| else
|
| {
|
| - dwarf2_read_abbrevs (cu, dwo_abbrev_section);
|
| - make_cleanup (dwarf2_free_abbrev_table, cu);
|
| - }
|
| -
|
| - /* Read in the die, but leave space to copy over the attributes
|
| - from the stub. This has the benefit of simplifying the rest of
|
| - the code - all the real work is done here. */
|
| - num_extra_attrs = ((stmt_list != NULL)
|
| - + (low_pc != NULL)
|
| - + (high_pc != NULL)
|
| - + (ranges != NULL)
|
| - + (comp_dir != NULL));
|
| - info_ptr = read_full_die_1 (&reader, &comp_unit_die, info_ptr,
|
| - &has_children, num_extra_attrs);
|
| -
|
| - /* Copy over the attributes from the stub to the DWO die. */
|
| - i = comp_unit_die->num_attrs;
|
| - if (stmt_list != NULL)
|
| - comp_unit_die->attrs[i++] = *stmt_list;
|
| - if (low_pc != NULL)
|
| - comp_unit_die->attrs[i++] = *low_pc;
|
| - if (high_pc != NULL)
|
| - comp_unit_die->attrs[i++] = *high_pc;
|
| - if (ranges != NULL)
|
| - comp_unit_die->attrs[i++] = *ranges;
|
| - if (comp_dir != NULL)
|
| - comp_unit_die->attrs[i++] = *comp_dir;
|
| - comp_unit_die->num_attrs += num_extra_attrs;
|
| -
|
| - /* Skip dummy compilation units. */
|
| - if (info_ptr >= begin_info_ptr + dwo_unit->length
|
| - || peek_abbrev_code (abfd, info_ptr) == 0)
|
| - {
|
| - do_cleanups (cleanups);
|
| - return;
|
| + /* Yikes, we couldn't find the rest of the DIE, we only have
|
| + the stub. A complaint has already been logged. There's
|
| + not much more we can do except pass on the stub DIE to
|
| + die_reader_func. We don't want to throw an error on bad
|
| + debug info. */
|
| }
|
| }
|
|
|
| + /* All of the above is setup for this call. Yikes. */
|
| die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
|
|
|
| + /* Done, clean up. */
|
| if (free_cu_cleanup != NULL)
|
| {
|
| if (keep)
|
| @@ -4486,8 +5484,8 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
|
|
| /* Read CU/TU THIS_CU in section SECTION,
|
| but do not follow DW_AT_GNU_dwo_name if present.
|
| - DWO_FILE, if non-NULL, is the DWO file to read (the caller is assumed to
|
| - have already done the lookup to find the DWO file).
|
| + DWOP_FILE, if non-NULL, is the DWO/DWP file to read (the caller is assumed
|
| + to have already done the lookup to find the DWO/DWP file).
|
|
|
| The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
|
| THIS_CU->is_debug_types, but nothing else.
|
| @@ -4509,10 +5507,10 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
|
| void *data)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - struct dwarf2_section_info *section = this_cu->info_or_types_section;
|
| - bfd *abfd = section->asection->owner;
|
| + struct dwarf2_section_info *section = this_cu->section;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
| struct dwarf2_cu cu;
|
| - gdb_byte *begin_info_ptr, *info_ptr;
|
| + const gdb_byte *begin_info_ptr, *info_ptr;
|
| struct die_reader_specs reader;
|
| struct cleanup *cleanups;
|
| struct die_info *comp_unit_die;
|
| @@ -4573,197 +5571,18 @@ init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu,
|
| void *data)
|
| {
|
| init_cutu_and_read_dies_no_follow (this_cu,
|
| - &dwarf2_per_objfile->abbrev,
|
| + get_abbrev_section_for_cu (this_cu),
|
| NULL,
|
| die_reader_func, data);
|
| }
|
| +
|
| +/* Type Unit Groups.
|
|
|
| -/* Create a psymtab named NAME and assign it to PER_CU.
|
| -
|
| - The caller must fill in the following details:
|
| - dirname, textlow, texthigh. */
|
| -
|
| -static struct partial_symtab *
|
| -create_partial_symtab (struct dwarf2_per_cu_data *per_cu, const char *name)
|
| -{
|
| - struct objfile *objfile = per_cu->objfile;
|
| - struct partial_symtab *pst;
|
| -
|
| - pst = start_psymtab_common (objfile, objfile->section_offsets,
|
| - name, 0,
|
| - objfile->global_psymbols.next,
|
| - objfile->static_psymbols.next);
|
| -
|
| - pst->psymtabs_addrmap_supported = 1;
|
| -
|
| - /* This is the glue that links PST into GDB's symbol API. */
|
| - pst->read_symtab_private = per_cu;
|
| - pst->read_symtab = dwarf2_psymtab_to_symtab;
|
| - per_cu->v.psymtab = pst;
|
| -
|
| - return pst;
|
| -}
|
| -
|
| -/* die_reader_func for process_psymtab_comp_unit. */
|
| -
|
| -static void
|
| -process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - struct die_info *comp_unit_die,
|
| - int has_children,
|
| - void *data)
|
| -{
|
| - struct dwarf2_cu *cu = reader->cu;
|
| - struct objfile *objfile = cu->objfile;
|
| - struct dwarf2_per_cu_data *per_cu = cu->per_cu;
|
| - struct attribute *attr;
|
| - CORE_ADDR baseaddr;
|
| - CORE_ADDR best_lowpc = 0, best_highpc = 0;
|
| - struct partial_symtab *pst;
|
| - int has_pc_info;
|
| - const char *filename;
|
| - int *want_partial_unit_ptr = data;
|
| -
|
| - if (comp_unit_die->tag == DW_TAG_partial_unit
|
| - && (want_partial_unit_ptr == NULL
|
| - || !*want_partial_unit_ptr))
|
| - return;
|
| -
|
| - gdb_assert (! per_cu->is_debug_types);
|
| -
|
| - prepare_one_comp_unit (cu, comp_unit_die, language_minimal);
|
| -
|
| - cu->list_in_scope = &file_symbols;
|
| -
|
| - /* Allocate a new partial symbol table structure. */
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu);
|
| - if (attr == NULL || !DW_STRING (attr))
|
| - filename = "";
|
| - else
|
| - filename = DW_STRING (attr);
|
| -
|
| - pst = create_partial_symtab (per_cu, filename);
|
| -
|
| - /* This must be done before calling dwarf2_build_include_psymtabs. */
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
|
| - if (attr != NULL)
|
| - pst->dirname = DW_STRING (attr);
|
| -
|
| - baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
| -
|
| - dwarf2_find_base_address (comp_unit_die, cu);
|
| -
|
| - /* Possibly set the default values of LOWPC and HIGHPC from
|
| - `DW_AT_ranges'. */
|
| - has_pc_info = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
|
| - &best_highpc, cu, pst);
|
| - if (has_pc_info == 1 && best_lowpc < best_highpc)
|
| - /* Store the contiguous range if it is not empty; it can be empty for
|
| - CUs with no code. */
|
| - addrmap_set_empty (objfile->psymtabs_addrmap,
|
| - best_lowpc + baseaddr,
|
| - best_highpc + baseaddr - 1, pst);
|
| -
|
| - /* Check if comp unit has_children.
|
| - If so, read the rest of the partial symbols from this comp unit.
|
| - If not, there's no more debug_info for this comp unit. */
|
| - if (has_children)
|
| - {
|
| - struct partial_die_info *first_die;
|
| - CORE_ADDR lowpc, highpc;
|
| -
|
| - lowpc = ((CORE_ADDR) -1);
|
| - highpc = ((CORE_ADDR) 0);
|
| -
|
| - first_die = load_partial_dies (reader, info_ptr, 1);
|
| -
|
| - scan_partial_symbols (first_die, &lowpc, &highpc,
|
| - ! has_pc_info, cu);
|
| -
|
| - /* If we didn't find a lowpc, set it to highpc to avoid
|
| - complaints from `maint check'. */
|
| - if (lowpc == ((CORE_ADDR) -1))
|
| - lowpc = highpc;
|
| -
|
| - /* If the compilation unit didn't have an explicit address range,
|
| - then use the information extracted from its child dies. */
|
| - if (! has_pc_info)
|
| - {
|
| - best_lowpc = lowpc;
|
| - best_highpc = highpc;
|
| - }
|
| - }
|
| - pst->textlow = best_lowpc + baseaddr;
|
| - pst->texthigh = best_highpc + baseaddr;
|
| -
|
| - pst->n_global_syms = objfile->global_psymbols.next -
|
| - (objfile->global_psymbols.list + pst->globals_offset);
|
| - pst->n_static_syms = objfile->static_psymbols.next -
|
| - (objfile->static_psymbols.list + pst->statics_offset);
|
| - sort_pst_symbols (pst);
|
| -
|
| - if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs))
|
| - {
|
| - int i;
|
| - int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs);
|
| - struct dwarf2_per_cu_data *iter;
|
| -
|
| - /* Fill in 'dependencies' here; we fill in 'users' in a
|
| - post-pass. */
|
| - pst->number_of_dependencies = len;
|
| - pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
|
| - len * sizeof (struct symtab *));
|
| - for (i = 0;
|
| - VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs,
|
| - i, iter);
|
| - ++i)
|
| - pst->dependencies[i] = iter->v.psymtab;
|
| -
|
| - VEC_free (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs);
|
| - }
|
| -
|
| - /* Get the list of files included in the current compilation unit,
|
| - and build a psymtab for each of them. */
|
| - dwarf2_build_include_psymtabs (cu, comp_unit_die, pst);
|
| -
|
| - if (dwarf2_read_debug)
|
| - {
|
| - struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
| -
|
| - fprintf_unfiltered (gdb_stdlog,
|
| - "Psymtab for %s unit @0x%x: 0x%s - 0x%s"
|
| - ", %d global, %d static syms\n",
|
| - per_cu->is_debug_types ? "type" : "comp",
|
| - per_cu->offset.sect_off,
|
| - paddress (gdbarch, pst->textlow),
|
| - paddress (gdbarch, pst->texthigh),
|
| - pst->n_global_syms, pst->n_static_syms);
|
| - }
|
| -}
|
| -
|
| -/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
| - Process compilation unit THIS_CU for a psymtab. */
|
| -
|
| -static void
|
| -process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| - int want_partial_unit)
|
| -{
|
| - /* If this compilation unit was already read in, free the
|
| - cached copy in order to read it in again. This is
|
| - necessary because we skipped some symbols when we first
|
| - read in the compilation unit (see load_partial_dies).
|
| - This problem could be avoided, but the benefit is unclear. */
|
| - if (this_cu->cu != NULL)
|
| - free_one_cached_comp_unit (this_cu);
|
| -
|
| - gdb_assert (! this_cu->is_debug_types);
|
| - init_cutu_and_read_dies (this_cu, NULL, 0, 0,
|
| - process_psymtab_comp_unit_reader,
|
| - &want_partial_unit);
|
| -
|
| - /* Age out any secondary CUs. */
|
| - age_cached_comp_units ();
|
| -}
|
| + Type Unit Groups are a way to collapse the set of all TUs (type units) into
|
| + a more manageable set. The grouping is done by DW_AT_stmt_list entry
|
| + so that all types coming from the same compilation (.o file) are grouped
|
| + together. A future step could be to put the types in the same symtab as
|
| + the CU the types ultimately came from. */
|
|
|
| static hashval_t
|
| hash_type_unit_group (const void *item)
|
| @@ -4816,14 +5635,11 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
|
| struct type_unit_group);
|
| per_cu = &tu_group->per_cu;
|
| per_cu->objfile = objfile;
|
| - per_cu->is_debug_types = 1;
|
| - per_cu->s.type_unit_group = tu_group;
|
|
|
| if (dwarf2_per_objfile->using_index)
|
| {
|
| per_cu->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| struct dwarf2_per_cu_quick_data);
|
| - tu_group->t.first_tu = cu->per_cu;
|
| }
|
| else
|
| {
|
| @@ -4854,7 +5670,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
|
| STMT_LIST is a DW_AT_stmt_list attribute. */
|
|
|
| static struct type_unit_group *
|
| -get_type_unit_group (struct dwarf2_cu *cu, struct attribute *stmt_list)
|
| +get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list)
|
| {
|
| struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
|
| struct type_unit_group *tu_group;
|
| @@ -5013,7 +5829,7 @@ build_type_unit_groups (die_reader_func_ftype *func, void *data)
|
|
|
| sorted_by_abbrev[i].sig_type = sig_type;
|
| sorted_by_abbrev[i].abbrev_offset =
|
| - read_abbrev_offset (sig_type->per_cu.info_or_types_section,
|
| + read_abbrev_offset (sig_type->per_cu.section,
|
| sig_type->per_cu.offset);
|
| }
|
| cleanups = make_cleanup (xfree, sorted_by_abbrev);
|
| @@ -5053,6 +5869,16 @@ build_type_unit_groups (die_reader_func_ftype *func, void *data)
|
| func, data);
|
| }
|
|
|
| + /* type_unit_groups can be NULL if there is an error in the debug info.
|
| + Just create an empty table so the rest of gdb doesn't have to watch
|
| + for this error case. */
|
| + if (dwarf2_per_objfile->type_unit_groups == NULL)
|
| + {
|
| + dwarf2_per_objfile->type_unit_groups =
|
| + allocate_type_unit_groups_table ();
|
| + dwarf2_per_objfile->n_type_unit_groups = 0;
|
| + }
|
| +
|
| /* Create a vector of pointers to primary type units to make it easy to
|
| iterate over them and CUs. See dw2_get_primary_cu. */
|
| dwarf2_per_objfile->n_type_unit_groups =
|
| @@ -5084,90 +5910,302 @@ build_type_unit_groups (die_reader_func_ftype *func, void *data)
|
| tu_stats->nr_stmt_less_type_units);
|
| }
|
| }
|
| +
|
| +/* Partial symbol tables. */
|
|
|
| -/* Reader function for build_type_psymtabs. */
|
| +/* Create a psymtab named NAME and assign it to PER_CU.
|
|
|
| -static void
|
| -build_type_psymtabs_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - struct die_info *type_unit_die,
|
| - int has_children,
|
| - void *data)
|
| + The caller must fill in the following details:
|
| + dirname, textlow, texthigh. */
|
| +
|
| +static struct partial_symtab *
|
| +create_partial_symtab (struct dwarf2_per_cu_data *per_cu, const char *name)
|
| {
|
| - struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - struct dwarf2_cu *cu = reader->cu;
|
| - struct dwarf2_per_cu_data *per_cu = cu->per_cu;
|
| - struct type_unit_group *tu_group;
|
| - struct attribute *attr;
|
| - struct partial_die_info *first_die;
|
| - CORE_ADDR lowpc, highpc;
|
| + struct objfile *objfile = per_cu->objfile;
|
| struct partial_symtab *pst;
|
|
|
| - gdb_assert (data == NULL);
|
| -
|
| - if (! has_children)
|
| - return;
|
| -
|
| - attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
|
| - tu_group = get_type_unit_group (cu, attr);
|
| -
|
| - VEC_safe_push (dwarf2_per_cu_ptr, tu_group->t.tus, per_cu);
|
| -
|
| - prepare_one_comp_unit (cu, type_unit_die, language_minimal);
|
| - cu->list_in_scope = &file_symbols;
|
| - pst = create_partial_symtab (per_cu, "");
|
| - pst->anonymous = 1;
|
| + pst = start_psymtab_common (objfile, objfile->section_offsets,
|
| + name, 0,
|
| + objfile->global_psymbols.next,
|
| + objfile->static_psymbols.next);
|
|
|
| - first_die = load_partial_dies (reader, info_ptr, 1);
|
| + pst->psymtabs_addrmap_supported = 1;
|
|
|
| - lowpc = (CORE_ADDR) -1;
|
| - highpc = (CORE_ADDR) 0;
|
| - scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
|
| + /* This is the glue that links PST into GDB's symbol API. */
|
| + pst->read_symtab_private = per_cu;
|
| + pst->read_symtab = dwarf2_read_symtab;
|
| + per_cu->v.psymtab = pst;
|
|
|
| - pst->n_global_syms = objfile->global_psymbols.next -
|
| - (objfile->global_psymbols.list + pst->globals_offset);
|
| - pst->n_static_syms = objfile->static_psymbols.next -
|
| - (objfile->static_psymbols.list + pst->statics_offset);
|
| - sort_pst_symbols (pst);
|
| + return pst;
|
| }
|
|
|
| -/* Traversal function for build_type_psymtabs. */
|
| +/* The DATA object passed to process_psymtab_comp_unit_reader has this
|
| + type. */
|
|
|
| -static int
|
| -build_type_psymtab_dependencies (void **slot, void *info)
|
| +struct process_psymtab_comp_unit_data
|
| {
|
| - struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
|
| - struct dwarf2_per_cu_data *per_cu = &tu_group->per_cu;
|
| - struct partial_symtab *pst = per_cu->v.psymtab;
|
| - int len = VEC_length (dwarf2_per_cu_ptr, tu_group->t.tus);
|
| - struct dwarf2_per_cu_data *iter;
|
| - int i;
|
| -
|
| - gdb_assert (len > 0);
|
| + /* True if we are reading a DW_TAG_partial_unit. */
|
|
|
| - pst->number_of_dependencies = len;
|
| - pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
|
| - len * sizeof (struct psymtab *));
|
| - for (i = 0;
|
| - VEC_iterate (dwarf2_per_cu_ptr, tu_group->t.tus, i, iter);
|
| - ++i)
|
| - {
|
| - pst->dependencies[i] = iter->v.psymtab;
|
| - iter->s.type_unit_group = tu_group;
|
| - }
|
| + int want_partial_unit;
|
|
|
| - VEC_free (dwarf2_per_cu_ptr, tu_group->t.tus);
|
| + /* The "pretend" language that is used if the CU doesn't declare a
|
| + language. */
|
|
|
| - return 1;
|
| -}
|
| + enum language pretend_language;
|
| +};
|
|
|
| -/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
| - Build partial symbol tables for the .debug_types comp-units. */
|
| +/* die_reader_func for process_psymtab_comp_unit. */
|
|
|
| static void
|
| -build_type_psymtabs (struct objfile *objfile)
|
| -{
|
| +process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
|
| + const gdb_byte *info_ptr,
|
| + struct die_info *comp_unit_die,
|
| + int has_children,
|
| + void *data)
|
| +{
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + struct objfile *objfile = cu->objfile;
|
| + struct dwarf2_per_cu_data *per_cu = cu->per_cu;
|
| + struct attribute *attr;
|
| + CORE_ADDR baseaddr;
|
| + CORE_ADDR best_lowpc = 0, best_highpc = 0;
|
| + struct partial_symtab *pst;
|
| + int has_pc_info;
|
| + const char *filename;
|
| + struct process_psymtab_comp_unit_data *info = data;
|
| +
|
| + if (comp_unit_die->tag == DW_TAG_partial_unit && !info->want_partial_unit)
|
| + return;
|
| +
|
| + gdb_assert (! per_cu->is_debug_types);
|
| +
|
| + prepare_one_comp_unit (cu, comp_unit_die, info->pretend_language);
|
| +
|
| + cu->list_in_scope = &file_symbols;
|
| +
|
| + /* Allocate a new partial symbol table structure. */
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu);
|
| + if (attr == NULL || !DW_STRING (attr))
|
| + filename = "";
|
| + else
|
| + filename = DW_STRING (attr);
|
| +
|
| + pst = create_partial_symtab (per_cu, filename);
|
| +
|
| + /* This must be done before calling dwarf2_build_include_psymtabs. */
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
|
| + if (attr != NULL)
|
| + pst->dirname = DW_STRING (attr);
|
| +
|
| + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
| +
|
| + dwarf2_find_base_address (comp_unit_die, cu);
|
| +
|
| + /* Possibly set the default values of LOWPC and HIGHPC from
|
| + `DW_AT_ranges'. */
|
| + has_pc_info = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc,
|
| + &best_highpc, cu, pst);
|
| + if (has_pc_info == 1 && best_lowpc < best_highpc)
|
| + /* Store the contiguous range if it is not empty; it can be empty for
|
| + CUs with no code. */
|
| + addrmap_set_empty (objfile->psymtabs_addrmap,
|
| + best_lowpc + baseaddr,
|
| + best_highpc + baseaddr - 1, pst);
|
| +
|
| + /* Check if comp unit has_children.
|
| + If so, read the rest of the partial symbols from this comp unit.
|
| + If not, there's no more debug_info for this comp unit. */
|
| + if (has_children)
|
| + {
|
| + struct partial_die_info *first_die;
|
| + CORE_ADDR lowpc, highpc;
|
| +
|
| + lowpc = ((CORE_ADDR) -1);
|
| + highpc = ((CORE_ADDR) 0);
|
| +
|
| + first_die = load_partial_dies (reader, info_ptr, 1);
|
| +
|
| + scan_partial_symbols (first_die, &lowpc, &highpc,
|
| + ! has_pc_info, cu);
|
| +
|
| + /* If we didn't find a lowpc, set it to highpc to avoid
|
| + complaints from `maint check'. */
|
| + if (lowpc == ((CORE_ADDR) -1))
|
| + lowpc = highpc;
|
| +
|
| + /* If the compilation unit didn't have an explicit address range,
|
| + then use the information extracted from its child dies. */
|
| + if (! has_pc_info)
|
| + {
|
| + best_lowpc = lowpc;
|
| + best_highpc = highpc;
|
| + }
|
| + }
|
| + pst->textlow = best_lowpc + baseaddr;
|
| + pst->texthigh = best_highpc + baseaddr;
|
| +
|
| + pst->n_global_syms = objfile->global_psymbols.next -
|
| + (objfile->global_psymbols.list + pst->globals_offset);
|
| + pst->n_static_syms = objfile->static_psymbols.next -
|
| + (objfile->static_psymbols.list + pst->statics_offset);
|
| + sort_pst_symbols (objfile, pst);
|
| +
|
| + if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs))
|
| + {
|
| + int i;
|
| + int len = VEC_length (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
|
| + struct dwarf2_per_cu_data *iter;
|
| +
|
| + /* Fill in 'dependencies' here; we fill in 'users' in a
|
| + post-pass. */
|
| + pst->number_of_dependencies = len;
|
| + pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
|
| + len * sizeof (struct symtab *));
|
| + for (i = 0;
|
| + VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
|
| + i, iter);
|
| + ++i)
|
| + pst->dependencies[i] = iter->v.psymtab;
|
| +
|
| + VEC_free (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs);
|
| + }
|
| +
|
| + /* Get the list of files included in the current compilation unit,
|
| + and build a psymtab for each of them. */
|
| + dwarf2_build_include_psymtabs (cu, comp_unit_die, pst);
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
| +
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Psymtab for %s unit @0x%x: %s - %s"
|
| + ", %d global, %d static syms\n",
|
| + per_cu->is_debug_types ? "type" : "comp",
|
| + per_cu->offset.sect_off,
|
| + paddress (gdbarch, pst->textlow),
|
| + paddress (gdbarch, pst->texthigh),
|
| + pst->n_global_syms, pst->n_static_syms);
|
| + }
|
| +}
|
| +
|
| +/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
| + Process compilation unit THIS_CU for a psymtab. */
|
| +
|
| +static void
|
| +process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| + int want_partial_unit,
|
| + enum language pretend_language)
|
| +{
|
| + struct process_psymtab_comp_unit_data info;
|
| +
|
| + /* If this compilation unit was already read in, free the
|
| + cached copy in order to read it in again. This is
|
| + necessary because we skipped some symbols when we first
|
| + read in the compilation unit (see load_partial_dies).
|
| + This problem could be avoided, but the benefit is unclear. */
|
| + if (this_cu->cu != NULL)
|
| + free_one_cached_comp_unit (this_cu);
|
| +
|
| + gdb_assert (! this_cu->is_debug_types);
|
| + info.want_partial_unit = want_partial_unit;
|
| + info.pretend_language = pretend_language;
|
| + init_cutu_and_read_dies (this_cu, NULL, 0, 0,
|
| + process_psymtab_comp_unit_reader,
|
| + &info);
|
| +
|
| + /* Age out any secondary CUs. */
|
| + age_cached_comp_units ();
|
| +}
|
| +
|
| +/* Reader function for build_type_psymtabs. */
|
| +
|
| +static void
|
| +build_type_psymtabs_reader (const struct die_reader_specs *reader,
|
| + const gdb_byte *info_ptr,
|
| + struct die_info *type_unit_die,
|
| + int has_children,
|
| + void *data)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + struct dwarf2_per_cu_data *per_cu = cu->per_cu;
|
| + struct signatured_type *sig_type;
|
| + struct type_unit_group *tu_group;
|
| + struct attribute *attr;
|
| + struct partial_die_info *first_die;
|
| + CORE_ADDR lowpc, highpc;
|
| + struct partial_symtab *pst;
|
| +
|
| + gdb_assert (data == NULL);
|
| + gdb_assert (per_cu->is_debug_types);
|
| + sig_type = (struct signatured_type *) per_cu;
|
| +
|
| + if (! has_children)
|
| + return;
|
| +
|
| + attr = dwarf2_attr_no_follow (type_unit_die, DW_AT_stmt_list);
|
| + tu_group = get_type_unit_group (cu, attr);
|
| +
|
| + VEC_safe_push (sig_type_ptr, tu_group->tus, sig_type);
|
| +
|
| + prepare_one_comp_unit (cu, type_unit_die, language_minimal);
|
| + cu->list_in_scope = &file_symbols;
|
| + pst = create_partial_symtab (per_cu, "");
|
| + pst->anonymous = 1;
|
| +
|
| + first_die = load_partial_dies (reader, info_ptr, 1);
|
| +
|
| + lowpc = (CORE_ADDR) -1;
|
| + highpc = (CORE_ADDR) 0;
|
| + scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
|
| +
|
| + pst->n_global_syms = objfile->global_psymbols.next -
|
| + (objfile->global_psymbols.list + pst->globals_offset);
|
| + pst->n_static_syms = objfile->static_psymbols.next -
|
| + (objfile->static_psymbols.list + pst->statics_offset);
|
| + sort_pst_symbols (objfile, pst);
|
| +}
|
| +
|
| +/* Traversal function for build_type_psymtabs. */
|
| +
|
| +static int
|
| +build_type_psymtab_dependencies (void **slot, void *info)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct type_unit_group *tu_group = (struct type_unit_group *) *slot;
|
| + struct dwarf2_per_cu_data *per_cu = &tu_group->per_cu;
|
| + struct partial_symtab *pst = per_cu->v.psymtab;
|
| + int len = VEC_length (sig_type_ptr, tu_group->tus);
|
| + struct signatured_type *iter;
|
| + int i;
|
| +
|
| + gdb_assert (len > 0);
|
| + gdb_assert (IS_TYPE_UNIT_GROUP (per_cu));
|
| +
|
| + pst->number_of_dependencies = len;
|
| + pst->dependencies = obstack_alloc (&objfile->objfile_obstack,
|
| + len * sizeof (struct psymtab *));
|
| + for (i = 0;
|
| + VEC_iterate (sig_type_ptr, tu_group->tus, i, iter);
|
| + ++i)
|
| + {
|
| + gdb_assert (iter->per_cu.is_debug_types);
|
| + pst->dependencies[i] = iter->per_cu.v.psymtab;
|
| + iter->type_unit_group = tu_group;
|
| + }
|
| +
|
| + VEC_free (sig_type_ptr, tu_group->tus);
|
| +
|
| + return 1;
|
| +}
|
| +
|
| +/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
| + Build partial symbol tables for the .debug_types comp-units. */
|
| +
|
| +static void
|
| +build_type_psymtabs (struct objfile *objfile)
|
| +{
|
| if (! create_all_type_units (objfile))
|
| return;
|
|
|
| @@ -5201,6 +6239,9 @@ set_partial_user (struct objfile *objfile)
|
| struct partial_symtab *pst = per_cu->v.psymtab;
|
| int j;
|
|
|
| + if (pst == NULL)
|
| + continue;
|
| +
|
| for (j = 0; j < pst->number_of_dependencies; ++j)
|
| {
|
| /* Set the 'user' field only if it is not already set. */
|
| @@ -5223,7 +6264,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
|
| if (dwarf2_read_debug)
|
| {
|
| fprintf_unfiltered (gdb_stdlog, "Building psymtabs of objfile %s ...\n",
|
| - objfile->name);
|
| + objfile_name (objfile));
|
| }
|
|
|
| dwarf2_per_objfile->reading_partial_symbols = 1;
|
| @@ -5249,7 +6290,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
|
| {
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| - process_psymtab_comp_unit (per_cu, 0);
|
| + process_psymtab_comp_unit (per_cu, 0, language_minimal);
|
| }
|
|
|
| set_partial_user (objfile);
|
| @@ -5262,14 +6303,14 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
|
|
|
| if (dwarf2_read_debug)
|
| fprintf_unfiltered (gdb_stdlog, "Done building psymtabs of %s\n",
|
| - objfile->name);
|
| + objfile_name (objfile));
|
| }
|
|
|
| /* die_reader_func for load_partial_comp_unit. */
|
|
|
| static void
|
| load_partial_comp_unit_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| struct die_info *comp_unit_die,
|
| int has_children,
|
| void *data)
|
| @@ -5295,38 +6336,37 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
|
| load_partial_comp_unit_reader, NULL);
|
| }
|
|
|
| -/* Create a list of all compilation units in OBJFILE.
|
| - This is only done for -readnow and building partial symtabs. */
|
| -
|
| static void
|
| -create_all_comp_units (struct objfile *objfile)
|
| +read_comp_units_from_section (struct objfile *objfile,
|
| + struct dwarf2_section_info *section,
|
| + unsigned int is_dwz,
|
| + int *n_allocated,
|
| + int *n_comp_units,
|
| + struct dwarf2_per_cu_data ***all_comp_units)
|
| {
|
| - int n_allocated;
|
| - int n_comp_units;
|
| - struct dwarf2_per_cu_data **all_comp_units;
|
| - gdb_byte *info_ptr;
|
| + const gdb_byte *info_ptr;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
|
|
| - dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
|
| - info_ptr = dwarf2_per_objfile->info.buffer;
|
| + if (dwarf2_read_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "Reading %s for %s\n",
|
| + get_section_name (section),
|
| + get_section_file_name (section));
|
|
|
| - n_comp_units = 0;
|
| - n_allocated = 10;
|
| - all_comp_units = xmalloc (n_allocated
|
| - * sizeof (struct dwarf2_per_cu_data *));
|
| + dwarf2_read_section (objfile, section);
|
| +
|
| + info_ptr = section->buffer;
|
|
|
| - while (info_ptr < dwarf2_per_objfile->info.buffer
|
| - + dwarf2_per_objfile->info.size)
|
| + while (info_ptr < section->buffer + section->size)
|
| {
|
| unsigned int length, initial_length_size;
|
| struct dwarf2_per_cu_data *this_cu;
|
| sect_offset offset;
|
|
|
| - offset.sect_off = info_ptr - dwarf2_per_objfile->info.buffer;
|
| + offset.sect_off = info_ptr - section->buffer;
|
|
|
| /* Read just enough information to find out where the next
|
| compilation unit is. */
|
| - length = read_initial_length (objfile->obfd, info_ptr,
|
| - &initial_length_size);
|
| + length = read_initial_length (abfd, info_ptr, &initial_length_size);
|
|
|
| /* Save the compilation unit for later lookup. */
|
| this_cu = obstack_alloc (&objfile->objfile_obstack,
|
| @@ -5334,37 +6374,65 @@ create_all_comp_units (struct objfile *objfile)
|
| memset (this_cu, 0, sizeof (*this_cu));
|
| this_cu->offset = offset;
|
| this_cu->length = length + initial_length_size;
|
| + this_cu->is_dwz = is_dwz;
|
| this_cu->objfile = objfile;
|
| - this_cu->info_or_types_section = &dwarf2_per_objfile->info;
|
| + this_cu->section = section;
|
|
|
| - if (n_comp_units == n_allocated)
|
| + if (*n_comp_units == *n_allocated)
|
| {
|
| - n_allocated *= 2;
|
| - all_comp_units = xrealloc (all_comp_units,
|
| - n_allocated
|
| - * sizeof (struct dwarf2_per_cu_data *));
|
| + *n_allocated *= 2;
|
| + *all_comp_units = xrealloc (*all_comp_units,
|
| + *n_allocated
|
| + * sizeof (struct dwarf2_per_cu_data *));
|
| }
|
| - all_comp_units[n_comp_units++] = this_cu;
|
| + (*all_comp_units)[*n_comp_units] = this_cu;
|
| + ++*n_comp_units;
|
|
|
| info_ptr = info_ptr + this_cu->length;
|
| }
|
| -
|
| - dwarf2_per_objfile->all_comp_units
|
| - = obstack_alloc (&objfile->objfile_obstack,
|
| - n_comp_units * sizeof (struct dwarf2_per_cu_data *));
|
| - memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units,
|
| - n_comp_units * sizeof (struct dwarf2_per_cu_data *));
|
| - xfree (all_comp_units);
|
| - dwarf2_per_objfile->n_comp_units = n_comp_units;
|
| }
|
|
|
| -/* Process all loaded DIEs for compilation unit CU, starting at
|
| - FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation
|
| - unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
|
| - DW_AT_ranges). If NEED_PC is set, then this function will set
|
| - *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
|
| - and record the covered ranges in the addrmap. */
|
| -
|
| +/* Create a list of all compilation units in OBJFILE.
|
| + This is only done for -readnow and building partial symtabs. */
|
| +
|
| +static void
|
| +create_all_comp_units (struct objfile *objfile)
|
| +{
|
| + int n_allocated;
|
| + int n_comp_units;
|
| + struct dwarf2_per_cu_data **all_comp_units;
|
| + struct dwz_file *dwz;
|
| +
|
| + n_comp_units = 0;
|
| + n_allocated = 10;
|
| + all_comp_units = xmalloc (n_allocated
|
| + * sizeof (struct dwarf2_per_cu_data *));
|
| +
|
| + read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, 0,
|
| + &n_allocated, &n_comp_units, &all_comp_units);
|
| +
|
| + dwz = dwarf2_get_dwz_file ();
|
| + if (dwz != NULL)
|
| + read_comp_units_from_section (objfile, &dwz->info, 1,
|
| + &n_allocated, &n_comp_units,
|
| + &all_comp_units);
|
| +
|
| + dwarf2_per_objfile->all_comp_units
|
| + = obstack_alloc (&objfile->objfile_obstack,
|
| + n_comp_units * sizeof (struct dwarf2_per_cu_data *));
|
| + memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units,
|
| + n_comp_units * sizeof (struct dwarf2_per_cu_data *));
|
| + xfree (all_comp_units);
|
| + dwarf2_per_objfile->n_comp_units = n_comp_units;
|
| +}
|
| +
|
| +/* Process all loaded DIEs for compilation unit CU, starting at
|
| + FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation
|
| + unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
|
| + DW_AT_ranges). If NEED_PC is set, then this function will set
|
| + *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
|
| + and record the covered ranges in the addrmap. */
|
| +
|
| static void
|
| scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
|
| CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
|
| @@ -5436,20 +6504,24 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
|
| {
|
| error (_("Dwarf Error: DW_TAG_imported_unit is not"
|
| " supported in type units [in module %s]"),
|
| - cu->objfile->name);
|
| + objfile_name (cu->objfile));
|
| }
|
|
|
| per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
|
| + pdi->is_dwz,
|
| cu->objfile);
|
|
|
| /* Go read the partial unit, if needed. */
|
| if (per_cu->v.psymtab == NULL)
|
| - process_psymtab_comp_unit (per_cu, 1);
|
| + process_psymtab_comp_unit (per_cu, 1, cu->language);
|
|
|
| VEC_safe_push (dwarf2_per_cu_ptr,
|
| - cu->per_cu->s.imported_symtabs, per_cu);
|
| + cu->per_cu->imported_symtabs, per_cu);
|
| }
|
| break;
|
| + case DW_TAG_imported_declaration:
|
| + add_partial_symbol (pdi, cu);
|
| + break;
|
| default:
|
| break;
|
| }
|
| @@ -5485,11 +6557,11 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
|
| compilation unit CU. The result will be allocated on CU's
|
| comp_unit_obstack, or a copy of the already allocated PDI->NAME
|
| field. NULL is returned if no prefix is necessary. */
|
| -static char *
|
| +static const char *
|
| partial_die_parent_scope (struct partial_die_info *pdi,
|
| struct dwarf2_cu *cu)
|
| {
|
| - char *grandparent_scope;
|
| + const char *grandparent_scope;
|
| struct partial_die_info *parent, *real_pdi;
|
|
|
| /* We need to look at our parent DIE; if we have a DW_AT_specification,
|
| @@ -5497,7 +6569,8 @@ partial_die_parent_scope (struct partial_die_info *pdi,
|
|
|
| real_pdi = pdi;
|
| while (real_pdi->has_specification)
|
| - real_pdi = find_partial_die (real_pdi->spec_offset, cu);
|
| + real_pdi = find_partial_die (real_pdi->spec_offset,
|
| + real_pdi->spec_is_dwz, cu);
|
|
|
| parent = real_pdi->die_parent;
|
| if (parent == NULL)
|
| @@ -5563,7 +6636,7 @@ static char *
|
| partial_die_full_name (struct partial_die_info *pdi,
|
| struct dwarf2_cu *cu)
|
| {
|
| - char *parent_scope;
|
| + const char *parent_scope;
|
|
|
| /* If this is a template instantiation, we can not work out the
|
| template arguments from partial DIEs. So, unfortunately, we have
|
| @@ -5601,15 +6674,15 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| CORE_ADDR addr = 0;
|
| - char *actual_name = NULL;
|
| + const char *actual_name = NULL;
|
| CORE_ADDR baseaddr;
|
| - int built_actual_name = 0;
|
| + char *built_actual_name;
|
|
|
| baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
|
|
| - actual_name = partial_die_full_name (pdi, cu);
|
| - if (actual_name)
|
| - built_actual_name = 1;
|
| + built_actual_name = partial_die_full_name (pdi, cu);
|
| + if (built_actual_name != NULL)
|
| + actual_name = built_actual_name;
|
|
|
| if (actual_name == NULL)
|
| actual_name = pdi->name;
|
| @@ -5626,7 +6699,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
|
| mst_text, objfile); */
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_BLOCK,
|
| &objfile->global_psymbols,
|
| 0, pdi->lowpc + baseaddr,
|
| @@ -5637,7 +6710,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| /* prim_record_minimal_symbol (actual_name, pdi->lowpc + baseaddr,
|
| mst_file_text, objfile); */
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_BLOCK,
|
| &objfile->static_psymbols,
|
| 0, pdi->lowpc + baseaddr,
|
| @@ -5653,7 +6726,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| else
|
| list = &objfile->static_psymbols;
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name, VAR_DOMAIN, LOC_STATIC,
|
| + built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC,
|
| list, 0, 0, cu->language, objfile);
|
| }
|
| break;
|
| @@ -5687,7 +6760,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
|
|
| if (pdi->d.locdesc || pdi->has_type)
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_STATIC,
|
| &objfile->global_psymbols,
|
| 0, addr + baseaddr,
|
| @@ -5698,14 +6771,13 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| /* Static Variable. Skip symbols without location descriptors. */
|
| if (pdi->d.locdesc == NULL)
|
| {
|
| - if (built_actual_name)
|
| - xfree (actual_name);
|
| + xfree (built_actual_name);
|
| return;
|
| }
|
| /* prim_record_minimal_symbol (actual_name, addr + baseaddr,
|
| mst_file_data, objfile); */
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_STATIC,
|
| &objfile->static_psymbols,
|
| 0, addr + baseaddr,
|
| @@ -5716,14 +6788,15 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| case DW_TAG_base_type:
|
| case DW_TAG_subrange_type:
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_TYPEDEF,
|
| &objfile->static_psymbols,
|
| 0, (CORE_ADDR) 0, cu->language, objfile);
|
| break;
|
| + case DW_TAG_imported_declaration:
|
| case DW_TAG_namespace:
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_TYPEDEF,
|
| &objfile->global_psymbols,
|
| 0, (CORE_ADDR) 0, cu->language, objfile);
|
| @@ -5740,15 +6813,14 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| and that has a DW_AT_declaration attribute." */
|
| if (!pdi->has_byte_size && pdi->is_declaration)
|
| {
|
| - if (built_actual_name)
|
| - xfree (actual_name);
|
| + xfree (built_actual_name);
|
| return;
|
| }
|
|
|
| /* NOTE: carlton/2003-10-07: See comment in new_symbol about
|
| static vs. global. */
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| STRUCT_DOMAIN, LOC_TYPEDEF,
|
| (cu->language == language_cplus
|
| || cu->language == language_java)
|
| @@ -5759,7 +6831,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| break;
|
| case DW_TAG_enumerator:
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| - built_actual_name,
|
| + built_actual_name != NULL,
|
| VAR_DOMAIN, LOC_CONST,
|
| (cu->language == language_cplus
|
| || cu->language == language_java)
|
| @@ -5771,8 +6843,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| break;
|
| }
|
|
|
| - if (built_actual_name)
|
| - xfree (actual_name);
|
| + xfree (built_actual_name);
|
| }
|
|
|
| /* Read a partial die corresponding to a namespace; also, add a symbol
|
| @@ -5896,7 +6967,7 @@ add_partial_enumeration (struct partial_die_info *enum_pdi,
|
| /* Return the initial uleb128 in the die at INFO_PTR. */
|
|
|
| static unsigned int
|
| -peek_abbrev_code (bfd *abfd, gdb_byte *info_ptr)
|
| +peek_abbrev_code (bfd *abfd, const gdb_byte *info_ptr)
|
| {
|
| unsigned int bytes_read;
|
|
|
| @@ -5909,7 +6980,7 @@ peek_abbrev_code (bfd *abfd, gdb_byte *info_ptr)
|
| the initial number. */
|
|
|
| static struct abbrev_info *
|
| -peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read,
|
| +peek_die_abbrev (const gdb_byte *info_ptr, unsigned int *bytes_read,
|
| struct dwarf2_cu *cu)
|
| {
|
| bfd *abfd = cu->objfile->obfd;
|
| @@ -5935,8 +7006,8 @@ peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read,
|
| Returns a pointer to the end of a series of DIEs, terminated by an empty
|
| DIE. Any children of the skipped DIEs will also be skipped. */
|
|
|
| -static gdb_byte *
|
| -skip_children (const struct die_reader_specs *reader, gdb_byte *info_ptr)
|
| +static const gdb_byte *
|
| +skip_children (const struct die_reader_specs *reader, const gdb_byte *info_ptr)
|
| {
|
| struct dwarf2_cu *cu = reader->cu;
|
| struct abbrev_info *abbrev;
|
| @@ -5958,17 +7029,17 @@ skip_children (const struct die_reader_specs *reader, gdb_byte *info_ptr)
|
| ABBREV. Returns a pointer to this DIE's sibling, skipping any
|
| children. */
|
|
|
| -static gdb_byte *
|
| -skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| +static const gdb_byte *
|
| +skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr,
|
| struct abbrev_info *abbrev)
|
| {
|
| unsigned int bytes_read;
|
| struct attribute attr;
|
| bfd *abfd = reader->abfd;
|
| struct dwarf2_cu *cu = reader->cu;
|
| - gdb_byte *buffer = reader->buffer;
|
| + const gdb_byte *buffer = reader->buffer;
|
| const gdb_byte *buffer_end = reader->buffer_end;
|
| - gdb_byte *start_info_ptr = info_ptr;
|
| + const gdb_byte *start_info_ptr = info_ptr;
|
| unsigned int form, i;
|
|
|
| for (i = 0; i < abbrev->num_attrs; i++)
|
| @@ -5981,7 +7052,16 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| complaint (&symfile_complaints,
|
| _("ignoring absolute DW_AT_sibling"));
|
| else
|
| - return buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
|
| + {
|
| + unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
|
| + const gdb_byte *sibling_ptr = buffer + off;
|
| +
|
| + if (sibling_ptr < info_ptr)
|
| + complaint (&symfile_complaints,
|
| + _("DW_AT_sibling points backwards"));
|
| + else
|
| + return sibling_ptr;
|
| + }
|
| }
|
|
|
| /* If it isn't DW_AT_sibling, skip this attribute. */
|
| @@ -5997,6 +7077,9 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| else
|
| info_ptr += cu->header.offset_size;
|
| break;
|
| + case DW_FORM_GNU_ref_alt:
|
| + info_ptr += cu->header.offset_size;
|
| + break;
|
| case DW_FORM_addr:
|
| info_ptr += cu->header.addr_size;
|
| break;
|
| @@ -6026,6 +7109,7 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| break;
|
| case DW_FORM_sec_offset:
|
| case DW_FORM_strp:
|
| + case DW_FORM_GNU_strp_alt:
|
| info_ptr += cu->header.offset_size;
|
| break;
|
| case DW_FORM_exprloc:
|
| @@ -6047,7 +7131,7 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| case DW_FORM_ref_udata:
|
| case DW_FORM_GNU_addr_index:
|
| case DW_FORM_GNU_str_index:
|
| - info_ptr = (gdb_byte *) safe_skip_leb128 (info_ptr, buffer_end);
|
| + info_ptr = safe_skip_leb128 (info_ptr, buffer_end);
|
| break;
|
| case DW_FORM_indirect:
|
| form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
| @@ -6073,10 +7157,10 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| /* Locate ORIG_PDI's sibling.
|
| INFO_PTR should point to the start of the next DIE after ORIG_PDI. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| locate_pdi_sibling (const struct die_reader_specs *reader,
|
| struct partial_die_info *orig_pdi,
|
| - gdb_byte *info_ptr)
|
| + const gdb_byte *info_ptr)
|
| {
|
| /* Do we know the sibling already? */
|
|
|
| @@ -6093,53 +7177,51 @@ locate_pdi_sibling (const struct die_reader_specs *reader,
|
| return skip_children (reader, info_ptr);
|
| }
|
|
|
| -/* Expand this partial symbol table into a full symbol table. */
|
| +/* Expand this partial symbol table into a full symbol table. SELF is
|
| + not NULL. */
|
|
|
| static void
|
| -dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
|
| +dwarf2_read_symtab (struct partial_symtab *self,
|
| + struct objfile *objfile)
|
| {
|
| - if (pst != NULL)
|
| + if (self->readin)
|
| + {
|
| + warning (_("bug: psymtab for %s is already read in."),
|
| + self->filename);
|
| + }
|
| + else
|
| {
|
| - if (pst->readin)
|
| + if (info_verbose)
|
| {
|
| - warning (_("bug: psymtab for %s is already read in."),
|
| - pst->filename);
|
| + printf_filtered (_("Reading in symbols for %s..."),
|
| + self->filename);
|
| + gdb_flush (gdb_stdout);
|
| }
|
| - else
|
| - {
|
| - if (info_verbose)
|
| - {
|
| - printf_filtered (_("Reading in symbols for %s..."),
|
| - pst->filename);
|
| - gdb_flush (gdb_stdout);
|
| - }
|
|
|
| - /* Restore our global data. */
|
| - dwarf2_per_objfile = objfile_data (pst->objfile,
|
| - dwarf2_objfile_data_key);
|
| + /* Restore our global data. */
|
| + dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
|
|
|
| - /* If this psymtab is constructed from a debug-only objfile, the
|
| - has_section_at_zero flag will not necessarily be correct. We
|
| - can get the correct value for this flag by looking at the data
|
| - associated with the (presumably stripped) associated objfile. */
|
| - if (pst->objfile->separate_debug_objfile_backlink)
|
| - {
|
| - struct dwarf2_per_objfile *dpo_backlink
|
| - = objfile_data (pst->objfile->separate_debug_objfile_backlink,
|
| - dwarf2_objfile_data_key);
|
| + /* If this psymtab is constructed from a debug-only objfile, the
|
| + has_section_at_zero flag will not necessarily be correct. We
|
| + can get the correct value for this flag by looking at the data
|
| + associated with the (presumably stripped) associated objfile. */
|
| + if (objfile->separate_debug_objfile_backlink)
|
| + {
|
| + struct dwarf2_per_objfile *dpo_backlink
|
| + = objfile_data (objfile->separate_debug_objfile_backlink,
|
| + dwarf2_objfile_data_key);
|
|
|
| - dwarf2_per_objfile->has_section_at_zero
|
| - = dpo_backlink->has_section_at_zero;
|
| - }
|
| + dwarf2_per_objfile->has_section_at_zero
|
| + = dpo_backlink->has_section_at_zero;
|
| + }
|
|
|
| - dwarf2_per_objfile->reading_partial_symbols = 0;
|
| + dwarf2_per_objfile->reading_partial_symbols = 0;
|
|
|
| - psymtab_to_symtab_1 (pst);
|
| + psymtab_to_symtab_1 (self);
|
|
|
| - /* Finish up the debug error message. */
|
| - if (info_verbose)
|
| - printf_filtered (_("done.\n"));
|
| - }
|
| + /* Finish up the debug error message. */
|
| + if (info_verbose)
|
| + printf_filtered (_("done.\n"));
|
| }
|
|
|
| process_cu_includes ();
|
| @@ -6169,13 +7251,17 @@ queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| dwarf2_queue_tail = item;
|
| }
|
|
|
| -/* THIS_CU has a reference to PER_CU. If necessary, load the new compilation
|
| - unit and add it to our queue.
|
| +/* If PER_CU is not yet queued, add it to the queue.
|
| + If DEPENDENT_CU is non-NULL, it has a reference to PER_CU so add a
|
| + dependency.
|
| The result is non-zero if PER_CU was queued, otherwise the result is zero
|
| - meaning either PER_CU is already queued or it is already loaded. */
|
| + meaning either PER_CU is already queued or it is already loaded.
|
| +
|
| + N.B. There is an invariant here that if a CU is queued then it is loaded.
|
| + The caller is required to load PER_CU if we return non-zero. */
|
|
|
| static int
|
| -maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
|
| +maybe_queue_comp_unit (struct dwarf2_cu *dependent_cu,
|
| struct dwarf2_per_cu_data *per_cu,
|
| enum language pretend_language)
|
| {
|
| @@ -6191,7 +7277,8 @@ maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
|
|
|
| /* Mark the dependence relation so that we don't flush PER_CU
|
| too early. */
|
| - dwarf2_add_dependence (this_cu, per_cu);
|
| + if (dependent_cu != NULL)
|
| + dwarf2_add_dependence (dependent_cu, per_cu);
|
|
|
| /* If it's already on the queue, we have nothing to do. */
|
| if (per_cu->queued)
|
| @@ -6222,7 +7309,7 @@ process_queue (void)
|
| {
|
| fprintf_unfiltered (gdb_stdlog,
|
| "Expanding one or more symtabs of objfile %s ...\n",
|
| - dwarf2_per_objfile->objfile->name);
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| }
|
|
|
| /* The queue starts out with one item, but following a DIE reference
|
| @@ -6234,27 +7321,37 @@ process_queue (void)
|
| : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
|
| {
|
| struct dwarf2_per_cu_data *per_cu = item->per_cu;
|
| + unsigned int debug_print_threshold;
|
| + char buf[100];
|
|
|
| - if (dwarf2_read_debug)
|
| + if (per_cu->is_debug_types)
|
| + {
|
| + struct signatured_type *sig_type =
|
| + (struct signatured_type *) per_cu;
|
| +
|
| + sprintf (buf, "TU %s at offset 0x%x",
|
| + hex_string (sig_type->signature),
|
| + per_cu->offset.sect_off);
|
| + /* There can be 100s of TUs.
|
| + Only print them in verbose mode. */
|
| + debug_print_threshold = 2;
|
| + }
|
| + else
|
| {
|
| - fprintf_unfiltered (gdb_stdlog,
|
| - "Expanding symtab of %s at offset 0x%x\n",
|
| - per_cu->is_debug_types ? "TU" : "CU",
|
| - per_cu->offset.sect_off);
|
| + sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off);
|
| + debug_print_threshold = 1;
|
| }
|
|
|
| + if (dwarf2_read_debug >= debug_print_threshold)
|
| + fprintf_unfiltered (gdb_stdlog, "Expanding symtab of %s\n", buf);
|
| +
|
| if (per_cu->is_debug_types)
|
| process_full_type_unit (per_cu, item->pretend_language);
|
| else
|
| process_full_comp_unit (per_cu, item->pretend_language);
|
|
|
| - if (dwarf2_read_debug)
|
| - {
|
| - fprintf_unfiltered (gdb_stdlog,
|
| - "Done expanding %s at offset 0x%x\n",
|
| - per_cu->is_debug_types ? "TU" : "CU",
|
| - per_cu->offset.sect_off);
|
| - }
|
| + if (dwarf2_read_debug >= debug_print_threshold)
|
| + fprintf_unfiltered (gdb_stdlog, "Done expanding %s\n", buf);
|
| }
|
|
|
| item->per_cu->queued = 0;
|
| @@ -6267,7 +7364,7 @@ process_queue (void)
|
| if (dwarf2_read_debug)
|
| {
|
| fprintf_unfiltered (gdb_stdlog, "Done expanding symtabs of %s.\n",
|
| - dwarf2_per_objfile->objfile->name);
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| }
|
| }
|
|
|
| @@ -6372,7 +7469,7 @@ die_eq (const void *item_lhs, const void *item_rhs)
|
|
|
| static void
|
| load_full_comp_unit_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| struct die_info *comp_unit_die,
|
| int has_children,
|
| void *data)
|
| @@ -6462,7 +7559,7 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
|
| const char *physname;
|
| struct fn_fieldlist *fn_flp
|
| = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
|
| - physname = dwarf2_physname ((char *) mi->name, mi->die, cu);
|
| + physname = dwarf2_physname (mi->name, mi->die, cu);
|
| fn_flp->fn_fields[mi->index].physname = physname ? physname : "";
|
| }
|
| }
|
| @@ -6505,9 +7602,9 @@ fixup_go_packaging (struct dwarf2_cu *cu)
|
| if (strcmp (package_name, this_package_name) != 0)
|
| complaint (&symfile_complaints,
|
| _("Symtab %s has objects from two different Go packages: %s and %s"),
|
| - (sym->symtab && sym->symtab->filename
|
| - ? sym->symtab->filename
|
| - : cu->objfile->name),
|
| + (SYMBOL_SYMTAB (sym)
|
| + ? symtab_to_filename_for_display (SYMBOL_SYMTAB (sym))
|
| + : objfile_name (cu->objfile)),
|
| this_package_name, package_name);
|
| xfree (this_package_name);
|
| }
|
| @@ -6518,19 +7615,23 @@ fixup_go_packaging (struct dwarf2_cu *cu)
|
| if (package_name != NULL)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| + const char *saved_package_name = obstack_copy0 (&objfile->objfile_obstack,
|
| + package_name,
|
| + strlen (package_name));
|
| struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
|
| - package_name, objfile);
|
| + saved_package_name, objfile);
|
| struct symbol *sym;
|
|
|
| TYPE_TAG_NAME (type) = TYPE_NAME (type);
|
|
|
| - sym = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
|
| - SYMBOL_SET_LANGUAGE (sym, language_go);
|
| - SYMBOL_SET_NAMES (sym, package_name, strlen (package_name), 1, objfile);
|
| + sym = allocate_symbol (objfile);
|
| + SYMBOL_SET_LANGUAGE (sym, language_go, &objfile->objfile_obstack);
|
| + SYMBOL_SET_NAMES (sym, saved_package_name,
|
| + strlen (saved_package_name), 0, objfile);
|
| /* This is not VAR_DOMAIN because we want a way to ensure a lookup of,
|
| e.g., "main" finds the "main" module and not C's main(). */
|
| SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
|
| - SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
|
| SYMBOL_TYPE (sym) = type;
|
|
|
| add_symbol_to_list (sym, &global_symbols);
|
| @@ -6539,8 +7640,6 @@ fixup_go_packaging (struct dwarf2_cu *cu)
|
| }
|
| }
|
|
|
| -static void compute_symtab_includes (struct dwarf2_per_cu_data *per_cu);
|
| -
|
| /* Return the symtab for PER_CU. This works properly regardless of
|
| whether we're using the index or psymtabs. */
|
|
|
| @@ -6556,12 +7655,14 @@ get_symtab (struct dwarf2_per_cu_data *per_cu)
|
| included by PER_CU. */
|
|
|
| static void
|
| -recursively_compute_inclusions (VEC (dwarf2_per_cu_ptr) **result,
|
| - htab_t all_children,
|
| - struct dwarf2_per_cu_data *per_cu)
|
| +recursively_compute_inclusions (VEC (symtab_ptr) **result,
|
| + htab_t all_children, htab_t all_type_symtabs,
|
| + struct dwarf2_per_cu_data *per_cu,
|
| + struct symtab *immediate_parent)
|
| {
|
| void **slot;
|
| int ix;
|
| + struct symtab *symtab;
|
| struct dwarf2_per_cu_data *iter;
|
|
|
| slot = htab_find_slot (all_children, per_cu, INSERT);
|
| @@ -6573,13 +7674,37 @@ recursively_compute_inclusions (VEC (dwarf2_per_cu_ptr) **result,
|
|
|
| *slot = per_cu;
|
| /* Only add a CU if it has a symbol table. */
|
| - if (get_symtab (per_cu) != NULL)
|
| - VEC_safe_push (dwarf2_per_cu_ptr, *result, per_cu);
|
| + symtab = get_symtab (per_cu);
|
| + if (symtab != NULL)
|
| + {
|
| + /* If this is a type unit only add its symbol table if we haven't
|
| + seen it yet (type unit per_cu's can share symtabs). */
|
| + if (per_cu->is_debug_types)
|
| + {
|
| + slot = htab_find_slot (all_type_symtabs, symtab, INSERT);
|
| + if (*slot == NULL)
|
| + {
|
| + *slot = symtab;
|
| + VEC_safe_push (symtab_ptr, *result, symtab);
|
| + if (symtab->user == NULL)
|
| + symtab->user = immediate_parent;
|
| + }
|
| + }
|
| + else
|
| + {
|
| + VEC_safe_push (symtab_ptr, *result, symtab);
|
| + if (symtab->user == NULL)
|
| + symtab->user = immediate_parent;
|
| + }
|
| + }
|
|
|
| for (ix = 0;
|
| - VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs, ix, iter);
|
| + VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs, ix, iter);
|
| ++ix)
|
| - recursively_compute_inclusions (result, all_children, iter);
|
| + {
|
| + recursively_compute_inclusions (result, all_children,
|
| + all_type_symtabs, iter, symtab);
|
| + }
|
| }
|
|
|
| /* Compute the symtab 'includes' fields for the symtab related to
|
| @@ -6590,12 +7715,13 @@ compute_symtab_includes (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| gdb_assert (! per_cu->is_debug_types);
|
|
|
| - if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs))
|
| + if (!VEC_empty (dwarf2_per_cu_ptr, per_cu->imported_symtabs))
|
| {
|
| int ix, len;
|
| - struct dwarf2_per_cu_data *iter;
|
| - VEC (dwarf2_per_cu_ptr) *result_children = NULL;
|
| - htab_t all_children;
|
| + struct dwarf2_per_cu_data *per_cu_iter;
|
| + struct symtab *symtab_iter;
|
| + VEC (symtab_ptr) *result_symtabs = NULL;
|
| + htab_t all_children, all_type_symtabs;
|
| struct symtab *symtab = get_symtab (per_cu);
|
|
|
| /* If we don't have a symtab, we can just skip this case. */
|
| @@ -6604,27 +7730,33 @@ compute_symtab_includes (struct dwarf2_per_cu_data *per_cu)
|
|
|
| all_children = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
|
| NULL, xcalloc, xfree);
|
| + all_type_symtabs = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
|
| + NULL, xcalloc, xfree);
|
|
|
| for (ix = 0;
|
| - VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs,
|
| - ix, iter);
|
| + VEC_iterate (dwarf2_per_cu_ptr, per_cu->imported_symtabs,
|
| + ix, per_cu_iter);
|
| ++ix)
|
| - recursively_compute_inclusions (&result_children, all_children, iter);
|
| + {
|
| + recursively_compute_inclusions (&result_symtabs, all_children,
|
| + all_type_symtabs, per_cu_iter,
|
| + symtab);
|
| + }
|
|
|
| - /* Now we have a transitive closure of all the included CUs, so
|
| - we can convert it to a list of symtabs. */
|
| - len = VEC_length (dwarf2_per_cu_ptr, result_children);
|
| + /* Now we have a transitive closure of all the included symtabs. */
|
| + len = VEC_length (symtab_ptr, result_symtabs);
|
| symtab->includes
|
| = obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
|
| (len + 1) * sizeof (struct symtab *));
|
| for (ix = 0;
|
| - VEC_iterate (dwarf2_per_cu_ptr, result_children, ix, iter);
|
| + VEC_iterate (symtab_ptr, result_symtabs, ix, symtab_iter);
|
| ++ix)
|
| - symtab->includes[ix] = get_symtab (iter);
|
| + symtab->includes[ix] = symtab_iter;
|
| symtab->includes[len] = NULL;
|
|
|
| - VEC_free (dwarf2_per_cu_ptr, result_children);
|
| + VEC_free (symtab_ptr, result_symtabs);
|
| htab_delete (all_children);
|
| + htab_delete (all_type_symtabs);
|
| }
|
| }
|
|
|
| @@ -6693,7 +7825,8 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| it, by scanning the DIE's below the compilation unit. */
|
| get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
|
|
|
| - static_block = end_symtab_get_static_block (highpc + baseaddr, objfile, 0);
|
| + static_block
|
| + = end_symtab_get_static_block (highpc + baseaddr, objfile, 0, 1);
|
|
|
| /* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
|
| Also, DW_AT_ranges may record ranges not belonging to any child DIEs
|
| @@ -6762,6 +7895,10 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
|
| struct objfile *objfile = per_cu->objfile;
|
| struct symtab *symtab;
|
| struct cleanup *back_to, *delayed_list_cleanup;
|
| + struct signatured_type *sig_type;
|
| +
|
| + gdb_assert (per_cu->is_debug_types);
|
| + sig_type = (struct signatured_type *) per_cu;
|
|
|
| buildsym_init ();
|
| back_to = make_cleanup (really_free_pendings, NULL);
|
| @@ -6789,10 +7926,10 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
|
| If this is the first TU to use this symtab, complete the construction
|
| of it with end_expandable_symtab. Otherwise, complete the addition of
|
| this TU's symbols to the existing symtab. */
|
| - if (per_cu->s.type_unit_group->primary_symtab == NULL)
|
| + if (sig_type->type_unit_group->primary_symtab == NULL)
|
| {
|
| symtab = end_expandable_symtab (0, objfile, SECT_OFF_TEXT (objfile));
|
| - per_cu->s.type_unit_group->primary_symtab = symtab;
|
| + sig_type->type_unit_group->primary_symtab = symtab;
|
|
|
| if (symtab != NULL)
|
| {
|
| @@ -6807,8 +7944,8 @@ process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
|
| else
|
| {
|
| augment_type_symtab (objfile,
|
| - per_cu->s.type_unit_group->primary_symtab);
|
| - symtab = per_cu->s.type_unit_group->primary_symtab;
|
| + sig_type->type_unit_group->primary_symtab);
|
| + symtab = sig_type->type_unit_group->primary_symtab;
|
| }
|
|
|
| if (dwarf2_per_objfile->using_index)
|
| @@ -6835,7 +7972,7 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| error (_("Dwarf Error: DW_TAG_imported_unit is not"
|
| " supported in type units [in module %s]"),
|
| - cu->objfile->name);
|
| + objfile_name (cu->objfile));
|
| }
|
|
|
| attr = dwarf2_attr (die, DW_AT_import, cu);
|
| @@ -6844,15 +7981,17 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
|
| struct dwarf2_per_cu_data *per_cu;
|
| struct symtab *imported_symtab;
|
| sect_offset offset;
|
| + int is_dwz;
|
|
|
| offset = dwarf2_get_ref_die_offset (attr);
|
| - per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
|
| + is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
|
| + per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile);
|
|
|
| - /* Queue the unit, if needed. */
|
| + /* If necessary, add it to the queue and load its DIEs. */
|
| if (maybe_queue_comp_unit (cu, per_cu, cu->language))
|
| load_full_comp_unit (per_cu, cu->language);
|
|
|
| - VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs,
|
| + VEC_safe_push (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs,
|
| per_cu);
|
| }
|
| }
|
| @@ -6920,16 +8059,20 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
|
| case DW_TAG_common_inclusion:
|
| break;
|
| case DW_TAG_namespace:
|
| - processing_has_namespace_info = 1;
|
| + cu->processing_has_namespace_info = 1;
|
| read_namespace (die, cu);
|
| break;
|
| case DW_TAG_module:
|
| - processing_has_namespace_info = 1;
|
| + cu->processing_has_namespace_info = 1;
|
| read_module (die, cu);
|
| break;
|
| case DW_TAG_imported_declaration:
|
| + cu->processing_has_namespace_info = 1;
|
| + if (read_namespace_alias (die, cu))
|
| + break;
|
| + /* The declaration is not a global namespace alias: fall through. */
|
| case DW_TAG_imported_module:
|
| - processing_has_namespace_info = 1;
|
| + cu->processing_has_namespace_info = 1;
|
| if (die->child != NULL && (die->tag == DW_TAG_imported_declaration
|
| || cu->language != language_fortran))
|
| complaint (&symfile_complaints, _("Tag '%s' has unexpected children"),
|
| @@ -6946,6 +8089,8 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
|
| break;
|
| }
|
| }
|
| +
|
| +/* DWARF name computation. */
|
|
|
| /* A helper function for dwarf2_compute_name which determines whether DIE
|
| needs to have the name of the scope prepended to the name listed in the
|
| @@ -6968,6 +8113,7 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu)
|
| case DW_TAG_enumerator:
|
| case DW_TAG_subprogram:
|
| case DW_TAG_member:
|
| + case DW_TAG_imported_declaration:
|
| return 1;
|
|
|
| case DW_TAG_variable:
|
| @@ -7031,7 +8177,8 @@ do_ui_file_peek_last (void *object, const char *buffer, long length)
|
| The result is allocated on the objfile_obstack and canonicalized. */
|
|
|
| static const char *
|
| -dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| +dwarf2_compute_name (const char *name,
|
| + struct die_info *die, struct dwarf2_cu *cu,
|
| int physname)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| @@ -7115,7 +8262,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| {
|
| struct type *type;
|
| LONGEST value;
|
| - gdb_byte *bytes;
|
| + const gdb_byte *bytes;
|
| struct dwarf2_locexpr_baton *baton;
|
| struct value *v;
|
|
|
| @@ -7143,7 +8290,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
|
|
| if (child->tag == DW_TAG_template_type_param)
|
| {
|
| - c_print_type (type, "", buf, -1, 0);
|
| + c_print_type (type, "", buf, -1, 0, &type_print_raw_options);
|
| continue;
|
| }
|
|
|
| @@ -7217,7 +8364,8 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| {
|
| struct type *type = read_type_die (die, cu);
|
|
|
| - c_type_print_args (type, buf, 1, cu->language);
|
| + c_type_print_args (type, buf, 1, cu->language,
|
| + &type_print_raw_options);
|
|
|
| if (cu->language == language_java)
|
| {
|
| @@ -7225,7 +8373,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| names. */
|
| if (die->tag == DW_TAG_subprogram)
|
| java_print_type (TYPE_TARGET_TYPE (type), "", buf,
|
| - 0, 0);
|
| + 0, 0, &type_print_raw_options);
|
| }
|
| else if (cu->language == language_cplus)
|
| {
|
| @@ -7249,7 +8397,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
|
|
| if (cu->language == language_cplus)
|
| {
|
| - char *cname
|
| + const char *cname
|
| = dwarf2_canonicalize_name (name, cu,
|
| &objfile->objfile_obstack);
|
|
|
| @@ -7271,7 +8419,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| The output string will be canonicalized (if C++/Java). */
|
|
|
| static const char *
|
| -dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| +dwarf2_full_name (const char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| return dwarf2_compute_name (name, die, cu, 0);
|
| }
|
| @@ -7284,7 +8432,7 @@ dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| The output string will be canonicalized (if C++/Java). */
|
|
|
| static const char *
|
| -dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| +dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| struct attribute *attr;
|
| @@ -7329,11 +8477,11 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| }
|
| else
|
| {
|
| - demangled = cplus_demangle (mangled,
|
| - (DMGL_PARAMS | DMGL_ANSI
|
| - | (cu->language == language_java
|
| - ? DMGL_JAVA | DMGL_RET_POSTFIX
|
| - : DMGL_RET_DROP)));
|
| + demangled = gdb_demangle (mangled,
|
| + (DMGL_PARAMS | DMGL_ANSI
|
| + | (cu->language == language_java
|
| + ? DMGL_JAVA | DMGL_RET_POSTFIX
|
| + : DMGL_RET_DROP)));
|
| }
|
| if (demangled)
|
| {
|
| @@ -7360,7 +8508,8 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("Computed physname <%s> does not match demangled <%s> "
|
| "(from linkage <%s>) - DIE at 0x%x [in module %s]"),
|
| - physname, canon, mangled, die->offset.sect_off, objfile->name);
|
| + physname, canon, mangled, die->offset.sect_off,
|
| + objfile_name (objfile));
|
|
|
| /* Prefer DW_AT_linkage_name (in the CANON form) - when it
|
| is available here - over computed PHYSNAME. It is safer
|
| @@ -7378,13 +8527,72 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| retval = canon;
|
|
|
| if (need_copy)
|
| - retval = obsavestring (retval, strlen (retval),
|
| - &objfile->objfile_obstack);
|
| + retval = obstack_copy0 (&objfile->objfile_obstack, retval, strlen (retval));
|
|
|
| do_cleanups (back_to);
|
| return retval;
|
| }
|
|
|
| +/* Inspect DIE in CU for a namespace alias. If one exists, record
|
| + a new symbol for it.
|
| +
|
| + Returns 1 if a namespace alias was recorded, 0 otherwise. */
|
| +
|
| +static int
|
| +read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + struct attribute *attr;
|
| +
|
| + /* If the die does not have a name, this is not a namespace
|
| + alias. */
|
| + attr = dwarf2_attr (die, DW_AT_name, cu);
|
| + if (attr != NULL)
|
| + {
|
| + int num;
|
| + struct die_info *d = die;
|
| + struct dwarf2_cu *imported_cu = cu;
|
| +
|
| + /* If the compiler has nested DW_AT_imported_declaration DIEs,
|
| + keep inspecting DIEs until we hit the underlying import. */
|
| +#define MAX_NESTED_IMPORTED_DECLARATIONS 100
|
| + for (num = 0; num < MAX_NESTED_IMPORTED_DECLARATIONS; ++num)
|
| + {
|
| + attr = dwarf2_attr (d, DW_AT_import, cu);
|
| + if (attr == NULL)
|
| + break;
|
| +
|
| + d = follow_die_ref (d, attr, &imported_cu);
|
| + if (d->tag != DW_TAG_imported_declaration)
|
| + break;
|
| + }
|
| +
|
| + if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("DIE at 0x%x has too many recursively imported "
|
| + "declarations"), d->offset.sect_off);
|
| + return 0;
|
| + }
|
| +
|
| + if (attr != NULL)
|
| + {
|
| + struct type *type;
|
| + sect_offset offset = dwarf2_get_ref_die_offset (attr);
|
| +
|
| + type = get_die_type_at_offset (offset, cu->per_cu);
|
| + if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE)
|
| + {
|
| + /* This declaration is a global namespace alias. Add
|
| + a symbol for it whose type is the aliased namespace. */
|
| + new_symbol (die, type, cu);
|
| + return 1;
|
| + }
|
| + }
|
| + }
|
| +
|
| + return 0;
|
| +}
|
| +
|
| /* Read the import statement specified by the given die and record it. */
|
|
|
| static void
|
| @@ -7403,8 +8611,6 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| VEC (const_char_ptr) *excludes = NULL;
|
| struct cleanup *cleanups;
|
|
|
| - char *temp;
|
| -
|
| import_attr = dwarf2_attr (die, DW_AT_import, cu);
|
| if (import_attr == NULL)
|
| {
|
| @@ -7470,14 +8676,9 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| canonical_name = imported_name_prefix;
|
| }
|
| else if (strlen (imported_name_prefix) > 0)
|
| - {
|
| - temp = alloca (strlen (imported_name_prefix)
|
| - + 2 + strlen (imported_name) + 1);
|
| - strcpy (temp, imported_name_prefix);
|
| - strcat (temp, "::");
|
| - strcat (temp, imported_name);
|
| - canonical_name = temp;
|
| - }
|
| + canonical_name = obconcat (&objfile->objfile_obstack,
|
| + imported_name_prefix, "::", imported_name,
|
| + (char *) NULL);
|
| else
|
| canonical_name = imported_name;
|
|
|
| @@ -7497,7 +8698,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("child DW_TAG_imported_declaration expected "
|
| "- DIE at 0x%x [in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| continue;
|
| }
|
|
|
| @@ -7518,7 +8719,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("child DW_TAG_imported_declaration has unknown "
|
| "imported name - DIE at 0x%x [in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| continue;
|
| }
|
|
|
| @@ -7532,6 +8733,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| import_alias,
|
| imported_declaration,
|
| excludes,
|
| + 0,
|
| &objfile->objfile_obstack);
|
|
|
| do_cleanups (cleanups);
|
| @@ -7548,9 +8750,22 @@ free_cu_line_header (void *arg)
|
| cu->line_header = NULL;
|
| }
|
|
|
| +/* Check for possibly missing DW_AT_comp_dir with relative .debug_line
|
| + directory paths. GCC SVN r127613 (new option -fdebug-prefix-map) fixed
|
| + this, it was first present in GCC release 4.3.0. */
|
| +
|
| +static int
|
| +producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu)
|
| +{
|
| + if (!cu->checked_producer)
|
| + check_producer (cu);
|
| +
|
| + return cu->producer_is_gcc_lt_4_3;
|
| +}
|
| +
|
| static void
|
| find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
|
| - char **name, char **comp_dir)
|
| + const char **name, const char **comp_dir)
|
| {
|
| struct attribute *attr;
|
|
|
| @@ -7568,11 +8783,14 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
|
| attr = dwarf2_attr (die, DW_AT_comp_dir, cu);
|
| if (attr)
|
| *comp_dir = DW_STRING (attr);
|
| - else if (*name != NULL && IS_ABSOLUTE_PATH (*name))
|
| + else if (producer_is_gcc_lt_4_3 (cu) && *name != NULL
|
| + && IS_ABSOLUTE_PATH (*name))
|
| {
|
| - *comp_dir = ldirname (*name);
|
| - if (*comp_dir != NULL)
|
| - make_cleanup (xfree, *comp_dir);
|
| + char *d = ldirname (*name);
|
| +
|
| + *comp_dir = d;
|
| + if (d != NULL)
|
| + make_cleanup (xfree, d);
|
| }
|
| if (*comp_dir != NULL)
|
| {
|
| @@ -7595,7 +8813,7 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
|
|
|
| static void
|
| handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
|
| - const char *comp_dir)
|
| + const char *comp_dir) /* ARI: editCase function */
|
| {
|
| struct attribute *attr;
|
|
|
| @@ -7627,8 +8845,8 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| CORE_ADDR lowpc = ((CORE_ADDR) -1);
|
| CORE_ADDR highpc = ((CORE_ADDR) 0);
|
| struct attribute *attr;
|
| - char *name = NULL;
|
| - char *comp_dir = NULL;
|
| + const char *name = NULL;
|
| + const char *comp_dir = NULL;
|
| struct die_info *child_die;
|
| bfd *abfd = objfile->obfd;
|
| CORE_ADDR baseaddr;
|
| @@ -7719,16 +8937,18 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
|
| struct line_header *lh;
|
| struct attribute *attr;
|
| unsigned int i, line_offset;
|
| + struct signatured_type *sig_type;
|
|
|
| gdb_assert (per_cu->is_debug_types);
|
| + sig_type = (struct signatured_type *) per_cu;
|
|
|
| attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
|
|
|
| /* If we're using .gdb_index (includes -readnow) then
|
| - per_cu->s.type_unit_group may not have been set up yet. */
|
| - if (per_cu->s.type_unit_group == NULL)
|
| - per_cu->s.type_unit_group = get_type_unit_group (cu, attr);
|
| - tu_group = per_cu->s.type_unit_group;
|
| + per_cu->type_unit_group may not have been set up yet. */
|
| + if (sig_type->type_unit_group == NULL)
|
| + sig_type->type_unit_group = get_type_unit_group (cu, attr);
|
| + tu_group = sig_type->type_unit_group;
|
|
|
| /* If we've already processed this stmt_list there's no real need to
|
| do it again, we could fake it and just recreate the part we need
|
| @@ -7769,7 +8989,7 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| for (i = 0; i < lh->num_file_names; ++i)
|
| {
|
| - char *dir = NULL;
|
| + const char *dir = NULL;
|
| struct file_entry *fe = &lh->file_names[i];
|
|
|
| if (fe->dir_index)
|
| @@ -7840,14 +9060,25 @@ read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| }
|
| }
|
|
|
| -/* DWO files. */
|
| +/* DWO/DWP files.
|
| +
|
| + http://gcc.gnu.org/wiki/DebugFission
|
| + http://gcc.gnu.org/wiki/DebugFissionDWP
|
| +
|
| + To simplify handling of both DWO files ("object" files with the DWARF info)
|
| + and DWP files (a file with the DWOs packaged up into one file), we treat
|
| + DWP files as having a collection of virtual DWO files. */
|
|
|
| static hashval_t
|
| hash_dwo_file (const void *item)
|
| {
|
| const struct dwo_file *dwo_file = item;
|
| + hashval_t hash;
|
|
|
| - return htab_hash_string (dwo_file->dwo_name);
|
| + hash = htab_hash_string (dwo_file->dwo_name);
|
| + if (dwo_file->comp_dir != NULL)
|
| + hash += htab_hash_string (dwo_file->comp_dir);
|
| + return hash;
|
| }
|
|
|
| static int
|
| @@ -7856,7 +9087,11 @@ eq_dwo_file (const void *item_lhs, const void *item_rhs)
|
| const struct dwo_file *lhs = item_lhs;
|
| const struct dwo_file *rhs = item_rhs;
|
|
|
| - return strcmp (lhs->dwo_name, rhs->dwo_name) == 0;
|
| + if (strcmp (lhs->dwo_name, rhs->dwo_name) != 0)
|
| + return 0;
|
| + if (lhs->comp_dir == NULL || rhs->comp_dir == NULL)
|
| + return lhs->comp_dir == rhs->comp_dir;
|
| + return strcmp (lhs->comp_dir, rhs->comp_dir) == 0;
|
| }
|
|
|
| /* Allocate a hash table for DWO files. */
|
| @@ -7875,6 +9110,25 @@ allocate_dwo_file_hash_table (void)
|
| dummy_obstack_deallocate);
|
| }
|
|
|
| +/* Lookup DWO file DWO_NAME. */
|
| +
|
| +static void **
|
| +lookup_dwo_file_slot (const char *dwo_name, const char *comp_dir)
|
| +{
|
| + struct dwo_file find_entry;
|
| + void **slot;
|
| +
|
| + if (dwarf2_per_objfile->dwo_files == NULL)
|
| + dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
|
| +
|
| + memset (&find_entry, 0, sizeof (find_entry));
|
| + find_entry.dwo_name = dwo_name;
|
| + find_entry.comp_dir = comp_dir;
|
| + slot = htab_find_slot (dwarf2_per_objfile->dwo_files, &find_entry, INSERT);
|
| +
|
| + return slot;
|
| +}
|
| +
|
| static hashval_t
|
| hash_dwo_unit (const void *item)
|
| {
|
| @@ -7914,145 +9168,66 @@ allocate_dwo_unit_table (struct objfile *objfile)
|
| dummy_obstack_deallocate);
|
| }
|
|
|
| -/* This function is mapped across the sections and remembers the offset and
|
| - size of each of the DWO debugging sections we are interested in. */
|
| -
|
| -static void
|
| -dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_file_ptr)
|
| -{
|
| - struct dwo_file *dwo_file = dwo_file_ptr;
|
| - const struct dwo_section_names *names = &dwo_section_names;
|
| -
|
| - if (section_is_p (sectp->name, &names->abbrev_dwo))
|
| - {
|
| - dwo_file->sections.abbrev.asection = sectp;
|
| - dwo_file->sections.abbrev.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->info_dwo))
|
| - {
|
| - dwo_file->sections.info.asection = sectp;
|
| - dwo_file->sections.info.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->line_dwo))
|
| - {
|
| - dwo_file->sections.line.asection = sectp;
|
| - dwo_file->sections.line.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->loc_dwo))
|
| - {
|
| - dwo_file->sections.loc.asection = sectp;
|
| - dwo_file->sections.loc.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->macinfo_dwo))
|
| - {
|
| - dwo_file->sections.macinfo.asection = sectp;
|
| - dwo_file->sections.macinfo.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->macro_dwo))
|
| - {
|
| - dwo_file->sections.macro.asection = sectp;
|
| - dwo_file->sections.macro.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->str_dwo))
|
| - {
|
| - dwo_file->sections.str.asection = sectp;
|
| - dwo_file->sections.str.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->str_offsets_dwo))
|
| - {
|
| - dwo_file->sections.str_offsets.asection = sectp;
|
| - dwo_file->sections.str_offsets.size = bfd_get_section_size (sectp);
|
| - }
|
| - else if (section_is_p (sectp->name, &names->types_dwo))
|
| - {
|
| - struct dwarf2_section_info type_section;
|
| -
|
| - memset (&type_section, 0, sizeof (type_section));
|
| - type_section.asection = sectp;
|
| - type_section.size = bfd_get_section_size (sectp);
|
| - VEC_safe_push (dwarf2_section_info_def, dwo_file->sections.types,
|
| - &type_section);
|
| - }
|
| -}
|
| -
|
| -/* Structure used to pass data to create_debug_info_hash_table_reader. */
|
| +/* Structure used to pass data to create_dwo_debug_info_hash_table_reader. */
|
|
|
| -struct create_dwo_info_table_data
|
| +struct create_dwo_cu_data
|
| {
|
| struct dwo_file *dwo_file;
|
| - htab_t cu_htab;
|
| + struct dwo_unit dwo_unit;
|
| };
|
|
|
| -/* die_reader_func for create_debug_info_hash_table. */
|
| +/* die_reader_func for create_dwo_cu. */
|
|
|
| static void
|
| -create_debug_info_hash_table_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - struct die_info *comp_unit_die,
|
| - int has_children,
|
| - void *datap)
|
| +create_dwo_cu_reader (const struct die_reader_specs *reader,
|
| + const gdb_byte *info_ptr,
|
| + struct die_info *comp_unit_die,
|
| + int has_children,
|
| + void *datap)
|
| {
|
| struct dwarf2_cu *cu = reader->cu;
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| sect_offset offset = cu->per_cu->offset;
|
| - struct dwarf2_section_info *section = cu->per_cu->info_or_types_section;
|
| - struct create_dwo_info_table_data *data = datap;
|
| + struct dwarf2_section_info *section = cu->per_cu->section;
|
| + struct create_dwo_cu_data *data = datap;
|
| struct dwo_file *dwo_file = data->dwo_file;
|
| - htab_t cu_htab = data->cu_htab;
|
| - void **slot;
|
| + struct dwo_unit *dwo_unit = &data->dwo_unit;
|
| struct attribute *attr;
|
| - struct dwo_unit *dwo_unit;
|
|
|
| attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_id, cu);
|
| if (attr == NULL)
|
| {
|
| - error (_("Dwarf Error: debug entry at offset 0x%x is missing"
|
| - " its dwo_id [in module %s]"),
|
| - offset.sect_off, dwo_file->dwo_name);
|
| + complaint (&symfile_complaints,
|
| + _("Dwarf Error: debug entry at offset 0x%x is missing"
|
| + " its dwo_id [in module %s]"),
|
| + offset.sect_off, dwo_file->dwo_name);
|
| return;
|
| }
|
|
|
| - dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
|
| dwo_unit->dwo_file = dwo_file;
|
| dwo_unit->signature = DW_UNSND (attr);
|
| - dwo_unit->info_or_types_section = section;
|
| + dwo_unit->section = section;
|
| dwo_unit->offset = offset;
|
| dwo_unit->length = cu->per_cu->length;
|
|
|
| - slot = htab_find_slot (cu_htab, dwo_unit, INSERT);
|
| - gdb_assert (slot != NULL);
|
| - if (*slot != NULL)
|
| - {
|
| - const struct dwo_unit *dup_dwo_unit = *slot;
|
| -
|
| - complaint (&symfile_complaints,
|
| - _("debug entry at offset 0x%x is duplicate to the entry at"
|
| - " offset 0x%x, dwo_id 0x%s [in module %s]"),
|
| - offset.sect_off, dup_dwo_unit->offset.sect_off,
|
| - phex (dwo_unit->signature, sizeof (dwo_unit->signature)),
|
| - dwo_file->dwo_name);
|
| - }
|
| - else
|
| - *slot = dwo_unit;
|
| -
|
| if (dwarf2_read_debug)
|
| - fprintf_unfiltered (gdb_stdlog, " offset 0x%x, dwo_id 0x%s\n",
|
| - offset.sect_off,
|
| - phex (dwo_unit->signature,
|
| - sizeof (dwo_unit->signature)));
|
| + fprintf_unfiltered (gdb_stdlog, " offset 0x%x, dwo_id %s\n",
|
| + offset.sect_off, hex_string (dwo_unit->signature));
|
| }
|
|
|
| -/* Create a hash table to map DWO IDs to their CU entry in .debug_info.dwo. */
|
| +/* Create the dwo_unit for the lone CU in DWO_FILE.
|
| + Note: This function processes DWO files only, not DWP files. */
|
|
|
| -static htab_t
|
| -create_debug_info_hash_table (struct dwo_file *dwo_file)
|
| +static struct dwo_unit *
|
| +create_dwo_cu (struct dwo_file *dwo_file)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| struct dwarf2_section_info *section = &dwo_file->sections.info;
|
| bfd *abfd;
|
| htab_t cu_htab;
|
| - gdb_byte *info_ptr, *end_ptr;
|
| - struct create_dwo_info_table_data create_dwo_info_table_data;
|
| + const gdb_byte *info_ptr, *end_ptr;
|
| + struct create_dwo_cu_data create_dwo_cu_data;
|
| + struct dwo_unit *dwo_unit;
|
|
|
| dwarf2_read_section (objfile, section);
|
| info_ptr = section->buffer;
|
| @@ -8062,255 +9237,1520 @@ create_debug_info_hash_table (struct dwo_file *dwo_file)
|
|
|
| /* We can't set abfd until now because the section may be empty or
|
| not present, in which case section->asection will be NULL. */
|
| - abfd = section->asection->owner;
|
| + abfd = get_section_bfd_owner (section);
|
|
|
| if (dwarf2_read_debug)
|
| - fprintf_unfiltered (gdb_stdlog, "Reading .debug_info.dwo for %s:\n",
|
| - bfd_get_filename (abfd));
|
| -
|
| - cu_htab = allocate_dwo_unit_table (objfile);
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
|
| + get_section_name (section),
|
| + get_section_file_name (section));
|
| + }
|
|
|
| - create_dwo_info_table_data.dwo_file = dwo_file;
|
| - create_dwo_info_table_data.cu_htab = cu_htab;
|
| + create_dwo_cu_data.dwo_file = dwo_file;
|
| + dwo_unit = NULL;
|
|
|
| end_ptr = info_ptr + section->size;
|
| while (info_ptr < end_ptr)
|
| {
|
| struct dwarf2_per_cu_data per_cu;
|
|
|
| + memset (&create_dwo_cu_data.dwo_unit, 0,
|
| + sizeof (create_dwo_cu_data.dwo_unit));
|
| memset (&per_cu, 0, sizeof (per_cu));
|
| per_cu.objfile = objfile;
|
| per_cu.is_debug_types = 0;
|
| per_cu.offset.sect_off = info_ptr - section->buffer;
|
| - per_cu.info_or_types_section = section;
|
| + per_cu.section = section;
|
|
|
| init_cutu_and_read_dies_no_follow (&per_cu,
|
| &dwo_file->sections.abbrev,
|
| dwo_file,
|
| - create_debug_info_hash_table_reader,
|
| - &create_dwo_info_table_data);
|
| + create_dwo_cu_reader,
|
| + &create_dwo_cu_data);
|
| +
|
| + if (create_dwo_cu_data.dwo_unit.dwo_file != NULL)
|
| + {
|
| + /* If we've already found one, complain. We only support one
|
| + because having more than one requires hacking the dwo_name of
|
| + each to match, which is highly unlikely to happen. */
|
| + if (dwo_unit != NULL)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Multiple CUs in DWO file %s [in module %s]"),
|
| + dwo_file->dwo_name, objfile_name (objfile));
|
| + break;
|
| + }
|
| +
|
| + dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
|
| + *dwo_unit = create_dwo_cu_data.dwo_unit;
|
| + }
|
|
|
| info_ptr += per_cu.length;
|
| }
|
|
|
| - return cu_htab;
|
| -}
|
| + return dwo_unit;
|
| +}
|
| +
|
| +/* DWP file .debug_{cu,tu}_index section format:
|
| + [ref: http://gcc.gnu.org/wiki/DebugFissionDWP]
|
| +
|
| + DWP Version 1:
|
| +
|
| + Both index sections have the same format, and serve to map a 64-bit
|
| + signature to a set of section numbers. Each section begins with a header,
|
| + followed by a hash table of 64-bit signatures, a parallel table of 32-bit
|
| + indexes, and a pool of 32-bit section numbers. The index sections will be
|
| + aligned at 8-byte boundaries in the file.
|
| +
|
| + The index section header consists of:
|
| +
|
| + V, 32 bit version number
|
| + -, 32 bits unused
|
| + N, 32 bit number of compilation units or type units in the index
|
| + M, 32 bit number of slots in the hash table
|
|
|
| -/* Subroutine of open_dwo_file to simplify it.
|
| - Open the file specified by FILE_NAME and hand it off to BFD for
|
| - preliminary analysis. Return a newly initialized bfd *, which
|
| - includes a canonicalized copy of FILE_NAME.
|
| - In case of trouble, return NULL.
|
| - NOTE: This function is derived from symfile_bfd_open. */
|
| + Numbers are recorded using the byte order of the application binary.
|
| +
|
| + The hash table begins at offset 16 in the section, and consists of an array
|
| + of M 64-bit slots. Each slot contains a 64-bit signature (using the byte
|
| + order of the application binary). Unused slots in the hash table are 0.
|
| + (We rely on the extreme unlikeliness of a signature being exactly 0.)
|
|
|
| -static bfd *
|
| -try_open_dwo_file (const char *file_name)
|
| + The parallel table begins immediately after the hash table
|
| + (at offset 16 + 8 * M from the beginning of the section), and consists of an
|
| + array of 32-bit indexes (using the byte order of the application binary),
|
| + corresponding 1-1 with slots in the hash table. Each entry in the parallel
|
| + table contains a 32-bit index into the pool of section numbers. For unused
|
| + hash table slots, the corresponding entry in the parallel table will be 0.
|
| +
|
| + The pool of section numbers begins immediately following the hash table
|
| + (at offset 16 + 12 * M from the beginning of the section). The pool of
|
| + section numbers consists of an array of 32-bit words (using the byte order
|
| + of the application binary). Each item in the array is indexed starting
|
| + from 0. The hash table entry provides the index of the first section
|
| + number in the set. Additional section numbers in the set follow, and the
|
| + set is terminated by a 0 entry (section number 0 is not used in ELF).
|
| +
|
| + In each set of section numbers, the .debug_info.dwo or .debug_types.dwo
|
| + section must be the first entry in the set, and the .debug_abbrev.dwo must
|
| + be the second entry. Other members of the set may follow in any order.
|
| +
|
| + ---
|
| +
|
| + DWP Version 2:
|
| +
|
| + DWP Version 2 combines all the .debug_info, etc. sections into one,
|
| + and the entries in the index tables are now offsets into these sections.
|
| + CU offsets begin at 0. TU offsets begin at the size of the .debug_info
|
| + section.
|
| +
|
| + Index Section Contents:
|
| + Header
|
| + Hash Table of Signatures dwp_hash_table.hash_table
|
| + Parallel Table of Indices dwp_hash_table.unit_table
|
| + Table of Section Offsets dwp_hash_table.v2.{section_ids,offsets}
|
| + Table of Section Sizes dwp_hash_table.v2.sizes
|
| +
|
| + The index section header consists of:
|
| +
|
| + V, 32 bit version number
|
| + L, 32 bit number of columns in the table of section offsets
|
| + N, 32 bit number of compilation units or type units in the index
|
| + M, 32 bit number of slots in the hash table
|
| +
|
| + Numbers are recorded using the byte order of the application binary.
|
| +
|
| + The hash table has the same format as version 1.
|
| + The parallel table of indices has the same format as version 1,
|
| + except that the entries are origin-1 indices into the table of sections
|
| + offsets and the table of section sizes.
|
| +
|
| + The table of offsets begins immediately following the parallel table
|
| + (at offset 16 + 12 * M from the beginning of the section). The table is
|
| + a two-dimensional array of 32-bit words (using the byte order of the
|
| + application binary), with L columns and N+1 rows, in row-major order.
|
| + Each row in the array is indexed starting from 0. The first row provides
|
| + a key to the remaining rows: each column in this row provides an identifier
|
| + for a debug section, and the offsets in the same column of subsequent rows
|
| + refer to that section. The section identifiers are:
|
| +
|
| + DW_SECT_INFO 1 .debug_info.dwo
|
| + DW_SECT_TYPES 2 .debug_types.dwo
|
| + DW_SECT_ABBREV 3 .debug_abbrev.dwo
|
| + DW_SECT_LINE 4 .debug_line.dwo
|
| + DW_SECT_LOC 5 .debug_loc.dwo
|
| + DW_SECT_STR_OFFSETS 6 .debug_str_offsets.dwo
|
| + DW_SECT_MACINFO 7 .debug_macinfo.dwo
|
| + DW_SECT_MACRO 8 .debug_macro.dwo
|
| +
|
| + The offsets provided by the CU and TU index sections are the base offsets
|
| + for the contributions made by each CU or TU to the corresponding section
|
| + in the package file. Each CU and TU header contains an abbrev_offset
|
| + field, used to find the abbreviations table for that CU or TU within the
|
| + contribution to the .debug_abbrev.dwo section for that CU or TU, and should
|
| + be interpreted as relative to the base offset given in the index section.
|
| + Likewise, offsets into .debug_line.dwo from DW_AT_stmt_list attributes
|
| + should be interpreted as relative to the base offset for .debug_line.dwo,
|
| + and offsets into other debug sections obtained from DWARF attributes should
|
| + also be interpreted as relative to the corresponding base offset.
|
| +
|
| + The table of sizes begins immediately following the table of offsets.
|
| + Like the table of offsets, it is a two-dimensional array of 32-bit words,
|
| + with L columns and N rows, in row-major order. Each row in the array is
|
| + indexed starting from 1 (row 0 is shared by the two tables).
|
| +
|
| + ---
|
| +
|
| + Hash table lookup is handled the same in version 1 and 2:
|
| +
|
| + We assume that N and M will not exceed 2^32 - 1.
|
| + The size of the hash table, M, must be 2^k such that 2^k > 3*N/2.
|
| +
|
| + Given a 64-bit compilation unit signature or a type signature S, an entry
|
| + in the hash table is located as follows:
|
| +
|
| + 1) Calculate a primary hash H = S & MASK(k), where MASK(k) is a mask with
|
| + the low-order k bits all set to 1.
|
| +
|
| + 2) Calculate a secondary hash H' = (((S >> 32) & MASK(k)) | 1).
|
| +
|
| + 3) If the hash table entry at index H matches the signature, use that
|
| + entry. If the hash table entry at index H is unused (all zeroes),
|
| + terminate the search: the signature is not present in the table.
|
| +
|
| + 4) Let H = (H + H') modulo M. Repeat at Step 3.
|
| +
|
| + Because M > N and H' and M are relatively prime, the search is guaranteed
|
| + to stop at an unused slot or find the match. */
|
| +
|
| +/* Create a hash table to map DWO IDs to their CU/TU entry in
|
| + .debug_{info,types}.dwo in DWP_FILE.
|
| + Returns NULL if there isn't one.
|
| + Note: This function processes DWP files only, not DWO files. */
|
| +
|
| +static struct dwp_hash_table *
|
| +create_dwp_hash_table (struct dwp_file *dwp_file, int is_debug_types)
|
| {
|
| - bfd *sym_bfd;
|
| - int desc;
|
| - char *absolute_name;
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + bfd *dbfd = dwp_file->dbfd;
|
| + const gdb_byte *index_ptr, *index_end;
|
| + struct dwarf2_section_info *index;
|
| + uint32_t version, nr_columns, nr_units, nr_slots;
|
| + struct dwp_hash_table *htab;
|
| +
|
| + if (is_debug_types)
|
| + index = &dwp_file->sections.tu_index;
|
| + else
|
| + index = &dwp_file->sections.cu_index;
|
|
|
| - desc = openp (debug_file_directory, OPF_TRY_CWD_FIRST, file_name,
|
| - O_RDONLY | O_BINARY, &absolute_name);
|
| - if (desc < 0)
|
| + if (dwarf2_section_empty_p (index))
|
| return NULL;
|
| + dwarf2_read_section (objfile, index);
|
| +
|
| + index_ptr = index->buffer;
|
| + index_end = index_ptr + index->size;
|
|
|
| - sym_bfd = bfd_fopen (absolute_name, gnutarget, FOPEN_RB, desc);
|
| - if (!sym_bfd)
|
| + version = read_4_bytes (dbfd, index_ptr);
|
| + index_ptr += 4;
|
| + if (version == 2)
|
| + nr_columns = read_4_bytes (dbfd, index_ptr);
|
| + else
|
| + nr_columns = 0;
|
| + index_ptr += 4;
|
| + nr_units = read_4_bytes (dbfd, index_ptr);
|
| + index_ptr += 4;
|
| + nr_slots = read_4_bytes (dbfd, index_ptr);
|
| + index_ptr += 4;
|
| +
|
| + if (version != 1 && version != 2)
|
| {
|
| - xfree (absolute_name);
|
| - return NULL;
|
| + error (_("Dwarf Error: unsupported DWP file version (%s)"
|
| + " [in module %s]"),
|
| + pulongest (version), dwp_file->name);
|
| }
|
| + if (nr_slots != (nr_slots & -nr_slots))
|
| + {
|
| + error (_("Dwarf Error: number of slots in DWP hash table (%s)"
|
| + " is not power of 2 [in module %s]"),
|
| + pulongest (nr_slots), dwp_file->name);
|
| + }
|
| +
|
| + htab = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_hash_table);
|
| + htab->version = version;
|
| + htab->nr_columns = nr_columns;
|
| + htab->nr_units = nr_units;
|
| + htab->nr_slots = nr_slots;
|
| + htab->hash_table = index_ptr;
|
| + htab->unit_table = htab->hash_table + sizeof (uint64_t) * nr_slots;
|
| +
|
| + /* Exit early if the table is empty. */
|
| + if (nr_slots == 0 || nr_units == 0
|
| + || (version == 2 && nr_columns == 0))
|
| + {
|
| + /* All must be zero. */
|
| + if (nr_slots != 0 || nr_units != 0
|
| + || (version == 2 && nr_columns != 0))
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Empty DWP but nr_slots,nr_units,nr_columns not"
|
| + " all zero [in modules %s]"),
|
| + dwp_file->name);
|
| + }
|
| + return htab;
|
| + }
|
| +
|
| + if (version == 1)
|
| + {
|
| + htab->section_pool.v1.indices =
|
| + htab->unit_table + sizeof (uint32_t) * nr_slots;
|
| + /* It's harder to decide whether the section is too small in v1.
|
| + V1 is deprecated anyway so we punt. */
|
| + }
|
| + else
|
| + {
|
| + const gdb_byte *ids_ptr = htab->unit_table + sizeof (uint32_t) * nr_slots;
|
| + int *ids = htab->section_pool.v2.section_ids;
|
| + /* Reverse map for error checking. */
|
| + int ids_seen[DW_SECT_MAX + 1];
|
| + int i;
|
| +
|
| + if (nr_columns < 2)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, too few columns"
|
| + " in section table [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + if (nr_columns > MAX_NR_V2_DWO_SECTIONS)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, too many columns"
|
| + " in section table [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + memset (ids, 255, (DW_SECT_MAX + 1) * sizeof (int32_t));
|
| + memset (ids_seen, 255, (DW_SECT_MAX + 1) * sizeof (int32_t));
|
| + for (i = 0; i < nr_columns; ++i)
|
| + {
|
| + int id = read_4_bytes (dbfd, ids_ptr + i * sizeof (uint32_t));
|
| +
|
| + if (id < DW_SECT_MIN || id > DW_SECT_MAX)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, bad section id %d"
|
| + " in section table [in module %s]"),
|
| + id, dwp_file->name);
|
| + }
|
| + if (ids_seen[id] != -1)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, duplicate section"
|
| + " id %d in section table [in module %s]"),
|
| + id, dwp_file->name);
|
| + }
|
| + ids_seen[id] = i;
|
| + ids[i] = id;
|
| + }
|
| + /* Must have exactly one info or types section. */
|
| + if (((ids_seen[DW_SECT_INFO] != -1)
|
| + + (ids_seen[DW_SECT_TYPES] != -1))
|
| + != 1)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, missing/duplicate"
|
| + " DWO info/types section [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + /* Must have an abbrev section. */
|
| + if (ids_seen[DW_SECT_ABBREV] == -1)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, missing DWO abbrev"
|
| + " section [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + htab->section_pool.v2.offsets = ids_ptr + sizeof (uint32_t) * nr_columns;
|
| + htab->section_pool.v2.sizes =
|
| + htab->section_pool.v2.offsets + (sizeof (uint32_t)
|
| + * nr_units * nr_columns);
|
| + if ((htab->section_pool.v2.sizes + (sizeof (uint32_t)
|
| + * nr_units * nr_columns))
|
| + > index_end)
|
| + {
|
| + error (_("Dwarf Error: DWP index section is corrupt (too small)"
|
| + " [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + }
|
| +
|
| + return htab;
|
| +}
|
| +
|
| +/* Update SECTIONS with the data from SECTP.
|
| +
|
| + This function is like the other "locate" section routines that are
|
| + passed to bfd_map_over_sections, but in this context the sections to
|
| + read comes from the DWP V1 hash table, not the full ELF section table.
|
| +
|
| + The result is non-zero for success, or zero if an error was found. */
|
| +
|
| +static int
|
| +locate_v1_virtual_dwo_sections (asection *sectp,
|
| + struct virtual_v1_dwo_sections *sections)
|
| +{
|
| + const struct dwop_section_names *names = &dwop_section_names;
|
| +
|
| + if (section_is_p (sectp->name, &names->abbrev_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->abbrev.s.asection != NULL)
|
| + return 0;
|
| + sections->abbrev.s.asection = sectp;
|
| + sections->abbrev.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->info_dwo)
|
| + || section_is_p (sectp->name, &names->types_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->info_or_types.s.asection != NULL)
|
| + return 0;
|
| + sections->info_or_types.s.asection = sectp;
|
| + sections->info_or_types.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->line_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->line.s.asection != NULL)
|
| + return 0;
|
| + sections->line.s.asection = sectp;
|
| + sections->line.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->loc_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->loc.s.asection != NULL)
|
| + return 0;
|
| + sections->loc.s.asection = sectp;
|
| + sections->loc.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->macinfo_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->macinfo.s.asection != NULL)
|
| + return 0;
|
| + sections->macinfo.s.asection = sectp;
|
| + sections->macinfo.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->macro_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->macro.s.asection != NULL)
|
| + return 0;
|
| + sections->macro.s.asection = sectp;
|
| + sections->macro.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->str_offsets_dwo))
|
| + {
|
| + /* There can be only one. */
|
| + if (sections->str_offsets.s.asection != NULL)
|
| + return 0;
|
| + sections->str_offsets.s.asection = sectp;
|
| + sections->str_offsets.size = bfd_get_section_size (sectp);
|
| + }
|
| + else
|
| + {
|
| + /* No other kind of section is valid. */
|
| + return 0;
|
| + }
|
| +
|
| + return 1;
|
| +}
|
| +
|
| +/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
|
| + UNIT_INDEX is the index of the DWO unit in the DWP hash table.
|
| + COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
|
| + This is for DWP version 1 files. */
|
| +
|
| +static struct dwo_unit *
|
| +create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file,
|
| + uint32_t unit_index,
|
| + const char *comp_dir,
|
| + ULONGEST signature, int is_debug_types)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + const struct dwp_hash_table *dwp_htab =
|
| + is_debug_types ? dwp_file->tus : dwp_file->cus;
|
| + bfd *dbfd = dwp_file->dbfd;
|
| + const char *kind = is_debug_types ? "TU" : "CU";
|
| + struct dwo_file *dwo_file;
|
| + struct dwo_unit *dwo_unit;
|
| + struct virtual_v1_dwo_sections sections;
|
| + void **dwo_file_slot;
|
| + char *virtual_dwo_name;
|
| + struct dwarf2_section_info *cutu;
|
| + struct cleanup *cleanups;
|
| + int i;
|
| +
|
| + gdb_assert (dwp_file->version == 1);
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V1 file: %s\n",
|
| + kind,
|
| + pulongest (unit_index), hex_string (signature),
|
| + dwp_file->name);
|
| + }
|
| +
|
| + /* Fetch the sections of this DWO unit.
|
| + Put a limit on the number of sections we look for so that bad data
|
| + doesn't cause us to loop forever. */
|
| +
|
| +#define MAX_NR_V1_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 */ \
|
| + + 1 /* trailing zero */)
|
| +
|
| + memset (§ions, 0, sizeof (sections));
|
| + cleanups = make_cleanup (null_cleanup, 0);
|
| +
|
| + for (i = 0; i < MAX_NR_V1_DWO_SECTIONS; ++i)
|
| + {
|
| + asection *sectp;
|
| + uint32_t section_nr =
|
| + read_4_bytes (dbfd,
|
| + dwp_htab->section_pool.v1.indices
|
| + + (unit_index + i) * sizeof (uint32_t));
|
| +
|
| + if (section_nr == 0)
|
| + break;
|
| + if (section_nr >= dwp_file->num_sections)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, section number too large"
|
| + " [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| +
|
| + sectp = dwp_file->elf_sections[section_nr];
|
| + if (! locate_v1_virtual_dwo_sections (sectp, §ions))
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, invalid section found"
|
| + " [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + }
|
| +
|
| + if (i < 2
|
| + || dwarf2_section_empty_p (§ions.info_or_types)
|
| + || dwarf2_section_empty_p (§ions.abbrev))
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, missing DWO sections"
|
| + " [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| + if (i == MAX_NR_V1_DWO_SECTIONS)
|
| + {
|
| + error (_("Dwarf Error: bad DWP hash table, too many DWO sections"
|
| + " [in module %s]"),
|
| + dwp_file->name);
|
| + }
|
| +
|
| + /* It's easier for the rest of the code if we fake a struct dwo_file and
|
| + have dwo_unit "live" in that. At least for now.
|
| +
|
| + The DWP file can be made up of a random collection of CUs and TUs.
|
| + However, for each CU + set of TUs that came from the same original DWO
|
| + file, we can combine them back into a virtual DWO file to save space
|
| + (fewer struct dwo_file objects to allocate). Remember that for really
|
| + large apps there can be on the order of 8K CUs and 200K TUs, or more. */
|
| +
|
| + virtual_dwo_name =
|
| + xstrprintf ("virtual-dwo/%d-%d-%d-%d",
|
| + get_section_id (§ions.abbrev),
|
| + get_section_id (§ions.line),
|
| + get_section_id (§ions.loc),
|
| + get_section_id (§ions.str_offsets));
|
| + make_cleanup (xfree, virtual_dwo_name);
|
| + /* Can we use an existing virtual DWO file? */
|
| + dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
|
| + /* Create one if necessary. */
|
| + if (*dwo_file_slot == NULL)
|
| + {
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
|
| + virtual_dwo_name);
|
| + }
|
| + dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
|
| + dwo_file->dwo_name = obstack_copy0 (&objfile->objfile_obstack,
|
| + virtual_dwo_name,
|
| + strlen (virtual_dwo_name));
|
| + dwo_file->comp_dir = comp_dir;
|
| + dwo_file->sections.abbrev = sections.abbrev;
|
| + dwo_file->sections.line = sections.line;
|
| + dwo_file->sections.loc = sections.loc;
|
| + dwo_file->sections.macinfo = sections.macinfo;
|
| + dwo_file->sections.macro = sections.macro;
|
| + dwo_file->sections.str_offsets = sections.str_offsets;
|
| + /* The "str" section is global to the entire DWP file. */
|
| + dwo_file->sections.str = dwp_file->sections.str;
|
| + /* The info or types section is assigned below to dwo_unit,
|
| + there's no need to record it in dwo_file.
|
| + Also, we can't simply record type sections in dwo_file because
|
| + we record a pointer into the vector in dwo_unit. As we collect more
|
| + types we'll grow the vector and eventually have to reallocate space
|
| + for it, invalidating all copies of pointers into the previous
|
| + contents. */
|
| + *dwo_file_slot = dwo_file;
|
| + }
|
| + else
|
| + {
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
|
| + virtual_dwo_name);
|
| + }
|
| + dwo_file = *dwo_file_slot;
|
| + }
|
| + do_cleanups (cleanups);
|
| +
|
| + dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
|
| + dwo_unit->dwo_file = dwo_file;
|
| + dwo_unit->signature = signature;
|
| + dwo_unit->section = obstack_alloc (&objfile->objfile_obstack,
|
| + sizeof (struct dwarf2_section_info));
|
| + *dwo_unit->section = sections.info_or_types;
|
| + /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
|
| +
|
| + return dwo_unit;
|
| +}
|
| +
|
| +/* Subroutine of create_dwo_unit_in_dwp_v2 to simplify it.
|
| + Given a pointer to the containing section SECTION, and OFFSET,SIZE of the
|
| + piece within that section used by a TU/CU, return a virtual section
|
| + of just that piece. */
|
| +
|
| +static struct dwarf2_section_info
|
| +create_dwp_v2_section (struct dwarf2_section_info *section,
|
| + bfd_size_type offset, bfd_size_type size)
|
| +{
|
| + struct dwarf2_section_info result;
|
| + asection *sectp;
|
| +
|
| + gdb_assert (section != NULL);
|
| + gdb_assert (!section->is_virtual);
|
| +
|
| + memset (&result, 0, sizeof (result));
|
| + result.s.containing_section = section;
|
| + result.is_virtual = 1;
|
| +
|
| + if (size == 0)
|
| + return result;
|
| +
|
| + sectp = get_section_bfd_section (section);
|
| +
|
| + /* Flag an error if the piece denoted by OFFSET,SIZE is outside the
|
| + bounds of the real section. This is a pretty-rare event, so just
|
| + flag an error (easier) instead of a warning and trying to cope. */
|
| + if (sectp == NULL
|
| + || offset + size > bfd_get_section_size (sectp))
|
| + {
|
| + bfd *abfd = sectp->owner;
|
| +
|
| + error (_("Dwarf Error: Bad DWP V2 section info, doesn't fit"
|
| + " in section %s [in module %s]"),
|
| + sectp ? bfd_section_name (abfd, sectp) : "<unknown>",
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| + }
|
| +
|
| + result.virtual_offset = offset;
|
| + result.size = size;
|
| + return result;
|
| +}
|
| +
|
| +/* Create a dwo_unit object for the DWO unit with signature SIGNATURE.
|
| + UNIT_INDEX is the index of the DWO unit in the DWP hash table.
|
| + COMP_DIR is the DW_AT_comp_dir attribute of the referencing CU.
|
| + This is for DWP version 2 files. */
|
| +
|
| +static struct dwo_unit *
|
| +create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file,
|
| + uint32_t unit_index,
|
| + const char *comp_dir,
|
| + ULONGEST signature, int is_debug_types)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + const struct dwp_hash_table *dwp_htab =
|
| + is_debug_types ? dwp_file->tus : dwp_file->cus;
|
| + bfd *dbfd = dwp_file->dbfd;
|
| + const char *kind = is_debug_types ? "TU" : "CU";
|
| + struct dwo_file *dwo_file;
|
| + struct dwo_unit *dwo_unit;
|
| + struct virtual_v2_dwo_sections sections;
|
| + void **dwo_file_slot;
|
| + char *virtual_dwo_name;
|
| + struct dwarf2_section_info *cutu;
|
| + struct cleanup *cleanups;
|
| + int i;
|
| +
|
| + gdb_assert (dwp_file->version == 2);
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Reading %s %s/%s in DWP V2 file: %s\n",
|
| + kind,
|
| + pulongest (unit_index), hex_string (signature),
|
| + dwp_file->name);
|
| + }
|
| +
|
| + /* Fetch the section offsets of this DWO unit. */
|
| +
|
| + memset (§ions, 0, sizeof (sections));
|
| + cleanups = make_cleanup (null_cleanup, 0);
|
| +
|
| + for (i = 0; i < dwp_htab->nr_columns; ++i)
|
| + {
|
| + uint32_t offset = read_4_bytes (dbfd,
|
| + dwp_htab->section_pool.v2.offsets
|
| + + (((unit_index - 1) * dwp_htab->nr_columns
|
| + + i)
|
| + * sizeof (uint32_t)));
|
| + uint32_t size = read_4_bytes (dbfd,
|
| + dwp_htab->section_pool.v2.sizes
|
| + + (((unit_index - 1) * dwp_htab->nr_columns
|
| + + i)
|
| + * sizeof (uint32_t)));
|
| +
|
| + switch (dwp_htab->section_pool.v2.section_ids[i])
|
| + {
|
| + case DW_SECT_INFO:
|
| + case DW_SECT_TYPES:
|
| + sections.info_or_types_offset = offset;
|
| + sections.info_or_types_size = size;
|
| + break;
|
| + case DW_SECT_ABBREV:
|
| + sections.abbrev_offset = offset;
|
| + sections.abbrev_size = size;
|
| + break;
|
| + case DW_SECT_LINE:
|
| + sections.line_offset = offset;
|
| + sections.line_size = size;
|
| + break;
|
| + case DW_SECT_LOC:
|
| + sections.loc_offset = offset;
|
| + sections.loc_size = size;
|
| + break;
|
| + case DW_SECT_STR_OFFSETS:
|
| + sections.str_offsets_offset = offset;
|
| + sections.str_offsets_size = size;
|
| + break;
|
| + case DW_SECT_MACINFO:
|
| + sections.macinfo_offset = offset;
|
| + sections.macinfo_size = size;
|
| + break;
|
| + case DW_SECT_MACRO:
|
| + sections.macro_offset = offset;
|
| + sections.macro_size = size;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + /* It's easier for the rest of the code if we fake a struct dwo_file and
|
| + have dwo_unit "live" in that. At least for now.
|
| +
|
| + The DWP file can be made up of a random collection of CUs and TUs.
|
| + However, for each CU + set of TUs that came from the same original DWO
|
| + file, we can combine them back into a virtual DWO file to save space
|
| + (fewer struct dwo_file objects to allocate). Remember that for really
|
| + large apps there can be on the order of 8K CUs and 200K TUs, or more. */
|
| +
|
| + virtual_dwo_name =
|
| + xstrprintf ("virtual-dwo/%ld-%ld-%ld-%ld",
|
| + (long) (sections.abbrev_size ? sections.abbrev_offset : 0),
|
| + (long) (sections.line_size ? sections.line_offset : 0),
|
| + (long) (sections.loc_size ? sections.loc_offset : 0),
|
| + (long) (sections.str_offsets_size
|
| + ? sections.str_offsets_offset : 0));
|
| + make_cleanup (xfree, virtual_dwo_name);
|
| + /* Can we use an existing virtual DWO file? */
|
| + dwo_file_slot = lookup_dwo_file_slot (virtual_dwo_name, comp_dir);
|
| + /* Create one if necessary. */
|
| + if (*dwo_file_slot == NULL)
|
| + {
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Creating virtual DWO: %s\n",
|
| + virtual_dwo_name);
|
| + }
|
| + dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
|
| + dwo_file->dwo_name = obstack_copy0 (&objfile->objfile_obstack,
|
| + virtual_dwo_name,
|
| + strlen (virtual_dwo_name));
|
| + dwo_file->comp_dir = comp_dir;
|
| + dwo_file->sections.abbrev =
|
| + create_dwp_v2_section (&dwp_file->sections.abbrev,
|
| + sections.abbrev_offset, sections.abbrev_size);
|
| + dwo_file->sections.line =
|
| + create_dwp_v2_section (&dwp_file->sections.line,
|
| + sections.line_offset, sections.line_size);
|
| + dwo_file->sections.loc =
|
| + create_dwp_v2_section (&dwp_file->sections.loc,
|
| + sections.loc_offset, sections.loc_size);
|
| + dwo_file->sections.macinfo =
|
| + create_dwp_v2_section (&dwp_file->sections.macinfo,
|
| + sections.macinfo_offset, sections.macinfo_size);
|
| + dwo_file->sections.macro =
|
| + create_dwp_v2_section (&dwp_file->sections.macro,
|
| + sections.macro_offset, sections.macro_size);
|
| + dwo_file->sections.str_offsets =
|
| + create_dwp_v2_section (&dwp_file->sections.str_offsets,
|
| + sections.str_offsets_offset,
|
| + sections.str_offsets_size);
|
| + /* The "str" section is global to the entire DWP file. */
|
| + dwo_file->sections.str = dwp_file->sections.str;
|
| + /* The info or types section is assigned below to dwo_unit,
|
| + there's no need to record it in dwo_file.
|
| + Also, we can't simply record type sections in dwo_file because
|
| + we record a pointer into the vector in dwo_unit. As we collect more
|
| + types we'll grow the vector and eventually have to reallocate space
|
| + for it, invalidating all copies of pointers into the previous
|
| + contents. */
|
| + *dwo_file_slot = dwo_file;
|
| + }
|
| + else
|
| + {
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n",
|
| + virtual_dwo_name);
|
| + }
|
| + dwo_file = *dwo_file_slot;
|
| + }
|
| + do_cleanups (cleanups);
|
| +
|
| + dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
|
| + dwo_unit->dwo_file = dwo_file;
|
| + dwo_unit->signature = signature;
|
| + dwo_unit->section = obstack_alloc (&objfile->objfile_obstack,
|
| + sizeof (struct dwarf2_section_info));
|
| + *dwo_unit->section = create_dwp_v2_section (is_debug_types
|
| + ? &dwp_file->sections.types
|
| + : &dwp_file->sections.info,
|
| + sections.info_or_types_offset,
|
| + sections.info_or_types_size);
|
| + /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */
|
| +
|
| + return dwo_unit;
|
| +}
|
| +
|
| +/* Lookup the DWO unit with SIGNATURE in DWP_FILE.
|
| + Returns NULL if the signature isn't found. */
|
| +
|
| +static struct dwo_unit *
|
| +lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir,
|
| + ULONGEST signature, int is_debug_types)
|
| +{
|
| + const struct dwp_hash_table *dwp_htab =
|
| + is_debug_types ? dwp_file->tus : dwp_file->cus;
|
| + bfd *dbfd = dwp_file->dbfd;
|
| + uint32_t mask = dwp_htab->nr_slots - 1;
|
| + uint32_t hash = signature & mask;
|
| + uint32_t hash2 = ((signature >> 32) & mask) | 1;
|
| + unsigned int i;
|
| + void **slot;
|
| + struct dwo_unit find_dwo_cu, *dwo_cu;
|
| +
|
| + memset (&find_dwo_cu, 0, sizeof (find_dwo_cu));
|
| + find_dwo_cu.signature = signature;
|
| + slot = htab_find_slot (is_debug_types
|
| + ? dwp_file->loaded_tus
|
| + : dwp_file->loaded_cus,
|
| + &find_dwo_cu, INSERT);
|
| +
|
| + if (*slot != NULL)
|
| + return *slot;
|
| +
|
| + /* Use a for loop so that we don't loop forever on bad debug info. */
|
| + for (i = 0; i < dwp_htab->nr_slots; ++i)
|
| + {
|
| + ULONGEST signature_in_table;
|
| +
|
| + signature_in_table =
|
| + read_8_bytes (dbfd, dwp_htab->hash_table + hash * sizeof (uint64_t));
|
| + if (signature_in_table == signature)
|
| + {
|
| + uint32_t unit_index =
|
| + read_4_bytes (dbfd,
|
| + dwp_htab->unit_table + hash * sizeof (uint32_t));
|
| +
|
| + if (dwp_file->version == 1)
|
| + {
|
| + *slot = create_dwo_unit_in_dwp_v1 (dwp_file, unit_index,
|
| + comp_dir, signature,
|
| + is_debug_types);
|
| + }
|
| + else
|
| + {
|
| + *slot = create_dwo_unit_in_dwp_v2 (dwp_file, unit_index,
|
| + comp_dir, signature,
|
| + is_debug_types);
|
| + }
|
| + return *slot;
|
| + }
|
| + if (signature_in_table == 0)
|
| + return NULL;
|
| + hash = (hash + hash2) & mask;
|
| + }
|
| +
|
| + error (_("Dwarf Error: bad DWP hash table, lookup didn't terminate"
|
| + " [in module %s]"),
|
| + dwp_file->name);
|
| +}
|
| +
|
| +/* Subroutine of open_dwo_file,open_dwp_file to simplify them.
|
| + Open the file specified by FILE_NAME and hand it off to BFD for
|
| + preliminary analysis. Return a newly initialized bfd *, which
|
| + includes a canonicalized copy of FILE_NAME.
|
| + If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
|
| + SEARCH_CWD is true if the current directory is to be searched.
|
| + It will be searched before debug-file-directory.
|
| + If unable to find/open the file, return NULL.
|
| + NOTE: This function is derived from symfile_bfd_open. */
|
| +
|
| +static bfd *
|
| +try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
|
| +{
|
| + bfd *sym_bfd;
|
| + int desc, flags;
|
| + char *absolute_name;
|
| + /* Blech. OPF_TRY_CWD_FIRST also disables searching the path list if
|
| + FILE_NAME contains a '/'. So we can't use it. Instead prepend "."
|
| + to debug_file_directory. */
|
| + char *search_path;
|
| + static const char dirname_separator_string[] = { DIRNAME_SEPARATOR, '\0' };
|
| +
|
| + if (search_cwd)
|
| + {
|
| + if (*debug_file_directory != '\0')
|
| + search_path = concat (".", dirname_separator_string,
|
| + debug_file_directory, NULL);
|
| + else
|
| + search_path = xstrdup (".");
|
| + }
|
| + else
|
| + search_path = xstrdup (debug_file_directory);
|
| +
|
| + flags = OPF_RETURN_REALPATH;
|
| + if (is_dwp)
|
| + flags |= OPF_SEARCH_IN_PATH;
|
| + desc = openp (search_path, flags, file_name,
|
| + O_RDONLY | O_BINARY, &absolute_name);
|
| + xfree (search_path);
|
| + if (desc < 0)
|
| + return NULL;
|
| +
|
| + sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
|
| + xfree (absolute_name);
|
| + if (sym_bfd == NULL)
|
| + return NULL;
|
| bfd_set_cacheable (sym_bfd, 1);
|
|
|
| if (!bfd_check_format (sym_bfd, bfd_object))
|
| {
|
| - bfd_close (sym_bfd); /* This also closes desc. */
|
| - xfree (absolute_name);
|
| + gdb_bfd_unref (sym_bfd); /* This also closes desc. */
|
| return NULL;
|
| }
|
|
|
| - /* bfd_usrdata exists for applications and libbfd must not touch it. */
|
| - gdb_assert (bfd_usrdata (sym_bfd) == NULL);
|
| -
|
| return sym_bfd;
|
| }
|
|
|
| -/* Try to open DWO file DWO_NAME.
|
| - COMP_DIR is the DW_AT_comp_dir attribute.
|
| +/* Try to open DWO file FILE_NAME.
|
| + COMP_DIR is the DW_AT_comp_dir attribute.
|
| + The result is the bfd handle of the file.
|
| + If there is a problem finding or opening the file, return NULL.
|
| + Upon success, the canonicalized path of the file is stored in the bfd,
|
| + same as symfile_bfd_open. */
|
| +
|
| +static bfd *
|
| +open_dwo_file (const char *file_name, const char *comp_dir)
|
| +{
|
| + bfd *abfd;
|
| +
|
| + if (IS_ABSOLUTE_PATH (file_name))
|
| + return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/);
|
| +
|
| + /* Before trying the search path, try DWO_NAME in COMP_DIR. */
|
| +
|
| + if (comp_dir != NULL)
|
| + {
|
| + char *path_to_try = concat (comp_dir, SLASH_STRING, file_name, NULL);
|
| +
|
| + /* NOTE: If comp_dir is a relative path, this will also try the
|
| + search path, which seems useful. */
|
| + abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/);
|
| + xfree (path_to_try);
|
| + if (abfd != NULL)
|
| + return abfd;
|
| + }
|
| +
|
| + /* That didn't work, try debug-file-directory, which, despite its name,
|
| + is a list of paths. */
|
| +
|
| + if (*debug_file_directory == '\0')
|
| + return NULL;
|
| +
|
| + return try_open_dwop_file (file_name, 0 /*is_dwp*/, 1 /*search_cwd*/);
|
| +}
|
| +
|
| +/* This function is mapped across the sections and remembers the offset and
|
| + size of each of the DWO debugging sections we are interested in. */
|
| +
|
| +static void
|
| +dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr)
|
| +{
|
| + struct dwo_sections *dwo_sections = dwo_sections_ptr;
|
| + const struct dwop_section_names *names = &dwop_section_names;
|
| +
|
| + if (section_is_p (sectp->name, &names->abbrev_dwo))
|
| + {
|
| + dwo_sections->abbrev.s.asection = sectp;
|
| + dwo_sections->abbrev.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->info_dwo))
|
| + {
|
| + dwo_sections->info.s.asection = sectp;
|
| + dwo_sections->info.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->line_dwo))
|
| + {
|
| + dwo_sections->line.s.asection = sectp;
|
| + dwo_sections->line.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->loc_dwo))
|
| + {
|
| + dwo_sections->loc.s.asection = sectp;
|
| + dwo_sections->loc.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->macinfo_dwo))
|
| + {
|
| + dwo_sections->macinfo.s.asection = sectp;
|
| + dwo_sections->macinfo.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->macro_dwo))
|
| + {
|
| + dwo_sections->macro.s.asection = sectp;
|
| + dwo_sections->macro.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->str_dwo))
|
| + {
|
| + dwo_sections->str.s.asection = sectp;
|
| + dwo_sections->str.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->str_offsets_dwo))
|
| + {
|
| + dwo_sections->str_offsets.s.asection = sectp;
|
| + dwo_sections->str_offsets.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->types_dwo))
|
| + {
|
| + struct dwarf2_section_info type_section;
|
| +
|
| + memset (&type_section, 0, sizeof (type_section));
|
| + type_section.s.asection = sectp;
|
| + type_section.size = bfd_get_section_size (sectp);
|
| + VEC_safe_push (dwarf2_section_info_def, dwo_sections->types,
|
| + &type_section);
|
| + }
|
| +}
|
| +
|
| +/* Initialize the use of the DWO file specified by DWO_NAME and referenced
|
| + by PER_CU. This is for the non-DWP case.
|
| + The result is NULL if DWO_NAME can't be found. */
|
| +
|
| +static struct dwo_file *
|
| +open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu,
|
| + const char *dwo_name, const char *comp_dir)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwo_file *dwo_file;
|
| + bfd *dbfd;
|
| + struct cleanup *cleanups;
|
| +
|
| + dbfd = open_dwo_file (dwo_name, comp_dir);
|
| + if (dbfd == NULL)
|
| + {
|
| + if (dwarf2_read_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "DWO file not found: %s\n", dwo_name);
|
| + return NULL;
|
| + }
|
| + dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
|
| + dwo_file->dwo_name = dwo_name;
|
| + dwo_file->comp_dir = comp_dir;
|
| + dwo_file->dbfd = dbfd;
|
| +
|
| + cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
|
| +
|
| + bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections);
|
| +
|
| + dwo_file->cu = create_dwo_cu (dwo_file);
|
| +
|
| + dwo_file->tus = create_debug_types_hash_table (dwo_file,
|
| + dwo_file->sections.types);
|
| +
|
| + discard_cleanups (cleanups);
|
| +
|
| + if (dwarf2_read_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "DWO file found: %s\n", dwo_name);
|
| +
|
| + return dwo_file;
|
| +}
|
| +
|
| +/* This function is mapped across the sections and remembers the offset and
|
| + size of each of the DWP debugging sections common to version 1 and 2 that
|
| + we are interested in. */
|
| +
|
| +static void
|
| +dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp,
|
| + void *dwp_file_ptr)
|
| +{
|
| + struct dwp_file *dwp_file = dwp_file_ptr;
|
| + const struct dwop_section_names *names = &dwop_section_names;
|
| + unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
|
| +
|
| + /* Record the ELF section number for later lookup: this is what the
|
| + .debug_cu_index,.debug_tu_index tables use in DWP V1. */
|
| + gdb_assert (elf_section_nr < dwp_file->num_sections);
|
| + dwp_file->elf_sections[elf_section_nr] = sectp;
|
| +
|
| + /* Look for specific sections that we need. */
|
| + if (section_is_p (sectp->name, &names->str_dwo))
|
| + {
|
| + dwp_file->sections.str.s.asection = sectp;
|
| + dwp_file->sections.str.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->cu_index))
|
| + {
|
| + dwp_file->sections.cu_index.s.asection = sectp;
|
| + dwp_file->sections.cu_index.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->tu_index))
|
| + {
|
| + dwp_file->sections.tu_index.s.asection = sectp;
|
| + dwp_file->sections.tu_index.size = bfd_get_section_size (sectp);
|
| + }
|
| +}
|
| +
|
| +/* This function is mapped across the sections and remembers the offset and
|
| + size of each of the DWP version 2 debugging sections that we are interested
|
| + in. This is split into a separate function because we don't know if we
|
| + have version 1 or 2 until we parse the cu_index/tu_index sections. */
|
| +
|
| +static void
|
| +dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr)
|
| +{
|
| + struct dwp_file *dwp_file = dwp_file_ptr;
|
| + const struct dwop_section_names *names = &dwop_section_names;
|
| + unsigned int elf_section_nr = elf_section_data (sectp)->this_idx;
|
| +
|
| + /* Record the ELF section number for later lookup: this is what the
|
| + .debug_cu_index,.debug_tu_index tables use in DWP V1. */
|
| + gdb_assert (elf_section_nr < dwp_file->num_sections);
|
| + dwp_file->elf_sections[elf_section_nr] = sectp;
|
| +
|
| + /* Look for specific sections that we need. */
|
| + if (section_is_p (sectp->name, &names->abbrev_dwo))
|
| + {
|
| + dwp_file->sections.abbrev.s.asection = sectp;
|
| + dwp_file->sections.abbrev.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->info_dwo))
|
| + {
|
| + dwp_file->sections.info.s.asection = sectp;
|
| + dwp_file->sections.info.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->line_dwo))
|
| + {
|
| + dwp_file->sections.line.s.asection = sectp;
|
| + dwp_file->sections.line.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->loc_dwo))
|
| + {
|
| + dwp_file->sections.loc.s.asection = sectp;
|
| + dwp_file->sections.loc.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->macinfo_dwo))
|
| + {
|
| + dwp_file->sections.macinfo.s.asection = sectp;
|
| + dwp_file->sections.macinfo.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->macro_dwo))
|
| + {
|
| + dwp_file->sections.macro.s.asection = sectp;
|
| + dwp_file->sections.macro.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->str_offsets_dwo))
|
| + {
|
| + dwp_file->sections.str_offsets.s.asection = sectp;
|
| + dwp_file->sections.str_offsets.size = bfd_get_section_size (sectp);
|
| + }
|
| + else if (section_is_p (sectp->name, &names->types_dwo))
|
| + {
|
| + dwp_file->sections.types.s.asection = sectp;
|
| + dwp_file->sections.types.size = bfd_get_section_size (sectp);
|
| + }
|
| +}
|
| +
|
| +/* Hash function for dwp_file loaded CUs/TUs. */
|
| +
|
| +static hashval_t
|
| +hash_dwp_loaded_cutus (const void *item)
|
| +{
|
| + const struct dwo_unit *dwo_unit = item;
|
| +
|
| + /* This drops the top 32 bits of the signature, but is ok for a hash. */
|
| + return dwo_unit->signature;
|
| +}
|
| +
|
| +/* Equality function for dwp_file loaded CUs/TUs. */
|
| +
|
| +static int
|
| +eq_dwp_loaded_cutus (const void *a, const void *b)
|
| +{
|
| + const struct dwo_unit *dua = a;
|
| + const struct dwo_unit *dub = b;
|
| +
|
| + return dua->signature == dub->signature;
|
| +}
|
| +
|
| +/* Allocate a hash table for dwp_file loaded CUs/TUs. */
|
| +
|
| +static htab_t
|
| +allocate_dwp_loaded_cutus_table (struct objfile *objfile)
|
| +{
|
| + return htab_create_alloc_ex (3,
|
| + hash_dwp_loaded_cutus,
|
| + eq_dwp_loaded_cutus,
|
| + NULL,
|
| + &objfile->objfile_obstack,
|
| + hashtab_obstack_allocate,
|
| + dummy_obstack_deallocate);
|
| +}
|
| +
|
| +/* Try to open DWP file FILE_NAME.
|
| The result is the bfd handle of the file.
|
| If there is a problem finding or opening the file, return NULL.
|
| Upon success, the canonicalized path of the file is stored in the bfd,
|
| same as symfile_bfd_open. */
|
|
|
| static bfd *
|
| -open_dwo_file (const char *dwo_name, const char *comp_dir)
|
| +open_dwp_file (const char *file_name)
|
| {
|
| bfd *abfd;
|
|
|
| - if (IS_ABSOLUTE_PATH (dwo_name))
|
| - return try_open_dwo_file (dwo_name);
|
| + abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/);
|
| + if (abfd != NULL)
|
| + return abfd;
|
|
|
| - /* Before trying the search path, try DWO_NAME in COMP_DIR. */
|
| -
|
| - if (comp_dir != NULL)
|
| + /* Work around upstream bug 15652.
|
| + http://sourceware.org/bugzilla/show_bug.cgi?id=15652
|
| + [Whether that's a "bug" is debatable, but it is getting in our way.]
|
| + We have no real idea where the dwp file is, because gdb's realpath-ing
|
| + of the executable's path may have discarded the needed info.
|
| + [IWBN if the dwp file name was recorded in the executable, akin to
|
| + .gnu_debuglink, but that doesn't exist yet.]
|
| + Strip the directory from FILE_NAME and search again. */
|
| + if (*debug_file_directory != '\0')
|
| {
|
| - char *path_to_try = concat (comp_dir, SLASH_STRING, dwo_name, NULL);
|
| -
|
| - /* NOTE: If comp_dir is a relative path, this will also try the
|
| - search path, which seems useful. */
|
| - abfd = try_open_dwo_file (path_to_try);
|
| - xfree (path_to_try);
|
| - if (abfd != NULL)
|
| - return abfd;
|
| + /* Don't implicitly search the current directory here.
|
| + If the user wants to search "." to handle this case,
|
| + it must be added to debug-file-directory. */
|
| + return try_open_dwop_file (lbasename (file_name), 1 /*is_dwp*/,
|
| + 0 /*search_cwd*/);
|
| }
|
|
|
| - /* That didn't work, try debug-file-directory, which, despite its name,
|
| - is a list of paths. */
|
| -
|
| - if (*debug_file_directory == '\0')
|
| - return NULL;
|
| -
|
| - return try_open_dwo_file (dwo_name);
|
| + return NULL;
|
| }
|
|
|
| -/* Initialize the use of the DWO file specified by DWO_NAME. */
|
| +/* Initialize the use of the DWP file for the current objfile.
|
| + By convention the name of the DWP file is ${objfile}.dwp.
|
| + The result is NULL if it can't be found. */
|
|
|
| -static struct dwo_file *
|
| -init_dwo_file (const char *dwo_name, const char *comp_dir)
|
| +static struct dwp_file *
|
| +open_and_init_dwp_file (void)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - struct dwo_file *dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| - struct dwo_file);
|
| - bfd *abfd;
|
| + struct dwp_file *dwp_file;
|
| + char *dwp_name;
|
| + bfd *dbfd;
|
| struct cleanup *cleanups;
|
|
|
| - if (dwarf2_read_debug)
|
| - fprintf_unfiltered (gdb_stdlog, "Reading DWO file %s:\n", dwo_name);
|
| -
|
| - abfd = open_dwo_file (dwo_name, comp_dir);
|
| - if (abfd == NULL)
|
| - return NULL;
|
| - dwo_file->dwo_name = dwo_name;
|
| - dwo_file->dwo_bfd = abfd;
|
| + /* Try to find first .dwp for the binary file before any symbolic links
|
| + resolving. */
|
| + dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
|
| + cleanups = make_cleanup (xfree, dwp_name);
|
|
|
| - cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
|
| + dbfd = open_dwp_file (dwp_name);
|
| + if (dbfd == NULL
|
| + && strcmp (objfile->original_name, objfile_name (objfile)) != 0)
|
| + {
|
| + /* Try to find .dwp for the binary file after gdb_realpath resolving. */
|
| + dwp_name = xstrprintf ("%s.dwp", objfile_name (objfile));
|
| + make_cleanup (xfree, dwp_name);
|
| + dbfd = open_dwp_file (dwp_name);
|
| + }
|
|
|
| - bfd_map_over_sections (abfd, dwarf2_locate_dwo_sections, dwo_file);
|
| + if (dbfd == NULL)
|
| + {
|
| + if (dwarf2_read_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name);
|
| + do_cleanups (cleanups);
|
| + return NULL;
|
| + }
|
| + dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
|
| + dwp_file->name = bfd_get_filename (dbfd);
|
| + dwp_file->dbfd = dbfd;
|
| + do_cleanups (cleanups);
|
|
|
| - dwo_file->cus = create_debug_info_hash_table (dwo_file);
|
| + /* +1: section 0 is unused */
|
| + dwp_file->num_sections = bfd_count_sections (dbfd) + 1;
|
| + dwp_file->elf_sections =
|
| + OBSTACK_CALLOC (&objfile->objfile_obstack,
|
| + dwp_file->num_sections, asection *);
|
|
|
| - dwo_file->tus = create_debug_types_hash_table (dwo_file,
|
| - dwo_file->sections.types);
|
| + bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
|
|
|
| - discard_cleanups (cleanups);
|
| + dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
|
|
|
| - return dwo_file;
|
| -}
|
| + dwp_file->tus = create_dwp_hash_table (dwp_file, 1);
|
|
|
| -/* Lookup DWO file DWO_NAME. */
|
| + /* The DWP file version is stored in the hash table. Oh well. */
|
| + if (dwp_file->cus->version != dwp_file->tus->version)
|
| + {
|
| + /* Technically speaking, we should try to limp along, but this is
|
| + pretty bizarre. */
|
| + error (_("Dwarf Error: DWP file CU version %d doesn't match"
|
| + " TU version %d [in DWP file %s]"),
|
| + dwp_file->cus->version, dwp_file->tus->version, dwp_name);
|
| + }
|
| + dwp_file->version = dwp_file->cus->version;
|
|
|
| -static struct dwo_file *
|
| -lookup_dwo_file (char *dwo_name, const char *comp_dir)
|
| -{
|
| - struct dwo_file *dwo_file;
|
| - struct dwo_file find_entry;
|
| - void **slot;
|
| + if (dwp_file->version == 2)
|
| + bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
|
|
|
| - if (dwarf2_per_objfile->dwo_files == NULL)
|
| - dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
|
| + dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
|
| + dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
|
|
|
| - /* Have we already seen this DWO file? */
|
| - find_entry.dwo_name = dwo_name;
|
| - slot = htab_find_slot (dwarf2_per_objfile->dwo_files, &find_entry, INSERT);
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "DWP file found: %s\n", dwp_file->name);
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + " %s CUs, %s TUs\n",
|
| + pulongest (dwp_file->cus ? dwp_file->cus->nr_units : 0),
|
| + pulongest (dwp_file->tus ? dwp_file->tus->nr_units : 0));
|
| + }
|
|
|
| - /* If not, read it in and build a table of the DWOs it contains. */
|
| - if (*slot == NULL)
|
| - *slot = init_dwo_file (dwo_name, comp_dir);
|
| + return dwp_file;
|
| +}
|
|
|
| - /* NOTE: This will be NULL if unable to open the file. */
|
| - dwo_file = *slot;
|
| +/* Wrapper around open_and_init_dwp_file, only open it once. */
|
|
|
| - return dwo_file;
|
| +static struct dwp_file *
|
| +get_dwp_file (void)
|
| +{
|
| + if (! dwarf2_per_objfile->dwp_checked)
|
| + {
|
| + dwarf2_per_objfile->dwp_file = open_and_init_dwp_file ();
|
| + dwarf2_per_objfile->dwp_checked = 1;
|
| + }
|
| + return dwarf2_per_objfile->dwp_file;
|
| }
|
|
|
| -/* Lookup the DWO CU referenced from THIS_CU in DWO file DWO_NAME.
|
| +/* Subroutine of lookup_dwo_comp_unit, lookup_dwo_type_unit.
|
| + Look up the CU/TU with signature SIGNATURE, either in DWO file DWO_NAME
|
| + or in the DWP file for the objfile, referenced by THIS_UNIT.
|
| If non-NULL, comp_dir is the DW_AT_comp_dir attribute.
|
| - SIGNATURE is the "dwo_id" of the CU (for consistency we use the same
|
| - nomenclature as TUs).
|
| + IS_DEBUG_TYPES is non-zero if reading a TU, otherwise read a CU.
|
| +
|
| + This is called, for example, when wanting to read a variable with a
|
| + complex location. Therefore we don't want to do file i/o for every call.
|
| + Therefore we don't want to look for a DWO file on every call.
|
| + Therefore we first see if we've already seen SIGNATURE in a DWP file,
|
| + then we check if we've already seen DWO_NAME, and only THEN do we check
|
| + for a DWO file.
|
| +
|
| The result is a pointer to the dwo_unit object or NULL if we didn't find it
|
| - (dwo_id mismatch or couldn't find the DWO file). */
|
| + (dwo_id mismatch or couldn't find the DWO/DWP file). */
|
|
|
| static struct dwo_unit *
|
| -lookup_dwo_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| - char *dwo_name, const char *comp_dir,
|
| - ULONGEST signature)
|
| +lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit,
|
| + const char *dwo_name, const char *comp_dir,
|
| + ULONGEST signature, int is_debug_types)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + const char *kind = is_debug_types ? "TU" : "CU";
|
| + void **dwo_file_slot;
|
| struct dwo_file *dwo_file;
|
| + struct dwp_file *dwp_file;
|
|
|
| - dwo_file = lookup_dwo_file (dwo_name, comp_dir);
|
| - if (dwo_file == NULL)
|
| - return NULL;
|
| + /* First see if there's a DWP file.
|
| + If we have a DWP file but didn't find the DWO inside it, don't
|
| + look for the original DWO file. It makes gdb behave differently
|
| + depending on whether one is debugging in the build tree. */
|
| +
|
| + dwp_file = get_dwp_file ();
|
| + if (dwp_file != NULL)
|
| + {
|
| + const struct dwp_hash_table *dwp_htab =
|
| + is_debug_types ? dwp_file->tus : dwp_file->cus;
|
|
|
| - /* Look up the DWO using its signature(dwo_id). */
|
| + if (dwp_htab != NULL)
|
| + {
|
| + struct dwo_unit *dwo_cutu =
|
| + lookup_dwo_unit_in_dwp (dwp_file, comp_dir,
|
| + signature, is_debug_types);
|
|
|
| - if (dwo_file->cus != NULL)
|
| + if (dwo_cutu != NULL)
|
| + {
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Virtual DWO %s %s found: @%s\n",
|
| + kind, hex_string (signature),
|
| + host_address_to_string (dwo_cutu));
|
| + }
|
| + return dwo_cutu;
|
| + }
|
| + }
|
| + }
|
| + else
|
| {
|
| - struct dwo_unit find_dwo_cu, *dwo_cu;
|
| + /* No DWP file, look for the DWO file. */
|
|
|
| - find_dwo_cu.signature = signature;
|
| - dwo_cu = htab_find (dwo_file->cus, &find_dwo_cu);
|
| + dwo_file_slot = lookup_dwo_file_slot (dwo_name, comp_dir);
|
| + if (*dwo_file_slot == NULL)
|
| + {
|
| + /* Read in the file and build a table of the CUs/TUs it contains. */
|
| + *dwo_file_slot = open_and_init_dwo_file (this_unit, dwo_name, comp_dir);
|
| + }
|
| + /* NOTE: This will be NULL if unable to open the file. */
|
| + dwo_file = *dwo_file_slot;
|
| +
|
| + if (dwo_file != NULL)
|
| + {
|
| + struct dwo_unit *dwo_cutu = NULL;
|
| +
|
| + if (is_debug_types && dwo_file->tus)
|
| + {
|
| + struct dwo_unit find_dwo_cutu;
|
| +
|
| + memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu));
|
| + find_dwo_cutu.signature = signature;
|
| + dwo_cutu = htab_find (dwo_file->tus, &find_dwo_cutu);
|
| + }
|
| + else if (!is_debug_types && dwo_file->cu)
|
| + {
|
| + if (signature == dwo_file->cu->signature)
|
| + dwo_cutu = dwo_file->cu;
|
| + }
|
|
|
| - if (dwo_cu != NULL)
|
| - return dwo_cu;
|
| + if (dwo_cutu != NULL)
|
| + {
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) found: @%s\n",
|
| + kind, dwo_name, hex_string (signature),
|
| + host_address_to_string (dwo_cutu));
|
| + }
|
| + return dwo_cutu;
|
| + }
|
| + }
|
| }
|
|
|
| - /* We didn't find it. This must mean a dwo_id mismatch. */
|
| + /* We didn't find it. This could mean a dwo_id mismatch, or
|
| + someone deleted the DWO/DWP file, or the search path isn't set up
|
| + correctly to find the file. */
|
|
|
| - complaint (&symfile_complaints,
|
| - _("Could not find DWO CU referenced by CU at offset 0x%x"
|
| - " [in module %s]"),
|
| - this_cu->offset.sect_off, objfile->name);
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "DWO %s %s(%s) not found\n",
|
| + kind, dwo_name, hex_string (signature));
|
| + }
|
| +
|
| + /* This is a warning and not a complaint because it can be caused by
|
| + pilot error (e.g., user accidentally deleting the DWO). */
|
| + warning (_("Could not find DWO %s %s(%s) referenced by %s at offset 0x%x"
|
| + " [in module %s]"),
|
| + kind, dwo_name, hex_string (signature),
|
| + this_unit->is_debug_types ? "TU" : "CU",
|
| + this_unit->offset.sect_off, objfile_name (objfile));
|
| return NULL;
|
| }
|
|
|
| -/* Lookup the DWO TU referenced from THIS_TU in DWO file DWO_NAME.
|
| - If non-NULL, comp_dir is the DW_AT_comp_dir attribute.
|
| - The result is a pointer to the dwo_unit object or NULL if we didn't find it
|
| - (dwo_id mismatch or couldn't find the DWO file). */
|
| +/* Lookup the DWO CU DWO_NAME/SIGNATURE referenced from THIS_CU.
|
| + See lookup_dwo_cutu_unit for details. */
|
| +
|
| +static struct dwo_unit *
|
| +lookup_dwo_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| + const char *dwo_name, const char *comp_dir,
|
| + ULONGEST signature)
|
| +{
|
| + return lookup_dwo_cutu (this_cu, dwo_name, comp_dir, signature, 0);
|
| +}
|
| +
|
| +/* Lookup the DWO TU DWO_NAME/SIGNATURE referenced from THIS_TU.
|
| + See lookup_dwo_cutu_unit for details. */
|
|
|
| static struct dwo_unit *
|
| lookup_dwo_type_unit (struct signatured_type *this_tu,
|
| - char *dwo_name, const char *comp_dir)
|
| + const char *dwo_name, const char *comp_dir)
|
| {
|
| - struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - struct dwo_file *dwo_file;
|
| + return lookup_dwo_cutu (&this_tu->per_cu, dwo_name, comp_dir, this_tu->signature, 1);
|
| +}
|
|
|
| - dwo_file = lookup_dwo_file (dwo_name, comp_dir);
|
| - if (dwo_file == NULL)
|
| - return NULL;
|
| +/* Traversal function for queue_and_load_all_dwo_tus. */
|
|
|
| - /* Look up the DWO using its signature(dwo_id). */
|
| +static int
|
| +queue_and_load_dwo_tu (void **slot, void *info)
|
| +{
|
| + struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
|
| + struct dwarf2_per_cu_data *per_cu = (struct dwarf2_per_cu_data *) info;
|
| + ULONGEST signature = dwo_unit->signature;
|
| + struct signatured_type *sig_type =
|
| + lookup_dwo_signatured_type (per_cu->cu, signature);
|
|
|
| - if (dwo_file->tus != NULL)
|
| + if (sig_type != NULL)
|
| {
|
| - struct dwo_unit find_dwo_tu, *dwo_tu;
|
| -
|
| - find_dwo_tu.signature = this_tu->signature;
|
| - dwo_tu = htab_find (dwo_file->tus, &find_dwo_tu);
|
| + struct dwarf2_per_cu_data *sig_cu = &sig_type->per_cu;
|
|
|
| - if (dwo_tu != NULL)
|
| - return dwo_tu;
|
| + /* We pass NULL for DEPENDENT_CU because we don't yet know if there's
|
| + a real dependency of PER_CU on SIG_TYPE. That is detected later
|
| + while processing PER_CU. */
|
| + if (maybe_queue_comp_unit (NULL, sig_cu, per_cu->cu->language))
|
| + load_full_type_unit (sig_cu);
|
| + VEC_safe_push (dwarf2_per_cu_ptr, per_cu->imported_symtabs, sig_cu);
|
| }
|
|
|
| - /* We didn't find it. This must mean a dwo_id mismatch. */
|
| + return 1;
|
| +}
|
| +
|
| +/* Queue all TUs contained in the DWO of PER_CU to be read in.
|
| + The DWO may have the only definition of the type, though it may not be
|
| + referenced anywhere in PER_CU. Thus we have to load *all* its TUs.
|
| + http://sourceware.org/bugzilla/show_bug.cgi?id=15021 */
|
|
|
| - complaint (&symfile_complaints,
|
| - _("Could not find DWO TU referenced by TU at offset 0x%x"
|
| - " [in module %s]"),
|
| - this_tu->per_cu.offset.sect_off, objfile->name);
|
| - return NULL;
|
| +static void
|
| +queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *per_cu)
|
| +{
|
| + struct dwo_unit *dwo_unit;
|
| + struct dwo_file *dwo_file;
|
| +
|
| + gdb_assert (!per_cu->is_debug_types);
|
| + gdb_assert (get_dwp_file () == NULL);
|
| + gdb_assert (per_cu->cu != NULL);
|
| +
|
| + dwo_unit = per_cu->cu->dwo_unit;
|
| + gdb_assert (dwo_unit != NULL);
|
| +
|
| + dwo_file = dwo_unit->dwo_file;
|
| + if (dwo_file->tus != NULL)
|
| + htab_traverse_noresize (dwo_file->tus, queue_and_load_dwo_tu, per_cu);
|
| }
|
|
|
| /* Free all resources associated with DWO_FILE.
|
| @@ -8323,21 +10763,8 @@ free_dwo_file (struct dwo_file *dwo_file, struct objfile *objfile)
|
| int ix;
|
| struct dwarf2_section_info *section;
|
|
|
| - gdb_assert (dwo_file->dwo_bfd != objfile->obfd);
|
| - bfd_close (dwo_file->dwo_bfd);
|
| -
|
| - munmap_section_buffer (&dwo_file->sections.abbrev);
|
| - munmap_section_buffer (&dwo_file->sections.info);
|
| - munmap_section_buffer (&dwo_file->sections.line);
|
| - munmap_section_buffer (&dwo_file->sections.loc);
|
| - munmap_section_buffer (&dwo_file->sections.str);
|
| - munmap_section_buffer (&dwo_file->sections.str_offsets);
|
| -
|
| - for (ix = 0;
|
| - VEC_iterate (dwarf2_section_info_def, dwo_file->sections.types,
|
| - ix, section);
|
| - ++ix)
|
| - munmap_section_buffer (section);
|
| + /* Note: dbfd is NULL for virtual DWO files. */
|
| + gdb_bfd_unref (dwo_file->dbfd);
|
|
|
| VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
|
| }
|
| @@ -8523,7 +10950,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| CORE_ADDR highpc;
|
| struct die_info *child_die;
|
| struct attribute *attr, *call_line, *call_file;
|
| - char *name;
|
| + const char *name;
|
| CORE_ADDR baseaddr;
|
| struct block *block;
|
| int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
|
| @@ -8580,8 +11007,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| if (child_die->tag == DW_TAG_template_type_param
|
| || child_die->tag == DW_TAG_template_value_param)
|
| {
|
| - templ_func = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| - struct template_symbol);
|
| + templ_func = allocate_template_symbol (objfile);
|
| templ_func->base.is_cplus_template_function = 1;
|
| break;
|
| }
|
| @@ -8595,16 +11021,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| it. */
|
| attr = dwarf2_attr (die, DW_AT_frame_base, cu);
|
| if (attr)
|
| - /* FIXME: cagney/2004-01-26: The DW_AT_frame_base's location
|
| - expression is being recorded directly in the function's symbol
|
| - and not in a separate frame-base object. I guess this hack is
|
| - to avoid adding some sort of frame-base adjunct/annex to the
|
| - function's symbol :-(. The problem with doing this is that it
|
| - results in a function symbol with a location expression that
|
| - has nothing to do with the location of the function, ouch! The
|
| - relationship should be: a function's symbol has-a frame base; a
|
| - frame-base has-a location expression. */
|
| - dwarf2_symbol_mark_computed (attr, new->name, cu);
|
| + dwarf2_symbol_mark_computed (attr, new->name, cu, 1);
|
|
|
| cu->list_in_scope = &local_symbols;
|
|
|
| @@ -8660,10 +11077,10 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| lowpc, highpc, objfile);
|
|
|
| /* For C++, set the block's scope. */
|
| - if (cu->language == language_cplus || cu->language == language_fortran)
|
| - cp_set_block_scope (new->name, block, &objfile->objfile_obstack,
|
| - determine_prefix (die, cu),
|
| - processing_has_namespace_info);
|
| + if ((cu->language == language_cplus || cu->language == language_fortran)
|
| + && cu->processing_has_namespace_info)
|
| + block_set_scope (block, determine_prefix (die, cu),
|
| + &objfile->objfile_obstack);
|
|
|
| /* If we have address ranges, record them. */
|
| dwarf2_record_block_ranges (die, block, baseaddr, cu);
|
| @@ -8689,7 +11106,6 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| when we finish processing a function scope, we may need to go
|
| back to building a containing block's symbol lists. */
|
| local_symbols = new->locals;
|
| - param_symbols = new->params;
|
| using_directives = new->using_directives;
|
|
|
| /* If we've finished processing a top-level function, subsequent
|
| @@ -8778,7 +11194,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("missing DW_AT_low_pc for DW_TAG_GNU_call_site "
|
| "DIE 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| + die->offset.sect_off, objfile_name (objfile));
|
| return;
|
| }
|
| pc = DW_ADDR (attr) + baseaddr;
|
| @@ -8794,7 +11210,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("Duplicate PC %s for DW_TAG_GNU_call_site "
|
| "DIE 0x%x [in module %s]"),
|
| - paddress (gdbarch, pc), die->offset.sect_off, objfile->name);
|
| + paddress (gdbarch, pc), die->offset.sect_off,
|
| + objfile_name (objfile));
|
| return;
|
| }
|
|
|
| @@ -8809,7 +11226,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("Tag %d is not DW_TAG_GNU_call_site_parameter in "
|
| "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
|
| - child_die->tag, child_die->offset.sect_off, objfile->name);
|
| + child_die->tag, child_die->offset.sect_off,
|
| + objfile_name (objfile));
|
| continue;
|
| }
|
|
|
| @@ -8867,7 +11285,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("Cannot find function owning DW_TAG_GNU_call_site "
|
| "DIE 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| + die->offset.sect_off, objfile_name (objfile));
|
| }
|
| }
|
|
|
| @@ -8888,25 +11306,34 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| SET_FIELD_DWARF_BLOCK (call_site->target, dlbaton);
|
| }
|
| - else if (is_ref_attr (attr))
|
| + else if (attr_form_is_ref (attr))
|
| {
|
| struct dwarf2_cu *target_cu = cu;
|
| struct die_info *target_die;
|
|
|
| - target_die = follow_die_ref_or_sig (die, attr, &target_cu);
|
| + target_die = follow_die_ref (die, attr, &target_cu);
|
| gdb_assert (target_cu->objfile == objfile);
|
| if (die_is_declaration (target_die, target_cu))
|
| {
|
| - const char *target_physname;
|
| -
|
| - target_physname = dwarf2_physname (NULL, target_die, target_cu);
|
| + const char *target_physname = NULL;
|
| + struct attribute *target_attr;
|
| +
|
| + /* Prefer the mangled name; otherwise compute the demangled one. */
|
| + target_attr = dwarf2_attr (target_die, DW_AT_linkage_name, target_cu);
|
| + if (target_attr == NULL)
|
| + target_attr = dwarf2_attr (target_die, DW_AT_MIPS_linkage_name,
|
| + target_cu);
|
| + if (target_attr != NULL && DW_STRING (target_attr) != NULL)
|
| + target_physname = DW_STRING (target_attr);
|
| + else
|
| + target_physname = dwarf2_physname (NULL, target_die, target_cu);
|
| if (target_physname == NULL)
|
| complaint (&symfile_complaints,
|
| _("DW_AT_GNU_call_site_target target DIE has invalid "
|
| "physname, for referencing DIE 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| + die->offset.sect_off, objfile_name (objfile));
|
| else
|
| - SET_FIELD_PHYSNAME (call_site->target, (char *) target_physname);
|
| + SET_FIELD_PHYSNAME (call_site->target, target_physname);
|
| }
|
| else
|
| {
|
| @@ -8917,7 +11344,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("DW_AT_GNU_call_site_target target DIE has invalid "
|
| "low pc, for referencing DIE 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| + die->offset.sect_off, objfile_name (objfile));
|
| else
|
| SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr);
|
| }
|
| @@ -8926,7 +11353,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither "
|
| "block nor reference, for DIE 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| + die->offset.sect_off, objfile_name (objfile));
|
|
|
| call_site->per_cu = cu->per_cu;
|
|
|
| @@ -8952,7 +11379,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| loc = dwarf2_attr (child_die, DW_AT_location, cu);
|
| origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
|
| - if (loc == NULL && origin != NULL && is_ref_attr (origin))
|
| + if (loc == NULL && origin != NULL && attr_form_is_ref (origin))
|
| {
|
| sect_offset offset;
|
|
|
| @@ -8967,7 +11394,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| _("DW_AT_abstract_origin offset is not in CU for "
|
| "DW_TAG_GNU_call_site child DIE 0x%x "
|
| "[in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| continue;
|
| }
|
| parameter->u.param_offset.cu_off = (offset.sect_off
|
| @@ -8978,7 +11405,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("No DW_FORM_block* DW_AT_location for "
|
| "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| continue;
|
| }
|
| else
|
| @@ -8998,7 +11425,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| "for DW_FORM_block* DW_AT_location is supported for "
|
| "DW_TAG_GNU_call_site child DIE 0x%x "
|
| "[in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| continue;
|
| }
|
| }
|
| @@ -9009,7 +11436,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("No DW_FORM_block* DW_AT_GNU_call_site_value for "
|
| "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| continue;
|
| }
|
| parameter->value = DW_BLOCK (attr)->data;
|
| @@ -9027,7 +11454,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for "
|
| "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
|
| - child_die->offset.sect_off, objfile->name);
|
| + child_die->offset.sect_off, objfile_name (objfile));
|
| else
|
| {
|
| parameter->data_value = DW_BLOCK (attr)->data;
|
| @@ -9055,7 +11482,7 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
|
| CORE_ADDR base;
|
| int found_base;
|
| unsigned int dummy;
|
| - gdb_byte *buffer;
|
| + const gdb_byte *buffer;
|
| CORE_ADDR marker;
|
| int low_set;
|
| CORE_ADDR low = 0;
|
| @@ -9142,6 +11569,17 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
|
| range_beginning += base;
|
| range_end += base;
|
|
|
| + /* A not-uncommon case of bad debug info.
|
| + Don't pollute the addrmap with bad data. */
|
| + if (range_beginning + baseaddr == 0
|
| + && !dwarf2_per_objfile->has_section_at_zero)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _(".debug_ranges entry has start address of zero"
|
| + " [in module %s]"), objfile_name (objfile));
|
| + continue;
|
| + }
|
| +
|
| if (ranges_pst != NULL)
|
| addrmap_set_empty (objfile->psymtabs_addrmap,
|
| range_beginning + baseaddr,
|
| @@ -9219,7 +11657,14 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
|
| attr = dwarf2_attr (die, DW_AT_ranges, cu);
|
| if (attr != NULL)
|
| {
|
| - unsigned int ranges_offset = DW_UNSND (attr) + cu->ranges_base;
|
| + /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton.
|
| + We take advantage of the fact that DW_AT_ranges does not appear
|
| + in DW_TAG_compile_unit of DWO files. */
|
| + int need_ranges_base = die->tag != DW_TAG_compile_unit;
|
| + unsigned int ranges_offset = (DW_UNSND (attr)
|
| + + (need_ranges_base
|
| + ? cu->ranges_base
|
| + : 0));
|
|
|
| /* Value of the DW_AT_ranges attribute is the offset in the
|
| .debug_ranges section. */
|
| @@ -9380,11 +11825,16 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| if (attr)
|
| {
|
| bfd *obfd = objfile->obfd;
|
| + /* DW_AT_ranges_base does not apply to DIEs from the DWO skeleton.
|
| + We take advantage of the fact that DW_AT_ranges does not appear
|
| + in DW_TAG_compile_unit of DWO files. */
|
| + int need_ranges_base = die->tag != DW_TAG_compile_unit;
|
|
|
| /* The value of the DW_AT_ranges attribute is the offset of the
|
| address range list in the .debug_ranges section. */
|
| - unsigned long offset = DW_UNSND (attr) + cu->ranges_base;
|
| - gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset;
|
| + unsigned long offset = (DW_UNSND (attr)
|
| + + (need_ranges_base ? cu->ranges_base : 0));
|
| + const gdb_byte *buffer;
|
|
|
| /* For some target architectures, but not others, the
|
| read_address function sign-extends the addresses it returns.
|
| @@ -9403,7 +11853,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| CORE_ADDR base = cu->base_address;
|
| int base_known = cu->base_known;
|
|
|
| - gdb_assert (dwarf2_per_objfile->ranges.readin);
|
| + dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
|
| if (offset >= dwarf2_per_objfile->ranges.size)
|
| {
|
| complaint (&symfile_complaints,
|
| @@ -9411,6 +11861,7 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| offset);
|
| return;
|
| }
|
| + buffer = dwarf2_per_objfile->ranges.buffer + offset;
|
|
|
| for (;;)
|
| {
|
| @@ -9457,9 +11908,20 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| if (start == end)
|
| continue;
|
|
|
| - record_block_range (block,
|
| - baseaddr + base + start,
|
| - baseaddr + base + end - 1);
|
| + start += base + baseaddr;
|
| + end += base + baseaddr;
|
| +
|
| + /* A not-uncommon case of bad debug info.
|
| + Don't pollute the addrmap with bad data. */
|
| + if (start == 0 && !dwarf2_per_objfile->has_section_at_zero)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _(".debug_ranges entry has start address of zero"
|
| + " [in module %s]"), objfile_name (objfile));
|
| + continue;
|
| + }
|
| +
|
| + record_block_range (block, start, end - 1);
|
| }
|
| }
|
| }
|
| @@ -9497,7 +11959,10 @@ check_producer (struct dwarf2_cu *cu)
|
| /* Not recognized as GCC. */
|
| }
|
| else
|
| - cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
|
| + {
|
| + cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
|
| + cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
|
| + }
|
| }
|
| else if (strncmp (cu->producer, "Intel(R) C", strlen ("Intel(R) C")) == 0)
|
| cu->producer_is_icc = 1;
|
| @@ -9598,7 +12063,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
|
| struct nextfield *new_field;
|
| struct attribute *attr;
|
| struct field *fp;
|
| - char *fieldname = "";
|
| + const char *fieldname = "";
|
|
|
| /* Allocate a new field list entry and link it in. */
|
| new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield));
|
| @@ -9909,6 +12374,34 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
|
| }
|
| }
|
|
|
| +/* Return true if this member function is a constructor, false
|
| + otherwise. */
|
| +
|
| +static int
|
| +dwarf2_is_constructor (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + const char *fieldname;
|
| + const char *typename;
|
| + int len;
|
| +
|
| + if (die->parent == NULL)
|
| + return 0;
|
| +
|
| + if (die->parent->tag != DW_TAG_structure_type
|
| + && die->parent->tag != DW_TAG_union_type
|
| + && die->parent->tag != DW_TAG_class_type)
|
| + return 0;
|
| +
|
| + fieldname = dwarf2_name (die, cu);
|
| + typename = dwarf2_name (die->parent, cu);
|
| + if (fieldname == NULL || typename == NULL)
|
| + return 0;
|
| +
|
| + len = strlen (fieldname);
|
| + return (strncmp (fieldname, typename, len) == 0
|
| + && (typename[len] == '\0' || typename[len] == '<'));
|
| +}
|
| +
|
| /* Add a member function to the proper fieldlist. */
|
|
|
| static void
|
| @@ -9920,7 +12413,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
|
| struct fnfieldlist *flp;
|
| int i;
|
| struct fn_field *fnp;
|
| - char *fieldname;
|
| + const char *fieldname;
|
| struct nextfnfield *new_fnfield;
|
| struct type *this_type;
|
| enum dwarf_access_attribute accessibility;
|
| @@ -10040,6 +12533,8 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
|
| if (attr && DW_UNSND (attr) != 0)
|
| fnp->is_artificial = 1;
|
|
|
| + fnp->is_constructor = dwarf2_is_constructor (die, cu);
|
| +
|
| /* Get index in virtual function table if it is a virtual member
|
| function. For older versions of GCC, this is an offset in the
|
| appropriate virtual table, as specified by DW_AT_containing_type.
|
| @@ -10218,7 +12713,7 @@ producer_is_icc (struct dwarf2_cu *cu)
|
| /* Called when we find the DIE that starts a structure or union scope
|
| (definition) to create a type for the structure or union. Fill in
|
| the type's name and general properties; the members will not be
|
| - processed until process_structure_type.
|
| + processed until process_structure_scope.
|
|
|
| NOTE: we need to call these functions regardless of whether or not the
|
| DIE has a DW_AT_name attribute, since it might be an anonymous
|
| @@ -10238,7 +12733,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
| struct objfile *objfile = cu->objfile;
|
| struct type *type;
|
| struct attribute *attr;
|
| - char *name;
|
| + const char *name;
|
|
|
| /* If the definition of this type lives in .debug_types, read that type.
|
| Don't follow DW_AT_specification though, that will take us back up
|
| @@ -10246,17 +12741,10 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
| attr = dwarf2_attr_no_follow (die, DW_AT_signature);
|
| if (attr)
|
| {
|
| - struct dwarf2_cu *type_cu = cu;
|
| - struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
|
| -
|
| - /* We could just recurse on read_structure_type, but we need to call
|
| - get_die_type to ensure only one type for this DIE is created.
|
| - This is important, for example, because for c++ classes we need
|
| - TYPE_NAME set which is only done by new_symbol. Blech. */
|
| - type = read_type_die (type_die, type_cu);
|
| + type = get_DW_AT_signature_type (die, attr, cu);
|
|
|
| - /* TYPE_CU may not be the same as CU.
|
| - Ensure TYPE is recorded in CU's type_hash table. */
|
| + /* The type's CU may not be the same as CU.
|
| + Ensure TYPE is recorded with CU in die_type_hash. */
|
| return set_die_type (die, type, cu);
|
| }
|
|
|
| @@ -10269,7 +12757,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
| if (cu->language == language_cplus
|
| || cu->language == language_java)
|
| {
|
| - char *full_name = (char *) dwarf2_full_name (name, die, cu);
|
| + const char *full_name = dwarf2_full_name (name, die, cu);
|
|
|
| /* dwarf2_full_name might have already finished building the DIE's
|
| type. If so, there is no need to continue. */
|
| @@ -10285,7 +12773,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| /* The name is already allocated along with this objfile, so
|
| we don't need to duplicate it for the type. */
|
| - TYPE_TAG_NAME (type) = (char *) name;
|
| + TYPE_TAG_NAME (type) = name;
|
| if (die->tag == DW_TAG_class_type)
|
| TYPE_NAME (type) = TYPE_TAG_NAME (type);
|
| }
|
| @@ -10573,13 +13061,10 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
|
| attr = dwarf2_attr_no_follow (die, DW_AT_signature);
|
| if (attr)
|
| {
|
| - struct dwarf2_cu *type_cu = cu;
|
| - struct die_info *type_die = follow_die_ref_or_sig (die, attr, &type_cu);
|
| -
|
| - type = read_type_die (type_die, type_cu);
|
| + type = get_DW_AT_signature_type (die, attr, cu);
|
|
|
| - /* TYPE_CU may not be the same as CU.
|
| - Ensure TYPE is recorded in CU's type_hash table. */
|
| + /* The type's CU may not be the same as CU.
|
| + Ensure TYPE is recorded with CU in die_type_hash. */
|
| return set_die_type (die, type, cu);
|
| }
|
|
|
| @@ -10588,7 +13073,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
|
| TYPE_CODE (type) = TYPE_CODE_ENUM;
|
| name = dwarf2_full_name (NULL, die, cu);
|
| if (name != NULL)
|
| - TYPE_TAG_NAME (type) = (char *) name;
|
| + TYPE_TAG_NAME (type) = name;
|
|
|
| attr = dwarf2_attr (die, DW_AT_byte_size, cu);
|
| if (attr)
|
| @@ -10633,7 +13118,7 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| struct field *fields = NULL;
|
| int num_fields = 0;
|
| int unsigned_enum = 1;
|
| - char *name;
|
| + const char *name;
|
| int flag_enum = 1;
|
| ULONGEST mask = 0;
|
|
|
| @@ -10708,10 +13193,7 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| struct signatured_type *sig_type;
|
|
|
| - sig_type
|
| - = lookup_signatured_type_at_offset (dwarf2_per_objfile->objfile,
|
| - cu->per_cu->info_or_types_section,
|
| - cu->per_cu->offset);
|
| + sig_type = (struct signatured_type *) cu->per_cu;
|
| gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
|
| if (sig_type->type_offset_in_section.sect_off != die->offset.sect_off)
|
| return;
|
| @@ -10735,7 +13217,7 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu)
|
| struct attribute *attr;
|
| int ndim = 0;
|
| struct cleanup *back_to;
|
| - char *name;
|
| + const char *name;
|
|
|
| element_type = die_type (die, cu);
|
|
|
| @@ -10894,15 +13376,88 @@ read_set_type (struct die_info *die, struct dwarf2_cu *cu)
|
| return set_die_type (die, set_type, cu);
|
| }
|
|
|
| -/* First cut: install each common block member as a global variable. */
|
| +/* A helper for read_common_block that creates a locexpr baton.
|
| + SYM is the symbol which we are marking as computed.
|
| + COMMON_DIE is the DIE for the common block.
|
| + COMMON_LOC is the location expression attribute for the common
|
| + block itself.
|
| + MEMBER_LOC is the location expression attribute for the particular
|
| + member of the common block that we are processing.
|
| + CU is the CU from which the above come. */
|
| +
|
| +static void
|
| +mark_common_block_symbol_computed (struct symbol *sym,
|
| + struct die_info *common_die,
|
| + struct attribute *common_loc,
|
| + struct attribute *member_loc,
|
| + struct dwarf2_cu *cu)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_locexpr_baton *baton;
|
| + gdb_byte *ptr;
|
| + unsigned int cu_off;
|
| + enum bfd_endian byte_order = gdbarch_byte_order (get_objfile_arch (objfile));
|
| + LONGEST offset = 0;
|
| +
|
| + gdb_assert (common_loc && member_loc);
|
| + gdb_assert (attr_form_is_block (common_loc));
|
| + gdb_assert (attr_form_is_block (member_loc)
|
| + || attr_form_is_constant (member_loc));
|
| +
|
| + baton = obstack_alloc (&objfile->objfile_obstack,
|
| + sizeof (struct dwarf2_locexpr_baton));
|
| + baton->per_cu = cu->per_cu;
|
| + gdb_assert (baton->per_cu);
|
| +
|
| + baton->size = 5 /* DW_OP_call4 */ + 1 /* DW_OP_plus */;
|
| +
|
| + if (attr_form_is_constant (member_loc))
|
| + {
|
| + offset = dwarf2_get_attr_constant_value (member_loc, 0);
|
| + baton->size += 1 /* DW_OP_addr */ + cu->header.addr_size;
|
| + }
|
| + else
|
| + baton->size += DW_BLOCK (member_loc)->size;
|
| +
|
| + ptr = obstack_alloc (&objfile->objfile_obstack, baton->size);
|
| + baton->data = ptr;
|
| +
|
| + *ptr++ = DW_OP_call4;
|
| + cu_off = common_die->offset.sect_off - cu->per_cu->offset.sect_off;
|
| + store_unsigned_integer (ptr, 4, byte_order, cu_off);
|
| + ptr += 4;
|
| +
|
| + if (attr_form_is_constant (member_loc))
|
| + {
|
| + *ptr++ = DW_OP_addr;
|
| + store_unsigned_integer (ptr, cu->header.addr_size, byte_order, offset);
|
| + ptr += cu->header.addr_size;
|
| + }
|
| + else
|
| + {
|
| + /* We have to copy the data here, because DW_OP_call4 will only
|
| + use a DW_AT_location attribute. */
|
| + memcpy (ptr, DW_BLOCK (member_loc)->data, DW_BLOCK (member_loc)->size);
|
| + ptr += DW_BLOCK (member_loc)->size;
|
| + }
|
| +
|
| + *ptr++ = DW_OP_plus;
|
| + gdb_assert (ptr - baton->data == baton->size);
|
| +
|
| + SYMBOL_LOCATION_BATON (sym) = baton;
|
| + SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
|
| +}
|
| +
|
| +/* Create appropriate locally-scoped variables for all the
|
| + DW_TAG_common_block entries. Also create a struct common_block
|
| + listing all such variables for `info common'. COMMON_BLOCK_DOMAIN
|
| + is used to sepate the common blocks name namespace from regular
|
| + variable names. */
|
|
|
| static void
|
| read_common_block (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| - struct die_info *child_die;
|
| struct attribute *attr;
|
| - struct symbol *sym;
|
| - CORE_ADDR base = (CORE_ADDR) 0;
|
|
|
| attr = dwarf2_attr (die, DW_AT_location, cu);
|
| if (attr)
|
| @@ -10910,34 +13465,85 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu)
|
| /* Support the .debug_loc offsets. */
|
| if (attr_form_is_block (attr))
|
| {
|
| - base = decode_locdesc (DW_BLOCK (attr), cu);
|
| + /* Ok. */
|
| }
|
| else if (attr_form_is_section_offset (attr))
|
| {
|
| dwarf2_complex_location_expr_complaint ();
|
| + attr = NULL;
|
| }
|
| else
|
| {
|
| dwarf2_invalid_attrib_class_complaint ("DW_AT_location",
|
| "common block member");
|
| + attr = NULL;
|
| }
|
| }
|
| +
|
| if (die->child != NULL)
|
| {
|
| - child_die = die->child;
|
| - while (child_die && child_die->tag)
|
| - {
|
| - LONGEST offset;
|
| + struct objfile *objfile = cu->objfile;
|
| + struct die_info *child_die;
|
| + size_t n_entries = 0, size;
|
| + struct common_block *common_block;
|
| + struct symbol *sym;
|
| +
|
| + for (child_die = die->child;
|
| + child_die && child_die->tag;
|
| + child_die = sibling_die (child_die))
|
| + ++n_entries;
|
|
|
| + size = (sizeof (struct common_block)
|
| + + (n_entries - 1) * sizeof (struct symbol *));
|
| + common_block = obstack_alloc (&objfile->objfile_obstack, size);
|
| + memset (common_block->contents, 0, n_entries * sizeof (struct symbol *));
|
| + common_block->n_entries = 0;
|
| +
|
| + for (child_die = die->child;
|
| + child_die && child_die->tag;
|
| + child_die = sibling_die (child_die))
|
| + {
|
| + /* Create the symbol in the DW_TAG_common_block block in the current
|
| + symbol scope. */
|
| sym = new_symbol (child_die, NULL, cu);
|
| - if (sym != NULL
|
| - && handle_data_member_location (child_die, cu, &offset))
|
| + if (sym != NULL)
|
| {
|
| - SYMBOL_VALUE_ADDRESS (sym) = base + offset;
|
| - add_symbol_to_list (sym, &global_symbols);
|
| + struct attribute *member_loc;
|
| +
|
| + common_block->contents[common_block->n_entries++] = sym;
|
| +
|
| + member_loc = dwarf2_attr (child_die, DW_AT_data_member_location,
|
| + cu);
|
| + if (member_loc)
|
| + {
|
| + /* GDB has handled this for a long time, but it is
|
| + not specified by DWARF. It seems to have been
|
| + emitted by gfortran at least as recently as:
|
| + http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23057. */
|
| + complaint (&symfile_complaints,
|
| + _("Variable in common block has "
|
| + "DW_AT_data_member_location "
|
| + "- DIE at 0x%x [in module %s]"),
|
| + child_die->offset.sect_off,
|
| + objfile_name (cu->objfile));
|
| +
|
| + if (attr_form_is_section_offset (member_loc))
|
| + dwarf2_complex_location_expr_complaint ();
|
| + else if (attr_form_is_constant (member_loc)
|
| + || attr_form_is_block (member_loc))
|
| + {
|
| + if (attr)
|
| + mark_common_block_symbol_computed (sym, die, attr,
|
| + member_loc, cu);
|
| + }
|
| + else
|
| + dwarf2_complex_location_expr_complaint ();
|
| + }
|
| }
|
| - child_die = sibling_die (child_die);
|
| }
|
| +
|
| + sym = new_symbol (die, objfile_type (objfile)->builtin_void, cu);
|
| + SYMBOL_VALUE_COMMON_BLOCK (sym) = common_block;
|
| }
|
| }
|
|
|
| @@ -10961,7 +13567,7 @@ read_namespace_type (struct die_info *die, struct dwarf2_cu *cu)
|
| type = read_type_die (ext_die, ext_cu);
|
|
|
| /* EXT_CU may not be the same as CU.
|
| - Ensure TYPE is recorded in CU's type_hash table. */
|
| + Ensure TYPE is recorded with CU in die_type_hash. */
|
| return set_die_type (die, type, cu);
|
| }
|
|
|
| @@ -10977,7 +13583,7 @@ read_namespace_type (struct die_info *die, struct dwarf2_cu *cu)
|
| /* Create the type. */
|
| type = init_type (TYPE_CODE_NAMESPACE, 0, 0, NULL,
|
| objfile);
|
| - TYPE_NAME (type) = (char *) name;
|
| + TYPE_NAME (type) = name;
|
| TYPE_TAG_NAME (type) = TYPE_NAME (type);
|
|
|
| return set_die_type (die, type, cu);
|
| @@ -11008,7 +13614,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
|
| const char *previous_prefix = determine_prefix (die, cu);
|
|
|
| cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL,
|
| - NULL, NULL, &objfile->objfile_obstack);
|
| + NULL, NULL, 0, &objfile->objfile_obstack);
|
| }
|
| }
|
|
|
| @@ -11032,7 +13638,7 @@ static struct type *
|
| read_module_type (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| - char *module_name;
|
| + const char *module_name;
|
| struct type *type;
|
|
|
| module_name = dwarf2_name (die, cu);
|
| @@ -11177,6 +13783,15 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_METHOD)
|
| type = lookup_methodptr_type (to_type);
|
| + else if (TYPE_CODE (check_typedef (to_type)) == TYPE_CODE_FUNC)
|
| + {
|
| + struct type *new_type = alloc_type (cu->objfile);
|
| +
|
| + smash_to_method_type (new_type, domain, TYPE_TARGET_TYPE (to_type),
|
| + TYPE_FIELDS (to_type), TYPE_NFIELDS (to_type),
|
| + TYPE_VARARGS (to_type));
|
| + type = lookup_methodptr_type (new_type);
|
| + }
|
| else
|
| type = lookup_memberptr_type (to_type, domain);
|
|
|
| @@ -11268,6 +13883,24 @@ read_tag_volatile_type (struct die_info *die, struct dwarf2_cu *cu)
|
| return set_die_type (die, cv_type, cu);
|
| }
|
|
|
| +/* Handle DW_TAG_restrict_type. */
|
| +
|
| +static struct type *
|
| +read_tag_restrict_type (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + struct type *base_type, *cv_type;
|
| +
|
| + base_type = die_type (die, cu);
|
| +
|
| + /* The die_type call above may have already set the type for this DIE. */
|
| + cv_type = get_die_type (die, cu);
|
| + if (cv_type)
|
| + return cv_type;
|
| +
|
| + cv_type = make_restrict_type (base_type);
|
| + return set_die_type (die, cv_type, cu);
|
| +}
|
| +
|
| /* Extract all information from a DW_TAG_string_type DIE and add to
|
| the user defined type vector. It isn't really a user defined type,
|
| but it behaves like one, with other DIE's using an AT_user_def_type
|
| @@ -11301,12 +13934,44 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
|
| }
|
| }
|
|
|
| - index_type = objfile_type (objfile)->builtin_int;
|
| - range_type = create_range_type (NULL, index_type, 1, length);
|
| - char_type = language_string_char_type (cu->language_defn, gdbarch);
|
| - type = create_string_type (NULL, char_type, range_type);
|
| + index_type = objfile_type (objfile)->builtin_int;
|
| + range_type = create_range_type (NULL, index_type, 1, length);
|
| + char_type = language_string_char_type (cu->language_defn, gdbarch);
|
| + type = create_string_type (NULL, char_type, range_type);
|
| +
|
| + return set_die_type (die, type, cu);
|
| +}
|
| +
|
| +/* Assuming that DIE corresponds to a function, returns nonzero
|
| + if the function is prototyped. */
|
| +
|
| +static int
|
| +prototyped_function_p (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + struct attribute *attr;
|
| +
|
| + attr = dwarf2_attr (die, DW_AT_prototyped, cu);
|
| + if (attr && (DW_UNSND (attr) != 0))
|
| + return 1;
|
|
|
| - return set_die_type (die, type, cu);
|
| + /* The DWARF standard implies that the DW_AT_prototyped attribute
|
| + is only meaninful for C, but the concept also extends to other
|
| + languages that allow unprototyped functions (Eg: Objective C).
|
| + For all other languages, assume that functions are always
|
| + prototyped. */
|
| + if (cu->language != language_c
|
| + && cu->language != language_objc
|
| + && cu->language != language_opencl)
|
| + return 1;
|
| +
|
| + /* RealView does not emit DW_AT_prototyped. We can not distinguish
|
| + prototyped and unprototyped functions; default to prototyped,
|
| + since that is more common in modern code (and RealView warns
|
| + about unprototyped functions). */
|
| + if (producer_is_realview (cu->producer))
|
| + return 1;
|
| +
|
| + return 0;
|
| }
|
|
|
| /* Handle DIES due to C code like:
|
| @@ -11336,18 +14001,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| ftype = lookup_function_type (type);
|
|
|
| - /* All functions in C++, Pascal and Java have prototypes. */
|
| - attr = dwarf2_attr (die, DW_AT_prototyped, cu);
|
| - if ((attr && (DW_UNSND (attr) != 0))
|
| - || cu->language == language_cplus
|
| - || cu->language == language_java
|
| - || cu->language == language_pascal)
|
| - TYPE_PROTOTYPED (ftype) = 1;
|
| - else if (producer_is_realview (cu->producer))
|
| - /* RealView does not emit DW_AT_prototyped. We can not
|
| - distinguish prototyped and unprototyped functions; default to
|
| - prototyped, since that is more common in modern code (and
|
| - RealView warns about unprototyped functions). */
|
| + if (prototyped_function_p (die, cu))
|
| TYPE_PROTOTYPED (ftype) = 1;
|
|
|
| /* Store the calling convention in the type if it's available in
|
| @@ -11483,7 +14137,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
|
| name = dwarf2_full_name (NULL, die, cu);
|
| this_type = init_type (TYPE_CODE_TYPEDEF, 0,
|
| TYPE_FLAG_TARGET_STUB, NULL, objfile);
|
| - TYPE_NAME (this_type) = (char *) name;
|
| + TYPE_NAME (this_type) = name;
|
| set_die_type (die, this_type, cu);
|
| target_type = die_type (die, cu);
|
| if (target_type != this_type)
|
| @@ -11495,7 +14149,7 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("Self-referential DW_TAG_typedef "
|
| "- DIE at 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| + die->offset.sect_off, objfile_name (objfile));
|
| TYPE_TARGET_TYPE (this_type) = NULL;
|
| }
|
| return this_type;
|
| @@ -11511,7 +14165,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
|
| struct type *type;
|
| struct attribute *attr;
|
| int encoding = 0, size = 0;
|
| - char *name;
|
| + const char *name;
|
| enum type_code code = TYPE_CODE_INT;
|
| int type_flags = 0;
|
| struct type *target_type = NULL;
|
| @@ -11603,17 +14257,20 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
|
| static struct type *
|
| read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| - struct type *base_type;
|
| + struct type *base_type, *orig_base_type;
|
| struct type *range_type;
|
| struct attribute *attr;
|
| LONGEST low, high;
|
| int low_default_is_valid;
|
| - char *name;
|
| + const char *name;
|
| LONGEST negative_mask;
|
|
|
| - base_type = die_type (die, cu);
|
| - /* Preserve BASE_TYPE's original type, just set its LENGTH. */
|
| - check_typedef (base_type);
|
| + orig_base_type = die_type (die, cu);
|
| + /* If ORIG_BASE_TYPE is a typedef, it will not be TYPE_UNSIGNED,
|
| + whereas the real type might be. So, we use ORIG_BASE_TYPE when
|
| + creating the range type, but we use the result of check_typedef
|
| + when examining properties of the type. */
|
| + base_type = check_typedef (orig_base_type);
|
|
|
| /* The die_type call above may have already set the type for this DIE. */
|
| range_type = get_die_type (die, cu);
|
| @@ -11660,12 +14317,12 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
| else if (!low_default_is_valid)
|
| complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
|
| "- DIE at 0x%x [in module %s]"),
|
| - die->offset.sect_off, cu->objfile->name);
|
| + die->offset.sect_off, objfile_name (cu->objfile));
|
|
|
| attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
|
| if (attr)
|
| {
|
| - if (attr_form_is_block (attr) || is_ref_attr (attr))
|
| + if (attr_form_is_block (attr) || attr_form_is_ref (attr))
|
| {
|
| /* GCC encodes arrays with unspecified or dynamic length
|
| with a DW_FORM_block1 attribute or a reference attribute.
|
| @@ -11743,7 +14400,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
| if (!TYPE_UNSIGNED (base_type) && (high & negative_mask))
|
| high |= negative_mask;
|
|
|
| - range_type = create_range_type (NULL, base_type, low, high);
|
| + range_type = create_range_type (NULL, orig_base_type, low, high);
|
|
|
| /* Mark arrays with dynamic length at least as an array of unspecified
|
| length. GDB could check the boundary but before it gets implemented at
|
| @@ -11792,15 +14449,15 @@ read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| static struct die_info *
|
| read_die_and_children (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| + const gdb_byte *info_ptr,
|
| + const gdb_byte **new_info_ptr,
|
| struct die_info *parent)
|
| {
|
| struct die_info *die;
|
| - gdb_byte *cur_ptr;
|
| + const gdb_byte *cur_ptr;
|
| int has_children;
|
|
|
| - cur_ptr = read_full_die (reader, &die, info_ptr, &has_children);
|
| + cur_ptr = read_full_die_1 (reader, &die, info_ptr, &has_children, 0);
|
| if (die == NULL)
|
| {
|
| *new_info_ptr = cur_ptr;
|
| @@ -11809,7 +14466,7 @@ read_die_and_children (const struct die_reader_specs *reader,
|
| store_in_ref_table (die, reader->cu);
|
|
|
| if (has_children)
|
| - die->child = read_die_and_siblings (reader, cur_ptr, new_info_ptr, die);
|
| + die->child = read_die_and_siblings_1 (reader, cur_ptr, new_info_ptr, die);
|
| else
|
| {
|
| die->child = NULL;
|
| @@ -11826,13 +14483,13 @@ read_die_and_children (const struct die_reader_specs *reader,
|
| in read_die_and_children. */
|
|
|
| static struct die_info *
|
| -read_die_and_siblings (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| - struct die_info *parent)
|
| +read_die_and_siblings_1 (const struct die_reader_specs *reader,
|
| + const gdb_byte *info_ptr,
|
| + const gdb_byte **new_info_ptr,
|
| + struct die_info *parent)
|
| {
|
| struct die_info *first_die, *last_sibling;
|
| - gdb_byte *cur_ptr;
|
| + const gdb_byte *cur_ptr;
|
|
|
| cur_ptr = info_ptr;
|
| first_die = last_sibling = NULL;
|
| @@ -11857,6 +14514,33 @@ read_die_and_siblings (const struct die_reader_specs *reader,
|
| }
|
| }
|
|
|
| +/* Read a die, all of its descendents, and all of its siblings; set
|
| + all of the fields of all of the dies correctly. Arguments are as
|
| + in read_die_and_children.
|
| + This the main entry point for reading a DIE and all its children. */
|
| +
|
| +static struct die_info *
|
| +read_die_and_siblings (const struct die_reader_specs *reader,
|
| + const gdb_byte *info_ptr,
|
| + const gdb_byte **new_info_ptr,
|
| + struct die_info *parent)
|
| +{
|
| + struct die_info *die = read_die_and_siblings_1 (reader, info_ptr,
|
| + new_info_ptr, parent);
|
| +
|
| + if (dwarf2_die_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Read die from %s@0x%x of %s:\n",
|
| + get_section_name (reader->die_section),
|
| + (unsigned) (info_ptr - reader->die_section->buffer),
|
| + bfd_get_filename (reader->abfd));
|
| + dump_die (die, dwarf2_die_debug);
|
| + }
|
| +
|
| + return die;
|
| +}
|
| +
|
| /* Read a die and all its attributes, leave space for NUM_EXTRA_ATTRS
|
| attributes.
|
| The caller is responsible for filling in the extra attributes
|
| @@ -11865,9 +14549,9 @@ read_die_and_siblings (const struct die_reader_specs *reader,
|
| except for its child, sibling, and parent fields.
|
| Set HAS_CHILDREN to tell whether the die has children or not. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_full_die_1 (const struct die_reader_specs *reader,
|
| - struct die_info **diep, gdb_byte *info_ptr,
|
| + struct die_info **diep, const gdb_byte *info_ptr,
|
| int *has_children, int num_extra_attrs)
|
| {
|
| unsigned int abbrev_number, bytes_read, i;
|
| @@ -11917,12 +14601,26 @@ read_full_die_1 (const struct die_reader_specs *reader,
|
| except for its child, sibling, and parent fields.
|
| Set HAS_CHILDREN to tell whether the die has children or not. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_full_die (const struct die_reader_specs *reader,
|
| - struct die_info **diep, gdb_byte *info_ptr,
|
| + struct die_info **diep, const gdb_byte *info_ptr,
|
| int *has_children)
|
| {
|
| - return read_full_die_1 (reader, diep, info_ptr, has_children, 0);
|
| + const gdb_byte *result;
|
| +
|
| + result = read_full_die_1 (reader, diep, info_ptr, has_children, 0);
|
| +
|
| + if (dwarf2_die_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Read die from %s@0x%x of %s:\n",
|
| + get_section_name (reader->die_section),
|
| + (unsigned) (info_ptr - reader->die_section->buffer),
|
| + bfd_get_filename (reader->abfd));
|
| + dump_die (*diep, dwarf2_die_debug);
|
| + }
|
| +
|
| + return result;
|
| }
|
|
|
| /* Abbreviation tables.
|
| @@ -11988,9 +14686,9 @@ abbrev_table_read_table (struct dwarf2_section_info *section,
|
| sect_offset offset)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - bfd *abfd = section->asection->owner;
|
| + bfd *abfd = get_section_bfd_owner (section);
|
| struct abbrev_table *abbrev_table;
|
| - gdb_byte *abbrev_ptr;
|
| + const gdb_byte *abbrev_ptr;
|
| struct abbrev_info *cur_abbrev;
|
| unsigned int abbrev_number, bytes_read, abbrev_name;
|
| unsigned int abbrev_form;
|
| @@ -12117,7 +14815,8 @@ dwarf2_free_abbrev_table (void *ptr_to_cu)
|
| {
|
| struct dwarf2_cu *cu = ptr_to_cu;
|
|
|
| - abbrev_table_free (cu->abbrev_table);
|
| + if (cu->abbrev_table != NULL)
|
| + abbrev_table_free (cu->abbrev_table);
|
| /* Set this to NULL so that we SEGV if we try to read it later,
|
| and also because free_comp_unit verifies this is NULL. */
|
| cu->abbrev_table = NULL;
|
| @@ -12159,7 +14858,7 @@ is_type_tag_for_partial (int tag)
|
|
|
| static struct partial_die_info *
|
| load_partial_dies (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr, int building_psymtab)
|
| + const gdb_byte *info_ptr, int building_psymtab)
|
| {
|
| struct dwarf2_cu *cu = reader->cu;
|
| struct objfile *objfile = cu->objfile;
|
| @@ -12254,7 +14953,8 @@ load_partial_dies (const struct die_reader_specs *reader,
|
| && abbrev->tag != DW_TAG_namespace
|
| && abbrev->tag != DW_TAG_module
|
| && abbrev->tag != DW_TAG_member
|
| - && abbrev->tag != DW_TAG_imported_unit)
|
| + && abbrev->tag != DW_TAG_imported_unit
|
| + && abbrev->tag != DW_TAG_imported_declaration)
|
| {
|
| /* Otherwise we skip to the next sibling, if any. */
|
| info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
|
| @@ -12308,7 +15008,7 @@ load_partial_dies (const struct die_reader_specs *reader,
|
| complaint (&symfile_complaints,
|
| _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
|
| "- DIE at 0x%x [in module %s]"),
|
| - part_die->offset.sect_off, objfile->name);
|
| + part_die->offset.sect_off, objfile_name (objfile));
|
|
|
| /* If we're at the second level, and we're an enumerator, and
|
| our parent has no specification (meaning possibly lives in a
|
| @@ -12433,15 +15133,15 @@ load_partial_dies (const struct die_reader_specs *reader,
|
|
|
| /* Read a minimal amount of information into the minimal die structure. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_partial_die (const struct die_reader_specs *reader,
|
| struct partial_die_info *part_die,
|
| struct abbrev_info *abbrev, unsigned int abbrev_len,
|
| - gdb_byte *info_ptr)
|
| + const gdb_byte *info_ptr)
|
| {
|
| struct dwarf2_cu *cu = reader->cu;
|
| struct objfile *objfile = cu->objfile;
|
| - gdb_byte *buffer = reader->buffer;
|
| + const gdb_byte *buffer = reader->buffer;
|
| unsigned int i;
|
| struct attribute attr;
|
| int has_low_pc_attr = 0;
|
| @@ -12543,6 +15243,8 @@ read_partial_die (const struct die_reader_specs *reader,
|
| case DW_AT_extension:
|
| part_die->has_specification = 1;
|
| part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
|
| + part_die->spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|
| + || cu->per_cu->is_dwz);
|
| break;
|
| case DW_AT_sibling:
|
| /* Ignore absolute siblings, they might point outside of
|
| @@ -12551,7 +15253,16 @@ read_partial_die (const struct die_reader_specs *reader,
|
| complaint (&symfile_complaints,
|
| _("ignoring absolute DW_AT_sibling"));
|
| else
|
| - part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
|
| + {
|
| + unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off;
|
| + const gdb_byte *sibling_ptr = buffer + off;
|
| +
|
| + if (sibling_ptr < info_ptr)
|
| + complaint (&symfile_complaints,
|
| + _("DW_AT_sibling points backwards"));
|
| + else
|
| + part_die->sibling = sibling_ptr;
|
| + }
|
| break;
|
| case DW_AT_byte_size:
|
| part_die->has_byte_size = 1;
|
| @@ -12589,7 +15300,11 @@ read_partial_die (const struct die_reader_specs *reader,
|
|
|
| case DW_AT_import:
|
| if (part_die->tag == DW_TAG_imported_unit)
|
| - part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
|
| + {
|
| + part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
|
| + part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|
| + || cu->per_cu->is_dwz);
|
| + }
|
| break;
|
|
|
| default:
|
| @@ -12618,7 +15333,7 @@ read_partial_die (const struct die_reader_specs *reader,
|
| _("DW_AT_low_pc %s is zero "
|
| "for DIE at 0x%x [in module %s]"),
|
| paddress (gdbarch, part_die->lowpc),
|
| - part_die->offset.sect_off, objfile->name);
|
| + part_die->offset.sect_off, objfile_name (objfile));
|
| }
|
| /* dwarf2_get_pc_bounds has also the strict low < high requirement. */
|
| else if (part_die->lowpc >= part_die->highpc)
|
| @@ -12630,7 +15345,7 @@ read_partial_die (const struct die_reader_specs *reader,
|
| "for DIE at 0x%x [in module %s]"),
|
| paddress (gdbarch, part_die->lowpc),
|
| paddress (gdbarch, part_die->highpc),
|
| - part_die->offset.sect_off, objfile->name);
|
| + part_die->offset.sect_off, objfile_name (objfile));
|
| }
|
| else
|
| part_die->has_pc_info = 1;
|
| @@ -12660,13 +15375,14 @@ find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
|
| DW_FORM_ref_sig8). */
|
|
|
| static struct partial_die_info *
|
| -find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
|
| +find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| struct dwarf2_per_cu_data *per_cu = NULL;
|
| struct partial_die_info *pd = NULL;
|
|
|
| - if (offset_in_cu_p (&cu->header, offset))
|
| + if (offset_in_dwz == cu->per_cu->is_dwz
|
| + && offset_in_cu_p (&cu->header, offset))
|
| {
|
| pd = find_partial_die_in_comp_unit (offset, cu);
|
| if (pd != NULL)
|
| @@ -12685,7 +15401,8 @@ find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
|
| (long) cu->header.offset.sect_off, (long) offset.sect_off,
|
| bfd_get_filename (objfile->obfd));
|
| }
|
| - per_cu = dwarf2_find_containing_comp_unit (offset, objfile);
|
| + per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
|
| + objfile);
|
|
|
| if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
|
| load_partial_comp_unit (per_cu);
|
| @@ -12743,7 +15460,8 @@ guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
|
|
|
| real_pdi = struct_pdi;
|
| while (real_pdi->has_specification)
|
| - real_pdi = find_partial_die (real_pdi->spec_offset, cu);
|
| + real_pdi = find_partial_die (real_pdi->spec_offset,
|
| + real_pdi->spec_is_dwz, cu);
|
|
|
| if (real_pdi->die_parent != NULL)
|
| return;
|
| @@ -12761,9 +15479,9 @@ guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
|
| if (actual_class_name != NULL)
|
| {
|
| struct_pdi->name
|
| - = obsavestring (actual_class_name,
|
| - strlen (actual_class_name),
|
| - &cu->objfile->objfile_obstack);
|
| + = obstack_copy0 (&cu->objfile->objfile_obstack,
|
| + actual_class_name,
|
| + strlen (actual_class_name));
|
| xfree (actual_class_name);
|
| }
|
| break;
|
| @@ -12791,7 +15509,8 @@ fixup_partial_die (struct partial_die_info *part_die,
|
| {
|
| struct partial_die_info *spec_die;
|
|
|
| - spec_die = find_partial_die (part_die->spec_offset, cu);
|
| + spec_die = find_partial_die (part_die->spec_offset,
|
| + part_die->spec_is_dwz, cu);
|
|
|
| fixup_partial_die (spec_die, cu);
|
|
|
| @@ -12833,7 +15552,7 @@ fixup_partial_die (struct partial_die_info *part_die,
|
| {
|
| char *demangled;
|
|
|
| - demangled = cplus_demangle (part_die->linkage_name, DMGL_TYPES);
|
| + demangled = gdb_demangle (part_die->linkage_name, DMGL_TYPES);
|
| if (demangled)
|
| {
|
| const char *base;
|
| @@ -12846,8 +15565,8 @@ fixup_partial_die (struct partial_die_info *part_die,
|
| else
|
| base = demangled;
|
|
|
| - part_die->name = obsavestring (base, strlen (base),
|
| - &cu->objfile->objfile_obstack);
|
| + part_die->name = obstack_copy0 (&cu->objfile->objfile_obstack,
|
| + base, strlen (base));
|
| xfree (demangled);
|
| }
|
| }
|
| @@ -12857,10 +15576,10 @@ fixup_partial_die (struct partial_die_info *part_die,
|
|
|
| /* Read an attribute value described by an attribute form. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_attribute_value (const struct die_reader_specs *reader,
|
| struct attribute *attr, unsigned form,
|
| - gdb_byte *info_ptr)
|
| + const gdb_byte *info_ptr)
|
| {
|
| struct dwarf2_cu *cu = reader->cu;
|
| bfd *abfd = reader->abfd;
|
| @@ -12879,6 +15598,10 @@ read_attribute_value (const struct die_reader_specs *reader,
|
| &cu->header, &bytes_read);
|
| info_ptr += bytes_read;
|
| break;
|
| + case DW_FORM_GNU_ref_alt:
|
| + DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
|
| + info_ptr += bytes_read;
|
| + break;
|
| case DW_FORM_addr:
|
| DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
|
| info_ptr += bytes_read;
|
| @@ -12921,10 +15644,25 @@ read_attribute_value (const struct die_reader_specs *reader,
|
| info_ptr += bytes_read;
|
| break;
|
| case DW_FORM_strp:
|
| - DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
|
| - &bytes_read);
|
| - DW_STRING_IS_CANONICAL (attr) = 0;
|
| - info_ptr += bytes_read;
|
| + if (!cu->per_cu->is_dwz)
|
| + {
|
| + DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
|
| + &bytes_read);
|
| + DW_STRING_IS_CANONICAL (attr) = 0;
|
| + info_ptr += bytes_read;
|
| + break;
|
| + }
|
| + /* FALLTHROUGH */
|
| + case DW_FORM_GNU_strp_alt:
|
| + {
|
| + struct dwz_file *dwz = dwarf2_get_dwz_file ();
|
| + LONGEST str_offset = read_offset (abfd, info_ptr, cu_header,
|
| + &bytes_read);
|
| +
|
| + DW_STRING (attr) = read_indirect_string_from_dwz (dwz, str_offset);
|
| + DW_STRING_IS_CANONICAL (attr) = 0;
|
| + info_ptr += bytes_read;
|
| + }
|
| break;
|
| case DW_FORM_exprloc:
|
| case DW_FORM_block:
|
| @@ -12983,11 +15721,7 @@ read_attribute_value (const struct die_reader_specs *reader,
|
| info_ptr += 8;
|
| break;
|
| case DW_FORM_ref_sig8:
|
| - /* Convert the signature to something we can record in DW_UNSND
|
| - for later lookup.
|
| - NOTE: This is NULL if the type wasn't found. */
|
| - DW_SIGNATURED_TYPE (attr) =
|
| - lookup_signatured_type (read_8_bytes (abfd, info_ptr));
|
| + DW_SIGNATURE (attr) = read_8_bytes (abfd, info_ptr);
|
| info_ptr += 8;
|
| break;
|
| case DW_FORM_ref_udata:
|
| @@ -13036,6 +15770,10 @@ read_attribute_value (const struct die_reader_specs *reader,
|
| bfd_get_filename (abfd));
|
| }
|
|
|
| + /* Super hack. */
|
| + if (cu->per_cu->is_dwz && attr_form_is_ref (attr))
|
| + attr->form = DW_FORM_GNU_ref_alt;
|
| +
|
| /* We have seen instances where the compiler tried to emit a byte
|
| size attribute of -1 which ended up being encoded as an unsigned
|
| 0xffffffff. Although 0xffffffff is technically a valid size value,
|
| @@ -13058,10 +15796,10 @@ read_attribute_value (const struct die_reader_specs *reader,
|
|
|
| /* Read an attribute described by an abbreviated attribute. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| read_attribute (const struct die_reader_specs *reader,
|
| struct attribute *attr, struct attr_abbrev *abbrev,
|
| - gdb_byte *info_ptr)
|
| + const gdb_byte *info_ptr)
|
| {
|
| attr->name = abbrev->name;
|
| return read_attribute_value (reader, attr, abbrev->form, info_ptr);
|
| @@ -13070,49 +15808,49 @@ read_attribute (const struct die_reader_specs *reader,
|
| /* Read dwarf information from a buffer. */
|
|
|
| static unsigned int
|
| -read_1_byte (bfd *abfd, gdb_byte *buf)
|
| +read_1_byte (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_8 (abfd, buf);
|
| }
|
|
|
| static int
|
| -read_1_signed_byte (bfd *abfd, gdb_byte *buf)
|
| +read_1_signed_byte (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_signed_8 (abfd, buf);
|
| }
|
|
|
| static unsigned int
|
| -read_2_bytes (bfd *abfd, gdb_byte *buf)
|
| +read_2_bytes (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_16 (abfd, buf);
|
| }
|
|
|
| static int
|
| -read_2_signed_bytes (bfd *abfd, gdb_byte *buf)
|
| +read_2_signed_bytes (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_signed_16 (abfd, buf);
|
| }
|
|
|
| static unsigned int
|
| -read_4_bytes (bfd *abfd, gdb_byte *buf)
|
| +read_4_bytes (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_32 (abfd, buf);
|
| }
|
|
|
| static int
|
| -read_4_signed_bytes (bfd *abfd, gdb_byte *buf)
|
| +read_4_signed_bytes (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_signed_32 (abfd, buf);
|
| }
|
|
|
| static ULONGEST
|
| -read_8_bytes (bfd *abfd, gdb_byte *buf)
|
| +read_8_bytes (bfd *abfd, const gdb_byte *buf)
|
| {
|
| return bfd_get_64 (abfd, buf);
|
| }
|
|
|
| static CORE_ADDR
|
| -read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu,
|
| +read_address (bfd *abfd, const gdb_byte *buf, struct dwarf2_cu *cu,
|
| unsigned int *bytes_read)
|
| {
|
| struct comp_unit_head *cu_header = &cu->header;
|
| @@ -13201,7 +15939,7 @@ read_address (bfd *abfd, gdb_byte *buf, struct dwarf2_cu *cu,
|
| ] */
|
|
|
| static LONGEST
|
| -read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read)
|
| +read_initial_length (bfd *abfd, const gdb_byte *buf, unsigned int *bytes_read)
|
| {
|
| LONGEST length = bfd_get_32 (abfd, buf);
|
|
|
| @@ -13233,7 +15971,7 @@ read_initial_length (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read)
|
| This is useful when reading non-comp-unit headers. */
|
|
|
| static LONGEST
|
| -read_checked_initial_length_and_offset (bfd *abfd, gdb_byte *buf,
|
| +read_checked_initial_length_and_offset (bfd *abfd, const gdb_byte *buf,
|
| const struct comp_unit_head *cu_header,
|
| unsigned int *bytes_read,
|
| unsigned int *offset_size)
|
| @@ -13256,7 +15994,8 @@ read_checked_initial_length_and_offset (bfd *abfd, gdb_byte *buf,
|
| given by cu_header->offset_size. */
|
|
|
| static LONGEST
|
| -read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header,
|
| +read_offset (bfd *abfd, const gdb_byte *buf,
|
| + const struct comp_unit_head *cu_header,
|
| unsigned int *bytes_read)
|
| {
|
| LONGEST offset = read_offset_1 (abfd, buf, cu_header->offset_size);
|
| @@ -13268,7 +16007,7 @@ read_offset (bfd *abfd, gdb_byte *buf, const struct comp_unit_head *cu_header,
|
| /* Read an offset from the data stream. */
|
|
|
| static LONGEST
|
| -read_offset_1 (bfd *abfd, gdb_byte *buf, unsigned int offset_size)
|
| +read_offset_1 (bfd *abfd, const gdb_byte *buf, unsigned int offset_size)
|
| {
|
| LONGEST retval = 0;
|
|
|
| @@ -13289,8 +16028,8 @@ read_offset_1 (bfd *abfd, gdb_byte *buf, unsigned int offset_size)
|
| return retval;
|
| }
|
|
|
| -static gdb_byte *
|
| -read_n_bytes (bfd *abfd, gdb_byte *buf, unsigned int size)
|
| +static const gdb_byte *
|
| +read_n_bytes (bfd *abfd, const gdb_byte *buf, unsigned int size)
|
| {
|
| /* If the size of a host char is 8 bits, we can return a pointer
|
| to the buffer, otherwise we have to copy the data to a buffer
|
| @@ -13299,8 +16038,9 @@ read_n_bytes (bfd *abfd, gdb_byte *buf, unsigned int size)
|
| return buf;
|
| }
|
|
|
| -static char *
|
| -read_direct_string (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| +static const char *
|
| +read_direct_string (bfd *abfd, const gdb_byte *buf,
|
| + unsigned int *bytes_read_ptr)
|
| {
|
| /* If the size of a host char is 8 bits, we can return a pointer
|
| to the string, otherwise we have to copy the string to a buffer
|
| @@ -13311,11 +16051,11 @@ read_direct_string (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| *bytes_read_ptr = 1;
|
| return NULL;
|
| }
|
| - *bytes_read_ptr = strlen ((char *) buf) + 1;
|
| - return (char *) buf;
|
| + *bytes_read_ptr = strlen ((const char *) buf) + 1;
|
| + return (const char *) buf;
|
| }
|
|
|
| -static char *
|
| +static const char *
|
| read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
|
| {
|
| dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str);
|
| @@ -13329,11 +16069,35 @@ read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
|
| gdb_assert (HOST_CHAR_BIT == 8);
|
| if (dwarf2_per_objfile->str.buffer[str_offset] == '\0')
|
| return NULL;
|
| - return (char *) (dwarf2_per_objfile->str.buffer + str_offset);
|
| + return (const char *) (dwarf2_per_objfile->str.buffer + str_offset);
|
| }
|
|
|
| -static char *
|
| -read_indirect_string (bfd *abfd, gdb_byte *buf,
|
| +/* Read a string at offset STR_OFFSET in the .debug_str section from
|
| + the .dwz file DWZ. Throw an error if the offset is too large. If
|
| + the string consists of a single NUL byte, return NULL; otherwise
|
| + return a pointer to the string. */
|
| +
|
| +static const char *
|
| +read_indirect_string_from_dwz (struct dwz_file *dwz, LONGEST str_offset)
|
| +{
|
| + dwarf2_read_section (dwarf2_per_objfile->objfile, &dwz->str);
|
| +
|
| + if (dwz->str.buffer == NULL)
|
| + error (_("DW_FORM_GNU_strp_alt used without .debug_str "
|
| + "section [in module %s]"),
|
| + bfd_get_filename (dwz->dwz_bfd));
|
| + if (str_offset >= dwz->str.size)
|
| + error (_("DW_FORM_GNU_strp_alt pointing outside of "
|
| + ".debug_str section [in module %s]"),
|
| + bfd_get_filename (dwz->dwz_bfd));
|
| + gdb_assert (HOST_CHAR_BIT == 8);
|
| + if (dwz->str.buffer[str_offset] == '\0')
|
| + return NULL;
|
| + return (const char *) (dwz->str.buffer + str_offset);
|
| +}
|
| +
|
| +static const char *
|
| +read_indirect_string (bfd *abfd, const gdb_byte *buf,
|
| const struct comp_unit_head *cu_header,
|
| unsigned int *bytes_read_ptr)
|
| {
|
| @@ -13343,7 +16107,8 @@ read_indirect_string (bfd *abfd, gdb_byte *buf,
|
| }
|
|
|
| static ULONGEST
|
| -read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| +read_unsigned_leb128 (bfd *abfd, const gdb_byte *buf,
|
| + unsigned int *bytes_read_ptr)
|
| {
|
| ULONGEST result;
|
| unsigned int num_read;
|
| @@ -13371,7 +16136,8 @@ read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| }
|
|
|
| static LONGEST
|
| -read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| +read_signed_leb128 (bfd *abfd, const gdb_byte *buf,
|
| + unsigned int *bytes_read_ptr)
|
| {
|
| LONGEST result;
|
| int i, shift, num_read;
|
| @@ -13413,11 +16179,11 @@ read_addr_index_1 (unsigned int addr_index, ULONGEST addr_base, int addr_size)
|
| dwarf2_read_section (objfile, &dwarf2_per_objfile->addr);
|
| if (dwarf2_per_objfile->addr.buffer == NULL)
|
| error (_("DW_FORM_addr_index used without .debug_addr section [in module %s]"),
|
| - objfile->name);
|
| + objfile_name (objfile));
|
| if (addr_base + addr_index * addr_size >= dwarf2_per_objfile->addr.size)
|
| error (_("DW_FORM_addr_index pointing outside of "
|
| ".debug_addr section [in module %s]"),
|
| - objfile->name);
|
| + objfile_name (objfile));
|
| info_ptr = (dwarf2_per_objfile->addr.buffer
|
| + addr_base + addr_index * addr_size);
|
| if (addr_size == 4)
|
| @@ -13437,7 +16203,7 @@ read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index)
|
| /* Given a pointer to an leb128 value, fetch the value from .debug_addr. */
|
|
|
| static CORE_ADDR
|
| -read_addr_index_from_leb128 (struct dwarf2_cu *cu, gdb_byte *info_ptr,
|
| +read_addr_index_from_leb128 (struct dwarf2_cu *cu, const gdb_byte *info_ptr,
|
| unsigned int *bytes_read)
|
| {
|
| bfd *abfd = cu->objfile->obfd;
|
| @@ -13459,7 +16225,7 @@ struct dwarf2_read_addr_index_data
|
|
|
| static void
|
| dwarf2_read_addr_index_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| struct die_info *comp_unit_die,
|
| int has_children,
|
| void *data)
|
| @@ -13501,8 +16267,9 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
|
|
|
| We don't need to read the entire CU(/TU).
|
| We just need the header and top level die.
|
| +
|
| IWBN to use the aging mechanism to let us lazily later discard the CU.
|
| - See however init_cutu_and_read_dies_simple. */
|
| + For now we skip this optimization. */
|
|
|
| if (cu != NULL)
|
| {
|
| @@ -13513,8 +16280,10 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
|
| {
|
| struct dwarf2_read_addr_index_data aidata;
|
|
|
| - init_cutu_and_read_dies_simple (per_cu, dwarf2_read_addr_index_reader,
|
| - &aidata);
|
| + /* Note: We can't use init_cutu_and_read_dies_simple here,
|
| + we need addr_base. */
|
| + init_cutu_and_read_dies (per_cu, NULL, 0, 0,
|
| + dwarf2_read_addr_index_reader, &aidata);
|
| addr_base = aidata.addr_base;
|
| addr_size = aidata.addr_size;
|
| }
|
| @@ -13522,44 +16291,48 @@ dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
|
| return read_addr_index_1 (addr_index, addr_base, addr_size);
|
| }
|
|
|
| -/* Given a DW_AT_str_index, fetch the string. */
|
| +/* Given a DW_FORM_GNU_str_index, fetch the string.
|
| + This is only used by the Fission support. */
|
|
|
| -static char *
|
| +static const char *
|
| read_str_index (const struct die_reader_specs *reader,
|
| struct dwarf2_cu *cu, ULONGEST str_index)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| - const char *dwo_name = objfile->name;
|
| + const char *dwo_name = objfile_name (objfile);
|
| bfd *abfd = objfile->obfd;
|
| - struct dwo_sections *sections = &reader->dwo_file->sections;
|
| - gdb_byte *info_ptr;
|
| + struct dwarf2_section_info *str_section = &reader->dwo_file->sections.str;
|
| + struct dwarf2_section_info *str_offsets_section =
|
| + &reader->dwo_file->sections.str_offsets;
|
| + const gdb_byte *info_ptr;
|
| ULONGEST str_offset;
|
| + static const char form_name[] = "DW_FORM_GNU_str_index";
|
|
|
| - dwarf2_read_section (objfile, §ions->str);
|
| - dwarf2_read_section (objfile, §ions->str_offsets);
|
| - if (sections->str.buffer == NULL)
|
| - error (_("DW_FORM_str_index used without .debug_str.dwo section"
|
| + dwarf2_read_section (objfile, str_section);
|
| + dwarf2_read_section (objfile, str_offsets_section);
|
| + if (str_section->buffer == NULL)
|
| + error (_("%s used without .debug_str.dwo section"
|
| " in CU at offset 0x%lx [in module %s]"),
|
| - (long) cu->header.offset.sect_off, dwo_name);
|
| - if (sections->str_offsets.buffer == NULL)
|
| - error (_("DW_FORM_str_index used without .debug_str_offsets.dwo section"
|
| + form_name, (long) cu->header.offset.sect_off, dwo_name);
|
| + if (str_offsets_section->buffer == NULL)
|
| + error (_("%s used without .debug_str_offsets.dwo section"
|
| " in CU at offset 0x%lx [in module %s]"),
|
| - (long) cu->header.offset.sect_off, dwo_name);
|
| - if (str_index * cu->header.offset_size >= sections->str_offsets.size)
|
| - error (_("DW_FORM_str_index pointing outside of .debug_str_offsets.dwo"
|
| + form_name, (long) cu->header.offset.sect_off, dwo_name);
|
| + if (str_index * cu->header.offset_size >= str_offsets_section->size)
|
| + error (_("%s pointing outside of .debug_str_offsets.dwo"
|
| " section in CU at offset 0x%lx [in module %s]"),
|
| - (long) cu->header.offset.sect_off, dwo_name);
|
| - info_ptr = (sections->str_offsets.buffer
|
| + form_name, (long) cu->header.offset.sect_off, dwo_name);
|
| + info_ptr = (str_offsets_section->buffer
|
| + str_index * cu->header.offset_size);
|
| if (cu->header.offset_size == 4)
|
| str_offset = bfd_get_32 (abfd, info_ptr);
|
| else
|
| str_offset = bfd_get_64 (abfd, info_ptr);
|
| - if (str_offset >= sections->str.size)
|
| - error (_("Offset from DW_FORM_str_index pointing outside of"
|
| + if (str_offset >= str_section->size)
|
| + error (_("Offset from %s pointing outside of"
|
| " .debug_str.dwo section in CU at offset 0x%lx [in module %s]"),
|
| - (long) cu->header.offset.sect_off, dwo_name);
|
| - return (char *) (sections->str.buffer + str_offset);
|
| + form_name, (long) cu->header.offset.sect_off, dwo_name);
|
| + return (const char *) (str_section->buffer + str_offset);
|
| }
|
|
|
| /* Return the length of an LEB128 number in BUF. */
|
| @@ -13586,6 +16359,7 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
|
| case DW_LANG_C89:
|
| case DW_LANG_C99:
|
| case DW_LANG_C:
|
| + case DW_LANG_UPC:
|
| cu->language = language_c;
|
| break;
|
| case DW_LANG_C_plus_plus:
|
| @@ -13748,7 +16522,7 @@ free_line_header (struct line_header *lh)
|
| /* Add an entry to LH's include directory table. */
|
|
|
| static void
|
| -add_include_dir (struct line_header *lh, char *include_dir)
|
| +add_include_dir (struct line_header *lh, const char *include_dir)
|
| {
|
| /* Grow the array if necessary. */
|
| if (lh->include_dirs_size == 0)
|
| @@ -13772,7 +16546,7 @@ add_include_dir (struct line_header *lh, char *include_dir)
|
|
|
| static void
|
| add_file_name (struct line_header *lh,
|
| - char *name,
|
| + const char *name,
|
| unsigned int dir_index,
|
| unsigned int mod_time,
|
| unsigned int length)
|
| @@ -13803,6 +16577,30 @@ add_file_name (struct line_header *lh,
|
| fe->symtab = NULL;
|
| }
|
|
|
| +/* A convenience function to find the proper .debug_line section for a
|
| + CU. */
|
| +
|
| +static struct dwarf2_section_info *
|
| +get_debug_line_section (struct dwarf2_cu *cu)
|
| +{
|
| + struct dwarf2_section_info *section;
|
| +
|
| + /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
|
| + DWO file. */
|
| + if (cu->dwo_unit && cu->per_cu->is_debug_types)
|
| + section = &cu->dwo_unit->dwo_file->sections.line;
|
| + else if (cu->per_cu->is_dwz)
|
| + {
|
| + struct dwz_file *dwz = dwarf2_get_dwz_file ();
|
| +
|
| + section = &dwz->line;
|
| + }
|
| + else
|
| + section = &dwarf2_per_objfile->line;
|
| +
|
| + return section;
|
| +}
|
| +
|
| /* Read the statement program header starting at OFFSET in
|
| .debug_line, or .debug_line.dwo. Return a pointer
|
| to a struct line_header, allocated using xmalloc.
|
| @@ -13816,20 +16614,14 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
|
| {
|
| struct cleanup *back_to;
|
| struct line_header *lh;
|
| - gdb_byte *line_ptr;
|
| + const gdb_byte *line_ptr;
|
| unsigned int bytes_read, offset_size;
|
| int i;
|
| - char *cur_dir, *cur_file;
|
| + const char *cur_dir, *cur_file;
|
| struct dwarf2_section_info *section;
|
| bfd *abfd;
|
|
|
| - /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
|
| - DWO file. */
|
| - if (cu->dwo_unit && cu->per_cu->is_debug_types)
|
| - section = &cu->dwo_unit->dwo_file->sections.line;
|
| - else
|
| - section = &dwarf2_per_objfile->line;
|
| -
|
| + section = get_debug_line_section (cu);
|
| dwarf2_read_section (dwarf2_per_objfile->objfile, section);
|
| if (section->buffer == NULL)
|
| {
|
| @@ -13842,7 +16634,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
|
|
|
| /* We can't do this until we know the section is non-empty.
|
| Only then do we know we have such a section. */
|
| - abfd = section->asection->owner;
|
| + abfd = get_section_bfd_owner (section);
|
|
|
| /* Make sure that at least there's room for the total_length field.
|
| That could be 12 bytes long, but we're just going to fudge that. */
|
| @@ -13867,6 +16659,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
|
| if (line_ptr + lh->total_length > (section->buffer + section->size))
|
| {
|
| dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
| + do_cleanups (back_to);
|
| return 0;
|
| }
|
| lh->statement_program_end = line_ptr + lh->total_length;
|
| @@ -13950,17 +16743,19 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
|
| in line header LH of PST.
|
| COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
|
| If space for the result is malloc'd, it will be freed by a cleanup.
|
| - Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename. */
|
| + Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.
|
|
|
| -static char *
|
| + The function creates dangling cleanup registration. */
|
| +
|
| +static const char *
|
| psymtab_include_file_name (const struct line_header *lh, int file_index,
|
| const struct partial_symtab *pst,
|
| const char *comp_dir)
|
| {
|
| const struct file_entry fe = lh->file_names [file_index];
|
| - char *include_name = fe.name;
|
| - char *include_name_to_compare = include_name;
|
| - char *dir_name = NULL;
|
| + const char *include_name = fe.name;
|
| + const char *include_name_to_compare = include_name;
|
| + const char *dir_name = NULL;
|
| const char *pst_filename;
|
| char *copied_name = NULL;
|
| int file_is_pst;
|
| @@ -13992,15 +16787,20 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
|
|
|
| if (dir_name != NULL)
|
| {
|
| - include_name = concat (dir_name, SLASH_STRING,
|
| - include_name, (char *)NULL);
|
| + char *tem = concat (dir_name, SLASH_STRING,
|
| + include_name, (char *)NULL);
|
| +
|
| + make_cleanup (xfree, tem);
|
| + include_name = tem;
|
| include_name_to_compare = include_name;
|
| - make_cleanup (xfree, include_name);
|
| }
|
| if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL)
|
| {
|
| - include_name_to_compare = concat (comp_dir, SLASH_STRING,
|
| - include_name, (char *)NULL);
|
| + char *tem = concat (comp_dir, SLASH_STRING,
|
| + include_name, (char *)NULL);
|
| +
|
| + make_cleanup (xfree, tem);
|
| + include_name_to_compare = tem;
|
| }
|
| }
|
|
|
| @@ -14014,8 +16814,6 @@ psymtab_include_file_name (const struct line_header *lh, int file_index,
|
|
|
| file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
|
|
|
| - if (include_name_to_compare != include_name)
|
| - xfree (include_name_to_compare);
|
| if (copied_name != NULL)
|
| xfree (copied_name);
|
|
|
| @@ -14039,8 +16837,8 @@ static void
|
| dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| struct dwarf2_cu *cu, struct partial_symtab *pst)
|
| {
|
| - gdb_byte *line_ptr, *extended_end;
|
| - gdb_byte *line_end;
|
| + const gdb_byte *line_ptr, *extended_end;
|
| + const gdb_byte *line_end;
|
| unsigned int bytes_read, extended_len;
|
| unsigned char op_code, extended_op, adj_opcode;
|
| CORE_ADDR baseaddr;
|
| @@ -14078,7 +16876,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| directory and file name numbers in the statement program
|
| are 1-based. */
|
| struct file_entry *fe = &lh->file_names[file - 1];
|
| - char *dir = NULL;
|
| + const char *dir = NULL;
|
|
|
| if (fe->dir_index)
|
| dir = lh->include_dirs[fe->dir_index - 1];
|
| @@ -14154,12 +16952,12 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| GCd by the linker. Ignore it. PR gdb/12528 */
|
|
|
| long line_offset
|
| - = line_ptr - dwarf2_per_objfile->line.buffer;
|
| + = line_ptr - get_debug_line_section (cu)->buffer;
|
|
|
| complaint (&symfile_complaints,
|
| _(".debug_line address at offset 0x%lx is 0 "
|
| "[in module %s]"),
|
| - line_offset, objfile->name);
|
| + line_offset, objfile_name (objfile));
|
| p_record_line = noop_record_line;
|
| }
|
|
|
| @@ -14169,7 +16967,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| break;
|
| case DW_LNE_define_file:
|
| {
|
| - char *cur_file;
|
| + const char *cur_file;
|
| unsigned int dir_index, mod_time, length;
|
|
|
| cur_file = read_direct_string (abfd, line_ptr,
|
| @@ -14251,7 +17049,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| 0-based, but the directory and file name numbers in
|
| the statement program are 1-based. */
|
| struct file_entry *fe;
|
| - char *dir = NULL;
|
| + const char *dir = NULL;
|
|
|
| file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
|
| line_ptr += bytes_read;
|
| @@ -14371,7 +17169,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
|
| for (file_index = 0; file_index < lh->num_file_names; file_index++)
|
| if (lh->file_names[file_index].included_p == 1)
|
| {
|
| - char *include_name =
|
| + const char *include_name =
|
| psymtab_include_file_name (lh, file_index, pst, comp_dir);
|
| if (include_name != NULL)
|
| dwarf2_create_include_psymtab (include_name, pst, objfile);
|
| @@ -14386,7 +17184,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
|
|
|
| for (i = 0; i < lh->num_file_names; i++)
|
| {
|
| - char *dir = NULL;
|
| + const char *dir = NULL;
|
| struct file_entry *fe;
|
|
|
| fe = &lh->file_names[i];
|
| @@ -14433,10 +17231,10 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
|
| subfile's name. */
|
|
|
| static void
|
| -dwarf2_start_subfile (char *filename, const char *dirname,
|
| +dwarf2_start_subfile (const char *filename, const char *dirname,
|
| const char *comp_dir)
|
| {
|
| - char *fullname;
|
| + char *copy = NULL;
|
|
|
| /* While reading the DIEs, we call start_symtab(DW_AT_name, DW_AT_comp_dir).
|
| `start_symtab' will always pass the contents of DW_AT_comp_dir as
|
| @@ -14449,14 +17247,15 @@ dwarf2_start_subfile (char *filename, const char *dirname,
|
| `else' branch below isn't an issue. */
|
|
|
| if (!IS_ABSOLUTE_PATH (filename) && dirname != NULL)
|
| - fullname = concat (dirname, SLASH_STRING, filename, (char *)NULL);
|
| - else
|
| - fullname = filename;
|
| + {
|
| + copy = concat (dirname, SLASH_STRING, filename, (char *)NULL);
|
| + filename = copy;
|
| + }
|
|
|
| - start_subfile (fullname, comp_dir);
|
| + start_subfile (filename, comp_dir);
|
|
|
| - if (fullname != filename)
|
| - xfree (fullname);
|
| + if (copy != NULL)
|
| + xfree (copy);
|
| }
|
|
|
| /* Start a symtab for DWARF.
|
| @@ -14464,7 +17263,7 @@ dwarf2_start_subfile (char *filename, const char *dirname,
|
|
|
| static void
|
| dwarf2_start_symtab (struct dwarf2_cu *cu,
|
| - char *name, char *comp_dir, CORE_ADDR low_pc)
|
| + const char *name, const char *comp_dir, CORE_ADDR low_pc)
|
| {
|
| start_symtab (name, comp_dir, low_pc);
|
| record_debugformat ("DWARF 2");
|
| @@ -14473,7 +17272,7 @@ dwarf2_start_symtab (struct dwarf2_cu *cu,
|
| /* We assume that we're processing GCC output. */
|
| processing_gcc_compilation = 2;
|
|
|
| - processing_has_namespace_info = 0;
|
| + cu->processing_has_namespace_info = 0;
|
| }
|
|
|
| static void
|
| @@ -14497,7 +17296,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
|
| variable has been optimized away. */
|
| if (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)
|
| {
|
| - SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
|
| return;
|
| }
|
|
|
| @@ -14521,7 +17320,7 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
|
| else
|
| SYMBOL_VALUE_ADDRESS (sym) =
|
| read_addr_index_from_leb128 (cu, DW_BLOCK (attr)->data + 1, &dummy);
|
| - SYMBOL_CLASS (sym) = LOC_STATIC;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_STATIC;
|
| fixup_symbol_section (sym, objfile);
|
| SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
|
| SYMBOL_SECTION (sym));
|
| @@ -14535,10 +17334,9 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
|
| not be worthwhile. I'm assuming that it isn't unless performance
|
| or memory numbers show me otherwise. */
|
|
|
| - dwarf2_symbol_mark_computed (attr, sym, cu);
|
| - SYMBOL_CLASS (sym) = LOC_COMPUTED;
|
| + dwarf2_symbol_mark_computed (attr, sym, cu, 0);
|
|
|
| - if (SYMBOL_COMPUTED_OPS (sym) == &dwarf2_loclist_funcs)
|
| + if (SYMBOL_COMPUTED_OPS (sym)->location_has_loclist)
|
| cu->has_loclist = 1;
|
| }
|
|
|
| @@ -14556,7 +17354,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| struct symbol *sym = NULL;
|
| - char *name;
|
| + const char *name;
|
| struct attribute *attr = NULL;
|
| struct attribute *attr2 = NULL;
|
| CORE_ADDR baseaddr;
|
| @@ -14575,11 +17373,11 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| if (space)
|
| sym = space;
|
| else
|
| - sym = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct symbol);
|
| + sym = allocate_symbol (objfile);
|
| OBJSTAT (objfile, n_syms++);
|
|
|
| /* Cache this symbol's name and the name's demangled form (if any). */
|
| - SYMBOL_SET_LANGUAGE (sym, cu->language);
|
| + SYMBOL_SET_LANGUAGE (sym, cu->language, &objfile->objfile_obstack);
|
| linkagename = dwarf2_physname (name, die, cu);
|
| SYMBOL_SET_NAMES (sym, linkagename, strlen (linkagename), 0, objfile);
|
|
|
| @@ -14588,13 +17386,13 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| if (cu->language == language_fortran
|
| && symbol_get_demangled_name (&(sym->ginfo)) == NULL)
|
| symbol_set_demangled_name (&(sym->ginfo),
|
| - (char *) dwarf2_full_name (name, die, cu),
|
| + dwarf2_full_name (name, die, cu),
|
| NULL);
|
|
|
| /* Default assumptions.
|
| Use the passed type or decode it from the die. */
|
| SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
|
| - SYMBOL_CLASS (sym) = LOC_OPTIMIZED_OUT;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_OPTIMIZED_OUT;
|
| if (type != NULL)
|
| SYMBOL_TYPE (sym) = type;
|
| else
|
| @@ -14637,13 +17435,13 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| }
|
| SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_core_addr;
|
| SYMBOL_DOMAIN (sym) = LABEL_DOMAIN;
|
| - SYMBOL_CLASS (sym) = LOC_LABEL;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
|
| add_symbol_to_list (sym, cu->list_in_scope);
|
| break;
|
| case DW_TAG_subprogram:
|
| /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
|
| finish_block. */
|
| - SYMBOL_CLASS (sym) = LOC_BLOCK;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
|
| attr2 = dwarf2_attr (die, DW_AT_external, cu);
|
| if ((attr2 && (DW_UNSND (attr2) != 0))
|
| || cu->language == language_ada)
|
| @@ -14664,7 +17462,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| case DW_TAG_inlined_subroutine:
|
| /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
|
| finish_block. */
|
| - SYMBOL_CLASS (sym) = LOC_BLOCK;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
|
| SYMBOL_INLINED (sym) = 1;
|
| list_to_add = cu->list_in_scope;
|
| break;
|
| @@ -14709,6 +17507,13 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| {
|
| var_decode_location (attr, sym, cu);
|
| attr2 = dwarf2_attr (die, DW_AT_external, cu);
|
| +
|
| + /* Fortran explicitly imports any global symbols to the local
|
| + scope by DW_TAG_common_block. */
|
| + if (cu->language == language_fortran && die->parent
|
| + && die->parent->tag == DW_TAG_common_block)
|
| + attr2 = NULL;
|
| +
|
| if (SYMBOL_CLASS (sym) == LOC_STATIC
|
| && SYMBOL_VALUE_ADDRESS (sym) == 0
|
| && !dwarf2_per_objfile->has_section_at_zero)
|
| @@ -14732,7 +17537,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| && die->parent->tag == DW_TAG_module
|
| && cu->producer
|
| && strncmp (cu->producer, "GNU Fortran ", 12) == 0)
|
| - SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
|
|
|
| /* A variable with DW_AT_external is never static,
|
| but it may be block-scoped. */
|
| @@ -14751,15 +17556,26 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| the minimal symbol table whenever the variable is
|
| referenced. */
|
| attr2 = dwarf2_attr (die, DW_AT_external, cu);
|
| - if (attr2 && (DW_UNSND (attr2) != 0)
|
| - && dwarf2_attr (die, DW_AT_type, cu) != NULL)
|
| +
|
| + /* Fortran explicitly imports any global symbols to the local
|
| + scope by DW_TAG_common_block. */
|
| + if (cu->language == language_fortran && die->parent
|
| + && die->parent->tag == DW_TAG_common_block)
|
| + {
|
| + /* SYMBOL_CLASS doesn't matter here because
|
| + read_common_block is going to reset it. */
|
| + if (!suppress_add)
|
| + list_to_add = cu->list_in_scope;
|
| + }
|
| + else if (attr2 && (DW_UNSND (attr2) != 0)
|
| + && dwarf2_attr (die, DW_AT_type, cu) != NULL)
|
| {
|
| /* A variable with DW_AT_external is never static, but it
|
| may be block-scoped. */
|
| list_to_add = (cu->list_in_scope == &file_symbols
|
| ? &global_symbols : cu->list_in_scope);
|
|
|
| - SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED;
|
| }
|
| else if (!die_is_declaration (die, cu))
|
| {
|
| @@ -14806,7 +17622,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| case DW_TAG_union_type:
|
| case DW_TAG_set_type:
|
| case DW_TAG_enumeration_type:
|
| - SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
|
| SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN;
|
|
|
| {
|
| @@ -14843,13 +17659,13 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| }
|
| break;
|
| case DW_TAG_typedef:
|
| - SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
|
| SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
|
| list_to_add = cu->list_in_scope;
|
| break;
|
| case DW_TAG_base_type:
|
| case DW_TAG_subrange_type:
|
| - SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
|
| SYMBOL_DOMAIN (sym) = VAR_DOMAIN;
|
| list_to_add = cu->list_in_scope;
|
| break;
|
| @@ -14869,10 +17685,16 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| ? &global_symbols : cu->list_in_scope);
|
| }
|
| break;
|
| + case DW_TAG_imported_declaration:
|
| case DW_TAG_namespace:
|
| - SYMBOL_CLASS (sym) = LOC_TYPEDEF;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_TYPEDEF;
|
| list_to_add = &global_symbols;
|
| break;
|
| + case DW_TAG_common_block:
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_COMMON_BLOCK;
|
| + SYMBOL_DOMAIN (sym) = COMMON_BLOCK_DOMAIN;
|
| + add_symbol_to_list (sym, cu->list_in_scope);
|
| + break;
|
| default:
|
| /* Not a tag we recognize. Hopefully we aren't processing
|
| trash data, but since we must specifically ignore things
|
| @@ -14895,7 +17717,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
|
|
| /* For the benefit of old versions of GCC, check for anonymous
|
| namespaces based on the demangled name. */
|
| - if (!processing_has_namespace_info
|
| + if (!cu->processing_has_namespace_info
|
| && cu->language == language_cplus)
|
| cp_scan_for_anonymous_namespaces (sym, objfile);
|
| }
|
| @@ -14919,8 +17741,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
|
| because that is the interpretation long in use by GCC. */
|
|
|
| static gdb_byte *
|
| -dwarf2_const_value_data (struct attribute *attr, struct type *type,
|
| - const char *name, struct obstack *obstack,
|
| +dwarf2_const_value_data (const struct attribute *attr, struct obstack *obstack,
|
| struct dwarf2_cu *cu, LONGEST *value, int bits)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| @@ -14952,10 +17773,10 @@ dwarf2_const_value_data (struct attribute *attr, struct type *type,
|
| expression. */
|
|
|
| static void
|
| -dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| +dwarf2_const_value_attr (const struct attribute *attr, struct type *type,
|
| const char *name, struct obstack *obstack,
|
| struct dwarf2_cu *cu,
|
| - LONGEST *value, gdb_byte **bytes,
|
| + LONGEST *value, const gdb_byte **bytes,
|
| struct dwarf2_locexpr_baton **baton)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| @@ -14982,13 +17803,12 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| /* Symbols of this form are reasonably rare, so we just
|
| piggyback on the existing location code rather than writing
|
| a new implementation of symbol_computed_ops. */
|
| - *baton = obstack_alloc (&objfile->objfile_obstack,
|
| - sizeof (struct dwarf2_locexpr_baton));
|
| + *baton = obstack_alloc (obstack, sizeof (struct dwarf2_locexpr_baton));
|
| (*baton)->per_cu = cu->per_cu;
|
| gdb_assert ((*baton)->per_cu);
|
|
|
| (*baton)->size = 2 + cu_header->addr_size;
|
| - data = obstack_alloc (&objfile->objfile_obstack, (*baton)->size);
|
| + data = obstack_alloc (obstack, (*baton)->size);
|
| (*baton)->data = data;
|
|
|
| data[0] = DW_OP_addr;
|
| @@ -15000,9 +17820,10 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| case DW_FORM_string:
|
| case DW_FORM_strp:
|
| case DW_FORM_GNU_str_index:
|
| + case DW_FORM_GNU_strp_alt:
|
| /* DW_STRING is already allocated on the objfile obstack, point
|
| directly to it. */
|
| - *bytes = (gdb_byte *) DW_STRING (attr);
|
| + *bytes = (const gdb_byte *) DW_STRING (attr);
|
| break;
|
| case DW_FORM_block1:
|
| case DW_FORM_block2:
|
| @@ -15022,20 +17843,16 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| converted to host endianness, so we just need to sign- or
|
| zero-extend it as appropriate. */
|
| case DW_FORM_data1:
|
| - *bytes = dwarf2_const_value_data (attr, type, name,
|
| - obstack, cu, value, 8);
|
| + *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 8);
|
| break;
|
| case DW_FORM_data2:
|
| - *bytes = dwarf2_const_value_data (attr, type, name,
|
| - obstack, cu, value, 16);
|
| + *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 16);
|
| break;
|
| case DW_FORM_data4:
|
| - *bytes = dwarf2_const_value_data (attr, type, name,
|
| - obstack, cu, value, 32);
|
| + *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 32);
|
| break;
|
| case DW_FORM_data8:
|
| - *bytes = dwarf2_const_value_data (attr, type, name,
|
| - obstack, cu, value, 64);
|
| + *bytes = dwarf2_const_value_data (attr, obstack, cu, value, 64);
|
| break;
|
|
|
| case DW_FORM_sdata:
|
| @@ -15059,13 +17876,13 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| /* Copy constant value from an attribute to a symbol. */
|
|
|
| static void
|
| -dwarf2_const_value (struct attribute *attr, struct symbol *sym,
|
| +dwarf2_const_value (const struct attribute *attr, struct symbol *sym,
|
| struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| struct comp_unit_head *cu_header = &cu->header;
|
| LONGEST value;
|
| - gdb_byte *bytes;
|
| + const gdb_byte *bytes;
|
| struct dwarf2_locexpr_baton *baton;
|
|
|
| dwarf2_const_value_attr (attr, SYMBOL_TYPE (sym),
|
| @@ -15075,19 +17892,18 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym,
|
|
|
| if (baton != NULL)
|
| {
|
| - SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
|
| SYMBOL_LOCATION_BATON (sym) = baton;
|
| - SYMBOL_CLASS (sym) = LOC_COMPUTED;
|
| + SYMBOL_ACLASS_INDEX (sym) = dwarf2_locexpr_index;
|
| }
|
| else if (bytes != NULL)
|
| {
|
| SYMBOL_VALUE_BYTES (sym) = bytes;
|
| - SYMBOL_CLASS (sym) = LOC_CONST_BYTES;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_CONST_BYTES;
|
| }
|
| else
|
| {
|
| SYMBOL_VALUE (sym) = value;
|
| - SYMBOL_CLASS (sym) = LOC_CONST;
|
| + SYMBOL_ACLASS_INDEX (sym) = LOC_CONST;
|
| }
|
| }
|
|
|
| @@ -15169,24 +17985,57 @@ die_containing_type (struct die_info *die, struct dwarf2_cu *cu)
|
| type_attr = dwarf2_attr (die, DW_AT_containing_type, cu);
|
| if (!type_attr)
|
| error (_("Dwarf Error: Problem turning containing type into gdb type "
|
| - "[in module %s]"), cu->objfile->name);
|
| + "[in module %s]"), objfile_name (cu->objfile));
|
|
|
| return lookup_die_type (die, type_attr, cu);
|
| }
|
|
|
| +/* Return an error marker type to use for the ill formed type in DIE/CU. */
|
| +
|
| +static struct type *
|
| +build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + char *message, *saved;
|
| +
|
| + message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
|
| + objfile_name (objfile),
|
| + cu->header.offset.sect_off,
|
| + die->offset.sect_off);
|
| + saved = obstack_copy0 (&objfile->objfile_obstack,
|
| + message, strlen (message));
|
| + xfree (message);
|
| +
|
| + return init_type (TYPE_CODE_ERROR, 0, 0, saved, objfile);
|
| +}
|
| +
|
| /* Look up the type of DIE in CU using its type attribute ATTR.
|
| + ATTR must be one of: DW_AT_type, DW_AT_GNAT_descriptive_type,
|
| + DW_AT_containing_type.
|
| If there is no type substitute an error marker. */
|
|
|
| static struct type *
|
| -lookup_die_type (struct die_info *die, struct attribute *attr,
|
| +lookup_die_type (struct die_info *die, const struct attribute *attr,
|
| struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| struct type *this_type;
|
|
|
| + gdb_assert (attr->name == DW_AT_type
|
| + || attr->name == DW_AT_GNAT_descriptive_type
|
| + || attr->name == DW_AT_containing_type);
|
| +
|
| /* First see if we have it cached. */
|
|
|
| - if (is_ref_attr (attr))
|
| + if (attr->form == DW_FORM_GNU_ref_alt)
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu;
|
| + sect_offset offset = dwarf2_get_ref_die_offset (attr);
|
| +
|
| + per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile);
|
| + this_type = get_die_type_at_offset (offset, per_cu);
|
| + }
|
| + else if (attr_form_is_ref (attr))
|
| {
|
| sect_offset offset = dwarf2_get_ref_die_offset (attr);
|
|
|
| @@ -15194,66 +18043,41 @@ lookup_die_type (struct die_info *die, struct attribute *attr,
|
| }
|
| else if (attr->form == DW_FORM_ref_sig8)
|
| {
|
| - struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
|
| + ULONGEST signature = DW_SIGNATURE (attr);
|
|
|
| - /* sig_type will be NULL if the signatured type is missing from
|
| - the debug info. */
|
| - if (sig_type == NULL)
|
| - error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
|
| - "at 0x%x [in module %s]"),
|
| - die->offset.sect_off, objfile->name);
|
| -
|
| - gdb_assert (sig_type->per_cu.is_debug_types);
|
| - /* If we haven't filled in type_offset_in_section yet, then we
|
| - haven't read the type in yet. */
|
| - this_type = NULL;
|
| - if (sig_type->type_offset_in_section.sect_off != 0)
|
| - {
|
| - this_type =
|
| - get_die_type_at_offset (sig_type->type_offset_in_section,
|
| - &sig_type->per_cu);
|
| - }
|
| + return get_signatured_type (die, signature, cu);
|
| }
|
| else
|
| {
|
| - dump_die_for_error (die);
|
| - error (_("Dwarf Error: Bad type attribute %s [in module %s]"),
|
| - dwarf_attr_name (attr->name), objfile->name);
|
| + complaint (&symfile_complaints,
|
| + _("Dwarf Error: Bad type attribute %s in DIE"
|
| + " at 0x%x [in module %s]"),
|
| + dwarf_attr_name (attr->name), die->offset.sect_off,
|
| + objfile_name (objfile));
|
| + return build_error_marker_type (cu, die);
|
| }
|
|
|
| /* If not cached we need to read it in. */
|
|
|
| if (this_type == NULL)
|
| {
|
| - struct die_info *type_die;
|
| + struct die_info *type_die = NULL;
|
| struct dwarf2_cu *type_cu = cu;
|
|
|
| - type_die = follow_die_ref_or_sig (die, attr, &type_cu);
|
| - /* If we found the type now, it's probably because the type came
|
| + if (attr_form_is_ref (attr))
|
| + type_die = follow_die_ref (die, attr, &type_cu);
|
| + if (type_die == NULL)
|
| + return build_error_marker_type (cu, die);
|
| + /* If we find the type now, it's probably because the type came
|
| from an inter-CU reference and the type's CU got expanded before
|
| ours. */
|
| - this_type = get_die_type (type_die, type_cu);
|
| - if (this_type == NULL)
|
| - this_type = read_type_die_1 (type_die, type_cu);
|
| + this_type = read_type_die (type_die, type_cu);
|
| }
|
|
|
| /* If we still don't have a type use an error marker. */
|
|
|
| if (this_type == NULL)
|
| - {
|
| - char *message, *saved;
|
| -
|
| - /* read_type_die already issued a complaint. */
|
| - message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
|
| - objfile->name,
|
| - cu->header.offset.sect_off,
|
| - die->offset.sect_off);
|
| - saved = obstack_copy0 (&objfile->objfile_obstack,
|
| - message, strlen (message));
|
| - xfree (message);
|
| -
|
| - this_type = init_type (TYPE_CODE_ERROR, 0, 0, saved, objfile);
|
| - }
|
| + return build_error_marker_type (cu, die);
|
|
|
| return this_type;
|
| }
|
| @@ -15261,7 +18085,7 @@ lookup_die_type (struct die_info *die, struct attribute *attr,
|
| /* Return the type in DIE, CU.
|
| Returns NULL for invalid types.
|
|
|
| - This first does a lookup in the appropriate type_hash table,
|
| + This first does a lookup in die_type_hash,
|
| and only reads the die in if necessary.
|
|
|
| NOTE: This can be called when reading in partial or full symbols. */
|
| @@ -15323,6 +18147,9 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
|
| case DW_TAG_volatile_type:
|
| this_type = read_tag_volatile_type (die, cu);
|
| break;
|
| + case DW_TAG_restrict_type:
|
| + this_type = read_tag_restrict_type (die, cu);
|
| + break;
|
| case DW_TAG_string_type:
|
| this_type = read_tag_string_type (die, cu);
|
| break;
|
| @@ -15397,7 +18224,7 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| if (actual_name != NULL)
|
| {
|
| - char *die_name = dwarf2_name (die, cu);
|
| + const char *die_name = dwarf2_name (die, cu);
|
|
|
| if (die_name != NULL
|
| && strcmp (die_name, actual_name) != 0)
|
| @@ -15412,9 +18239,9 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu)
|
| && actual_name[actual_name_len
|
| - die_name_len - 1] == ':')
|
| name =
|
| - obsavestring (actual_name,
|
| - actual_name_len - die_name_len - 2,
|
| - &cu->objfile->objfile_obstack);
|
| + obstack_copy0 (&cu->objfile->objfile_obstack,
|
| + actual_name,
|
| + actual_name_len - die_name_len - 2);
|
| }
|
| }
|
| xfree (actual_name);
|
| @@ -15458,8 +18285,8 @@ anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
|
| if (base == NULL || base == DW_STRING (attr) || base[-1] != ':')
|
| return "";
|
|
|
| - return obsavestring (DW_STRING (attr), &base[-1] - DW_STRING (attr),
|
| - &cu->objfile->objfile_obstack);
|
| + return obstack_copy0 (&cu->objfile->objfile_obstack,
|
| + DW_STRING (attr), &base[-1] - DW_STRING (attr));
|
| }
|
|
|
| /* Return the name of the namespace/class that DIE is defined within,
|
| @@ -15677,8 +18504,8 @@ sibling_die (struct die_info *die)
|
|
|
| /* Get name of a die, return NULL if not found. */
|
|
|
| -static char *
|
| -dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
|
| +static const char *
|
| +dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
|
| struct obstack *obstack)
|
| {
|
| if (name && cu->language == language_cplus)
|
| @@ -15688,8 +18515,7 @@ dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
|
| if (canon_name != NULL)
|
| {
|
| if (strcmp (canon_name, name) != 0)
|
| - name = obsavestring (canon_name, strlen (canon_name),
|
| - obstack);
|
| + name = obstack_copy0 (obstack, canon_name, strlen (canon_name));
|
| xfree (canon_name);
|
| }
|
| }
|
| @@ -15699,7 +18525,7 @@ dwarf2_canonicalize_name (char *name, struct dwarf2_cu *cu,
|
|
|
| /* Get name of a die, return NULL if not found. */
|
|
|
| -static char *
|
| +static const char *
|
| dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| struct attribute *attr;
|
| @@ -15783,15 +18609,15 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
|
| /* Avoid demangling DW_STRING (attr) the second time on a second
|
| call for the same DIE. */
|
| if (!DW_STRING_IS_CANONICAL (attr))
|
| - demangled = cplus_demangle (DW_STRING (attr), DMGL_TYPES);
|
| + demangled = gdb_demangle (DW_STRING (attr), DMGL_TYPES);
|
|
|
| if (demangled)
|
| {
|
| char *base;
|
|
|
| /* FIXME: we already did this for the partial symbol... */
|
| - DW_STRING (attr) = obsavestring (demangled, strlen (demangled),
|
| - &cu->objfile->objfile_obstack);
|
| + DW_STRING (attr) = obstack_copy0 (&cu->objfile->objfile_obstack,
|
| + demangled, strlen (demangled));
|
| DW_STRING_IS_CANONICAL (attr) = 1;
|
| xfree (demangled);
|
|
|
| @@ -15948,17 +18774,21 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
| case DW_FORM_block4:
|
| case DW_FORM_block:
|
| case DW_FORM_block1:
|
| - fprintf_unfiltered (f, "block: size %d",
|
| - DW_BLOCK (&die->attrs[i])->size);
|
| + fprintf_unfiltered (f, "block: size %s",
|
| + pulongest (DW_BLOCK (&die->attrs[i])->size));
|
| break;
|
| case DW_FORM_exprloc:
|
| - fprintf_unfiltered (f, "expression: size %u",
|
| - DW_BLOCK (&die->attrs[i])->size);
|
| + fprintf_unfiltered (f, "expression: size %s",
|
| + pulongest (DW_BLOCK (&die->attrs[i])->size));
|
| break;
|
| case DW_FORM_ref_addr:
|
| fprintf_unfiltered (f, "ref address: ");
|
| fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
|
| break;
|
| + case DW_FORM_GNU_ref_alt:
|
| + fprintf_unfiltered (f, "alt ref address: ");
|
| + fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
|
| + break;
|
| case DW_FORM_ref1:
|
| case DW_FORM_ref2:
|
| case DW_FORM_ref4:
|
| @@ -15981,15 +18811,13 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
| pulongest (DW_UNSND (&die->attrs[i])));
|
| break;
|
| case DW_FORM_ref_sig8:
|
| - if (DW_SIGNATURED_TYPE (&die->attrs[i]) != NULL)
|
| - fprintf_unfiltered (f, "signatured type, offset: 0x%x",
|
| - DW_SIGNATURED_TYPE (&die->attrs[i])->per_cu.offset.sect_off);
|
| - else
|
| - fprintf_unfiltered (f, "signatured type, offset: unknown");
|
| + fprintf_unfiltered (f, "signature: %s",
|
| + hex_string (DW_SIGNATURE (&die->attrs[i])));
|
| break;
|
| case DW_FORM_string:
|
| case DW_FORM_strp:
|
| case DW_FORM_GNU_str_index:
|
| + case DW_FORM_GNU_strp_alt:
|
| fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
|
| DW_STRING (&die->attrs[i])
|
| ? DW_STRING (&die->attrs[i]) : "",
|
| @@ -16079,35 +18907,15 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
|
| *slot = die;
|
| }
|
|
|
| -/* DW_ADDR is always stored already as sect_offset; despite for the forms
|
| - besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */
|
| -
|
| -static int
|
| -is_ref_attr (struct attribute *attr)
|
| -{
|
| - switch (attr->form)
|
| - {
|
| - case DW_FORM_ref_addr:
|
| - case DW_FORM_ref1:
|
| - case DW_FORM_ref2:
|
| - case DW_FORM_ref4:
|
| - case DW_FORM_ref8:
|
| - case DW_FORM_ref_udata:
|
| - return 1;
|
| - default:
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| /* Return DIE offset of ATTR. Return 0 with complaint if ATTR is not of the
|
| required kind. */
|
|
|
| static sect_offset
|
| -dwarf2_get_ref_die_offset (struct attribute *attr)
|
| +dwarf2_get_ref_die_offset (const struct attribute *attr)
|
| {
|
| sect_offset retval = { DW_UNSND (attr) };
|
|
|
| - if (is_ref_attr (attr))
|
| + if (attr_form_is_ref (attr))
|
| return retval;
|
|
|
| retval.sect_off = 0;
|
| @@ -16121,7 +18929,7 @@ dwarf2_get_ref_die_offset (struct attribute *attr)
|
| * the value held by the attribute is not constant. */
|
|
|
| static LONGEST
|
| -dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
|
| +dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value)
|
| {
|
| if (attr->form == DW_FORM_sdata)
|
| return DW_SND (attr);
|
| @@ -16145,12 +18953,12 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
|
| On exit *REF_CU is the CU of the result. */
|
|
|
| static struct die_info *
|
| -follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
|
| +follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr,
|
| struct dwarf2_cu **ref_cu)
|
| {
|
| struct die_info *die;
|
|
|
| - if (is_ref_attr (attr))
|
| + if (attr_form_is_ref (attr))
|
| die = follow_die_ref (src_die, attr, ref_cu);
|
| else if (attr->form == DW_FORM_ref_sig8)
|
| die = follow_die_sig (src_die, attr, ref_cu);
|
| @@ -16158,7 +18966,7 @@ follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
|
| {
|
| dump_die_for_error (src_die);
|
| error (_("Dwarf Error: Expected reference attribute [in module %s]"),
|
| - (*ref_cu)->objfile->name);
|
| + objfile_name ((*ref_cu)->objfile));
|
| }
|
|
|
| return die;
|
| @@ -16170,7 +18978,8 @@ follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
|
| Returns NULL if OFFSET is invalid. */
|
|
|
| static struct die_info *
|
| -follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
|
| +follow_die_offset (sect_offset offset, int offset_in_dwz,
|
| + struct dwarf2_cu **ref_cu)
|
| {
|
| struct die_info temp_die;
|
| struct dwarf2_cu *target_cu, *cu = *ref_cu;
|
| @@ -16187,11 +18996,13 @@ follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
|
| if (! offset_in_cu_p (&cu->header, offset))
|
| return NULL;
|
| }
|
| - else if (! offset_in_cu_p (&cu->header, offset))
|
| + else if (offset_in_dwz != cu->per_cu->is_dwz
|
| + || ! offset_in_cu_p (&cu->header, offset))
|
| {
|
| struct dwarf2_per_cu_data *per_cu;
|
|
|
| - per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
|
| + per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
|
| + cu->objfile);
|
|
|
| /* If necessary, add it to the queue and load its DIEs. */
|
| if (maybe_queue_comp_unit (cu, per_cu, cu->language))
|
| @@ -16216,37 +19027,141 @@ follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
|
| On exit *REF_CU is the CU of the result. */
|
|
|
| static struct die_info *
|
| -follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
| +follow_die_ref (struct die_info *src_die, const struct attribute *attr,
|
| struct dwarf2_cu **ref_cu)
|
| {
|
| sect_offset offset = dwarf2_get_ref_die_offset (attr);
|
| struct dwarf2_cu *cu = *ref_cu;
|
| struct die_info *die;
|
|
|
| - die = follow_die_offset (offset, ref_cu);
|
| + die = follow_die_offset (offset,
|
| + (attr->form == DW_FORM_GNU_ref_alt
|
| + || cu->per_cu->is_dwz),
|
| + ref_cu);
|
| if (!die)
|
| error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
|
| "at 0x%x [in module %s]"),
|
| - offset.sect_off, src_die->offset.sect_off, cu->objfile->name);
|
| + offset.sect_off, src_die->offset.sect_off,
|
| + objfile_name (cu->objfile));
|
|
|
| return die;
|
| }
|
|
|
| -/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU.
|
| - Returned value is intended for DW_OP_call*. Returned
|
| - dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */
|
| +/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU.
|
| + Returned value is intended for DW_OP_call*. Returned
|
| + dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */
|
| +
|
| +struct dwarf2_locexpr_baton
|
| +dwarf2_fetch_die_loc_sect_off (sect_offset offset,
|
| + struct dwarf2_per_cu_data *per_cu,
|
| + CORE_ADDR (*get_frame_pc) (void *baton),
|
| + void *baton)
|
| +{
|
| + struct dwarf2_cu *cu;
|
| + struct die_info *die;
|
| + struct attribute *attr;
|
| + struct dwarf2_locexpr_baton retval;
|
| +
|
| + dw2_setup (per_cu->objfile);
|
| +
|
| + if (per_cu->cu == NULL)
|
| + load_cu (per_cu);
|
| + cu = per_cu->cu;
|
| +
|
| + die = follow_die_offset (offset, per_cu->is_dwz, &cu);
|
| + if (!die)
|
| + error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
|
| + offset.sect_off, objfile_name (per_cu->objfile));
|
| +
|
| + attr = dwarf2_attr (die, DW_AT_location, cu);
|
| + if (!attr)
|
| + {
|
| + /* DWARF: "If there is no such attribute, then there is no effect.".
|
| + DATA is ignored if SIZE is 0. */
|
| +
|
| + retval.data = NULL;
|
| + retval.size = 0;
|
| + }
|
| + else if (attr_form_is_section_offset (attr))
|
| + {
|
| + struct dwarf2_loclist_baton loclist_baton;
|
| + CORE_ADDR pc = (*get_frame_pc) (baton);
|
| + size_t size;
|
| +
|
| + fill_in_loclist_baton (cu, &loclist_baton, attr);
|
| +
|
| + retval.data = dwarf2_find_location_expression (&loclist_baton,
|
| + &size, pc);
|
| + retval.size = size;
|
| + }
|
| + else
|
| + {
|
| + if (!attr_form_is_block (attr))
|
| + error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
|
| + "is neither DW_FORM_block* nor DW_FORM_exprloc"),
|
| + offset.sect_off, objfile_name (per_cu->objfile));
|
| +
|
| + retval.data = DW_BLOCK (attr)->data;
|
| + retval.size = DW_BLOCK (attr)->size;
|
| + }
|
| + retval.per_cu = cu->per_cu;
|
| +
|
| + age_cached_comp_units ();
|
| +
|
| + return retval;
|
| +}
|
| +
|
| +/* Like dwarf2_fetch_die_loc_sect_off, but take a CU
|
| + offset. */
|
| +
|
| +struct dwarf2_locexpr_baton
|
| +dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
|
| + struct dwarf2_per_cu_data *per_cu,
|
| + CORE_ADDR (*get_frame_pc) (void *baton),
|
| + void *baton)
|
| +{
|
| + sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
|
| +
|
| + return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton);
|
| +}
|
| +
|
| +/* Write a constant of a given type as target-ordered bytes into
|
| + OBSTACK. */
|
| +
|
| +static const gdb_byte *
|
| +write_constant_as_bytes (struct obstack *obstack,
|
| + enum bfd_endian byte_order,
|
| + struct type *type,
|
| + ULONGEST value,
|
| + LONGEST *len)
|
| +{
|
| + gdb_byte *result;
|
| +
|
| + *len = TYPE_LENGTH (type);
|
| + result = obstack_alloc (obstack, *len);
|
| + store_unsigned_integer (result, *len, byte_order, value);
|
| +
|
| + return result;
|
| +}
|
| +
|
| +/* If the DIE at OFFSET in PER_CU has a DW_AT_const_value, return a
|
| + pointer to the constant bytes and set LEN to the length of the
|
| + data. If memory is needed, allocate it on OBSTACK. If the DIE
|
| + does not have a DW_AT_const_value, return NULL. */
|
|
|
| -struct dwarf2_locexpr_baton
|
| -dwarf2_fetch_die_location_block (cu_offset offset_in_cu,
|
| - struct dwarf2_per_cu_data *per_cu,
|
| - CORE_ADDR (*get_frame_pc) (void *baton),
|
| - void *baton)
|
| +const gdb_byte *
|
| +dwarf2_fetch_constant_bytes (sect_offset offset,
|
| + struct dwarf2_per_cu_data *per_cu,
|
| + struct obstack *obstack,
|
| + LONGEST *len)
|
| {
|
| - sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
|
| struct dwarf2_cu *cu;
|
| struct die_info *die;
|
| struct attribute *attr;
|
| - struct dwarf2_locexpr_baton retval;
|
| + const gdb_byte *result = NULL;
|
| + struct type *type;
|
| + LONGEST value;
|
| + enum bfd_endian byte_order;
|
|
|
| dw2_setup (per_cu->objfile);
|
|
|
| @@ -16254,47 +19169,104 @@ dwarf2_fetch_die_location_block (cu_offset offset_in_cu,
|
| load_cu (per_cu);
|
| cu = per_cu->cu;
|
|
|
| - die = follow_die_offset (offset, &cu);
|
| + die = follow_die_offset (offset, per_cu->is_dwz, &cu);
|
| if (!die)
|
| error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
|
| - offset.sect_off, per_cu->objfile->name);
|
| + offset.sect_off, objfile_name (per_cu->objfile));
|
|
|
| - attr = dwarf2_attr (die, DW_AT_location, cu);
|
| - if (!attr)
|
| - {
|
| - /* DWARF: "If there is no such attribute, then there is no effect.".
|
| - DATA is ignored if SIZE is 0. */
|
|
|
| - retval.data = NULL;
|
| - retval.size = 0;
|
| - }
|
| - else if (attr_form_is_section_offset (attr))
|
| - {
|
| - struct dwarf2_loclist_baton loclist_baton;
|
| - CORE_ADDR pc = (*get_frame_pc) (baton);
|
| - size_t size;
|
| + attr = dwarf2_attr (die, DW_AT_const_value, cu);
|
| + if (attr == NULL)
|
| + return NULL;
|
|
|
| - fill_in_loclist_baton (cu, &loclist_baton, attr);
|
| + byte_order = (bfd_big_endian (per_cu->objfile->obfd)
|
| + ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE);
|
|
|
| - retval.data = dwarf2_find_location_expression (&loclist_baton,
|
| - &size, pc);
|
| - retval.size = size;
|
| - }
|
| - else
|
| + switch (attr->form)
|
| {
|
| - if (!attr_form_is_block (attr))
|
| - error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
|
| - "is neither DW_FORM_block* nor DW_FORM_exprloc"),
|
| - offset.sect_off, per_cu->objfile->name);
|
| + case DW_FORM_addr:
|
| + case DW_FORM_GNU_addr_index:
|
| + {
|
| + gdb_byte *tem;
|
|
|
| - retval.data = DW_BLOCK (attr)->data;
|
| - retval.size = DW_BLOCK (attr)->size;
|
| - }
|
| - retval.per_cu = cu->per_cu;
|
| + *len = cu->header.addr_size;
|
| + tem = obstack_alloc (obstack, *len);
|
| + store_unsigned_integer (tem, *len, byte_order, DW_ADDR (attr));
|
| + result = tem;
|
| + }
|
| + break;
|
| + case DW_FORM_string:
|
| + case DW_FORM_strp:
|
| + case DW_FORM_GNU_str_index:
|
| + case DW_FORM_GNU_strp_alt:
|
| + /* DW_STRING is already allocated on the objfile obstack, point
|
| + directly to it. */
|
| + result = (const gdb_byte *) DW_STRING (attr);
|
| + *len = strlen (DW_STRING (attr));
|
| + break;
|
| + case DW_FORM_block1:
|
| + case DW_FORM_block2:
|
| + case DW_FORM_block4:
|
| + case DW_FORM_block:
|
| + case DW_FORM_exprloc:
|
| + result = DW_BLOCK (attr)->data;
|
| + *len = DW_BLOCK (attr)->size;
|
| + break;
|
|
|
| - age_cached_comp_units ();
|
| + /* The DW_AT_const_value attributes are supposed to carry the
|
| + symbol's value "represented as it would be on the target
|
| + architecture." By the time we get here, it's already been
|
| + converted to host endianness, so we just need to sign- or
|
| + zero-extend it as appropriate. */
|
| + case DW_FORM_data1:
|
| + type = die_type (die, cu);
|
| + result = dwarf2_const_value_data (attr, obstack, cu, &value, 8);
|
| + if (result == NULL)
|
| + result = write_constant_as_bytes (obstack, byte_order,
|
| + type, value, len);
|
| + break;
|
| + case DW_FORM_data2:
|
| + type = die_type (die, cu);
|
| + result = dwarf2_const_value_data (attr, obstack, cu, &value, 16);
|
| + if (result == NULL)
|
| + result = write_constant_as_bytes (obstack, byte_order,
|
| + type, value, len);
|
| + break;
|
| + case DW_FORM_data4:
|
| + type = die_type (die, cu);
|
| + result = dwarf2_const_value_data (attr, obstack, cu, &value, 32);
|
| + if (result == NULL)
|
| + result = write_constant_as_bytes (obstack, byte_order,
|
| + type, value, len);
|
| + break;
|
| + case DW_FORM_data8:
|
| + type = die_type (die, cu);
|
| + result = dwarf2_const_value_data (attr, obstack, cu, &value, 64);
|
| + if (result == NULL)
|
| + result = write_constant_as_bytes (obstack, byte_order,
|
| + type, value, len);
|
| + break;
|
|
|
| - return retval;
|
| + case DW_FORM_sdata:
|
| + type = die_type (die, cu);
|
| + result = write_constant_as_bytes (obstack, byte_order,
|
| + type, DW_SND (attr), len);
|
| + break;
|
| +
|
| + case DW_FORM_udata:
|
| + type = die_type (die, cu);
|
| + result = write_constant_as_bytes (obstack, byte_order,
|
| + type, DW_UNSND (attr), len);
|
| + break;
|
| +
|
| + default:
|
| + complaint (&symfile_complaints,
|
| + _("unsupported const value attribute form: '%s'"),
|
| + dwarf_form_name (attr->form));
|
| + break;
|
| + }
|
| +
|
| + return result;
|
| }
|
|
|
| /* Return the type of the DIE at DIE_OFFSET in the CU named by
|
| @@ -16312,76 +19284,183 @@ dwarf2_get_die_type (cu_offset die_offset,
|
| return get_die_type_at_offset (die_offset_sect, per_cu);
|
| }
|
|
|
| -/* Follow the signature attribute ATTR in SRC_DIE.
|
| +/* Follow type unit SIG_TYPE referenced by SRC_DIE.
|
| On entry *REF_CU is the CU of SRC_DIE.
|
| - On exit *REF_CU is the CU of the result. */
|
| + On exit *REF_CU is the CU of the result.
|
| + Returns NULL if the referenced DIE isn't found. */
|
|
|
| static struct die_info *
|
| -follow_die_sig (struct die_info *src_die, struct attribute *attr,
|
| - struct dwarf2_cu **ref_cu)
|
| +follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type,
|
| + struct dwarf2_cu **ref_cu)
|
| {
|
| struct objfile *objfile = (*ref_cu)->objfile;
|
| struct die_info temp_die;
|
| - struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
|
| struct dwarf2_cu *sig_cu;
|
| struct die_info *die;
|
|
|
| - /* sig_type will be NULL if the signatured type is missing from
|
| - the debug info. */
|
| - if (sig_type == NULL)
|
| - error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
|
| - "at 0x%x [in module %s]"),
|
| - src_die->offset.sect_off, objfile->name);
|
| + /* While it might be nice to assert sig_type->type == NULL here,
|
| + we can get here for DW_AT_imported_declaration where we need
|
| + the DIE not the type. */
|
|
|
| /* If necessary, add it to the queue and load its DIEs. */
|
|
|
| if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu, language_minimal))
|
| read_signatured_type (sig_type);
|
|
|
| - gdb_assert (sig_type->per_cu.cu != NULL);
|
| -
|
| sig_cu = sig_type->per_cu.cu;
|
| + gdb_assert (sig_cu != NULL);
|
| gdb_assert (sig_type->type_offset_in_section.sect_off != 0);
|
| temp_die.offset = sig_type->type_offset_in_section;
|
| die = htab_find_with_hash (sig_cu->die_hash, &temp_die,
|
| temp_die.offset.sect_off);
|
| if (die)
|
| {
|
| + /* For .gdb_index version 7 keep track of included TUs.
|
| + http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
|
| + if (dwarf2_per_objfile->index_table != NULL
|
| + && dwarf2_per_objfile->index_table->version <= 7)
|
| + {
|
| + VEC_safe_push (dwarf2_per_cu_ptr,
|
| + (*ref_cu)->per_cu->imported_symtabs,
|
| + sig_cu->per_cu);
|
| + }
|
| +
|
| *ref_cu = sig_cu;
|
| return die;
|
| }
|
|
|
| - error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced "
|
| - "from DIE at 0x%x [in module %s]"),
|
| - temp_die.offset.sect_off, src_die->offset.sect_off, objfile->name);
|
| + return NULL;
|
| +}
|
| +
|
| +/* Follow signatured type referenced by ATTR in SRC_DIE.
|
| + On entry *REF_CU is the CU of SRC_DIE.
|
| + On exit *REF_CU is the CU of the result.
|
| + The result is the DIE of the type.
|
| + If the referenced type cannot be found an error is thrown. */
|
| +
|
| +static struct die_info *
|
| +follow_die_sig (struct die_info *src_die, const struct attribute *attr,
|
| + struct dwarf2_cu **ref_cu)
|
| +{
|
| + ULONGEST signature = DW_SIGNATURE (attr);
|
| + struct signatured_type *sig_type;
|
| + struct die_info *die;
|
| +
|
| + gdb_assert (attr->form == DW_FORM_ref_sig8);
|
| +
|
| + sig_type = lookup_signatured_type (*ref_cu, signature);
|
| + /* sig_type will be NULL if the signatured type is missing from
|
| + the debug info. */
|
| + if (sig_type == NULL)
|
| + {
|
| + error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
|
| + " from DIE at 0x%x [in module %s]"),
|
| + hex_string (signature), src_die->offset.sect_off,
|
| + objfile_name ((*ref_cu)->objfile));
|
| + }
|
| +
|
| + die = follow_die_sig_1 (src_die, sig_type, ref_cu);
|
| + if (die == NULL)
|
| + {
|
| + dump_die_for_error (src_die);
|
| + error (_("Dwarf Error: Problem reading signatured DIE %s referenced"
|
| + " from DIE at 0x%x [in module %s]"),
|
| + hex_string (signature), src_die->offset.sect_off,
|
| + objfile_name ((*ref_cu)->objfile));
|
| + }
|
| +
|
| + return die;
|
| }
|
|
|
| -/* Given an offset of a signatured type, return its signatured_type. */
|
| +/* Get the type specified by SIGNATURE referenced in DIE/CU,
|
| + reading in and processing the type unit if necessary. */
|
|
|
| -static struct signatured_type *
|
| -lookup_signatured_type_at_offset (struct objfile *objfile,
|
| - struct dwarf2_section_info *section,
|
| - sect_offset offset)
|
| -{
|
| - gdb_byte *info_ptr = section->buffer + offset.sect_off;
|
| - unsigned int length, initial_length_size;
|
| - unsigned int sig_offset;
|
| - struct signatured_type find_entry, *sig_type;
|
| -
|
| - length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size);
|
| - sig_offset = (initial_length_size
|
| - + 2 /*version*/
|
| - + (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/
|
| - + 1 /*address_size*/);
|
| - find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset);
|
| - sig_type = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
|
| -
|
| - /* This is only used to lookup previously recorded types.
|
| - If we didn't find it, it's our bug. */
|
| - gdb_assert (sig_type != NULL);
|
| - gdb_assert (offset.sect_off == sig_type->per_cu.offset.sect_off);
|
| +static struct type *
|
| +get_signatured_type (struct die_info *die, ULONGEST signature,
|
| + struct dwarf2_cu *cu)
|
| +{
|
| + struct signatured_type *sig_type;
|
| + struct dwarf2_cu *type_cu;
|
| + struct die_info *type_die;
|
| + struct type *type;
|
|
|
| - return sig_type;
|
| + sig_type = lookup_signatured_type (cu, signature);
|
| + /* sig_type will be NULL if the signatured type is missing from
|
| + the debug info. */
|
| + if (sig_type == NULL)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Dwarf Error: Cannot find signatured DIE %s referenced"
|
| + " from DIE at 0x%x [in module %s]"),
|
| + hex_string (signature), die->offset.sect_off,
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| + return build_error_marker_type (cu, die);
|
| + }
|
| +
|
| + /* If we already know the type we're done. */
|
| + if (sig_type->type != NULL)
|
| + return sig_type->type;
|
| +
|
| + type_cu = cu;
|
| + type_die = follow_die_sig_1 (die, sig_type, &type_cu);
|
| + if (type_die != NULL)
|
| + {
|
| + /* N.B. We need to call get_die_type to ensure only one type for this DIE
|
| + is created. This is important, for example, because for c++ classes
|
| + we need TYPE_NAME set which is only done by new_symbol. Blech. */
|
| + type = read_type_die (type_die, type_cu);
|
| + if (type == NULL)
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Dwarf Error: Cannot build signatured type %s"
|
| + " referenced from DIE at 0x%x [in module %s]"),
|
| + hex_string (signature), die->offset.sect_off,
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| + type = build_error_marker_type (cu, die);
|
| + }
|
| + }
|
| + else
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Dwarf Error: Problem reading signatured DIE %s referenced"
|
| + " from DIE at 0x%x [in module %s]"),
|
| + hex_string (signature), die->offset.sect_off,
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| + type = build_error_marker_type (cu, die);
|
| + }
|
| + sig_type->type = type;
|
| +
|
| + return type;
|
| +}
|
| +
|
| +/* Get the type specified by the DW_AT_signature ATTR in DIE/CU,
|
| + reading in and processing the type unit if necessary. */
|
| +
|
| +static struct type *
|
| +get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr,
|
| + struct dwarf2_cu *cu) /* ARI: editCase function */
|
| +{
|
| + /* Yes, DW_AT_signature can use a non-ref_sig8 reference. */
|
| + if (attr_form_is_ref (attr))
|
| + {
|
| + struct dwarf2_cu *type_cu = cu;
|
| + struct die_info *type_die = follow_die_ref (die, attr, &type_cu);
|
| +
|
| + return read_type_die (type_die, type_cu);
|
| + }
|
| + else if (attr->form == DW_FORM_ref_sig8)
|
| + {
|
| + return get_signatured_type (die, DW_SIGNATURE (attr), cu);
|
| + }
|
| + else
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Dwarf Error: DW_AT_signature has bad form %s in DIE"
|
| + " at 0x%x [in module %s]"),
|
| + dwarf_form_name (attr->form), die->offset.sect_off,
|
| + objfile_name (dwarf2_per_objfile->objfile));
|
| + return build_error_marker_type (cu, die);
|
| + }
|
| }
|
|
|
| /* Load the DIEs associated with type unit PER_CU into memory. */
|
| @@ -16412,7 +19491,7 @@ load_full_type_unit (struct dwarf2_per_cu_data *per_cu)
|
|
|
| static void
|
| read_signatured_type_reader (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| + const gdb_byte *info_ptr,
|
| struct die_info *comp_unit_die,
|
| int has_children,
|
| void *data)
|
| @@ -16458,6 +19537,7 @@ read_signatured_type (struct signatured_type *sig_type)
|
|
|
| init_cutu_and_read_dies (per_cu, NULL, 0, 1,
|
| read_signatured_type_reader, NULL);
|
| + sig_type->per_cu.tu_read = 1;
|
| }
|
|
|
| /* Decode simple location descriptions.
|
| @@ -16485,9 +19565,9 @@ static CORE_ADDR
|
| decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| - int i;
|
| - int size = blk->size;
|
| - gdb_byte *data = blk->data;
|
| + size_t i;
|
| + size_t size = blk->size;
|
| + const gdb_byte *data = blk->data;
|
| CORE_ADDR stack[64];
|
| int stacki;
|
| unsigned int bytes_read, unsnd;
|
| @@ -16752,12 +19832,12 @@ dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs)
|
|
|
| /* Macro support. */
|
|
|
| -/* Return the full name of file number I in *LH's file name table.
|
| - Use COMP_DIR as the name of the current directory of the
|
| - compilation. The result is allocated using xmalloc; the caller is
|
| +/* Return file name relative to the compilation directory of file number I in
|
| + *LH's file name table. The result is allocated using xmalloc; the caller is
|
| responsible for freeing it. */
|
| +
|
| static char *
|
| -file_full_name (int file, struct line_header *lh, const char *comp_dir)
|
| +file_file_name (int file, struct line_header *lh)
|
| {
|
| /* Is the file number a valid index into the line header's file name
|
| table? Remember that file numbers start with one, not zero. */
|
| @@ -16765,31 +19845,10 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir)
|
| {
|
| struct file_entry *fe = &lh->file_names[file - 1];
|
|
|
| - if (IS_ABSOLUTE_PATH (fe->name))
|
| + if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0)
|
| return xstrdup (fe->name);
|
| - else
|
| - {
|
| - const char *dir;
|
| - int dir_len;
|
| - char *full_name;
|
| -
|
| - if (fe->dir_index)
|
| - dir = lh->include_dirs[fe->dir_index - 1];
|
| - else
|
| - dir = comp_dir;
|
| -
|
| - if (dir)
|
| - {
|
| - dir_len = strlen (dir);
|
| - full_name = xmalloc (dir_len + 1 + strlen (fe->name) + 1);
|
| - strcpy (full_name, dir);
|
| - full_name[dir_len] = '/';
|
| - strcpy (full_name + dir_len + 1, fe->name);
|
| - return full_name;
|
| - }
|
| - else
|
| - return xstrdup (fe->name);
|
| - }
|
| + return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING,
|
| + fe->name, NULL);
|
| }
|
| else
|
| {
|
| @@ -16798,7 +19857,8 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir)
|
| won't be able to find the file by name. */
|
| char fake_name[80];
|
|
|
| - sprintf (fake_name, "<bad macro file number %d>", file);
|
| + xsnprintf (fake_name, sizeof (fake_name),
|
| + "<bad macro file number %d>", file);
|
|
|
| complaint (&symfile_complaints,
|
| _("bad file number in macro information (%d)"),
|
| @@ -16808,6 +19868,27 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir)
|
| }
|
| }
|
|
|
| +/* Return the full name of file number I in *LH's file name table.
|
| + Use COMP_DIR as the name of the current directory of the
|
| + compilation. The result is allocated using xmalloc; the caller is
|
| + responsible for freeing it. */
|
| +static char *
|
| +file_full_name (int file, struct line_header *lh, const char *comp_dir)
|
| +{
|
| + /* Is the file number a valid index into the line header's file name
|
| + table? Remember that file numbers start with one, not zero. */
|
| + if (1 <= file && file <= lh->num_file_names)
|
| + {
|
| + char *relative = file_file_name (file, lh);
|
| +
|
| + if (IS_ABSOLUTE_PATH (relative) || comp_dir == NULL)
|
| + return relative;
|
| + return reconcat (relative, comp_dir, SLASH_STRING, relative, NULL);
|
| + }
|
| + else
|
| + return file_file_name (file, lh);
|
| +}
|
| +
|
|
|
| static struct macro_source_file *
|
| macro_start_file (int file, int line,
|
| @@ -16815,26 +19896,24 @@ macro_start_file (int file, int line,
|
| const char *comp_dir,
|
| struct line_header *lh, struct objfile *objfile)
|
| {
|
| - /* The full name of this source file. */
|
| - char *full_name = file_full_name (file, lh, comp_dir);
|
| -
|
| - /* We don't create a macro table for this compilation unit
|
| - at all until we actually get a filename. */
|
| - if (! pending_macros)
|
| - pending_macros = new_macro_table (&objfile->objfile_obstack,
|
| - objfile->macro_cache);
|
| + /* File name relative to the compilation directory of this source file. */
|
| + char *file_name = file_file_name (file, lh);
|
|
|
| if (! current_file)
|
| {
|
| + /* Note: We don't create a macro table for this compilation unit
|
| + at all until we actually get a filename. */
|
| + struct macro_table *macro_table = get_macro_table (objfile, comp_dir);
|
| +
|
| /* If we have no current file, then this must be the start_file
|
| directive for the compilation unit's main source file. */
|
| - current_file = macro_set_main (pending_macros, full_name);
|
| - macro_define_special (pending_macros);
|
| + current_file = macro_set_main (macro_table, file_name);
|
| + macro_define_special (macro_table);
|
| }
|
| else
|
| - current_file = macro_include (current_file, line, full_name);
|
| + current_file = macro_include (current_file, line, file_name);
|
|
|
| - xfree (full_name);
|
| + xfree (file_name);
|
|
|
| return current_file;
|
| }
|
| @@ -17014,8 +20093,8 @@ parse_macro_definition (struct macro_source_file *file, int line,
|
| /* Skip some bytes from BYTES according to the form given in FORM.
|
| Returns the new pointer. */
|
|
|
| -static gdb_byte *
|
| -skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
|
| +static const gdb_byte *
|
| +skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end,
|
| enum dwarf_form form,
|
| unsigned int offset_size,
|
| struct dwarf2_section_info *section)
|
| @@ -17048,6 +20127,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
|
|
|
| case DW_FORM_sec_offset:
|
| case DW_FORM_strp:
|
| + case DW_FORM_GNU_strp_alt:
|
| bytes += offset_size;
|
| break;
|
|
|
| @@ -17070,7 +20150,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
|
| case DW_FORM_udata:
|
| case DW_FORM_GNU_addr_index:
|
| case DW_FORM_GNU_str_index:
|
| - bytes = (gdb_byte *) gdb_skip_leb128 (bytes, buffer_end);
|
| + bytes = gdb_skip_leb128 (bytes, buffer_end);
|
| if (bytes == NULL)
|
| {
|
| dwarf2_section_buffer_overflow_complaint (section);
|
| @@ -17083,8 +20163,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
|
| complain:
|
| complaint (&symfile_complaints,
|
| _("invalid form 0x%x in `%s'"),
|
| - form,
|
| - section->asection->name);
|
| + form, get_section_name (section));
|
| return NULL;
|
| }
|
| }
|
| @@ -17096,17 +20175,17 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
|
| opcode. Returns an updated pointer to the macro data buffer; or,
|
| on error, issues a complaint and returns NULL. */
|
|
|
| -static gdb_byte *
|
| +static const gdb_byte *
|
| skip_unknown_opcode (unsigned int opcode,
|
| - gdb_byte **opcode_definitions,
|
| - gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| + const gdb_byte **opcode_definitions,
|
| + const gdb_byte *mac_ptr, const gdb_byte *mac_end,
|
| bfd *abfd,
|
| unsigned int offset_size,
|
| struct dwarf2_section_info *section)
|
| {
|
| unsigned int bytes_read, i;
|
| unsigned long arg;
|
| - gdb_byte *defn;
|
| + const gdb_byte *defn;
|
|
|
| if (opcode_definitions[opcode] == NULL)
|
| {
|
| @@ -17139,10 +20218,10 @@ skip_unknown_opcode (unsigned int opcode,
|
| then this updates *OFFSET_SIZE. Returns a pointer to just after
|
| the header, or issues a complaint and returns NULL on error. */
|
|
|
| -static gdb_byte *
|
| -dwarf_parse_macro_header (gdb_byte **opcode_definitions,
|
| +static const gdb_byte *
|
| +dwarf_parse_macro_header (const gdb_byte **opcode_definitions,
|
| bfd *abfd,
|
| - gdb_byte *mac_ptr,
|
| + const gdb_byte *mac_ptr,
|
| unsigned int *offset_size,
|
| int section_is_gnu)
|
| {
|
| @@ -17199,18 +20278,19 @@ dwarf_parse_macro_header (gdb_byte **opcode_definitions,
|
| including DW_MACRO_GNU_transparent_include. */
|
|
|
| static void
|
| -dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| +dwarf_decode_macro_bytes (bfd *abfd,
|
| + const gdb_byte *mac_ptr, const gdb_byte *mac_end,
|
| struct macro_source_file *current_file,
|
| - struct line_header *lh, char *comp_dir,
|
| + struct line_header *lh, const char *comp_dir,
|
| struct dwarf2_section_info *section,
|
| - int section_is_gnu,
|
| + int section_is_gnu, int section_is_dwz,
|
| unsigned int offset_size,
|
| struct objfile *objfile,
|
| htab_t include_hash)
|
| {
|
| enum dwarf_macro_record_type macinfo_type;
|
| int at_commandline;
|
| - gdb_byte *opcode_definitions[256];
|
| + const gdb_byte *opcode_definitions[256];
|
|
|
| mac_ptr = dwarf_parse_macro_header (opcode_definitions, abfd, mac_ptr,
|
| &offset_size, section_is_gnu);
|
| @@ -17254,10 +20334,12 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| case DW_MACRO_GNU_undef:
|
| case DW_MACRO_GNU_define_indirect:
|
| case DW_MACRO_GNU_undef_indirect:
|
| + case DW_MACRO_GNU_define_indirect_alt:
|
| + case DW_MACRO_GNU_undef_indirect_alt:
|
| {
|
| unsigned int bytes_read;
|
| int line;
|
| - char *body;
|
| + const char *body;
|
| int is_define;
|
|
|
| line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
|
| @@ -17276,11 +20358,21 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
|
| mac_ptr += offset_size;
|
|
|
| - body = read_indirect_string_at_offset (abfd, str_offset);
|
| + if (macinfo_type == DW_MACRO_GNU_define_indirect_alt
|
| + || macinfo_type == DW_MACRO_GNU_undef_indirect_alt
|
| + || section_is_dwz)
|
| + {
|
| + struct dwz_file *dwz = dwarf2_get_dwz_file ();
|
| +
|
| + body = read_indirect_string_from_dwz (dwz, str_offset);
|
| + }
|
| + else
|
| + body = read_indirect_string_at_offset (abfd, str_offset);
|
| }
|
|
|
| is_define = (macinfo_type == DW_MACRO_GNU_define
|
| - || macinfo_type == DW_MACRO_GNU_define_indirect);
|
| + || macinfo_type == DW_MACRO_GNU_define_indirect
|
| + || macinfo_type == DW_MACRO_GNU_define_indirect_alt);
|
| if (! current_file)
|
| {
|
| /* DWARF violation as no main source is present. */
|
| @@ -17304,7 +20396,8 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| else
|
| {
|
| gdb_assert (macinfo_type == DW_MACRO_GNU_undef
|
| - || macinfo_type == DW_MACRO_GNU_undef_indirect);
|
| + || macinfo_type == DW_MACRO_GNU_undef_indirect
|
| + || macinfo_type == DW_MACRO_GNU_undef_indirect_alt);
|
| macro_undef (current_file, line, body);
|
| }
|
| }
|
| @@ -17379,14 +20472,36 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| break;
|
|
|
| case DW_MACRO_GNU_transparent_include:
|
| + case DW_MACRO_GNU_transparent_include_alt:
|
| {
|
| LONGEST offset;
|
| void **slot;
|
| + bfd *include_bfd = abfd;
|
| + struct dwarf2_section_info *include_section = section;
|
| + struct dwarf2_section_info alt_section;
|
| + const gdb_byte *include_mac_end = mac_end;
|
| + int is_dwz = section_is_dwz;
|
| + const gdb_byte *new_mac_ptr;
|
|
|
| offset = read_offset_1 (abfd, mac_ptr, offset_size);
|
| mac_ptr += offset_size;
|
|
|
| - slot = htab_find_slot (include_hash, mac_ptr, INSERT);
|
| + if (macinfo_type == DW_MACRO_GNU_transparent_include_alt)
|
| + {
|
| + struct dwz_file *dwz = dwarf2_get_dwz_file ();
|
| +
|
| + dwarf2_read_section (dwarf2_per_objfile->objfile,
|
| + &dwz->macro);
|
| +
|
| + include_section = &dwz->macro;
|
| + include_bfd = get_section_bfd_owner (include_section);
|
| + include_mac_end = dwz->macro.buffer + dwz->macro.size;
|
| + is_dwz = 1;
|
| + }
|
| +
|
| + new_mac_ptr = include_section->buffer + offset;
|
| + slot = htab_find_slot (include_hash, new_mac_ptr, INSERT);
|
| +
|
| if (*slot != NULL)
|
| {
|
| /* This has actually happened; see
|
| @@ -17397,16 +20512,15 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| }
|
| else
|
| {
|
| - *slot = mac_ptr;
|
| + *slot = (void *) new_mac_ptr;
|
|
|
| - dwarf_decode_macro_bytes (abfd,
|
| - section->buffer + offset,
|
| - mac_end, current_file,
|
| + dwarf_decode_macro_bytes (include_bfd, new_mac_ptr,
|
| + include_mac_end, current_file,
|
| lh, comp_dir,
|
| - section, section_is_gnu,
|
| + section, section_is_gnu, is_dwz,
|
| offset_size, objfile, include_hash);
|
|
|
| - htab_remove_elt (include_hash, mac_ptr);
|
| + htab_remove_elt (include_hash, (void *) new_mac_ptr);
|
| }
|
| }
|
| break;
|
| @@ -17440,16 +20554,16 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
|
|
| static void
|
| dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
| - char *comp_dir, int section_is_gnu)
|
| + const char *comp_dir, int section_is_gnu)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| struct line_header *lh = cu->line_header;
|
| bfd *abfd;
|
| - gdb_byte *mac_ptr, *mac_end;
|
| + const gdb_byte *mac_ptr, *mac_end;
|
| struct macro_source_file *current_file = 0;
|
| enum dwarf_macro_record_type macinfo_type;
|
| unsigned int offset_size = cu->header.offset_size;
|
| - gdb_byte *opcode_definitions[256];
|
| + const gdb_byte *opcode_definitions[256];
|
| struct cleanup *cleanup;
|
| htab_t include_hash;
|
| void **slot;
|
| @@ -17489,7 +20603,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
| complaint (&symfile_complaints, _("missing %s section"), section_name);
|
| return;
|
| }
|
| - abfd = section->asection->owner;
|
| + abfd = get_section_bfd_owner (section);
|
|
|
| /* First pass: Find the name of the base filename.
|
| This filename is needed in order to process all macros whose definition
|
| @@ -17570,6 +20684,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
|
|
| case DW_MACRO_GNU_define_indirect:
|
| case DW_MACRO_GNU_undef_indirect:
|
| + case DW_MACRO_GNU_define_indirect_alt:
|
| + case DW_MACRO_GNU_undef_indirect_alt:
|
| {
|
| unsigned int bytes_read;
|
|
|
| @@ -17580,6 +20696,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
| break;
|
|
|
| case DW_MACRO_GNU_transparent_include:
|
| + case DW_MACRO_GNU_transparent_include_alt:
|
| /* Note that, according to the spec, a transparent include
|
| chain cannot call DW_MACRO_GNU_start_file. So, we can just
|
| skip this opcode. */
|
| @@ -17620,9 +20737,10 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
| cleanup = make_cleanup_htab_delete (include_hash);
|
| mac_ptr = section->buffer + offset;
|
| slot = htab_find_slot (include_hash, mac_ptr, INSERT);
|
| - *slot = mac_ptr;
|
| + *slot = (void *) mac_ptr;
|
| dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
|
| - current_file, lh, comp_dir, section, section_is_gnu,
|
| + current_file, lh, comp_dir, section,
|
| + section_is_gnu, 0,
|
| offset_size, objfile, include_hash);
|
| do_cleanups (cleanup);
|
| }
|
| @@ -17631,7 +20749,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
| if so return true else false. */
|
|
|
| static int
|
| -attr_form_is_block (struct attribute *attr)
|
| +attr_form_is_block (const struct attribute *attr)
|
| {
|
| return (attr == NULL ? 0 :
|
| attr->form == DW_FORM_block1
|
| @@ -17651,7 +20769,7 @@ attr_form_is_block (struct attribute *attr)
|
| of them. */
|
|
|
| static int
|
| -attr_form_is_section_offset (struct attribute *attr)
|
| +attr_form_is_section_offset (const struct attribute *attr)
|
| {
|
| return (attr->form == DW_FORM_data4
|
| || attr->form == DW_FORM_data8
|
| @@ -17672,7 +20790,7 @@ attr_form_is_section_offset (struct attribute *attr)
|
| taken as section offsets, not constants. */
|
|
|
| static int
|
| -attr_form_is_constant (struct attribute *attr)
|
| +attr_form_is_constant (const struct attribute *attr)
|
| {
|
| switch (attr->form)
|
| {
|
| @@ -17688,6 +20806,28 @@ attr_form_is_constant (struct attribute *attr)
|
| }
|
| }
|
|
|
| +
|
| +/* DW_ADDR is always stored already as sect_offset; despite for the forms
|
| + besides DW_FORM_ref_addr it is stored as cu_offset in the DWARF file. */
|
| +
|
| +static int
|
| +attr_form_is_ref (const struct attribute *attr)
|
| +{
|
| + switch (attr->form)
|
| + {
|
| + case DW_FORM_ref_addr:
|
| + case DW_FORM_ref1:
|
| + case DW_FORM_ref2:
|
| + case DW_FORM_ref4:
|
| + case DW_FORM_ref8:
|
| + case DW_FORM_ref_udata:
|
| + case DW_FORM_GNU_ref_alt:
|
| + return 1;
|
| + default:
|
| + return 0;
|
| + }
|
| +}
|
| +
|
| /* Return the .debug_loc section to use for CU.
|
| For DWO files use .debug_loc.dwo. */
|
|
|
| @@ -17704,7 +20844,7 @@ cu_debug_loc_section (struct dwarf2_cu *cu)
|
| static void
|
| fill_in_loclist_baton (struct dwarf2_cu *cu,
|
| struct dwarf2_loclist_baton *baton,
|
| - struct attribute *attr)
|
| + const struct attribute *attr)
|
| {
|
| struct dwarf2_section_info *section = cu_debug_loc_section (cu);
|
|
|
| @@ -17721,8 +20861,8 @@ fill_in_loclist_baton (struct dwarf2_cu *cu,
|
| }
|
|
|
| static void
|
| -dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
|
| - struct dwarf2_cu *cu)
|
| +dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym,
|
| + struct dwarf2_cu *cu, int is_block)
|
| {
|
| struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| struct dwarf2_section_info *section = cu_debug_loc_section (cu);
|
| @@ -17745,7 +20885,9 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
|
| _("Location list used without "
|
| "specifying the CU base address."));
|
|
|
| - SYMBOL_COMPUTED_OPS (sym) = &dwarf2_loclist_funcs;
|
| + SYMBOL_ACLASS_INDEX (sym) = (is_block
|
| + ? dwarf2_loclist_block_index
|
| + : dwarf2_loclist_index);
|
| SYMBOL_LOCATION_BATON (sym) = baton;
|
| }
|
| else
|
| @@ -17774,7 +20916,9 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
|
| baton->size = 0;
|
| }
|
|
|
| - SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs;
|
| + SYMBOL_ACLASS_INDEX (sym) = (is_block
|
| + ? dwarf2_locexpr_block_index
|
| + : dwarf2_locexpr_index);
|
| SYMBOL_LOCATION_BATON (sym) = baton;
|
| }
|
| }
|
| @@ -17804,12 +20948,12 @@ static const struct comp_unit_head *
|
| per_cu_header_read_in (struct comp_unit_head *cu_headerp,
|
| struct dwarf2_per_cu_data *per_cu)
|
| {
|
| - gdb_byte *info_ptr;
|
| + const gdb_byte *info_ptr;
|
|
|
| if (per_cu->cu)
|
| return &per_cu->cu->header;
|
|
|
| - info_ptr = per_cu->info_or_types_section->buffer + per_cu->offset.sect_off;
|
| + info_ptr = per_cu->section->buffer + per_cu->offset.sect_off;
|
|
|
| memset (cu_headerp, 0, sizeof (*cu_headerp));
|
| read_comp_unit_head (cu_headerp, info_ptr, per_cu->objfile->obfd);
|
| @@ -17877,28 +21021,35 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu)
|
|
|
| static struct dwarf2_per_cu_data *
|
| dwarf2_find_containing_comp_unit (sect_offset offset,
|
| + unsigned int offset_in_dwz,
|
| struct objfile *objfile)
|
| {
|
| struct dwarf2_per_cu_data *this_cu;
|
| int low, high;
|
| + const sect_offset *cu_off;
|
|
|
| low = 0;
|
| high = dwarf2_per_objfile->n_comp_units - 1;
|
| while (high > low)
|
| {
|
| + struct dwarf2_per_cu_data *mid_cu;
|
| int mid = low + (high - low) / 2;
|
|
|
| - if (dwarf2_per_objfile->all_comp_units[mid]->offset.sect_off
|
| - >= offset.sect_off)
|
| + mid_cu = dwarf2_per_objfile->all_comp_units[mid];
|
| + cu_off = &mid_cu->offset;
|
| + if (mid_cu->is_dwz > offset_in_dwz
|
| + || (mid_cu->is_dwz == offset_in_dwz
|
| + && cu_off->sect_off >= offset.sect_off))
|
| high = mid;
|
| else
|
| low = mid + 1;
|
| }
|
| gdb_assert (low == high);
|
| - if (dwarf2_per_objfile->all_comp_units[low]->offset.sect_off
|
| - > offset.sect_off)
|
| + this_cu = dwarf2_per_objfile->all_comp_units[low];
|
| + cu_off = &this_cu->offset;
|
| + if (this_cu->is_dwz != offset_in_dwz || cu_off->sect_off > offset.sect_off)
|
| {
|
| - if (low == 0)
|
| + if (low == 0 || this_cu->is_dwz != offset_in_dwz)
|
| error (_("Dwarf Error: could not find partial DIE containing "
|
| "offset 0x%lx [in module %s]"),
|
| (long) offset.sect_off, bfd_get_filename (objfile->obfd));
|
| @@ -18104,11 +21255,13 @@ dwarf2_free_objfile (struct objfile *objfile)
|
|
|
| The CU "per_cu" pointer is needed because offset alone is not enough to
|
| uniquely identify the type. A file may have multiple .debug_types sections,
|
| - or the type may come from a DWO file. We have to use something in
|
| - dwarf2_per_cu_data (or the pointer to it) because we can enter the lookup
|
| - routine, get_die_type_at_offset, from outside this file, and thus won't
|
| - necessarily have PER_CU->cu. Fortunately, PER_CU is stable for the life
|
| - of the objfile. */
|
| + or the type may come from a DWO file. Furthermore, while it's more logical
|
| + to use per_cu->section+offset, with Fission the section with the data is in
|
| + the DWO file but we don't know that section at the point we need it.
|
| + We have to use something in dwarf2_per_cu_data (or the pointer to it)
|
| + because we can enter the lookup routine, get_die_type_at_offset, from
|
| + outside this file, and thus won't necessarily have PER_CU->cu.
|
| + Fortunately, PER_CU is stable for the life of the objfile. */
|
|
|
| struct dwarf2_per_cu_offset_and_type
|
| {
|
| @@ -18202,8 +21355,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
|
| return type;
|
| }
|
|
|
| -/* Look up the type for the die at OFFSET in the appropriate type_hash
|
| - table, or return NULL if the die does not have a saved type. */
|
| +/* Look up the type for the die at OFFSET in PER_CU in die_type_hash,
|
| + or return NULL if the die does not have a saved type. */
|
|
|
| static struct type *
|
| get_die_type_at_offset (sect_offset offset,
|
| @@ -18223,7 +21376,7 @@ get_die_type_at_offset (sect_offset offset,
|
| return NULL;
|
| }
|
|
|
| -/* Look up the type for DIE in the appropriate type_hash table,
|
| +/* Look up the type for DIE in CU in die_type_hash,
|
| or return NULL if DIE does not have a saved type. */
|
|
|
| static struct type *
|
| @@ -18340,62 +21493,35 @@ show_dwarf2_cmd (char *args, int from_tty)
|
| cmd_show_list (show_dwarf2_cmdlist, from_tty, "");
|
| }
|
|
|
| -/* If section described by INFO was mmapped, munmap it now. */
|
| -
|
| -static void
|
| -munmap_section_buffer (struct dwarf2_section_info *info)
|
| -{
|
| - if (info->map_addr != NULL)
|
| - {
|
| -#ifdef HAVE_MMAP
|
| - int res;
|
| -
|
| - res = munmap (info->map_addr, info->map_len);
|
| - gdb_assert (res == 0);
|
| -#else
|
| - /* Without HAVE_MMAP, we should never be here to begin with. */
|
| - gdb_assert_not_reached ("no mmap support");
|
| -#endif
|
| - }
|
| -}
|
| -
|
| -/* munmap debug sections for OBJFILE, if necessary. */
|
| +/* Free data associated with OBJFILE, if necessary. */
|
|
|
| static void
|
| dwarf2_per_objfile_free (struct objfile *objfile, void *d)
|
| {
|
| struct dwarf2_per_objfile *data = d;
|
| int ix;
|
| - struct dwarf2_section_info *section;
|
|
|
| - /* This is sorted according to the order they're defined in to make it easier
|
| - to keep in sync. */
|
| - munmap_section_buffer (&data->info);
|
| - munmap_section_buffer (&data->abbrev);
|
| - munmap_section_buffer (&data->line);
|
| - munmap_section_buffer (&data->loc);
|
| - munmap_section_buffer (&data->macinfo);
|
| - munmap_section_buffer (&data->macro);
|
| - munmap_section_buffer (&data->str);
|
| - munmap_section_buffer (&data->ranges);
|
| - munmap_section_buffer (&data->addr);
|
| - munmap_section_buffer (&data->frame);
|
| - munmap_section_buffer (&data->eh_frame);
|
| - munmap_section_buffer (&data->gdb_index);
|
| + /* Make sure we don't accidentally use dwarf2_per_objfile while
|
| + cleaning up. */
|
| + dwarf2_per_objfile = NULL;
|
|
|
| - for (ix = 0;
|
| - VEC_iterate (dwarf2_section_info_def, data->types, ix, section);
|
| - ++ix)
|
| - munmap_section_buffer (section);
|
| + for (ix = 0; ix < data->n_comp_units; ++ix)
|
| + VEC_free (dwarf2_per_cu_ptr, data->all_comp_units[ix]->imported_symtabs);
|
|
|
| - for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
|
| + for (ix = 0; ix < data->n_type_units; ++ix)
|
| VEC_free (dwarf2_per_cu_ptr,
|
| - dwarf2_per_objfile->all_comp_units[ix]->s.imported_symtabs);
|
| + data->all_type_units[ix]->per_cu.imported_symtabs);
|
| + xfree (data->all_type_units);
|
|
|
| VEC_free (dwarf2_section_info_def, data->types);
|
|
|
| if (data->dwo_files)
|
| free_dwo_files (data->dwo_files, objfile);
|
| + if (data->dwp_file)
|
| + gdb_bfd_unref (data->dwp_file->dbfd);
|
| +
|
| + if (data->dwz_file && data->dwz_file->dwz_bfd)
|
| + gdb_bfd_unref (data->dwz_file->dwz_bfd);
|
| }
|
|
|
|
|
| @@ -18831,7 +21957,7 @@ add_address_entry (struct objfile *objfile, struct obstack *obstack,
|
| CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
|
| {
|
| offset_type cu_index_to_write;
|
| - char addr[8];
|
| + gdb_byte addr[8];
|
| CORE_ADDR baseaddr;
|
|
|
| baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
| @@ -19015,8 +22141,7 @@ write_one_signatured_type (void **slot, void *d)
|
| {
|
| struct signatured_type_index_data *info = d;
|
| struct signatured_type *entry = (struct signatured_type *) *slot;
|
| - struct dwarf2_per_cu_data *per_cu = &entry->per_cu;
|
| - struct partial_symtab *psymtab = per_cu->v.psymtab;
|
| + struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
|
| gdb_byte val[8];
|
|
|
| write_psymbols (info->symtab,
|
| @@ -19093,23 +22218,23 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| htab_t cu_index_htab;
|
| struct psymtab_cu_index_map *psymtab_cu_index_map;
|
|
|
| - if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
|
| - return;
|
| -
|
| if (dwarf2_per_objfile->using_index)
|
| error (_("Cannot use an index to create the index"));
|
|
|
| if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
|
| error (_("Cannot make an index when the file has multiple .debug_types sections"));
|
|
|
| - if (stat (objfile->name, &st) < 0)
|
| - perror_with_name (objfile->name);
|
| + if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
|
| + return;
|
| +
|
| + if (stat (objfile_name (objfile), &st) < 0)
|
| + perror_with_name (objfile_name (objfile));
|
|
|
| - filename = concat (dir, SLASH_STRING, lbasename (objfile->name),
|
| + filename = concat (dir, SLASH_STRING, lbasename (objfile_name (objfile)),
|
| INDEX_SUFFIX, (char *) NULL);
|
| cleanup = make_cleanup (xfree, filename);
|
|
|
| - out_file = fopen (filename, "wb");
|
| + out_file = gdb_fopen_cloexec (filename, "wb");
|
| if (!out_file)
|
| error (_("Can't open `%s' for writing"), filename);
|
|
|
| @@ -19158,6 +22283,12 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| struct psymtab_cu_index_map *map;
|
| void **slot;
|
|
|
| + /* CU of a shared file from 'dwz -m' may be unused by this main file.
|
| + It may be referenced from a local scope but in such case it does not
|
| + need to be present in .gdb_index. */
|
| + if (psymtab == NULL)
|
| + continue;
|
| +
|
| if (psymtab->user == NULL)
|
| recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, i);
|
|
|
| @@ -19209,7 +22340,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| total_len = size_of_contents;
|
|
|
| /* The version number. */
|
| - val = MAYBE_SWAP (7);
|
| + val = MAYBE_SWAP (8);
|
| obstack_grow (&contents, &val, sizeof (val));
|
|
|
| /* The offset of the CU list from the start of the file. */
|
| @@ -19273,7 +22404,7 @@ save_gdb_index_command (char *arg, int from_tty)
|
| struct stat st;
|
|
|
| /* If the objfile does not correspond to an actual file, skip it. */
|
| - if (stat (objfile->name, &st) < 0)
|
| + if (stat (objfile_name (objfile), &st) < 0)
|
| continue;
|
|
|
| dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
|
| @@ -19288,7 +22419,7 @@ save_gdb_index_command (char *arg, int from_tty)
|
| if (except.reason < 0)
|
| exception_fprintf (gdb_stderr, except,
|
| _("Error while writing index for `%s': "),
|
| - objfile->name);
|
| + objfile_name (objfile));
|
| }
|
| }
|
| }
|
| @@ -19362,23 +22493,24 @@ conversational style, when possible."),
|
| &set_dwarf2_cmdlist,
|
| &show_dwarf2_cmdlist);
|
|
|
| - add_setshow_boolean_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
|
| + add_setshow_zuinteger_cmd ("dwarf2-read", no_class, &dwarf2_read_debug, _("\
|
| Set debugging of the dwarf2 reader."), _("\
|
| Show debugging of the dwarf2 reader."), _("\
|
| -When enabled, debugging messages are printed during dwarf2 reading\n\
|
| -and symtab expansion."),
|
| +When enabled (non-zero), debugging messages are printed during dwarf2\n\
|
| +reading and symtab expansion. A value of 1 (one) provides basic\n\
|
| +information. A value greater than 1 provides more verbose information."),
|
| NULL,
|
| NULL,
|
| &setdebuglist, &showdebuglist);
|
|
|
| - add_setshow_zinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\
|
| + add_setshow_zuinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\
|
| Set debugging of the dwarf2 DIE reader."), _("\
|
| Show debugging of the dwarf2 DIE reader."), _("\
|
| When enabled (non-zero), DIEs are dumped after they are read in.\n\
|
| The value is the maximum depth to print."),
|
| - NULL,
|
| - NULL,
|
| - &setdebuglist, &showdebuglist);
|
| + NULL,
|
| + NULL,
|
| + &setdebuglist, &showdebuglist);
|
|
|
| add_setshow_boolean_cmd ("check-physname", no_class, &check_physname, _("\
|
| Set cross-checking of \"physname\" code against demangler."), _("\
|
| @@ -19406,4 +22538,14 @@ Save a gdb-index file.\n\
|
| Usage: save gdb-index DIRECTORY"),
|
| &save_cmdlist);
|
| set_cmd_completer (c, filename_completer);
|
| +
|
| + dwarf2_locexpr_index = register_symbol_computed_impl (LOC_COMPUTED,
|
| + &dwarf2_locexpr_funcs);
|
| + dwarf2_loclist_index = register_symbol_computed_impl (LOC_COMPUTED,
|
| + &dwarf2_loclist_funcs);
|
| +
|
| + dwarf2_locexpr_block_index = register_symbol_block_impl (LOC_BLOCK,
|
| + &dwarf2_block_frame_base_locexpr_funcs);
|
| + dwarf2_loclist_block_index = register_symbol_block_impl (LOC_BLOCK,
|
| + &dwarf2_block_frame_base_loclist_funcs);
|
| }
|
|
|