| Index: gdb/dwarf2read.c
|
| diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
|
| index 8c81c8a78d4315deac655b81eee3fda069461c7c..48b8c08ae63204384fbe563ec2b5626a715945c2 100644
|
| --- a/gdb/dwarf2read.c
|
| +++ b/gdb/dwarf2read.c
|
| @@ -24,6 +24,10 @@
|
| You should have received a copy of the GNU General Public License
|
| along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
| +/* FIXME: Various die-reading functions need to be more careful with
|
| + reading off the end of the section.
|
| + E.g., load_partial_dies, read_partial_die. */
|
| +
|
| #include "defs.h"
|
| #include "bfd.h"
|
| #include "symtab.h"
|
| @@ -55,7 +59,10 @@
|
| #include "completer.h"
|
| #include "vec.h"
|
| #include "c-lang.h"
|
| +#include "go-lang.h"
|
| #include "valprint.h"
|
| +#include "gdbcore.h" /* for gnutarget */
|
| +#include "gdb/gdb-index.h"
|
| #include <ctype.h>
|
|
|
| #include <fcntl.h>
|
| @@ -75,45 +82,9 @@
|
| typedef struct symbol *symbolp;
|
| DEF_VEC_P (symbolp);
|
|
|
| -#if 0
|
| -/* .debug_info header for a compilation unit
|
| - Because of alignment constraints, this structure has padding and cannot
|
| - be mapped directly onto the beginning of the .debug_info section. */
|
| -typedef struct comp_unit_header
|
| - {
|
| - unsigned int length; /* length of the .debug_info
|
| - contribution */
|
| - unsigned short version; /* version number -- 2 for DWARF
|
| - version 2 */
|
| - unsigned int abbrev_offset; /* offset into .debug_abbrev section */
|
| - unsigned char addr_size; /* byte size of an address -- 4 */
|
| - }
|
| -_COMP_UNIT_HEADER;
|
| -#define _ACTUAL_COMP_UNIT_HEADER_SIZE 11
|
| -#endif
|
| -
|
| -/* .debug_line statement program prologue
|
| - Because of alignment constraints, this structure has padding and cannot
|
| - be mapped directly onto the beginning of the .debug_info section. */
|
| -typedef struct statement_prologue
|
| - {
|
| - unsigned int total_length; /* byte length of the statement
|
| - information */
|
| - unsigned short version; /* version number -- 2 for DWARF
|
| - version 2 */
|
| - unsigned int prologue_length; /* # bytes between prologue &
|
| - stmt program */
|
| - unsigned char minimum_instruction_length; /* byte size of
|
| - smallest instr */
|
| - unsigned char default_is_stmt; /* initial value of is_stmt
|
| - register */
|
| - char line_base;
|
| - unsigned char line_range;
|
| - unsigned char opcode_base; /* number assigned to first special
|
| - opcode */
|
| - unsigned char *standard_opcode_lengths;
|
| - }
|
| -_STATEMENT_PROLOGUE;
|
| +/* When non-zero, print basic high level tracing messages.
|
| + This is in contrast to the low level DIE reading of dwarf2_die_debug. */
|
| +static int dwarf2_read_debug = 0;
|
|
|
| /* When non-zero, dump DIEs after they are read in. */
|
| static int dwarf2_die_debug = 0;
|
| @@ -121,6 +92,9 @@ static int dwarf2_die_debug = 0;
|
| /* When non-zero, cross-check physname against demangler. */
|
| static int check_physname = 0;
|
|
|
| +/* When non-zero, do not reject deprecated .gdb_index sections. */
|
| +static int use_deprecated_index_sections = 0;
|
| +
|
| static int pagesize;
|
|
|
| /* When set, the file that we're processing is known to have debugging
|
| @@ -153,6 +127,28 @@ typedef uint32_t offset_type;
|
|
|
| DEF_VEC_I (offset_type);
|
|
|
| +/* Ensure only legit values are used. */
|
| +#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
|
| + do { \
|
| + gdb_assert ((unsigned int) (value) <= 1); \
|
| + GDB_INDEX_SYMBOL_STATIC_SET_VALUE((cu_index), (value)); \
|
| + } while (0)
|
| +
|
| +/* Ensure only legit values are used. */
|
| +#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
|
| + do { \
|
| + gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
|
| + && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
|
| + GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
|
| + } while (0)
|
| +
|
| +/* Ensure we don't use more than the alloted nuber of bits for the CU. */
|
| +#define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value) \
|
| + do { \
|
| + gdb_assert (((value) & ~GDB_INDEX_CU_MASK) == 0); \
|
| + GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \
|
| + } while (0)
|
| +
|
| /* A description of the mapped index. The file format is described in
|
| a comment by the code that writes the index. */
|
| struct mapped_index
|
| @@ -179,6 +175,12 @@ struct mapped_index
|
| const char *constant_pool;
|
| };
|
|
|
| +typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
|
| +DEF_VEC_P (dwarf2_per_cu_ptr);
|
| +
|
| +/* Collection of data recorded per objfile.
|
| + This hangs off of dwarf2_objfile_data_key. */
|
| +
|
| struct dwarf2_per_objfile
|
| {
|
| struct dwarf2_section_info info;
|
| @@ -189,6 +191,7 @@ struct dwarf2_per_objfile
|
| struct dwarf2_section_info macro;
|
| struct dwarf2_section_info str;
|
| struct dwarf2_section_info ranges;
|
| + struct dwarf2_section_info addr;
|
| struct dwarf2_section_info frame;
|
| struct dwarf2_section_info eh_frame;
|
| struct dwarf2_section_info gdb_index;
|
| @@ -198,7 +201,7 @@ struct dwarf2_per_objfile
|
| /* Back link. */
|
| struct objfile *objfile;
|
|
|
| - /* A list of all the compilation units. This is used to locate
|
| + /* Table of all the compilation units. This is used to locate
|
| the target compilation unit of a particular reference. */
|
| struct dwarf2_per_cu_data **all_comp_units;
|
|
|
| @@ -206,19 +209,44 @@ struct dwarf2_per_objfile
|
| int n_comp_units;
|
|
|
| /* The number of .debug_types-related CUs. */
|
| - int n_type_comp_units;
|
| + int n_type_units;
|
|
|
| - /* The .debug_types-related CUs. */
|
| - struct dwarf2_per_cu_data **type_comp_units;
|
| + /* The .debug_types-related CUs (TUs). */
|
| + struct signatured_type **all_type_units;
|
|
|
| - /* A chain of compilation units that are currently read in, so that
|
| - they can be freed later. */
|
| - struct dwarf2_per_cu_data *read_in_chain;
|
| + /* The number of entries in all_type_unit_groups. */
|
| + int n_type_unit_groups;
|
| +
|
| + /* Table of type unit groups.
|
| + This exists to make it easy to iterate over all CUs and TU groups. */
|
| + struct type_unit_group **all_type_unit_groups;
|
| +
|
| + /* Table of struct type_unit_group objects.
|
| + The hash key is the DW_AT_stmt_list value. */
|
| + htab_t type_unit_groups;
|
|
|
| /* A table mapping .debug_types signatures to its signatured_type entry.
|
| This is NULL if the .debug_types section hasn't been read in yet. */
|
| htab_t signatured_types;
|
|
|
| + /* Type unit statistics, to see how well the scaling improvements
|
| + are doing. */
|
| + struct tu_stats
|
| + {
|
| + int nr_uniq_abbrev_tables;
|
| + int nr_symtabs;
|
| + int nr_symtab_sharers;
|
| + int nr_stmt_less_type_units;
|
| + } tu_stats;
|
| +
|
| + /* A chain of compilation units that are currently read in, so that
|
| + they can be freed later. */
|
| + struct dwarf2_per_cu_data *read_in_chain;
|
| +
|
| + /* A table mapping DW_AT_dwo_name values to struct dwo_file objects.
|
| + This is NULL if the table hasn't been allocated yet. */
|
| + htab_t dwo_files;
|
| +
|
| /* A flag indicating wether this objfile has a section loaded at a
|
| VMA of 0. */
|
| int has_section_at_zero;
|
| @@ -240,15 +268,13 @@ struct dwarf2_per_objfile
|
| symbols. */
|
| int reading_partial_symbols;
|
|
|
| - /* Table mapping type .debug_info DIE offsets to types.
|
| + /* Table mapping type DIEs to their struct type *.
|
| This is NULL if not allocated yet.
|
| - It (currently) makes sense to allocate debug_types_type_hash lazily.
|
| - To keep things simple we allocate both lazily. */
|
| - htab_t debug_info_type_hash;
|
| + The mapping is done via (CU/TU signature + DIE offset) -> type. */
|
| + htab_t die_type_hash;
|
|
|
| - /* Table mapping type .debug_types DIE offsets to types.
|
| - This is NULL if not allocated yet. */
|
| - htab_t debug_types_type_hash;
|
| + /* The CUs we recently read. */
|
| + VEC (dwarf2_per_cu_ptr) *just_read_cus;
|
| };
|
|
|
| static struct dwarf2_per_objfile *dwarf2_per_objfile;
|
| @@ -258,7 +284,8 @@ static struct dwarf2_per_objfile *dwarf2_per_objfile;
|
| /* Note that if the debugging section has been compressed, it might
|
| have a name like .zdebug_info. */
|
|
|
| -static const struct dwarf2_debug_sections dwarf2_elf_names = {
|
| +static const struct dwarf2_debug_sections dwarf2_elf_names =
|
| +{
|
| { ".debug_info", ".zdebug_info" },
|
| { ".debug_abbrev", ".zdebug_abbrev" },
|
| { ".debug_line", ".zdebug_line" },
|
| @@ -268,18 +295,41 @@ static const struct dwarf2_debug_sections dwarf2_elf_names = {
|
| { ".debug_str", ".zdebug_str" },
|
| { ".debug_ranges", ".zdebug_ranges" },
|
| { ".debug_types", ".zdebug_types" },
|
| + { ".debug_addr", ".zdebug_addr" },
|
| { ".debug_frame", ".zdebug_frame" },
|
| { ".eh_frame", NULL },
|
| { ".gdb_index", ".zgdb_index" },
|
| 23
|
| };
|
|
|
| -/* local data types */
|
| +/* List of DWO sections. */
|
| +
|
| +static const struct dwo_section_names
|
| +{
|
| + struct dwarf2_section_names abbrev_dwo;
|
| + struct dwarf2_section_names info_dwo;
|
| + struct dwarf2_section_names line_dwo;
|
| + struct dwarf2_section_names loc_dwo;
|
| + struct dwarf2_section_names macinfo_dwo;
|
| + struct dwarf2_section_names macro_dwo;
|
| + struct dwarf2_section_names str_dwo;
|
| + struct dwarf2_section_names str_offsets_dwo;
|
| + struct dwarf2_section_names types_dwo;
|
| +}
|
| +dwo_section_names =
|
| +{
|
| + { ".debug_abbrev.dwo", ".zdebug_abbrev.dwo" },
|
| + { ".debug_info.dwo", ".zdebug_info.dwo" },
|
| + { ".debug_line.dwo", ".zdebug_line.dwo" },
|
| + { ".debug_loc.dwo", ".zdebug_loc.dwo" },
|
| + { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
|
| + { ".debug_macro.dwo", ".zdebug_macro.dwo" },
|
| + { ".debug_str.dwo", ".zdebug_str.dwo" },
|
| + { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
|
| + { ".debug_types.dwo", ".zdebug_types.dwo" },
|
| +};
|
|
|
| -/* We hold several abbreviation tables in memory at the same time. */
|
| -#ifndef ABBREV_HASH_SIZE
|
| -#define ABBREV_HASH_SIZE 121
|
| -#endif
|
| +/* local data types */
|
|
|
| /* The data in a compilation unit header, after target2host
|
| translation, looks like this. */
|
| @@ -289,7 +339,7 @@ struct comp_unit_head
|
| short version;
|
| unsigned char addr_size;
|
| unsigned char signed_addr_p;
|
| - unsigned int abbrev_offset;
|
| + sect_offset abbrev_offset;
|
|
|
| /* Size of file offsets; either 4 or 8. */
|
| unsigned int offset_size;
|
| @@ -299,11 +349,11 @@ struct comp_unit_head
|
|
|
| /* Offset to the first byte of this compilation unit header in the
|
| .debug_info section, for resolving relative reference dies. */
|
| - unsigned int offset;
|
| + sect_offset offset;
|
|
|
| /* Offset to first die in this cu from the start of the cu.
|
| This will be the first byte following the compilation unit header. */
|
| - unsigned int first_die_offset;
|
| + cu_offset first_die_offset;
|
| };
|
|
|
| /* Type used for delaying computation of method physnames.
|
| @@ -344,8 +394,6 @@ struct dwarf2_cu
|
| /* Non-zero if base_address has been set. */
|
| int base_known;
|
|
|
| - struct function_range *first_fn, *last_fn, *cached_fn;
|
| -
|
| /* The language we are debugging. */
|
| enum language language;
|
| const struct language_defn *language_defn;
|
| @@ -363,13 +411,13 @@ struct dwarf2_cu
|
| distinguish these in buildsym.c. */
|
| struct pending **list_in_scope;
|
|
|
| - /* DWARF abbreviation table associated with this compilation unit. */
|
| - struct abbrev_info **dwarf2_abbrevs;
|
| -
|
| - /* Storage for the abbrev table. */
|
| - struct obstack abbrev_obstack;
|
| + /* The abbrev table for this CU.
|
| + Normally this points to the abbrev table in the objfile.
|
| + But if DWO_UNIT is non-NULL this is the abbrev table in the DWO file. */
|
| + struct abbrev_table *abbrev_table;
|
|
|
| - /* Hash table holding all the loaded partial DIEs. */
|
| + /* Hash table holding all the loaded partial DIEs
|
| + with partial_die->offset.SECT_OFF as hash. */
|
| htab_t partial_dies;
|
|
|
| /* Storage for things with the same lifetime as this read-in compilation
|
| @@ -388,7 +436,8 @@ struct dwarf2_cu
|
| /* How many compilation units ago was this CU last referenced? */
|
| int last_used;
|
|
|
| - /* A hash table of die offsets for following references. */
|
| + /* A hash table of DIE cu_offset for following references with
|
| + die_info->offset.sect_off as hash. */
|
| htab_t die_hash;
|
|
|
| /* Full DIEs if read in. */
|
| @@ -409,32 +458,50 @@ struct dwarf2_cu
|
| /* To be copied to symtab->call_site_htab. */
|
| htab_t call_site_htab;
|
|
|
| + /* Non-NULL if this CU came from a DWO file.
|
| + There is an invariant here that is important to remember:
|
| + Except for attributes copied from the top level DIE in the "main"
|
| + (or "stub") file in preparation for reading the DWO file
|
| + (e.g., DW_AT_GNU_addr_base), we KISS: there is only *one* CU.
|
| + Either there isn't a DWO file (in which case this is NULL and the point
|
| + is moot), or there is and either we're not going to read it (in which
|
| + case this is NULL) or there is and we are reading it (in which case this
|
| + is non-NULL). */
|
| + struct dwo_unit *dwo_unit;
|
| +
|
| + /* The DW_AT_addr_base attribute if present, zero otherwise
|
| + (zero is a valid value though).
|
| + Note this value comes from the stub CU/TU's DIE. */
|
| + ULONGEST addr_base;
|
| +
|
| + /* The DW_AT_ranges_base attribute if present, zero otherwise
|
| + (zero is a valid value though).
|
| + Note this value comes from the 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. */
|
| + ULONGEST ranges_base;
|
| +
|
| /* Mark used when releasing cached dies. */
|
| unsigned int mark : 1;
|
|
|
| - /* This flag will be set if this compilation unit might include
|
| - inter-compilation-unit references. */
|
| - unsigned int has_form_ref_addr : 1;
|
| -
|
| - /* This flag will be set if this compilation unit includes any
|
| - DW_TAG_namespace DIEs. If we know that there are explicit
|
| - DIEs for namespaces, we don't need to try to infer them
|
| - from mangled names. */
|
| - unsigned int has_namespace_info : 1;
|
| -
|
| /* This CU references .debug_loc. See the symtab->locations_valid field.
|
| This test is imperfect as there may exist optimized debug code not using
|
| any location list and still facing inlining issues if handled as
|
| unoptimized code. For a future better test see GCC PR other/32998. */
|
| -
|
| unsigned int has_loclist : 1;
|
| +
|
| + /* These cache the results for producer_is_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. */
|
| + unsigned int checked_producer : 1;
|
| + unsigned int producer_is_gxx_lt_4_6 : 1;
|
| + unsigned int producer_is_icc : 1;
|
| };
|
|
|
| /* Persistent data held for a compilation unit, even when not
|
| processing it. We put a pointer to this structure in the
|
| - read_symtab_private field of the psymtab. If we encounter
|
| - inter-compilation-unit references, we also maintain a sorted
|
| - list of all compilation units. */
|
| + read_symtab_private field of the psymtab. */
|
|
|
| struct dwarf2_per_cu_data
|
| {
|
| @@ -442,29 +509,37 @@ struct dwarf2_per_cu_data
|
| bytes should suffice to store the length of any compilation unit
|
| - if it doesn't, GDB will fall over anyway.
|
| NOTE: Unlike comp_unit_head.length, this length includes
|
| - initial_length_size. */
|
| - unsigned int offset;
|
| + 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;
|
|
|
| /* Flag indicating this compilation unit will be read in before
|
| any of the current compilation units are processed. */
|
| unsigned int queued : 1;
|
|
|
| - /* This flag will be set if we need to load absolutely all DIEs
|
| - for this compilation unit, instead of just the ones we think
|
| - are interesting. It gets set if we look for a DIE in the
|
| + /* This flag will be set when reading partial DIEs if we need to load
|
| + absolutely all DIEs for this compilation unit, instead of just the ones
|
| + we think are interesting. It gets set if we look for a DIE in the
|
| hash table and don't find it. */
|
| unsigned int load_all_dies : 1;
|
|
|
| - /* Non-null if this CU is from .debug_types; in which case it points
|
| - to the section. Otherwise it's from .debug_info. */
|
| - struct dwarf2_section_info *debug_types_section;
|
| + /* Non-zero if this CU is from .debug_types. */
|
| + unsigned int is_debug_types : 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;
|
|
|
| /* 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. */
|
| struct dwarf2_cu *cu;
|
|
|
| - /* The corresponding objfile. */
|
| + /* The corresponding objfile.
|
| + Normally we can get the objfile from dwarf2_per_objfile.
|
| + However we can enter this file with just a "per_cu" handle. */
|
| struct objfile *objfile;
|
|
|
| /* When using partial symbol tables, the 'psymtab' field is active.
|
| @@ -472,47 +547,208 @@ struct dwarf2_per_cu_data
|
| union
|
| {
|
| /* The partial symbol table associated with this compilation unit,
|
| - or NULL for partial units (which do not have an associated
|
| - symtab). */
|
| + or NULL for unread partial units. */
|
| struct partial_symtab *psymtab;
|
|
|
| /* Data needed by the "quick" functions. */
|
| 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;
|
| };
|
|
|
| /* Entry in the signatured_types hash table. */
|
|
|
| struct signatured_type
|
| {
|
| + /* The "per_cu" object of this type.
|
| + N.B.: This is the first member so that it's easy to convert pointers
|
| + between them. */
|
| + struct dwarf2_per_cu_data per_cu;
|
| +
|
| + /* The type's signature. */
|
| ULONGEST signature;
|
|
|
| - /* Offset in .debug_types of the type defined by this TU. */
|
| - unsigned int type_offset;
|
| + /* 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. */
|
| + cu_offset type_offset_in_tu;
|
| +
|
| + /* Offset in the section of the type's DIE.
|
| + If the definition lives in a DWO file, this is the offset in the
|
| + .debug_types.dwo section.
|
| + The value is zero until the actual value is known.
|
| + Zero is otherwise not a valid section offset. */
|
| + sect_offset type_offset_in_section;
|
| +};
|
| +
|
| +/* 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. */
|
|
|
| - /* The CU(/TU) of this type. */
|
| +struct stmt_list_hash
|
| +{
|
| + /* The DWO unit this table is from or NULL if there is none. */
|
| + struct dwo_unit *dwo_unit;
|
| +
|
| + /* Offset in .debug_line or .debug_line.dwo. */
|
| + sect_offset line_offset;
|
| +};
|
| +
|
| +/* Each element of dwarf2_per_objfile->type_unit_groups is a pointer to
|
| + an object of this type. */
|
| +
|
| +struct type_unit_group
|
| +{
|
| + /* dwarf2read.c's main "handle" on the 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)
|
| 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 primary symtab.
|
| + Type units in a group needn't all be defined in the same source file,
|
| + so we create an essentially anonymous symtab as the primary symtab. */
|
| + struct symtab *primary_symtab;
|
| +
|
| + /* The data used to construct the hash key. */
|
| + struct stmt_list_hash hash;
|
| +
|
| + /* The number of symtabs from the line header.
|
| + The value here must match line_header.num_file_names. */
|
| + unsigned int num_symtabs;
|
| +
|
| + /* The symbol tables for this TU (obtained from the files listed in
|
| + DW_AT_stmt_list).
|
| + WARNING: The order of entries here must match the order of entries
|
| + in the line header. After the first TU using this type_unit_group, the
|
| + line header for the subsequent TUs is recreated from this. This is done
|
| + because we need to use the same symtabs for each TU using the same
|
| + DW_AT_stmt_list value. Also note that symtabs may be repeated here,
|
| + there's no guarantee the line header doesn't have duplicate entries. */
|
| + struct symtab **symtabs;
|
| +};
|
| +
|
| +/* These sections are what may appear in a "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;
|
| + VEC (dwarf2_section_info_def) *types;
|
| +};
|
| +
|
| +/* Common bits of DWO CUs/TUs. */
|
| +
|
| +struct dwo_unit
|
| +{
|
| + /* Backlink to the containing struct dwo_file. */
|
| + struct dwo_file *dwo_file;
|
| +
|
| + /* The "id" that distinguishes this CU/TU.
|
| + .debug_info calls this "dwo_id", .debug_types calls this "signature".
|
| + Since signatures came first, we stick with it for consistency. */
|
| + ULONGEST signature;
|
| +
|
| + /* The section this CU/TU lives in, in the DWO file. */
|
| + struct dwarf2_section_info *info_or_types_section;
|
| +
|
| + /* Same as dwarf2_per_cu_data:{offset,length} but for the DWO section. */
|
| + sect_offset offset;
|
| + unsigned int length;
|
| +
|
| + /* For types, offset in the type's DIE of the type defined by this TU. */
|
| + cu_offset type_offset_in_tu;
|
| +};
|
| +
|
| +/* Data for one DWO file. */
|
| +
|
| +struct dwo_file
|
| +{
|
| + /* The DW_AT_GNU_dwo_name attribute.
|
| + We don't manage space for this, it's an attribute. */
|
| + const char *dwo_name;
|
| +
|
| + /* The bfd, when the file is open. Otherwise this is NULL. */
|
| + bfd *dwo_bfd;
|
| +
|
| + /* Section info for this file. */
|
| + struct dwo_sections sections;
|
| +
|
| + /* Table of CUs in the file.
|
| + Each element is a struct dwo_unit. */
|
| + htab_t cus;
|
| +
|
| + /* Table of TUs in the file.
|
| + Each element is a struct dwo_unit. */
|
| + htab_t tus;
|
| };
|
|
|
| /* Struct used to pass misc. parameters to read_die_and_children, et
|
| al. which are used for both .debug_info and .debug_types dies.
|
| All parameters here are unchanging for the life of the call. This
|
| - struct exists to abstract away the constant parameters of die
|
| - reading. */
|
| + struct exists to abstract away the constant parameters of die reading. */
|
|
|
| struct die_reader_specs
|
| {
|
| - /* The bfd of this objfile. */
|
| + /* die_section->asection->owner. */
|
| bfd* abfd;
|
|
|
| /* The CU of the DIE we are parsing. */
|
| struct dwarf2_cu *cu;
|
|
|
| - /* Pointer to start of section buffer.
|
| - This is either the start of .debug_info or .debug_types. */
|
| - const gdb_byte *buffer;
|
| + /* Non-NULL if reading a DWO file. */
|
| + struct dwo_file *dwo_file;
|
| +
|
| + /* The section the die comes from.
|
| + This is either .debug_info or .debug_types, or the .dwo variants. */
|
| + struct dwarf2_section_info *die_section;
|
| +
|
| + /* die_section->buffer. */
|
| + gdb_byte *buffer;
|
| +
|
| + /* The end of the buffer. */
|
| + const gdb_byte *buffer_end;
|
| };
|
|
|
| +/* 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,
|
| + struct die_info *comp_unit_die,
|
| + int has_children,
|
| + void *data);
|
| +
|
| /* The line number information for a compilation unit (found in the
|
| .debug_line section) begins with a "statement program header",
|
| which contains the following information. */
|
| @@ -565,7 +801,7 @@ struct line_header
|
| struct partial_die_info
|
| {
|
| /* Offset of this DIE. */
|
| - unsigned int offset;
|
| + sect_offset offset;
|
|
|
| /* DWARF-2 tag for this DIE. */
|
| ENUM_BITFIELD(dwarf_tag) tag : 16;
|
| @@ -577,6 +813,7 @@ struct partial_die_info
|
| unsigned int has_type : 1;
|
| unsigned int has_specification : 1;
|
| unsigned int has_pc_info : 1;
|
| + unsigned int may_be_inlined : 1;
|
|
|
| /* Flag set if the SCOPE field of this structure has been
|
| computed. */
|
| @@ -603,8 +840,15 @@ struct partial_die_info
|
| when this compilation unit leaves the cache. */
|
| char *scope;
|
|
|
| - /* The location description associated with this DIE, if any. */
|
| - struct dwarf_block *locdesc;
|
| + /* Some data associated with the partial DIE. The tag determines
|
| + which field is live. */
|
| + union
|
| + {
|
| + /* The location description associated with this DIE, if any. */
|
| + struct dwarf_block *locdesc;
|
| + /* The offset of an import, for DW_TAG_imported_unit. */
|
| + sect_offset offset;
|
| + } d;
|
|
|
| /* If HAS_PC_INFO, the PC range associated with this DIE. */
|
| CORE_ADDR lowpc;
|
| @@ -619,7 +863,7 @@ struct partial_die_info
|
| /* If HAS_SPECIFICATION, the offset of the DIE referred to by
|
| DW_AT_specification (or DW_AT_abstract_origin or
|
| DW_AT_extension). */
|
| - unsigned int spec_offset;
|
| + sect_offset spec_offset;
|
|
|
| /* Pointers to this DIE's parent, first child, and next sibling,
|
| if any. */
|
| @@ -643,6 +887,27 @@ struct attr_abbrev
|
| ENUM_BITFIELD(dwarf_form) form : 16;
|
| };
|
|
|
| +/* Size of abbrev_table.abbrev_hash_table. */
|
| +#define ABBREV_HASH_SIZE 121
|
| +
|
| +/* Top level data structure to contain an abbreviation table. */
|
| +
|
| +struct abbrev_table
|
| +{
|
| + /* Where the abbrev table came from.
|
| + This is used as a sanity check when the table is used. */
|
| + sect_offset offset;
|
| +
|
| + /* Storage for the abbrev table. */
|
| + struct obstack abbrev_obstack;
|
| +
|
| + /* Hash table of abbrevs.
|
| + This is an array of size ABBREV_HASH_SIZE allocated in abbrev_obstack.
|
| + It could be statically allocated, but the previous code didn't so we
|
| + don't either. */
|
| + struct abbrev_info **abbrevs;
|
| +};
|
| +
|
| /* Attributes have a name and a value. */
|
| struct attribute
|
| {
|
| @@ -683,7 +948,7 @@ struct die_info
|
| unsigned int abbrev;
|
|
|
| /* Offset in .debug_info or .debug_types section. */
|
| - unsigned int offset;
|
| + sect_offset offset;
|
|
|
| /* The dies in a compilation unit form an n-ary tree. PARENT
|
| points to this die's parent; CHILD points to the first child of
|
| @@ -699,14 +964,6 @@ struct die_info
|
| struct attribute attrs[1];
|
| };
|
|
|
| -struct function_range
|
| -{
|
| - const char *name;
|
| - CORE_ADDR lowpc, highpc;
|
| - int seen_line;
|
| - struct function_range *next;
|
| -};
|
| -
|
| /* Get at parts of an attribute structure. */
|
|
|
| #define DW_STRING(attr) ((attr)->u.str)
|
| @@ -803,6 +1060,7 @@ struct field_info
|
| struct dwarf2_queue_item
|
| {
|
| struct dwarf2_per_cu_data *per_cu;
|
| + enum language pretend_language;
|
| struct dwarf2_queue_item *next;
|
| };
|
|
|
| @@ -865,11 +1123,13 @@ dwarf2_const_value_length_mismatch_complaint (const char *arg1, int arg2,
|
| }
|
|
|
| static void
|
| -dwarf2_macros_too_long_complaint (struct dwarf2_section_info *section)
|
| +dwarf2_section_buffer_overflow_complaint (struct dwarf2_section_info *section)
|
| {
|
| complaint (&symfile_complaints,
|
| - _("macro info runs off end of `%s' section"),
|
| - section->asection->name);
|
| + _("debug info runs off end of %s section"
|
| + " [in module %s]"),
|
| + section->asection->name,
|
| + bfd_get_filename (section->asection->owner));
|
| }
|
|
|
| static void
|
| @@ -923,47 +1183,45 @@ static void add_partial_subprogram (struct partial_die_info *pdi,
|
| CORE_ADDR *lowpc, CORE_ADDR *highpc,
|
| int need_pc, struct dwarf2_cu *cu);
|
|
|
| -static gdb_byte *locate_pdi_sibling (struct partial_die_info *orig_pdi,
|
| - gdb_byte *buffer, gdb_byte *info_ptr,
|
| - bfd *abfd, struct dwarf2_cu *cu);
|
| -
|
| static void dwarf2_psymtab_to_symtab (struct partial_symtab *);
|
|
|
| static void psymtab_to_symtab_1 (struct partial_symtab *);
|
|
|
| -static void dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu);
|
| +static struct abbrev_info *abbrev_table_lookup_abbrev
|
| + (const struct abbrev_table *, unsigned int);
|
|
|
| -static void dwarf2_free_abbrev_table (void *);
|
| +static struct abbrev_table *abbrev_table_read_table
|
| + (struct dwarf2_section_info *, sect_offset);
|
|
|
| -static unsigned int peek_abbrev_code (bfd *, gdb_byte *);
|
| +static void abbrev_table_free (struct abbrev_table *);
|
|
|
| -static struct abbrev_info *peek_die_abbrev (gdb_byte *, unsigned int *,
|
| - struct dwarf2_cu *);
|
| +static void abbrev_table_free_cleanup (void *);
|
|
|
| -static struct abbrev_info *dwarf2_lookup_abbrev (unsigned int,
|
| - struct dwarf2_cu *);
|
| +static void dwarf2_read_abbrevs (struct dwarf2_cu *,
|
| + struct dwarf2_section_info *);
|
|
|
| -static struct partial_die_info *load_partial_dies (bfd *,
|
| - gdb_byte *, gdb_byte *,
|
| - int, struct dwarf2_cu *);
|
| +static void dwarf2_free_abbrev_table (void *);
|
| +
|
| +static unsigned int peek_abbrev_code (bfd *, gdb_byte *);
|
| +
|
| +static struct partial_die_info *load_partial_dies
|
| + (const struct die_reader_specs *, gdb_byte *, int);
|
|
|
| -static gdb_byte *read_partial_die (struct partial_die_info *,
|
| - struct abbrev_info *abbrev,
|
| - unsigned int, bfd *,
|
| - gdb_byte *, gdb_byte *,
|
| - struct dwarf2_cu *);
|
| +static gdb_byte *read_partial_die (const struct die_reader_specs *,
|
| + struct partial_die_info *,
|
| + struct abbrev_info *,
|
| + unsigned int,
|
| + gdb_byte *);
|
|
|
| -static struct partial_die_info *find_partial_die (unsigned int,
|
| +static struct partial_die_info *find_partial_die (sect_offset,
|
| struct dwarf2_cu *);
|
|
|
| static void fixup_partial_die (struct partial_die_info *,
|
| struct dwarf2_cu *);
|
|
|
| -static gdb_byte *read_attribute (struct attribute *, struct attr_abbrev *,
|
| - bfd *, gdb_byte *, struct dwarf2_cu *);
|
| -
|
| -static gdb_byte *read_attribute_value (struct attribute *, unsigned,
|
| - bfd *, gdb_byte *, struct dwarf2_cu *);
|
| +static gdb_byte *read_attribute (const struct die_reader_specs *,
|
| + struct attribute *, struct attr_abbrev *,
|
| + gdb_byte *);
|
|
|
| static unsigned int read_1_byte (bfd *, gdb_byte *);
|
|
|
| @@ -989,6 +1247,9 @@ static LONGEST read_offset (bfd *, gdb_byte *, const struct comp_unit_head *,
|
|
|
| static LONGEST read_offset_1 (bfd *, 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 char *read_direct_string (bfd *, gdb_byte *, unsigned int *);
|
| @@ -997,11 +1258,15 @@ static char *read_indirect_string (bfd *, gdb_byte *,
|
| const struct comp_unit_head *,
|
| unsigned int *);
|
|
|
| -static unsigned long read_unsigned_leb128 (bfd *, gdb_byte *, unsigned int *);
|
| +static ULONGEST read_unsigned_leb128 (bfd *, gdb_byte *, unsigned int *);
|
|
|
| -static long read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
|
| +static LONGEST read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
|
|
|
| -static gdb_byte *skip_leb128 (bfd *, gdb_byte *);
|
| +static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, gdb_byte *,
|
| + unsigned int *);
|
| +
|
| +static 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 *);
|
|
|
| @@ -1009,8 +1274,7 @@ static struct attribute *dwarf2_attr (struct die_info *, unsigned int,
|
| struct dwarf2_cu *);
|
|
|
| static struct attribute *dwarf2_attr_no_follow (struct die_info *,
|
| - unsigned int,
|
| - struct dwarf2_cu *);
|
| + unsigned int);
|
|
|
| static int dwarf2_flag_true_p (struct die_info *die, unsigned name,
|
| struct dwarf2_cu *cu);
|
| @@ -1025,9 +1289,8 @@ 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,
|
| - bfd *abfd, struct dwarf2_cu *cu));
|
| +static struct line_header *dwarf_decode_line_header (unsigned int offset,
|
| + struct dwarf2_cu *cu);
|
|
|
| static void dwarf_decode_lines (struct line_header *, const char *,
|
| struct dwarf2_cu *, struct partial_symtab *,
|
| @@ -1035,6 +1298,9 @@ static void dwarf_decode_lines (struct line_header *, const char *,
|
|
|
| static void dwarf2_start_subfile (char *, const char *, const char *);
|
|
|
| +static void dwarf2_start_symtab (struct dwarf2_cu *,
|
| + char *, char *, CORE_ADDR);
|
| +
|
| static struct symbol *new_symbol (struct die_info *, struct type *,
|
| struct dwarf2_cu *);
|
|
|
| @@ -1048,7 +1314,7 @@ static void dwarf2_const_value_attr (struct attribute *attr,
|
| struct type *type,
|
| const char *name,
|
| struct obstack *obstack,
|
| - struct dwarf2_cu *cu, long *value,
|
| + struct dwarf2_cu *cu, LONGEST *value,
|
| gdb_byte **bytes,
|
| struct dwarf2_locexpr_baton **baton);
|
|
|
| @@ -1072,7 +1338,7 @@ static struct type *read_type_die (struct die_info *, struct dwarf2_cu *);
|
|
|
| static struct type *read_type_die_1 (struct die_info *, struct dwarf2_cu *);
|
|
|
| -static char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
|
| +static const char *determine_prefix (struct die_info *die, struct dwarf2_cu *);
|
|
|
| static char *typename_concat (struct obstack *obs, const char *prefix,
|
| const char *suffix, int physname,
|
| @@ -1139,26 +1405,21 @@ 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_comp_unit (gdb_byte *, struct dwarf2_cu *);
|
| -
|
| -static struct die_info *read_die_and_children_1 (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| - struct die_info *parent);
|
| -
|
| -static struct die_info *read_die_and_children (const struct die_reader_specs *reader,
|
| +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 (const struct die_reader_specs *reader,
|
| +static struct die_info *read_die_and_siblings (const struct die_reader_specs *,
|
| gdb_byte *info_ptr,
|
| gdb_byte **new_info_ptr,
|
| struct die_info *parent);
|
|
|
| -static gdb_byte *read_full_die (const struct die_reader_specs *reader,
|
| - struct die_info **, gdb_byte *,
|
| - int *);
|
| +static gdb_byte *read_full_die_1 (const struct die_reader_specs *,
|
| + struct die_info **, gdb_byte *, int *, int);
|
| +
|
| +static gdb_byte *read_full_die (const struct die_reader_specs *,
|
| + struct die_info **, gdb_byte *, int *);
|
|
|
| static void process_die (struct die_info *, struct dwarf2_cu *);
|
|
|
| @@ -1174,19 +1435,15 @@ static const char *dwarf2_full_name (char *name,
|
| static struct die_info *dwarf2_extension (struct die_info *die,
|
| struct dwarf2_cu **);
|
|
|
| -static char *dwarf_tag_name (unsigned int);
|
| +static const char *dwarf_tag_name (unsigned int);
|
|
|
| -static char *dwarf_attr_name (unsigned int);
|
| +static const char *dwarf_attr_name (unsigned int);
|
|
|
| -static char *dwarf_form_name (unsigned int);
|
| +static const char *dwarf_form_name (unsigned int);
|
|
|
| static char *dwarf_bool_name (unsigned int);
|
|
|
| -static char *dwarf_type_encoding_name (unsigned int);
|
| -
|
| -#if 0
|
| -static char *dwarf_cfi_name (unsigned int);
|
| -#endif
|
| +static const char *dwarf_type_encoding_name (unsigned int);
|
|
|
| static struct die_info *sibling_die (struct die_info *);
|
|
|
| @@ -1204,7 +1461,7 @@ static void store_in_ref_table (struct die_info *,
|
|
|
| static int is_ref_attr (struct attribute *);
|
|
|
| -static unsigned int dwarf2_get_ref_die_offset (struct attribute *);
|
| +static sect_offset dwarf2_get_ref_die_offset (struct attribute *);
|
|
|
| static LONGEST dwarf2_get_attr_constant_value (struct attribute *, int);
|
|
|
| @@ -1222,33 +1479,25 @@ static struct die_info *follow_die_sig (struct die_info *,
|
|
|
| static struct signatured_type *lookup_signatured_type_at_offset
|
| (struct objfile *objfile,
|
| - struct dwarf2_section_info *section,
|
| - unsigned int offset);
|
| + struct dwarf2_section_info *section, sect_offset offset);
|
| +
|
| +static void load_full_type_unit (struct dwarf2_per_cu_data *per_cu);
|
| +
|
| +static void read_signatured_type (struct signatured_type *);
|
|
|
| -static void read_signatured_type_at_offset (struct objfile *objfile,
|
| - struct dwarf2_section_info *sect,
|
| - unsigned int offset);
|
| +static struct type_unit_group *get_type_unit_group
|
| + (struct dwarf2_cu *, struct attribute *);
|
|
|
| -static void read_signatured_type (struct objfile *,
|
| - struct signatured_type *type_sig);
|
| +static void build_type_unit_groups (die_reader_func_ftype *, void *);
|
|
|
| /* memory allocation interface */
|
|
|
| static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *);
|
|
|
| -static struct abbrev_info *dwarf_alloc_abbrev (struct dwarf2_cu *);
|
| -
|
| static struct die_info *dwarf_alloc_die (struct dwarf2_cu *, int);
|
|
|
| -static void initialize_cu_func_list (struct dwarf2_cu *);
|
| -
|
| -static void add_to_cu_func_list (const char *, CORE_ADDR, CORE_ADDR,
|
| - struct dwarf2_cu *);
|
| -
|
| -static void dwarf_decode_macros (struct line_header *, unsigned int,
|
| - char *, bfd *, struct dwarf2_cu *,
|
| - struct dwarf2_section_info *,
|
| - int);
|
| +static void dwarf_decode_macros (struct dwarf2_cu *, unsigned int,
|
| + char *, int);
|
|
|
| static int attr_form_is_block (struct attribute *);
|
|
|
| @@ -1264,9 +1513,9 @@ static void dwarf2_symbol_mark_computed (struct attribute *attr,
|
| struct symbol *sym,
|
| struct dwarf2_cu *cu);
|
|
|
| -static gdb_byte *skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
|
| - struct abbrev_info *abbrev,
|
| - struct dwarf2_cu *cu);
|
| +static gdb_byte *skip_one_die (const struct die_reader_specs *reader,
|
| + gdb_byte *info_ptr,
|
| + struct abbrev_info *abbrev);
|
|
|
| static void free_stack_comp_unit (void *);
|
|
|
| @@ -1275,36 +1524,38 @@ 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
|
| - (unsigned int offset, struct objfile *objfile);
|
| -
|
| -static struct dwarf2_per_cu_data *dwarf2_find_comp_unit
|
| - (unsigned int offset, struct objfile *objfile);
|
| + (sect_offset offset, struct objfile *objfile);
|
|
|
| static void init_one_comp_unit (struct dwarf2_cu *cu,
|
| - struct objfile *objfile);
|
| + struct dwarf2_per_cu_data *per_cu);
|
|
|
| static void prepare_one_comp_unit (struct dwarf2_cu *cu,
|
| - struct die_info *comp_unit_die);
|
| + struct die_info *comp_unit_die,
|
| + enum language pretend_language);
|
|
|
| -static void free_one_comp_unit (void *);
|
| +static void free_heap_comp_unit (void *);
|
|
|
| static void free_cached_comp_units (void *);
|
|
|
| static void age_cached_comp_units (void);
|
|
|
| -static void free_one_cached_comp_unit (void *);
|
| +static void free_one_cached_comp_unit (struct dwarf2_per_cu_data *);
|
|
|
| static struct type *set_die_type (struct die_info *, struct type *,
|
| struct dwarf2_cu *);
|
|
|
| static void create_all_comp_units (struct objfile *);
|
|
|
| -static int create_debug_types_hash_table (struct objfile *objfile);
|
| +static int create_all_type_units (struct objfile *);
|
|
|
| static void load_full_comp_unit (struct dwarf2_per_cu_data *,
|
| - struct objfile *);
|
| + enum language);
|
| +
|
| +static void process_full_comp_unit (struct dwarf2_per_cu_data *,
|
| + enum language);
|
|
|
| -static void process_full_comp_unit (struct dwarf2_per_cu_data *);
|
| +static void process_full_type_unit (struct dwarf2_per_cu_data *,
|
| + enum language);
|
|
|
| static void dwarf2_add_dependence (struct dwarf2_cu *,
|
| struct dwarf2_per_cu_data *);
|
| @@ -1313,7 +1564,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 (unsigned int,
|
| +static struct type *get_die_type_at_offset (sect_offset,
|
| struct dwarf2_per_cu_data *per_cu);
|
|
|
| static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
|
| @@ -1321,9 +1572,13 @@ static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
|
| static void dwarf2_release_queue (void *dummy);
|
|
|
| static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| - struct objfile *objfile);
|
| + enum language pretend_language);
|
|
|
| -static void process_queue (struct objfile *objfile);
|
| +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,
|
| @@ -1332,18 +1587,31 @@ static void find_file_and_directory (struct die_info *die,
|
| static char *file_full_name (int file, struct line_header *lh,
|
| const char *comp_dir);
|
|
|
| -static gdb_byte *partial_read_comp_unit_head (struct comp_unit_head *header,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte *buffer,
|
| - unsigned int buffer_size,
|
| - bfd *abfd,
|
| - int is_debug_types_section);
|
| +static void init_cutu_and_read_dies
|
| + (struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table,
|
| + int use_existing_cu, int keep,
|
| + die_reader_func_ftype *die_reader_func, void *data);
|
|
|
| -static void init_cu_die_reader (struct die_reader_specs *reader,
|
| - struct dwarf2_cu *cu);
|
| +static void init_cutu_and_read_dies_simple
|
| + (struct dwarf2_per_cu_data *this_cu,
|
| + die_reader_func_ftype *die_reader_func, void *data);
|
|
|
| static htab_t allocate_signatured_type_table (struct objfile *objfile);
|
|
|
| +static htab_t allocate_dwo_unit_table (struct objfile *objfile);
|
| +
|
| +static struct dwo_unit *lookup_dwo_comp_unit
|
| + (struct dwarf2_per_cu_data *, char *, const char *, ULONGEST);
|
| +
|
| +static struct dwo_unit *lookup_dwo_type_unit
|
| + (struct signatured_type *, char *, const char *);
|
| +
|
| +static void free_dwo_file_cleanup (void *);
|
| +
|
| +static void munmap_section_buffer (struct dwarf2_section_info *);
|
| +
|
| +static void process_cu_includes (void);
|
| +
|
| #if WORDS_BIGENDIAN
|
|
|
| /* Convert VALUE between big- and little-endian. */
|
| @@ -1423,13 +1691,17 @@ static void
|
| dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| {
|
| const struct dwarf2_debug_sections *names;
|
| + flagword aflag = bfd_get_section_flags (abfd, sectp);
|
|
|
| if (vnames == NULL)
|
| names = &dwarf2_elf_names;
|
| else
|
| names = (const struct dwarf2_debug_sections *) vnames;
|
|
|
| - if (section_is_p (sectp->name, &names->info))
|
| + if ((aflag & SEC_HAS_CONTENTS) == 0)
|
| + {
|
| + }
|
| + else if (section_is_p (sectp->name, &names->info))
|
| {
|
| dwarf2_per_objfile->info.asection = sectp;
|
| dwarf2_per_objfile->info.size = bfd_get_section_size (sectp);
|
| @@ -1464,6 +1736,11 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| dwarf2_per_objfile->str.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.size = bfd_get_section_size (sectp);
|
| + }
|
| else if (section_is_p (sectp->name, &names->frame))
|
| {
|
| dwarf2_per_objfile->frame.asection = sectp;
|
| @@ -1471,13 +1748,8 @@ dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames)
|
| }
|
| else if (section_is_p (sectp->name, &names->eh_frame))
|
| {
|
| - flagword aflag = bfd_get_section_flags (ignore_abfd, sectp);
|
| -
|
| - if (aflag & SEC_HAS_CONTENTS)
|
| - {
|
| - dwarf2_per_objfile->eh_frame.asection = sectp;
|
| - dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
|
| - }
|
| + dwarf2_per_objfile->eh_frame.asection = sectp;
|
| + dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp);
|
| }
|
| else if (section_is_p (sectp->name, &names->ranges))
|
| {
|
| @@ -1513,7 +1785,7 @@ static void
|
| zlib_decompress_section (struct objfile *objfile, asection *sectp,
|
| gdb_byte **outbuf, bfd_size_type *outsize)
|
| {
|
| - bfd *abfd = objfile->obfd;
|
| + bfd *abfd = sectp->owner;
|
| #ifndef HAVE_ZLIB_H
|
| error (_("Support for zlib-compressed DWARF data (from '%s') "
|
| "is disabled in this copy of GDB"),
|
| @@ -1585,7 +1857,8 @@ zlib_decompress_section (struct objfile *objfile, asection *sectp,
|
| #endif
|
| }
|
|
|
| -/* A helper function that decides whether a section is empty. */
|
| +/* A helper function that decides whether a section is empty,
|
| + or not present. */
|
|
|
| static int
|
| dwarf2_section_empty_p (struct dwarf2_section_info *info)
|
| @@ -1593,15 +1866,17 @@ dwarf2_section_empty_p (struct dwarf2_section_info *info)
|
| return info->asection == NULL || info->size == 0;
|
| }
|
|
|
| -/* Read the contents of the section SECTP from object file specified by
|
| - OBJFILE, store info about the section into INFO.
|
| +/* 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.
|
| If the section is compressed, uncompress it before returning. */
|
|
|
| static void
|
| dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
|
| {
|
| - bfd *abfd = objfile->obfd;
|
| asection *sectp = info->asection;
|
| + bfd *abfd;
|
| gdb_byte *buf, *retbuf;
|
| unsigned char header[4];
|
|
|
| @@ -1614,6 +1889,9 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
|
| 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
|
| @@ -1740,8 +2018,8 @@ dwarf2_get_section_info (struct objfile *objfile,
|
| line_header when we're done and don't need to record it here. */
|
| struct quick_file_names
|
| {
|
| - /* The offset in .debug_line of the line table. We hash on this. */
|
| - unsigned int offset;
|
| + /* The data used to construct the hash key. */
|
| + struct stmt_list_hash hash;
|
|
|
| /* The number of entries in file_names, real_names. */
|
| unsigned int num_file_names;
|
| @@ -1778,6 +2056,34 @@ struct dwarf2_per_cu_quick_data
|
| unsigned int no_file_data : 1;
|
| };
|
|
|
| +/* Utility hash function for a stmt_list_hash. */
|
| +
|
| +static hashval_t
|
| +hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash)
|
| +{
|
| + hashval_t v = 0;
|
| +
|
| + if (stmt_list_hash->dwo_unit != NULL)
|
| + v += (uintptr_t) stmt_list_hash->dwo_unit->dwo_file;
|
| + v += stmt_list_hash->line_offset.sect_off;
|
| + return v;
|
| +}
|
| +
|
| +/* Utility equality function for a stmt_list_hash. */
|
| +
|
| +static int
|
| +eq_stmt_list_entry (const struct stmt_list_hash *lhs,
|
| + const struct stmt_list_hash *rhs)
|
| +{
|
| + if ((lhs->dwo_unit != NULL) != (rhs->dwo_unit != NULL))
|
| + return 0;
|
| + if (lhs->dwo_unit != NULL
|
| + && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file)
|
| + return 0;
|
| +
|
| + return lhs->line_offset.sect_off == rhs->line_offset.sect_off;
|
| +}
|
| +
|
| /* Hash function for a quick_file_names. */
|
|
|
| static hashval_t
|
| @@ -1785,7 +2091,7 @@ hash_file_name_entry (const void *e)
|
| {
|
| const struct quick_file_names *file_data = e;
|
|
|
| - return file_data->offset;
|
| + return hash_stmt_list_entry (&file_data->hash);
|
| }
|
|
|
| /* Equality function for a quick_file_names. */
|
| @@ -1796,7 +2102,7 @@ eq_file_name_entry (const void *a, const void *b)
|
| const struct quick_file_names *ea = a;
|
| const struct quick_file_names *eb = b;
|
|
|
| - return ea->offset == eb->offset;
|
| + return eq_stmt_list_entry (&ea->hash, &eb->hash);
|
| }
|
|
|
| /* Delete function for a quick_file_names. */
|
| @@ -1835,34 +2141,39 @@ create_quick_file_names_table (unsigned int nr_initial_entries)
|
| static void
|
| load_cu (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| - if (per_cu->debug_types_section)
|
| - read_signatured_type_at_offset (per_cu->objfile,
|
| - per_cu->debug_types_section,
|
| - per_cu->offset);
|
| + if (per_cu->is_debug_types)
|
| + load_full_type_unit (per_cu);
|
| else
|
| - load_full_comp_unit (per_cu, per_cu->objfile);
|
| -
|
| - dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
|
| + load_full_comp_unit (per_cu, language_minimal);
|
|
|
| gdb_assert (per_cu->cu != NULL);
|
| +
|
| + dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
|
| }
|
|
|
| -/* Read in the symbols for PER_CU. OBJFILE is the objfile from which
|
| - this CU came. */
|
| +/* Read in the symbols for PER_CU. */
|
|
|
| static void
|
| -dw2_do_instantiate_symtab (struct objfile *objfile,
|
| - struct dwarf2_per_cu_data *per_cu)
|
| +dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| struct cleanup *back_to;
|
|
|
| - back_to = make_cleanup (dwarf2_release_queue, NULL);
|
| + /* Skip type_unit_groups, reading the type units they contain
|
| + is handled elsewhere. */
|
| + if (IS_TYPE_UNIT_GROUP (per_cu))
|
| + return;
|
|
|
| - queue_comp_unit (per_cu, objfile);
|
| + back_to = make_cleanup (dwarf2_release_queue, NULL);
|
|
|
| - load_cu (per_cu);
|
| + if (dwarf2_per_objfile->using_index
|
| + ? per_cu->v.quick->symtab == NULL
|
| + : (per_cu->v.psymtab == NULL || !per_cu->v.psymtab->readin))
|
| + {
|
| + queue_comp_unit (per_cu, language_minimal);
|
| + load_cu (per_cu);
|
| + }
|
|
|
| - process_queue (objfile);
|
| + process_queue ();
|
|
|
| /* Age the cache, releasing compilation units that have not
|
| been used recently. */
|
| @@ -1876,20 +2187,32 @@ dw2_do_instantiate_symtab (struct objfile *objfile,
|
| table. */
|
|
|
| static struct symtab *
|
| -dw2_instantiate_symtab (struct objfile *objfile,
|
| - struct dwarf2_per_cu_data *per_cu)
|
| +dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| + gdb_assert (dwarf2_per_objfile->using_index);
|
| if (!per_cu->v.quick->symtab)
|
| {
|
| struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL);
|
| increment_reading_symtab ();
|
| - dw2_do_instantiate_symtab (objfile, per_cu);
|
| + dw2_do_instantiate_symtab (per_cu);
|
| + process_cu_includes ();
|
| do_cleanups (back_to);
|
| }
|
| return per_cu->v.quick->symtab;
|
| }
|
|
|
| -/* Return the CU given its index. */
|
| +/* Return the CU given its index.
|
| +
|
| + This is intended for loops like:
|
| +
|
| + for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_units); ++i)
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
| +
|
| + ...;
|
| + }
|
| +*/
|
|
|
| static struct dwarf2_per_cu_data *
|
| dw2_get_cu (int index)
|
| @@ -1897,8 +2220,38 @@ dw2_get_cu (int index)
|
| if (index >= dwarf2_per_objfile->n_comp_units)
|
| {
|
| index -= dwarf2_per_objfile->n_comp_units;
|
| - return dwarf2_per_objfile->type_comp_units[index];
|
| + gdb_assert (index < dwarf2_per_objfile->n_type_units);
|
| + return &dwarf2_per_objfile->all_type_units[index]->per_cu;
|
| + }
|
| +
|
| + return dwarf2_per_objfile->all_comp_units[index];
|
| +}
|
| +
|
| +/* Return the primary CU given its index.
|
| + The difference between this function and dw2_get_cu is in the handling
|
| + of type units (TUs). Here we return the type_unit_group object.
|
| +
|
| + This is intended for loops like:
|
| +
|
| + for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| +
|
| + ...;
|
| + }
|
| +*/
|
| +
|
| +static struct dwarf2_per_cu_data *
|
| +dw2_get_primary_cu (int index)
|
| +{
|
| + if (index >= dwarf2_per_objfile->n_comp_units)
|
| + {
|
| + index -= dwarf2_per_objfile->n_comp_units;
|
| + gdb_assert (index < dwarf2_per_objfile->n_type_unit_groups);
|
| + return &dwarf2_per_objfile->all_type_unit_groups[index]->per_cu;
|
| }
|
| +
|
| return dwarf2_per_objfile->all_comp_units[index];
|
| }
|
|
|
| @@ -1953,9 +2306,10 @@ create_cus_from_index (struct objfile *objfile, const gdb_byte *cu_list,
|
|
|
| the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| struct dwarf2_per_cu_data);
|
| - the_cu->offset = offset;
|
| + 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->v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| struct dwarf2_per_cu_quick_data);
|
| dwarf2_per_objfile->all_comp_units[i / 2] = the_cu;
|
| @@ -1975,41 +2329,42 @@ create_signatured_type_table_from_index (struct objfile *objfile,
|
| offset_type i;
|
| htab_t sig_types_hash;
|
|
|
| - dwarf2_per_objfile->n_type_comp_units = elements / 3;
|
| - dwarf2_per_objfile->type_comp_units
|
| + dwarf2_per_objfile->n_type_units = elements / 3;
|
| + dwarf2_per_objfile->all_type_units
|
| = obstack_alloc (&objfile->objfile_obstack,
|
| - dwarf2_per_objfile->n_type_comp_units
|
| - * sizeof (struct dwarf2_per_cu_data *));
|
| + dwarf2_per_objfile->n_type_units
|
| + * sizeof (struct signatured_type *));
|
|
|
| sig_types_hash = allocate_signatured_type_table (objfile);
|
|
|
| for (i = 0; i < elements; i += 3)
|
| {
|
| - struct signatured_type *type_sig;
|
| - ULONGEST offset, type_offset, signature;
|
| + struct signatured_type *sig_type;
|
| + ULONGEST offset, type_offset_in_tu, signature;
|
| void **slot;
|
|
|
| if (!extract_cu_value (bytes, &offset)
|
| - || !extract_cu_value (bytes + 8, &type_offset))
|
| + || !extract_cu_value (bytes + 8, &type_offset_in_tu))
|
| return 0;
|
| signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE);
|
| bytes += 3 * 8;
|
|
|
| - type_sig = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| struct signatured_type);
|
| - type_sig->signature = signature;
|
| - type_sig->type_offset = type_offset;
|
| - type_sig->per_cu.debug_types_section = section;
|
| - type_sig->per_cu.offset = offset;
|
| - type_sig->per_cu.objfile = objfile;
|
| - type_sig->per_cu.v.quick
|
| + 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.offset.sect_off = offset;
|
| + sig_type->per_cu.objfile = objfile;
|
| + sig_type->per_cu.v.quick
|
| = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| struct dwarf2_per_cu_quick_data);
|
|
|
| - slot = htab_find_slot (sig_types_hash, type_sig, INSERT);
|
| - *slot = type_sig;
|
| + slot = htab_find_slot (sig_types_hash, sig_type, INSERT);
|
| + *slot = sig_type;
|
|
|
| - dwarf2_per_objfile->type_comp_units[i / 3] = &type_sig->per_cu;
|
| + dwarf2_per_objfile->all_type_units[i / 3] = sig_type;
|
| }
|
|
|
| dwarf2_per_objfile->signatured_types = sig_types_hash;
|
| @@ -2117,7 +2472,7 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name,
|
| }
|
|
|
| /* Index version 4 did not support case insensitive searches. But the
|
| - indexes for case insensitive languages are built in lowercase, therefore
|
| + indices for case insensitive languages are built in lowercase, therefore
|
| simulate our NAME being searched is also lowercased. */
|
| hash = mapped_index_string_hash ((index->version == 4
|
| && case_sensitivity == case_sensitive_off
|
| @@ -2184,13 +2539,43 @@ dwarf2_read_index (struct objfile *objfile)
|
| /* Versions earlier than 3 emitted every copy of a psymbol. This
|
| causes the index to behave very poorly for certain requests. Version 3
|
| contained incomplete addrmap. So, it seems better to just ignore such
|
| - indices. Index version 4 uses a different hash function than index
|
| - version 5 and later. */
|
| + indices. */
|
| if (version < 4)
|
| - return 0;
|
| + {
|
| + static int warning_printed = 0;
|
| + if (!warning_printed)
|
| + {
|
| + warning (_("Skipping obsolete .gdb_index section in %s."),
|
| + objfile->name);
|
| + warning_printed = 1;
|
| + }
|
| + return 0;
|
| + }
|
| + /* Index version 4 uses a different hash function than index version
|
| + 5 and later.
|
| +
|
| + Versions earlier than 6 did not emit psymbols for inlined
|
| + functions. Using these files will cause GDB not to be able to
|
| + set breakpoints on inlined functions by name, so we ignore these
|
| + indices unless the user has done
|
| + "set use-deprecated-index-sections on". */
|
| + if (version < 6 && !use_deprecated_index_sections)
|
| + {
|
| + static int warning_printed = 0;
|
| + if (!warning_printed)
|
| + {
|
| + warning (_("\
|
| +Skipping deprecated .gdb_index section in %s.\n\
|
| +Do \"set use-deprecated-index-sections on\" before the file is read\n\
|
| +to use the section anyway."),
|
| + objfile->name);
|
| + warning_printed = 1;
|
| + }
|
| + return 0;
|
| + }
|
| /* Indexes with higher version than the one supported by GDB may be no
|
| longer backward compatible. */
|
| - if (version > 5)
|
| + if (version > 7)
|
| return 0;
|
|
|
| map = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct mapped_index);
|
| @@ -2224,6 +2609,10 @@ dwarf2_read_index (struct objfile *objfile)
|
|
|
| map->constant_pool = addr + MAYBE_SWAP (metadata[i]);
|
|
|
| + /* Don't use the index if it's empty. */
|
| + if (map->symbol_table_slots == 0)
|
| + return 0;
|
| +
|
| if (!create_cus_from_index (objfile, cu_list, cu_list_elements))
|
| return 0;
|
|
|
| @@ -2265,74 +2654,86 @@ dw2_setup (struct objfile *objfile)
|
| gdb_assert (dwarf2_per_objfile);
|
| }
|
|
|
| -/* A helper for the "quick" functions which attempts to read the line
|
| - table for THIS_CU. */
|
| +/* Reader function for dw2_build_type_unit_groups. */
|
|
|
| -static struct quick_file_names *
|
| -dw2_get_file_names (struct objfile *objfile,
|
| - struct dwarf2_per_cu_data *this_cu)
|
| +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)
|
| {
|
| - bfd *abfd = objfile->obfd;
|
| + 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,
|
| + struct die_info *comp_unit_die,
|
| + int has_children,
|
| + void *data)
|
| +{
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + struct dwarf2_per_cu_data *this_cu = cu->per_cu;
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_per_cu_data *lh_cu;
|
| struct line_header *lh;
|
| struct attribute *attr;
|
| - struct cleanup *cleanups;
|
| - struct die_info *comp_unit_die;
|
| - struct dwarf2_section_info* sec;
|
| - gdb_byte *info_ptr, *buffer;
|
| - int has_children, i;
|
| - struct dwarf2_cu cu;
|
| - unsigned int bytes_read, buffer_size;
|
| - struct die_reader_specs reader_specs;
|
| + int i;
|
| char *name, *comp_dir;
|
| void **slot;
|
| struct quick_file_names *qfn;
|
| unsigned int line_offset;
|
|
|
| - if (this_cu->v.quick->file_names != NULL)
|
| - return this_cu->v.quick->file_names;
|
| - /* If we know there is no line data, no point in looking again. */
|
| - if (this_cu->v.quick->no_file_data)
|
| - return NULL;
|
| + /* 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)
|
| + {
|
| + this_cu->v.quick->no_file_data = 1;
|
| + return;
|
| + }
|
|
|
| - init_one_comp_unit (&cu, objfile);
|
| - cleanups = make_cleanup (free_stack_comp_unit, &cu);
|
| + /* 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;
|
|
|
| - if (this_cu->debug_types_section)
|
| - sec = this_cu->debug_types_section;
|
| + gdb_assert (tu_group != NULL);
|
| + lh_cu = &tu_group->per_cu;
|
| + }
|
| else
|
| - sec = &dwarf2_per_objfile->info;
|
| - dwarf2_read_section (objfile, sec);
|
| - buffer_size = sec->size;
|
| - buffer = sec->buffer;
|
| - info_ptr = buffer + this_cu->offset;
|
| -
|
| - info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
|
| - buffer, buffer_size,
|
| - abfd,
|
| - this_cu->debug_types_section != NULL);
|
| -
|
| - /* Skip dummy compilation units. */
|
| - if (info_ptr >= buffer + buffer_size
|
| - || peek_abbrev_code (abfd, info_ptr) == 0)
|
| - {
|
| - do_cleanups (cleanups);
|
| - return NULL;
|
| - }
|
| -
|
| - this_cu->cu = &cu;
|
| - cu.per_cu = this_cu;
|
| -
|
| - dwarf2_read_abbrevs (abfd, &cu);
|
| - make_cleanup (dwarf2_free_abbrev_table, &cu);
|
| -
|
| - init_cu_die_reader (&reader_specs, &cu);
|
| - read_full_die (&reader_specs, &comp_unit_die, info_ptr,
|
| - &has_children);
|
| + lh_cu = this_cu;
|
|
|
| lh = NULL;
|
| slot = NULL;
|
| line_offset = 0;
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, &cu);
|
| +
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu);
|
| if (attr)
|
| {
|
| struct quick_file_names find_entry;
|
| @@ -2341,31 +2742,31 @@ dw2_get_file_names (struct objfile *objfile,
|
|
|
| /* We may have already read in this line header (TU line header sharing).
|
| If we have we're done. */
|
| - find_entry.offset = line_offset;
|
| + find_entry.hash.dwo_unit = cu->dwo_unit;
|
| + find_entry.hash.line_offset.sect_off = line_offset;
|
| slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table,
|
| &find_entry, INSERT);
|
| if (*slot != NULL)
|
| {
|
| - do_cleanups (cleanups);
|
| - this_cu->v.quick->file_names = *slot;
|
| - return *slot;
|
| + lh_cu->v.quick->file_names = *slot;
|
| + return;
|
| }
|
|
|
| - lh = dwarf_decode_line_header (line_offset, abfd, &cu);
|
| + lh = dwarf_decode_line_header (line_offset, cu);
|
| }
|
| if (lh == NULL)
|
| {
|
| - do_cleanups (cleanups);
|
| - this_cu->v.quick->no_file_data = 1;
|
| - return NULL;
|
| + lh_cu->v.quick->no_file_data = 1;
|
| + return;
|
| }
|
|
|
| qfn = obstack_alloc (&objfile->objfile_obstack, sizeof (*qfn));
|
| - qfn->offset = line_offset;
|
| + qfn->hash.dwo_unit = cu->dwo_unit;
|
| + qfn->hash.line_offset.sect_off = line_offset;
|
| gdb_assert (slot != NULL);
|
| *slot = qfn;
|
|
|
| - find_file_and_directory (comp_unit_die, &cu, &name, &comp_dir);
|
| + find_file_and_directory (comp_unit_die, cu, &name, &comp_dir);
|
|
|
| qfn->num_file_names = lh->num_file_names;
|
| qfn->file_names = obstack_alloc (&objfile->objfile_obstack,
|
| @@ -2375,10 +2776,44 @@ dw2_get_file_names (struct objfile *objfile,
|
| qfn->real_names = NULL;
|
|
|
| free_line_header (lh);
|
| - do_cleanups (cleanups);
|
|
|
| - this_cu->v.quick->file_names = qfn;
|
| - return qfn;
|
| + lh_cu->v.quick->file_names = qfn;
|
| +}
|
| +
|
| +/* A helper for the "quick" functions which attempts to read the line
|
| + table for THIS_CU. */
|
| +
|
| +static struct quick_file_names *
|
| +dw2_get_file_names (struct objfile *objfile,
|
| + 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));
|
| +
|
| + if (this_cu->v.quick->file_names != NULL)
|
| + return this_cu->v.quick->file_names;
|
| + /* If we know there is no line data, no point in looking again. */
|
| + 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);
|
| +
|
| + if (this_cu->v.quick->no_file_data)
|
| + return NULL;
|
| + return this_cu->v.quick->file_names;
|
| }
|
|
|
| /* A helper for the "quick" functions which computes and caches the
|
| @@ -2405,7 +2840,7 @@ dw2_find_last_source_symtab (struct objfile *objfile)
|
|
|
| dw2_setup (objfile);
|
| index = dwarf2_per_objfile->n_comp_units - 1;
|
| - return dw2_instantiate_symtab (objfile, dw2_get_cu (index));
|
| + return dw2_instantiate_symtab (dw2_get_cu (index));
|
| }
|
|
|
| /* Traversal function for dw2_forget_cached_source_info. */
|
| @@ -2457,7 +2892,7 @@ dw2_map_expand_apply (struct objfile *objfile,
|
|
|
| /* This may expand more than one symtab, and we want to iterate over
|
| all of them. */
|
| - dw2_instantiate_symtab (objfile, per_cu);
|
| + dw2_instantiate_symtab (per_cu);
|
|
|
| return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
|
| objfile->symtabs, last_made);
|
| @@ -2473,16 +2908,18 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| {
|
| int i;
|
| const char *name_basename = lbasename (name);
|
| - int check_basename = name_basename == name;
|
| - struct dwarf2_per_cu_data *base_cu = NULL;
|
| + int name_len = strlen (name);
|
| + int is_abs = IS_ABSOLUTE_PATH (name);
|
|
|
| dw2_setup (objfile);
|
|
|
| + dw2_build_type_unit_groups ();
|
| +
|
| for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_comp_units); ++i)
|
| + + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| {
|
| int j;
|
| - struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| struct quick_file_names *file_data;
|
|
|
| /* We only need to look at symtabs not already expanded. */
|
| @@ -2497,7 +2934,9 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| {
|
| const char *this_name = file_data->file_names[j];
|
|
|
| - if (FILENAME_CMP (name, this_name) == 0)
|
| + if (FILENAME_CMP (name, this_name) == 0
|
| + || (!is_abs && compare_filenames_for_search (this_name,
|
| + name, name_len)))
|
| {
|
| if (dw2_map_expand_apply (objfile, per_cu,
|
| name, full_path, real_path,
|
| @@ -2505,10 +2944,6 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| return 1;
|
| }
|
|
|
| - if (check_basename && ! base_cu
|
| - && FILENAME_CMP (lbasename (this_name), name) == 0)
|
| - base_cu = per_cu;
|
| -
|
| /* Before we invoke realpath, which can get expensive when many
|
| files are involved, do a quick comparison of the basenames. */
|
| if (! basenames_may_differ
|
| @@ -2521,7 +2956,10 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| file_data, j);
|
|
|
| if (this_real_name != NULL
|
| - && FILENAME_CMP (full_path, this_real_name) == 0)
|
| + && (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,
|
| @@ -2536,7 +2974,10 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| file_data, j);
|
|
|
| if (this_real_name != NULL
|
| - && FILENAME_CMP (real_path, this_real_name) == 0)
|
| + && (FILENAME_CMP (real_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,
|
| @@ -2547,14 +2988,6 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
|
| }
|
| }
|
|
|
| - if (base_cu)
|
| - {
|
| - if (dw2_map_expand_apply (objfile, base_cu,
|
| - name, full_path, real_path,
|
| - callback, data))
|
| - return 1;
|
| - }
|
| -
|
| return 0;
|
| }
|
|
|
| @@ -2568,28 +3001,72 @@ dw2_lookup_symbol (struct objfile *objfile, int block_index,
|
| }
|
|
|
| /* A helper function that expands all symtabs that hold an object
|
| - named NAME. */
|
| + named NAME. If WANT_SPECIFIC_BLOCK is non-zero, only look for
|
| + symbols in block BLOCK_KIND. */
|
|
|
| static void
|
| -dw2_do_expand_symtabs_matching (struct objfile *objfile, const char *name)
|
| +dw2_do_expand_symtabs_matching (struct objfile *objfile,
|
| + int want_specific_block,
|
| + enum block_enum block_kind,
|
| + const char *name, domain_enum domain)
|
| {
|
| + struct mapped_index *index;
|
| +
|
| dw2_setup (objfile);
|
|
|
| + index = dwarf2_per_objfile->index_table;
|
| +
|
| /* index_table is NULL if OBJF_READNOW. */
|
| - if (dwarf2_per_objfile->index_table)
|
| + if (index)
|
| {
|
| offset_type *vec;
|
|
|
| - if (find_slot_in_mapped_hash (dwarf2_per_objfile->index_table,
|
| - name, &vec))
|
| + if (find_slot_in_mapped_hash (index, name, &vec))
|
| {
|
| offset_type i, len = MAYBE_SWAP (*vec);
|
| for (i = 0; i < len; ++i)
|
| {
|
| - offset_type cu_index = MAYBE_SWAP (vec[i + 1]);
|
| + 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;
|
| +
|
| + /* 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;
|
| + }
|
| + }
|
|
|
| - dw2_instantiate_symtab (objfile, per_cu);
|
| + dw2_instantiate_symtab (per_cu);
|
| }
|
| }
|
| }
|
| @@ -2600,7 +3077,7 @@ 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, name);
|
| + dw2_do_expand_symtabs_matching (objfile, 1, block_kind, name, domain);
|
| }
|
|
|
| static void
|
| @@ -2611,7 +3088,7 @@ dw2_print_stats (struct objfile *objfile)
|
| dw2_setup (objfile);
|
| count = 0;
|
| for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_comp_units); ++i)
|
| + + dwarf2_per_objfile->n_type_units); ++i)
|
| {
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| @@ -2638,7 +3115,9 @@ static void
|
| dw2_expand_symtabs_for_function (struct objfile *objfile,
|
| const char *func_name)
|
| {
|
| - dw2_do_expand_symtabs_matching (objfile, 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);
|
| }
|
|
|
| static void
|
| @@ -2649,11 +3128,11 @@ dw2_expand_all_symtabs (struct objfile *objfile)
|
| dw2_setup (objfile);
|
|
|
| for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_comp_units); ++i)
|
| + + dwarf2_per_objfile->n_type_units); ++i)
|
| {
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| - dw2_instantiate_symtab (objfile, per_cu);
|
| + dw2_instantiate_symtab (per_cu);
|
| }
|
| }
|
|
|
| @@ -2689,19 +3168,41 @@ dw2_expand_symtabs_with_filename (struct objfile *objfile,
|
| const char *this_name = file_data->file_names[j];
|
| if (FILENAME_CMP (this_name, filename) == 0)
|
| {
|
| - dw2_instantiate_symtab (objfile, per_cu);
|
| + dw2_instantiate_symtab (per_cu);
|
| break;
|
| }
|
| }
|
| }
|
| }
|
|
|
| +/* 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);
|
|
|
| @@ -2710,16 +3211,15 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name)
|
| {
|
| struct symtab *s;
|
|
|
| - ALL_OBJFILE_SYMTABS (objfile, s)
|
| - if (s->primary)
|
| - {
|
| - struct blockvector *bv = BLOCKVECTOR (s);
|
| - const struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
|
| - struct symbol *sym = lookup_block_symbol (block, name, VAR_DOMAIN);
|
| + 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;
|
| - }
|
| + if (sym)
|
| + return sym->symtab->filename;
|
| + }
|
| return NULL;
|
| }
|
|
|
| @@ -2732,13 +3232,15 @@ dw2_find_symbol_file (struct objfile *objfile, const char *name)
|
| 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 (MAYBE_SWAP (vec[1]));
|
| + per_cu = dw2_get_cu (GDB_INDEX_CU_VALUE (MAYBE_SWAP (vec[1])));
|
|
|
| - file_data = dw2_get_file_names (objfile, per_cu);
|
| - if (file_data == NULL)
|
| - return NULL;
|
| + if (per_cu->v.quick->symtab != NULL)
|
| + return per_cu->v.quick->symtab->filename;
|
|
|
| - return file_data->file_names[file_data->num_file_names - 1];
|
| + init_cutu_and_read_dies (per_cu, NULL, 0, 0,
|
| + dw2_get_primary_filename_reader, &filename);
|
| +
|
| + return filename;
|
| }
|
|
|
| static void
|
| @@ -2758,7 +3260,7 @@ static void
|
| dw2_expand_symtabs_matching
|
| (struct objfile *objfile,
|
| int (*file_matcher) (const char *, void *),
|
| - int (*name_matcher) (const struct language_defn *, const char *, void *),
|
| + int (*name_matcher) (const char *, void *),
|
| enum search_domain kind,
|
| void *data)
|
| {
|
| @@ -2774,32 +3276,65 @@ dw2_expand_symtabs_matching
|
| index = dwarf2_per_objfile->index_table;
|
|
|
| if (file_matcher != NULL)
|
| - for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_comp_units); ++i)
|
| - {
|
| - int j;
|
| - struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
| - struct quick_file_names *file_data;
|
| + {
|
| + struct cleanup *cleanup;
|
| + htab_t visited_found, visited_not_found;
|
|
|
| - per_cu->v.quick->mark = 0;
|
| + dw2_build_type_unit_groups ();
|
|
|
| - /* We only need to look at symtabs not already expanded. */
|
| - if (per_cu->v.quick->symtab)
|
| - continue;
|
| + visited_found = htab_create_alloc (10,
|
| + htab_hash_pointer, htab_eq_pointer,
|
| + NULL, xcalloc, xfree);
|
| + cleanup = make_cleanup_htab_delete (visited_found);
|
| + visited_not_found = htab_create_alloc (10,
|
| + htab_hash_pointer, htab_eq_pointer,
|
| + NULL, xcalloc, xfree);
|
| + make_cleanup_htab_delete (visited_not_found);
|
|
|
| - file_data = dw2_get_file_names (objfile, per_cu);
|
| - if (file_data == NULL)
|
| - continue;
|
| + for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| + {
|
| + int j;
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| + struct quick_file_names *file_data;
|
| + void **slot;
|
|
|
| - for (j = 0; j < file_data->num_file_names; ++j)
|
| - {
|
| - if (file_matcher (file_data->file_names[j], data))
|
| - {
|
| - per_cu->v.quick->mark = 1;
|
| - break;
|
| - }
|
| - }
|
| - }
|
| + per_cu->v.quick->mark = 0;
|
| +
|
| + /* We only need to look at symtabs not already expanded. */
|
| + if (per_cu->v.quick->symtab)
|
| + continue;
|
| +
|
| + file_data = dw2_get_file_names (objfile, per_cu);
|
| + if (file_data == NULL)
|
| + continue;
|
| +
|
| + if (htab_find (visited_not_found, file_data) != NULL)
|
| + continue;
|
| + else if (htab_find (visited_found, file_data) != NULL)
|
| + {
|
| + per_cu->v.quick->mark = 1;
|
| + continue;
|
| + }
|
| +
|
| + for (j = 0; j < file_data->num_file_names; ++j)
|
| + {
|
| + if (file_matcher (file_data->file_names[j], data))
|
| + {
|
| + per_cu->v.quick->mark = 1;
|
| + break;
|
| + }
|
| + }
|
| +
|
| + slot = htab_find_slot (per_cu->v.quick->mark
|
| + ? visited_found
|
| + : visited_not_found,
|
| + file_data, INSERT);
|
| + *slot = file_data;
|
| + }
|
| +
|
| + do_cleanups (cleanup);
|
| + }
|
|
|
| for (iter = 0; iter < index->symbol_table_slots; ++iter)
|
| {
|
| @@ -2812,7 +3347,7 @@ dw2_expand_symtabs_matching
|
|
|
| name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
|
|
|
| - if (! (*name_matcher) (current_language, name, data))
|
| + if (! (*name_matcher) (name, data))
|
| continue;
|
|
|
| /* The name was matched, now expand corresponding CUs that were
|
| @@ -2823,14 +3358,73 @@ dw2_expand_symtabs_matching
|
| for (vec_idx = 0; vec_idx < vec_len; ++vec_idx)
|
| {
|
| struct dwarf2_per_cu_data *per_cu;
|
| + offset_type cu_index_and_attrs = MAYBE_SWAP (vec[vec_idx + 1]);
|
| + 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);
|
| +
|
| + /* Don't crash on bad data. */
|
| + if (cu_index >= (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_units))
|
| + continue;
|
|
|
| - per_cu = dw2_get_cu (MAYBE_SWAP (vec[vec_idx + 1]));
|
| + /* Only check the symbol's kind if it has one.
|
| + Indices prior to version 7 don't record it. */
|
| + if (index->version >= 7)
|
| + {
|
| + switch (kind)
|
| + {
|
| + case VARIABLES_DOMAIN:
|
| + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_VARIABLE)
|
| + continue;
|
| + break;
|
| + case FUNCTIONS_DOMAIN:
|
| + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_FUNCTION)
|
| + continue;
|
| + break;
|
| + case TYPES_DOMAIN:
|
| + if (symbol_kind != GDB_INDEX_SYMBOL_KIND_TYPE)
|
| + continue;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| +
|
| + per_cu = dw2_get_cu (cu_index);
|
| if (file_matcher == NULL || per_cu->v.quick->mark)
|
| - dw2_instantiate_symtab (objfile, per_cu);
|
| + dw2_instantiate_symtab (per_cu);
|
| }
|
| }
|
| }
|
|
|
| +/* A helper for dw2_find_pc_sect_symtab which finds the most specific
|
| + symtab. */
|
| +
|
| +static struct symtab *
|
| +recursively_find_pc_sect_symtab (struct symtab *symtab, CORE_ADDR pc)
|
| +{
|
| + int i;
|
| +
|
| + if (BLOCKVECTOR (symtab) != NULL
|
| + && blockvector_contains_pc (BLOCKVECTOR (symtab), pc))
|
| + return symtab;
|
| +
|
| + if (symtab->includes == NULL)
|
| + return NULL;
|
| +
|
| + for (i = 0; symtab->includes[i]; ++i)
|
| + {
|
| + struct symtab *s = symtab->includes[i];
|
| +
|
| + s = recursively_find_pc_sect_symtab (s, pc);
|
| + if (s != NULL)
|
| + return s;
|
| + }
|
| +
|
| + return NULL;
|
| +}
|
| +
|
| static struct symtab *
|
| dw2_find_pc_sect_symtab (struct objfile *objfile,
|
| struct minimal_symbol *msymbol,
|
| @@ -2839,6 +3433,7 @@ dw2_find_pc_sect_symtab (struct objfile *objfile,
|
| int warn_if_readin)
|
| {
|
| struct dwarf2_per_cu_data *data;
|
| + struct symtab *result;
|
|
|
| dw2_setup (objfile);
|
|
|
| @@ -2853,7 +3448,9 @@ dw2_find_pc_sect_symtab (struct objfile *objfile,
|
| warning (_("(Internal error: pc %s in read in CU, but not in symtab.)"),
|
| paddress (get_objfile_arch (objfile), pc));
|
|
|
| - return dw2_instantiate_symtab (objfile, data);
|
| + result = recursively_find_pc_sect_symtab (dw2_instantiate_symtab (data), pc);
|
| + gdb_assert (result != NULL);
|
| + return result;
|
| }
|
|
|
| static void
|
| @@ -2861,15 +3458,37 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
|
| void *data, int need_fullname)
|
| {
|
| int i;
|
| + struct cleanup *cleanup;
|
| + htab_t visited = htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
|
| + NULL, xcalloc, xfree);
|
|
|
| + cleanup = make_cleanup_htab_delete (visited);
|
| dw2_setup (objfile);
|
|
|
| + dw2_build_type_unit_groups ();
|
| +
|
| + /* 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_comp_units); ++i)
|
| + + dwarf2_per_objfile->n_type_units); ++i)
|
| {
|
| - int j;
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
| +
|
| + if (per_cu->v.quick->symtab)
|
| + {
|
| + void **slot = htab_find_slot (visited, per_cu->v.quick->file_names,
|
| + INSERT);
|
| +
|
| + *slot = per_cu->v.quick->file_names;
|
| + }
|
| + }
|
| +
|
| + for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| + + dwarf2_per_objfile->n_type_unit_groups); ++i)
|
| + {
|
| + int j;
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_primary_cu (i);
|
| struct quick_file_names *file_data;
|
| + void **slot;
|
|
|
| /* We only need to look at symtabs not already expanded. */
|
| if (per_cu->v.quick->symtab)
|
| @@ -2879,6 +3498,14 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
|
| if (file_data == NULL)
|
| continue;
|
|
|
| + slot = htab_find_slot (visited, file_data, INSERT);
|
| + if (*slot)
|
| + {
|
| + /* Already visited. */
|
| + continue;
|
| + }
|
| + *slot = file_data;
|
| +
|
| for (j = 0; j < file_data->num_file_names; ++j)
|
| {
|
| const char *this_real_name;
|
| @@ -2890,6 +3517,8 @@ dw2_map_symbol_filenames (struct objfile *objfile, symbol_filename_ftype *fun,
|
| (*fun) (file_data->file_names[j], this_real_name, data);
|
| }
|
| }
|
| +
|
| + do_cleanups (cleanup);
|
| }
|
|
|
| static int
|
| @@ -2935,12 +3564,12 @@ dwarf2_initialize_objfile (struct objfile *objfile)
|
|
|
| dwarf2_per_objfile->using_index = 1;
|
| create_all_comp_units (objfile);
|
| - create_debug_types_hash_table (objfile);
|
| + create_all_type_units (objfile);
|
| dwarf2_per_objfile->quick_file_names_table =
|
| create_quick_file_names_table (dwarf2_per_objfile->n_comp_units);
|
|
|
| for (i = 0; i < (dwarf2_per_objfile->n_comp_units
|
| - + dwarf2_per_objfile->n_type_comp_units); ++i)
|
| + + dwarf2_per_objfile->n_type_units); ++i)
|
| {
|
| struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| @@ -2975,17 +3604,54 @@ dwarf2_build_psymtabs (struct objfile *objfile)
|
| dwarf2_build_psymtabs_hard (objfile);
|
| }
|
|
|
| +/* Return the total length of the CU described by HEADER. */
|
| +
|
| +static unsigned int
|
| +get_cu_length (const struct comp_unit_head *header)
|
| +{
|
| + return header->initial_length_size + header->length;
|
| +}
|
| +
|
| /* Return TRUE if OFFSET is within CU_HEADER. */
|
|
|
| static inline int
|
| -offset_in_cu_p (const struct comp_unit_head *cu_header, unsigned int offset)
|
| +offset_in_cu_p (const struct comp_unit_head *cu_header, sect_offset offset)
|
| +{
|
| + sect_offset bottom = { cu_header->offset.sect_off };
|
| + sect_offset top = { cu_header->offset.sect_off + get_cu_length (cu_header) };
|
| +
|
| + return (offset.sect_off >= bottom.sect_off && offset.sect_off < top.sect_off);
|
| +}
|
| +
|
| +/* Find the base address of the compilation unit for range lists and
|
| + location lists. It will normally be specified by DW_AT_low_pc.
|
| + In DWARF-3 draft 4, the base address could be overridden by
|
| + DW_AT_entry_pc. It's been removed, but GCC still uses this for
|
| + compilation units with discontinuous ranges. */
|
| +
|
| +static void
|
| +dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| - unsigned int bottom = cu_header->offset;
|
| - unsigned int top = (cu_header->offset
|
| - + cu_header->length
|
| - + cu_header->initial_length_size);
|
| + struct attribute *attr;
|
| +
|
| + cu->base_known = 0;
|
| + cu->base_address = 0;
|
|
|
| - return (offset >= bottom && offset < top);
|
| + attr = dwarf2_attr (die, DW_AT_entry_pc, cu);
|
| + if (attr)
|
| + {
|
| + cu->base_address = DW_ADDR (attr);
|
| + cu->base_known = 1;
|
| + }
|
| + else
|
| + {
|
| + attr = dwarf2_attr (die, DW_AT_low_pc, cu);
|
| + if (attr)
|
| + {
|
| + cu->base_address = DW_ADDR (attr);
|
| + cu->base_known = 1;
|
| + }
|
| + }
|
| }
|
|
|
| /* Read in the comp unit header information from the debug_info at info_ptr.
|
| @@ -3005,8 +3671,8 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
|
| info_ptr += bytes_read;
|
| cu_header->version = read_2_bytes (abfd, info_ptr);
|
| info_ptr += 2;
|
| - cu_header->abbrev_offset = read_offset (abfd, info_ptr, cu_header,
|
| - &bytes_read);
|
| + cu_header->abbrev_offset.sect_off = read_offset (abfd, info_ptr, cu_header,
|
| + &bytes_read);
|
| info_ptr += bytes_read;
|
| cu_header->addr_size = read_1_byte (abfd, info_ptr);
|
| info_ptr += 1;
|
| @@ -3019,47 +3685,67 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
|
| return info_ptr;
|
| }
|
|
|
| -/* Read in a CU header and perform some basic error checking. */
|
| +/* 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. */
|
|
|
| -static gdb_byte *
|
| -partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
|
| - gdb_byte *buffer, unsigned int buffer_size,
|
| - bfd *abfd, int is_debug_types_section)
|
| +static void
|
| +error_check_comp_unit_head (struct comp_unit_head *header,
|
| + struct dwarf2_section_info *section,
|
| + struct dwarf2_section_info *abbrev_section)
|
| {
|
| - gdb_byte *beg_of_comp_unit = info_ptr;
|
| -
|
| - header->offset = beg_of_comp_unit - buffer;
|
| -
|
| - info_ptr = read_comp_unit_head (header, info_ptr, abfd);
|
| -
|
| - /* If we're reading a type unit, skip over the signature and
|
| - type_offset fields. */
|
| - if (is_debug_types_section)
|
| - info_ptr += 8 /*signature*/ + header->offset_size;
|
| -
|
| - header->first_die_offset = info_ptr - beg_of_comp_unit;
|
| + bfd *abfd = section->asection->owner;
|
| + const char *filename = bfd_get_filename (abfd);
|
|
|
| if (header->version != 2 && header->version != 3 && header->version != 4)
|
| error (_("Dwarf Error: wrong version in compilation unit header "
|
| "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
|
| - bfd_get_filename (abfd));
|
| + filename);
|
|
|
| - if (header->abbrev_offset
|
| + if (header->abbrev_offset.sect_off
|
| >= dwarf2_section_size (dwarf2_per_objfile->objfile,
|
| &dwarf2_per_objfile->abbrev))
|
| error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
|
| "(offset 0x%lx + 6) [in module %s]"),
|
| - (long) header->abbrev_offset,
|
| - (long) (beg_of_comp_unit - buffer),
|
| - bfd_get_filename (abfd));
|
| + (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
|
| + filename);
|
|
|
| - if (beg_of_comp_unit + header->length + header->initial_length_size
|
| - > buffer + buffer_size)
|
| + /* Cast to unsigned long to use 64-bit arithmetic when possible to
|
| + avoid potential 32-bit overflow. */
|
| + if (((unsigned long) header->offset.sect_off + get_cu_length (header))
|
| + > section->size)
|
| error (_("Dwarf Error: bad length (0x%lx) in compilation unit header "
|
| "(offset 0x%lx + 0) [in module %s]"),
|
| - (long) header->length,
|
| - (long) (beg_of_comp_unit - buffer),
|
| - bfd_get_filename (abfd));
|
| + (long) header->length, (long) header->offset.sect_off,
|
| + filename);
|
| +}
|
| +
|
| +/* Read in a CU/TU header and perform some basic error checking.
|
| + The contents of the header are stored in HEADER.
|
| + The result is a pointer to the start of the first DIE. */
|
| +
|
| +static 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,
|
| + int is_debug_types_section)
|
| +{
|
| + gdb_byte *beg_of_comp_unit = info_ptr;
|
| + bfd *abfd = section->asection->owner;
|
| +
|
| + header->offset.sect_off = beg_of_comp_unit - section->buffer;
|
| +
|
| + info_ptr = read_comp_unit_head (header, info_ptr, abfd);
|
| +
|
| + /* If we're reading a type unit, skip over the signature and
|
| + type_offset fields. */
|
| + if (is_debug_types_section)
|
| + info_ptr += 8 /*signature*/ + header->offset_size;
|
| +
|
| + header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
|
| +
|
| + error_check_comp_unit_head (header, section, abbrev_section);
|
|
|
| return info_ptr;
|
| }
|
| @@ -3068,24 +3754,55 @@ partial_read_comp_unit_head (struct comp_unit_head *header, gdb_byte *info_ptr,
|
| types_ptr. The result is a pointer to one past the end of the header. */
|
|
|
| static gdb_byte *
|
| -read_type_comp_unit_head (struct comp_unit_head *cu_header,
|
| - struct dwarf2_section_info *section,
|
| - ULONGEST *signature,
|
| - gdb_byte *types_ptr, bfd *abfd)
|
| +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,
|
| + ULONGEST *signature,
|
| + cu_offset *type_offset_in_tu)
|
| {
|
| - gdb_byte *initial_types_ptr = types_ptr;
|
| + gdb_byte *beg_of_comp_unit = info_ptr;
|
| + bfd *abfd = section->asection->owner;
|
|
|
| - dwarf2_read_section (dwarf2_per_objfile->objfile, section);
|
| - cu_header->offset = types_ptr - section->buffer;
|
| + header->offset.sect_off = beg_of_comp_unit - section->buffer;
|
| +
|
| + info_ptr = read_comp_unit_head (header, info_ptr, abfd);
|
| +
|
| + /* If we're reading a type unit, skip over the signature and
|
| + type_offset fields. */
|
| + if (signature != NULL)
|
| + *signature = read_8_bytes (abfd, info_ptr);
|
| + info_ptr += 8;
|
| + if (type_offset_in_tu != NULL)
|
| + type_offset_in_tu->cu_off = read_offset_1 (abfd, info_ptr,
|
| + header->offset_size);
|
| + info_ptr += header->offset_size;
|
| +
|
| + header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
|
| +
|
| + error_check_comp_unit_head (header, section, abbrev_section);
|
| +
|
| + return info_ptr;
|
| +}
|
|
|
| - types_ptr = read_comp_unit_head (cu_header, types_ptr, abfd);
|
| +/* Fetch the abbreviation table offset from a comp or type unit header. */
|
|
|
| - *signature = read_8_bytes (abfd, types_ptr);
|
| - types_ptr += 8;
|
| - types_ptr += cu_header->offset_size;
|
| - cu_header->first_die_offset = types_ptr - initial_types_ptr;
|
| +static sect_offset
|
| +read_abbrev_offset (struct dwarf2_section_info *section,
|
| + sect_offset offset)
|
| +{
|
| + bfd *abfd = section->asection->owner;
|
| + gdb_byte *info_ptr;
|
| + unsigned int length, initial_length_size, offset_size;
|
| + sect_offset abbrev_offset;
|
|
|
| - return types_ptr;
|
| + dwarf2_read_section (dwarf2_per_objfile->objfile, section);
|
| + info_ptr = section->buffer + offset.sect_off;
|
| + length = read_initial_length (abfd, info_ptr, &initial_length_size);
|
| + offset_size = initial_length_size == 4 ? 4 : 8;
|
| + info_ptr += initial_length_size + 2 /*version*/;
|
| + abbrev_offset.sect_off = read_offset_1 (abfd, info_ptr, offset_size);
|
| + return abbrev_offset;
|
| }
|
|
|
| /* Allocate a new partial symtab for file named NAME and mark this new
|
| @@ -3127,21 +3844,15 @@ dwarf2_create_include_psymtab (char *name, struct partial_symtab *pst,
|
|
|
| static void
|
| dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
|
| - struct die_info *die,
|
| - struct partial_symtab *pst)
|
| + struct die_info *die,
|
| + struct partial_symtab *pst)
|
| {
|
| - struct objfile *objfile = cu->objfile;
|
| - bfd *abfd = objfile->obfd;
|
| struct line_header *lh = NULL;
|
| struct attribute *attr;
|
|
|
| attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
|
| if (attr)
|
| - {
|
| - unsigned int line_offset = DW_UNSND (attr);
|
| -
|
| - lh = dwarf_decode_line_header (line_offset, abfd, cu);
|
| - }
|
| + lh = dwarf_decode_line_header (DW_UNSND (attr), cu);
|
| if (lh == NULL)
|
| return; /* No linetable, so no includes. */
|
|
|
| @@ -3152,16 +3863,16 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
|
| }
|
|
|
| static hashval_t
|
| -hash_type_signature (const void *item)
|
| +hash_signatured_type (const void *item)
|
| {
|
| - const struct signatured_type *type_sig = item;
|
| + const struct signatured_type *sig_type = item;
|
|
|
| /* This drops the top 32 bits of the signature, but is ok for a hash. */
|
| - return type_sig->signature;
|
| + return sig_type->signature;
|
| }
|
|
|
| static int
|
| -eq_type_signature (const void *item_lhs, const void *item_rhs)
|
| +eq_signatured_type (const void *item_lhs, const void *item_rhs)
|
| {
|
| const struct signatured_type *lhs = item_lhs;
|
| const struct signatured_type *rhs = item_rhs;
|
| @@ -3175,51 +3886,60 @@ static htab_t
|
| allocate_signatured_type_table (struct objfile *objfile)
|
| {
|
| return htab_create_alloc_ex (41,
|
| - hash_type_signature,
|
| - eq_type_signature,
|
| + hash_signatured_type,
|
| + eq_signatured_type,
|
| NULL,
|
| &objfile->objfile_obstack,
|
| hashtab_obstack_allocate,
|
| dummy_obstack_deallocate);
|
| }
|
|
|
| -/* A helper function to add a signatured type CU to a list. */
|
| +/* A helper function to add a signatured type CU to a table. */
|
|
|
| static int
|
| -add_signatured_type_cu_to_list (void **slot, void *datum)
|
| +add_signatured_type_cu_to_table (void **slot, void *datum)
|
| {
|
| struct signatured_type *sigt = *slot;
|
| - struct dwarf2_per_cu_data ***datap = datum;
|
| + struct signatured_type ***datap = datum;
|
|
|
| - **datap = &sigt->per_cu;
|
| + **datap = sigt;
|
| ++*datap;
|
|
|
| return 1;
|
| }
|
|
|
| /* Create the hash table of all entries in the .debug_types section.
|
| - The result is zero if there is an error (e.g. missing .debug_types section),
|
| - otherwise non-zero. */
|
| + 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. */
|
|
|
| -static int
|
| -create_debug_types_hash_table (struct objfile *objfile)
|
| +static htab_t
|
| +create_debug_types_hash_table (struct dwo_file *dwo_file,
|
| + VEC (dwarf2_section_info_def) *types)
|
| {
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| htab_t types_htab = NULL;
|
| - struct dwarf2_per_cu_data **iter;
|
| int ix;
|
| struct dwarf2_section_info *section;
|
| + struct dwarf2_section_info *abbrev_section;
|
|
|
| - if (VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types))
|
| - {
|
| - dwarf2_per_objfile->signatured_types = NULL;
|
| - return 0;
|
| - }
|
| + if (VEC_empty (dwarf2_section_info_def, types))
|
| + return NULL;
|
| +
|
| + abbrev_section = (dwo_file != NULL
|
| + ? &dwo_file->sections.abbrev
|
| + : &dwarf2_per_objfile->abbrev);
|
| +
|
| + 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));
|
|
|
| for (ix = 0;
|
| - VEC_iterate (dwarf2_section_info_def, dwarf2_per_objfile->types,
|
| - ix, section);
|
| + VEC_iterate (dwarf2_section_info_def, types, ix, section);
|
| ++ix)
|
| {
|
| + bfd *abfd;
|
| gdb_byte *info_ptr, *end_ptr;
|
|
|
| dwarf2_read_section (objfile, section);
|
| @@ -3228,110 +3948,161 @@ create_debug_types_hash_table (struct objfile *objfile)
|
| if (info_ptr == NULL)
|
| 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)
|
| - types_htab = allocate_signatured_type_table (objfile);
|
| + {
|
| + if (dwo_file)
|
| + types_htab = allocate_dwo_unit_table (objfile);
|
| + else
|
| + types_htab = allocate_signatured_type_table (objfile);
|
| + }
|
|
|
| - if (dwarf2_die_debug)
|
| - fprintf_unfiltered (gdb_stdlog, "Signatured types:\n");
|
| + /* 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
|
| + header. */
|
|
|
| end_ptr = info_ptr + section->size;
|
| while (info_ptr < end_ptr)
|
| {
|
| - unsigned int offset;
|
| - unsigned int offset_size;
|
| - unsigned int type_offset;
|
| - unsigned int length, initial_length_size;
|
| - unsigned short version;
|
| + sect_offset offset;
|
| + cu_offset type_offset_in_tu;
|
| ULONGEST signature;
|
| - struct signatured_type *type_sig;
|
| + struct signatured_type *sig_type;
|
| + struct dwo_unit *dwo_tu;
|
| void **slot;
|
| gdb_byte *ptr = info_ptr;
|
| + struct comp_unit_head header;
|
| + unsigned int length;
|
|
|
| - offset = ptr - section->buffer;
|
| + offset.sect_off = ptr - section->buffer;
|
|
|
| /* We need to read the type's signature in order to build the hash
|
| - table, but we don't need to read anything else just yet. */
|
| + table, but we don't need anything else just yet. */
|
|
|
| - /* Sanity check to ensure entire cu is present. */
|
| - length = read_initial_length (objfile->obfd, ptr,
|
| - &initial_length_size);
|
| - if (ptr + length + initial_length_size > end_ptr)
|
| - {
|
| - complaint (&symfile_complaints,
|
| - _("debug type entry runs off end "
|
| - "of `.debug_types' section, ignored"));
|
| - break;
|
| - }
|
| + ptr = read_and_check_type_unit_head (&header, section,
|
| + abbrev_section, ptr,
|
| + &signature, &type_offset_in_tu);
|
|
|
| - offset_size = initial_length_size == 4 ? 4 : 8;
|
| - ptr += initial_length_size;
|
| - version = bfd_get_16 (objfile->obfd, ptr);
|
| - ptr += 2;
|
| - ptr += offset_size; /* abbrev offset */
|
| - ptr += 1; /* address size */
|
| - signature = bfd_get_64 (objfile->obfd, ptr);
|
| - ptr += 8;
|
| - type_offset = read_offset_1 (objfile->obfd, ptr, offset_size);
|
| - ptr += offset_size;
|
| + length = get_cu_length (&header);
|
|
|
| /* Skip dummy type units. */
|
| - if (ptr >= end_ptr || peek_abbrev_code (objfile->obfd, ptr) == 0)
|
| + if (ptr >= info_ptr + length
|
| + || peek_abbrev_code (abfd, ptr) == 0)
|
| {
|
| - info_ptr = info_ptr + initial_length_size + length;
|
| + info_ptr += length;
|
| continue;
|
| }
|
|
|
| - type_sig = obstack_alloc (&objfile->objfile_obstack, sizeof (*type_sig));
|
| - memset (type_sig, 0, sizeof (*type_sig));
|
| - type_sig->signature = signature;
|
| - type_sig->type_offset = type_offset;
|
| - type_sig->per_cu.objfile = objfile;
|
| - type_sig->per_cu.debug_types_section = section;
|
| - type_sig->per_cu.offset = offset;
|
| + if (dwo_file)
|
| + {
|
| + sig_type = NULL;
|
| + dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + struct dwo_unit);
|
| + 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->offset = offset;
|
| + dwo_tu->length = length;
|
| + }
|
| + else
|
| + {
|
| + /* N.B.: type_offset is not usable if this type uses a DWO file.
|
| + The real type_offset is in the DWO file. */
|
| + dwo_tu = NULL;
|
| + sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + struct signatured_type);
|
| + sig_type->signature = signature;
|
| + 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.offset = offset;
|
| + sig_type->per_cu.length = length;
|
| + }
|
|
|
| - slot = htab_find_slot (types_htab, type_sig, INSERT);
|
| + slot = htab_find_slot (types_htab,
|
| + dwo_file ? (void*) dwo_tu : (void *) sig_type,
|
| + INSERT);
|
| gdb_assert (slot != NULL);
|
| if (*slot != NULL)
|
| {
|
| - const struct signatured_type *dup_sig = *slot;
|
| + sect_offset dup_offset;
|
| +
|
| + if (dwo_file)
|
| + {
|
| + const struct dwo_unit *dup_tu = *slot;
|
| +
|
| + dup_offset = dup_tu->offset;
|
| + }
|
| + else
|
| + {
|
| + const struct signatured_type *dup_tu = *slot;
|
| +
|
| + dup_offset = dup_tu->per_cu.offset;
|
| + }
|
|
|
| complaint (&symfile_complaints,
|
| _("debug type entry at offset 0x%x is duplicate to the "
|
| "entry at offset 0x%x, signature 0x%s"),
|
| - offset, dup_sig->per_cu.offset,
|
| + offset.sect_off, dup_offset.sect_off,
|
| phex (signature, sizeof (signature)));
|
| - gdb_assert (signature == dup_sig->signature);
|
| }
|
| - *slot = type_sig;
|
| + *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
|
|
|
| - if (dwarf2_die_debug)
|
| + if (dwarf2_read_debug)
|
| fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n",
|
| - offset, phex (signature, sizeof (signature)));
|
| + offset.sect_off,
|
| + phex (signature, sizeof (signature)));
|
|
|
| - info_ptr = info_ptr + initial_length_size + length;
|
| + info_ptr += length;
|
| }
|
| }
|
|
|
| + return types_htab;
|
| +}
|
| +
|
| +/* Create the hash table of all entries in the .debug_types section,
|
| + and initialize all_type_units.
|
| + The result is zero if there is an error (e.g. missing .debug_types section),
|
| + otherwise non-zero. */
|
| +
|
| +static int
|
| +create_all_type_units (struct objfile *objfile)
|
| +{
|
| + htab_t types_htab;
|
| + struct signatured_type **iter;
|
| +
|
| + types_htab = create_debug_types_hash_table (NULL, dwarf2_per_objfile->types);
|
| + if (types_htab == NULL)
|
| + {
|
| + dwarf2_per_objfile->signatured_types = NULL;
|
| + return 0;
|
| + }
|
| +
|
| dwarf2_per_objfile->signatured_types = types_htab;
|
|
|
| - dwarf2_per_objfile->n_type_comp_units = htab_elements (types_htab);
|
| - dwarf2_per_objfile->type_comp_units
|
| + 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_comp_units
|
| - * sizeof (struct dwarf2_per_cu_data *));
|
| - iter = &dwarf2_per_objfile->type_comp_units[0];
|
| - htab_traverse_noresize (types_htab, add_signatured_type_cu_to_list, &iter);
|
| - gdb_assert (iter - &dwarf2_per_objfile->type_comp_units[0]
|
| - == dwarf2_per_objfile->n_type_comp_units);
|
| + 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]
|
| + == dwarf2_per_objfile->n_type_units);
|
|
|
| return 1;
|
| }
|
|
|
| -/* Lookup a signature based type.
|
| - Returns NULL if SIG is not present in the table. */
|
| +/* Lookup a signature based type for DW_FORM_ref_sig8.
|
| + Returns NULL if signature SIG is not present in the table. */
|
|
|
| static struct signatured_type *
|
| -lookup_signatured_type (struct objfile *objfile, ULONGEST sig)
|
| +lookup_signatured_type (ULONGEST sig)
|
| {
|
| struct signatured_type find_entry, *entry;
|
|
|
| @@ -3339,186 +4110,553 @@ lookup_signatured_type (struct objfile *objfile, ULONGEST sig)
|
| {
|
| complaint (&symfile_complaints,
|
| _("missing `.debug_types' section for DW_FORM_ref_sig8 die"));
|
| - return 0;
|
| + return NULL;
|
| }
|
|
|
| find_entry.signature = sig;
|
| entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
|
| return entry;
|
| }
|
| +
|
| +/* Low level DIE reading support. */
|
|
|
| /* Initialize a die_reader_specs struct from a dwarf2_cu struct. */
|
|
|
| static void
|
| init_cu_die_reader (struct die_reader_specs *reader,
|
| - struct dwarf2_cu *cu)
|
| + struct dwarf2_cu *cu,
|
| + struct dwarf2_section_info *section,
|
| + struct dwo_file *dwo_file)
|
| {
|
| - reader->abfd = cu->objfile->obfd;
|
| + gdb_assert (section->readin && section->buffer != NULL);
|
| + reader->abfd = section->asection->owner;
|
| reader->cu = cu;
|
| - if (cu->per_cu->debug_types_section)
|
| + reader->dwo_file = dwo_file;
|
| + reader->die_section = section;
|
| + reader->buffer = section->buffer;
|
| + reader->buffer_end = section->buffer + section->size;
|
| +}
|
| +
|
| +/* Initialize a CU (or TU) and read its DIEs.
|
| + If the CU defers to a DWO file, read the DWO file as well.
|
| +
|
| + ABBREV_TABLE, if non-NULL, is the abbreviation table to use.
|
| + Otherwise the table specified in the comp unit header is read in and used.
|
| + This is an optimization for when we already have the abbrev table.
|
| +
|
| + If USE_EXISTING_CU is non-zero, and THIS_CU->cu is non-NULL, then use it.
|
| + Otherwise, a new CU is allocated with xmalloc.
|
| +
|
| + If KEEP is non-zero, then if we allocated a dwarf2_cu we add it to
|
| + read_in_chain. Otherwise the dwarf2_cu data is freed at the end.
|
| +
|
| + WARNING: If THIS_CU is a "dummy CU" (used as filler by the incremental
|
| + linker) then DIE_READER_FUNC will not get called. */
|
| +
|
| +static void
|
| +init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
|
| + struct abbrev_table *abbrev_table,
|
| + int use_existing_cu, int keep,
|
| + die_reader_func_ftype *die_reader_func,
|
| + void *data)
|
| +{
|
| + 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_cu *cu;
|
| + gdb_byte *begin_info_ptr, *info_ptr;
|
| + struct die_reader_specs reader;
|
| + struct die_info *comp_unit_die;
|
| + int has_children;
|
| + struct attribute *attr;
|
| + struct cleanup *cleanups, *free_cu_cleanup = NULL;
|
| + struct signatured_type *sig_type = NULL;
|
| + 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. */
|
| + int rereading_dwo_cu = 0;
|
| +
|
| + if (dwarf2_die_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
|
| + this_cu->is_debug_types ? "type" : "comp",
|
| + this_cu->offset.sect_off);
|
| +
|
| + if (use_existing_cu)
|
| + gdb_assert (keep);
|
| +
|
| + 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;
|
| +
|
| + if (use_existing_cu && this_cu->cu != NULL)
|
| {
|
| - gdb_assert (cu->per_cu->debug_types_section->readin);
|
| - reader->buffer = cu->per_cu->debug_types_section->buffer;
|
| + cu = this_cu->cu;
|
| +
|
| + /* If this CU is from a DWO file we need to start over, we need to
|
| + refetch the attributes from the skeleton CU.
|
| + This could be optimized by retrieving those attributes from when we
|
| + were here the first time: the previous comp_unit_die was stored in
|
| + comp_unit_obstack. But there's no data yet that we need this
|
| + optimization. */
|
| + if (cu->dwo_unit != NULL)
|
| + rereading_dwo_cu = 1;
|
| }
|
| else
|
| {
|
| - gdb_assert (dwarf2_per_objfile->info.readin);
|
| - reader->buffer = dwarf2_per_objfile->info.buffer;
|
| + /* If !use_existing_cu, this_cu->cu must be 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);
|
| }
|
| -}
|
|
|
| -/* Find the base address of the compilation unit for range lists and
|
| - location lists. It will normally be specified by DW_AT_low_pc.
|
| - In DWARF-3 draft 4, the base address could be overridden by
|
| - DW_AT_entry_pc. It's been removed, but GCC still uses this for
|
| - compilation units with discontinuous ranges. */
|
| + 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. */
|
| + info_ptr += cu->header.first_die_offset.cu_off;
|
| + }
|
| + else
|
| + {
|
| + if (this_cu->is_debug_types)
|
| + {
|
| + ULONGEST signature;
|
| + cu_offset type_offset_in_tu;
|
| +
|
| + info_ptr = read_and_check_type_unit_head (&cu->header, section,
|
| + abbrev_section, info_ptr,
|
| + &signature,
|
| + &type_offset_in_tu);
|
| +
|
| + /* Since per_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;
|
| + gdb_assert (sig_type->signature == signature);
|
| + gdb_assert (sig_type->type_offset_in_tu.cu_off
|
| + == type_offset_in_tu.cu_off);
|
| + gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
|
| +
|
| + /* LENGTH has not been set yet for type units if we're
|
| + using .gdb_index. */
|
| + this_cu->length = get_cu_length (&cu->header);
|
| +
|
| + /* Establish the type offset that can be used to lookup the type. */
|
| + sig_type->type_offset_in_section.sect_off =
|
| + this_cu->offset.sect_off + sig_type->type_offset_in_tu.cu_off;
|
| + }
|
| + else
|
| + {
|
| + info_ptr = read_and_check_comp_unit_head (&cu->header, section,
|
| + abbrev_section,
|
| + info_ptr, 0);
|
|
|
| -static void
|
| -dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu)
|
| -{
|
| - struct attribute *attr;
|
| + gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
|
| + gdb_assert (this_cu->length == get_cu_length (&cu->header));
|
| + }
|
| + }
|
|
|
| - cu->base_known = 0;
|
| - cu->base_address = 0;
|
| + /* Skip dummy compilation units. */
|
| + if (info_ptr >= begin_info_ptr + this_cu->length
|
| + || peek_abbrev_code (abfd, info_ptr) == 0)
|
| + {
|
| + do_cleanups (cleanups);
|
| + return;
|
| + }
|
|
|
| - attr = dwarf2_attr (die, DW_AT_entry_pc, cu);
|
| - if (attr)
|
| + /* If we don't have them yet, read the abbrevs for this compilation unit.
|
| + And if we need to read them now, make sure they're freed when we're
|
| + done. Note that it's important that if the CU had an abbrev table
|
| + on entry we don't free it when we're done: Somewhere up the call stack
|
| + it may be in use. */
|
| + if (abbrev_table != NULL)
|
| {
|
| - cu->base_address = DW_ADDR (attr);
|
| - cu->base_known = 1;
|
| + gdb_assert (cu->abbrev_table == NULL);
|
| + gdb_assert (cu->header.abbrev_offset.sect_off
|
| + == abbrev_table->offset.sect_off);
|
| + cu->abbrev_table = abbrev_table;
|
| }
|
| - else
|
| + else if (cu->abbrev_table == NULL)
|
| {
|
| - attr = dwarf2_attr (die, DW_AT_low_pc, cu);
|
| + dwarf2_read_abbrevs (cu, abbrev_section);
|
| + make_cleanup (dwarf2_free_abbrev_table, cu);
|
| + }
|
| + else if (rereading_dwo_cu)
|
| + {
|
| + dwarf2_free_abbrev_table (cu);
|
| + dwarf2_read_abbrevs (cu, abbrev_section);
|
| + }
|
| +
|
| + /* Read the top level CU/TU die. */
|
| + 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. */
|
| + 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;
|
| +
|
| + 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)
|
| {
|
| - cu->base_address = DW_ADDR (attr);
|
| - cu->base_known = 1;
|
| + 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));
|
| + }
|
| +
|
| + /* Discard the original CU's abbrev table, and read the DWO's. */
|
| + if (abbrev_table == NULL)
|
| + {
|
| + dwarf2_free_abbrev_table (cu);
|
| + dwarf2_read_abbrevs (cu, dwo_abbrev_section);
|
| + }
|
| + 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;
|
| + }
|
| + }
|
| +
|
| + die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
|
| +
|
| + if (free_cu_cleanup != NULL)
|
| + {
|
| + 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);
|
| }
|
|
|
| -/* Subroutine of process_type_comp_unit and dwarf2_build_psymtabs_hard
|
| - to combine the common parts.
|
| - Process a compilation unit for a psymtab.
|
| - BUFFER is a pointer to the beginning of the dwarf section buffer,
|
| - either .debug_info or debug_types.
|
| - INFO_PTR is a pointer to the start of the CU.
|
| - Returns a pointer to the next 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).
|
|
|
| -static gdb_byte *
|
| -process_psymtab_comp_unit (struct objfile *objfile,
|
| - struct dwarf2_per_cu_data *this_cu,
|
| - gdb_byte *buffer, gdb_byte *info_ptr,
|
| - unsigned int buffer_size)
|
| + The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
|
| + THIS_CU->is_debug_types, but nothing else.
|
| +
|
| + We fill in THIS_CU->length.
|
| +
|
| + WARNING: If THIS_CU is a "dummy CU" (used as filler by the incremental
|
| + linker) then DIE_READER_FUNC will not get called.
|
| +
|
| + THIS_CU->cu is always freed when done.
|
| + This is done in order to not leave THIS_CU->cu in a state where we have
|
| + to care whether it refers to the "main" CU or the DWO CU. */
|
| +
|
| +static void
|
| +init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu,
|
| + struct dwarf2_section_info *abbrev_section,
|
| + struct dwo_file *dwo_file,
|
| + die_reader_func_ftype *die_reader_func,
|
| + void *data)
|
| {
|
| - bfd *abfd = objfile->obfd;
|
| - gdb_byte *beg_of_comp_unit = info_ptr;
|
| - struct die_info *comp_unit_die;
|
| - struct partial_symtab *pst;
|
| - CORE_ADDR baseaddr;
|
| - struct cleanup *back_to_inner;
|
| + 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_cu cu;
|
| - int has_children, has_pc_info;
|
| - struct attribute *attr;
|
| - CORE_ADDR best_lowpc = 0, best_highpc = 0;
|
| - struct die_reader_specs reader_specs;
|
| - const char *filename;
|
| + gdb_byte *begin_info_ptr, *info_ptr;
|
| + struct die_reader_specs reader;
|
| + struct cleanup *cleanups;
|
| + struct die_info *comp_unit_die;
|
| + int has_children;
|
| +
|
| + if (dwarf2_die_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
|
| + this_cu->is_debug_types ? "type" : "comp",
|
| + this_cu->offset.sect_off);
|
| +
|
| + gdb_assert (this_cu->cu == NULL);
|
| +
|
| + /* This is cheap if the section is already read in. */
|
| + dwarf2_read_section (objfile, section);
|
| +
|
| + init_one_comp_unit (&cu, this_cu);
|
| +
|
| + cleanups = make_cleanup (free_stack_comp_unit, &cu);
|
|
|
| - init_one_comp_unit (&cu, objfile);
|
| - back_to_inner = make_cleanup (free_stack_comp_unit, &cu);
|
| + begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
|
| + info_ptr = read_and_check_comp_unit_head (&cu.header, section,
|
| + abbrev_section, info_ptr,
|
| + this_cu->is_debug_types);
|
|
|
| - info_ptr = partial_read_comp_unit_head (&cu.header, info_ptr,
|
| - buffer, buffer_size,
|
| - abfd,
|
| - this_cu->debug_types_section != NULL);
|
| + this_cu->length = get_cu_length (&cu.header);
|
|
|
| /* Skip dummy compilation units. */
|
| - if (info_ptr >= buffer + buffer_size
|
| + if (info_ptr >= begin_info_ptr + this_cu->length
|
| || peek_abbrev_code (abfd, info_ptr) == 0)
|
| {
|
| - info_ptr = (beg_of_comp_unit + cu.header.length
|
| - + cu.header.initial_length_size);
|
| - do_cleanups (back_to_inner);
|
| - return info_ptr;
|
| + do_cleanups (cleanups);
|
| + return;
|
| }
|
|
|
| - cu.list_in_scope = &file_symbols;
|
| + dwarf2_read_abbrevs (&cu, abbrev_section);
|
| + make_cleanup (dwarf2_free_abbrev_table, &cu);
|
| +
|
| + init_cu_die_reader (&reader, &cu, section, dwo_file);
|
| + info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
|
|
|
| - /* 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->cu);
|
| + die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
|
|
|
| - /* Note that this is a pointer to our stack frame, being
|
| - added to a global data structure. It will be cleaned up
|
| - in free_stack_comp_unit when we finish with this
|
| - compilation unit. */
|
| - this_cu->cu = &cu;
|
| - cu.per_cu = this_cu;
|
| + do_cleanups (cleanups);
|
| +}
|
|
|
| - /* Read the abbrevs for this compilation unit into a table. */
|
| - dwarf2_read_abbrevs (abfd, &cu);
|
| - make_cleanup (dwarf2_free_abbrev_table, &cu);
|
| +/* Read a CU/TU, except that this does not look for DW_AT_GNU_dwo_name and
|
| + does not lookup the specified DWO file.
|
| + This cannot be used to read DWO files.
|
|
|
| - /* Read the compilation unit die. */
|
| - init_cu_die_reader (&reader_specs, &cu);
|
| - info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
|
| - &has_children);
|
| + THIS_CU->cu is always freed when done.
|
| + This is done in order to not leave THIS_CU->cu in a state where we have
|
| + to care whether it refers to the "main" CU or the DWO CU.
|
| + We can revisit this if the data shows there's a performance issue. */
|
|
|
| - if (this_cu->debug_types_section)
|
| - {
|
| - /* LENGTH has not been set yet for type units. */
|
| - gdb_assert (this_cu->offset == cu.header.offset);
|
| - this_cu->length = cu.header.length + cu.header.initial_length_size;
|
| - }
|
| - else if (comp_unit_die->tag == DW_TAG_partial_unit)
|
| - {
|
| - info_ptr = (beg_of_comp_unit + cu.header.length
|
| - + cu.header.initial_length_size);
|
| - do_cleanups (back_to_inner);
|
| - return info_ptr;
|
| - }
|
| +static void
|
| +init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu,
|
| + die_reader_func_ftype *die_reader_func,
|
| + void *data)
|
| +{
|
| + init_cutu_and_read_dies_no_follow (this_cu,
|
| + &dwarf2_per_objfile->abbrev,
|
| + NULL,
|
| + die_reader_func, data);
|
| +}
|
| +
|
| +/* 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);
|
|
|
| - prepare_one_comp_unit (&cu, comp_unit_die);
|
| + cu->list_in_scope = &file_symbols;
|
|
|
| /* Allocate a new partial symbol table structure. */
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_name, &cu);
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu);
|
| if (attr == NULL || !DW_STRING (attr))
|
| filename = "";
|
| else
|
| filename = DW_STRING (attr);
|
| - pst = start_psymtab_common (objfile, objfile->section_offsets,
|
| - filename,
|
| - /* TEXTLOW and TEXTHIGH are set below. */
|
| - 0,
|
| - objfile->global_psymbols.next,
|
| - objfile->static_psymbols.next);
|
| - pst->psymtabs_addrmap_supported = 1;
|
|
|
| - attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, &cu);
|
| + 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);
|
|
|
| - pst->read_symtab_private = this_cu;
|
| -
|
| baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
|
|
| - /* Store the function that reads in the rest of the symbol table. */
|
| - pst->read_symtab = dwarf2_psymtab_to_symtab;
|
| -
|
| - this_cu->v.psymtab = pst;
|
| -
|
| - dwarf2_find_base_address (comp_unit_die, &cu);
|
| + 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);
|
| + &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. */
|
| @@ -3537,10 +4675,10 @@ process_psymtab_comp_unit (struct objfile *objfile,
|
| lowpc = ((CORE_ADDR) -1);
|
| highpc = ((CORE_ADDR) 0);
|
|
|
| - first_die = load_partial_dies (abfd, buffer, info_ptr, 1, &cu);
|
| + first_die = load_partial_dies (reader, info_ptr, 1);
|
|
|
| scan_partial_symbols (first_die, &lowpc, &highpc,
|
| - ! has_pc_info, &cu);
|
| + ! has_pc_info, cu);
|
|
|
| /* If we didn't find a lowpc, set it to highpc to avoid
|
| complaints from `maint check'. */
|
| @@ -3564,44 +4702,462 @@ process_psymtab_comp_unit (struct objfile *objfile,
|
| (objfile->static_psymbols.list + pst->statics_offset);
|
| sort_pst_symbols (pst);
|
|
|
| - info_ptr = (beg_of_comp_unit + cu.header.length
|
| - + cu.header.initial_length_size);
|
| -
|
| - if (this_cu->debug_types_section)
|
| + if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->s.imported_symtabs))
|
| {
|
| - /* It's not clear we want to do anything with stmt lists here.
|
| - Waiting to see what gcc ultimately does. */
|
| + 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);
|
| }
|
| - else
|
| +
|
| + /* 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)
|
| {
|
| - /* 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);
|
| + 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);
|
| }
|
| +}
|
|
|
| - do_cleanups (back_to_inner);
|
| +/* Subroutine of dwarf2_build_psymtabs_hard to simplify it.
|
| + Process compilation unit THIS_CU for a psymtab. */
|
|
|
| - return info_ptr;
|
| +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 ();
|
| }
|
|
|
| -/* Traversal function for htab_traverse_noresize.
|
| - Process one .debug_types comp-unit. */
|
| +static hashval_t
|
| +hash_type_unit_group (const void *item)
|
| +{
|
| + const struct type_unit_group *tu_group = item;
|
| +
|
| + return hash_stmt_list_entry (&tu_group->hash);
|
| +}
|
|
|
| static int
|
| -process_type_comp_unit (void **slot, void *info)
|
| +eq_type_unit_group (const void *item_lhs, const void *item_rhs)
|
| {
|
| - struct signatured_type *entry = (struct signatured_type *) *slot;
|
| - struct objfile *objfile = (struct objfile *) info;
|
| - struct dwarf2_per_cu_data *this_cu;
|
| + const struct type_unit_group *lhs = item_lhs;
|
| + const struct type_unit_group *rhs = item_rhs;
|
| +
|
| + return eq_stmt_list_entry (&lhs->hash, &rhs->hash);
|
| +}
|
| +
|
| +/* Allocate a hash table for type unit groups. */
|
| +
|
| +static htab_t
|
| +allocate_type_unit_groups_table (void)
|
| +{
|
| + return htab_create_alloc_ex (3,
|
| + hash_type_unit_group,
|
| + eq_type_unit_group,
|
| + NULL,
|
| + &dwarf2_per_objfile->objfile->objfile_obstack,
|
| + hashtab_obstack_allocate,
|
| + dummy_obstack_deallocate);
|
| +}
|
| +
|
| +/* Type units that don't have DW_AT_stmt_list are grouped into their own
|
| + partial symtabs. We combine several TUs per psymtab to not let the size
|
| + of any one psymtab grow too big. */
|
| +#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB (1 << 31)
|
| +#define NO_STMT_LIST_TYPE_UNIT_PSYMTAB_SIZE 10
|
| +
|
| +/* Helper routine for get_type_unit_group.
|
| + Create the type_unit_group object used to hold one or more TUs. */
|
| +
|
| +static struct type_unit_group *
|
| +create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_per_cu_data *per_cu;
|
| + struct type_unit_group *tu_group;
|
| +
|
| + tu_group = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + 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
|
| + {
|
| + unsigned int line_offset = line_offset_struct.sect_off;
|
| + struct partial_symtab *pst;
|
| + char *name;
|
| +
|
| + /* Give the symtab a useful name for debug purposes. */
|
| + if ((line_offset & NO_STMT_LIST_TYPE_UNIT_PSYMTAB) != 0)
|
| + name = xstrprintf ("<type_units_%d>",
|
| + (line_offset & ~NO_STMT_LIST_TYPE_UNIT_PSYMTAB));
|
| + else
|
| + name = xstrprintf ("<type_units_at_0x%x>", line_offset);
|
| +
|
| + pst = create_partial_symtab (per_cu, name);
|
| + pst->anonymous = 1;
|
| +
|
| + xfree (name);
|
| + }
|
| +
|
| + tu_group->hash.dwo_unit = cu->dwo_unit;
|
| + tu_group->hash.line_offset = line_offset_struct;
|
| +
|
| + return tu_group;
|
| +}
|
| +
|
| +/* Look up the type_unit_group for type unit CU, and create it if necessary.
|
| + 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)
|
| +{
|
| + struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
|
| + struct type_unit_group *tu_group;
|
| + void **slot;
|
| + unsigned int line_offset;
|
| + struct type_unit_group type_unit_group_for_lookup;
|
| +
|
| + if (dwarf2_per_objfile->type_unit_groups == NULL)
|
| + {
|
| + dwarf2_per_objfile->type_unit_groups =
|
| + allocate_type_unit_groups_table ();
|
| + }
|
| +
|
| + /* Do we need to create a new group, or can we use an existing one? */
|
| +
|
| + if (stmt_list)
|
| + {
|
| + line_offset = DW_UNSND (stmt_list);
|
| + ++tu_stats->nr_symtab_sharers;
|
| + }
|
| + else
|
| + {
|
| + /* Ugh, no stmt_list. Rare, but we have to handle it.
|
| + We can do various things here like create one group per TU or
|
| + spread them over multiple groups to split up the expansion work.
|
| + To avoid worst case scenarios (too many groups or too large groups)
|
| + we, umm, group them in bunches. */
|
| + line_offset = (NO_STMT_LIST_TYPE_UNIT_PSYMTAB
|
| + | (tu_stats->nr_stmt_less_type_units
|
| + / NO_STMT_LIST_TYPE_UNIT_PSYMTAB_SIZE));
|
| + ++tu_stats->nr_stmt_less_type_units;
|
| + }
|
| +
|
| + type_unit_group_for_lookup.hash.dwo_unit = cu->dwo_unit;
|
| + type_unit_group_for_lookup.hash.line_offset.sect_off = line_offset;
|
| + slot = htab_find_slot (dwarf2_per_objfile->type_unit_groups,
|
| + &type_unit_group_for_lookup, INSERT);
|
| + if (*slot != NULL)
|
| + {
|
| + tu_group = *slot;
|
| + gdb_assert (tu_group != NULL);
|
| + }
|
| + else
|
| + {
|
| + sect_offset line_offset_struct;
|
| +
|
| + line_offset_struct.sect_off = line_offset;
|
| + tu_group = create_type_unit_group (cu, line_offset_struct);
|
| + *slot = tu_group;
|
| + ++tu_stats->nr_symtabs;
|
| + }
|
| +
|
| + return tu_group;
|
| +}
|
| +
|
| +/* Struct used to sort TUs by their abbreviation table offset. */
|
| +
|
| +struct tu_abbrev_offset
|
| +{
|
| + struct signatured_type *sig_type;
|
| + sect_offset abbrev_offset;
|
| +};
|
| +
|
| +/* Helper routine for build_type_unit_groups, passed to qsort. */
|
| +
|
| +static int
|
| +sort_tu_by_abbrev_offset (const void *ap, const void *bp)
|
| +{
|
| + const struct tu_abbrev_offset * const *a = ap;
|
| + const struct tu_abbrev_offset * const *b = bp;
|
| + unsigned int aoff = (*a)->abbrev_offset.sect_off;
|
| + unsigned int boff = (*b)->abbrev_offset.sect_off;
|
| +
|
| + return (aoff > boff) - (aoff < boff);
|
| +}
|
| +
|
| +/* A helper function to add a type_unit_group to a table. */
|
| +
|
| +static int
|
| +add_type_unit_group_to_table (void **slot, void *datum)
|
| +{
|
| + struct type_unit_group *tu_group = *slot;
|
| + struct type_unit_group ***datap = datum;
|
| +
|
| + **datap = tu_group;
|
| + ++*datap;
|
| +
|
| + return 1;
|
| +}
|
| +
|
| +/* Efficiently read all the type units, calling init_cutu_and_read_dies on
|
| + each one passing FUNC,DATA.
|
| +
|
| + The efficiency is because we sort TUs by the abbrev table they use and
|
| + only read each abbrev table once. In one program there are 200K TUs
|
| + sharing 8K abbrev tables.
|
| +
|
| + The main purpose of this function is to support building the
|
| + dwarf2_per_objfile->type_unit_groups table.
|
| + TUs typically share the DW_AT_stmt_list of the CU they came from, so we
|
| + can collapse the search space by grouping them by stmt_list.
|
| + The savings can be significant, in the same program from above the 200K TUs
|
| + share 8K stmt_list tables.
|
| +
|
| + FUNC is expected to call get_type_unit_group, which will create the
|
| + struct type_unit_group if necessary and add it to
|
| + dwarf2_per_objfile->type_unit_groups. */
|
| +
|
| +static void
|
| +build_type_unit_groups (die_reader_func_ftype *func, void *data)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
|
| + struct cleanup *cleanups;
|
| + struct abbrev_table *abbrev_table;
|
| + sect_offset abbrev_offset;
|
| + struct tu_abbrev_offset *sorted_by_abbrev;
|
| + struct type_unit_group **iter;
|
| + int i;
|
| +
|
| + /* It's up to the caller to not call us multiple times. */
|
| + gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
|
| +
|
| + if (dwarf2_per_objfile->n_type_units == 0)
|
| + return;
|
| +
|
| + /* TUs typically share abbrev tables, and there can be way more TUs than
|
| + abbrev tables. Sort by abbrev table to reduce the number of times we
|
| + read each abbrev table in.
|
| + Alternatives are to punt or to maintain a cache of abbrev tables.
|
| + This is simpler and efficient enough for now.
|
| +
|
| + Later we group TUs by their DW_AT_stmt_list value (as this defines the
|
| + symtab to use). Typically TUs with the same abbrev offset have the same
|
| + stmt_list value too so in practice this should work well.
|
| +
|
| + The basic algorithm here is:
|
| +
|
| + sort TUs by abbrev table
|
| + for each TU with same abbrev table:
|
| + read abbrev table if first user
|
| + read TU top level DIE
|
| + [IWBN if DWO skeletons had DW_AT_stmt_list]
|
| + call FUNC */
|
| +
|
| + if (dwarf2_read_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
|
| +
|
| + /* Sort in a separate table to maintain the order of all_type_units
|
| + for .gdb_index: TU indices directly index all_type_units. */
|
| + sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
|
| + dwarf2_per_objfile->n_type_units);
|
| + for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
|
| + {
|
| + struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
|
| +
|
| + 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,
|
| + sig_type->per_cu.offset);
|
| + }
|
| + cleanups = make_cleanup (xfree, sorted_by_abbrev);
|
| + qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
|
| + sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
|
| +
|
| + /* Note: In the .gdb_index case, get_type_unit_group may have already been
|
| + called any number of times, so we don't reset tu_stats here. */
|
| +
|
| + abbrev_offset.sect_off = ~(unsigned) 0;
|
| + abbrev_table = NULL;
|
| + make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
|
| +
|
| + for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
|
| + {
|
| + const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
|
| +
|
| + /* Switch to the next abbrev table if necessary. */
|
| + if (abbrev_table == NULL
|
| + || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
|
| + {
|
| + if (abbrev_table != NULL)
|
| + {
|
| + abbrev_table_free (abbrev_table);
|
| + /* Reset to NULL in case abbrev_table_read_table throws
|
| + an error: abbrev_table_free_cleanup will get called. */
|
| + abbrev_table = NULL;
|
| + }
|
| + abbrev_offset = tu->abbrev_offset;
|
| + abbrev_table =
|
| + abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
|
| + abbrev_offset);
|
| + ++tu_stats->nr_uniq_abbrev_tables;
|
| + }
|
| +
|
| + init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
|
| + func, data);
|
| + }
|
| +
|
| + /* 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 =
|
| + htab_elements (dwarf2_per_objfile->type_unit_groups);
|
| + dwarf2_per_objfile->all_type_unit_groups =
|
| + obstack_alloc (&objfile->objfile_obstack,
|
| + dwarf2_per_objfile->n_type_unit_groups
|
| + * sizeof (struct type_unit_group *));
|
| + iter = &dwarf2_per_objfile->all_type_unit_groups[0];
|
| + htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
|
| + add_type_unit_group_to_table, &iter);
|
| + gdb_assert (iter - &dwarf2_per_objfile->all_type_unit_groups[0]
|
| + == dwarf2_per_objfile->n_type_unit_groups);
|
| +
|
| + do_cleanups (cleanups);
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Done building type unit groups:\n");
|
| + fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
|
| + dwarf2_per_objfile->n_type_units);
|
| + fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
|
| + tu_stats->nr_uniq_abbrev_tables);
|
| + fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
|
| + tu_stats->nr_symtabs);
|
| + fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
|
| + tu_stats->nr_symtab_sharers);
|
| + fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
|
| + tu_stats->nr_stmt_less_type_units);
|
| + }
|
| +}
|
| +
|
| +/* Reader function for build_type_psymtabs. */
|
| +
|
| +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)
|
| +{
|
| + 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 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;
|
| +
|
| + 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 (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 (dwarf2_per_cu_ptr, tu_group->t.tus);
|
| + struct dwarf2_per_cu_data *iter;
|
| + int i;
|
|
|
| - this_cu = &entry->per_cu;
|
| + gdb_assert (len > 0);
|
|
|
| - gdb_assert (this_cu->debug_types_section->readin);
|
| - process_psymtab_comp_unit (objfile, this_cu,
|
| - this_cu->debug_types_section->buffer,
|
| - (this_cu->debug_types_section->buffer
|
| - + this_cu->offset),
|
| - this_cu->debug_types_section->size);
|
| + 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;
|
| + }
|
| +
|
| + VEC_free (dwarf2_per_cu_ptr, tu_group->t.tus);
|
|
|
| return 1;
|
| }
|
| @@ -3612,11 +5168,14 @@ process_type_comp_unit (void **slot, void *info)
|
| static void
|
| build_type_psymtabs (struct objfile *objfile)
|
| {
|
| - if (! create_debug_types_hash_table (objfile))
|
| + if (! create_all_type_units (objfile))
|
| return;
|
|
|
| - htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
|
| - process_type_comp_unit, objfile);
|
| + build_type_unit_groups (build_type_psymtabs_reader, NULL);
|
| +
|
| + /* Now that all TUs have been processed we can fill in the dependencies. */
|
| + htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
|
| + build_type_psymtab_dependencies, NULL);
|
| }
|
|
|
| /* A cleanup function that clears objfile's psymtabs_addrmap field. */
|
| @@ -3629,20 +5188,47 @@ psymtabs_addrmap_cleanup (void *o)
|
| objfile->psymtabs_addrmap = NULL;
|
| }
|
|
|
| +/* Compute the 'user' field for each psymtab in OBJFILE. */
|
| +
|
| +static void
|
| +set_partial_user (struct objfile *objfile)
|
| +{
|
| + int i;
|
| +
|
| + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
| + struct partial_symtab *pst = per_cu->v.psymtab;
|
| + int j;
|
| +
|
| + for (j = 0; j < pst->number_of_dependencies; ++j)
|
| + {
|
| + /* Set the 'user' field only if it is not already set. */
|
| + if (pst->dependencies[j]->user == NULL)
|
| + pst->dependencies[j]->user = pst;
|
| + }
|
| + }
|
| +}
|
| +
|
| /* Build the partial symbol table by doing a quick pass through the
|
| .debug_info and .debug_abbrev sections. */
|
|
|
| static void
|
| dwarf2_build_psymtabs_hard (struct objfile *objfile)
|
| {
|
| - gdb_byte *info_ptr;
|
| struct cleanup *back_to, *addrmap_cleanup;
|
| struct obstack temp_obstack;
|
| + int i;
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Building psymtabs of objfile %s ...\n",
|
| + objfile->name);
|
| + }
|
|
|
| dwarf2_per_objfile->reading_partial_symbols = 1;
|
|
|
| dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
|
| - info_ptr = dwarf2_per_objfile->info.buffer;
|
|
|
| /* Any cached compilation units will be linked by the per-objfile
|
| read_in_chain. Make sure to free them when we're done. */
|
| @@ -3659,132 +5245,58 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile)
|
| objfile->psymtabs_addrmap = addrmap_create_mutable (&temp_obstack);
|
| addrmap_cleanup = make_cleanup (psymtabs_addrmap_cleanup, objfile);
|
|
|
| - /* Since the objects we're extracting from .debug_info vary in
|
| - length, only the individual functions to extract them (like
|
| - read_comp_unit_head and load_partial_die) can really know whether
|
| - the buffer is large enough to hold another complete object.
|
| -
|
| - At the moment, they don't actually check that. If .debug_info
|
| - holds just one extra byte after the last compilation unit's dies,
|
| - then read_comp_unit_head will happily read off the end of the
|
| - buffer. read_partial_die is similarly casual. Those functions
|
| - should be fixed.
|
| -
|
| - For this loop condition, simply checking whether there's any data
|
| - left at all should be sufficient. */
|
| -
|
| - while (info_ptr < (dwarf2_per_objfile->info.buffer
|
| - + dwarf2_per_objfile->info.size))
|
| + for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
|
| {
|
| - struct dwarf2_per_cu_data *this_cu;
|
| -
|
| - this_cu = dwarf2_find_comp_unit (info_ptr
|
| - - dwarf2_per_objfile->info.buffer,
|
| - objfile);
|
| + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i);
|
|
|
| - info_ptr = process_psymtab_comp_unit (objfile, this_cu,
|
| - dwarf2_per_objfile->info.buffer,
|
| - info_ptr,
|
| - dwarf2_per_objfile->info.size);
|
| + process_psymtab_comp_unit (per_cu, 0);
|
| }
|
|
|
| + set_partial_user (objfile);
|
| +
|
| objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
|
| &objfile->objfile_obstack);
|
| discard_cleanups (addrmap_cleanup);
|
|
|
| do_cleanups (back_to);
|
| +
|
| + if (dwarf2_read_debug)
|
| + fprintf_unfiltered (gdb_stdlog, "Done building psymtabs of %s\n",
|
| + objfile->name);
|
| }
|
|
|
| -/* Load the partial DIEs for a secondary CU into memory. */
|
| +/* die_reader_func for load_partial_comp_unit. */
|
|
|
| static void
|
| -load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| - struct objfile *objfile)
|
| +load_partial_comp_unit_reader (const struct die_reader_specs *reader,
|
| + gdb_byte *info_ptr,
|
| + struct die_info *comp_unit_die,
|
| + int has_children,
|
| + void *data)
|
| {
|
| - bfd *abfd = objfile->obfd;
|
| - gdb_byte *info_ptr;
|
| - struct die_info *comp_unit_die;
|
| - struct dwarf2_cu *cu;
|
| - struct cleanup *free_abbrevs_cleanup, *free_cu_cleanup = NULL;
|
| - int has_children;
|
| - struct die_reader_specs reader_specs;
|
| - int read_cu = 0;
|
| -
|
| - gdb_assert (! this_cu->debug_types_section);
|
| -
|
| - gdb_assert (dwarf2_per_objfile->info.readin);
|
| - info_ptr = dwarf2_per_objfile->info.buffer + this_cu->offset;
|
| -
|
| - if (this_cu->cu == NULL)
|
| - {
|
| - cu = xmalloc (sizeof (*cu));
|
| - init_one_comp_unit (cu, objfile);
|
| -
|
| - read_cu = 1;
|
| -
|
| - /* If an error occurs while loading, release our storage. */
|
| - free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
|
| -
|
| - info_ptr = partial_read_comp_unit_head (&cu->header, info_ptr,
|
| - dwarf2_per_objfile->info.buffer,
|
| - dwarf2_per_objfile->info.size,
|
| - abfd, 0);
|
| -
|
| - /* Skip dummy compilation units. */
|
| - if (info_ptr >= (dwarf2_per_objfile->info.buffer
|
| - + dwarf2_per_objfile->info.size)
|
| - || peek_abbrev_code (abfd, info_ptr) == 0)
|
| - {
|
| - do_cleanups (free_cu_cleanup);
|
| - return;
|
| - }
|
| -
|
| - /* Link this compilation unit into the compilation unit tree. */
|
| - this_cu->cu = cu;
|
| - cu->per_cu = this_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
|
| - {
|
| - cu = this_cu->cu;
|
| - info_ptr += cu->header.first_die_offset;
|
| - }
|
| -
|
| - /* Read the abbrevs for this compilation unit into a table. */
|
| - gdb_assert (cu->dwarf2_abbrevs == NULL);
|
| - dwarf2_read_abbrevs (abfd, cu);
|
| - free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu);
|
| -
|
| - /* Read the compilation unit die. */
|
| - init_cu_die_reader (&reader_specs, cu);
|
| - info_ptr = read_full_die (&reader_specs, &comp_unit_die, info_ptr,
|
| - &has_children);
|
| + struct dwarf2_cu *cu = reader->cu;
|
|
|
| - prepare_one_comp_unit (cu, comp_unit_die);
|
| + prepare_one_comp_unit (cu, comp_unit_die, language_minimal);
|
|
|
| /* 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)
|
| - load_partial_dies (abfd, dwarf2_per_objfile->info.buffer, info_ptr, 0, cu);
|
| + load_partial_dies (reader, info_ptr, 0);
|
| +}
|
|
|
| - do_cleanups (free_abbrevs_cleanup);
|
| +/* Load the partial DIEs for a secondary CU into memory.
|
| + This is also used when rereading a primary CU with load_all_dies. */
|
|
|
| - if (read_cu)
|
| - {
|
| - /* We've successfully allocated this compilation unit. Let our
|
| - caller clean it up when finished with it. */
|
| - discard_cleanups (free_cu_cleanup);
|
| - }
|
| +static void
|
| +load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
|
| +{
|
| + init_cutu_and_read_dies (this_cu, NULL, 1, 1,
|
| + load_partial_comp_unit_reader, NULL);
|
| }
|
|
|
| -/* Create a list of all compilation units in OBJFILE. We do this only
|
| - if an inter-comp-unit reference is found; presumably if there is one,
|
| - there will be many, and one will occur early in the .debug_info section.
|
| - So there's no point in building this list incrementally. */
|
| +/* 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)
|
| @@ -3807,9 +5319,9 @@ create_all_comp_units (struct objfile *objfile)
|
| {
|
| unsigned int length, initial_length_size;
|
| struct dwarf2_per_cu_data *this_cu;
|
| - unsigned int offset;
|
| + sect_offset offset;
|
|
|
| - offset = info_ptr - dwarf2_per_objfile->info.buffer;
|
| + offset.sect_off = info_ptr - dwarf2_per_objfile->info.buffer;
|
|
|
| /* Read just enough information to find out where the next
|
| compilation unit is. */
|
| @@ -3823,6 +5335,7 @@ create_all_comp_units (struct objfile *objfile)
|
| this_cu->offset = offset;
|
| this_cu->length = length + initial_length_size;
|
| this_cu->objfile = objfile;
|
| + this_cu->info_or_types_section = &dwarf2_per_objfile->info;
|
|
|
| if (n_comp_units == n_allocated)
|
| {
|
| @@ -3873,7 +5386,8 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
|
| enums. */
|
|
|
| if (pdi->name != NULL || pdi->tag == DW_TAG_namespace
|
| - || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type)
|
| + || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type
|
| + || pdi->tag == DW_TAG_imported_unit)
|
| {
|
| switch (pdi->tag)
|
| {
|
| @@ -3913,6 +5427,29 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
|
| case DW_TAG_module:
|
| add_partial_module (pdi, lowpc, highpc, need_pc, cu);
|
| break;
|
| + case DW_TAG_imported_unit:
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu;
|
| +
|
| + /* For now we don't handle imported units in type units. */
|
| + if (cu->per_cu->is_debug_types)
|
| + {
|
| + error (_("Dwarf Error: DW_TAG_imported_unit is not"
|
| + " supported in type units [in module %s]"),
|
| + cu->objfile->name);
|
| + }
|
| +
|
| + per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
|
| + cu->objfile);
|
| +
|
| + /* Go read the partial unit, if needed. */
|
| + if (per_cu->v.psymtab == NULL)
|
| + process_psymtab_comp_unit (per_cu, 1);
|
| +
|
| + VEC_safe_push (dwarf2_per_cu_ptr,
|
| + cu->per_cu->s.imported_symtabs, per_cu);
|
| + }
|
| + break;
|
| default:
|
| break;
|
| }
|
| @@ -4011,7 +5548,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
|
| ignoring them. */
|
| complaint (&symfile_complaints,
|
| _("unhandled containing DIE tag %d for DIE at %d"),
|
| - parent->tag, pdi->offset);
|
| + parent->tag, pdi->offset.sect_off);
|
| parent->scope = grandparent_scope;
|
| }
|
|
|
| @@ -4021,6 +5558,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
|
|
|
| /* Return the fully scoped name associated with PDI, from compilation unit
|
| CU. The result will be allocated with malloc. */
|
| +
|
| static char *
|
| partial_die_full_name (struct partial_die_info *pdi,
|
| struct dwarf2_cu *cu)
|
| @@ -4041,9 +5579,10 @@ partial_die_full_name (struct partial_die_info *pdi,
|
| struct attribute attr;
|
| struct dwarf2_cu *ref_cu = cu;
|
|
|
| + /* DW_FORM_ref_addr is using section offset. */
|
| attr.name = 0;
|
| attr.form = DW_FORM_ref_addr;
|
| - attr.u.addr = pdi->offset;
|
| + attr.u.unsnd = pdi->offset.sect_off;
|
| die = follow_die_ref (NULL, &attr, &ref_cu);
|
|
|
| return xstrdup (dwarf2_full_name (NULL, die, ref_cu));
|
| @@ -4063,7 +5602,6 @@ 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 struct partial_symbol *psym = NULL;
|
| CORE_ADDR baseaddr;
|
| int built_actual_name = 0;
|
|
|
| @@ -4120,10 +5658,10 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| }
|
| break;
|
| case DW_TAG_variable:
|
| - if (pdi->locdesc)
|
| - addr = decode_locdesc (pdi->locdesc, cu);
|
| + if (pdi->d.locdesc)
|
| + addr = decode_locdesc (pdi->d.locdesc, cu);
|
|
|
| - if (pdi->locdesc
|
| + if (pdi->d.locdesc
|
| && addr == 0
|
| && !dwarf2_per_objfile->has_section_at_zero)
|
| {
|
| @@ -4147,7 +5685,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| used by GDB, but it comes in handy for debugging partial symbol
|
| table building. */
|
|
|
| - if (pdi->locdesc || pdi->has_type)
|
| + if (pdi->d.locdesc || pdi->has_type)
|
| add_psymbol_to_list (actual_name, strlen (actual_name),
|
| built_actual_name,
|
| VAR_DOMAIN, LOC_STATIC,
|
| @@ -4158,7 +5696,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
| else
|
| {
|
| /* Static Variable. Skip symbols without location descriptors. */
|
| - if (pdi->locdesc == NULL)
|
| + if (pdi->d.locdesc == NULL)
|
| {
|
| if (built_actual_name)
|
| xfree (actual_name);
|
| @@ -4303,6 +5841,10 @@ add_partial_subprogram (struct partial_die_info *pdi,
|
| pdi->highpc - 1 + baseaddr,
|
| cu->per_cu->v.psymtab);
|
| }
|
| + }
|
| +
|
| + if (pdi->has_pc_info || (!pdi->is_external && pdi->may_be_inlined))
|
| + {
|
| if (!pdi->is_declaration)
|
| /* Ignore subprogram DIEs that do not have a name, they are
|
| illegal. Do not emit a complaint at this point, we will
|
| @@ -4379,7 +5921,7 @@ peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read,
|
| if (abbrev_number == 0)
|
| return NULL;
|
|
|
| - abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
|
| + abbrev = abbrev_table_lookup_abbrev (cu->abbrev_table, abbrev_number);
|
| if (!abbrev)
|
| {
|
| error (_("Dwarf Error: Could not find abbrev number %d [in module %s]"),
|
| @@ -4394,8 +5936,9 @@ peek_die_abbrev (gdb_byte *info_ptr, unsigned int *bytes_read,
|
| DIE. Any children of the skipped DIEs will also be skipped. */
|
|
|
| static gdb_byte *
|
| -skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu)
|
| +skip_children (const struct die_reader_specs *reader, gdb_byte *info_ptr)
|
| {
|
| + struct dwarf2_cu *cu = reader->cu;
|
| struct abbrev_info *abbrev;
|
| unsigned int bytes_read;
|
|
|
| @@ -4405,7 +5948,7 @@ skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu)
|
| if (abbrev == NULL)
|
| return info_ptr + bytes_read;
|
| else
|
| - info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu);
|
| + info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
|
| }
|
| }
|
|
|
| @@ -4416,12 +5959,16 @@ skip_children (gdb_byte *buffer, gdb_byte *info_ptr, struct dwarf2_cu *cu)
|
| children. */
|
|
|
| static gdb_byte *
|
| -skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
|
| - struct abbrev_info *abbrev, struct dwarf2_cu *cu)
|
| +skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
|
| + struct abbrev_info *abbrev)
|
| {
|
| unsigned int bytes_read;
|
| struct attribute attr;
|
| - bfd *abfd = cu->objfile->obfd;
|
| + bfd *abfd = reader->abfd;
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + gdb_byte *buffer = reader->buffer;
|
| + const gdb_byte *buffer_end = reader->buffer_end;
|
| + gdb_byte *start_info_ptr = info_ptr;
|
| unsigned int form, i;
|
|
|
| for (i = 0; i < abbrev->num_attrs; i++)
|
| @@ -4429,13 +5976,12 @@ skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
|
| /* The only abbrev we care about is DW_AT_sibling. */
|
| if (abbrev->attrs[i].name == DW_AT_sibling)
|
| {
|
| - read_attribute (&attr, &abbrev->attrs[i],
|
| - abfd, info_ptr, cu);
|
| + read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
|
| if (attr.form == DW_FORM_ref_addr)
|
| complaint (&symfile_complaints,
|
| _("ignoring absolute DW_AT_sibling"));
|
| else
|
| - return buffer + dwarf2_get_ref_die_offset (&attr);
|
| + return buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
|
| }
|
|
|
| /* If it isn't DW_AT_sibling, skip this attribute. */
|
| @@ -4499,7 +6045,9 @@ skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
|
| case DW_FORM_sdata:
|
| case DW_FORM_udata:
|
| case DW_FORM_ref_udata:
|
| - info_ptr = skip_leb128 (abfd, info_ptr);
|
| + case DW_FORM_GNU_addr_index:
|
| + case DW_FORM_GNU_str_index:
|
| + info_ptr = (gdb_byte *) safe_skip_leb128 (info_ptr, buffer_end);
|
| break;
|
| case DW_FORM_indirect:
|
| form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
| @@ -4517,19 +6065,18 @@ skip_one_die (gdb_byte *buffer, gdb_byte *info_ptr,
|
| }
|
|
|
| if (abbrev->has_children)
|
| - return skip_children (buffer, info_ptr, cu);
|
| + return skip_children (reader, info_ptr);
|
| else
|
| return info_ptr;
|
| }
|
|
|
| /* Locate ORIG_PDI's sibling.
|
| - INFO_PTR should point to the start of the next DIE after ORIG_PDI
|
| - in BUFFER. */
|
| + INFO_PTR should point to the start of the next DIE after ORIG_PDI. */
|
|
|
| static gdb_byte *
|
| -locate_pdi_sibling (struct partial_die_info *orig_pdi,
|
| - gdb_byte *buffer, gdb_byte *info_ptr,
|
| - bfd *abfd, struct dwarf2_cu *cu)
|
| +locate_pdi_sibling (const struct die_reader_specs *reader,
|
| + struct partial_die_info *orig_pdi,
|
| + gdb_byte *info_ptr)
|
| {
|
| /* Do we know the sibling already? */
|
|
|
| @@ -4543,7 +6090,7 @@ locate_pdi_sibling (struct partial_die_info *orig_pdi,
|
|
|
| /* Skip the children the long way. */
|
|
|
| - return skip_children (buffer, info_ptr, cu);
|
| + return skip_children (reader, info_ptr);
|
| }
|
|
|
| /* Expand this partial symbol table into a full symbol table. */
|
| @@ -4594,18 +6141,24 @@ dwarf2_psymtab_to_symtab (struct partial_symtab *pst)
|
| printf_filtered (_("done.\n"));
|
| }
|
| }
|
| -}
|
| +
|
| + process_cu_includes ();
|
| +}
|
| +
|
| +/* Reading in full CUs. */
|
|
|
| /* Add PER_CU to the queue. */
|
|
|
| static void
|
| -queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
|
| +queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| + enum language pretend_language)
|
| {
|
| struct dwarf2_queue_item *item;
|
|
|
| per_cu->queued = 1;
|
| item = xmalloc (sizeof (*item));
|
| item->per_cu = per_cu;
|
| + item->pretend_language = pretend_language;
|
| item->next = NULL;
|
|
|
| if (dwarf2_queue == NULL)
|
| @@ -4616,13 +6169,62 @@ queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct objfile *objfile)
|
| 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.
|
| + 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. */
|
| +
|
| +static int
|
| +maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
|
| + struct dwarf2_per_cu_data *per_cu,
|
| + enum language pretend_language)
|
| +{
|
| + /* We may arrive here during partial symbol reading, if we need full
|
| + DIEs to process an unusual case (e.g. template arguments). Do
|
| + not queue PER_CU, just tell our caller to load its DIEs. */
|
| + if (dwarf2_per_objfile->reading_partial_symbols)
|
| + {
|
| + if (per_cu->cu == NULL || per_cu->cu->dies == NULL)
|
| + return 1;
|
| + return 0;
|
| + }
|
| +
|
| + /* Mark the dependence relation so that we don't flush PER_CU
|
| + too early. */
|
| + dwarf2_add_dependence (this_cu, per_cu);
|
| +
|
| + /* If it's already on the queue, we have nothing to do. */
|
| + if (per_cu->queued)
|
| + return 0;
|
| +
|
| + /* If the compilation unit is already loaded, just mark it as
|
| + used. */
|
| + if (per_cu->cu != NULL)
|
| + {
|
| + per_cu->cu->last_used = 0;
|
| + return 0;
|
| + }
|
| +
|
| + /* Add it to the queue. */
|
| + queue_comp_unit (per_cu, pretend_language);
|
| +
|
| + return 1;
|
| +}
|
| +
|
| /* Process the queue. */
|
|
|
| static void
|
| -process_queue (struct objfile *objfile)
|
| +process_queue (void)
|
| {
|
| struct dwarf2_queue_item *item, *next_item;
|
|
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog,
|
| + "Expanding one or more symtabs of objfile %s ...\n",
|
| + dwarf2_per_objfile->objfile->name);
|
| + }
|
| +
|
| /* The queue starts out with one item, but following a DIE reference
|
| may load a new CU, adding it to the end of the queue. */
|
| for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
|
| @@ -4630,7 +6232,30 @@ process_queue (struct objfile *objfile)
|
| if (dwarf2_per_objfile->using_index
|
| ? !item->per_cu->v.quick->symtab
|
| : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
|
| - process_full_comp_unit (item->per_cu);
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu = item->per_cu;
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + 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);
|
| + }
|
| +
|
| + 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);
|
| + }
|
| + }
|
|
|
| item->per_cu->queued = 0;
|
| next_item = item->next;
|
| @@ -4638,6 +6263,12 @@ process_queue (struct objfile *objfile)
|
| }
|
|
|
| dwarf2_queue_tail = NULL;
|
| +
|
| + if (dwarf2_read_debug)
|
| + {
|
| + fprintf_unfiltered (gdb_stdlog, "Done expanding symtabs of %s.\n",
|
| + dwarf2_per_objfile->objfile->name);
|
| + }
|
| }
|
|
|
| /* Free all allocated queue entries. This function only releases anything if
|
| @@ -4657,7 +6288,7 @@ dwarf2_release_queue (void *dummy)
|
| if (item->per_cu->queued)
|
| {
|
| if (item->per_cu->cu != NULL)
|
| - free_one_cached_comp_unit (item->per_cu->cu);
|
| + free_one_cached_comp_unit (item->per_cu);
|
| item->per_cu->queued = 0;
|
| }
|
|
|
| @@ -4675,11 +6306,14 @@ static void
|
| psymtab_to_symtab_1 (struct partial_symtab *pst)
|
| {
|
| struct dwarf2_per_cu_data *per_cu;
|
| - struct cleanup *back_to;
|
| int i;
|
|
|
| + if (pst->readin)
|
| + return;
|
| +
|
| for (i = 0; i < pst->number_of_dependencies; i++)
|
| - if (!pst->dependencies[i]->readin)
|
| + if (!pst->dependencies[i]->readin
|
| + && pst->dependencies[i]->user == NULL)
|
| {
|
| /* Inform about additional files that need to be read in. */
|
| if (info_verbose)
|
| @@ -4706,98 +6340,81 @@ psymtab_to_symtab_1 (struct partial_symtab *pst)
|
| return;
|
| }
|
|
|
| - dw2_do_instantiate_symtab (pst->objfile, per_cu);
|
| + dw2_do_instantiate_symtab (per_cu);
|
| }
|
|
|
| -/* Load the DIEs associated with PER_CU into memory. */
|
| +/* Trivial hash function for die_info: the hash value of a DIE
|
| + is its offset in .debug_info for this objfile. */
|
|
|
| -static void
|
| -load_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| - struct objfile *objfile)
|
| +static hashval_t
|
| +die_hash (const void *item)
|
| {
|
| - bfd *abfd = objfile->obfd;
|
| - struct dwarf2_cu *cu;
|
| - unsigned int offset;
|
| - gdb_byte *info_ptr, *beg_of_comp_unit;
|
| - struct cleanup *free_abbrevs_cleanup = NULL, *free_cu_cleanup = NULL;
|
| - struct attribute *attr;
|
| - int read_cu = 0;
|
| -
|
| - gdb_assert (! per_cu->debug_types_section);
|
| -
|
| - /* Set local variables from the partial symbol table info. */
|
| - offset = per_cu->offset;
|
| -
|
| - dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
|
| - info_ptr = dwarf2_per_objfile->info.buffer + offset;
|
| - beg_of_comp_unit = info_ptr;
|
| -
|
| - if (per_cu->cu == NULL)
|
| - {
|
| - cu = xmalloc (sizeof (*cu));
|
| - init_one_comp_unit (cu, objfile);
|
| -
|
| - read_cu = 1;
|
| + const struct die_info *die = item;
|
|
|
| - /* If an error occurs while loading, release our storage. */
|
| - free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
|
| + return die->offset.sect_off;
|
| +}
|
|
|
| - /* Read in the comp_unit header. */
|
| - info_ptr = read_comp_unit_head (&cu->header, info_ptr, abfd);
|
| +/* Trivial comparison function for die_info structures: two DIEs
|
| + are equal if they have the same offset. */
|
|
|
| - /* Skip dummy compilation units. */
|
| - if (info_ptr >= (dwarf2_per_objfile->info.buffer
|
| - + dwarf2_per_objfile->info.size)
|
| - || peek_abbrev_code (abfd, info_ptr) == 0)
|
| - {
|
| - do_cleanups (free_cu_cleanup);
|
| - return;
|
| - }
|
| +static int
|
| +die_eq (const void *item_lhs, const void *item_rhs)
|
| +{
|
| + const struct die_info *die_lhs = item_lhs;
|
| + const struct die_info *die_rhs = item_rhs;
|
|
|
| - /* Complete the cu_header. */
|
| - cu->header.offset = offset;
|
| - cu->header.first_die_offset = info_ptr - beg_of_comp_unit;
|
| + return die_lhs->offset.sect_off == die_rhs->offset.sect_off;
|
| +}
|
|
|
| - /* Read the abbrevs for this compilation unit. */
|
| - dwarf2_read_abbrevs (abfd, cu);
|
| - free_abbrevs_cleanup = make_cleanup (dwarf2_free_abbrev_table, cu);
|
| +/* die_reader_func for load_full_comp_unit.
|
| + This is identical to read_signatured_type_reader,
|
| + but is kept separate for now. */
|
|
|
| - /* Link this compilation unit into the compilation unit tree. */
|
| - per_cu->cu = cu;
|
| - cu->per_cu = per_cu;
|
| +static void
|
| +load_full_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;
|
| + enum language *language_ptr = data;
|
|
|
| - /* Link this CU into read_in_chain. */
|
| - per_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
|
| - dwarf2_per_objfile->read_in_chain = per_cu;
|
| - }
|
| - else
|
| - {
|
| - cu = per_cu->cu;
|
| - info_ptr += cu->header.first_die_offset;
|
| - }
|
| + gdb_assert (cu->die_hash == NULL);
|
| + cu->die_hash =
|
| + htab_create_alloc_ex (cu->header.length / 12,
|
| + die_hash,
|
| + die_eq,
|
| + NULL,
|
| + &cu->comp_unit_obstack,
|
| + hashtab_obstack_allocate,
|
| + dummy_obstack_deallocate);
|
|
|
| - cu->dies = read_comp_unit (info_ptr, cu);
|
| + if (has_children)
|
| + comp_unit_die->child = read_die_and_siblings (reader, info_ptr,
|
| + &info_ptr, comp_unit_die);
|
| + cu->dies = comp_unit_die;
|
| + /* comp_unit_die is not stored in die_hash, no need. */
|
|
|
| /* We try not to read any attributes in this function, because not
|
| - all objfiles needed for references have been loaded yet, and symbol
|
| + all CUs needed for references have been loaded yet, and symbol
|
| table processing isn't initialized. But we have to set the CU language,
|
| - or we won't be able to build types correctly. */
|
| - prepare_one_comp_unit (cu, cu->dies);
|
| -
|
| - /* Similarly, if we do not read the producer, we can not apply
|
| + or we won't be able to build types correctly.
|
| + Similarly, if we do not read the producer, we can not apply
|
| producer-specific interpretation. */
|
| - attr = dwarf2_attr (cu->dies, DW_AT_producer, cu);
|
| - if (attr)
|
| - cu->producer = DW_STRING (attr);
|
| + prepare_one_comp_unit (cu, cu->dies, *language_ptr);
|
| +}
|
|
|
| - if (read_cu)
|
| - {
|
| - do_cleanups (free_abbrevs_cleanup);
|
| +/* Load the DIEs associated with PER_CU into memory. */
|
|
|
| - /* We've successfully allocated this compilation unit. Let our
|
| - caller clean it up when finished with it. */
|
| - discard_cleanups (free_cu_cleanup);
|
| - }
|
| +static void
|
| +load_full_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| + enum language pretend_language)
|
| +{
|
| + gdb_assert (! this_cu->is_debug_types);
|
| +
|
| + init_cutu_and_read_dies (this_cu, NULL, 1, 1,
|
| + load_full_comp_unit_reader, &pretend_language);
|
| }
|
|
|
| /* Add a DIE to the delayed physname list. */
|
| @@ -4850,11 +6467,194 @@ compute_delayed_physnames (struct dwarf2_cu *cu)
|
| }
|
| }
|
|
|
| -/* Generate full symbol information for PST and CU, whose DIEs have
|
| +/* Go objects should be embedded in a DW_TAG_module DIE,
|
| + and it's not clear if/how imported objects will appear.
|
| + To keep Go support simple until that's worked out,
|
| + go back through what we've read and create something usable.
|
| + We could do this while processing each DIE, and feels kinda cleaner,
|
| + but that way is more invasive.
|
| + This is to, for example, allow the user to type "p var" or "b main"
|
| + without having to specify the package name, and allow lookups
|
| + of module.object to work in contexts that use the expression
|
| + parser. */
|
| +
|
| +static void
|
| +fixup_go_packaging (struct dwarf2_cu *cu)
|
| +{
|
| + char *package_name = NULL;
|
| + struct pending *list;
|
| + int i;
|
| +
|
| + for (list = global_symbols; list != NULL; list = list->next)
|
| + {
|
| + for (i = 0; i < list->nsyms; ++i)
|
| + {
|
| + struct symbol *sym = list->symbol[i];
|
| +
|
| + if (SYMBOL_LANGUAGE (sym) == language_go
|
| + && SYMBOL_CLASS (sym) == LOC_BLOCK)
|
| + {
|
| + char *this_package_name = go_symbol_package_name (sym);
|
| +
|
| + if (this_package_name == NULL)
|
| + continue;
|
| + if (package_name == NULL)
|
| + package_name = this_package_name;
|
| + else
|
| + {
|
| + 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),
|
| + this_package_name, package_name);
|
| + xfree (this_package_name);
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + if (package_name != NULL)
|
| + {
|
| + struct objfile *objfile = cu->objfile;
|
| + struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
|
| + 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);
|
| + /* 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_TYPE (sym) = type;
|
| +
|
| + add_symbol_to_list (sym, &global_symbols);
|
| +
|
| + xfree (package_name);
|
| + }
|
| +}
|
| +
|
| +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. */
|
| +
|
| +static struct symtab *
|
| +get_symtab (struct dwarf2_per_cu_data *per_cu)
|
| +{
|
| + return (dwarf2_per_objfile->using_index
|
| + ? per_cu->v.quick->symtab
|
| + : per_cu->v.psymtab->symtab);
|
| +}
|
| +
|
| +/* A helper function for computing the list of all symbol tables
|
| + 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)
|
| +{
|
| + void **slot;
|
| + int ix;
|
| + struct dwarf2_per_cu_data *iter;
|
| +
|
| + slot = htab_find_slot (all_children, per_cu, INSERT);
|
| + if (*slot != NULL)
|
| + {
|
| + /* This inclusion and its children have been processed. */
|
| + return;
|
| + }
|
| +
|
| + *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);
|
| +
|
| + for (ix = 0;
|
| + VEC_iterate (dwarf2_per_cu_ptr, per_cu->s.imported_symtabs, ix, iter);
|
| + ++ix)
|
| + recursively_compute_inclusions (result, all_children, iter);
|
| +}
|
| +
|
| +/* Compute the symtab 'includes' fields for the symtab related to
|
| + PER_CU. */
|
| +
|
| +static void
|
| +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))
|
| + {
|
| + int ix, len;
|
| + struct dwarf2_per_cu_data *iter;
|
| + VEC (dwarf2_per_cu_ptr) *result_children = NULL;
|
| + htab_t all_children;
|
| + struct symtab *symtab = get_symtab (per_cu);
|
| +
|
| + /* If we don't have a symtab, we can just skip this case. */
|
| + if (symtab == NULL)
|
| + return;
|
| +
|
| + all_children = 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);
|
| + ++ix)
|
| + recursively_compute_inclusions (&result_children, all_children, iter);
|
| +
|
| + /* 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);
|
| + 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);
|
| + ++ix)
|
| + symtab->includes[ix] = get_symtab (iter);
|
| + symtab->includes[len] = NULL;
|
| +
|
| + VEC_free (dwarf2_per_cu_ptr, result_children);
|
| + htab_delete (all_children);
|
| + }
|
| +}
|
| +
|
| +/* Compute the 'includes' field for the symtabs of all the CUs we just
|
| + read. */
|
| +
|
| +static void
|
| +process_cu_includes (void)
|
| +{
|
| + int ix;
|
| + struct dwarf2_per_cu_data *iter;
|
| +
|
| + for (ix = 0;
|
| + VEC_iterate (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus,
|
| + ix, iter);
|
| + ++ix)
|
| + {
|
| + if (! iter->is_debug_types)
|
| + compute_symtab_includes (iter);
|
| + }
|
| +
|
| + VEC_free (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus);
|
| +}
|
| +
|
| +/* Generate full symbol information for PER_CU, whose DIEs have
|
| already been loaded into memory. */
|
|
|
| static void
|
| -process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
| +process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
|
| + enum language pretend_language)
|
| {
|
| struct dwarf2_cu *cu = per_cu->cu;
|
| struct objfile *objfile = per_cu->objfile;
|
| @@ -4862,6 +6662,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
| struct symtab *symtab;
|
| struct cleanup *back_to, *delayed_list_cleanup;
|
| CORE_ADDR baseaddr;
|
| + struct block *static_block;
|
|
|
| baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
|
|
| @@ -4871,9 +6672,16 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
|
|
| cu->list_in_scope = &file_symbols;
|
|
|
| + cu->language = pretend_language;
|
| + cu->language_defn = language_def (cu->language);
|
| +
|
| /* Do line number decoding in read_file_scope () */
|
| process_die (cu->dies, cu);
|
|
|
| + /* For now fudge the Go package. */
|
| + if (cu->language == language_go)
|
| + fixup_go_packaging (cu);
|
| +
|
| /* Now that we have processed all the DIEs in the CU, all the types
|
| should be complete, and it should now be safe to compute all of the
|
| physnames. */
|
| @@ -4885,7 +6693,17 @@ 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);
|
|
|
| - symtab = end_symtab (highpc + baseaddr, objfile, SECT_OFF_TEXT (objfile));
|
| + static_block = end_symtab_get_static_block (highpc + baseaddr, objfile, 0);
|
| +
|
| + /* 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
|
| + (such as virtual method tables). Record the ranges in STATIC_BLOCK's
|
| + addrmap to help ensure it has an accurate map of pc values belonging to
|
| + this comp unit. */
|
| + dwarf2_record_block_ranges (cu->dies, static_block, baseaddr, cu);
|
| +
|
| + symtab = end_symtab_from_static_block (static_block, objfile,
|
| + SECT_OFF_TEXT (objfile), 0);
|
|
|
| if (symtab != NULL)
|
| {
|
| @@ -4899,7 +6717,9 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
|
|
| /* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can
|
| produce DW_AT_location with location lists but it can be possibly
|
| - invalid without -fvar-tracking.
|
| + invalid without -fvar-tracking. Still up to GCC-4.4.x incl. 4.4.0
|
| + there were bugs in prologue debug info, fixed later in GCC-4.5
|
| + by "unwind info for epilogues" patch (which is not directly related).
|
|
|
| For -gdwarf-4 type units LOCATIONS_VALID indication is fortunately not
|
| needed, it would be wrong due to missing DW_AT_producer there.
|
| @@ -4907,7 +6727,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
| Still one can confuse GDB by using non-standard GCC compilation
|
| options - this waits on GCC PR other/32998 (-frecord-gcc-switches).
|
| */
|
| - if (cu->has_loclist && gcc_4_minor >= 0)
|
| + if (cu->has_loclist && gcc_4_minor >= 5)
|
| symtab->locations_valid = 1;
|
|
|
| if (gcc_4_minor >= 5)
|
| @@ -4925,63 +6745,173 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu)
|
| pst->readin = 1;
|
| }
|
|
|
| + /* Push it for inclusion processing later. */
|
| + VEC_safe_push (dwarf2_per_cu_ptr, dwarf2_per_objfile->just_read_cus, per_cu);
|
| +
|
| do_cleanups (back_to);
|
| }
|
|
|
| -/* Process a die and its children. */
|
| +/* Generate full symbol information for type unit PER_CU, whose DIEs have
|
| + already been loaded into memory. */
|
|
|
| static void
|
| -process_die (struct die_info *die, struct dwarf2_cu *cu)
|
| +process_full_type_unit (struct dwarf2_per_cu_data *per_cu,
|
| + enum language pretend_language)
|
| {
|
| - switch (die->tag)
|
| - {
|
| - case DW_TAG_padding:
|
| - break;
|
| - case DW_TAG_compile_unit:
|
| - read_file_scope (die, cu);
|
| - break;
|
| - case DW_TAG_type_unit:
|
| - read_type_unit_scope (die, cu);
|
| - break;
|
| - case DW_TAG_subprogram:
|
| - case DW_TAG_inlined_subroutine:
|
| - read_func_scope (die, cu);
|
| - break;
|
| - case DW_TAG_lexical_block:
|
| - case DW_TAG_try_block:
|
| - case DW_TAG_catch_block:
|
| - read_lexical_block_scope (die, cu);
|
| - break;
|
| - case DW_TAG_GNU_call_site:
|
| - read_call_site_scope (die, cu);
|
| - break;
|
| - case DW_TAG_class_type:
|
| - case DW_TAG_interface_type:
|
| - case DW_TAG_structure_type:
|
| - case DW_TAG_union_type:
|
| - process_structure_scope (die, cu);
|
| - break;
|
| - case DW_TAG_enumeration_type:
|
| - process_enumeration_scope (die, cu);
|
| - break;
|
| + struct dwarf2_cu *cu = per_cu->cu;
|
| + struct objfile *objfile = per_cu->objfile;
|
| + struct symtab *symtab;
|
| + struct cleanup *back_to, *delayed_list_cleanup;
|
|
|
| - /* These dies have a type, but processing them does not create
|
| - a symbol or recurse to process the children. Therefore we can
|
| - read them on-demand through read_type_die. */
|
| - case DW_TAG_subroutine_type:
|
| - case DW_TAG_set_type:
|
| - case DW_TAG_array_type:
|
| - case DW_TAG_pointer_type:
|
| - case DW_TAG_ptr_to_member_type:
|
| - case DW_TAG_reference_type:
|
| - case DW_TAG_string_type:
|
| - break;
|
| + buildsym_init ();
|
| + back_to = make_cleanup (really_free_pendings, NULL);
|
| + delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
|
|
|
| - case DW_TAG_base_type:
|
| - case DW_TAG_subrange_type:
|
| - case DW_TAG_typedef:
|
| - /* Add a typedef symbol for the type definition, if it has a
|
| - DW_AT_name. */
|
| + cu->list_in_scope = &file_symbols;
|
| +
|
| + cu->language = pretend_language;
|
| + cu->language_defn = language_def (cu->language);
|
| +
|
| + /* The symbol tables are set up in read_type_unit_scope. */
|
| + process_die (cu->dies, cu);
|
| +
|
| + /* For now fudge the Go package. */
|
| + if (cu->language == language_go)
|
| + fixup_go_packaging (cu);
|
| +
|
| + /* Now that we have processed all the DIEs in the CU, all the types
|
| + should be complete, and it should now be safe to compute all of the
|
| + physnames. */
|
| + compute_delayed_physnames (cu);
|
| + do_cleanups (delayed_list_cleanup);
|
| +
|
| + /* TUs share symbol tables.
|
| + 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)
|
| + {
|
| + symtab = end_expandable_symtab (0, objfile, SECT_OFF_TEXT (objfile));
|
| + per_cu->s.type_unit_group->primary_symtab = symtab;
|
| +
|
| + if (symtab != NULL)
|
| + {
|
| + /* Set symtab language to language from DW_AT_language. If the
|
| + compilation is from a C file generated by language preprocessors,
|
| + do not set the language if it was already deduced by
|
| + start_subfile. */
|
| + if (!(cu->language == language_c && symtab->language != language_c))
|
| + symtab->language = cu->language;
|
| + }
|
| + }
|
| + else
|
| + {
|
| + augment_type_symtab (objfile,
|
| + per_cu->s.type_unit_group->primary_symtab);
|
| + symtab = per_cu->s.type_unit_group->primary_symtab;
|
| + }
|
| +
|
| + if (dwarf2_per_objfile->using_index)
|
| + per_cu->v.quick->symtab = symtab;
|
| + else
|
| + {
|
| + struct partial_symtab *pst = per_cu->v.psymtab;
|
| + pst->symtab = symtab;
|
| + pst->readin = 1;
|
| + }
|
| +
|
| + do_cleanups (back_to);
|
| +}
|
| +
|
| +/* Process an imported unit DIE. */
|
| +
|
| +static void
|
| +process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + struct attribute *attr;
|
| +
|
| + /* For now we don't handle imported units in type units. */
|
| + if (cu->per_cu->is_debug_types)
|
| + {
|
| + error (_("Dwarf Error: DW_TAG_imported_unit is not"
|
| + " supported in type units [in module %s]"),
|
| + cu->objfile->name);
|
| + }
|
| +
|
| + attr = dwarf2_attr (die, DW_AT_import, cu);
|
| + if (attr != NULL)
|
| + {
|
| + struct dwarf2_per_cu_data *per_cu;
|
| + struct symtab *imported_symtab;
|
| + sect_offset offset;
|
| +
|
| + offset = dwarf2_get_ref_die_offset (attr);
|
| + per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
|
| +
|
| + /* Queue the unit, if needed. */
|
| + 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,
|
| + per_cu);
|
| + }
|
| +}
|
| +
|
| +/* Process a die and its children. */
|
| +
|
| +static void
|
| +process_die (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + switch (die->tag)
|
| + {
|
| + case DW_TAG_padding:
|
| + break;
|
| + case DW_TAG_compile_unit:
|
| + case DW_TAG_partial_unit:
|
| + read_file_scope (die, cu);
|
| + break;
|
| + case DW_TAG_type_unit:
|
| + read_type_unit_scope (die, cu);
|
| + break;
|
| + case DW_TAG_subprogram:
|
| + case DW_TAG_inlined_subroutine:
|
| + read_func_scope (die, cu);
|
| + break;
|
| + case DW_TAG_lexical_block:
|
| + case DW_TAG_try_block:
|
| + case DW_TAG_catch_block:
|
| + read_lexical_block_scope (die, cu);
|
| + break;
|
| + case DW_TAG_GNU_call_site:
|
| + read_call_site_scope (die, cu);
|
| + break;
|
| + case DW_TAG_class_type:
|
| + case DW_TAG_interface_type:
|
| + case DW_TAG_structure_type:
|
| + case DW_TAG_union_type:
|
| + process_structure_scope (die, cu);
|
| + break;
|
| + case DW_TAG_enumeration_type:
|
| + process_enumeration_scope (die, cu);
|
| + break;
|
| +
|
| + /* These dies have a type, but processing them does not create
|
| + a symbol or recurse to process the children. Therefore we can
|
| + read them on-demand through read_type_die. */
|
| + case DW_TAG_subroutine_type:
|
| + case DW_TAG_set_type:
|
| + case DW_TAG_array_type:
|
| + case DW_TAG_pointer_type:
|
| + case DW_TAG_ptr_to_member_type:
|
| + case DW_TAG_reference_type:
|
| + case DW_TAG_string_type:
|
| + break;
|
| +
|
| + case DW_TAG_base_type:
|
| + case DW_TAG_subrange_type:
|
| + case DW_TAG_typedef:
|
| + /* Add a typedef symbol for the type definition, if it has a
|
| + DW_AT_name. */
|
| new_symbol (die, read_type_die (die, cu), cu);
|
| break;
|
| case DW_TAG_common_block:
|
| @@ -5006,6 +6936,11 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
|
| dwarf_tag_name (die->tag));
|
| read_import_statement (die, cu);
|
| break;
|
| +
|
| + case DW_TAG_imported_unit:
|
| + process_imported_unit_die (die, cu);
|
| + break;
|
| +
|
| default:
|
| new_symbol (die, NULL, cu);
|
| break;
|
| @@ -5081,8 +7016,14 @@ do_ui_file_peek_last (void *object, const char *buffer, long length)
|
| }
|
|
|
| /* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero,
|
| - compute the physname for the object, which include a method's
|
| - formal parameters (C++/Java) and return type (Java).
|
| + compute the physname for the object, which include a method's:
|
| + - formal parameters (C++/Java),
|
| + - receiver type (Go),
|
| + - return type (Java).
|
| +
|
| + The term "physname" is a bit confusing.
|
| + For C++, for example, it is the demangled name.
|
| + For Go, for example, it's the mangled name.
|
|
|
| For Ada, return the DIE's linkage name rather than the fully qualified
|
| name. PHYSNAME is ignored..
|
| @@ -5093,6 +7034,8 @@ static const char *
|
| dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| int physname)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| +
|
| if (name == NULL)
|
| name = dwarf2_name (die, cu);
|
|
|
| @@ -5123,7 +7066,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| if (die_needs_namespace (die, cu))
|
| {
|
| long length;
|
| - char *prefix;
|
| + const char *prefix;
|
| struct ui_file *buf;
|
|
|
| prefix = determine_prefix (die, cu);
|
| @@ -5171,7 +7114,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| for (child = die->child; child != NULL; child = child->sibling)
|
| {
|
| struct type *type;
|
| - long value;
|
| + LONGEST value;
|
| gdb_byte *bytes;
|
| struct dwarf2_locexpr_baton *baton;
|
| struct value *v;
|
| @@ -5300,7 +7243,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| }
|
| }
|
|
|
| - name = ui_file_obsavestring (buf, &cu->objfile->objfile_obstack,
|
| + name = ui_file_obsavestring (buf, &objfile->objfile_obstack,
|
| &length);
|
| ui_file_delete (buf);
|
|
|
| @@ -5308,7 +7251,7 @@ dwarf2_compute_name (char *name, struct die_info *die, struct dwarf2_cu *cu,
|
| {
|
| char *cname
|
| = dwarf2_canonicalize_name (name, cu,
|
| - &cu->objfile->objfile_obstack);
|
| + &objfile->objfile_obstack);
|
|
|
| if (cname != NULL)
|
| name = cname;
|
| @@ -5343,6 +7286,7 @@ dwarf2_full_name (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| static const char *
|
| dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| struct attribute *attr;
|
| const char *retval, *mangled = NULL, *canon = NULL;
|
| struct cleanup *back_to;
|
| @@ -5376,10 +7320,21 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| variant `long name(params)' does not have the proper inferior type.
|
| */
|
|
|
| - demangled = cplus_demangle (mangled, (DMGL_PARAMS | DMGL_ANSI
|
| - | (cu->language == language_java
|
| - ? DMGL_JAVA | DMGL_RET_POSTFIX
|
| - : DMGL_RET_DROP)));
|
| + if (cu->language == language_go)
|
| + {
|
| + /* This is a lie, but we already lie to the caller new_symbol_full.
|
| + new_symbol_full assumes we return the mangled name.
|
| + This just undoes that lie until things are cleaned up. */
|
| + demangled = NULL;
|
| + }
|
| + else
|
| + {
|
| + demangled = cplus_demangle (mangled,
|
| + (DMGL_PARAMS | DMGL_ANSI
|
| + | (cu->language == language_java
|
| + ? DMGL_JAVA | DMGL_RET_POSTFIX
|
| + : DMGL_RET_DROP)));
|
| + }
|
| if (demangled)
|
| {
|
| make_cleanup (xfree, demangled);
|
| @@ -5405,7 +7360,7 @@ 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, cu->objfile->name);
|
| + physname, canon, mangled, die->offset.sect_off, objfile->name);
|
|
|
| /* Prefer DW_AT_linkage_name (in the CANON form) - when it
|
| is available here - over computed PHYSNAME. It is safer
|
| @@ -5424,7 +7379,7 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| if (need_copy)
|
| retval = obsavestring (retval, strlen (retval),
|
| - &cu->objfile->objfile_obstack);
|
| + &objfile->objfile_obstack);
|
|
|
| do_cleanups (back_to);
|
| return retval;
|
| @@ -5435,6 +7390,7 @@ dwarf2_physname (char *name, struct die_info *die, struct dwarf2_cu *cu)
|
| static void
|
| read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| struct attribute *import_attr;
|
| struct die_info *imported_die, *child_die;
|
| struct dwarf2_cu *imported_cu;
|
| @@ -5541,7 +7497,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, cu->objfile->name);
|
| + child_die->offset.sect_off, objfile->name);
|
| continue;
|
| }
|
|
|
| @@ -5562,7 +7518,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, cu->objfile->name);
|
| + child_die->offset.sect_off, objfile->name);
|
| continue;
|
| }
|
|
|
| @@ -5576,18 +7532,12 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
|
| import_alias,
|
| imported_declaration,
|
| excludes,
|
| - &cu->objfile->objfile_obstack);
|
| + &objfile->objfile_obstack);
|
|
|
| do_cleanups (cleanups);
|
| }
|
|
|
| -static void
|
| -initialize_cu_func_list (struct dwarf2_cu *cu)
|
| -{
|
| - cu->first_fn = cu->last_fn = cu->cached_fn = NULL;
|
| -}
|
| -
|
| -/* Cleanup function for read_file_scope. */
|
| +/* Cleanup function for handle_DW_AT_stmt_list. */
|
|
|
| static void
|
| free_cu_line_header (void *arg)
|
| @@ -5638,41 +7588,41 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
|
| *name = "<unknown>";
|
| }
|
|
|
| -/* Handle DW_AT_stmt_list for a compilation unit or type unit.
|
| - DIE is the DW_TAG_compile_unit or DW_TAG_type_unit die for CU.
|
| +/* Handle DW_AT_stmt_list for a compilation unit.
|
| + DIE is the DW_TAG_compile_unit die for CU.
|
| COMP_DIR is the compilation directory.
|
| WANT_LINE_INFO is non-zero if the pc/line-number mapping is needed. */
|
|
|
| static void
|
| handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
|
| - const char *comp_dir, int want_line_info)
|
| + const char *comp_dir)
|
| {
|
| struct attribute *attr;
|
| - struct objfile *objfile = cu->objfile;
|
| - bfd *abfd = objfile->obfd;
|
| +
|
| + gdb_assert (! cu->per_cu->is_debug_types);
|
|
|
| attr = dwarf2_attr (die, DW_AT_stmt_list, cu);
|
| if (attr)
|
| {
|
| unsigned int line_offset = DW_UNSND (attr);
|
| struct line_header *line_header
|
| - = dwarf_decode_line_header (line_offset, abfd, cu);
|
| + = dwarf_decode_line_header (line_offset, cu);
|
|
|
| if (line_header)
|
| - {
|
| - cu->line_header = line_header;
|
| - make_cleanup (free_cu_line_header, cu);
|
| - dwarf_decode_lines (line_header, comp_dir, cu, NULL, want_line_info);
|
| - }
|
| + {
|
| + cu->line_header = line_header;
|
| + make_cleanup (free_cu_line_header, cu);
|
| + dwarf_decode_lines (line_header, comp_dir, cu, NULL, 1);
|
| + }
|
| }
|
| }
|
|
|
| -/* Process DW_TAG_compile_unit. */
|
| +/* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */
|
|
|
| static void
|
| read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| - struct objfile *objfile = cu->objfile;
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| struct cleanup *back_to = make_cleanup (null_cleanup, 0);
|
| CORE_ADDR lowpc = ((CORE_ADDR) -1);
|
| CORE_ADDR highpc = ((CORE_ADDR) 0);
|
| @@ -5696,15 +7646,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| find_file_and_directory (die, cu, &name, &comp_dir);
|
|
|
| - attr = dwarf2_attr (die, DW_AT_language, cu);
|
| - if (attr)
|
| - {
|
| - set_cu_language (DW_UNSND (attr), cu);
|
| - }
|
| -
|
| - attr = dwarf2_attr (die, DW_AT_producer, cu);
|
| - if (attr)
|
| - cu->producer = DW_STRING (attr);
|
| + prepare_one_comp_unit (cu, die, cu->language);
|
|
|
| /* The XLCL doesn't generate DW_LANG_OpenCL because this attribute is not
|
| standardised yet. As a workaround for the language detection we fall
|
| @@ -5712,21 +7654,16 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| if (cu->producer && strstr (cu->producer, "IBM XL C for OpenCL") != NULL)
|
| cu->language = language_opencl;
|
|
|
| - /* We assume that we're processing GCC output. */
|
| - processing_gcc_compilation = 2;
|
| -
|
| - processing_has_namespace_info = 0;
|
| -
|
| - start_symtab (name, comp_dir, lowpc);
|
| - record_debugformat ("DWARF 2");
|
| - record_producer (cu->producer);
|
| + /* Similar hack for Go. */
|
| + if (cu->producer && strstr (cu->producer, "GNU Go ") != NULL)
|
| + set_cu_language (DW_LANG_Go, cu);
|
|
|
| - initialize_cu_func_list (cu);
|
| + dwarf2_start_symtab (cu, name, comp_dir, lowpc);
|
|
|
| /* Decode line number information if present. We do this before
|
| processing child DIEs, so that the line header table is available
|
| for DW_AT_decl_file. */
|
| - handle_DW_AT_stmt_list (die, cu, comp_dir, 1);
|
| + handle_DW_AT_stmt_list (die, cu, comp_dir);
|
|
|
| /* Process all dies in compilation unit. */
|
| if (die->child != NULL)
|
| @@ -5750,9 +7687,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info"));
|
|
|
| - dwarf_decode_macros (cu->line_header, DW_UNSND (attr),
|
| - comp_dir, abfd, cu,
|
| - &dwarf2_per_objfile->macro, 1);
|
| + dwarf_decode_macros (cu, DW_UNSND (attr), comp_dir, 1);
|
| }
|
| else
|
| {
|
| @@ -5761,14 +7696,122 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| unsigned int macro_offset = DW_UNSND (attr);
|
|
|
| - dwarf_decode_macros (cu->line_header, macro_offset,
|
| - comp_dir, abfd, cu,
|
| - &dwarf2_per_objfile->macinfo, 0);
|
| + dwarf_decode_macros (cu, macro_offset, comp_dir, 0);
|
| }
|
| }
|
| +
|
| do_cleanups (back_to);
|
| }
|
|
|
| +/* TU version of handle_DW_AT_stmt_list for read_type_unit_scope.
|
| + Create the set of symtabs used by this TU, or if this TU is sharing
|
| + symtabs with another TU and the symtabs have already been created
|
| + then restore those symtabs in the line header.
|
| + We don't need the pc/line-number mapping for type units. */
|
| +
|
| +static void
|
| +setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_per_cu_data *per_cu = cu->per_cu;
|
| + struct type_unit_group *tu_group;
|
| + int first_time;
|
| + struct line_header *lh;
|
| + struct attribute *attr;
|
| + unsigned int i, line_offset;
|
| +
|
| + gdb_assert (per_cu->is_debug_types);
|
| +
|
| + 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;
|
| +
|
| + /* 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
|
| + (file name,index -> symtab mapping). If data shows this optimization
|
| + is useful we can do it then. */
|
| + first_time = tu_group->primary_symtab == NULL;
|
| +
|
| + /* We have to handle the case of both a missing DW_AT_stmt_list or bad
|
| + debug info. */
|
| + lh = NULL;
|
| + if (attr != NULL)
|
| + {
|
| + line_offset = DW_UNSND (attr);
|
| + lh = dwarf_decode_line_header (line_offset, cu);
|
| + }
|
| + if (lh == NULL)
|
| + {
|
| + if (first_time)
|
| + dwarf2_start_symtab (cu, "", NULL, 0);
|
| + else
|
| + {
|
| + gdb_assert (tu_group->symtabs == NULL);
|
| + restart_symtab (0);
|
| + }
|
| + /* Note: The primary symtab will get allocated at the end. */
|
| + return;
|
| + }
|
| +
|
| + cu->line_header = lh;
|
| + make_cleanup (free_cu_line_header, cu);
|
| +
|
| + if (first_time)
|
| + {
|
| + dwarf2_start_symtab (cu, "", NULL, 0);
|
| +
|
| + tu_group->num_symtabs = lh->num_file_names;
|
| + tu_group->symtabs = XNEWVEC (struct symtab *, lh->num_file_names);
|
| +
|
| + for (i = 0; i < lh->num_file_names; ++i)
|
| + {
|
| + char *dir = NULL;
|
| + struct file_entry *fe = &lh->file_names[i];
|
| +
|
| + if (fe->dir_index)
|
| + dir = lh->include_dirs[fe->dir_index - 1];
|
| + dwarf2_start_subfile (fe->name, dir, NULL);
|
| +
|
| + /* Note: We don't have to watch for the main subfile here, type units
|
| + don't have DW_AT_name. */
|
| +
|
| + if (current_subfile->symtab == NULL)
|
| + {
|
| + /* NOTE: start_subfile will recognize when it's been passed
|
| + a file it has already seen. So we can't assume there's a
|
| + simple mapping from lh->file_names to subfiles,
|
| + lh->file_names may contain dups. */
|
| + current_subfile->symtab = allocate_symtab (current_subfile->name,
|
| + objfile);
|
| + }
|
| +
|
| + fe->symtab = current_subfile->symtab;
|
| + tu_group->symtabs[i] = fe->symtab;
|
| + }
|
| + }
|
| + else
|
| + {
|
| + restart_symtab (0);
|
| +
|
| + for (i = 0; i < lh->num_file_names; ++i)
|
| + {
|
| + struct file_entry *fe = &lh->file_names[i];
|
| +
|
| + fe->symtab = tu_group->symtabs[i];
|
| + }
|
| + }
|
| +
|
| + /* The main symtab is allocated last. Type units don't have DW_AT_name
|
| + so they don't have a "real" (so to speak) symtab anyway.
|
| + There is later code that will assign the main symtab to all symbols
|
| + that don't have one. We need to handle the case of a symbol with a
|
| + missing symtab (DW_AT_decl_file) anyway. */
|
| +}
|
| +
|
| /* Process DW_TAG_type_unit.
|
| For TUs we want to skip the first top level sibling if it's not the
|
| actual type being defined by this TU. In this case the first top
|
| @@ -5777,104 +7820,561 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| static void
|
| read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| - struct objfile *objfile = cu->objfile;
|
| - struct cleanup *back_to = make_cleanup (null_cleanup, 0);
|
| - CORE_ADDR lowpc;
|
| - struct attribute *attr;
|
| - char *name = NULL;
|
| - char *comp_dir = NULL;
|
| struct die_info *child_die;
|
| - bfd *abfd = objfile->obfd;
|
|
|
| - /* start_symtab needs a low pc, but we don't really have one.
|
| - Do what read_file_scope would do in the absence of such info. */
|
| - lowpc = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
|
| + prepare_one_comp_unit (cu, die, language_minimal);
|
|
|
| - /* Find the filename. Do not use dwarf2_name here, since the filename
|
| - is not a source language identifier. */
|
| - attr = dwarf2_attr (die, DW_AT_name, cu);
|
| - if (attr)
|
| - name = DW_STRING (attr);
|
| + /* Initialize (or reinitialize) the machinery for building symtabs.
|
| + We do this before processing child DIEs, so that the line header table
|
| + is available for DW_AT_decl_file. */
|
| + setup_type_unit_groups (die, 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))
|
| + if (die->child != NULL)
|
| {
|
| - comp_dir = ldirname (name);
|
| - if (comp_dir != NULL)
|
| - make_cleanup (xfree, comp_dir);
|
| + child_die = die->child;
|
| + while (child_die && child_die->tag)
|
| + {
|
| + process_die (child_die, cu);
|
| + child_die = sibling_die (child_die);
|
| + }
|
| }
|
| +}
|
| +
|
| +/* DWO files. */
|
|
|
| - if (name == NULL)
|
| - name = "<unknown>";
|
| +static hashval_t
|
| +hash_dwo_file (const void *item)
|
| +{
|
| + const struct dwo_file *dwo_file = item;
|
|
|
| - attr = dwarf2_attr (die, DW_AT_language, cu);
|
| - if (attr)
|
| - set_cu_language (DW_UNSND (attr), cu);
|
| + return htab_hash_string (dwo_file->dwo_name);
|
| +}
|
|
|
| - /* This isn't technically needed today. It is done for symmetry
|
| - with read_file_scope. */
|
| - attr = dwarf2_attr (die, DW_AT_producer, cu);
|
| - if (attr)
|
| - cu->producer = DW_STRING (attr);
|
| +static int
|
| +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;
|
|
|
| - /* We assume that we're processing GCC output. */
|
| - processing_gcc_compilation = 2;
|
| + return strcmp (lhs->dwo_name, rhs->dwo_name) == 0;
|
| +}
|
|
|
| - processing_has_namespace_info = 0;
|
| +/* Allocate a hash table for DWO files. */
|
|
|
| - start_symtab (name, comp_dir, lowpc);
|
| - record_debugformat ("DWARF 2");
|
| - record_producer (cu->producer);
|
| +static htab_t
|
| +allocate_dwo_file_hash_table (void)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
|
|
| - /* Decode line number information if present. We do this before
|
| - processing child DIEs, so that the line header table is available
|
| - for DW_AT_decl_file.
|
| - We don't need the pc/line-number mapping for type units. */
|
| - handle_DW_AT_stmt_list (die, cu, comp_dir, 0);
|
| + return htab_create_alloc_ex (41,
|
| + hash_dwo_file,
|
| + eq_dwo_file,
|
| + NULL,
|
| + &objfile->objfile_obstack,
|
| + hashtab_obstack_allocate,
|
| + dummy_obstack_deallocate);
|
| +}
|
|
|
| - /* Process the dies in the type unit. */
|
| - if (die->child == NULL)
|
| +static hashval_t
|
| +hash_dwo_unit (const void *item)
|
| +{
|
| + const struct dwo_unit *dwo_unit = item;
|
| +
|
| + /* This drops the top 32 bits of the id, but is ok for a hash. */
|
| + return dwo_unit->signature;
|
| +}
|
| +
|
| +static int
|
| +eq_dwo_unit (const void *item_lhs, const void *item_rhs)
|
| +{
|
| + const struct dwo_unit *lhs = item_lhs;
|
| + const struct dwo_unit *rhs = item_rhs;
|
| +
|
| + /* The signature is assumed to be unique within the DWO file.
|
| + So while object file CU dwo_id's always have the value zero,
|
| + that's OK, assuming each object file DWO file has only one CU,
|
| + and that's the rule for now. */
|
| + return lhs->signature == rhs->signature;
|
| +}
|
| +
|
| +/* Allocate a hash table for DWO CUs,TUs.
|
| + There is one of these tables for each of CUs,TUs for each DWO file. */
|
| +
|
| +static htab_t
|
| +allocate_dwo_unit_table (struct objfile *objfile)
|
| +{
|
| + /* Start out with a pretty small number.
|
| + Generally DWO files contain only one CU and maybe some TUs. */
|
| + return htab_create_alloc_ex (3,
|
| + hash_dwo_unit,
|
| + eq_dwo_unit,
|
| + NULL,
|
| + &objfile->objfile_obstack,
|
| + hashtab_obstack_allocate,
|
| + 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))
|
| {
|
| - dump_die_for_error (die);
|
| - error (_("Dwarf Error: Missing children for type unit [in module %s]"),
|
| - bfd_get_filename (abfd));
|
| + 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. */
|
| +
|
| +struct create_dwo_info_table_data
|
| +{
|
| + struct dwo_file *dwo_file;
|
| + htab_t cu_htab;
|
| +};
|
| +
|
| +/* die_reader_func for create_debug_info_hash_table. */
|
| +
|
| +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)
|
| +{
|
| + 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 dwo_file *dwo_file = data->dwo_file;
|
| + htab_t cu_htab = data->cu_htab;
|
| + void **slot;
|
| + 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);
|
| + 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->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)));
|
| +}
|
| +
|
| +/* Create a hash table to map DWO IDs to their CU entry in .debug_info.dwo. */
|
| +
|
| +static htab_t
|
| +create_debug_info_hash_table (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;
|
| +
|
| + dwarf2_read_section (objfile, section);
|
| + info_ptr = section->buffer;
|
| +
|
| + if (info_ptr == NULL)
|
| + return NULL;
|
| +
|
| + /* 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 (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);
|
| +
|
| + create_dwo_info_table_data.dwo_file = dwo_file;
|
| + create_dwo_info_table_data.cu_htab = cu_htab;
|
| +
|
| + end_ptr = info_ptr + section->size;
|
| + while (info_ptr < end_ptr)
|
| + {
|
| + struct dwarf2_per_cu_data per_cu;
|
| +
|
| + 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;
|
| +
|
| + 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);
|
| +
|
| + info_ptr += per_cu.length;
|
| + }
|
| +
|
| + return cu_htab;
|
| +}
|
| +
|
| +/* 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. */
|
| +
|
| +static bfd *
|
| +try_open_dwo_file (const char *file_name)
|
| +{
|
| + bfd *sym_bfd;
|
| + int desc;
|
| + char *absolute_name;
|
| +
|
| + desc = openp (debug_file_directory, OPF_TRY_CWD_FIRST, file_name,
|
| + O_RDONLY | O_BINARY, &absolute_name);
|
| + if (desc < 0)
|
| + return NULL;
|
| +
|
| + sym_bfd = bfd_fopen (absolute_name, gnutarget, FOPEN_RB, desc);
|
| + if (!sym_bfd)
|
| + {
|
| + xfree (absolute_name);
|
| + 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);
|
| + 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.
|
| + 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)
|
| +{
|
| + bfd *abfd;
|
| +
|
| + if (IS_ABSOLUTE_PATH (dwo_name))
|
| + return try_open_dwo_file (dwo_name);
|
| +
|
| + /* Before trying the search path, try DWO_NAME in COMP_DIR. */
|
| +
|
| + if (comp_dir != NULL)
|
| + {
|
| + 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;
|
| + }
|
| +
|
| + /* 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);
|
| +}
|
| +
|
| +/* Initialize the use of the DWO file specified by DWO_NAME. */
|
| +
|
| +static struct dwo_file *
|
| +init_dwo_file (const char *dwo_name, const char *comp_dir)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwo_file *dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack,
|
| + struct dwo_file);
|
| + bfd *abfd;
|
| + 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;
|
| +
|
| + cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
|
| +
|
| + bfd_map_over_sections (abfd, dwarf2_locate_dwo_sections, dwo_file);
|
| +
|
| + dwo_file->cus = create_debug_info_hash_table (dwo_file);
|
| +
|
| + dwo_file->tus = create_debug_types_hash_table (dwo_file,
|
| + dwo_file->sections.types);
|
| +
|
| + discard_cleanups (cleanups);
|
| +
|
| + return dwo_file;
|
| +}
|
| +
|
| +/* Lookup DWO file DWO_NAME. */
|
| +
|
| +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 (dwarf2_per_objfile->dwo_files == NULL)
|
| + dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
|
| +
|
| + /* 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 not, read it in and build a table of the DWOs it contains. */
|
| + if (*slot == NULL)
|
| + *slot = init_dwo_file (dwo_name, comp_dir);
|
| +
|
| + /* NOTE: This will be NULL if unable to open the file. */
|
| + dwo_file = *slot;
|
| +
|
| + return dwo_file;
|
| +}
|
| +
|
| +/* Lookup the DWO CU referenced from THIS_CU in DWO file DWO_NAME.
|
| + 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).
|
| + 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). */
|
| +
|
| +static struct dwo_unit *
|
| +lookup_dwo_comp_unit (struct dwarf2_per_cu_data *this_cu,
|
| + char *dwo_name, const char *comp_dir,
|
| + ULONGEST signature)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwo_file *dwo_file;
|
| +
|
| + dwo_file = lookup_dwo_file (dwo_name, comp_dir);
|
| + if (dwo_file == NULL)
|
| + return NULL;
|
| +
|
| + /* Look up the DWO using its signature(dwo_id). */
|
| +
|
| + if (dwo_file->cus != NULL)
|
| + {
|
| + struct dwo_unit find_dwo_cu, *dwo_cu;
|
| +
|
| + find_dwo_cu.signature = signature;
|
| + dwo_cu = htab_find (dwo_file->cus, &find_dwo_cu);
|
| +
|
| + if (dwo_cu != NULL)
|
| + return dwo_cu;
|
| + }
|
| +
|
| + /* We didn't find it. This must mean a dwo_id mismatch. */
|
| +
|
| + 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);
|
| + 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). */
|
| +
|
| +static struct dwo_unit *
|
| +lookup_dwo_type_unit (struct signatured_type *this_tu,
|
| + char *dwo_name, const char *comp_dir)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwo_file *dwo_file;
|
| +
|
| + dwo_file = lookup_dwo_file (dwo_name, comp_dir);
|
| + if (dwo_file == NULL)
|
| + return NULL;
|
| +
|
| + /* Look up the DWO using its signature(dwo_id). */
|
| +
|
| + if (dwo_file->tus != 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);
|
| +
|
| + if (dwo_tu != NULL)
|
| + return dwo_tu;
|
| + }
|
| +
|
| + /* We didn't find it. This must mean a dwo_id mismatch. */
|
| +
|
| + 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;
|
| +}
|
| +
|
| +/* Free all resources associated with DWO_FILE.
|
| + Close the DWO file and munmap the sections.
|
| + All memory should be on the objfile obstack. */
|
| +
|
| +static void
|
| +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);
|
|
|
| - child_die = die->child;
|
| + VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
|
| +}
|
|
|
| - while (child_die && child_die->tag)
|
| - {
|
| - process_die (child_die, cu);
|
| +/* Wrapper for free_dwo_file for use in cleanups. */
|
|
|
| - child_die = sibling_die (child_die);
|
| - }
|
| +static void
|
| +free_dwo_file_cleanup (void *arg)
|
| +{
|
| + struct dwo_file *dwo_file = (struct dwo_file *) arg;
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
|
|
| - do_cleanups (back_to);
|
| + free_dwo_file (dwo_file, objfile);
|
| }
|
|
|
| -static void
|
| -add_to_cu_func_list (const char *name, CORE_ADDR lowpc, CORE_ADDR highpc,
|
| - struct dwarf2_cu *cu)
|
| +/* Traversal function for free_dwo_files. */
|
| +
|
| +static int
|
| +free_dwo_file_from_slot (void **slot, void *info)
|
| {
|
| - struct function_range *thisfn;
|
| + struct dwo_file *dwo_file = (struct dwo_file *) *slot;
|
| + struct objfile *objfile = (struct objfile *) info;
|
|
|
| - thisfn = (struct function_range *)
|
| - obstack_alloc (&cu->comp_unit_obstack, sizeof (struct function_range));
|
| - thisfn->name = name;
|
| - thisfn->lowpc = lowpc;
|
| - thisfn->highpc = highpc;
|
| - thisfn->seen_line = 0;
|
| - thisfn->next = NULL;
|
| + free_dwo_file (dwo_file, objfile);
|
|
|
| - if (cu->last_fn == NULL)
|
| - cu->first_fn = thisfn;
|
| - else
|
| - cu->last_fn->next = thisfn;
|
| + return 1;
|
| +}
|
|
|
| - cu->last_fn = thisfn;
|
| +/* Free all resources associated with DWO_FILES. */
|
| +
|
| +static void
|
| +free_dwo_files (htab_t dwo_files, struct objfile *objfile)
|
| +{
|
| + htab_traverse_noresize (dwo_files, free_dwo_file_from_slot, objfile);
|
| }
|
| +
|
| +/* Read in various DIEs. */
|
|
|
| /* qsort helper for inherit_abstract_dies. */
|
|
|
| @@ -5898,8 +8398,8 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
|
| struct die_info *child_die;
|
| unsigned die_children_count;
|
| /* CU offsets which were referenced by children of the current DIE. */
|
| - unsigned *offsets;
|
| - unsigned *offsets_end, *offsetp;
|
| + sect_offset *offsets;
|
| + sect_offset *offsets_end, *offsetp;
|
| /* Parent of DIE - referenced by DW_AT_abstract_origin. */
|
| struct die_info *origin_die;
|
| /* Iterator of the ORIGIN_DIE children. */
|
| @@ -5929,7 +8429,7 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
|
| && origin_die->tag == DW_TAG_subprogram))
|
| complaint (&symfile_complaints,
|
| _("DIE 0x%x and its abstract origin 0x%x have different tags"),
|
| - die->offset, origin_die->offset);
|
| + die->offset.sect_off, origin_die->offset.sect_off);
|
|
|
| child_die = die->child;
|
| die_children_count = 0;
|
| @@ -5972,13 +8472,13 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
|
| && child_origin_die->tag == DW_TAG_subprogram))
|
| complaint (&symfile_complaints,
|
| _("Child DIE 0x%x and its abstract origin 0x%x have "
|
| - "different tags"), child_die->offset,
|
| - child_origin_die->offset);
|
| + "different tags"), child_die->offset.sect_off,
|
| + child_origin_die->offset.sect_off);
|
| if (child_origin_die->parent != origin_die)
|
| complaint (&symfile_complaints,
|
| _("Child DIE 0x%x and its abstract origin 0x%x have "
|
| - "different parents"), child_die->offset,
|
| - child_origin_die->offset);
|
| + "different parents"), child_die->offset.sect_off,
|
| + child_origin_die->offset.sect_off);
|
| else
|
| *offsets_end++ = child_origin_die->offset;
|
| }
|
| @@ -5987,20 +8487,22 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu)
|
| qsort (offsets, offsets_end - offsets, sizeof (*offsets),
|
| unsigned_int_compar);
|
| for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++)
|
| - if (offsetp[-1] == *offsetp)
|
| + if (offsetp[-1].sect_off == offsetp->sect_off)
|
| complaint (&symfile_complaints,
|
| _("Multiple children of DIE 0x%x refer "
|
| "to DIE 0x%x as their abstract origin"),
|
| - die->offset, *offsetp);
|
| + die->offset.sect_off, offsetp->sect_off);
|
|
|
| offsetp = offsets;
|
| origin_child_die = origin_die->child;
|
| while (origin_child_die && origin_child_die->tag)
|
| {
|
| /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children? */
|
| - while (offsetp < offsets_end && *offsetp < origin_child_die->offset)
|
| + while (offsetp < offsets_end
|
| + && offsetp->sect_off < origin_child_die->offset.sect_off)
|
| offsetp++;
|
| - if (offsetp >= offsets_end || *offsetp > origin_child_die->offset)
|
| + if (offsetp >= offsets_end
|
| + || offsetp->sect_off > origin_child_die->offset.sect_off)
|
| {
|
| /* Found that ORIGIN_CHILD_DIE is really not referenced. */
|
| process_die (origin_child_die, origin_cu);
|
| @@ -6051,7 +8553,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| if (name == NULL)
|
| {
|
| complaint (&symfile_complaints,
|
| - _("missing name for subprogram DIE at %d"), die->offset);
|
| + _("missing name for subprogram DIE at %d"),
|
| + die->offset.sect_off);
|
| return;
|
| }
|
|
|
| @@ -6063,16 +8566,13 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| complaint (&symfile_complaints,
|
| _("cannot get low and high bounds "
|
| "for subprogram DIE at %d"),
|
| - die->offset);
|
| + die->offset.sect_off);
|
| return;
|
| }
|
|
|
| lowpc += baseaddr;
|
| highpc += baseaddr;
|
|
|
| - /* Record the function range for dwarf_decode_lines. */
|
| - add_to_cu_func_list (name, lowpc, highpc, cu);
|
| -
|
| /* If we have any template arguments, then we must allocate a
|
| different sort of symbol. */
|
| for (child_die = die->child; child_die; child_die = sibling_die (child_die))
|
| @@ -6278,7 +8778,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, cu->objfile->name);
|
| + die->offset.sect_off, objfile->name);
|
| return;
|
| }
|
| pc = DW_ADDR (attr) + baseaddr;
|
| @@ -6294,7 +8794,7 @@ 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, cu->objfile->name);
|
| + paddress (gdbarch, pc), die->offset.sect_off, objfile->name);
|
| return;
|
| }
|
|
|
| @@ -6309,7 +8809,7 @@ 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, cu->objfile->name);
|
| + child_die->tag, child_die->offset.sect_off, objfile->name);
|
| continue;
|
| }
|
|
|
| @@ -6367,7 +8867,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, cu->objfile->name);
|
| + die->offset.sect_off, objfile->name);
|
| }
|
| }
|
|
|
| @@ -6390,7 +8890,6 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| }
|
| else if (is_ref_attr (attr))
|
| {
|
| - struct objfile *objfile = cu->objfile;
|
| struct dwarf2_cu *target_cu = cu;
|
| struct die_info *target_die;
|
|
|
| @@ -6405,7 +8904,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 "
|
| "physname, for referencing DIE 0x%x [in module %s]"),
|
| - die->offset, cu->objfile->name);
|
| + die->offset.sect_off, objfile->name);
|
| else
|
| SET_FIELD_PHYSNAME (call_site->target, (char *) target_physname);
|
| }
|
| @@ -6418,7 +8917,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, cu->objfile->name);
|
| + die->offset.sect_off, objfile->name);
|
| else
|
| SET_FIELD_PHYSADDR (call_site->target, lowpc + baseaddr);
|
| }
|
| @@ -6427,7 +8926,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, cu->objfile->name);
|
| + die->offset.sect_off, objfile->name);
|
|
|
| call_site->per_cu = cu->per_cu;
|
|
|
| @@ -6435,8 +8934,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| child_die && child_die->tag;
|
| child_die = sibling_die (child_die))
|
| {
|
| - struct dwarf2_locexpr_baton *dlbaton;
|
| struct call_site_parameter *parameter;
|
| + struct attribute *loc, *origin;
|
|
|
| if (child_die->tag != DW_TAG_GNU_call_site_parameter)
|
| {
|
| @@ -6447,31 +8946,61 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| gdb_assert (call_site->parameter_count < nparams);
|
| parameter = &call_site->parameter[call_site->parameter_count];
|
|
|
| - /* DW_AT_location specifies the register number. Value of the data
|
| - assumed for the register is contained in DW_AT_GNU_call_site_value. */
|
| + /* DW_AT_location specifies the register number or DW_AT_abstract_origin
|
| + specifies DW_TAG_formal_parameter. Value of the data assumed for the
|
| + register is contained in DW_AT_GNU_call_site_value. */
|
| +
|
| + 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))
|
| + {
|
| + sect_offset offset;
|
|
|
| - attr = dwarf2_attr (child_die, DW_AT_location, cu);
|
| - if (!attr || !attr_form_is_block (attr))
|
| + parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET;
|
| + offset = dwarf2_get_ref_die_offset (origin);
|
| + if (!offset_in_cu_p (&cu->header, offset))
|
| + {
|
| + /* As DW_OP_GNU_parameter_ref uses CU-relative offset this
|
| + binding can be done only inside one CU. Such referenced DIE
|
| + therefore cannot be even moved to DW_TAG_partial_unit. */
|
| + complaint (&symfile_complaints,
|
| + _("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);
|
| + continue;
|
| + }
|
| + parameter->u.param_offset.cu_off = (offset.sect_off
|
| + - cu->header.offset.sect_off);
|
| + }
|
| + else if (loc == NULL || origin != NULL || !attr_form_is_block (loc))
|
| {
|
| 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, cu->objfile->name);
|
| + child_die->offset.sect_off, objfile->name);
|
| continue;
|
| }
|
| - parameter->dwarf_reg = dwarf_block_to_dwarf_reg (DW_BLOCK (attr)->data,
|
| - &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size]);
|
| - if (parameter->dwarf_reg == -1
|
| - && !dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (attr)->data,
|
| - &DW_BLOCK (attr)->data[DW_BLOCK (attr)->size],
|
| - ¶meter->fb_offset))
|
| + else
|
| {
|
| - complaint (&symfile_complaints,
|
| - _("Only single DW_OP_reg or DW_OP_fbreg is supported "
|
| - "for DW_FORM_block* DW_AT_location for "
|
| - "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
|
| - child_die->offset, cu->objfile->name);
|
| - continue;
|
| + parameter->u.dwarf_reg = dwarf_block_to_dwarf_reg
|
| + (DW_BLOCK (loc)->data, &DW_BLOCK (loc)->data[DW_BLOCK (loc)->size]);
|
| + if (parameter->u.dwarf_reg != -1)
|
| + parameter->kind = CALL_SITE_PARAMETER_DWARF_REG;
|
| + else if (dwarf_block_to_sp_offset (gdbarch, DW_BLOCK (loc)->data,
|
| + &DW_BLOCK (loc)->data[DW_BLOCK (loc)->size],
|
| + ¶meter->u.fb_offset))
|
| + parameter->kind = CALL_SITE_PARAMETER_FB_OFFSET;
|
| + else
|
| + {
|
| + complaint (&symfile_complaints,
|
| + _("Only single DW_OP_reg or DW_OP_fbreg is supported "
|
| + "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);
|
| + continue;
|
| + }
|
| }
|
|
|
| attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
|
| @@ -6480,7 +9009,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, cu->objfile->name);
|
| + child_die->offset.sect_off, objfile->name);
|
| continue;
|
| }
|
| parameter->value = DW_BLOCK (attr)->data;
|
| @@ -6498,7 +9027,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, cu->objfile->name);
|
| + child_die->offset.sect_off, objfile->name);
|
| else
|
| {
|
| parameter->data_value = DW_BLOCK (attr)->data;
|
| @@ -6653,23 +9182,31 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
|
| /* Get low and high pc attributes from a die. Return 1 if the attributes
|
| are present and valid, otherwise, return 0. Return -1 if the range is
|
| discontinuous, i.e. derived from DW_AT_ranges information. */
|
| +
|
| static int
|
| dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
|
| CORE_ADDR *highpc, struct dwarf2_cu *cu,
|
| struct partial_symtab *pst)
|
| {
|
| struct attribute *attr;
|
| + struct attribute *attr_high;
|
| CORE_ADDR low = 0;
|
| CORE_ADDR high = 0;
|
| int ret = 0;
|
|
|
| - attr = dwarf2_attr (die, DW_AT_high_pc, cu);
|
| - if (attr)
|
| + attr_high = dwarf2_attr (die, DW_AT_high_pc, cu);
|
| + if (attr_high)
|
| {
|
| - high = DW_ADDR (attr);
|
| attr = dwarf2_attr (die, DW_AT_low_pc, cu);
|
| if (attr)
|
| - low = DW_ADDR (attr);
|
| + {
|
| + low = DW_ADDR (attr);
|
| + if (attr_high->form == DW_FORM_addr
|
| + || attr_high->form == DW_FORM_GNU_addr_index)
|
| + high = DW_ADDR (attr_high);
|
| + else
|
| + high = low + DW_UNSND (attr_high);
|
| + }
|
| else
|
| /* Found high w/o low attribute. */
|
| return 0;
|
| @@ -6682,9 +9219,11 @@ 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;
|
| +
|
| /* Value of the DW_AT_ranges attribute is the offset in the
|
| .debug_ranges section. */
|
| - if (!dwarf2_ranges_read (DW_UNSND (attr), &low, &high, cu, pst))
|
| + if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst))
|
| return 0;
|
| /* Found discontinuous range of addresses. */
|
| ret = -1;
|
| @@ -6810,21 +9349,28 @@ get_scope_pc_bounds (struct die_info *die,
|
|
|
| /* Record the address ranges for BLOCK, offset by BASEADDR, as given
|
| in DIE. */
|
| +
|
| static void
|
| dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| CORE_ADDR baseaddr, struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| struct attribute *attr;
|
| + struct attribute *attr_high;
|
|
|
| - attr = dwarf2_attr (die, DW_AT_high_pc, cu);
|
| - if (attr)
|
| + attr_high = dwarf2_attr (die, DW_AT_high_pc, cu);
|
| + if (attr_high)
|
| {
|
| - CORE_ADDR high = DW_ADDR (attr);
|
| -
|
| attr = dwarf2_attr (die, DW_AT_low_pc, cu);
|
| if (attr)
|
| {
|
| CORE_ADDR low = DW_ADDR (attr);
|
| + CORE_ADDR high;
|
| + if (attr_high->form == DW_FORM_addr
|
| + || attr_high->form == DW_FORM_GNU_addr_index)
|
| + high = DW_ADDR (attr_high);
|
| + else
|
| + high = low + DW_UNSND (attr_high);
|
|
|
| record_block_range (block, baseaddr + low, baseaddr + high - 1);
|
| }
|
| @@ -6833,11 +9379,11 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| attr = dwarf2_attr (die, DW_AT_ranges, cu);
|
| if (attr)
|
| {
|
| - bfd *obfd = cu->objfile->obfd;
|
| + bfd *obfd = objfile->obfd;
|
|
|
| /* 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);
|
| + unsigned long offset = DW_UNSND (attr) + cu->ranges_base;
|
| gdb_byte *buffer = dwarf2_per_objfile->ranges.buffer + offset;
|
|
|
| /* For some target architectures, but not others, the
|
| @@ -6919,12 +9465,11 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block,
|
| }
|
| }
|
|
|
| -/* Check for GCC PR debug/45124 fix which is not present in any G++ version up
|
| - to 4.5.any while it is present already in G++ 4.6.0 - the PR has been fixed
|
| - during 4.6.0 experimental. */
|
| +/* Check whether the producer field indicates either of GCC < 4.6, or the
|
| + Intel C/C++ compiler, and cache the result in CU. */
|
|
|
| -static int
|
| -producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu)
|
| +static void
|
| +check_producer (struct dwarf2_cu *cu)
|
| {
|
| const char *cs;
|
| int major, minor, release;
|
| @@ -6939,30 +9484,43 @@ producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu)
|
| for their space efficiency GDB cannot workaround gcc-4.5.x -gdwarf-4
|
| combination. gcc-4.5.x -gdwarf-4 binaries have DW_AT_accessibility
|
| interpreted incorrectly by GDB now - GCC PR debug/48229. */
|
| -
|
| - return 0;
|
| }
|
| -
|
| - /* Skip any identifier after "GNU " - such as "C++" or "Java". */
|
| -
|
| - if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) != 0)
|
| + else if (strncmp (cu->producer, "GNU ", strlen ("GNU ")) == 0)
|
| {
|
| - /* For non-GCC compilers expect their behavior is DWARF version
|
| - compliant. */
|
| + /* Skip any identifier after "GNU " - such as "C++" or "Java". */
|
|
|
| - return 0;
|
| + cs = &cu->producer[strlen ("GNU ")];
|
| + while (*cs && !isdigit (*cs))
|
| + cs++;
|
| + if (sscanf (cs, "%d.%d.%d", &major, &minor, &release) != 3)
|
| + {
|
| + /* Not recognized as GCC. */
|
| + }
|
| + else
|
| + cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
|
| }
|
| - cs = &cu->producer[strlen ("GNU ")];
|
| - while (*cs && !isdigit (*cs))
|
| - cs++;
|
| - if (sscanf (cs, "%d.%d.%d", &major, &minor, &release) != 3)
|
| + else if (strncmp (cu->producer, "Intel(R) C", strlen ("Intel(R) C")) == 0)
|
| + cu->producer_is_icc = 1;
|
| + else
|
| {
|
| - /* Not recognized as GCC. */
|
| -
|
| - return 0;
|
| + /* For other non-GCC compilers, expect their behavior is DWARF version
|
| + compliant. */
|
| }
|
|
|
| - return major < 4 || (major == 4 && minor < 6);
|
| + cu->checked_producer = 1;
|
| +}
|
| +
|
| +/* Check for GCC PR debug/45124 fix which is not present in any G++ version up
|
| + to 4.5.any while it is present already in G++ 4.6.0 - the PR has been fixed
|
| + during 4.6.0 experimental. */
|
| +
|
| +static int
|
| +producer_is_gxx_lt_4_6 (struct dwarf2_cu *cu)
|
| +{
|
| + if (!cu->checked_producer)
|
| + check_producer (cu);
|
| +
|
| + return cu->producer_is_gxx_lt_4_6;
|
| }
|
|
|
| /* Return the default accessibility type if it is not overriden by
|
| @@ -7110,7 +9668,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
|
| anonymous object to the MSB of the field. We don't
|
| have to do anything special since we don't need to
|
| know the size of the anonymous object. */
|
| - FIELD_BITPOS (*fp) += DW_UNSND (attr);
|
| + SET_FIELD_BITPOS (*fp, FIELD_BITPOS (*fp) + DW_UNSND (attr));
|
| }
|
| else
|
| {
|
| @@ -7139,8 +9697,10 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die,
|
| bit field. */
|
| anonymous_size = TYPE_LENGTH (fp->type);
|
| }
|
| - FIELD_BITPOS (*fp) += anonymous_size * bits_per_byte
|
| - - bit_offset - FIELD_BITSIZE (*fp);
|
| + SET_FIELD_BITPOS (*fp,
|
| + (FIELD_BITPOS (*fp)
|
| + + anonymous_size * bits_per_byte
|
| + - bit_offset - FIELD_BITSIZE (*fp)));
|
| }
|
| }
|
|
|
| @@ -7540,7 +10100,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die,
|
| complaint (&symfile_complaints,
|
| _("Member function \"%s\" (offset %d) is virtual "
|
| "but the vtable offset is not specified"),
|
| - fieldname, die->offset);
|
| + fieldname, die->offset.sect_off);
|
| ALLOCATE_CPLUS_STRUCT_TYPE (type);
|
| TYPE_CPLUS_DYNAMIC (type) = 1;
|
| }
|
| @@ -7554,7 +10114,6 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
|
| struct dwarf2_cu *cu)
|
| {
|
| struct fnfieldlist *flp;
|
| - int total_length = 0;
|
| int i;
|
|
|
| if (cu->language == language_ada)
|
| @@ -7576,12 +10135,9 @@ dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
|
| TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
|
| for (k = flp->length; (k--, nfp); nfp = nfp->next)
|
| fn_flp->fn_fields[k] = nfp->fnfield;
|
| -
|
| - total_length += flp->length;
|
| }
|
|
|
| TYPE_NFN_FIELDS (type) = fip->nfnfields;
|
| - TYPE_NFN_FIELDS_TOTAL (type) = total_length;
|
| }
|
|
|
| /* Returns non-zero if NAME is the name of a vtable member in CU's
|
| @@ -7647,6 +10203,18 @@ quirk_gcc_member_function_pointer (struct type *type, struct objfile *objfile)
|
| smash_to_methodptr_type (type, new_type);
|
| }
|
|
|
| +/* Return non-zero if the CU's PRODUCER string matches the Intel C/C++ compiler
|
| + (icc). */
|
| +
|
| +static int
|
| +producer_is_icc (struct dwarf2_cu *cu)
|
| +{
|
| + if (!cu->checked_producer)
|
| + check_producer (cu);
|
| +
|
| + return cu->producer_is_icc;
|
| +}
|
| +
|
| /* 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
|
| @@ -7675,7 +10243,7 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
| /* 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
|
| the chain and we want to go down. */
|
| - attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
|
| + attr = dwarf2_attr_no_follow (die, DW_AT_signature);
|
| if (attr)
|
| {
|
| struct dwarf2_cu *type_cu = cu;
|
| @@ -7749,7 +10317,14 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu)
|
| TYPE_LENGTH (type) = 0;
|
| }
|
|
|
| - TYPE_STUB_SUPPORTED (type) = 1;
|
| + if (producer_is_icc (cu))
|
| + {
|
| + /* ICC does not output the required DW_AT_declaration
|
| + on incomplete types, but gives them a size of zero. */
|
| + }
|
| + else
|
| + TYPE_STUB_SUPPORTED (type) = 1;
|
| +
|
| if (die_is_declaration (die, cu))
|
| TYPE_STUB (type) = 1;
|
| else if (attr == NULL && die->child == NULL
|
| @@ -7873,7 +10448,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| i >= TYPE_N_BASECLASSES (t);
|
| --i)
|
| {
|
| - char *fieldname = TYPE_FIELD_NAME (t, i);
|
| + const char *fieldname = TYPE_FIELD_NAME (t, i);
|
|
|
| if (is_vtable_name (fieldname, cu))
|
| {
|
| @@ -7948,7 +10523,7 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| TYPE_CPLUS_REALLY_JAVA (type) = cu->language == language_java;
|
| }
|
|
|
| - quirk_gcc_member_function_pointer (type, cu->objfile);
|
| + quirk_gcc_member_function_pointer (type, objfile);
|
|
|
| /* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
|
| snapshots) has been known to create a die giving a declaration
|
| @@ -7995,7 +10570,7 @@ read_enumeration_type (struct die_info *die, struct dwarf2_cu *cu)
|
| /* 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
|
| the chain and we want to go down. */
|
| - attr = dwarf2_attr_no_follow (die, DW_AT_signature, cu);
|
| + attr = dwarf2_attr_no_follow (die, DW_AT_signature);
|
| if (attr)
|
| {
|
| struct dwarf2_cu *type_cu = cu;
|
| @@ -8059,6 +10634,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| int num_fields = 0;
|
| int unsigned_enum = 1;
|
| char *name;
|
| + int flag_enum = 1;
|
| + ULONGEST mask = 0;
|
|
|
| child_die = die->child;
|
| while (child_die && child_die->tag)
|
| @@ -8074,7 +10651,14 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| sym = new_symbol (child_die, this_type, cu);
|
| if (SYMBOL_VALUE (sym) < 0)
|
| - unsigned_enum = 0;
|
| + {
|
| + unsigned_enum = 0;
|
| + flag_enum = 0;
|
| + }
|
| + else if ((mask & SYMBOL_VALUE (sym)) != 0)
|
| + flag_enum = 0;
|
| + else
|
| + mask |= SYMBOL_VALUE (sym);
|
|
|
| if ((num_fields % DW_FIELD_ALLOC_CHUNK) == 0)
|
| {
|
| @@ -8086,7 +10670,7 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| FIELD_NAME (fields[num_fields]) = SYMBOL_LINKAGE_NAME (sym);
|
| FIELD_TYPE (fields[num_fields]) = NULL;
|
| - SET_FIELD_BITPOS (fields[num_fields], SYMBOL_VALUE (sym));
|
| + SET_FIELD_ENUMVAL (fields[num_fields], SYMBOL_VALUE (sym));
|
| FIELD_BITSIZE (fields[num_fields]) = 0;
|
|
|
| num_fields++;
|
| @@ -8107,6 +10691,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| }
|
| if (unsigned_enum)
|
| TYPE_UNSIGNED (this_type) = 1;
|
| + if (flag_enum)
|
| + TYPE_FLAG_ENUM (this_type) = 1;
|
| }
|
|
|
| /* If we are reading an enum from a .debug_types unit, and the enum
|
| @@ -8117,16 +10703,17 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu)
|
| actually available. Note that we do not want to do this for all
|
| enums which are just declarations, because C++0x allows forward
|
| enum declarations. */
|
| - if (cu->per_cu->debug_types_section
|
| + if (cu->per_cu->is_debug_types
|
| && die_is_declaration (die, cu))
|
| {
|
| - struct signatured_type *type_sig;
|
| + struct signatured_type *sig_type;
|
|
|
| - type_sig
|
| + sig_type
|
| = lookup_signatured_type_at_offset (dwarf2_per_objfile->objfile,
|
| - cu->per_cu->debug_types_section,
|
| + cu->per_cu->info_or_types_section,
|
| cu->per_cu->offset);
|
| - if (type_sig->type_offset != die->offset)
|
| + 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;
|
| }
|
|
|
| @@ -8452,7 +11039,7 @@ read_module_type (struct die_info *die, struct dwarf2_cu *cu)
|
| if (!module_name)
|
| complaint (&symfile_complaints,
|
| _("DW_TAG_module has no name, offset 0x%x"),
|
| - die->offset);
|
| + die->offset.sect_off);
|
| type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile);
|
|
|
| /* determine_prefix uses TYPE_TAG_NAME. */
|
| @@ -8735,6 +11322,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu)
|
| static struct type *
|
| read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| struct type *type; /* Type that this function returns. */
|
| struct type *ftype; /* Function that returns above type. */
|
| struct attribute *attr;
|
| @@ -8780,7 +11368,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| if (die->child != NULL)
|
| {
|
| - struct type *void_type = objfile_type (cu->objfile)->builtin_void;
|
| + struct type *void_type = objfile_type (objfile)->builtin_void;
|
| struct die_info *child_die;
|
| int nparams, iparams;
|
|
|
| @@ -8890,14 +11478,26 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| const char *name = NULL;
|
| - struct type *this_type;
|
| + struct type *this_type, *target_type;
|
|
|
| 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;
|
| set_die_type (die, this_type, cu);
|
| - TYPE_TARGET_TYPE (this_type) = die_type (die, cu);
|
| + target_type = die_type (die, cu);
|
| + if (target_type != this_type)
|
| + TYPE_TARGET_TYPE (this_type) = target_type;
|
| + else
|
| + {
|
| + /* Self-referential typedefs are, it seems, not allowed by the DWARF
|
| + spec and cause infinite loops in GDB. */
|
| + complaint (&symfile_complaints,
|
| + _("Self-referential DW_TAG_typedef "
|
| + "- DIE at 0x%x [in module %s]"),
|
| + die->offset.sect_off, objfile->name);
|
| + TYPE_TARGET_TYPE (this_type) = NULL;
|
| + }
|
| return this_type;
|
| }
|
|
|
| @@ -9006,8 +11606,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
| struct type *base_type;
|
| struct type *range_type;
|
| struct attribute *attr;
|
| - LONGEST low = 0;
|
| - LONGEST high = -1;
|
| + LONGEST low, high;
|
| + int low_default_is_valid;
|
| char *name;
|
| LONGEST negative_mask;
|
|
|
| @@ -9020,10 +11620,35 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
| if (range_type)
|
| return range_type;
|
|
|
| - if (cu->language == language_fortran)
|
| + /* Set LOW_DEFAULT_IS_VALID if current language and DWARF version allow
|
| + omitting DW_AT_lower_bound. */
|
| + switch (cu->language)
|
| {
|
| - /* FORTRAN implies a lower bound of 1, if not given. */
|
| + case language_c:
|
| + case language_cplus:
|
| + low = 0;
|
| + low_default_is_valid = 1;
|
| + break;
|
| + case language_fortran:
|
| + low = 1;
|
| + low_default_is_valid = 1;
|
| + break;
|
| + case language_d:
|
| + case language_java:
|
| + case language_objc:
|
| + low = 0;
|
| + low_default_is_valid = (cu->header.version >= 4);
|
| + break;
|
| + case language_ada:
|
| + case language_m2:
|
| + case language_pascal:
|
| low = 1;
|
| + low_default_is_valid = (cu->header.version >= 4);
|
| + break;
|
| + default:
|
| + low = 0;
|
| + low_default_is_valid = 0;
|
| + break;
|
| }
|
|
|
| /* FIXME: For variable sized arrays either of these could be
|
| @@ -9031,7 +11656,11 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu)
|
| but we don't know how to handle it. */
|
| attr = dwarf2_attr (die, DW_AT_lower_bound, cu);
|
| if (attr)
|
| - low = dwarf2_get_attr_constant_value (attr, 0);
|
| + low = dwarf2_get_attr_constant_value (attr, low);
|
| + 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);
|
|
|
| attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
|
| if (attr)
|
| @@ -9155,92 +11784,6 @@ read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu)
|
| return set_die_type (die, type, cu);
|
| }
|
|
|
| -/* Trivial hash function for die_info: the hash value of a DIE
|
| - is its offset in .debug_info for this objfile. */
|
| -
|
| -static hashval_t
|
| -die_hash (const void *item)
|
| -{
|
| - const struct die_info *die = item;
|
| -
|
| - return die->offset;
|
| -}
|
| -
|
| -/* Trivial comparison function for die_info structures: two DIEs
|
| - are equal if they have the same offset. */
|
| -
|
| -static int
|
| -die_eq (const void *item_lhs, const void *item_rhs)
|
| -{
|
| - const struct die_info *die_lhs = item_lhs;
|
| - const struct die_info *die_rhs = item_rhs;
|
| -
|
| - return die_lhs->offset == die_rhs->offset;
|
| -}
|
| -
|
| -/* Read a whole compilation unit into a linked list of dies. */
|
| -
|
| -static struct die_info *
|
| -read_comp_unit (gdb_byte *info_ptr, struct dwarf2_cu *cu)
|
| -{
|
| - struct die_reader_specs reader_specs;
|
| - int read_abbrevs = 0;
|
| - struct cleanup *back_to = NULL;
|
| - struct die_info *die;
|
| -
|
| - if (cu->dwarf2_abbrevs == NULL)
|
| - {
|
| - dwarf2_read_abbrevs (cu->objfile->obfd, cu);
|
| - back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
|
| - read_abbrevs = 1;
|
| - }
|
| -
|
| - gdb_assert (cu->die_hash == NULL);
|
| - cu->die_hash
|
| - = htab_create_alloc_ex (cu->header.length / 12,
|
| - die_hash,
|
| - die_eq,
|
| - NULL,
|
| - &cu->comp_unit_obstack,
|
| - hashtab_obstack_allocate,
|
| - dummy_obstack_deallocate);
|
| -
|
| - init_cu_die_reader (&reader_specs, cu);
|
| -
|
| - die = read_die_and_children (&reader_specs, info_ptr, &info_ptr, NULL);
|
| -
|
| - if (read_abbrevs)
|
| - do_cleanups (back_to);
|
| -
|
| - return die;
|
| -}
|
| -
|
| -/* Main entry point for reading a DIE and all children.
|
| - Read the DIE and dump it if requested. */
|
| -
|
| -static struct die_info *
|
| -read_die_and_children (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| - struct die_info *parent)
|
| -{
|
| - struct die_info *result = read_die_and_children_1 (reader, info_ptr,
|
| - new_info_ptr, parent);
|
| -
|
| - if (dwarf2_die_debug)
|
| - {
|
| - fprintf_unfiltered (gdb_stdlog,
|
| - "\nRead die from %s of %s:\n",
|
| - (reader->cu->per_cu->debug_types_section
|
| - ? ".debug_types"
|
| - : ".debug_info"),
|
| - reader->abfd->filename);
|
| - dump_die (result, dwarf2_die_debug);
|
| - }
|
| -
|
| - return result;
|
| -}
|
| -
|
| /* Read a single die and all its descendents. Set the die's sibling
|
| field to NULL; set other fields in the die correctly, and set all
|
| of the descendents' fields correctly. Set *NEW_INFO_PTR to the
|
| @@ -9248,10 +11791,10 @@ read_die_and_children (const struct die_reader_specs *reader,
|
| is the parent of the die in question. */
|
|
|
| static struct die_info *
|
| -read_die_and_children_1 (const struct die_reader_specs *reader,
|
| - gdb_byte *info_ptr,
|
| - gdb_byte **new_info_ptr,
|
| - struct die_info *parent)
|
| +read_die_and_children (const struct die_reader_specs *reader,
|
| + gdb_byte *info_ptr,
|
| + gdb_byte **new_info_ptr,
|
| + struct die_info *parent)
|
| {
|
| struct die_info *die;
|
| gdb_byte *cur_ptr;
|
| @@ -9297,7 +11840,7 @@ read_die_and_siblings (const struct die_reader_specs *reader,
|
| while (1)
|
| {
|
| struct die_info *die
|
| - = read_die_and_children_1 (reader, cur_ptr, &cur_ptr, parent);
|
| + = read_die_and_children (reader, cur_ptr, &cur_ptr, parent);
|
|
|
| if (die == NULL)
|
| {
|
| @@ -9314,23 +11857,27 @@ read_die_and_siblings (const struct die_reader_specs *reader,
|
| }
|
| }
|
|
|
| -/* Read the die from the .debug_info section buffer. Set DIEP to
|
| - point to a newly allocated die with its information, except for its
|
| - child, sibling, and parent fields. Set HAS_CHILDREN to tell
|
| - whether the die has children or not. */
|
| +/* Read a die and all its attributes, leave space for NUM_EXTRA_ATTRS
|
| + attributes.
|
| + The caller is responsible for filling in the extra attributes
|
| + and updating (*DIEP)->num_attrs.
|
| + Set DIEP to point to a newly allocated die with its information,
|
| + except for its child, sibling, and parent fields.
|
| + Set HAS_CHILDREN to tell whether the die has children or not. */
|
|
|
| static gdb_byte *
|
| -read_full_die (const struct die_reader_specs *reader,
|
| - struct die_info **diep, gdb_byte *info_ptr,
|
| - int *has_children)
|
| +read_full_die_1 (const struct die_reader_specs *reader,
|
| + struct die_info **diep, gdb_byte *info_ptr,
|
| + int *has_children, int num_extra_attrs)
|
| {
|
| - unsigned int abbrev_number, bytes_read, i, offset;
|
| + unsigned int abbrev_number, bytes_read, i;
|
| + sect_offset offset;
|
| struct abbrev_info *abbrev;
|
| struct die_info *die;
|
| struct dwarf2_cu *cu = reader->cu;
|
| bfd *abfd = reader->abfd;
|
|
|
| - offset = info_ptr - reader->buffer;
|
| + offset.sect_off = info_ptr - reader->buffer;
|
| abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
| info_ptr += bytes_read;
|
| if (!abbrev_number)
|
| @@ -9340,56 +11887,127 @@ read_full_die (const struct die_reader_specs *reader,
|
| return info_ptr;
|
| }
|
|
|
| - abbrev = dwarf2_lookup_abbrev (abbrev_number, cu);
|
| + abbrev = abbrev_table_lookup_abbrev (cu->abbrev_table, abbrev_number);
|
| if (!abbrev)
|
| error (_("Dwarf Error: could not find abbrev number %d [in module %s]"),
|
| abbrev_number,
|
| bfd_get_filename (abfd));
|
|
|
| - die = dwarf_alloc_die (cu, abbrev->num_attrs);
|
| + die = dwarf_alloc_die (cu, abbrev->num_attrs + num_extra_attrs);
|
| die->offset = offset;
|
| die->tag = abbrev->tag;
|
| die->abbrev = abbrev_number;
|
|
|
| + /* Make the result usable.
|
| + The caller needs to update num_attrs after adding the extra
|
| + attributes. */
|
| die->num_attrs = abbrev->num_attrs;
|
|
|
| for (i = 0; i < abbrev->num_attrs; ++i)
|
| - info_ptr = read_attribute (&die->attrs[i], &abbrev->attrs[i],
|
| - abfd, info_ptr, cu);
|
| + info_ptr = read_attribute (reader, &die->attrs[i], &abbrev->attrs[i],
|
| + info_ptr);
|
|
|
| *diep = die;
|
| *has_children = abbrev->has_children;
|
| return info_ptr;
|
| }
|
|
|
| -/* In DWARF version 2, the description of the debugging information is
|
| +/* Read a die and all its attributes.
|
| + Set DIEP to point to a newly allocated die with its information,
|
| + except for its child, sibling, and parent fields.
|
| + Set HAS_CHILDREN to tell whether the die has children or not. */
|
| +
|
| +static gdb_byte *
|
| +read_full_die (const struct die_reader_specs *reader,
|
| + struct die_info **diep, gdb_byte *info_ptr,
|
| + int *has_children)
|
| +{
|
| + return read_full_die_1 (reader, diep, info_ptr, has_children, 0);
|
| +}
|
| +
|
| +/* Abbreviation tables.
|
| +
|
| + In DWARF version 2, the description of the debugging information is
|
| stored in a separate .debug_abbrev section. Before we read any
|
| dies from a section we read in all abbreviations and install them
|
| - in a hash table. This function also sets flags in CU describing
|
| - the data found in the abbrev table. */
|
| + in a hash table. */
|
| +
|
| +/* Allocate space for a struct abbrev_info object in ABBREV_TABLE. */
|
| +
|
| +static struct abbrev_info *
|
| +abbrev_table_alloc_abbrev (struct abbrev_table *abbrev_table)
|
| +{
|
| + struct abbrev_info *abbrev;
|
| +
|
| + abbrev = (struct abbrev_info *)
|
| + obstack_alloc (&abbrev_table->abbrev_obstack, sizeof (struct abbrev_info));
|
| + memset (abbrev, 0, sizeof (struct abbrev_info));
|
| + return abbrev;
|
| +}
|
| +
|
| +/* Add an abbreviation to the table. */
|
|
|
| static void
|
| -dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
|
| +abbrev_table_add_abbrev (struct abbrev_table *abbrev_table,
|
| + unsigned int abbrev_number,
|
| + struct abbrev_info *abbrev)
|
| {
|
| - struct comp_unit_head *cu_header = &cu->header;
|
| + unsigned int hash_number;
|
| +
|
| + hash_number = abbrev_number % ABBREV_HASH_SIZE;
|
| + abbrev->next = abbrev_table->abbrevs[hash_number];
|
| + abbrev_table->abbrevs[hash_number] = abbrev;
|
| +}
|
| +
|
| +/* Look up an abbrev in the table.
|
| + Returns NULL if the abbrev is not found. */
|
| +
|
| +static struct abbrev_info *
|
| +abbrev_table_lookup_abbrev (const struct abbrev_table *abbrev_table,
|
| + unsigned int abbrev_number)
|
| +{
|
| + unsigned int hash_number;
|
| + struct abbrev_info *abbrev;
|
| +
|
| + hash_number = abbrev_number % ABBREV_HASH_SIZE;
|
| + abbrev = abbrev_table->abbrevs[hash_number];
|
| +
|
| + while (abbrev)
|
| + {
|
| + if (abbrev->number == abbrev_number)
|
| + return abbrev;
|
| + abbrev = abbrev->next;
|
| + }
|
| + return NULL;
|
| +}
|
| +
|
| +/* Read in an abbrev table. */
|
| +
|
| +static struct abbrev_table *
|
| +abbrev_table_read_table (struct dwarf2_section_info *section,
|
| + sect_offset offset)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + bfd *abfd = section->asection->owner;
|
| + struct abbrev_table *abbrev_table;
|
| gdb_byte *abbrev_ptr;
|
| struct abbrev_info *cur_abbrev;
|
| unsigned int abbrev_number, bytes_read, abbrev_name;
|
| - unsigned int abbrev_form, hash_number;
|
| + unsigned int abbrev_form;
|
| struct attr_abbrev *cur_attrs;
|
| unsigned int allocated_attrs;
|
|
|
| - /* Initialize dwarf2 abbrevs. */
|
| - obstack_init (&cu->abbrev_obstack);
|
| - cu->dwarf2_abbrevs = obstack_alloc (&cu->abbrev_obstack,
|
| - (ABBREV_HASH_SIZE
|
| - * sizeof (struct abbrev_info *)));
|
| - memset (cu->dwarf2_abbrevs, 0,
|
| - ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
|
| -
|
| - dwarf2_read_section (dwarf2_per_objfile->objfile,
|
| - &dwarf2_per_objfile->abbrev);
|
| - abbrev_ptr = dwarf2_per_objfile->abbrev.buffer + cu_header->abbrev_offset;
|
| + abbrev_table = XMALLOC (struct abbrev_table);
|
| + abbrev_table->offset = offset;
|
| + obstack_init (&abbrev_table->abbrev_obstack);
|
| + abbrev_table->abbrevs = obstack_alloc (&abbrev_table->abbrev_obstack,
|
| + (ABBREV_HASH_SIZE
|
| + * sizeof (struct abbrev_info *)));
|
| + memset (abbrev_table->abbrevs, 0,
|
| + ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
|
| +
|
| + dwarf2_read_section (objfile, section);
|
| + abbrev_ptr = section->buffer + offset.sect_off;
|
| abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
| abbrev_ptr += bytes_read;
|
|
|
| @@ -9399,7 +12017,7 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
|
| /* Loop until we reach an abbrev number of 0. */
|
| while (abbrev_number)
|
| {
|
| - cur_abbrev = dwarf_alloc_abbrev (cu);
|
| + cur_abbrev = abbrev_table_alloc_abbrev (abbrev_table);
|
|
|
| /* read in abbrev header */
|
| cur_abbrev->number = abbrev_number;
|
| @@ -9408,9 +12026,6 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
|
| cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
|
| abbrev_ptr += 1;
|
|
|
| - if (cur_abbrev->tag == DW_TAG_namespace)
|
| - cu->has_namespace_info = 1;
|
| -
|
| /* now read in declarations */
|
| abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
| abbrev_ptr += bytes_read;
|
| @@ -9426,16 +12041,6 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
|
| * sizeof (struct attr_abbrev)));
|
| }
|
|
|
| - /* Record whether this compilation unit might have
|
| - inter-compilation-unit references. If we don't know what form
|
| - this attribute will have, then it might potentially be a
|
| - DW_FORM_ref_addr, so we conservatively expect inter-CU
|
| - references. */
|
| -
|
| - if (abbrev_form == DW_FORM_ref_addr
|
| - || abbrev_form == DW_FORM_indirect)
|
| - cu->has_form_ref_addr = 1;
|
| -
|
| cur_attrs[cur_abbrev->num_attrs].name = abbrev_name;
|
| cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form;
|
| abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
| @@ -9444,15 +12049,13 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
|
| abbrev_ptr += bytes_read;
|
| }
|
|
|
| - cur_abbrev->attrs = obstack_alloc (&cu->abbrev_obstack,
|
| + cur_abbrev->attrs = obstack_alloc (&abbrev_table->abbrev_obstack,
|
| (cur_abbrev->num_attrs
|
| * sizeof (struct attr_abbrev)));
|
| memcpy (cur_abbrev->attrs, cur_attrs,
|
| cur_abbrev->num_attrs * sizeof (struct attr_abbrev));
|
|
|
| - hash_number = abbrev_number % ABBREV_HASH_SIZE;
|
| - cur_abbrev->next = cu->dwarf2_abbrevs[hash_number];
|
| - cu->dwarf2_abbrevs[hash_number] = cur_abbrev;
|
| + abbrev_table_add_abbrev (abbrev_table, abbrev_number, cur_abbrev);
|
|
|
| /* Get next abbreviation.
|
| Under Irix6 the abbreviations for a compilation unit are not
|
| @@ -9461,50 +12064,65 @@ dwarf2_read_abbrevs (bfd *abfd, struct dwarf2_cu *cu)
|
| already read (which means we are about to read the abbreviations
|
| for the next compile unit) or if the end of the abbreviation
|
| table is reached. */
|
| - if ((unsigned int) (abbrev_ptr - dwarf2_per_objfile->abbrev.buffer)
|
| - >= dwarf2_per_objfile->abbrev.size)
|
| + if ((unsigned int) (abbrev_ptr - section->buffer) >= section->size)
|
| break;
|
| abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
|
| abbrev_ptr += bytes_read;
|
| - if (dwarf2_lookup_abbrev (abbrev_number, cu) != NULL)
|
| + if (abbrev_table_lookup_abbrev (abbrev_table, abbrev_number) != NULL)
|
| break;
|
| }
|
|
|
| xfree (cur_attrs);
|
| + return abbrev_table;
|
| }
|
|
|
| -/* Release the memory used by the abbrev table for a compilation unit. */
|
| +/* Free the resources held by ABBREV_TABLE. */
|
|
|
| static void
|
| -dwarf2_free_abbrev_table (void *ptr_to_cu)
|
| +abbrev_table_free (struct abbrev_table *abbrev_table)
|
| {
|
| - struct dwarf2_cu *cu = ptr_to_cu;
|
| -
|
| - obstack_free (&cu->abbrev_obstack, NULL);
|
| - cu->dwarf2_abbrevs = NULL;
|
| + obstack_free (&abbrev_table->abbrev_obstack, NULL);
|
| + xfree (abbrev_table);
|
| }
|
|
|
| -/* Lookup an abbrev_info structure in the abbrev hash table. */
|
| +/* Same as abbrev_table_free but as a cleanup.
|
| + We pass in a pointer to the pointer to the table so that we can
|
| + set the pointer to NULL when we're done. It also simplifies
|
| + build_type_unit_groups. */
|
|
|
| -static struct abbrev_info *
|
| -dwarf2_lookup_abbrev (unsigned int number, struct dwarf2_cu *cu)
|
| +static void
|
| +abbrev_table_free_cleanup (void *table_ptr)
|
| {
|
| - unsigned int hash_number;
|
| - struct abbrev_info *abbrev;
|
| + struct abbrev_table **abbrev_table_ptr = table_ptr;
|
|
|
| - hash_number = number % ABBREV_HASH_SIZE;
|
| - abbrev = cu->dwarf2_abbrevs[hash_number];
|
| + if (*abbrev_table_ptr != NULL)
|
| + abbrev_table_free (*abbrev_table_ptr);
|
| + *abbrev_table_ptr = NULL;
|
| +}
|
|
|
| - while (abbrev)
|
| - {
|
| - if (abbrev->number == number)
|
| - return abbrev;
|
| - else
|
| - abbrev = abbrev->next;
|
| - }
|
| - return NULL;
|
| +/* Read the abbrev table for CU from ABBREV_SECTION. */
|
| +
|
| +static void
|
| +dwarf2_read_abbrevs (struct dwarf2_cu *cu,
|
| + struct dwarf2_section_info *abbrev_section)
|
| +{
|
| + cu->abbrev_table =
|
| + abbrev_table_read_table (abbrev_section, cu->header.abbrev_offset);
|
| }
|
|
|
| +/* Release the memory used by the abbrev table for a compilation unit. */
|
| +
|
| +static void
|
| +dwarf2_free_abbrev_table (void *ptr_to_cu)
|
| +{
|
| + struct dwarf2_cu *cu = ptr_to_cu;
|
| +
|
| + 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;
|
| +}
|
| +
|
| /* Returns nonzero if TAG represents a type that we might generate a partial
|
| symbol for. */
|
|
|
| @@ -9540,21 +12158,23 @@ is_type_tag_for_partial (int tag)
|
| /* Load all DIEs that are interesting for partial symbols into memory. */
|
|
|
| static struct partial_die_info *
|
| -load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| - int building_psymtab, struct dwarf2_cu *cu)
|
| +load_partial_dies (const struct die_reader_specs *reader,
|
| + gdb_byte *info_ptr, int building_psymtab)
|
| {
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + struct objfile *objfile = cu->objfile;
|
| struct partial_die_info *part_die;
|
| struct partial_die_info *parent_die, *last_die, *first_die = NULL;
|
| struct abbrev_info *abbrev;
|
| unsigned int bytes_read;
|
| unsigned int load_all = 0;
|
| -
|
| int nesting_level = 1;
|
|
|
| parent_die = NULL;
|
| last_die = NULL;
|
|
|
| - if (cu->per_cu && cu->per_cu->load_all_dies)
|
| + gdb_assert (cu->per_cu != NULL);
|
| + if (cu->per_cu->load_all_dies)
|
| load_all = 1;
|
|
|
| cu->partial_dies
|
| @@ -9604,20 +12224,19 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| if (!load_all)
|
| {
|
| /* We don't need a partial DIE for the template argument. */
|
| - info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev,
|
| - cu);
|
| + info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
|
| continue;
|
| }
|
| }
|
|
|
| - /* We only recurse into subprograms looking for template arguments.
|
| + /* We only recurse into c++ subprograms looking for template arguments.
|
| Skip their other children. */
|
| if (!load_all
|
| && cu->language == language_cplus
|
| && parent_die != NULL
|
| && parent_die->tag == DW_TAG_subprogram)
|
| {
|
| - info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu);
|
| + info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
|
| continue;
|
| }
|
|
|
| @@ -9634,15 +12253,16 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| && abbrev->tag != DW_TAG_variable
|
| && abbrev->tag != DW_TAG_namespace
|
| && abbrev->tag != DW_TAG_module
|
| - && abbrev->tag != DW_TAG_member)
|
| + && abbrev->tag != DW_TAG_member
|
| + && abbrev->tag != DW_TAG_imported_unit)
|
| {
|
| /* Otherwise we skip to the next sibling, if any. */
|
| - info_ptr = skip_one_die (buffer, info_ptr + bytes_read, abbrev, cu);
|
| + info_ptr = skip_one_die (reader, info_ptr + bytes_read, abbrev);
|
| continue;
|
| }
|
|
|
| - info_ptr = read_partial_die (part_die, abbrev, bytes_read, abfd,
|
| - buffer, info_ptr, cu);
|
| + info_ptr = read_partial_die (reader, part_die, abbrev, bytes_read,
|
| + info_ptr);
|
|
|
| /* This two-pass algorithm for processing partial symbols has a
|
| high cost in cache pressure. Thus, handle some simple cases
|
| @@ -9670,9 +12290,9 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| if (building_psymtab && part_die->name != NULL)
|
| add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
|
| VAR_DOMAIN, LOC_TYPEDEF,
|
| - &cu->objfile->static_psymbols,
|
| - 0, (CORE_ADDR) 0, cu->language, cu->objfile);
|
| - info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
|
| + &objfile->static_psymbols,
|
| + 0, (CORE_ADDR) 0, cu->language, objfile);
|
| + info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
|
| continue;
|
| }
|
|
|
| @@ -9688,7 +12308,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| complaint (&symfile_complaints,
|
| _("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
|
| "- DIE at 0x%x [in module %s]"),
|
| - part_die->offset, cu->objfile->name);
|
| + part_die->offset.sect_off, objfile->name);
|
|
|
| /* If we're at the second level, and we're an enumerator, and
|
| our parent has no specification (meaning possibly lives in a
|
| @@ -9708,11 +12328,11 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| VAR_DOMAIN, LOC_CONST,
|
| (cu->language == language_cplus
|
| || cu->language == language_java)
|
| - ? &cu->objfile->global_psymbols
|
| - : &cu->objfile->static_psymbols,
|
| - 0, (CORE_ADDR) 0, cu->language, cu->objfile);
|
| + ? &objfile->global_psymbols
|
| + : &objfile->static_psymbols,
|
| + 0, (CORE_ADDR) 0, cu->language, objfile);
|
|
|
| - info_ptr = locate_pdi_sibling (part_die, buffer, info_ptr, abfd, cu);
|
| + info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
|
| continue;
|
| }
|
|
|
| @@ -9762,7 +12382,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| void **slot;
|
|
|
| slot = htab_find_slot_with_hash (cu->partial_dies, part_die,
|
| - part_die->offset, INSERT);
|
| + part_die->offset.sect_off, INSERT);
|
| *slot = part_die;
|
| }
|
|
|
| @@ -9805,7 +12425,7 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| }
|
|
|
| /* Otherwise we skip to the next sibling, if any. */
|
| - info_ptr = locate_pdi_sibling (last_die, buffer, info_ptr, abfd, cu);
|
| + info_ptr = locate_pdi_sibling (reader, last_die, info_ptr);
|
|
|
| /* Back to the top, do it again. */
|
| }
|
| @@ -9814,20 +12434,23 @@ load_partial_dies (bfd *abfd, gdb_byte *buffer, gdb_byte *info_ptr,
|
| /* Read a minimal amount of information into the minimal die structure. */
|
|
|
| static gdb_byte *
|
| -read_partial_die (struct partial_die_info *part_die,
|
| - struct abbrev_info *abbrev,
|
| - unsigned int abbrev_len, bfd *abfd,
|
| - gdb_byte *buffer, gdb_byte *info_ptr,
|
| - struct dwarf2_cu *cu)
|
| +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)
|
| {
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + struct objfile *objfile = cu->objfile;
|
| + gdb_byte *buffer = reader->buffer;
|
| unsigned int i;
|
| struct attribute attr;
|
| int has_low_pc_attr = 0;
|
| int has_high_pc_attr = 0;
|
| + int high_pc_relative = 0;
|
|
|
| memset (part_die, 0, sizeof (struct partial_die_info));
|
|
|
| - part_die->offset = info_ptr - buffer;
|
| + part_die->offset.sect_off = info_ptr - buffer;
|
|
|
| info_ptr += abbrev_len;
|
|
|
| @@ -9839,7 +12462,7 @@ read_partial_die (struct partial_die_info *part_die,
|
|
|
| for (i = 0; i < abbrev->num_attrs; ++i)
|
| {
|
| - info_ptr = read_attribute (&attr, &abbrev->attrs[i], abfd, info_ptr, cu);
|
| + info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
|
|
|
| /* Store the data if it is of an attribute we want to keep in a
|
| partial symbol table. */
|
| @@ -9849,6 +12472,7 @@ read_partial_die (struct partial_die_info *part_die,
|
| switch (part_die->tag)
|
| {
|
| case DW_TAG_compile_unit:
|
| + case DW_TAG_partial_unit:
|
| case DW_TAG_type_unit:
|
| /* Compilation units have a DW_AT_name that is a filename, not
|
| a source language identifier. */
|
| @@ -9861,7 +12485,7 @@ read_partial_die (struct partial_die_info *part_die,
|
| default:
|
| part_die->name
|
| = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
|
| - &cu->objfile->objfile_obstack);
|
| + &objfile->objfile_obstack);
|
| break;
|
| }
|
| break;
|
| @@ -9880,13 +12504,20 @@ read_partial_die (struct partial_die_info *part_die,
|
| break;
|
| case DW_AT_high_pc:
|
| has_high_pc_attr = 1;
|
| - part_die->highpc = DW_ADDR (&attr);
|
| + if (attr.form == DW_FORM_addr
|
| + || attr.form == DW_FORM_GNU_addr_index)
|
| + part_die->highpc = DW_ADDR (&attr);
|
| + else
|
| + {
|
| + high_pc_relative = 1;
|
| + part_die->highpc = DW_UNSND (&attr);
|
| + }
|
| break;
|
| case DW_AT_location:
|
| /* Support the .debug_loc offsets. */
|
| if (attr_form_is_block (&attr))
|
| {
|
| - part_die->locdesc = DW_BLOCK (&attr);
|
| + part_die->d.locdesc = DW_BLOCK (&attr);
|
| }
|
| else if (attr_form_is_section_offset (&attr))
|
| {
|
| @@ -9920,7 +12551,7 @@ read_partial_die (struct partial_die_info *part_die,
|
| complaint (&symfile_complaints,
|
| _("ignoring absolute DW_AT_sibling"));
|
| else
|
| - part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr);
|
| + part_die->sibling = buffer + dwarf2_get_ref_die_offset (&attr).sect_off;
|
| break;
|
| case DW_AT_byte_size:
|
| part_die->has_byte_size = 1;
|
| @@ -9950,11 +12581,25 @@ read_partial_die (struct partial_die_info *part_die,
|
| language_of_main = language_fortran;
|
| }
|
| break;
|
| + case DW_AT_inline:
|
| + if (DW_UNSND (&attr) == DW_INL_inlined
|
| + || DW_UNSND (&attr) == DW_INL_declared_inlined)
|
| + part_die->may_be_inlined = 1;
|
| + break;
|
| +
|
| + case DW_AT_import:
|
| + if (part_die->tag == DW_TAG_imported_unit)
|
| + part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
|
| + break;
|
| +
|
| default:
|
| break;
|
| }
|
| }
|
|
|
| + if (high_pc_relative)
|
| + part_die->highpc += part_die->lowpc;
|
| +
|
| if (has_low_pc_attr && has_high_pc_attr)
|
| {
|
| /* When using the GNU linker, .gnu.linkonce. sections are used to
|
| @@ -9967,25 +12612,25 @@ read_partial_die (struct partial_die_info *part_die,
|
| so that GDB will ignore it. */
|
| if (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
|
| {
|
| - struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
|
| + struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
|
|
| complaint (&symfile_complaints,
|
| _("DW_AT_low_pc %s is zero "
|
| "for DIE at 0x%x [in module %s]"),
|
| paddress (gdbarch, part_die->lowpc),
|
| - part_die->offset, cu->objfile->name);
|
| + part_die->offset.sect_off, objfile->name);
|
| }
|
| /* dwarf2_get_pc_bounds has also the strict low < high requirement. */
|
| else if (part_die->lowpc >= part_die->highpc)
|
| {
|
| - struct gdbarch *gdbarch = get_objfile_arch (cu->objfile);
|
| + struct gdbarch *gdbarch = get_objfile_arch (objfile);
|
|
|
| complaint (&symfile_complaints,
|
| _("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
|
| "for DIE at 0x%x [in module %s]"),
|
| paddress (gdbarch, part_die->lowpc),
|
| paddress (gdbarch, part_die->highpc),
|
| - part_die->offset, cu->objfile->name);
|
| + part_die->offset.sect_off, objfile->name);
|
| }
|
| else
|
| part_die->has_pc_info = 1;
|
| @@ -9997,13 +12642,14 @@ read_partial_die (struct partial_die_info *part_die,
|
| /* Find a cached partial DIE at OFFSET in CU. */
|
|
|
| static struct partial_die_info *
|
| -find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu)
|
| +find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
|
| {
|
| struct partial_die_info *lookup_die = NULL;
|
| struct partial_die_info part_die;
|
|
|
| part_die.offset = offset;
|
| - lookup_die = htab_find_with_hash (cu->partial_dies, &part_die, offset);
|
| + lookup_die = htab_find_with_hash (cu->partial_dies, &part_die,
|
| + offset.sect_off);
|
|
|
| return lookup_die;
|
| }
|
| @@ -10014,75 +12660,63 @@ find_partial_die_in_comp_unit (unsigned int offset, struct dwarf2_cu *cu)
|
| DW_FORM_ref_sig8). */
|
|
|
| static struct partial_die_info *
|
| -find_partial_die (unsigned int offset, struct dwarf2_cu *cu)
|
| +find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| struct dwarf2_per_cu_data *per_cu = NULL;
|
| struct partial_die_info *pd = NULL;
|
|
|
| - if (cu->per_cu->debug_types_section)
|
| - {
|
| - pd = find_partial_die_in_comp_unit (offset, cu);
|
| - if (pd != NULL)
|
| - return pd;
|
| - goto not_found;
|
| - }
|
| -
|
| if (offset_in_cu_p (&cu->header, offset))
|
| {
|
| pd = find_partial_die_in_comp_unit (offset, cu);
|
| if (pd != NULL)
|
| return pd;
|
| + /* We missed recording what we needed.
|
| + Load all dies and try again. */
|
| + per_cu = cu->per_cu;
|
| }
|
| + else
|
| + {
|
| + /* TUs don't reference other CUs/TUs (except via type signatures). */
|
| + if (cu->per_cu->is_debug_types)
|
| + {
|
| + error (_("Dwarf Error: Type Unit at offset 0x%lx contains"
|
| + " external reference to offset 0x%lx [in module %s].\n"),
|
| + (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, cu->objfile);
|
| + if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
|
| + load_partial_comp_unit (per_cu);
|
|
|
| - if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
|
| - load_partial_comp_unit (per_cu, cu->objfile);
|
| + per_cu->cu->last_used = 0;
|
| + pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
|
| + }
|
|
|
| - per_cu->cu->last_used = 0;
|
| - pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
|
| + /* If we didn't find it, and not all dies have been loaded,
|
| + load them all and try again. */
|
|
|
| if (pd == NULL && per_cu->load_all_dies == 0)
|
| {
|
| - struct cleanup *back_to;
|
| - struct partial_die_info comp_unit_die;
|
| - struct abbrev_info *abbrev;
|
| - unsigned int bytes_read;
|
| - char *info_ptr;
|
| -
|
| per_cu->load_all_dies = 1;
|
|
|
| - /* Re-read the DIEs. */
|
| - back_to = make_cleanup (null_cleanup, 0);
|
| - if (per_cu->cu->dwarf2_abbrevs == NULL)
|
| - {
|
| - dwarf2_read_abbrevs (per_cu->cu->objfile->obfd, per_cu->cu);
|
| - make_cleanup (dwarf2_free_abbrev_table, per_cu->cu);
|
| - }
|
| - info_ptr = (dwarf2_per_objfile->info.buffer
|
| - + per_cu->cu->header.offset
|
| - + per_cu->cu->header.first_die_offset);
|
| - abbrev = peek_die_abbrev (info_ptr, &bytes_read, per_cu->cu);
|
| - info_ptr = read_partial_die (&comp_unit_die, abbrev, bytes_read,
|
| - per_cu->cu->objfile->obfd,
|
| - dwarf2_per_objfile->info.buffer, info_ptr,
|
| - per_cu->cu);
|
| - if (comp_unit_die.has_children)
|
| - load_partial_dies (per_cu->cu->objfile->obfd,
|
| - dwarf2_per_objfile->info.buffer, info_ptr,
|
| - 0, per_cu->cu);
|
| - do_cleanups (back_to);
|
| + /* This is nasty. When we reread the DIEs, somewhere up the call chain
|
| + THIS_CU->cu may already be in use. So we can't just free it and
|
| + replace its DIEs with the ones we read in. Instead, we leave those
|
| + DIEs alone (which can still be in use, e.g. in scan_partial_symbols),
|
| + and clobber THIS_CU->cu->partial_dies with the hash table for the new
|
| + set. */
|
| + load_partial_comp_unit (per_cu);
|
|
|
| pd = find_partial_die_in_comp_unit (offset, per_cu->cu);
|
| }
|
|
|
| - not_found:
|
| -
|
| if (pd == NULL)
|
| internal_error (__FILE__, __LINE__,
|
| _("could not find partial DIE 0x%x "
|
| "in cache [from module %s]\n"),
|
| - offset, bfd_get_filename (cu->objfile->obfd));
|
| + offset.sect_off, bfd_get_filename (objfile->obfd));
|
| return pd;
|
| }
|
|
|
| @@ -10178,9 +12812,7 @@ fixup_partial_die (struct partial_die_info *part_die,
|
|
|
| /* If there is no parent die to provide a namespace, and there are
|
| children, see if we can determine the namespace from their linkage
|
| - name.
|
| - NOTE: We need to do this even if cu->has_namespace_info != 0.
|
| - gcc-4.5 -gdwarf-4 can drop the enclosing namespace. */
|
| + name. */
|
| if (cu->language == language_cplus
|
| && !VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types)
|
| && part_die->die_parent == NULL
|
| @@ -10226,10 +12858,12 @@ fixup_partial_die (struct partial_die_info *part_die,
|
| /* Read an attribute value described by an attribute form. */
|
|
|
| static gdb_byte *
|
| -read_attribute_value (struct attribute *attr, unsigned form,
|
| - bfd *abfd, gdb_byte *info_ptr,
|
| - struct dwarf2_cu *cu)
|
| +read_attribute_value (const struct die_reader_specs *reader,
|
| + struct attribute *attr, unsigned form,
|
| + gdb_byte *info_ptr)
|
| {
|
| + struct dwarf2_cu *cu = reader->cu;
|
| + bfd *abfd = reader->abfd;
|
| struct comp_unit_head *cu_header = &cu->header;
|
| unsigned int bytes_read;
|
| struct dwarf_block *blk;
|
| @@ -10239,10 +12873,10 @@ read_attribute_value (struct attribute *attr, unsigned form,
|
| {
|
| case DW_FORM_ref_addr:
|
| if (cu->header.version == 2)
|
| - DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
|
| + DW_UNSND (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
|
| else
|
| - DW_ADDR (attr) = read_offset (abfd, info_ptr,
|
| - &cu->header, &bytes_read);
|
| + DW_UNSND (attr) = read_offset (abfd, info_ptr,
|
| + &cu->header, &bytes_read);
|
| info_ptr += bytes_read;
|
| break;
|
| case DW_FORM_addr:
|
| @@ -10329,19 +12963,23 @@ read_attribute_value (struct attribute *attr, unsigned form,
|
| info_ptr += bytes_read;
|
| break;
|
| case DW_FORM_ref1:
|
| - DW_ADDR (attr) = cu->header.offset + read_1_byte (abfd, info_ptr);
|
| + DW_UNSND (attr) = (cu->header.offset.sect_off
|
| + + read_1_byte (abfd, info_ptr));
|
| info_ptr += 1;
|
| break;
|
| case DW_FORM_ref2:
|
| - DW_ADDR (attr) = cu->header.offset + read_2_bytes (abfd, info_ptr);
|
| + DW_UNSND (attr) = (cu->header.offset.sect_off
|
| + + read_2_bytes (abfd, info_ptr));
|
| info_ptr += 2;
|
| break;
|
| case DW_FORM_ref4:
|
| - DW_ADDR (attr) = cu->header.offset + read_4_bytes (abfd, info_ptr);
|
| + DW_UNSND (attr) = (cu->header.offset.sect_off
|
| + + read_4_bytes (abfd, info_ptr));
|
| info_ptr += 4;
|
| break;
|
| case DW_FORM_ref8:
|
| - DW_ADDR (attr) = cu->header.offset + read_8_bytes (abfd, info_ptr);
|
| + DW_UNSND (attr) = (cu->header.offset.sect_off
|
| + + read_8_bytes (abfd, info_ptr));
|
| info_ptr += 8;
|
| break;
|
| case DW_FORM_ref_sig8:
|
| @@ -10349,18 +12987,48 @@ read_attribute_value (struct attribute *attr, unsigned form,
|
| for later lookup.
|
| NOTE: This is NULL if the type wasn't found. */
|
| DW_SIGNATURED_TYPE (attr) =
|
| - lookup_signatured_type (cu->objfile, read_8_bytes (abfd, info_ptr));
|
| + lookup_signatured_type (read_8_bytes (abfd, info_ptr));
|
| info_ptr += 8;
|
| break;
|
| case DW_FORM_ref_udata:
|
| - DW_ADDR (attr) = (cu->header.offset
|
| - + read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
|
| + DW_UNSND (attr) = (cu->header.offset.sect_off
|
| + + read_unsigned_leb128 (abfd, info_ptr, &bytes_read));
|
| info_ptr += bytes_read;
|
| break;
|
| case DW_FORM_indirect:
|
| form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
| info_ptr += bytes_read;
|
| - info_ptr = read_attribute_value (attr, form, abfd, info_ptr, cu);
|
| + info_ptr = read_attribute_value (reader, attr, form, info_ptr);
|
| + break;
|
| + case DW_FORM_GNU_addr_index:
|
| + if (reader->dwo_file == NULL)
|
| + {
|
| + /* For now flag a hard error.
|
| + Later we can turn this into a complaint. */
|
| + error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"),
|
| + dwarf_form_name (form),
|
| + bfd_get_filename (abfd));
|
| + }
|
| + DW_ADDR (attr) = read_addr_index_from_leb128 (cu, info_ptr, &bytes_read);
|
| + info_ptr += bytes_read;
|
| + break;
|
| + case DW_FORM_GNU_str_index:
|
| + if (reader->dwo_file == NULL)
|
| + {
|
| + /* For now flag a hard error.
|
| + Later we can turn this into a complaint if warranted. */
|
| + error (_("Dwarf Error: %s found in non-DWO CU [in module %s]"),
|
| + dwarf_form_name (form),
|
| + bfd_get_filename (abfd));
|
| + }
|
| + {
|
| + ULONGEST str_index =
|
| + read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
|
| +
|
| + DW_STRING (attr) = read_str_index (reader, cu, str_index);
|
| + DW_STRING_IS_CANONICAL (attr) = 0;
|
| + info_ptr += bytes_read;
|
| + }
|
| break;
|
| default:
|
| error (_("Dwarf Error: Cannot handle %s in DWARF reader [in module %s]"),
|
| @@ -10391,11 +13059,12 @@ read_attribute_value (struct attribute *attr, unsigned form,
|
| /* Read an attribute described by an abbreviated attribute. */
|
|
|
| static gdb_byte *
|
| -read_attribute (struct attribute *attr, struct attr_abbrev *abbrev,
|
| - bfd *abfd, gdb_byte *info_ptr, struct dwarf2_cu *cu)
|
| +read_attribute (const struct die_reader_specs *reader,
|
| + struct attribute *attr, struct attr_abbrev *abbrev,
|
| + gdb_byte *info_ptr)
|
| {
|
| attr->name = abbrev->name;
|
| - return read_attribute_value (attr, abbrev->form, abfd, info_ptr, cu);
|
| + return read_attribute_value (reader, attr, abbrev->form, info_ptr);
|
| }
|
|
|
| /* Read dwarf information from a buffer. */
|
| @@ -10673,10 +13342,10 @@ read_indirect_string (bfd *abfd, gdb_byte *buf,
|
| return read_indirect_string_at_offset (abfd, str_offset);
|
| }
|
|
|
| -static unsigned long
|
| +static ULONGEST
|
| read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| {
|
| - unsigned long result;
|
| + ULONGEST result;
|
| unsigned int num_read;
|
| int i, shift;
|
| unsigned char byte;
|
| @@ -10690,7 +13359,7 @@ read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| byte = bfd_get_8 (abfd, buf);
|
| buf++;
|
| num_read++;
|
| - result |= ((unsigned long)(byte & 127) << shift);
|
| + result |= ((ULONGEST) (byte & 127) << shift);
|
| if ((byte & 128) == 0)
|
| {
|
| break;
|
| @@ -10701,10 +13370,10 @@ read_unsigned_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| return result;
|
| }
|
|
|
| -static long
|
| +static LONGEST
|
| read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| {
|
| - long result;
|
| + LONGEST result;
|
| int i, shift, num_read;
|
| unsigned char byte;
|
|
|
| @@ -10717,7 +13386,7 @@ read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| byte = bfd_get_8 (abfd, buf);
|
| buf++;
|
| num_read++;
|
| - result |= ((long)(byte & 127) << shift);
|
| + result |= ((LONGEST) (byte & 127) << shift);
|
| shift += 7;
|
| if ((byte & 128) == 0)
|
| {
|
| @@ -10725,24 +13394,187 @@ read_signed_leb128 (bfd *abfd, gdb_byte *buf, unsigned int *bytes_read_ptr)
|
| }
|
| }
|
| if ((shift < 8 * sizeof (result)) && (byte & 0x40))
|
| - result |= -(((long)1) << shift);
|
| + result |= -(((LONGEST) 1) << shift);
|
| *bytes_read_ptr = num_read;
|
| return result;
|
| }
|
|
|
| -/* Return a pointer to just past the end of an LEB128 number in BUF. */
|
| +/* Given index ADDR_INDEX in .debug_addr, fetch the value.
|
| + ADDR_BASE is the DW_AT_GNU_addr_base attribute or zero.
|
| + ADDR_SIZE is the size of addresses from the CU header. */
|
|
|
| -static gdb_byte *
|
| -skip_leb128 (bfd *abfd, gdb_byte *buf)
|
| +static CORE_ADDR
|
| +read_addr_index_1 (unsigned int addr_index, ULONGEST addr_base, int addr_size)
|
| +{
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + bfd *abfd = objfile->obfd;
|
| + const gdb_byte *info_ptr;
|
| +
|
| + 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);
|
| + 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);
|
| + info_ptr = (dwarf2_per_objfile->addr.buffer
|
| + + addr_base + addr_index * addr_size);
|
| + if (addr_size == 4)
|
| + return bfd_get_32 (abfd, info_ptr);
|
| + else
|
| + return bfd_get_64 (abfd, info_ptr);
|
| +}
|
| +
|
| +/* Given index ADDR_INDEX in .debug_addr, fetch the value. */
|
| +
|
| +static CORE_ADDR
|
| +read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index)
|
| +{
|
| + return read_addr_index_1 (addr_index, cu->addr_base, cu->header.addr_size);
|
| +}
|
| +
|
| +/* 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,
|
| + unsigned int *bytes_read)
|
| +{
|
| + bfd *abfd = cu->objfile->obfd;
|
| + unsigned int addr_index = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
|
| +
|
| + return read_addr_index (cu, addr_index);
|
| +}
|
| +
|
| +/* Data structure to pass results from dwarf2_read_addr_index_reader
|
| + back to dwarf2_read_addr_index. */
|
| +
|
| +struct dwarf2_read_addr_index_data
|
| +{
|
| + ULONGEST addr_base;
|
| + int addr_size;
|
| +};
|
| +
|
| +/* die_reader_func for dwarf2_read_addr_index. */
|
| +
|
| +static void
|
| +dwarf2_read_addr_index_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 dwarf2_read_addr_index_data *aidata =
|
| + (struct dwarf2_read_addr_index_data *) data;
|
| +
|
| + aidata->addr_base = cu->addr_base;
|
| + aidata->addr_size = cu->header.addr_size;
|
| +}
|
| +
|
| +/* Given an index in .debug_addr, fetch the value.
|
| + NOTE: This can be called during dwarf expression evaluation,
|
| + long after the debug information has been read, and thus per_cu->cu
|
| + may no longer exist. */
|
| +
|
| +CORE_ADDR
|
| +dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
|
| + unsigned int addr_index)
|
| +{
|
| + struct objfile *objfile = per_cu->objfile;
|
| + struct dwarf2_cu *cu = per_cu->cu;
|
| + ULONGEST addr_base;
|
| + int addr_size;
|
| +
|
| + /* This is intended to be called from outside this file. */
|
| + dw2_setup (objfile);
|
| +
|
| + /* We need addr_base and addr_size.
|
| + If we don't have PER_CU->cu, we have to get it.
|
| + Nasty, but the alternative is storing the needed info in PER_CU,
|
| + which at this point doesn't seem justified: it's not clear how frequently
|
| + it would get used and it would increase the size of every PER_CU.
|
| + Entry points like dwarf2_per_cu_addr_size do a similar thing
|
| + so we're not in uncharted territory here.
|
| + Alas we need to be a bit more complicated as addr_base is contained
|
| + in the DIE.
|
| +
|
| + 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. */
|
| +
|
| + if (cu != NULL)
|
| + {
|
| + addr_base = cu->addr_base;
|
| + addr_size = cu->header.addr_size;
|
| + }
|
| + else
|
| + {
|
| + struct dwarf2_read_addr_index_data aidata;
|
| +
|
| + init_cutu_and_read_dies_simple (per_cu, dwarf2_read_addr_index_reader,
|
| + &aidata);
|
| + addr_base = aidata.addr_base;
|
| + addr_size = aidata.addr_size;
|
| + }
|
| +
|
| + return read_addr_index_1 (addr_index, addr_base, addr_size);
|
| +}
|
| +
|
| +/* Given a DW_AT_str_index, fetch the string. */
|
| +
|
| +static 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;
|
| + bfd *abfd = objfile->obfd;
|
| + struct dwo_sections *sections = &reader->dwo_file->sections;
|
| + gdb_byte *info_ptr;
|
| + ULONGEST str_offset;
|
| +
|
| + 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"
|
| + " 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"
|
| + " 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"
|
| + " section in CU at offset 0x%lx [in module %s]"),
|
| + (long) cu->header.offset.sect_off, dwo_name);
|
| + info_ptr = (sections->str_offsets.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"
|
| + " .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);
|
| +}
|
| +
|
| +/* Return the length of an LEB128 number in BUF. */
|
| +
|
| +static int
|
| +leb128_size (const gdb_byte *buf)
|
| {
|
| - int byte;
|
| + const gdb_byte *begin = buf;
|
| + gdb_byte byte;
|
|
|
| while (1)
|
| {
|
| - byte = bfd_get_8 (abfd, buf);
|
| - buf++;
|
| + byte = *buf++;
|
| if ((byte & 128) == 0)
|
| - return buf;
|
| + return buf - begin;
|
| }
|
| }
|
|
|
| @@ -10767,6 +13599,9 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
|
| case DW_LANG_Fortran95:
|
| cu->language = language_fortran;
|
| break;
|
| + case DW_LANG_Go:
|
| + cu->language = language_go;
|
| + break;
|
| case DW_LANG_Mips_Assembler:
|
| cu->language = language_asm;
|
| break;
|
| @@ -10800,22 +13635,24 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
|
| static struct attribute *
|
| dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
|
| {
|
| - unsigned int i;
|
| - struct attribute *spec = NULL;
|
| -
|
| - for (i = 0; i < die->num_attrs; ++i)
|
| + for (;;)
|
| {
|
| - if (die->attrs[i].name == name)
|
| - return &die->attrs[i];
|
| - if (die->attrs[i].name == DW_AT_specification
|
| - || die->attrs[i].name == DW_AT_abstract_origin)
|
| - spec = &die->attrs[i];
|
| - }
|
| + unsigned int i;
|
| + struct attribute *spec = NULL;
|
| +
|
| + for (i = 0; i < die->num_attrs; ++i)
|
| + {
|
| + if (die->attrs[i].name == name)
|
| + return &die->attrs[i];
|
| + if (die->attrs[i].name == DW_AT_specification
|
| + || die->attrs[i].name == DW_AT_abstract_origin)
|
| + spec = &die->attrs[i];
|
| + }
|
| +
|
| + if (!spec)
|
| + break;
|
|
|
| - if (spec)
|
| - {
|
| die = follow_die_ref (die, spec, &cu);
|
| - return dwarf2_attr (die, name, cu);
|
| }
|
|
|
| return NULL;
|
| @@ -10828,8 +13665,7 @@ dwarf2_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu)
|
| back up the chain, and we want to go down. */
|
|
|
| static struct attribute *
|
| -dwarf2_attr_no_follow (struct die_info *die, unsigned int name,
|
| - struct dwarf2_cu *cu)
|
| +dwarf2_attr_no_follow (struct die_info *die, unsigned int name)
|
| {
|
| unsigned int i;
|
|
|
| @@ -10968,16 +13804,15 @@ add_file_name (struct line_header *lh,
|
| }
|
|
|
| /* Read the statement program header starting at OFFSET in
|
| - .debug_line, according to the endianness of ABFD. Return a pointer
|
| + .debug_line, or .debug_line.dwo. Return a pointer
|
| to a struct line_header, allocated using xmalloc.
|
|
|
| NOTE: the strings in the include directory and file name tables of
|
| - the returned object point into debug_line_buffer, and must not be
|
| - freed. */
|
| + the returned object point into the dwarf line section buffer,
|
| + and must not be freed. */
|
|
|
| static struct line_header *
|
| -dwarf_decode_line_header (unsigned int offset, bfd *abfd,
|
| - struct dwarf2_cu *cu)
|
| +dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
|
| {
|
| struct cleanup *back_to;
|
| struct line_header *lh;
|
| @@ -10985,17 +13820,33 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
|
| unsigned int bytes_read, offset_size;
|
| int i;
|
| 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;
|
|
|
| - dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->line);
|
| - if (dwarf2_per_objfile->line.buffer == NULL)
|
| + dwarf2_read_section (dwarf2_per_objfile->objfile, section);
|
| + if (section->buffer == NULL)
|
| {
|
| - complaint (&symfile_complaints, _("missing .debug_line section"));
|
| + if (cu->dwo_unit && cu->per_cu->is_debug_types)
|
| + complaint (&symfile_complaints, _("missing .debug_line.dwo section"));
|
| + else
|
| + complaint (&symfile_complaints, _("missing .debug_line section"));
|
| return 0;
|
| }
|
|
|
| + /* 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;
|
| +
|
| /* 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. */
|
| - if (offset + 4 >= dwarf2_per_objfile->line.size)
|
| + if (offset + 4 >= section->size)
|
| {
|
| dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
| return 0;
|
| @@ -11006,15 +13857,14 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
|
| back_to = make_cleanup ((make_cleanup_ftype *) free_line_header,
|
| (void *) lh);
|
|
|
| - line_ptr = dwarf2_per_objfile->line.buffer + offset;
|
| + line_ptr = section->buffer + offset;
|
|
|
| /* Read in the header. */
|
| lh->total_length =
|
| read_checked_initial_length_and_offset (abfd, line_ptr, &cu->header,
|
| &bytes_read, &offset_size);
|
| line_ptr += bytes_read;
|
| - if (line_ptr + lh->total_length > (dwarf2_per_objfile->line.buffer
|
| - + dwarf2_per_objfile->line.size))
|
| + if (line_ptr + lh->total_length > (section->buffer + section->size))
|
| {
|
| dwarf2_statement_list_fits_in_line_number_section_complaint ();
|
| return 0;
|
| @@ -11086,8 +13936,7 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
|
| line_ptr += bytes_read;
|
| lh->statement_program_start = line_ptr;
|
|
|
| - if (line_ptr > (dwarf2_per_objfile->line.buffer
|
| - + dwarf2_per_objfile->line.size))
|
| + if (line_ptr > (section->buffer + section->size))
|
| complaint (&symfile_complaints,
|
| _("line number info header doesn't "
|
| "fit in `.debug_line' section"));
|
| @@ -11096,52 +13945,6 @@ dwarf_decode_line_header (unsigned int offset, bfd *abfd,
|
| return lh;
|
| }
|
|
|
| -/* This function exists to work around a bug in certain compilers
|
| - (particularly GCC 2.95), in which the first line number marker of a
|
| - function does not show up until after the prologue, right before
|
| - the second line number marker. This function shifts ADDRESS down
|
| - to the beginning of the function if necessary, and is called on
|
| - addresses passed to record_line. */
|
| -
|
| -static CORE_ADDR
|
| -check_cu_functions (CORE_ADDR address, struct dwarf2_cu *cu)
|
| -{
|
| - struct function_range *fn;
|
| -
|
| - /* Find the function_range containing address. */
|
| - if (!cu->first_fn)
|
| - return address;
|
| -
|
| - if (!cu->cached_fn)
|
| - cu->cached_fn = cu->first_fn;
|
| -
|
| - fn = cu->cached_fn;
|
| - while (fn)
|
| - if (fn->lowpc <= address && fn->highpc > address)
|
| - goto found;
|
| - else
|
| - fn = fn->next;
|
| -
|
| - fn = cu->first_fn;
|
| - while (fn && fn != cu->cached_fn)
|
| - if (fn->lowpc <= address && fn->highpc > address)
|
| - goto found;
|
| - else
|
| - fn = fn->next;
|
| -
|
| - return address;
|
| -
|
| - found:
|
| - if (fn->seen_line)
|
| - return address;
|
| - if (address != fn->lowpc)
|
| - complaint (&symfile_complaints,
|
| - _("misplaced first line number at 0x%lx for '%s'"),
|
| - (unsigned long) address, fn->name);
|
| - fn->seen_line = 1;
|
| - return fn->lowpc;
|
| -}
|
| -
|
| /* Subroutine of dwarf_decode_lines to simplify it.
|
| Return the file name of the psymtab for included file FILE_INDEX
|
| in line header LH of PST.
|
| @@ -11321,8 +14124,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| last_subfile = current_subfile;
|
| }
|
| /* Append row to matrix using current values. */
|
| - addr = check_cu_functions (address, cu);
|
| - addr = gdbarch_addr_bits_remove (gdbarch, addr);
|
| + addr = gdbarch_addr_bits_remove (gdbarch, address);
|
| (*p_record_line) (current_subfile, line, addr);
|
| }
|
| }
|
| @@ -11357,7 +14159,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| complaint (&symfile_complaints,
|
| _(".debug_line address at offset 0x%lx is 0 "
|
| "[in module %s]"),
|
| - line_offset, cu->objfile->name);
|
| + line_offset, objfile->name);
|
| p_record_line = noop_record_line;
|
| }
|
|
|
| @@ -11420,8 +14222,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
|
| (*p_record_line) (last_subfile, 0, addr);
|
| last_subfile = current_subfile;
|
| }
|
| - addr = check_cu_functions (address, cu);
|
| - addr = gdbarch_addr_bits_remove (gdbarch, addr);
|
| + addr = gdbarch_addr_bits_remove (gdbarch, address);
|
| (*p_record_line) (current_subfile, line, addr);
|
| }
|
| }
|
| @@ -11601,7 +14402,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
|
|
|
| if (current_subfile->symtab == NULL)
|
| current_subfile->symtab = allocate_symtab (current_subfile->name,
|
| - cu->objfile);
|
| + objfile);
|
| fe->symtab = current_subfile->symtab;
|
| }
|
| }
|
| @@ -11658,6 +14459,23 @@ dwarf2_start_subfile (char *filename, const char *dirname,
|
| xfree (fullname);
|
| }
|
|
|
| +/* Start a symtab for DWARF.
|
| + NAME, COMP_DIR, LOW_PC are passed to start_symtab. */
|
| +
|
| +static void
|
| +dwarf2_start_symtab (struct dwarf2_cu *cu,
|
| + char *name, char *comp_dir, CORE_ADDR low_pc)
|
| +{
|
| + start_symtab (name, comp_dir, low_pc);
|
| + record_debugformat ("DWARF 2");
|
| + record_producer (cu->producer);
|
| +
|
| + /* We assume that we're processing GCC output. */
|
| + processing_gcc_compilation = 2;
|
| +
|
| + processing_has_namespace_info = 0;
|
| +}
|
| +
|
| static void
|
| var_decode_location (struct attribute *attr, struct symbol *sym,
|
| struct dwarf2_cu *cu)
|
| @@ -11685,17 +14503,24 @@ var_decode_location (struct attribute *attr, struct symbol *sym,
|
|
|
| /* Handle one degenerate form of location expression specially, to
|
| preserve GDB's previous behavior when section offsets are
|
| - specified. If this is just a DW_OP_addr then mark this symbol
|
| - as LOC_STATIC. */
|
| + specified. If this is just a DW_OP_addr or DW_OP_GNU_addr_index
|
| + then mark this symbol as LOC_STATIC. */
|
|
|
| if (attr_form_is_block (attr)
|
| - && DW_BLOCK (attr)->size == 1 + cu_header->addr_size
|
| - && DW_BLOCK (attr)->data[0] == DW_OP_addr)
|
| + && ((DW_BLOCK (attr)->data[0] == DW_OP_addr
|
| + && DW_BLOCK (attr)->size == 1 + cu_header->addr_size)
|
| + || (DW_BLOCK (attr)->data[0] == DW_OP_GNU_addr_index
|
| + && (DW_BLOCK (attr)->size
|
| + == 1 + leb128_size (&DW_BLOCK (attr)->data[1])))))
|
| {
|
| unsigned int dummy;
|
|
|
| - SYMBOL_VALUE_ADDRESS (sym) =
|
| - read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
|
| + if (DW_BLOCK (attr)->data[0] == DW_OP_addr)
|
| + SYMBOL_VALUE_ADDRESS (sym) =
|
| + read_address (objfile->obfd, DW_BLOCK (attr)->data + 1, cu, &dummy);
|
| + else
|
| + SYMBOL_VALUE_ADDRESS (sym) =
|
| + read_addr_index_from_leb128 (cu, DW_BLOCK (attr)->data + 1, &dummy);
|
| SYMBOL_CLASS (sym) = LOC_STATIC;
|
| fixup_symbol_section (sym, objfile);
|
| SYMBOL_VALUE_ADDRESS (sym) += ANOFFSET (objfile->section_offsets,
|
| @@ -11841,8 +14666,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
| finish_block. */
|
| SYMBOL_CLASS (sym) = LOC_BLOCK;
|
| SYMBOL_INLINED (sym) = 1;
|
| - /* Do not add the symbol to any lists. It will be found via
|
| - BLOCK_FUNCTION from the blockvector. */
|
| + list_to_add = cu->list_in_scope;
|
| break;
|
| case DW_TAG_template_value_param:
|
| suppress_add = 1;
|
| @@ -12097,7 +14921,7 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
|
| static gdb_byte *
|
| dwarf2_const_value_data (struct attribute *attr, struct type *type,
|
| const char *name, struct obstack *obstack,
|
| - struct dwarf2_cu *cu, long *value, int bits)
|
| + struct dwarf2_cu *cu, LONGEST *value, int bits)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| enum bfd_endian byte_order = bfd_big_endian (objfile->obfd) ?
|
| @@ -12131,7 +14955,7 @@ static void
|
| dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| const char *name, struct obstack *obstack,
|
| struct dwarf2_cu *cu,
|
| - long *value, gdb_byte **bytes,
|
| + LONGEST *value, gdb_byte **bytes,
|
| struct dwarf2_locexpr_baton **baton)
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| @@ -12147,6 +14971,7 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| switch (attr->form)
|
| {
|
| case DW_FORM_addr:
|
| + case DW_FORM_GNU_addr_index:
|
| {
|
| gdb_byte *data;
|
|
|
| @@ -12174,6 +14999,7 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
|
| break;
|
| case DW_FORM_string:
|
| case DW_FORM_strp:
|
| + case DW_FORM_GNU_str_index:
|
| /* DW_STRING is already allocated on the objfile obstack, point
|
| directly to it. */
|
| *bytes = (gdb_byte *) DW_STRING (attr);
|
| @@ -12238,7 +15064,7 @@ dwarf2_const_value (struct attribute *attr, struct symbol *sym,
|
| {
|
| struct objfile *objfile = cu->objfile;
|
| struct comp_unit_head *cu_header = &cu->header;
|
| - long value;
|
| + LONGEST value;
|
| gdb_byte *bytes;
|
| struct dwarf2_locexpr_baton *baton;
|
|
|
| @@ -12355,38 +15181,44 @@ static struct type *
|
| lookup_die_type (struct die_info *die, struct attribute *attr,
|
| struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = cu->objfile;
|
| struct type *this_type;
|
|
|
| /* First see if we have it cached. */
|
|
|
| if (is_ref_attr (attr))
|
| {
|
| - unsigned int offset = dwarf2_get_ref_die_offset (attr);
|
| + sect_offset offset = dwarf2_get_ref_die_offset (attr);
|
|
|
| this_type = get_die_type_at_offset (offset, cu->per_cu);
|
| }
|
| else if (attr->form == DW_FORM_ref_sig8)
|
| {
|
| struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
|
| - struct dwarf2_cu *sig_cu;
|
| - unsigned int offset;
|
|
|
| /* 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, cu->objfile->name);
|
| + die->offset.sect_off, objfile->name);
|
|
|
| - gdb_assert (sig_type->per_cu.debug_types_section);
|
| - offset = sig_type->per_cu.offset + sig_type->type_offset;
|
| - this_type = get_die_type_at_offset (offset, &sig_type->per_cu);
|
| + 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);
|
| + }
|
| }
|
| else
|
| {
|
| dump_die_for_error (die);
|
| error (_("Dwarf Error: Bad type attribute %s [in module %s]"),
|
| - dwarf_attr_name (attr->name), cu->objfile->name);
|
| + dwarf_attr_name (attr->name), objfile->name);
|
| }
|
|
|
| /* If not cached we need to read it in. */
|
| @@ -12397,9 +15229,12 @@ lookup_die_type (struct die_info *die, struct attribute *attr,
|
| struct dwarf2_cu *type_cu = cu;
|
|
|
| type_die = follow_die_ref_or_sig (die, attr, &type_cu);
|
| - /* If the type is cached, we should have found it above. */
|
| - gdb_assert (get_die_type (type_die, type_cu) == NULL);
|
| - this_type = read_type_die_1 (type_die, type_cu);
|
| + /* If we found 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);
|
| }
|
|
|
| /* If we still don't have a type use an error marker. */
|
| @@ -12410,14 +15245,14 @@ lookup_die_type (struct die_info *die, struct attribute *attr,
|
|
|
| /* read_type_die already issued a complaint. */
|
| message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
|
| - cu->objfile->name,
|
| - cu->header.offset,
|
| - die->offset);
|
| - saved = obstack_copy0 (&cu->objfile->objfile_obstack,
|
| + 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, cu->objfile);
|
| + this_type = init_type (TYPE_CODE_ERROR, 0, 0, saved, objfile);
|
| }
|
|
|
| return this_type;
|
| @@ -12642,7 +15477,7 @@ anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu)
|
|
|
| then determine_prefix on foo's die will return "N::C". */
|
|
|
| -static char *
|
| +static const char *
|
| determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| struct die_info *parent, *spec_die;
|
| @@ -12759,6 +15594,7 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
|
| So it does not need a prefix. */
|
| return "";
|
| case DW_TAG_compile_unit:
|
| + case DW_TAG_partial_unit:
|
| /* gcc-4.5 -gdwarf-4 can drop the enclosing namespace. Cope. */
|
| if (cu->language == language_cplus
|
| && !VEC_empty (dwarf2_section_info_def, dwarf2_per_objfile->types)
|
| @@ -12879,6 +15715,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
|
| switch (die->tag)
|
| {
|
| case DW_TAG_compile_unit:
|
| + case DW_TAG_partial_unit:
|
| /* Compilation units have a DW_AT_name that is a filename, not
|
| a source language identifier. */
|
| case DW_TAG_enumeration_type:
|
| @@ -12912,7 +15749,8 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu)
|
| if (die->tag == DW_TAG_class_type)
|
| return dwarf2_name (die, cu);
|
| }
|
| - while (die->tag != DW_TAG_compile_unit);
|
| + while (die->tag != DW_TAG_compile_unit
|
| + && die->tag != DW_TAG_partial_unit);
|
| }
|
| break;
|
|
|
| @@ -13000,843 +15838,51 @@ dwarf2_extension (struct die_info *die, struct dwarf2_cu **ext_cu)
|
|
|
| /* Convert a DIE tag into its string name. */
|
|
|
| -static char *
|
| +static const char *
|
| dwarf_tag_name (unsigned tag)
|
| {
|
| - switch (tag)
|
| - {
|
| - case DW_TAG_padding:
|
| - return "DW_TAG_padding";
|
| - case DW_TAG_array_type:
|
| - return "DW_TAG_array_type";
|
| - case DW_TAG_class_type:
|
| - return "DW_TAG_class_type";
|
| - case DW_TAG_entry_point:
|
| - return "DW_TAG_entry_point";
|
| - case DW_TAG_enumeration_type:
|
| - return "DW_TAG_enumeration_type";
|
| - case DW_TAG_formal_parameter:
|
| - return "DW_TAG_formal_parameter";
|
| - case DW_TAG_imported_declaration:
|
| - return "DW_TAG_imported_declaration";
|
| - case DW_TAG_label:
|
| - return "DW_TAG_label";
|
| - case DW_TAG_lexical_block:
|
| - return "DW_TAG_lexical_block";
|
| - case DW_TAG_member:
|
| - return "DW_TAG_member";
|
| - case DW_TAG_pointer_type:
|
| - return "DW_TAG_pointer_type";
|
| - case DW_TAG_reference_type:
|
| - return "DW_TAG_reference_type";
|
| - case DW_TAG_compile_unit:
|
| - return "DW_TAG_compile_unit";
|
| - case DW_TAG_string_type:
|
| - return "DW_TAG_string_type";
|
| - case DW_TAG_structure_type:
|
| - return "DW_TAG_structure_type";
|
| - case DW_TAG_subroutine_type:
|
| - return "DW_TAG_subroutine_type";
|
| - case DW_TAG_typedef:
|
| - return "DW_TAG_typedef";
|
| - case DW_TAG_union_type:
|
| - return "DW_TAG_union_type";
|
| - case DW_TAG_unspecified_parameters:
|
| - return "DW_TAG_unspecified_parameters";
|
| - case DW_TAG_variant:
|
| - return "DW_TAG_variant";
|
| - case DW_TAG_common_block:
|
| - return "DW_TAG_common_block";
|
| - case DW_TAG_common_inclusion:
|
| - return "DW_TAG_common_inclusion";
|
| - case DW_TAG_inheritance:
|
| - return "DW_TAG_inheritance";
|
| - case DW_TAG_inlined_subroutine:
|
| - return "DW_TAG_inlined_subroutine";
|
| - case DW_TAG_module:
|
| - return "DW_TAG_module";
|
| - case DW_TAG_ptr_to_member_type:
|
| - return "DW_TAG_ptr_to_member_type";
|
| - case DW_TAG_set_type:
|
| - return "DW_TAG_set_type";
|
| - case DW_TAG_subrange_type:
|
| - return "DW_TAG_subrange_type";
|
| - case DW_TAG_with_stmt:
|
| - return "DW_TAG_with_stmt";
|
| - case DW_TAG_access_declaration:
|
| - return "DW_TAG_access_declaration";
|
| - case DW_TAG_base_type:
|
| - return "DW_TAG_base_type";
|
| - case DW_TAG_catch_block:
|
| - return "DW_TAG_catch_block";
|
| - case DW_TAG_const_type:
|
| - return "DW_TAG_const_type";
|
| - case DW_TAG_constant:
|
| - return "DW_TAG_constant";
|
| - case DW_TAG_enumerator:
|
| - return "DW_TAG_enumerator";
|
| - case DW_TAG_file_type:
|
| - return "DW_TAG_file_type";
|
| - case DW_TAG_friend:
|
| - return "DW_TAG_friend";
|
| - case DW_TAG_namelist:
|
| - return "DW_TAG_namelist";
|
| - case DW_TAG_namelist_item:
|
| - return "DW_TAG_namelist_item";
|
| - case DW_TAG_packed_type:
|
| - return "DW_TAG_packed_type";
|
| - case DW_TAG_subprogram:
|
| - return "DW_TAG_subprogram";
|
| - case DW_TAG_template_type_param:
|
| - return "DW_TAG_template_type_param";
|
| - case DW_TAG_template_value_param:
|
| - return "DW_TAG_template_value_param";
|
| - case DW_TAG_thrown_type:
|
| - return "DW_TAG_thrown_type";
|
| - case DW_TAG_try_block:
|
| - return "DW_TAG_try_block";
|
| - case DW_TAG_variant_part:
|
| - return "DW_TAG_variant_part";
|
| - case DW_TAG_variable:
|
| - return "DW_TAG_variable";
|
| - case DW_TAG_volatile_type:
|
| - return "DW_TAG_volatile_type";
|
| - case DW_TAG_dwarf_procedure:
|
| - return "DW_TAG_dwarf_procedure";
|
| - case DW_TAG_restrict_type:
|
| - return "DW_TAG_restrict_type";
|
| - case DW_TAG_interface_type:
|
| - return "DW_TAG_interface_type";
|
| - case DW_TAG_namespace:
|
| - return "DW_TAG_namespace";
|
| - case DW_TAG_imported_module:
|
| - return "DW_TAG_imported_module";
|
| - case DW_TAG_unspecified_type:
|
| - return "DW_TAG_unspecified_type";
|
| - case DW_TAG_partial_unit:
|
| - return "DW_TAG_partial_unit";
|
| - case DW_TAG_imported_unit:
|
| - return "DW_TAG_imported_unit";
|
| - case DW_TAG_condition:
|
| - return "DW_TAG_condition";
|
| - case DW_TAG_shared_type:
|
| - return "DW_TAG_shared_type";
|
| - case DW_TAG_type_unit:
|
| - return "DW_TAG_type_unit";
|
| - case DW_TAG_MIPS_loop:
|
| - return "DW_TAG_MIPS_loop";
|
| - case DW_TAG_HP_array_descriptor:
|
| - return "DW_TAG_HP_array_descriptor";
|
| - case DW_TAG_format_label:
|
| - return "DW_TAG_format_label";
|
| - case DW_TAG_function_template:
|
| - return "DW_TAG_function_template";
|
| - case DW_TAG_class_template:
|
| - return "DW_TAG_class_template";
|
| - case DW_TAG_GNU_BINCL:
|
| - return "DW_TAG_GNU_BINCL";
|
| - case DW_TAG_GNU_EINCL:
|
| - return "DW_TAG_GNU_EINCL";
|
| - case DW_TAG_upc_shared_type:
|
| - return "DW_TAG_upc_shared_type";
|
| - case DW_TAG_upc_strict_type:
|
| - return "DW_TAG_upc_strict_type";
|
| - case DW_TAG_upc_relaxed_type:
|
| - return "DW_TAG_upc_relaxed_type";
|
| - case DW_TAG_PGI_kanji_type:
|
| - return "DW_TAG_PGI_kanji_type";
|
| - case DW_TAG_PGI_interface_block:
|
| - return "DW_TAG_PGI_interface_block";
|
| - case DW_TAG_GNU_call_site:
|
| - return "DW_TAG_GNU_call_site";
|
| - default:
|
| - return "DW_TAG_<unknown>";
|
| - }
|
| + const char *name = get_DW_TAG_name (tag);
|
| +
|
| + if (name == NULL)
|
| + return "DW_TAG_<unknown>";
|
| +
|
| + return name;
|
| }
|
|
|
| /* Convert a DWARF attribute code into its string name. */
|
|
|
| -static char *
|
| +static const char *
|
| dwarf_attr_name (unsigned attr)
|
| {
|
| - switch (attr)
|
| - {
|
| - case DW_AT_sibling:
|
| - return "DW_AT_sibling";
|
| - case DW_AT_location:
|
| - return "DW_AT_location";
|
| - case DW_AT_name:
|
| - return "DW_AT_name";
|
| - case DW_AT_ordering:
|
| - return "DW_AT_ordering";
|
| - case DW_AT_subscr_data:
|
| - return "DW_AT_subscr_data";
|
| - case DW_AT_byte_size:
|
| - return "DW_AT_byte_size";
|
| - case DW_AT_bit_offset:
|
| - return "DW_AT_bit_offset";
|
| - case DW_AT_bit_size:
|
| - return "DW_AT_bit_size";
|
| - case DW_AT_element_list:
|
| - return "DW_AT_element_list";
|
| - case DW_AT_stmt_list:
|
| - return "DW_AT_stmt_list";
|
| - case DW_AT_low_pc:
|
| - return "DW_AT_low_pc";
|
| - case DW_AT_high_pc:
|
| - return "DW_AT_high_pc";
|
| - case DW_AT_language:
|
| - return "DW_AT_language";
|
| - case DW_AT_member:
|
| - return "DW_AT_member";
|
| - case DW_AT_discr:
|
| - return "DW_AT_discr";
|
| - case DW_AT_discr_value:
|
| - return "DW_AT_discr_value";
|
| - case DW_AT_visibility:
|
| - return "DW_AT_visibility";
|
| - case DW_AT_import:
|
| - return "DW_AT_import";
|
| - case DW_AT_string_length:
|
| - return "DW_AT_string_length";
|
| - case DW_AT_common_reference:
|
| - return "DW_AT_common_reference";
|
| - case DW_AT_comp_dir:
|
| - return "DW_AT_comp_dir";
|
| - case DW_AT_const_value:
|
| - return "DW_AT_const_value";
|
| - case DW_AT_containing_type:
|
| - return "DW_AT_containing_type";
|
| - case DW_AT_default_value:
|
| - return "DW_AT_default_value";
|
| - case DW_AT_inline:
|
| - return "DW_AT_inline";
|
| - case DW_AT_is_optional:
|
| - return "DW_AT_is_optional";
|
| - case DW_AT_lower_bound:
|
| - return "DW_AT_lower_bound";
|
| - case DW_AT_producer:
|
| - return "DW_AT_producer";
|
| - case DW_AT_prototyped:
|
| - return "DW_AT_prototyped";
|
| - case DW_AT_return_addr:
|
| - return "DW_AT_return_addr";
|
| - case DW_AT_start_scope:
|
| - return "DW_AT_start_scope";
|
| - case DW_AT_bit_stride:
|
| - return "DW_AT_bit_stride";
|
| - case DW_AT_upper_bound:
|
| - return "DW_AT_upper_bound";
|
| - case DW_AT_abstract_origin:
|
| - return "DW_AT_abstract_origin";
|
| - case DW_AT_accessibility:
|
| - return "DW_AT_accessibility";
|
| - case DW_AT_address_class:
|
| - return "DW_AT_address_class";
|
| - case DW_AT_artificial:
|
| - return "DW_AT_artificial";
|
| - case DW_AT_base_types:
|
| - return "DW_AT_base_types";
|
| - case DW_AT_calling_convention:
|
| - return "DW_AT_calling_convention";
|
| - case DW_AT_count:
|
| - return "DW_AT_count";
|
| - case DW_AT_data_member_location:
|
| - return "DW_AT_data_member_location";
|
| - case DW_AT_decl_column:
|
| - return "DW_AT_decl_column";
|
| - case DW_AT_decl_file:
|
| - return "DW_AT_decl_file";
|
| - case DW_AT_decl_line:
|
| - return "DW_AT_decl_line";
|
| - case DW_AT_declaration:
|
| - return "DW_AT_declaration";
|
| - case DW_AT_discr_list:
|
| - return "DW_AT_discr_list";
|
| - case DW_AT_encoding:
|
| - return "DW_AT_encoding";
|
| - case DW_AT_external:
|
| - return "DW_AT_external";
|
| - case DW_AT_frame_base:
|
| - return "DW_AT_frame_base";
|
| - case DW_AT_friend:
|
| - return "DW_AT_friend";
|
| - case DW_AT_identifier_case:
|
| - return "DW_AT_identifier_case";
|
| - case DW_AT_macro_info:
|
| - return "DW_AT_macro_info";
|
| - case DW_AT_namelist_items:
|
| - return "DW_AT_namelist_items";
|
| - case DW_AT_priority:
|
| - return "DW_AT_priority";
|
| - case DW_AT_segment:
|
| - return "DW_AT_segment";
|
| - case DW_AT_specification:
|
| - return "DW_AT_specification";
|
| - case DW_AT_static_link:
|
| - return "DW_AT_static_link";
|
| - case DW_AT_type:
|
| - return "DW_AT_type";
|
| - case DW_AT_use_location:
|
| - return "DW_AT_use_location";
|
| - case DW_AT_variable_parameter:
|
| - return "DW_AT_variable_parameter";
|
| - case DW_AT_virtuality:
|
| - return "DW_AT_virtuality";
|
| - case DW_AT_vtable_elem_location:
|
| - return "DW_AT_vtable_elem_location";
|
| - /* DWARF 3 values. */
|
| - case DW_AT_allocated:
|
| - return "DW_AT_allocated";
|
| - case DW_AT_associated:
|
| - return "DW_AT_associated";
|
| - case DW_AT_data_location:
|
| - return "DW_AT_data_location";
|
| - case DW_AT_byte_stride:
|
| - return "DW_AT_byte_stride";
|
| - case DW_AT_entry_pc:
|
| - return "DW_AT_entry_pc";
|
| - case DW_AT_use_UTF8:
|
| - return "DW_AT_use_UTF8";
|
| - case DW_AT_extension:
|
| - return "DW_AT_extension";
|
| - case DW_AT_ranges:
|
| - return "DW_AT_ranges";
|
| - case DW_AT_trampoline:
|
| - return "DW_AT_trampoline";
|
| - case DW_AT_call_column:
|
| - return "DW_AT_call_column";
|
| - case DW_AT_call_file:
|
| - return "DW_AT_call_file";
|
| - case DW_AT_call_line:
|
| - return "DW_AT_call_line";
|
| - case DW_AT_description:
|
| - return "DW_AT_description";
|
| - case DW_AT_binary_scale:
|
| - return "DW_AT_binary_scale";
|
| - case DW_AT_decimal_scale:
|
| - return "DW_AT_decimal_scale";
|
| - case DW_AT_small:
|
| - return "DW_AT_small";
|
| - case DW_AT_decimal_sign:
|
| - return "DW_AT_decimal_sign";
|
| - case DW_AT_digit_count:
|
| - return "DW_AT_digit_count";
|
| - case DW_AT_picture_string:
|
| - return "DW_AT_picture_string";
|
| - case DW_AT_mutable:
|
| - return "DW_AT_mutable";
|
| - case DW_AT_threads_scaled:
|
| - return "DW_AT_threads_scaled";
|
| - case DW_AT_explicit:
|
| - return "DW_AT_explicit";
|
| - case DW_AT_object_pointer:
|
| - return "DW_AT_object_pointer";
|
| - case DW_AT_endianity:
|
| - return "DW_AT_endianity";
|
| - case DW_AT_elemental:
|
| - return "DW_AT_elemental";
|
| - case DW_AT_pure:
|
| - return "DW_AT_pure";
|
| - case DW_AT_recursive:
|
| - return "DW_AT_recursive";
|
| - /* DWARF 4 values. */
|
| - case DW_AT_signature:
|
| - return "DW_AT_signature";
|
| - case DW_AT_linkage_name:
|
| - return "DW_AT_linkage_name";
|
| - /* SGI/MIPS extensions. */
|
| + const char *name;
|
| +
|
| #ifdef MIPS /* collides with DW_AT_HP_block_index */
|
| - case DW_AT_MIPS_fde:
|
| - return "DW_AT_MIPS_fde";
|
| -#endif
|
| - case DW_AT_MIPS_loop_begin:
|
| - return "DW_AT_MIPS_loop_begin";
|
| - case DW_AT_MIPS_tail_loop_begin:
|
| - return "DW_AT_MIPS_tail_loop_begin";
|
| - case DW_AT_MIPS_epilog_begin:
|
| - return "DW_AT_MIPS_epilog_begin";
|
| - case DW_AT_MIPS_loop_unroll_factor:
|
| - return "DW_AT_MIPS_loop_unroll_factor";
|
| - case DW_AT_MIPS_software_pipeline_depth:
|
| - return "DW_AT_MIPS_software_pipeline_depth";
|
| - case DW_AT_MIPS_linkage_name:
|
| - return "DW_AT_MIPS_linkage_name";
|
| - case DW_AT_MIPS_stride:
|
| - return "DW_AT_MIPS_stride";
|
| - case DW_AT_MIPS_abstract_name:
|
| - return "DW_AT_MIPS_abstract_name";
|
| - case DW_AT_MIPS_clone_origin:
|
| - return "DW_AT_MIPS_clone_origin";
|
| - case DW_AT_MIPS_has_inlines:
|
| - return "DW_AT_MIPS_has_inlines";
|
| - /* HP extensions. */
|
| -#ifndef MIPS /* collides with DW_AT_MIPS_fde */
|
| - case DW_AT_HP_block_index:
|
| - return "DW_AT_HP_block_index";
|
| + if (attr == DW_AT_MIPS_fde)
|
| + return "DW_AT_MIPS_fde";
|
| +#else
|
| + if (attr == DW_AT_HP_block_index)
|
| + return "DW_AT_HP_block_index";
|
| #endif
|
| - case DW_AT_HP_unmodifiable:
|
| - return "DW_AT_HP_unmodifiable";
|
| - case DW_AT_HP_actuals_stmt_list:
|
| - return "DW_AT_HP_actuals_stmt_list";
|
| - case DW_AT_HP_proc_per_section:
|
| - return "DW_AT_HP_proc_per_section";
|
| - case DW_AT_HP_raw_data_ptr:
|
| - return "DW_AT_HP_raw_data_ptr";
|
| - case DW_AT_HP_pass_by_reference:
|
| - return "DW_AT_HP_pass_by_reference";
|
| - case DW_AT_HP_opt_level:
|
| - return "DW_AT_HP_opt_level";
|
| - case DW_AT_HP_prof_version_id:
|
| - return "DW_AT_HP_prof_version_id";
|
| - case DW_AT_HP_opt_flags:
|
| - return "DW_AT_HP_opt_flags";
|
| - case DW_AT_HP_cold_region_low_pc:
|
| - return "DW_AT_HP_cold_region_low_pc";
|
| - case DW_AT_HP_cold_region_high_pc:
|
| - return "DW_AT_HP_cold_region_high_pc";
|
| - case DW_AT_HP_all_variables_modifiable:
|
| - return "DW_AT_HP_all_variables_modifiable";
|
| - case DW_AT_HP_linkage_name:
|
| - return "DW_AT_HP_linkage_name";
|
| - case DW_AT_HP_prof_flags:
|
| - return "DW_AT_HP_prof_flags";
|
| - /* GNU extensions. */
|
| - case DW_AT_sf_names:
|
| - return "DW_AT_sf_names";
|
| - case DW_AT_src_info:
|
| - return "DW_AT_src_info";
|
| - case DW_AT_mac_info:
|
| - return "DW_AT_mac_info";
|
| - case DW_AT_src_coords:
|
| - return "DW_AT_src_coords";
|
| - case DW_AT_body_begin:
|
| - return "DW_AT_body_begin";
|
| - case DW_AT_body_end:
|
| - return "DW_AT_body_end";
|
| - case DW_AT_GNU_vector:
|
| - return "DW_AT_GNU_vector";
|
| - case DW_AT_GNU_odr_signature:
|
| - return "DW_AT_GNU_odr_signature";
|
| - /* VMS extensions. */
|
| - case DW_AT_VMS_rtnbeg_pd_address:
|
| - return "DW_AT_VMS_rtnbeg_pd_address";
|
| - /* UPC extension. */
|
| - case DW_AT_upc_threads_scaled:
|
| - return "DW_AT_upc_threads_scaled";
|
| - /* PGI (STMicroelectronics) extensions. */
|
| - case DW_AT_PGI_lbase:
|
| - return "DW_AT_PGI_lbase";
|
| - case DW_AT_PGI_soffset:
|
| - return "DW_AT_PGI_soffset";
|
| - case DW_AT_PGI_lstride:
|
| - return "DW_AT_PGI_lstride";
|
| - default:
|
| - return "DW_AT_<unknown>";
|
| - }
|
| -}
|
|
|
| -/* Convert a DWARF value form code into its string name. */
|
| + name = get_DW_AT_name (attr);
|
|
|
| -static char *
|
| -dwarf_form_name (unsigned form)
|
| -{
|
| - switch (form)
|
| - {
|
| - case DW_FORM_addr:
|
| - return "DW_FORM_addr";
|
| - case DW_FORM_block2:
|
| - return "DW_FORM_block2";
|
| - case DW_FORM_block4:
|
| - return "DW_FORM_block4";
|
| - case DW_FORM_data2:
|
| - return "DW_FORM_data2";
|
| - case DW_FORM_data4:
|
| - return "DW_FORM_data4";
|
| - case DW_FORM_data8:
|
| - return "DW_FORM_data8";
|
| - case DW_FORM_string:
|
| - return "DW_FORM_string";
|
| - case DW_FORM_block:
|
| - return "DW_FORM_block";
|
| - case DW_FORM_block1:
|
| - return "DW_FORM_block1";
|
| - case DW_FORM_data1:
|
| - return "DW_FORM_data1";
|
| - case DW_FORM_flag:
|
| - return "DW_FORM_flag";
|
| - case DW_FORM_sdata:
|
| - return "DW_FORM_sdata";
|
| - case DW_FORM_strp:
|
| - return "DW_FORM_strp";
|
| - case DW_FORM_udata:
|
| - return "DW_FORM_udata";
|
| - case DW_FORM_ref_addr:
|
| - return "DW_FORM_ref_addr";
|
| - case DW_FORM_ref1:
|
| - return "DW_FORM_ref1";
|
| - case DW_FORM_ref2:
|
| - return "DW_FORM_ref2";
|
| - case DW_FORM_ref4:
|
| - return "DW_FORM_ref4";
|
| - case DW_FORM_ref8:
|
| - return "DW_FORM_ref8";
|
| - case DW_FORM_ref_udata:
|
| - return "DW_FORM_ref_udata";
|
| - case DW_FORM_indirect:
|
| - return "DW_FORM_indirect";
|
| - case DW_FORM_sec_offset:
|
| - return "DW_FORM_sec_offset";
|
| - case DW_FORM_exprloc:
|
| - return "DW_FORM_exprloc";
|
| - case DW_FORM_flag_present:
|
| - return "DW_FORM_flag_present";
|
| - case DW_FORM_ref_sig8:
|
| - return "DW_FORM_ref_sig8";
|
| - default:
|
| - return "DW_FORM_<unknown>";
|
| - }
|
| -}
|
| -
|
| -/* Convert a DWARF stack opcode into its string name. */
|
| -
|
| -const char *
|
| -dwarf_stack_op_name (unsigned op)
|
| -{
|
| - switch (op)
|
| - {
|
| - case DW_OP_addr:
|
| - return "DW_OP_addr";
|
| - case DW_OP_deref:
|
| - return "DW_OP_deref";
|
| - case DW_OP_const1u:
|
| - return "DW_OP_const1u";
|
| - case DW_OP_const1s:
|
| - return "DW_OP_const1s";
|
| - case DW_OP_const2u:
|
| - return "DW_OP_const2u";
|
| - case DW_OP_const2s:
|
| - return "DW_OP_const2s";
|
| - case DW_OP_const4u:
|
| - return "DW_OP_const4u";
|
| - case DW_OP_const4s:
|
| - return "DW_OP_const4s";
|
| - case DW_OP_const8u:
|
| - return "DW_OP_const8u";
|
| - case DW_OP_const8s:
|
| - return "DW_OP_const8s";
|
| - case DW_OP_constu:
|
| - return "DW_OP_constu";
|
| - case DW_OP_consts:
|
| - return "DW_OP_consts";
|
| - case DW_OP_dup:
|
| - return "DW_OP_dup";
|
| - case DW_OP_drop:
|
| - return "DW_OP_drop";
|
| - case DW_OP_over:
|
| - return "DW_OP_over";
|
| - case DW_OP_pick:
|
| - return "DW_OP_pick";
|
| - case DW_OP_swap:
|
| - return "DW_OP_swap";
|
| - case DW_OP_rot:
|
| - return "DW_OP_rot";
|
| - case DW_OP_xderef:
|
| - return "DW_OP_xderef";
|
| - case DW_OP_abs:
|
| - return "DW_OP_abs";
|
| - case DW_OP_and:
|
| - return "DW_OP_and";
|
| - case DW_OP_div:
|
| - return "DW_OP_div";
|
| - case DW_OP_minus:
|
| - return "DW_OP_minus";
|
| - case DW_OP_mod:
|
| - return "DW_OP_mod";
|
| - case DW_OP_mul:
|
| - return "DW_OP_mul";
|
| - case DW_OP_neg:
|
| - return "DW_OP_neg";
|
| - case DW_OP_not:
|
| - return "DW_OP_not";
|
| - case DW_OP_or:
|
| - return "DW_OP_or";
|
| - case DW_OP_plus:
|
| - return "DW_OP_plus";
|
| - case DW_OP_plus_uconst:
|
| - return "DW_OP_plus_uconst";
|
| - case DW_OP_shl:
|
| - return "DW_OP_shl";
|
| - case DW_OP_shr:
|
| - return "DW_OP_shr";
|
| - case DW_OP_shra:
|
| - return "DW_OP_shra";
|
| - case DW_OP_xor:
|
| - return "DW_OP_xor";
|
| - case DW_OP_bra:
|
| - return "DW_OP_bra";
|
| - case DW_OP_eq:
|
| - return "DW_OP_eq";
|
| - case DW_OP_ge:
|
| - return "DW_OP_ge";
|
| - case DW_OP_gt:
|
| - return "DW_OP_gt";
|
| - case DW_OP_le:
|
| - return "DW_OP_le";
|
| - case DW_OP_lt:
|
| - return "DW_OP_lt";
|
| - case DW_OP_ne:
|
| - return "DW_OP_ne";
|
| - case DW_OP_skip:
|
| - return "DW_OP_skip";
|
| - case DW_OP_lit0:
|
| - return "DW_OP_lit0";
|
| - case DW_OP_lit1:
|
| - return "DW_OP_lit1";
|
| - case DW_OP_lit2:
|
| - return "DW_OP_lit2";
|
| - case DW_OP_lit3:
|
| - return "DW_OP_lit3";
|
| - case DW_OP_lit4:
|
| - return "DW_OP_lit4";
|
| - case DW_OP_lit5:
|
| - return "DW_OP_lit5";
|
| - case DW_OP_lit6:
|
| - return "DW_OP_lit6";
|
| - case DW_OP_lit7:
|
| - return "DW_OP_lit7";
|
| - case DW_OP_lit8:
|
| - return "DW_OP_lit8";
|
| - case DW_OP_lit9:
|
| - return "DW_OP_lit9";
|
| - case DW_OP_lit10:
|
| - return "DW_OP_lit10";
|
| - case DW_OP_lit11:
|
| - return "DW_OP_lit11";
|
| - case DW_OP_lit12:
|
| - return "DW_OP_lit12";
|
| - case DW_OP_lit13:
|
| - return "DW_OP_lit13";
|
| - case DW_OP_lit14:
|
| - return "DW_OP_lit14";
|
| - case DW_OP_lit15:
|
| - return "DW_OP_lit15";
|
| - case DW_OP_lit16:
|
| - return "DW_OP_lit16";
|
| - case DW_OP_lit17:
|
| - return "DW_OP_lit17";
|
| - case DW_OP_lit18:
|
| - return "DW_OP_lit18";
|
| - case DW_OP_lit19:
|
| - return "DW_OP_lit19";
|
| - case DW_OP_lit20:
|
| - return "DW_OP_lit20";
|
| - case DW_OP_lit21:
|
| - return "DW_OP_lit21";
|
| - case DW_OP_lit22:
|
| - return "DW_OP_lit22";
|
| - case DW_OP_lit23:
|
| - return "DW_OP_lit23";
|
| - case DW_OP_lit24:
|
| - return "DW_OP_lit24";
|
| - case DW_OP_lit25:
|
| - return "DW_OP_lit25";
|
| - case DW_OP_lit26:
|
| - return "DW_OP_lit26";
|
| - case DW_OP_lit27:
|
| - return "DW_OP_lit27";
|
| - case DW_OP_lit28:
|
| - return "DW_OP_lit28";
|
| - case DW_OP_lit29:
|
| - return "DW_OP_lit29";
|
| - case DW_OP_lit30:
|
| - return "DW_OP_lit30";
|
| - case DW_OP_lit31:
|
| - return "DW_OP_lit31";
|
| - case DW_OP_reg0:
|
| - return "DW_OP_reg0";
|
| - case DW_OP_reg1:
|
| - return "DW_OP_reg1";
|
| - case DW_OP_reg2:
|
| - return "DW_OP_reg2";
|
| - case DW_OP_reg3:
|
| - return "DW_OP_reg3";
|
| - case DW_OP_reg4:
|
| - return "DW_OP_reg4";
|
| - case DW_OP_reg5:
|
| - return "DW_OP_reg5";
|
| - case DW_OP_reg6:
|
| - return "DW_OP_reg6";
|
| - case DW_OP_reg7:
|
| - return "DW_OP_reg7";
|
| - case DW_OP_reg8:
|
| - return "DW_OP_reg8";
|
| - case DW_OP_reg9:
|
| - return "DW_OP_reg9";
|
| - case DW_OP_reg10:
|
| - return "DW_OP_reg10";
|
| - case DW_OP_reg11:
|
| - return "DW_OP_reg11";
|
| - case DW_OP_reg12:
|
| - return "DW_OP_reg12";
|
| - case DW_OP_reg13:
|
| - return "DW_OP_reg13";
|
| - case DW_OP_reg14:
|
| - return "DW_OP_reg14";
|
| - case DW_OP_reg15:
|
| - return "DW_OP_reg15";
|
| - case DW_OP_reg16:
|
| - return "DW_OP_reg16";
|
| - case DW_OP_reg17:
|
| - return "DW_OP_reg17";
|
| - case DW_OP_reg18:
|
| - return "DW_OP_reg18";
|
| - case DW_OP_reg19:
|
| - return "DW_OP_reg19";
|
| - case DW_OP_reg20:
|
| - return "DW_OP_reg20";
|
| - case DW_OP_reg21:
|
| - return "DW_OP_reg21";
|
| - case DW_OP_reg22:
|
| - return "DW_OP_reg22";
|
| - case DW_OP_reg23:
|
| - return "DW_OP_reg23";
|
| - case DW_OP_reg24:
|
| - return "DW_OP_reg24";
|
| - case DW_OP_reg25:
|
| - return "DW_OP_reg25";
|
| - case DW_OP_reg26:
|
| - return "DW_OP_reg26";
|
| - case DW_OP_reg27:
|
| - return "DW_OP_reg27";
|
| - case DW_OP_reg28:
|
| - return "DW_OP_reg28";
|
| - case DW_OP_reg29:
|
| - return "DW_OP_reg29";
|
| - case DW_OP_reg30:
|
| - return "DW_OP_reg30";
|
| - case DW_OP_reg31:
|
| - return "DW_OP_reg31";
|
| - case DW_OP_breg0:
|
| - return "DW_OP_breg0";
|
| - case DW_OP_breg1:
|
| - return "DW_OP_breg1";
|
| - case DW_OP_breg2:
|
| - return "DW_OP_breg2";
|
| - case DW_OP_breg3:
|
| - return "DW_OP_breg3";
|
| - case DW_OP_breg4:
|
| - return "DW_OP_breg4";
|
| - case DW_OP_breg5:
|
| - return "DW_OP_breg5";
|
| - case DW_OP_breg6:
|
| - return "DW_OP_breg6";
|
| - case DW_OP_breg7:
|
| - return "DW_OP_breg7";
|
| - case DW_OP_breg8:
|
| - return "DW_OP_breg8";
|
| - case DW_OP_breg9:
|
| - return "DW_OP_breg9";
|
| - case DW_OP_breg10:
|
| - return "DW_OP_breg10";
|
| - case DW_OP_breg11:
|
| - return "DW_OP_breg11";
|
| - case DW_OP_breg12:
|
| - return "DW_OP_breg12";
|
| - case DW_OP_breg13:
|
| - return "DW_OP_breg13";
|
| - case DW_OP_breg14:
|
| - return "DW_OP_breg14";
|
| - case DW_OP_breg15:
|
| - return "DW_OP_breg15";
|
| - case DW_OP_breg16:
|
| - return "DW_OP_breg16";
|
| - case DW_OP_breg17:
|
| - return "DW_OP_breg17";
|
| - case DW_OP_breg18:
|
| - return "DW_OP_breg18";
|
| - case DW_OP_breg19:
|
| - return "DW_OP_breg19";
|
| - case DW_OP_breg20:
|
| - return "DW_OP_breg20";
|
| - case DW_OP_breg21:
|
| - return "DW_OP_breg21";
|
| - case DW_OP_breg22:
|
| - return "DW_OP_breg22";
|
| - case DW_OP_breg23:
|
| - return "DW_OP_breg23";
|
| - case DW_OP_breg24:
|
| - return "DW_OP_breg24";
|
| - case DW_OP_breg25:
|
| - return "DW_OP_breg25";
|
| - case DW_OP_breg26:
|
| - return "DW_OP_breg26";
|
| - case DW_OP_breg27:
|
| - return "DW_OP_breg27";
|
| - case DW_OP_breg28:
|
| - return "DW_OP_breg28";
|
| - case DW_OP_breg29:
|
| - return "DW_OP_breg29";
|
| - case DW_OP_breg30:
|
| - return "DW_OP_breg30";
|
| - case DW_OP_breg31:
|
| - return "DW_OP_breg31";
|
| - case DW_OP_regx:
|
| - return "DW_OP_regx";
|
| - case DW_OP_fbreg:
|
| - return "DW_OP_fbreg";
|
| - case DW_OP_bregx:
|
| - return "DW_OP_bregx";
|
| - case DW_OP_piece:
|
| - return "DW_OP_piece";
|
| - case DW_OP_deref_size:
|
| - return "DW_OP_deref_size";
|
| - case DW_OP_xderef_size:
|
| - return "DW_OP_xderef_size";
|
| - case DW_OP_nop:
|
| - return "DW_OP_nop";
|
| - /* DWARF 3 extensions. */
|
| - case DW_OP_push_object_address:
|
| - return "DW_OP_push_object_address";
|
| - case DW_OP_call2:
|
| - return "DW_OP_call2";
|
| - case DW_OP_call4:
|
| - return "DW_OP_call4";
|
| - case DW_OP_call_ref:
|
| - return "DW_OP_call_ref";
|
| - case DW_OP_form_tls_address:
|
| - return "DW_OP_form_tls_address";
|
| - case DW_OP_call_frame_cfa:
|
| - return "DW_OP_call_frame_cfa";
|
| - case DW_OP_bit_piece:
|
| - return "DW_OP_bit_piece";
|
| - /* DWARF 4 extensions. */
|
| - case DW_OP_implicit_value:
|
| - return "DW_OP_implicit_value";
|
| - case DW_OP_stack_value:
|
| - return "DW_OP_stack_value";
|
| - /* GNU extensions. */
|
| - case DW_OP_GNU_push_tls_address:
|
| - return "DW_OP_GNU_push_tls_address";
|
| - case DW_OP_GNU_uninit:
|
| - return "DW_OP_GNU_uninit";
|
| - case DW_OP_GNU_implicit_pointer:
|
| - return "DW_OP_GNU_implicit_pointer";
|
| - case DW_OP_GNU_entry_value:
|
| - return "DW_OP_GNU_entry_value";
|
| - case DW_OP_GNU_const_type:
|
| - return "DW_OP_GNU_const_type";
|
| - case DW_OP_GNU_regval_type:
|
| - return "DW_OP_GNU_regval_type";
|
| - case DW_OP_GNU_deref_type:
|
| - return "DW_OP_GNU_deref_type";
|
| - case DW_OP_GNU_convert:
|
| - return "DW_OP_GNU_convert";
|
| - case DW_OP_GNU_reinterpret:
|
| - return "DW_OP_GNU_reinterpret";
|
| - default:
|
| - return NULL;
|
| - }
|
| + if (name == NULL)
|
| + return "DW_AT_<unknown>";
|
| +
|
| + return name;
|
| +}
|
| +
|
| +/* Convert a DWARF value form code into its string name. */
|
| +
|
| +static const char *
|
| +dwarf_form_name (unsigned form)
|
| +{
|
| + const char *name = get_DW_FORM_name (form);
|
| +
|
| + if (name == NULL)
|
| + return "DW_FORM_<unknown>";
|
| +
|
| + return name;
|
| }
|
|
|
| static char *
|
| @@ -13850,143 +15896,16 @@ dwarf_bool_name (unsigned mybool)
|
|
|
| /* Convert a DWARF type code into its string name. */
|
|
|
| -static char *
|
| +static const char *
|
| dwarf_type_encoding_name (unsigned enc)
|
| {
|
| - switch (enc)
|
| - {
|
| - case DW_ATE_void:
|
| - return "DW_ATE_void";
|
| - case DW_ATE_address:
|
| - return "DW_ATE_address";
|
| - case DW_ATE_boolean:
|
| - return "DW_ATE_boolean";
|
| - case DW_ATE_complex_float:
|
| - return "DW_ATE_complex_float";
|
| - case DW_ATE_float:
|
| - return "DW_ATE_float";
|
| - case DW_ATE_signed:
|
| - return "DW_ATE_signed";
|
| - case DW_ATE_signed_char:
|
| - return "DW_ATE_signed_char";
|
| - case DW_ATE_unsigned:
|
| - return "DW_ATE_unsigned";
|
| - case DW_ATE_unsigned_char:
|
| - return "DW_ATE_unsigned_char";
|
| - /* DWARF 3. */
|
| - case DW_ATE_imaginary_float:
|
| - return "DW_ATE_imaginary_float";
|
| - case DW_ATE_packed_decimal:
|
| - return "DW_ATE_packed_decimal";
|
| - case DW_ATE_numeric_string:
|
| - return "DW_ATE_numeric_string";
|
| - case DW_ATE_edited:
|
| - return "DW_ATE_edited";
|
| - case DW_ATE_signed_fixed:
|
| - return "DW_ATE_signed_fixed";
|
| - case DW_ATE_unsigned_fixed:
|
| - return "DW_ATE_unsigned_fixed";
|
| - case DW_ATE_decimal_float:
|
| - return "DW_ATE_decimal_float";
|
| - /* DWARF 4. */
|
| - case DW_ATE_UTF:
|
| - return "DW_ATE_UTF";
|
| - /* HP extensions. */
|
| - case DW_ATE_HP_float80:
|
| - return "DW_ATE_HP_float80";
|
| - case DW_ATE_HP_complex_float80:
|
| - return "DW_ATE_HP_complex_float80";
|
| - case DW_ATE_HP_float128:
|
| - return "DW_ATE_HP_float128";
|
| - case DW_ATE_HP_complex_float128:
|
| - return "DW_ATE_HP_complex_float128";
|
| - case DW_ATE_HP_floathpintel:
|
| - return "DW_ATE_HP_floathpintel";
|
| - case DW_ATE_HP_imaginary_float80:
|
| - return "DW_ATE_HP_imaginary_float80";
|
| - case DW_ATE_HP_imaginary_float128:
|
| - return "DW_ATE_HP_imaginary_float128";
|
| - default:
|
| - return "DW_ATE_<unknown>";
|
| - }
|
| -}
|
| + const char *name = get_DW_ATE_name (enc);
|
|
|
| -/* Convert a DWARF call frame info operation to its string name. */
|
| + if (name == NULL)
|
| + return "DW_ATE_<unknown>";
|
|
|
| -#if 0
|
| -static char *
|
| -dwarf_cfi_name (unsigned cfi_opc)
|
| -{
|
| - switch (cfi_opc)
|
| - {
|
| - case DW_CFA_advance_loc:
|
| - return "DW_CFA_advance_loc";
|
| - case DW_CFA_offset:
|
| - return "DW_CFA_offset";
|
| - case DW_CFA_restore:
|
| - return "DW_CFA_restore";
|
| - case DW_CFA_nop:
|
| - return "DW_CFA_nop";
|
| - case DW_CFA_set_loc:
|
| - return "DW_CFA_set_loc";
|
| - case DW_CFA_advance_loc1:
|
| - return "DW_CFA_advance_loc1";
|
| - case DW_CFA_advance_loc2:
|
| - return "DW_CFA_advance_loc2";
|
| - case DW_CFA_advance_loc4:
|
| - return "DW_CFA_advance_loc4";
|
| - case DW_CFA_offset_extended:
|
| - return "DW_CFA_offset_extended";
|
| - case DW_CFA_restore_extended:
|
| - return "DW_CFA_restore_extended";
|
| - case DW_CFA_undefined:
|
| - return "DW_CFA_undefined";
|
| - case DW_CFA_same_value:
|
| - return "DW_CFA_same_value";
|
| - case DW_CFA_register:
|
| - return "DW_CFA_register";
|
| - case DW_CFA_remember_state:
|
| - return "DW_CFA_remember_state";
|
| - case DW_CFA_restore_state:
|
| - return "DW_CFA_restore_state";
|
| - case DW_CFA_def_cfa:
|
| - return "DW_CFA_def_cfa";
|
| - case DW_CFA_def_cfa_register:
|
| - return "DW_CFA_def_cfa_register";
|
| - case DW_CFA_def_cfa_offset:
|
| - return "DW_CFA_def_cfa_offset";
|
| - /* DWARF 3. */
|
| - case DW_CFA_def_cfa_expression:
|
| - return "DW_CFA_def_cfa_expression";
|
| - case DW_CFA_expression:
|
| - return "DW_CFA_expression";
|
| - case DW_CFA_offset_extended_sf:
|
| - return "DW_CFA_offset_extended_sf";
|
| - case DW_CFA_def_cfa_sf:
|
| - return "DW_CFA_def_cfa_sf";
|
| - case DW_CFA_def_cfa_offset_sf:
|
| - return "DW_CFA_def_cfa_offset_sf";
|
| - case DW_CFA_val_offset:
|
| - return "DW_CFA_val_offset";
|
| - case DW_CFA_val_offset_sf:
|
| - return "DW_CFA_val_offset_sf";
|
| - case DW_CFA_val_expression:
|
| - return "DW_CFA_val_expression";
|
| - /* SGI/MIPS specific. */
|
| - case DW_CFA_MIPS_advance_loc8:
|
| - return "DW_CFA_MIPS_advance_loc8";
|
| - /* GNU extensions. */
|
| - case DW_CFA_GNU_window_save:
|
| - return "DW_CFA_GNU_window_save";
|
| - case DW_CFA_GNU_args_size:
|
| - return "DW_CFA_GNU_args_size";
|
| - case DW_CFA_GNU_negative_offset_extended:
|
| - return "DW_CFA_GNU_negative_offset_extended";
|
| - default:
|
| - return "DW_CFA_<unknown>";
|
| - }
|
| + return name;
|
| }
|
| -#endif
|
|
|
| static void
|
| dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
| @@ -13995,13 +15914,13 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
|
|
| print_spaces (indent, f);
|
| fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n",
|
| - dwarf_tag_name (die->tag), die->abbrev, die->offset);
|
| + dwarf_tag_name (die->tag), die->abbrev, die->offset.sect_off);
|
|
|
| if (die->parent != NULL)
|
| {
|
| print_spaces (indent, f);
|
| fprintf_unfiltered (f, " parent at offset: 0x%x\n",
|
| - die->parent->offset);
|
| + die->parent->offset.sect_off);
|
| }
|
|
|
| print_spaces (indent, f);
|
| @@ -14020,8 +15939,8 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
|
|
| switch (die->attrs[i].form)
|
| {
|
| - case DW_FORM_ref_addr:
|
| case DW_FORM_addr:
|
| + case DW_FORM_GNU_addr_index:
|
| fprintf_unfiltered (f, "address: ");
|
| fputs_filtered (hex_string (DW_ADDR (&die->attrs[i])), f);
|
| break;
|
| @@ -14036,11 +15955,17 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
| fprintf_unfiltered (f, "expression: size %u",
|
| 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_ref1:
|
| case DW_FORM_ref2:
|
| case DW_FORM_ref4:
|
| + case DW_FORM_ref8:
|
| + case DW_FORM_ref_udata:
|
| fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
|
| - (long) (DW_ADDR (&die->attrs[i])));
|
| + (long) (DW_UNSND (&die->attrs[i])));
|
| break;
|
| case DW_FORM_data1:
|
| case DW_FORM_data2:
|
| @@ -14058,12 +15983,13 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
|
| 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);
|
| + DW_SIGNATURED_TYPE (&die->attrs[i])->per_cu.offset.sect_off);
|
| else
|
| fprintf_unfiltered (f, "signatured type, offset: unknown");
|
| break;
|
| case DW_FORM_string:
|
| case DW_FORM_strp:
|
| + case DW_FORM_GNU_str_index:
|
| fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
|
| DW_STRING (&die->attrs[i])
|
| ? DW_STRING (&die->attrs[i]) : "",
|
| @@ -14147,11 +16073,15 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu)
|
| {
|
| void **slot;
|
|
|
| - slot = htab_find_slot_with_hash (cu->die_hash, die, die->offset, INSERT);
|
| + slot = htab_find_slot_with_hash (cu->die_hash, die, die->offset.sect_off,
|
| + INSERT);
|
|
|
| *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)
|
| {
|
| @@ -14169,16 +16099,22 @@ is_ref_attr (struct attribute *attr)
|
| }
|
| }
|
|
|
| -static unsigned int
|
| +/* 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)
|
| {
|
| + sect_offset retval = { DW_UNSND (attr) };
|
| +
|
| if (is_ref_attr (attr))
|
| - return DW_ADDR (attr);
|
| + return retval;
|
|
|
| + retval.sect_off = 0;
|
| complaint (&symfile_complaints,
|
| _("unsupported die ref attribute form: '%s'"),
|
| dwarf_form_name (attr->form));
|
| - return 0;
|
| + return retval;
|
| }
|
|
|
| /* Return the constant value held by ATTR. Return DEFAULT_VALUE if
|
| @@ -14204,47 +16140,6 @@ dwarf2_get_attr_constant_value (struct attribute *attr, int default_value)
|
| }
|
| }
|
|
|
| -/* THIS_CU has a reference to PER_CU. If necessary, load the new compilation
|
| - unit and add it to our queue.
|
| - 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. */
|
| -
|
| -static int
|
| -maybe_queue_comp_unit (struct dwarf2_cu *this_cu,
|
| - struct dwarf2_per_cu_data *per_cu)
|
| -{
|
| - /* We may arrive here during partial symbol reading, if we need full
|
| - DIEs to process an unusual case (e.g. template arguments). Do
|
| - not queue PER_CU, just tell our caller to load its DIEs. */
|
| - if (dwarf2_per_objfile->reading_partial_symbols)
|
| - {
|
| - if (per_cu->cu == NULL || per_cu->cu->dies == NULL)
|
| - return 1;
|
| - return 0;
|
| - }
|
| -
|
| - /* Mark the dependence relation so that we don't flush PER_CU
|
| - too early. */
|
| - dwarf2_add_dependence (this_cu, per_cu);
|
| -
|
| - /* If it's already on the queue, we have nothing to do. */
|
| - if (per_cu->queued)
|
| - return 0;
|
| -
|
| - /* If the compilation unit is already loaded, just mark it as
|
| - used. */
|
| - if (per_cu->cu != NULL)
|
| - {
|
| - per_cu->cu->last_used = 0;
|
| - return 0;
|
| - }
|
| -
|
| - /* Add it to the queue. */
|
| - queue_comp_unit (per_cu, this_cu->objfile);
|
| -
|
| - return 1;
|
| -}
|
| -
|
| /* Follow reference or signature attribute ATTR of SRC_DIE.
|
| On entry *REF_CU is the CU of SRC_DIE.
|
| On exit *REF_CU is the CU of the result. */
|
| @@ -14275,7 +16170,7 @@ 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 (unsigned int offset, struct dwarf2_cu **ref_cu)
|
| +follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
|
| {
|
| struct die_info temp_die;
|
| struct dwarf2_cu *target_cu, *cu = *ref_cu;
|
| @@ -14284,7 +16179,7 @@ follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu)
|
|
|
| target_cu = cu;
|
|
|
| - if (cu->per_cu->debug_types_section)
|
| + if (cu->per_cu->is_debug_types)
|
| {
|
| /* .debug_types CUs cannot reference anything outside their CU.
|
| If they need to, they have to reference a signatured type via
|
| @@ -14299,8 +16194,8 @@ follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu)
|
| per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
|
|
|
| /* If necessary, add it to the queue and load its DIEs. */
|
| - if (maybe_queue_comp_unit (cu, per_cu))
|
| - load_full_comp_unit (per_cu, cu->objfile);
|
| + if (maybe_queue_comp_unit (cu, per_cu, cu->language))
|
| + load_full_comp_unit (per_cu, cu->language);
|
|
|
| target_cu = per_cu->cu;
|
| }
|
| @@ -14308,12 +16203,12 @@ follow_die_offset (unsigned int offset, struct dwarf2_cu **ref_cu)
|
| {
|
| /* We're loading full DIEs during partial symbol reading. */
|
| gdb_assert (dwarf2_per_objfile->reading_partial_symbols);
|
| - load_full_comp_unit (cu->per_cu, cu->objfile);
|
| + load_full_comp_unit (cu->per_cu, language_minimal);
|
| }
|
|
|
| *ref_cu = target_cu;
|
| temp_die.offset = offset;
|
| - return htab_find_with_hash (target_cu->die_hash, &temp_die, offset);
|
| + return htab_find_with_hash (target_cu->die_hash, &temp_die, offset.sect_off);
|
| }
|
|
|
| /* Follow reference attribute ATTR of SRC_DIE.
|
| @@ -14324,7 +16219,7 @@ static struct die_info *
|
| follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
| struct dwarf2_cu **ref_cu)
|
| {
|
| - unsigned int offset = dwarf2_get_ref_die_offset (attr);
|
| + sect_offset offset = dwarf2_get_ref_die_offset (attr);
|
| struct dwarf2_cu *cu = *ref_cu;
|
| struct die_info *die;
|
|
|
| @@ -14332,7 +16227,7 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
| if (!die)
|
| error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
|
| "at 0x%x [in module %s]"),
|
| - offset, src_die->offset, cu->objfile->name);
|
| + offset.sect_off, src_die->offset.sect_off, cu->objfile->name);
|
|
|
| return die;
|
| }
|
| @@ -14342,11 +16237,12 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
|
| dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */
|
|
|
| struct dwarf2_locexpr_baton
|
| -dwarf2_fetch_die_location_block (unsigned int offset,
|
| +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)
|
| {
|
| + sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off };
|
| struct dwarf2_cu *cu;
|
| struct die_info *die;
|
| struct attribute *attr;
|
| @@ -14361,7 +16257,7 @@ dwarf2_fetch_die_location_block (unsigned int offset,
|
| die = follow_die_offset (offset, &cu);
|
| if (!die)
|
| error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
|
| - offset, per_cu->cu->objfile->name);
|
| + offset.sect_off, per_cu->objfile->name);
|
|
|
| attr = dwarf2_attr (die, DW_AT_location, cu);
|
| if (!attr)
|
| @@ -14389,7 +16285,7 @@ dwarf2_fetch_die_location_block (unsigned int offset,
|
| 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, per_cu->cu->objfile->name);
|
| + offset.sect_off, per_cu->objfile->name);
|
|
|
| retval.data = DW_BLOCK (attr)->data;
|
| retval.size = DW_BLOCK (attr)->size;
|
| @@ -14405,11 +16301,15 @@ dwarf2_fetch_die_location_block (unsigned int offset,
|
| PER_CU. */
|
|
|
| struct type *
|
| -dwarf2_get_die_type (unsigned int die_offset,
|
| +dwarf2_get_die_type (cu_offset die_offset,
|
| struct dwarf2_per_cu_data *per_cu)
|
| {
|
| + sect_offset die_offset_sect;
|
| +
|
| dw2_setup (per_cu->objfile);
|
| - return get_die_type_at_offset (die_offset, per_cu);
|
| +
|
| + die_offset_sect.sect_off = per_cu->offset.sect_off + die_offset.cu_off;
|
| + return get_die_type_at_offset (die_offset_sect, per_cu);
|
| }
|
|
|
| /* Follow the signature attribute ATTR in SRC_DIE.
|
| @@ -14431,18 +16331,20 @@ follow_die_sig (struct die_info *src_die, struct attribute *attr,
|
| if (sig_type == NULL)
|
| error (_("Dwarf Error: Cannot find signatured DIE referenced from DIE "
|
| "at 0x%x [in module %s]"),
|
| - src_die->offset, objfile->name);
|
| + src_die->offset.sect_off, objfile->name);
|
|
|
| /* If necessary, add it to the queue and load its DIEs. */
|
|
|
| - if (maybe_queue_comp_unit (*ref_cu, &sig_type->per_cu))
|
| - read_signatured_type (objfile, sig_type);
|
| + 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;
|
| - temp_die.offset = sig_cu->header.offset + sig_type->type_offset;
|
| - die = htab_find_with_hash (sig_cu->die_hash, &temp_die, temp_die.offset);
|
| + 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)
|
| {
|
| *ref_cu = sig_cu;
|
| @@ -14451,7 +16353,7 @@ follow_die_sig (struct die_info *src_die, struct attribute *attr,
|
|
|
| error (_("Dwarf Error: Cannot find signatured DIE at 0x%x referenced "
|
| "from DIE at 0x%x [in module %s]"),
|
| - sig_type->type_offset, src_die->offset, objfile->name);
|
| + temp_die.offset.sect_off, src_die->offset.sect_off, objfile->name);
|
| }
|
|
|
| /* Given an offset of a signatured type, return its signatured_type. */
|
| @@ -14459,12 +16361,12 @@ follow_die_sig (struct die_info *src_die, struct attribute *attr,
|
| static struct signatured_type *
|
| lookup_signatured_type_at_offset (struct objfile *objfile,
|
| struct dwarf2_section_info *section,
|
| - unsigned int offset)
|
| + sect_offset offset)
|
| {
|
| - gdb_byte *info_ptr = section->buffer + 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, *type_sig;
|
| + struct signatured_type find_entry, *sig_type;
|
|
|
| length = read_initial_length (objfile->obfd, info_ptr, &initial_length_size);
|
| sig_offset = (initial_length_size
|
| @@ -14472,100 +16374,90 @@ lookup_signatured_type_at_offset (struct objfile *objfile,
|
| + (initial_length_size == 4 ? 4 : 8) /*debug_abbrev_offset*/
|
| + 1 /*address_size*/);
|
| find_entry.signature = bfd_get_64 (objfile->obfd, info_ptr + sig_offset);
|
| - type_sig = htab_find (dwarf2_per_objfile->signatured_types, &find_entry);
|
| + 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 (type_sig != NULL);
|
| - gdb_assert (offset == type_sig->per_cu.offset);
|
| + gdb_assert (sig_type != NULL);
|
| + gdb_assert (offset.sect_off == sig_type->per_cu.offset.sect_off);
|
|
|
| - return type_sig;
|
| + return sig_type;
|
| }
|
|
|
| -/* Read in signatured type at OFFSET and build its CU and die(s). */
|
| +/* Load the DIEs associated with type unit PER_CU into memory. */
|
|
|
| static void
|
| -read_signatured_type_at_offset (struct objfile *objfile,
|
| - struct dwarf2_section_info *sect,
|
| - unsigned int offset)
|
| +load_full_type_unit (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| - struct signatured_type *type_sig;
|
| + struct signatured_type *sig_type;
|
|
|
| - dwarf2_read_section (objfile, sect);
|
| + /* Caller is responsible for ensuring type_unit_groups don't get here. */
|
| + gdb_assert (! IS_TYPE_UNIT_GROUP (per_cu));
|
|
|
| - /* We have the section offset, but we need the signature to do the
|
| - hash table lookup. */
|
| - type_sig = lookup_signatured_type_at_offset (objfile, sect, offset);
|
| + /* We have the per_cu, but we need the signatured_type.
|
| + Fortunately this is an easy translation. */
|
| + gdb_assert (per_cu->is_debug_types);
|
| + sig_type = (struct signatured_type *) per_cu;
|
|
|
| - gdb_assert (type_sig->per_cu.cu == NULL);
|
| + gdb_assert (per_cu->cu == NULL);
|
|
|
| - read_signatured_type (objfile, type_sig);
|
| + read_signatured_type (sig_type);
|
|
|
| - gdb_assert (type_sig->per_cu.cu != NULL);
|
| + gdb_assert (per_cu->cu != NULL);
|
| }
|
|
|
| -/* Read in a signatured type and build its CU and DIEs. */
|
| +/* die_reader_func for read_signatured_type.
|
| + This is identical to load_full_comp_unit_reader,
|
| + but is kept separate for now. */
|
|
|
| static void
|
| -read_signatured_type (struct objfile *objfile,
|
| - struct signatured_type *type_sig)
|
| +read_signatured_type_reader (const struct die_reader_specs *reader,
|
| + gdb_byte *info_ptr,
|
| + struct die_info *comp_unit_die,
|
| + int has_children,
|
| + void *data)
|
| {
|
| - gdb_byte *types_ptr;
|
| - struct die_reader_specs reader_specs;
|
| - struct dwarf2_cu *cu;
|
| - ULONGEST signature;
|
| - struct cleanup *back_to, *free_cu_cleanup;
|
| - struct dwarf2_section_info *section = type_sig->per_cu.debug_types_section;
|
| -
|
| - dwarf2_read_section (objfile, section);
|
| - types_ptr = section->buffer + type_sig->per_cu.offset;
|
| -
|
| - gdb_assert (type_sig->per_cu.cu == NULL);
|
| -
|
| - cu = xmalloc (sizeof (*cu));
|
| - init_one_comp_unit (cu, objfile);
|
| -
|
| - type_sig->per_cu.cu = cu;
|
| - cu->per_cu = &type_sig->per_cu;
|
| -
|
| - /* If an error occurs while loading, release our storage. */
|
| - free_cu_cleanup = make_cleanup (free_one_comp_unit, cu);
|
| -
|
| - types_ptr = read_type_comp_unit_head (&cu->header, section, &signature,
|
| - types_ptr, objfile->obfd);
|
| - gdb_assert (signature == type_sig->signature);
|
| -
|
| - cu->die_hash
|
| - = htab_create_alloc_ex (cu->header.length / 12,
|
| - die_hash,
|
| - die_eq,
|
| - NULL,
|
| - &cu->comp_unit_obstack,
|
| - hashtab_obstack_allocate,
|
| - dummy_obstack_deallocate);
|
| -
|
| - dwarf2_read_abbrevs (cu->objfile->obfd, cu);
|
| - back_to = make_cleanup (dwarf2_free_abbrev_table, cu);
|
| + struct dwarf2_cu *cu = reader->cu;
|
|
|
| - init_cu_die_reader (&reader_specs, cu);
|
| + gdb_assert (cu->die_hash == NULL);
|
| + cu->die_hash =
|
| + htab_create_alloc_ex (cu->header.length / 12,
|
| + die_hash,
|
| + die_eq,
|
| + NULL,
|
| + &cu->comp_unit_obstack,
|
| + hashtab_obstack_allocate,
|
| + dummy_obstack_deallocate);
|
|
|
| - cu->dies = read_die_and_children (&reader_specs, types_ptr, &types_ptr,
|
| - NULL /*parent*/);
|
| + if (has_children)
|
| + comp_unit_die->child = read_die_and_siblings (reader, info_ptr,
|
| + &info_ptr, comp_unit_die);
|
| + cu->dies = comp_unit_die;
|
| + /* comp_unit_die is not stored in die_hash, no need. */
|
|
|
| /* We try not to read any attributes in this function, because not
|
| - all objfiles needed for references have been loaded yet, and symbol
|
| + all CUs needed for references have been loaded yet, and symbol
|
| table processing isn't initialized. But we have to set the CU language,
|
| - or we won't be able to build types correctly. */
|
| - prepare_one_comp_unit (cu, cu->dies);
|
| + or we won't be able to build types correctly.
|
| + Similarly, if we do not read the producer, we can not apply
|
| + producer-specific interpretation. */
|
| + prepare_one_comp_unit (cu, cu->dies, language_minimal);
|
| +}
|
|
|
| - do_cleanups (back_to);
|
| +/* Read in a signatured type and build its CU and DIEs.
|
| + If the type is a stub for the real type in a DWO file,
|
| + read in the real type from the DWO file as well. */
|
| +
|
| +static void
|
| +read_signatured_type (struct signatured_type *sig_type)
|
| +{
|
| + struct dwarf2_per_cu_data *per_cu = &sig_type->per_cu;
|
|
|
| - /* We've successfully allocated this compilation unit. Let our caller
|
| - clean it up when finished with it. */
|
| - discard_cleanups (free_cu_cleanup);
|
| + gdb_assert (per_cu->is_debug_types);
|
| + gdb_assert (per_cu->cu == NULL);
|
|
|
| - type_sig->per_cu.cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
|
| - dwarf2_per_objfile->read_in_chain = &type_sig->per_cu;
|
| + init_cutu_and_read_dies (per_cu, NULL, 0, 1,
|
| + read_signatured_type_reader, NULL);
|
| }
|
|
|
| /* Decode simple location descriptions.
|
| @@ -14790,9 +16682,16 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu)
|
| case DW_OP_GNU_uninit:
|
| break;
|
|
|
| + case DW_OP_GNU_addr_index:
|
| + case DW_OP_GNU_const_index:
|
| + stack[++stacki] = read_addr_index_from_leb128 (cu, &data[i],
|
| + &bytes_read);
|
| + i += bytes_read;
|
| + break;
|
| +
|
| default:
|
| {
|
| - const char *name = dwarf_stack_op_name (op);
|
| + const char *name = get_DW_OP_name (op);
|
|
|
| if (name)
|
| complaint (&symfile_complaints, _("unsupported stack op: '%s'"),
|
| @@ -14836,17 +16735,6 @@ dwarf_alloc_block (struct dwarf2_cu *cu)
|
| return (blk);
|
| }
|
|
|
| -static struct abbrev_info *
|
| -dwarf_alloc_abbrev (struct dwarf2_cu *cu)
|
| -{
|
| - struct abbrev_info *abbrev;
|
| -
|
| - abbrev = (struct abbrev_info *)
|
| - obstack_alloc (&cu->abbrev_obstack, sizeof (struct abbrev_info));
|
| - memset (abbrev, 0, sizeof (struct abbrev_info));
|
| - return (abbrev);
|
| -}
|
| -
|
| static struct die_info *
|
| dwarf_alloc_die (struct dwarf2_cu *cu, int num_attrs)
|
| {
|
| @@ -14937,9 +16825,12 @@ macro_start_file (int file, int line,
|
| objfile->macro_cache);
|
|
|
| if (! current_file)
|
| - /* 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);
|
| + {
|
| + /* 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);
|
| + }
|
| else
|
| current_file = macro_include (current_file, line, full_name);
|
|
|
| @@ -15124,7 +17015,7 @@ parse_macro_definition (struct macro_source_file *file, int line,
|
| Returns the new pointer. */
|
|
|
| static gdb_byte *
|
| -skip_form_bytes (bfd *abfd, gdb_byte *bytes,
|
| +skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
|
| enum dwarf_form form,
|
| unsigned int offset_size,
|
| struct dwarf2_section_info *section)
|
| @@ -15177,7 +17068,14 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes,
|
|
|
| case DW_FORM_sdata:
|
| case DW_FORM_udata:
|
| - bytes = skip_leb128 (abfd, bytes);
|
| + case DW_FORM_GNU_addr_index:
|
| + case DW_FORM_GNU_str_index:
|
| + bytes = (gdb_byte *) gdb_skip_leb128 (bytes, buffer_end);
|
| + if (bytes == NULL)
|
| + {
|
| + dwarf2_section_buffer_overflow_complaint (section);
|
| + return NULL;
|
| + }
|
| break;
|
|
|
| default:
|
| @@ -15201,7 +17099,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes,
|
| static gdb_byte *
|
| skip_unknown_opcode (unsigned int opcode,
|
| gdb_byte **opcode_definitions,
|
| - gdb_byte *mac_ptr,
|
| + gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| bfd *abfd,
|
| unsigned int offset_size,
|
| struct dwarf2_section_info *section)
|
| @@ -15224,7 +17122,8 @@ skip_unknown_opcode (unsigned int opcode,
|
|
|
| for (i = 0; i < arg; ++i)
|
| {
|
| - mac_ptr = skip_form_bytes (abfd, mac_ptr, defn[i], offset_size, section);
|
| + mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end, defn[i], offset_size,
|
| + section);
|
| if (mac_ptr == NULL)
|
| {
|
| /* skip_form_bytes already issued the complaint. */
|
| @@ -15297,7 +17196,7 @@ dwarf_parse_macro_header (gdb_byte **opcode_definitions,
|
| }
|
|
|
| /* A helper for dwarf_decode_macros that handles the GNU extensions,
|
| - including DW_GNU_MACINFO_transparent_include. */
|
| + including DW_MACRO_GNU_transparent_include. */
|
|
|
| static void
|
| dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| @@ -15306,7 +17205,8 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| struct dwarf2_section_info *section,
|
| int section_is_gnu,
|
| unsigned int offset_size,
|
| - struct objfile *objfile)
|
| + struct objfile *objfile,
|
| + htab_t include_hash)
|
| {
|
| enum dwarf_macro_record_type macinfo_type;
|
| int at_commandline;
|
| @@ -15334,7 +17234,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| /* Do we at least have room for a macinfo type byte? */
|
| if (mac_ptr >= mac_end)
|
| {
|
| - dwarf2_macros_too_long_complaint (section);
|
| + dwarf2_section_buffer_overflow_complaint (section);
|
| break;
|
| }
|
|
|
| @@ -15461,7 +17361,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| /* Do we at least have room for a macinfo type byte? */
|
| if (mac_ptr >= mac_end)
|
| {
|
| - dwarf2_macros_too_long_complaint (section);
|
| + dwarf2_section_buffer_overflow_complaint (section);
|
| return;
|
| }
|
|
|
| @@ -15481,16 +17381,33 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| case DW_MACRO_GNU_transparent_include:
|
| {
|
| LONGEST offset;
|
| + void **slot;
|
|
|
| offset = read_offset_1 (abfd, mac_ptr, offset_size);
|
| mac_ptr += offset_size;
|
|
|
| - dwarf_decode_macro_bytes (abfd,
|
| - section->buffer + offset,
|
| - mac_end, current_file,
|
| - lh, comp_dir,
|
| - section, section_is_gnu,
|
| - offset_size, objfile);
|
| + slot = htab_find_slot (include_hash, mac_ptr, INSERT);
|
| + if (*slot != NULL)
|
| + {
|
| + /* This has actually happened; see
|
| + http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */
|
| + complaint (&symfile_complaints,
|
| + _("recursive DW_MACRO_GNU_transparent_include in "
|
| + ".debug_macro section"));
|
| + }
|
| + else
|
| + {
|
| + *slot = mac_ptr;
|
| +
|
| + dwarf_decode_macro_bytes (abfd,
|
| + section->buffer + offset,
|
| + mac_end, current_file,
|
| + lh, comp_dir,
|
| + section, section_is_gnu,
|
| + offset_size, objfile, include_hash);
|
| +
|
| + htab_remove_elt (include_hash, mac_ptr);
|
| + }
|
| }
|
| break;
|
|
|
| @@ -15512,7 +17429,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
|
|
| default:
|
| mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
|
| - mac_ptr, abfd, offset_size,
|
| + mac_ptr, mac_end, abfd, offset_size,
|
| section);
|
| if (mac_ptr == NULL)
|
| return;
|
| @@ -15522,25 +17439,57 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
|
| }
|
|
|
| static void
|
| -dwarf_decode_macros (struct line_header *lh, unsigned int offset,
|
| - char *comp_dir, bfd *abfd,
|
| - struct dwarf2_cu *cu,
|
| - struct dwarf2_section_info *section,
|
| - int section_is_gnu)
|
| +dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
|
| + 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;
|
| 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];
|
| + struct cleanup *cleanup;
|
| + htab_t include_hash;
|
| + void **slot;
|
| + struct dwarf2_section_info *section;
|
| + const char *section_name;
|
|
|
| - dwarf2_read_section (dwarf2_per_objfile->objfile, section);
|
| + if (cu->dwo_unit != NULL)
|
| + {
|
| + if (section_is_gnu)
|
| + {
|
| + section = &cu->dwo_unit->dwo_file->sections.macro;
|
| + section_name = ".debug_macro.dwo";
|
| + }
|
| + else
|
| + {
|
| + section = &cu->dwo_unit->dwo_file->sections.macinfo;
|
| + section_name = ".debug_macinfo.dwo";
|
| + }
|
| + }
|
| + else
|
| + {
|
| + if (section_is_gnu)
|
| + {
|
| + section = &dwarf2_per_objfile->macro;
|
| + section_name = ".debug_macro";
|
| + }
|
| + else
|
| + {
|
| + section = &dwarf2_per_objfile->macinfo;
|
| + section_name = ".debug_macinfo";
|
| + }
|
| + }
|
| +
|
| + dwarf2_read_section (objfile, section);
|
| if (section->buffer == NULL)
|
| {
|
| - complaint (&symfile_complaints, _("missing %s section"),
|
| - section->asection->name);
|
| + complaint (&symfile_complaints, _("missing %s section"), section_name);
|
| return;
|
| }
|
| + abfd = section->asection->owner;
|
|
|
| /* First pass: Find the name of the base filename.
|
| This filename is needed in order to process all macros whose definition
|
| @@ -15611,7 +17560,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
|
| mac_ptr += bytes_read;
|
|
|
| current_file = macro_start_file (file, line, current_file,
|
| - comp_dir, lh, cu->objfile);
|
| + comp_dir, lh, objfile);
|
| }
|
| break;
|
|
|
| @@ -15652,7 +17601,7 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
|
|
|
| default:
|
| mac_ptr = skip_unknown_opcode (macinfo_type, opcode_definitions,
|
| - mac_ptr, abfd, offset_size,
|
| + mac_ptr, mac_end, abfd, offset_size,
|
| section);
|
| if (mac_ptr == NULL)
|
| return;
|
| @@ -15666,13 +17615,21 @@ dwarf_decode_macros (struct line_header *lh, unsigned int offset,
|
| command-line macro definitions/undefinitions. This flag is unset when we
|
| reach the first DW_MACINFO_start_file entry. */
|
|
|
| - dwarf_decode_macro_bytes (abfd, section->buffer + offset, mac_end,
|
| + include_hash = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
|
| + NULL, xcalloc, xfree);
|
| + cleanup = make_cleanup_htab_delete (include_hash);
|
| + mac_ptr = section->buffer + offset;
|
| + slot = htab_find_slot (include_hash, mac_ptr, INSERT);
|
| + *slot = mac_ptr;
|
| + dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
|
| current_file, lh, comp_dir, section, section_is_gnu,
|
| - offset_size, cu->objfile);
|
| + offset_size, objfile, include_hash);
|
| + do_cleanups (cleanup);
|
| }
|
|
|
| /* Check if the attribute's form is a DW_FORM_block*
|
| if so return true else false. */
|
| +
|
| static int
|
| attr_form_is_block (struct attribute *attr)
|
| {
|
| @@ -15692,6 +17649,7 @@ attr_form_is_block (struct attribute *attr)
|
| may have a value that belongs to more than one of these classes; it
|
| would be ambiguous if we did, because we use the same forms for all
|
| of them. */
|
| +
|
| static int
|
| attr_form_is_section_offset (struct attribute *attr)
|
| {
|
| @@ -15700,7 +17658,6 @@ attr_form_is_section_offset (struct attribute *attr)
|
| || attr->form == DW_FORM_sec_offset);
|
| }
|
|
|
| -
|
| /* Return non-zero if ATTR's value falls in the 'constant' class, or
|
| zero otherwise. When this function returns true, you can apply
|
| dwarf2_get_attr_constant_value to it.
|
| @@ -15713,6 +17670,7 @@ attr_form_is_section_offset (struct attribute *attr)
|
| that, if an attribute's can be either a constant or one of the
|
| section offset classes, DW_FORM_data4 and DW_FORM_data8 should be
|
| taken as section offsets, not constants. */
|
| +
|
| static int
|
| attr_form_is_constant (struct attribute *attr)
|
| {
|
| @@ -15730,6 +17688,17 @@ attr_form_is_constant (struct attribute *attr)
|
| }
|
| }
|
|
|
| +/* Return the .debug_loc section to use for CU.
|
| + For DWO files use .debug_loc.dwo. */
|
| +
|
| +static struct dwarf2_section_info *
|
| +cu_debug_loc_section (struct dwarf2_cu *cu)
|
| +{
|
| + if (cu->dwo_unit)
|
| + return &cu->dwo_unit->dwo_file->sections.loc;
|
| + return &dwarf2_per_objfile->loc;
|
| +}
|
| +
|
| /* A helper function that fills in a dwarf2_loclist_baton. */
|
|
|
| static void
|
| @@ -15737,32 +17706,36 @@ fill_in_loclist_baton (struct dwarf2_cu *cu,
|
| struct dwarf2_loclist_baton *baton,
|
| struct attribute *attr)
|
| {
|
| - dwarf2_read_section (dwarf2_per_objfile->objfile,
|
| - &dwarf2_per_objfile->loc);
|
| + struct dwarf2_section_info *section = cu_debug_loc_section (cu);
|
| +
|
| + dwarf2_read_section (dwarf2_per_objfile->objfile, section);
|
|
|
| baton->per_cu = cu->per_cu;
|
| gdb_assert (baton->per_cu);
|
| /* We don't know how long the location list is, but make sure we
|
| don't run off the edge of the section. */
|
| - baton->size = dwarf2_per_objfile->loc.size - DW_UNSND (attr);
|
| - baton->data = dwarf2_per_objfile->loc.buffer + DW_UNSND (attr);
|
| + baton->size = section->size - DW_UNSND (attr);
|
| + baton->data = section->buffer + DW_UNSND (attr);
|
| baton->base_address = cu->base_address;
|
| + baton->from_dwo = cu->dwo_unit != NULL;
|
| }
|
|
|
| static void
|
| dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
|
| struct dwarf2_cu *cu)
|
| {
|
| + struct objfile *objfile = dwarf2_per_objfile->objfile;
|
| + struct dwarf2_section_info *section = cu_debug_loc_section (cu);
|
| +
|
| if (attr_form_is_section_offset (attr)
|
| - /* ".debug_loc" may not exist at all, or the offset may be outside
|
| + /* .debug_loc{,.dwo} may not exist at all, or the offset may be outside
|
| the section. If so, fall through to the complaint in the
|
| other branch. */
|
| - && DW_UNSND (attr) < dwarf2_section_size (dwarf2_per_objfile->objfile,
|
| - &dwarf2_per_objfile->loc))
|
| + && DW_UNSND (attr) < dwarf2_section_size (objfile, section))
|
| {
|
| struct dwarf2_loclist_baton *baton;
|
|
|
| - baton = obstack_alloc (&cu->objfile->objfile_obstack,
|
| + baton = obstack_alloc (&objfile->objfile_obstack,
|
| sizeof (struct dwarf2_loclist_baton));
|
|
|
| fill_in_loclist_baton (cu, baton, attr);
|
| @@ -15779,7 +17752,7 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym,
|
| {
|
| struct dwarf2_locexpr_baton *baton;
|
|
|
| - baton = obstack_alloc (&cu->objfile->objfile_obstack,
|
| + baton = obstack_alloc (&objfile->objfile_obstack,
|
| sizeof (struct dwarf2_locexpr_baton));
|
| baton->per_cu = cu->per_cu;
|
| gdb_assert (baton->per_cu);
|
| @@ -15831,26 +17804,22 @@ static const struct comp_unit_head *
|
| per_cu_header_read_in (struct comp_unit_head *cu_headerp,
|
| struct dwarf2_per_cu_data *per_cu)
|
| {
|
| - struct objfile *objfile;
|
| - struct dwarf2_per_objfile *per_objfile;
|
| gdb_byte *info_ptr;
|
|
|
| if (per_cu->cu)
|
| return &per_cu->cu->header;
|
|
|
| - objfile = per_cu->objfile;
|
| - per_objfile = objfile_data (objfile, dwarf2_objfile_data_key);
|
| - info_ptr = per_objfile->info.buffer + per_cu->offset;
|
| + info_ptr = per_cu->info_or_types_section->buffer + per_cu->offset.sect_off;
|
|
|
| memset (cu_headerp, 0, sizeof (*cu_headerp));
|
| - read_comp_unit_head (cu_headerp, info_ptr, objfile->obfd);
|
| + read_comp_unit_head (cu_headerp, info_ptr, per_cu->objfile->obfd);
|
|
|
| return cu_headerp;
|
| }
|
|
|
| /* Return the address size given in the compilation unit header for CU. */
|
|
|
| -CORE_ADDR
|
| +int
|
| dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu)
|
| {
|
| struct comp_unit_head cu_header_local;
|
| @@ -15907,7 +17876,7 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu)
|
| the DIE at OFFSET. Raises an error on failure. */
|
|
|
| static struct dwarf2_per_cu_data *
|
| -dwarf2_find_containing_comp_unit (unsigned int offset,
|
| +dwarf2_find_containing_comp_unit (sect_offset offset,
|
| struct objfile *objfile)
|
| {
|
| struct dwarf2_per_cu_data *this_cu;
|
| @@ -15919,61 +17888,53 @@ dwarf2_find_containing_comp_unit (unsigned int offset,
|
| {
|
| int mid = low + (high - low) / 2;
|
|
|
| - if (dwarf2_per_objfile->all_comp_units[mid]->offset >= offset)
|
| + if (dwarf2_per_objfile->all_comp_units[mid]->offset.sect_off
|
| + >= offset.sect_off)
|
| high = mid;
|
| else
|
| low = mid + 1;
|
| }
|
| gdb_assert (low == high);
|
| - if (dwarf2_per_objfile->all_comp_units[low]->offset > offset)
|
| + if (dwarf2_per_objfile->all_comp_units[low]->offset.sect_off
|
| + > offset.sect_off)
|
| {
|
| if (low == 0)
|
| error (_("Dwarf Error: could not find partial DIE containing "
|
| "offset 0x%lx [in module %s]"),
|
| - (long) offset, bfd_get_filename (objfile->obfd));
|
| + (long) offset.sect_off, bfd_get_filename (objfile->obfd));
|
|
|
| - gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset <= offset);
|
| + gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset.sect_off
|
| + <= offset.sect_off);
|
| return dwarf2_per_objfile->all_comp_units[low-1];
|
| }
|
| else
|
| {
|
| this_cu = dwarf2_per_objfile->all_comp_units[low];
|
| if (low == dwarf2_per_objfile->n_comp_units - 1
|
| - && offset >= this_cu->offset + this_cu->length)
|
| - error (_("invalid dwarf2 offset %u"), offset);
|
| - gdb_assert (offset < this_cu->offset + this_cu->length);
|
| + && offset.sect_off >= this_cu->offset.sect_off + this_cu->length)
|
| + error (_("invalid dwarf2 offset %u"), offset.sect_off);
|
| + gdb_assert (offset.sect_off < this_cu->offset.sect_off + this_cu->length);
|
| return this_cu;
|
| }
|
| }
|
|
|
| -/* Locate the compilation unit from OBJFILE which is located at exactly
|
| - OFFSET. Raises an error on failure. */
|
| -
|
| -static struct dwarf2_per_cu_data *
|
| -dwarf2_find_comp_unit (unsigned int offset, struct objfile *objfile)
|
| -{
|
| - struct dwarf2_per_cu_data *this_cu;
|
| -
|
| - this_cu = dwarf2_find_containing_comp_unit (offset, objfile);
|
| - if (this_cu->offset != offset)
|
| - error (_("no compilation unit with offset %u."), offset);
|
| - return this_cu;
|
| -}
|
| -
|
| -/* Initialize dwarf2_cu CU for OBJFILE in a pre-allocated space. */
|
| +/* Initialize dwarf2_cu CU, owned by PER_CU. */
|
|
|
| static void
|
| -init_one_comp_unit (struct dwarf2_cu *cu, struct objfile *objfile)
|
| +init_one_comp_unit (struct dwarf2_cu *cu, struct dwarf2_per_cu_data *per_cu)
|
| {
|
| memset (cu, 0, sizeof (*cu));
|
| - cu->objfile = objfile;
|
| + per_cu->cu = cu;
|
| + cu->per_cu = per_cu;
|
| + cu->objfile = per_cu->objfile;
|
| obstack_init (&cu->comp_unit_obstack);
|
| }
|
|
|
| /* Initialize basic fields of dwarf_cu CU according to DIE COMP_UNIT_DIE. */
|
|
|
| static void
|
| -prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die)
|
| +prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die,
|
| + enum language pretend_language)
|
| {
|
| struct attribute *attr;
|
|
|
| @@ -15983,9 +17944,13 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die)
|
| set_cu_language (DW_UNSND (attr), cu);
|
| else
|
| {
|
| - cu->language = language_minimal;
|
| + cu->language = pretend_language;
|
| cu->language_defn = language_def (cu->language);
|
| }
|
| +
|
| + attr = dwarf2_attr (comp_unit_die, DW_AT_producer, cu);
|
| + if (attr)
|
| + cu->producer = DW_STRING (attr);
|
| }
|
|
|
| /* Release one cached compilation unit, CU. We unlink it from the tree
|
| @@ -15995,12 +17960,12 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die)
|
| cleanup routine. */
|
|
|
| static void
|
| -free_one_comp_unit (void *data)
|
| +free_heap_comp_unit (void *data)
|
| {
|
| struct dwarf2_cu *cu = data;
|
|
|
| - if (cu->per_cu != NULL)
|
| - cu->per_cu->cu = NULL;
|
| + gdb_assert (cu->per_cu != NULL);
|
| + cu->per_cu->cu = NULL;
|
| cu->per_cu = NULL;
|
|
|
| obstack_free (&cu->comp_unit_obstack, NULL);
|
| @@ -16010,30 +17975,19 @@ free_one_comp_unit (void *data)
|
|
|
| /* This cleanup function is passed the address of a dwarf2_cu on the stack
|
| when we're finished with it. We can't free the pointer itself, but be
|
| - sure to unlink it from the cache. Also release any associated storage
|
| - and perform cache maintenance.
|
| -
|
| - Only used during partial symbol parsing. */
|
| + sure to unlink it from the cache. Also release any associated storage. */
|
|
|
| static void
|
| free_stack_comp_unit (void *data)
|
| {
|
| struct dwarf2_cu *cu = data;
|
|
|
| + gdb_assert (cu->per_cu != NULL);
|
| + cu->per_cu->cu = NULL;
|
| + cu->per_cu = NULL;
|
| +
|
| obstack_free (&cu->comp_unit_obstack, NULL);
|
| cu->partial_dies = NULL;
|
| -
|
| - if (cu->per_cu != NULL)
|
| - {
|
| - /* This compilation unit is on the stack in our caller, so we
|
| - should not xfree it. Just unlink it. */
|
| - cu->per_cu->cu = NULL;
|
| - cu->per_cu = NULL;
|
| -
|
| - /* If we had a per-cu pointer, then we may have other compilation
|
| - units loaded, so age them now. */
|
| - age_cached_comp_units ();
|
| - }
|
| }
|
|
|
| /* Free all cached compilation units. */
|
| @@ -16051,7 +18005,7 @@ free_cached_comp_units (void *data)
|
|
|
| next_cu = per_cu->cu->read_in_chain;
|
|
|
| - free_one_comp_unit (per_cu->cu);
|
| + free_heap_comp_unit (per_cu->cu);
|
| *last_chain = next_cu;
|
|
|
| per_cu = next_cu;
|
| @@ -16086,7 +18040,7 @@ age_cached_comp_units (void)
|
|
|
| if (!per_cu->cu->mark)
|
| {
|
| - free_one_comp_unit (per_cu->cu);
|
| + free_heap_comp_unit (per_cu->cu);
|
| *last_chain = next_cu;
|
| }
|
| else
|
| @@ -16099,7 +18053,7 @@ age_cached_comp_units (void)
|
| /* Remove a single compilation unit from the cache. */
|
|
|
| static void
|
| -free_one_cached_comp_unit (void *target_cu)
|
| +free_one_cached_comp_unit (struct dwarf2_per_cu_data *target_per_cu)
|
| {
|
| struct dwarf2_per_cu_data *per_cu, **last_chain;
|
|
|
| @@ -16111,9 +18065,10 @@ free_one_cached_comp_unit (void *target_cu)
|
|
|
| next_cu = per_cu->cu->read_in_chain;
|
|
|
| - if (per_cu->cu == target_cu)
|
| + if (per_cu == target_per_cu)
|
| {
|
| - free_one_comp_unit (per_cu->cu);
|
| + free_heap_comp_unit (per_cu->cu);
|
| + per_cu->cu = NULL;
|
| *last_chain = next_cu;
|
| break;
|
| }
|
| @@ -16143,35 +18098,45 @@ dwarf2_free_objfile (struct objfile *objfile)
|
| /* Everything else should be on the objfile obstack. */
|
| }
|
|
|
| -/* A pair of DIE offset and GDB type pointer. We store these
|
| - in a hash table separate from the DIEs, and preserve them
|
| - when the DIEs are flushed out of cache. */
|
| +/* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer.
|
| + We store these in a hash table separate from the DIEs, and preserve them
|
| + when the DIEs are flushed out of cache.
|
| +
|
| + 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. */
|
|
|
| -struct dwarf2_offset_and_type
|
| +struct dwarf2_per_cu_offset_and_type
|
| {
|
| - unsigned int offset;
|
| + const struct dwarf2_per_cu_data *per_cu;
|
| + sect_offset offset;
|
| struct type *type;
|
| };
|
|
|
| -/* Hash function for a dwarf2_offset_and_type. */
|
| +/* Hash function for a dwarf2_per_cu_offset_and_type. */
|
|
|
| static hashval_t
|
| -offset_and_type_hash (const void *item)
|
| +per_cu_offset_and_type_hash (const void *item)
|
| {
|
| - const struct dwarf2_offset_and_type *ofs = item;
|
| + const struct dwarf2_per_cu_offset_and_type *ofs = item;
|
|
|
| - return ofs->offset;
|
| + return (uintptr_t) ofs->per_cu + ofs->offset.sect_off;
|
| }
|
|
|
| -/* Equality function for a dwarf2_offset_and_type. */
|
| +/* Equality function for a dwarf2_per_cu_offset_and_type. */
|
|
|
| static int
|
| -offset_and_type_eq (const void *item_lhs, const void *item_rhs)
|
| +per_cu_offset_and_type_eq (const void *item_lhs, const void *item_rhs)
|
| {
|
| - const struct dwarf2_offset_and_type *ofs_lhs = item_lhs;
|
| - const struct dwarf2_offset_and_type *ofs_rhs = item_rhs;
|
| + const struct dwarf2_per_cu_offset_and_type *ofs_lhs = item_lhs;
|
| + const struct dwarf2_per_cu_offset_and_type *ofs_rhs = item_rhs;
|
|
|
| - return ofs_lhs->offset == ofs_rhs->offset;
|
| + return (ofs_lhs->per_cu == ofs_rhs->per_cu
|
| + && ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off);
|
| }
|
|
|
| /* Set the type associated with DIE to TYPE. Save it in CU's hash
|
| @@ -16195,9 +18160,8 @@ offset_and_type_eq (const void *item_lhs, const void *item_rhs)
|
| static struct type *
|
| set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
|
| {
|
| - struct dwarf2_offset_and_type **slot, ofs;
|
| + struct dwarf2_per_cu_offset_and_type **slot, ofs;
|
| struct objfile *objfile = cu->objfile;
|
| - htab_t *type_hash_ptr;
|
|
|
| /* For Ada types, make sure that the gnat-specific data is always
|
| initialized (if not already set). There are a few types where
|
| @@ -16212,55 +18176,47 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
|
| && !HAVE_GNAT_AUX_INFO (type))
|
| INIT_GNAT_SPECIFIC (type);
|
|
|
| - if (cu->per_cu->debug_types_section)
|
| - type_hash_ptr = &dwarf2_per_objfile->debug_types_type_hash;
|
| - else
|
| - type_hash_ptr = &dwarf2_per_objfile->debug_info_type_hash;
|
| -
|
| - if (*type_hash_ptr == NULL)
|
| + if (dwarf2_per_objfile->die_type_hash == NULL)
|
| {
|
| - *type_hash_ptr
|
| - = htab_create_alloc_ex (127,
|
| - offset_and_type_hash,
|
| - offset_and_type_eq,
|
| - NULL,
|
| - &objfile->objfile_obstack,
|
| - hashtab_obstack_allocate,
|
| - dummy_obstack_deallocate);
|
| + dwarf2_per_objfile->die_type_hash =
|
| + htab_create_alloc_ex (127,
|
| + per_cu_offset_and_type_hash,
|
| + per_cu_offset_and_type_eq,
|
| + NULL,
|
| + &objfile->objfile_obstack,
|
| + hashtab_obstack_allocate,
|
| + dummy_obstack_deallocate);
|
| }
|
|
|
| + ofs.per_cu = cu->per_cu;
|
| ofs.offset = die->offset;
|
| ofs.type = type;
|
| - slot = (struct dwarf2_offset_and_type **)
|
| - htab_find_slot_with_hash (*type_hash_ptr, &ofs, ofs.offset, INSERT);
|
| + slot = (struct dwarf2_per_cu_offset_and_type **)
|
| + htab_find_slot (dwarf2_per_objfile->die_type_hash, &ofs, INSERT);
|
| if (*slot)
|
| complaint (&symfile_complaints,
|
| _("A problem internal to GDB: DIE 0x%x has type already set"),
|
| - die->offset);
|
| + die->offset.sect_off);
|
| *slot = obstack_alloc (&objfile->objfile_obstack, sizeof (**slot));
|
| **slot = ofs;
|
| return type;
|
| }
|
|
|
| -/* Look up the type for the die at DIE_OFFSET in the appropriate type_hash
|
| +/* 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. */
|
|
|
| static struct type *
|
| -get_die_type_at_offset (unsigned int offset,
|
| +get_die_type_at_offset (sect_offset offset,
|
| struct dwarf2_per_cu_data *per_cu)
|
| {
|
| - struct dwarf2_offset_and_type *slot, ofs;
|
| - htab_t type_hash;
|
| + struct dwarf2_per_cu_offset_and_type *slot, ofs;
|
|
|
| - if (per_cu->debug_types_section)
|
| - type_hash = dwarf2_per_objfile->debug_types_type_hash;
|
| - else
|
| - type_hash = dwarf2_per_objfile->debug_info_type_hash;
|
| - if (type_hash == NULL)
|
| + if (dwarf2_per_objfile->die_type_hash == NULL)
|
| return NULL;
|
|
|
| + ofs.per_cu = per_cu;
|
| ofs.offset = offset;
|
| - slot = htab_find_with_hash (type_hash, &ofs, ofs.offset);
|
| + slot = htab_find (dwarf2_per_objfile->die_type_hash, &ofs);
|
| if (slot)
|
| return slot->type;
|
| else
|
| @@ -16354,7 +18310,7 @@ partial_die_hash (const void *item)
|
| {
|
| const struct partial_die_info *part_die = item;
|
|
|
| - return part_die->offset;
|
| + return part_die->offset.sect_off;
|
| }
|
|
|
| /* Trivial comparison function for partial_die_info structures: two DIEs
|
| @@ -16366,7 +18322,7 @@ partial_die_eq (const void *item_lhs, const void *item_rhs)
|
| const struct partial_die_info *part_die_lhs = item_lhs;
|
| const struct partial_die_info *part_die_rhs = item_rhs;
|
|
|
| - return part_die_lhs->offset == part_die_rhs->offset;
|
| + return part_die_lhs->offset.sect_off == part_die_rhs->offset.sect_off;
|
| }
|
|
|
| static struct cmd_list_element *set_dwarf2_cmdlist;
|
| @@ -16422,6 +18378,7 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
|
| 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);
|
| @@ -16431,7 +18388,14 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
|
| ++ix)
|
| munmap_section_buffer (section);
|
|
|
| + for (ix = 0; ix < dwarf2_per_objfile->n_comp_units; ++ix)
|
| + VEC_free (dwarf2_per_cu_ptr,
|
| + dwarf2_per_objfile->all_comp_units[ix]->s.imported_symtabs);
|
| +
|
| VEC_free (dwarf2_section_info_def, data->types);
|
| +
|
| + if (data->dwo_files)
|
| + free_dwo_files (data->dwo_files, objfile);
|
| }
|
|
|
|
|
| @@ -16638,14 +18602,17 @@ hash_expand (struct mapped_symtab *symtab)
|
| xfree (old_entries);
|
| }
|
|
|
| -/* Add an entry to SYMTAB. NAME is the name of the symbol. CU_INDEX
|
| - is the index of the CU in which the symbol appears. */
|
| +/* Add an entry to SYMTAB. NAME is the name of the symbol.
|
| + CU_INDEX is the index of the CU in which the symbol appears.
|
| + IS_STATIC is one if the symbol is static, otherwise zero (global). */
|
|
|
| static void
|
| add_index_entry (struct mapped_symtab *symtab, const char *name,
|
| + int is_static, gdb_index_symbol_kind kind,
|
| offset_type cu_index)
|
| {
|
| struct symtab_index_entry **slot;
|
| + offset_type cu_index_and_attrs;
|
|
|
| ++symtab->n_elements;
|
| if (4 * symtab->n_elements / 3 >= symtab->size)
|
| @@ -16656,13 +18623,76 @@ add_index_entry (struct mapped_symtab *symtab, const char *name,
|
| {
|
| *slot = XNEW (struct symtab_index_entry);
|
| (*slot)->name = name;
|
| + /* index_offset is set later. */
|
| (*slot)->cu_indices = NULL;
|
| }
|
| - /* Don't push an index twice. Due to how we add entries we only
|
| - have to check the last one. */
|
| - if (VEC_empty (offset_type, (*slot)->cu_indices)
|
| - || VEC_last (offset_type, (*slot)->cu_indices) != cu_index)
|
| - VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index);
|
| +
|
| + cu_index_and_attrs = 0;
|
| + DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
|
| + DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
|
| + DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
|
| +
|
| + /* We don't want to record an index value twice as we want to avoid the
|
| + duplication.
|
| + We process all global symbols and then all static symbols
|
| + (which would allow us to avoid the duplication by only having to check
|
| + the last entry pushed), but a symbol could have multiple kinds in one CU.
|
| + To keep things simple we don't worry about the duplication here and
|
| + sort and uniqufy the list after we've processed all symbols. */
|
| + VEC_safe_push (offset_type, (*slot)->cu_indices, cu_index_and_attrs);
|
| +}
|
| +
|
| +/* qsort helper routine for uniquify_cu_indices. */
|
| +
|
| +static int
|
| +offset_type_compare (const void *ap, const void *bp)
|
| +{
|
| + offset_type a = *(offset_type *) ap;
|
| + offset_type b = *(offset_type *) bp;
|
| +
|
| + return (a > b) - (b > a);
|
| +}
|
| +
|
| +/* Sort and remove duplicates of all symbols' cu_indices lists. */
|
| +
|
| +static void
|
| +uniquify_cu_indices (struct mapped_symtab *symtab)
|
| +{
|
| + int i;
|
| +
|
| + for (i = 0; i < symtab->size; ++i)
|
| + {
|
| + struct symtab_index_entry *entry = symtab->data[i];
|
| +
|
| + if (entry
|
| + && entry->cu_indices != NULL)
|
| + {
|
| + unsigned int next_to_insert, next_to_check;
|
| + offset_type last_value;
|
| +
|
| + qsort (VEC_address (offset_type, entry->cu_indices),
|
| + VEC_length (offset_type, entry->cu_indices),
|
| + sizeof (offset_type), offset_type_compare);
|
| +
|
| + last_value = VEC_index (offset_type, entry->cu_indices, 0);
|
| + next_to_insert = 1;
|
| + for (next_to_check = 1;
|
| + next_to_check < VEC_length (offset_type, entry->cu_indices);
|
| + ++next_to_check)
|
| + {
|
| + if (VEC_index (offset_type, entry->cu_indices, next_to_check)
|
| + != last_value)
|
| + {
|
| + last_value = VEC_index (offset_type, entry->cu_indices,
|
| + next_to_check);
|
| + VEC_replace (offset_type, entry->cu_indices, next_to_insert,
|
| + last_value);
|
| + ++next_to_insert;
|
| + }
|
| + }
|
| + VEC_truncate (offset_type, entry->cu_indices, next_to_insert);
|
| + }
|
| + }
|
| }
|
|
|
| /* Add a vector of indices to the constant pool. */
|
| @@ -16821,8 +18851,6 @@ add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj)
|
| {
|
| struct addrmap_index_data *data = datap;
|
| struct partial_symtab *pst = obj;
|
| - offset_type cu_index;
|
| - void **slot;
|
|
|
| if (data->previous_valid)
|
| add_address_entry (data->objfile, data->addr_obstack,
|
| @@ -16878,6 +18906,44 @@ write_address_map (struct objfile *objfile, struct obstack *obstack,
|
| addrmap_index_data.previous_cu_index);
|
| }
|
|
|
| +/* Return the symbol kind of PSYM. */
|
| +
|
| +static gdb_index_symbol_kind
|
| +symbol_kind (struct partial_symbol *psym)
|
| +{
|
| + domain_enum domain = PSYMBOL_DOMAIN (psym);
|
| + enum address_class aclass = PSYMBOL_CLASS (psym);
|
| +
|
| + switch (domain)
|
| + {
|
| + case VAR_DOMAIN:
|
| + switch (aclass)
|
| + {
|
| + case LOC_BLOCK:
|
| + return GDB_INDEX_SYMBOL_KIND_FUNCTION;
|
| + case LOC_TYPEDEF:
|
| + return GDB_INDEX_SYMBOL_KIND_TYPE;
|
| + case LOC_COMPUTED:
|
| + case LOC_CONST_BYTES:
|
| + case LOC_OPTIMIZED_OUT:
|
| + case LOC_STATIC:
|
| + return GDB_INDEX_SYMBOL_KIND_VARIABLE;
|
| + case LOC_CONST:
|
| + /* Note: It's currently impossible to recognize psyms as enum values
|
| + short of reading the type info. For now punt. */
|
| + return GDB_INDEX_SYMBOL_KIND_VARIABLE;
|
| + default:
|
| + /* There are other LOC_FOO values that one might want to classify
|
| + as variables, but dwarf2read.c doesn't currently use them. */
|
| + return GDB_INDEX_SYMBOL_KIND_OTHER;
|
| + }
|
| + case STRUCT_DOMAIN:
|
| + return GDB_INDEX_SYMBOL_KIND_TYPE;
|
| + default:
|
| + return GDB_INDEX_SYMBOL_KIND_OTHER;
|
| + }
|
| +}
|
| +
|
| /* Add a list of partial symbols to SYMTAB. */
|
|
|
| static void
|
| @@ -16890,29 +18956,21 @@ write_psymbols (struct mapped_symtab *symtab,
|
| {
|
| for (; count-- > 0; ++psymp)
|
| {
|
| - void **slot, *lookup;
|
| + struct partial_symbol *psym = *psymp;
|
| + void **slot;
|
|
|
| - if (SYMBOL_LANGUAGE (*psymp) == language_ada)
|
| + if (SYMBOL_LANGUAGE (psym) == language_ada)
|
| error (_("Ada is not currently supported by the index"));
|
|
|
| - /* We only want to add a given psymbol once. However, we also
|
| - want to account for whether it is global or static. So, we
|
| - may add it twice, using slightly different values. */
|
| - if (is_static)
|
| - {
|
| - uintptr_t val = 1 | (uintptr_t) *psymp;
|
| -
|
| - lookup = (void *) val;
|
| - }
|
| - else
|
| - lookup = *psymp;
|
| -
|
| /* Only add a given psymbol once. */
|
| - slot = htab_find_slot (psyms_seen, lookup, INSERT);
|
| + slot = htab_find_slot (psyms_seen, psym, INSERT);
|
| if (!*slot)
|
| {
|
| - *slot = lookup;
|
| - add_index_entry (symtab, SYMBOL_NATURAL_NAME (*psymp), cu_index);
|
| + gdb_index_symbol_kind kind = symbol_kind (psym);
|
| +
|
| + *slot = psym;
|
| + add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
|
| + is_static, kind, cu_index);
|
| }
|
| }
|
| }
|
| @@ -16974,9 +19032,11 @@ write_one_signatured_type (void **slot, void *d)
|
| psymtab->n_static_syms, info->cu_index,
|
| 1);
|
|
|
| - store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->per_cu.offset);
|
| + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
|
| + entry->per_cu.offset.sect_off);
|
| obstack_grow (info->types_list, val, 8);
|
| - store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->type_offset);
|
| + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
|
| + entry->type_offset_in_tu.cu_off);
|
| obstack_grow (info->types_list, val, 8);
|
| store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, entry->signature);
|
| obstack_grow (info->types_list, val, 8);
|
| @@ -16986,6 +19046,35 @@ write_one_signatured_type (void **slot, void *d)
|
| return 1;
|
| }
|
|
|
| +/* Recurse into all "included" dependencies and write their symbols as
|
| + if they appeared in this psymtab. */
|
| +
|
| +static void
|
| +recursively_write_psymbols (struct objfile *objfile,
|
| + struct partial_symtab *psymtab,
|
| + struct mapped_symtab *symtab,
|
| + htab_t psyms_seen,
|
| + offset_type cu_index)
|
| +{
|
| + int i;
|
| +
|
| + for (i = 0; i < psymtab->number_of_dependencies; ++i)
|
| + if (psymtab->dependencies[i]->user != NULL)
|
| + recursively_write_psymbols (objfile, psymtab->dependencies[i],
|
| + symtab, psyms_seen, cu_index);
|
| +
|
| + write_psymbols (symtab,
|
| + psyms_seen,
|
| + objfile->global_psymbols.list + psymtab->globals_offset,
|
| + psymtab->n_global_syms, cu_index,
|
| + 0);
|
| + write_psymbols (symtab,
|
| + psyms_seen,
|
| + objfile->static_psymbols.list + psymtab->statics_offset,
|
| + psymtab->n_static_syms, cu_index,
|
| + 1);
|
| +}
|
| +
|
| /* Create an index file for OBJFILE in the directory DIR. */
|
|
|
| static void
|
| @@ -17000,7 +19089,6 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| struct mapped_symtab *symtab;
|
| offset_type val, size_of_contents, total_len;
|
| struct stat st;
|
| - char buf[8];
|
| htab_t psyms_seen;
|
| htab_t cu_index_htab;
|
| struct psymtab_cu_index_map *psymtab_cu_index_map;
|
| @@ -17070,16 +19158,8 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| struct psymtab_cu_index_map *map;
|
| void **slot;
|
|
|
| - write_psymbols (symtab,
|
| - psyms_seen,
|
| - objfile->global_psymbols.list + psymtab->globals_offset,
|
| - psymtab->n_global_syms, i,
|
| - 0);
|
| - write_psymbols (symtab,
|
| - psyms_seen,
|
| - objfile->static_psymbols.list + psymtab->statics_offset,
|
| - psymtab->n_static_syms, i,
|
| - 1);
|
| + if (psymtab->user == NULL)
|
| + recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, i);
|
|
|
| map = &psymtab_cu_index_map[i];
|
| map->psymtab = psymtab;
|
| @@ -17089,7 +19169,8 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| gdb_assert (*slot == NULL);
|
| *slot = map;
|
|
|
| - store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->offset);
|
| + store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE,
|
| + per_cu->offset.sect_off);
|
| obstack_grow (&cu_list, val, 8);
|
| store_unsigned_integer (val, 8, BFD_ENDIAN_LITTLE, per_cu->length);
|
| obstack_grow (&cu_list, val, 8);
|
| @@ -17112,6 +19193,10 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| write_one_signatured_type, &sig_data);
|
| }
|
|
|
| + /* Now that we've processed all symbols we can shrink their cu_indices
|
| + lists. */
|
| + uniquify_cu_indices (symtab);
|
| +
|
| obstack_init (&constant_pool);
|
| make_cleanup_obstack_free (&constant_pool);
|
| obstack_init (&symtab_obstack);
|
| @@ -17124,7 +19209,7 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir)
|
| total_len = size_of_contents;
|
|
|
| /* The version number. */
|
| - val = MAYBE_SWAP (5);
|
| + val = MAYBE_SWAP (7);
|
| obstack_grow (&contents, &val, sizeof (val));
|
|
|
| /* The offset of the CU list from the start of the file. */
|
| @@ -17277,6 +19362,15 @@ conversational style, when possible."),
|
| &set_dwarf2_cmdlist,
|
| &show_dwarf2_cmdlist);
|
|
|
| + add_setshow_boolean_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."),
|
| + NULL,
|
| + NULL,
|
| + &setdebuglist, &showdebuglist);
|
| +
|
| add_setshow_zinteger_cmd ("dwarf2-die", no_class, &dwarf2_die_debug, _("\
|
| Set debugging of the dwarf2 DIE reader."), _("\
|
| Show debugging of the dwarf2 DIE reader."), _("\
|
| @@ -17294,6 +19388,18 @@ the demangler."),
|
| NULL, show_check_physname,
|
| &setdebuglist, &showdebuglist);
|
|
|
| + add_setshow_boolean_cmd ("use-deprecated-index-sections",
|
| + no_class, &use_deprecated_index_sections, _("\
|
| +Set whether to use deprecated gdb_index sections."), _("\
|
| +Show whether to use deprecated gdb_index sections."), _("\
|
| +When enabled, deprecated .gdb_index sections are used anyway.\n\
|
| +Normally they are ignored either because of a missing feature or\n\
|
| +performance issue.\n\
|
| +Warning: This option must be enabled before gdb reads the file."),
|
| + NULL,
|
| + NULL,
|
| + &setlist, &showlist);
|
| +
|
| c = add_cmd ("gdb-index", class_files, save_gdb_index_command,
|
| _("\
|
| Save a gdb-index file.\n\
|
|
|