X-Git-Url: https://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fdwarf2read.c;h=a123ea7024920683135dabc3a38efa2ad4ca22fd;hb=26e53f3eace35cabeec4559d417df99a48f6477a;hp=24a4022c4a7cff6877b99e20e6fc6719f1f239af;hpb=cc12ce380e8dab7e3cee8ecad29db6e9bb36a8fa;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 24a4022c4a..a123ea7024 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1,6 +1,6 @@ /* DWARF 2 debugging format support for GDB. - Copyright (C) 1994-2015 Free Software Foundation, Inc. + Copyright (C) 1994-2017 Free Software Foundation, Inc. Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology, Inc. with support from Florida State University (under contract @@ -53,7 +53,6 @@ #include "block.h" #include "addrmap.h" #include "typeprint.h" -#include "jv-lang.h" #include "psympriv.h" #include #include "completer.h" @@ -69,9 +68,18 @@ #include "source.h" #include "filestuff.h" #include "build-id.h" - +#include "namespace.h" +#include "common/gdb_unlinker.h" +#include "common/function-view.h" +#include "common/gdb_optional.h" +#include "common/underlying.h" +#include "common/byte-vector.h" +#include "filename-seen-cache.h" #include #include +#include +#include +#include typedef struct symbol *symbolp; DEF_VEC_P (symbolp); @@ -123,7 +131,7 @@ struct dwarf2_section_info union { /* If this is a real section, the bfd section. */ - asection *asection; + asection *section; /* If this is a virtual section, pointer to the containing ("real") section. */ struct dwarf2_section_info *containing_section; @@ -138,7 +146,7 @@ struct dwarf2_section_info /* True if we have tried to read this section. */ char readin; /* True if this is a virtual section, False otherwise. - This specifies which of s.asection and s.containing_section to use. */ + This specifies which of s.section and s.containing_section to use. */ char is_virtual; }; @@ -216,82 +224,107 @@ struct tu_stats struct dwarf2_per_objfile { - struct dwarf2_section_info info; - struct dwarf2_section_info abbrev; - struct dwarf2_section_info line; - struct dwarf2_section_info loc; - struct dwarf2_section_info macinfo; - struct dwarf2_section_info macro; - struct dwarf2_section_info str; - struct dwarf2_section_info ranges; - struct dwarf2_section_info addr; - struct dwarf2_section_info frame; - struct dwarf2_section_info eh_frame; - struct dwarf2_section_info gdb_index; - - VEC (dwarf2_section_info_def) *types; + /* Construct a dwarf2_per_objfile for OBJFILE. NAMES points to the + dwarf2 section names, or is NULL if the standard ELF names are + used. */ + dwarf2_per_objfile (struct objfile *objfile, + const dwarf2_debug_sections *names); + + ~dwarf2_per_objfile (); + + /* Disable copy. */ + dwarf2_per_objfile (const dwarf2_per_objfile &) = delete; + void operator= (const dwarf2_per_objfile &) = delete; + + /* Free all cached compilation units. */ + void free_cached_comp_units (); +private: + /* This function is mapped across the sections and remembers the + offset and size of each of the debugging sections we are + interested in. */ + void locate_sections (bfd *abfd, asection *sectp, + const dwarf2_debug_sections &names); + +public: + dwarf2_section_info info {}; + dwarf2_section_info abbrev {}; + dwarf2_section_info line {}; + dwarf2_section_info loc {}; + dwarf2_section_info loclists {}; + dwarf2_section_info macinfo {}; + dwarf2_section_info macro {}; + dwarf2_section_info str {}; + dwarf2_section_info line_str {}; + dwarf2_section_info ranges {}; + dwarf2_section_info rnglists {}; + dwarf2_section_info addr {}; + dwarf2_section_info frame {}; + dwarf2_section_info eh_frame {}; + dwarf2_section_info gdb_index {}; + + VEC (dwarf2_section_info_def) *types = NULL; /* Back link. */ - struct objfile *objfile; + struct objfile *objfile = NULL; /* 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; + struct dwarf2_per_cu_data **all_comp_units = NULL; /* The number of compilation units in ALL_COMP_UNITS. */ - int n_comp_units; + int n_comp_units = 0; /* The number of .debug_types-related CUs. */ - int n_type_units; + int n_type_units = 0; /* The number of elements allocated in all_type_units. If there are skeleton-less TUs, we add them to all_type_units lazily. */ - int n_allocated_type_units; + int n_allocated_type_units = 0; /* The .debug_types-related CUs (TUs). This is stored in malloc space because we may realloc it. */ - struct signatured_type **all_type_units; + struct signatured_type **all_type_units = NULL; /* Table of struct type_unit_group objects. The hash key is the DW_AT_stmt_list value. */ - htab_t type_unit_groups; + 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; + htab_t signatured_types {}; /* Type unit statistics, to see how well the scaling improvements are doing. */ - struct tu_stats tu_stats; + struct tu_stats tu_stats {}; /* A chain of compilation units that are currently read in, so that they can be freed later. */ - struct dwarf2_per_cu_data *read_in_chain; + dwarf2_per_cu_data *read_in_chain = NULL; /* 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; + htab_t dwo_files {}; - /* Non-zero if we've check for whether there is a DWP file. */ - int dwp_checked; + /* True if we've checked for whether there is a DWP file. */ + bool dwp_checked = false; /* The DWP file if there is one, or NULL. */ - struct dwp_file *dwp_file; + struct dwp_file *dwp_file = NULL; /* The shared '.dwz' file, if one exists. This is used when the original data was compressed using 'dwz -m'. */ - struct dwz_file *dwz_file; + struct dwz_file *dwz_file = NULL; - /* A flag indicating wether this objfile has a section loaded at a + /* A flag indicating whether this objfile has a section loaded at a VMA of 0. */ - int has_section_at_zero; + bool has_section_at_zero = false; /* True if we are using the mapped index, or we are faking it for OBJF_READNOW's sake. */ - unsigned char using_index; + bool using_index = false; /* The mapped index, or NULL if .gdb_index is missing or not being used. */ - struct mapped_index *index_table; + mapped_index *index_table = NULL; /* When using index_table, this keeps track of all quick_file_names entries. TUs typically share line table entries with a CU, so we maintain a @@ -300,22 +333,26 @@ struct dwarf2_per_objfile sorted all the TUs into "type unit groups", grouped by their DW_AT_stmt_list value. Therefore the only sharing done here is with a CU and its associated TU group if there is one. */ - htab_t quick_file_names_table; + htab_t quick_file_names_table {}; /* Set during partial symbol reading, to prevent queueing of full symbols. */ - int reading_partial_symbols; + bool reading_partial_symbols = false; /* Table mapping type DIEs to their struct type *. This is NULL if not allocated yet. The mapping is done via (CU/TU + DIE offset) -> type. */ - htab_t die_type_hash; + htab_t die_type_hash {}; /* The CUs we recently read. */ - VEC (dwarf2_per_cu_ptr) *just_read_cus; + VEC (dwarf2_per_cu_ptr) *just_read_cus = NULL; /* Table containing line_header indexed by offset and offset_in_dwz. */ - htab_t line_header_hash; + htab_t line_header_hash {}; + + /* Table containing all filenames. This is an optional because the + table is lazily constructed on first access. */ + gdb::optional filenames_cache; }; static struct dwarf2_per_objfile *dwarf2_per_objfile; @@ -331,10 +368,13 @@ static const struct dwarf2_debug_sections dwarf2_elf_names = { ".debug_abbrev", ".zdebug_abbrev" }, { ".debug_line", ".zdebug_line" }, { ".debug_loc", ".zdebug_loc" }, + { ".debug_loclists", ".zdebug_loclists" }, { ".debug_macinfo", ".zdebug_macinfo" }, { ".debug_macro", ".zdebug_macro" }, { ".debug_str", ".zdebug_str" }, + { ".debug_line_str", ".zdebug_line_str" }, { ".debug_ranges", ".zdebug_ranges" }, + { ".debug_rnglists", ".zdebug_rnglists" }, { ".debug_types", ".zdebug_types" }, { ".debug_addr", ".zdebug_addr" }, { ".debug_frame", ".zdebug_frame" }, @@ -351,6 +391,7 @@ static const struct dwop_section_names struct dwarf2_section_names info_dwo; struct dwarf2_section_names line_dwo; struct dwarf2_section_names loc_dwo; + struct dwarf2_section_names loclists_dwo; struct dwarf2_section_names macinfo_dwo; struct dwarf2_section_names macro_dwo; struct dwarf2_section_names str_dwo; @@ -365,6 +406,7 @@ dwop_section_names = { ".debug_info.dwo", ".zdebug_info.dwo" }, { ".debug_line.dwo", ".zdebug_line.dwo" }, { ".debug_loc.dwo", ".zdebug_loc.dwo" }, + { ".debug_loclists.dwo", ".zdebug_loclists.dwo" }, { ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" }, { ".debug_macro.dwo", ".zdebug_macro.dwo" }, { ".debug_str.dwo", ".zdebug_str.dwo" }, @@ -384,7 +426,7 @@ struct comp_unit_head short version; unsigned char addr_size; unsigned char signed_addr_p; - sect_offset abbrev_offset; + sect_offset abbrev_sect_off; /* Size of file offsets; either 4 or 8. */ unsigned int offset_size; @@ -392,13 +434,22 @@ struct comp_unit_head /* Size of the length field; either 4 or 12. */ unsigned int initial_length_size; + enum dwarf_unit_type unit_type; + /* Offset to the first byte of this compilation unit header in the .debug_info section, for resolving relative reference dies. */ - sect_offset offset; + sect_offset sect_off; /* Offset to first die in this cu from the start of the cu. This will be the first byte following the compilation unit header. */ - cu_offset first_die_offset; + cu_offset first_die_cu_offset; + + /* 64-bit signature of this type unit - it is valid only for + UNIT_TYPE DW_UT_type. */ + ULONGEST signature; + + /* For types, offset in the type's DIE of the type defined by this TU. */ + cu_offset type_cu_offset_in_tu; }; /* Type used for delaying computation of method physnames. @@ -495,6 +546,12 @@ struct dwarf2_cu /* Header data from the line table, during full symbol processing. */ struct line_header *line_header; + /* Non-NULL if LINE_HEADER is owned by this DWARF_CU. Otherwise, + it's owned by dwarf2_per_objfile::line_header_hash. If non-NULL, + this is the DW_TAG_compile_unit die for this CU. We'll hold on + to the line header as long as this DIE is being processed. See + process_die_scope. */ + die_info *line_header_die_owner; /* A list of methods which need to have physnames computed after all type information has been read. */ @@ -567,9 +624,12 @@ struct dwarf2_per_cu_data 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; + sect_offset sect_off; unsigned int length; + /* DWARF standard version this data has been read from (such as 4 or 5). */ + short dwarf_version; + /* Flag indicating this compilation unit will be read in before any of the current compilation units are processed. */ unsigned int queued : 1; @@ -703,7 +763,7 @@ struct stmt_list_hash struct dwo_unit *dwo_unit; /* Offset in .debug_line or .debug_line.dwo. */ - sect_offset line_offset; + sect_offset line_sect_off; }; /* Each element of dwarf2_per_objfile->type_unit_groups is a pointer to @@ -754,6 +814,7 @@ struct dwo_sections struct dwarf2_section_info abbrev; struct dwarf2_section_info line; struct dwarf2_section_info loc; + struct dwarf2_section_info loclists; struct dwarf2_section_info macinfo; struct dwarf2_section_info macro; struct dwarf2_section_info str; @@ -778,8 +839,8 @@ struct dwo_unit /* The section this CU/TU lives in, in the DWO file. */ struct dwarf2_section_info *section; - /* Same as dwarf2_per_cu_data:{offset,length} but in the DWO section. */ - sect_offset offset; + /* Same as dwarf2_per_cu_data:{sect_off,length} but in the DWO section. */ + sect_offset sect_off; unsigned int length; /* For types, offset in the type's DIE of the type defined by this TU. */ @@ -826,12 +887,11 @@ struct dwo_file sections (for lack of a better name). */ struct dwo_sections sections; - /* The CU in the file. - We only support one because having more than one requires hacking the - dwo_name of each to match, which is highly unlikely to happen. - Doing this means all TUs can share comp_dir: We also assume that - DW_AT_comp_dir across all TUs in a DWO file will be identical. */ - struct dwo_unit *cu; + /* The CUs in the file. + Each element is a struct dwo_unit. Multiple CUs per DWO are supported as + an extension to handle LLVM's Link Time Optimization output (where + multiple source files may be compiled into a single object/dwo pair). */ + htab_t cus; /* Table of TUs in the file. Each element is a struct dwo_unit. */ @@ -1028,16 +1088,46 @@ typedef void (die_reader_func_ftype) (const struct die_reader_specs *reader, int has_children, void *data); +/* A 1-based directory index. This is a strong typedef to prevent + accidentally using a directory index as a 0-based index into an + array/vector. */ +enum class dir_index : unsigned int {}; + +/* Likewise, a 1-based file name index. */ +enum class file_name_index : unsigned int {}; + struct file_entry { - const char *name; - unsigned int dir_index; - unsigned int mod_time; - unsigned int length; - /* Non-zero if referenced by the Line Number Program. */ - int included_p; + file_entry () = default; + + file_entry (const char *name_, dir_index d_index_, + unsigned int mod_time_, unsigned int length_) + : name (name_), + d_index (d_index_), + mod_time (mod_time_), + length (length_) + {} + + /* Return the include directory at D_INDEX stored in LH. Returns + NULL if D_INDEX is out of bounds. */ + const char *include_dir (const line_header *lh) const; + + /* The file name. Note this is an observing pointer. The memory is + owned by debug_line_buffer. */ + const char *name {}; + + /* The directory index (1-based). */ + dir_index d_index {}; + + unsigned int mod_time {}; + + unsigned int length {}; + + /* True if referenced by the Line Number Program. */ + bool included_p {}; + /* The associated symbol table, if any. */ - struct symtab *symtab; + struct symtab *symtab {}; }; /* The line number information for a compilation unit (found in the @@ -1045,52 +1135,99 @@ struct file_entry which contains the following information. */ struct line_header { + line_header () + : offset_in_dwz {} + {} + + /* Add an entry to the include directory table. */ + void add_include_dir (const char *include_dir); + + /* Add an entry to the file name table. */ + void add_file_name (const char *name, dir_index d_index, + unsigned int mod_time, unsigned int length); + + /* Return the include dir at INDEX (1-based). Returns NULL if INDEX + is out of bounds. */ + const char *include_dir_at (dir_index index) const + { + /* Convert directory index number (1-based) to vector index + (0-based). */ + size_t vec_index = to_underlying (index) - 1; + + if (vec_index >= include_dirs.size ()) + return NULL; + return include_dirs[vec_index]; + } + + /* Return the file name at INDEX (1-based). Returns NULL if INDEX + is out of bounds. */ + file_entry *file_name_at (file_name_index index) + { + /* Convert file name index number (1-based) to vector index + (0-based). */ + size_t vec_index = to_underlying (index) - 1; + + if (vec_index >= file_names.size ()) + return NULL; + return &file_names[vec_index]; + } + + /* Const version of the above. */ + const file_entry *file_name_at (unsigned int index) const + { + if (index >= file_names.size ()) + return NULL; + return &file_names[index]; + } + /* Offset of line number information in .debug_line section. */ - sect_offset offset; + sect_offset sect_off {}; /* OFFSET is for struct dwz_file associated with dwarf2_per_objfile. */ - unsigned offset_in_dwz : 1; - - unsigned int total_length; - unsigned short version; - unsigned int header_length; - unsigned char minimum_instruction_length; - unsigned char maximum_ops_per_instruction; - unsigned char default_is_stmt; - int line_base; - unsigned char line_range; - unsigned char opcode_base; + unsigned offset_in_dwz : 1; /* Can't initialize bitfields in-class. */ + + unsigned int total_length {}; + unsigned short version {}; + unsigned int header_length {}; + unsigned char minimum_instruction_length {}; + unsigned char maximum_ops_per_instruction {}; + unsigned char default_is_stmt {}; + int line_base {}; + unsigned char line_range {}; + unsigned char opcode_base {}; /* standard_opcode_lengths[i] is the number of operands for the standard opcode whose value is i. This means that standard_opcode_lengths[0] is unused, and the last meaningful element is standard_opcode_lengths[opcode_base - 1]. */ - unsigned char *standard_opcode_lengths; + std::unique_ptr standard_opcode_lengths; - /* The include_directories table. NOTE! These strings are not - allocated with xmalloc; instead, they are pointers into - debug_line_buffer. If you try to free them, `free' will get - indigestion. */ - unsigned int num_include_dirs, include_dirs_size; - const char **include_dirs; + /* The include_directories table. Note these are observing + pointers. The memory is owned by debug_line_buffer. */ + std::vector include_dirs; - /* The file_names table. NOTE! These strings are not allocated - with xmalloc; instead, they are pointers into debug_line_buffer. - Don't try to free them directly. */ - unsigned int num_file_names, file_names_size; - struct file_entry *file_names; + /* The file_names table. */ + std::vector file_names; /* The start and end of the statement program following this header. These point into dwarf2_per_objfile->line_buffer. */ - const gdb_byte *statement_program_start, *statement_program_end; + const gdb_byte *statement_program_start {}, *statement_program_end {}; }; +typedef std::unique_ptr line_header_up; + +const char * +file_entry::include_dir (const line_header *lh) const +{ + return lh->include_dir_at (d_index); +} + /* When we construct a partial symbol table entry we only need this much information. */ struct partial_die_info { /* Offset of this DIE. */ - sect_offset offset; + sect_offset sect_off; /* DWARF-2 tag for this DIE. */ ENUM_BITFIELD(dwarf_tag) tag : 16; @@ -1104,6 +1241,9 @@ struct partial_die_info unsigned int has_pc_info : 1; unsigned int may_be_inlined : 1; + /* This DIE has been marked DW_AT_main_subprogram. */ + unsigned int main_subprogram : 1; + /* Flag set if the SCOPE field of this structure has been computed. */ unsigned int scope_set : 1; @@ -1145,7 +1285,7 @@ struct partial_die_info /* 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; + sect_offset sect_off; } d; /* If HAS_PC_INFO, the PC range associated with this DIE. */ @@ -1183,6 +1323,9 @@ struct attr_abbrev { ENUM_BITFIELD(dwarf_attribute) name : 16; ENUM_BITFIELD(dwarf_form) form : 16; + + /* It is valid only if FORM is DW_FORM_implicit_const. */ + LONGEST implicit_const; }; /* Size of abbrev_table.abbrev_hash_table. */ @@ -1194,7 +1337,7 @@ struct abbrev_table { /* Where the abbrev table came from. This is used as a sanity check when the table is used. */ - sect_offset offset; + sect_offset sect_off; /* Storage for the abbrev table. */ struct obstack abbrev_obstack; @@ -1249,7 +1392,7 @@ struct die_info unsigned int abbrev; /* Offset in .debug_info or .debug_types section. */ - sect_offset offset; + sect_offset sect_off; /* The dies in a compilation unit form an n-ary tree. PARENT points to this die's parent; CHILD points to the first child of @@ -1342,10 +1485,6 @@ struct field_info /* Set if the accesibility of one of the fields is not public. */ int non_public_fields; - /* Member function fields array, entries are allocated in the order they - are encountered in the object file. */ - struct nextfnfield *fnfields; - /* Member function fieldlist array, contains name of possibly overloaded member function, number of overloaded member functions and a pointer to the head of the member function field chain. */ @@ -1393,14 +1532,17 @@ static const char *get_section_name (const struct dwarf2_section_info *); static const char *get_section_file_name (const struct dwarf2_section_info *); -static void dwarf2_locate_sections (bfd *, asection *, void *); - static void dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu); static struct partial_symtab *create_partial_symtab (struct dwarf2_per_cu_data *per_cu, const char *name); +static void build_type_psymtabs_reader (const struct die_reader_specs *reader, + const gdb_byte *info_ptr, + struct die_info *type_unit_die, + int has_children, void *data); + static void dwarf2_build_psymtabs_hard (struct objfile *); static void scan_partial_symbols (struct partial_die_info *, @@ -1502,9 +1644,11 @@ static const char *read_indirect_string (bfd *, const gdb_byte *, const struct comp_unit_head *, unsigned int *); -static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST); +static const char *read_indirect_line_string (bfd *, const gdb_byte *, + const struct comp_unit_head *, + unsigned int *); -static ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *); +static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST); static LONGEST read_signed_leb128 (bfd *, const gdb_byte *, unsigned int *); @@ -1523,6 +1667,9 @@ static struct attribute *dwarf2_attr (struct die_info *, unsigned int, static struct attribute *dwarf2_attr_no_follow (struct die_info *, unsigned int); +static const char *dwarf2_string_attr (struct die_info *die, unsigned int name, + struct dwarf2_cu *cu); + static int dwarf2_flag_true_p (struct die_info *die, unsigned name, struct dwarf2_cu *cu); @@ -1531,10 +1678,8 @@ static int die_is_declaration (struct die_info *, struct dwarf2_cu *cu); static struct die_info *die_specification (struct die_info *die, struct dwarf2_cu **); -static void free_line_header (struct line_header *lh); - -static struct line_header *dwarf_decode_line_header (unsigned int offset, - struct dwarf2_cu *cu); +static line_header_up dwarf_decode_line_header (sect_offset sect_off, + struct dwarf2_cu *cu); static void dwarf_decode_lines (struct line_header *, const char *, struct dwarf2_cu *, struct partial_symtab *, @@ -1602,9 +1747,28 @@ static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu); static int dwarf2_ranges_read (unsigned, CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, struct partial_symtab *); -static int dwarf2_get_pc_bounds (struct die_info *, - CORE_ADDR *, CORE_ADDR *, struct dwarf2_cu *, - struct partial_symtab *); +/* How dwarf2_get_pc_bounds constructed its *LOWPC and *HIGHPC return + values. Keep the items ordered with increasing constraints compliance. */ +enum pc_bounds_kind +{ + /* No attribute DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges was found. */ + PC_BOUNDS_NOT_PRESENT, + + /* Some of the attributes DW_AT_low_pc, DW_AT_high_pc or DW_AT_ranges + were present but they do not form a valid range of PC addresses. */ + PC_BOUNDS_INVALID, + + /* Discontiguous range was found - that is DW_AT_ranges was found. */ + PC_BOUNDS_RANGES, + + /* Contiguous range was found - DW_AT_low_pc and DW_AT_high_pc were found. */ + PC_BOUNDS_HIGH_LOW, +}; + +static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *, + CORE_ADDR *, CORE_ADDR *, + struct dwarf2_cu *, + struct partial_symtab *); static void get_scope_pc_bounds (struct die_info *, CORE_ADDR *, CORE_ADDR *, @@ -1635,6 +1799,8 @@ static void read_namespace (struct die_info *die, struct dwarf2_cu *); static void read_module (struct die_info *die, struct dwarf2_cu *cu); +static struct using_direct **using_directives (enum language); + static void read_import_statement (struct die_info *die, struct dwarf2_cu *); static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu); @@ -1692,7 +1858,7 @@ static const char *dwarf_attr_name (unsigned int); static const char *dwarf_form_name (unsigned int); -static char *dwarf_bool_name (unsigned int); +static const char *dwarf_bool_name (unsigned int); static const char *dwarf_type_encoding_name (unsigned int); @@ -1737,6 +1903,10 @@ static void load_full_type_unit (struct dwarf2_per_cu_data *per_cu); static void read_signatured_type (struct signatured_type *); +static int attr_to_dynamic_prop (const struct attribute *attr, + struct die_info *die, struct dwarf2_cu *cu, + struct dynamic_prop *prop); + /* memory allocation interface */ static struct dwarf_block *dwarf_alloc_block (struct dwarf2_cu *); @@ -1773,7 +1943,7 @@ static hashval_t partial_die_hash (const void *item); static int partial_die_eq (const void *item_lhs, const void *item_rhs); static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit - (sect_offset offset, unsigned int offset_in_dwz, struct objfile *objfile); + (sect_offset sect_off, unsigned int offset_in_dwz, struct objfile *objfile); static void init_one_comp_unit (struct dwarf2_cu *cu, struct dwarf2_per_cu_data *per_cu); @@ -1825,18 +1995,39 @@ static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, static void process_queue (void); -static void find_file_and_directory (struct die_info *die, - struct dwarf2_cu *cu, - const char **name, const char **comp_dir); +/* The return type of find_file_and_directory. Note, the enclosed + string pointers are only valid while this object is valid. */ + +struct file_and_directory +{ + /* The filename. This is never NULL. */ + const char *name; + + /* The compilation directory. NULL if not known. If we needed to + compute a new string, this points to COMP_DIR_STORAGE, otherwise, + points directly to the DW_AT_comp_dir string attribute owned by + the obstack that owns the DIE. */ + const char *comp_dir; + + /* If we needed to build a new string for comp_dir, this is what + owns the storage. */ + std::string comp_dir_storage; +}; + +static file_and_directory find_file_and_directory (struct die_info *die, + struct dwarf2_cu *cu); static char *file_full_name (int file, struct line_header *lh, const char *comp_dir); +/* Expected enum dwarf_unit_type for read_comp_unit_head. */ +enum class rcuh_kind { COMPILE, TYPE }; + static const gdb_byte *read_and_check_comp_unit_head (struct comp_unit_head *header, struct dwarf2_section_info *section, struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr, - int is_debug_types_section); + rcuh_kind section_kind); static void init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table, @@ -1944,7 +2135,7 @@ dwarf2_invalid_attrib_class_complaint (const char *arg1, const char *arg2) static hashval_t line_header_hash (const struct line_header *ofs) { - return ofs->offset.sect_off ^ ofs->offset_in_dwz; + return to_underlying (ofs->sect_off) ^ ofs->offset_in_dwz; } /* Hash function for htab_create_alloc_ex for line_header_hash. */ @@ -1952,7 +2143,7 @@ line_header_hash (const struct line_header *ofs) static hashval_t line_header_hash_voidp (const void *item) { - const struct line_header *ofs = item; + const struct line_header *ofs = (const struct line_header *) item; return line_header_hash (ofs); } @@ -1962,10 +2153,10 @@ line_header_hash_voidp (const void *item) static int line_header_eq_voidp (const void *item_lhs, const void *item_rhs) { - const struct line_header *ofs_lhs = item_lhs; - const struct line_header *ofs_rhs = item_rhs; + const struct line_header *ofs_lhs = (const struct line_header *) item_lhs; + const struct line_header *ofs_rhs = (const struct line_header *) item_rhs; - return (ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off + return (ofs_lhs->sect_off == ofs_rhs->sect_off && ofs_lhs->offset_in_dwz == ofs_rhs->offset_in_dwz); } @@ -1988,7 +2179,7 @@ byte_swap (offset_type value) #define MAYBE_SWAP(V) byte_swap (V) #else -#define MAYBE_SWAP(V) (V) +#define MAYBE_SWAP(V) static_cast (V) #endif /* WORDS_BIGENDIAN */ /* Read the given attribute value as an address, taking the attribute's @@ -2024,6 +2215,52 @@ attr_value_as_address (struct attribute *attr) /* The suffix for an index file. */ #define INDEX_SUFFIX ".gdb-index" +/* See declaration. */ + +dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_, + const dwarf2_debug_sections *names) + : objfile (objfile_) +{ + if (names == NULL) + names = &dwarf2_elf_names; + + bfd *obfd = objfile->obfd; + + for (asection *sec = obfd->sections; sec != NULL; sec = sec->next) + locate_sections (obfd, sec, *names); +} + +dwarf2_per_objfile::~dwarf2_per_objfile () +{ + /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ + free_cached_comp_units (); + + if (quick_file_names_table) + htab_delete (quick_file_names_table); + + if (line_header_hash) + htab_delete (line_header_hash); + + /* Everything else should be on the objfile obstack. */ +} + +/* See declaration. */ + +void +dwarf2_per_objfile::free_cached_comp_units () +{ + dwarf2_per_cu_data *per_cu = read_in_chain; + dwarf2_per_cu_data **last_chain = &read_in_chain; + while (per_cu != NULL) + { + dwarf2_per_cu_data *next_cu = per_cu->cu->read_in_chain; + + free_heap_comp_unit (per_cu->cu); + *last_chain = next_cu; + per_cu = next_cu; + } +} + /* Try to locate the sections we need for DWARF 2 debugging information and return true if we have enough to do something. NAMES points to the dwarf2 section names, or is NULL if the standard @@ -2033,25 +2270,21 @@ int dwarf2_has_info (struct objfile *objfile, const struct dwarf2_debug_sections *names) { - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + dwarf2_per_objfile = ((struct dwarf2_per_objfile *) + objfile_data (objfile, dwarf2_objfile_data_key)); if (!dwarf2_per_objfile) { /* Initialize per-objfile state. */ struct dwarf2_per_objfile *data - = obstack_alloc (&objfile->objfile_obstack, sizeof (*data)); - - memset (data, 0, sizeof (*data)); - set_objfile_data (objfile, dwarf2_objfile_data_key, data); - dwarf2_per_objfile = data; + = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_objfile); - bfd_map_over_sections (objfile->obfd, dwarf2_locate_sections, - (void *) names); - dwarf2_per_objfile->objfile = objfile; + dwarf2_per_objfile = new (data) struct dwarf2_per_objfile (objfile, names); + set_objfile_data (objfile, dwarf2_objfile_data_key, dwarf2_per_objfile); } return (!dwarf2_per_objfile->info.is_virtual - && dwarf2_per_objfile->info.s.asection != NULL + && dwarf2_per_objfile->info.s.section != NULL && !dwarf2_per_objfile->abbrev.is_virtual - && dwarf2_per_objfile->abbrev.s.asection != NULL); + && dwarf2_per_objfile->abbrev.s.section != NULL); } /* Return the containing section of virtual section SECTION. */ @@ -2073,7 +2306,7 @@ get_section_bfd_owner (const struct dwarf2_section_info *section) section = get_containing_section (section); gdb_assert (!section->is_virtual); } - return section->s.asection->owner; + return section->s.section->owner; } /* Return the bfd section of SECTION. @@ -2087,7 +2320,7 @@ get_section_bfd_section (const struct dwarf2_section_info *section) section = get_containing_section (section); gdb_assert (!section->is_virtual); } - return section->s.asection; + return section->s.section; } /* Return the name of SECTION. */ @@ -2152,99 +2385,107 @@ section_is_p (const char *section_name, return 0; } -/* This function is mapped across the sections and remembers the - offset and size of each of the debugging sections we are interested - in. */ +/* See declaration. */ -static void -dwarf2_locate_sections (bfd *abfd, asection *sectp, void *vnames) +void +dwarf2_per_objfile::locate_sections (bfd *abfd, asection *sectp, + const dwarf2_debug_sections &names) { - const struct dwarf2_debug_sections *names; flagword aflag = bfd_get_section_flags (abfd, sectp); - if (vnames == NULL) - names = &dwarf2_elf_names; - else - names = (const struct dwarf2_debug_sections *) vnames; - if ((aflag & SEC_HAS_CONTENTS) == 0) { } - else if (section_is_p (sectp->name, &names->info)) + else if (section_is_p (sectp->name, &names.info)) + { + this->info.s.section = sectp; + this->info.size = bfd_get_section_size (sectp); + } + else if (section_is_p (sectp->name, &names.abbrev)) + { + this->abbrev.s.section = sectp; + this->abbrev.size = bfd_get_section_size (sectp); + } + else if (section_is_p (sectp->name, &names.line)) + { + this->line.s.section = sectp; + this->line.size = bfd_get_section_size (sectp); + } + else if (section_is_p (sectp->name, &names.loc)) { - dwarf2_per_objfile->info.s.asection = sectp; - dwarf2_per_objfile->info.size = bfd_get_section_size (sectp); + this->loc.s.section = sectp; + this->loc.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->abbrev)) + else if (section_is_p (sectp->name, &names.loclists)) { - dwarf2_per_objfile->abbrev.s.asection = sectp; - dwarf2_per_objfile->abbrev.size = bfd_get_section_size (sectp); + this->loclists.s.section = sectp; + this->loclists.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->line)) + else if (section_is_p (sectp->name, &names.macinfo)) { - dwarf2_per_objfile->line.s.asection = sectp; - dwarf2_per_objfile->line.size = bfd_get_section_size (sectp); + this->macinfo.s.section = sectp; + this->macinfo.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->loc)) + else if (section_is_p (sectp->name, &names.macro)) { - dwarf2_per_objfile->loc.s.asection = sectp; - dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp); + this->macro.s.section = sectp; + this->macro.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->macinfo)) + else if (section_is_p (sectp->name, &names.str)) { - dwarf2_per_objfile->macinfo.s.asection = sectp; - dwarf2_per_objfile->macinfo.size = bfd_get_section_size (sectp); + this->str.s.section = sectp; + this->str.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->macro)) + else if (section_is_p (sectp->name, &names.line_str)) { - dwarf2_per_objfile->macro.s.asection = sectp; - dwarf2_per_objfile->macro.size = bfd_get_section_size (sectp); + this->line_str.s.section = sectp; + this->line_str.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->str)) + else if (section_is_p (sectp->name, &names.addr)) { - dwarf2_per_objfile->str.s.asection = sectp; - dwarf2_per_objfile->str.size = bfd_get_section_size (sectp); + this->addr.s.section = sectp; + this->addr.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->addr)) + else if (section_is_p (sectp->name, &names.frame)) { - dwarf2_per_objfile->addr.s.asection = sectp; - dwarf2_per_objfile->addr.size = bfd_get_section_size (sectp); + this->frame.s.section = sectp; + this->frame.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->frame)) + else if (section_is_p (sectp->name, &names.eh_frame)) { - dwarf2_per_objfile->frame.s.asection = sectp; - dwarf2_per_objfile->frame.size = bfd_get_section_size (sectp); + this->eh_frame.s.section = sectp; + this->eh_frame.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->eh_frame)) + else if (section_is_p (sectp->name, &names.ranges)) { - dwarf2_per_objfile->eh_frame.s.asection = sectp; - dwarf2_per_objfile->eh_frame.size = bfd_get_section_size (sectp); + this->ranges.s.section = sectp; + this->ranges.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->ranges)) + else if (section_is_p (sectp->name, &names.rnglists)) { - dwarf2_per_objfile->ranges.s.asection = sectp; - dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp); + this->rnglists.s.section = sectp; + this->rnglists.size = bfd_get_section_size (sectp); } - else if (section_is_p (sectp->name, &names->types)) + else if (section_is_p (sectp->name, &names.types)) { struct dwarf2_section_info type_section; memset (&type_section, 0, sizeof (type_section)); - type_section.s.asection = sectp; + type_section.s.section = sectp; type_section.size = bfd_get_section_size (sectp); - VEC_safe_push (dwarf2_section_info_def, dwarf2_per_objfile->types, + VEC_safe_push (dwarf2_section_info_def, this->types, &type_section); } - else if (section_is_p (sectp->name, &names->gdb_index)) + else if (section_is_p (sectp->name, &names.gdb_index)) { - dwarf2_per_objfile->gdb_index.s.asection = sectp; - dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp); + this->gdb_index.s.section = sectp; + this->gdb_index.size = bfd_get_section_size (sectp); } if ((bfd_get_section_flags (abfd, sectp) & (SEC_LOAD | SEC_ALLOC)) && bfd_section_vma (abfd, sectp) == 0) - dwarf2_per_objfile->has_section_at_zero = 1; + this->has_section_at_zero = true; } /* A helper function that decides whether a section is empty, @@ -2255,7 +2496,7 @@ dwarf2_section_empty_p (const struct dwarf2_section_info *section) { if (section->is_virtual) return section->size == 0; - return section->s.asection == NULL || section->size == 0; + return section->s.section == NULL || section->size == 0; } /* Read the contents of the section INFO. @@ -2314,7 +2555,7 @@ dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info) return; } - buf = obstack_alloc (&objfile->objfile_obstack, info->size); + buf = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack, info->size); info->buffer = buf; /* When debugging .o files, we may need to apply relocations; see @@ -2366,7 +2607,8 @@ dwarf2_get_section_info (struct objfile *objfile, bfd_size_type *sizep) { struct dwarf2_per_objfile *data - = objfile_data (objfile, dwarf2_objfile_data_key); + = (struct dwarf2_per_objfile *) objfile_data (objfile, + dwarf2_objfile_data_key); struct dwarf2_section_info *info; /* We may see an objfile without any DWARF, in which case we just @@ -2402,38 +2644,38 @@ dwarf2_get_section_info (struct objfile *objfile, static void locate_dwz_sections (bfd *abfd, asection *sectp, void *arg) { - struct dwz_file *dwz_file = arg; + struct dwz_file *dwz_file = (struct dwz_file *) arg; /* Note that we only support the standard ELF names, because .dwz is ELF-only (at the time of writing). */ if (section_is_p (sectp->name, &dwarf2_elf_names.abbrev)) { - dwz_file->abbrev.s.asection = sectp; + dwz_file->abbrev.s.section = sectp; dwz_file->abbrev.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &dwarf2_elf_names.info)) { - dwz_file->info.s.asection = sectp; + dwz_file->info.s.section = sectp; dwz_file->info.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &dwarf2_elf_names.str)) { - dwz_file->str.s.asection = sectp; + dwz_file->str.s.section = sectp; dwz_file->str.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &dwarf2_elf_names.line)) { - dwz_file->line.s.asection = sectp; + dwz_file->line.s.section = sectp; dwz_file->line.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &dwarf2_elf_names.macro)) { - dwz_file->macro.s.asection = sectp; + dwz_file->macro.s.section = sectp; dwz_file->macro.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &dwarf2_elf_names.gdb_index)) { - dwz_file->gdb_index.s.asection = sectp; + dwz_file->gdb_index.s.section = sectp; dwz_file->gdb_index.size = bfd_get_section_size (sectp); } } @@ -2445,7 +2687,6 @@ locate_dwz_sections (bfd *abfd, asection *sectp, void *arg) static struct dwz_file * dwarf2_get_dwz_file (void) { - bfd *dwz_bfd; char *data; struct cleanup *cleanup; const char *filename; @@ -2473,30 +2714,24 @@ dwarf2_get_dwz_file (void) buildid_len = (size_t) buildid_len_arg; filename = (const char *) data; + + std::string abs_storage; if (!IS_ABSOLUTE_PATH (filename)) { - char *abs = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile)); - char *rel; - - make_cleanup (xfree, abs); - abs = ldirname (abs); - make_cleanup (xfree, abs); + gdb::unique_xmalloc_ptr abs + = gdb_realpath (objfile_name (dwarf2_per_objfile->objfile)); - rel = concat (abs, SLASH_STRING, filename, (char *) NULL); - make_cleanup (xfree, rel); - filename = rel; + abs_storage = ldirname (abs.get ()) + SLASH_STRING + filename; + filename = abs_storage.c_str (); } /* First try the file name given in the section. If that doesn't work, try to use the build-id instead. */ - dwz_bfd = gdb_bfd_open (filename, gnutarget, -1); + gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget, -1)); if (dwz_bfd != NULL) { - if (!build_id_verify (dwz_bfd, buildid_len, buildid)) - { - gdb_bfd_unref (dwz_bfd); - dwz_bfd = NULL; - } + if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid)) + dwz_bfd.release (); } if (dwz_bfd == NULL) @@ -2508,13 +2743,13 @@ dwarf2_get_dwz_file (void) result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack, struct dwz_file); - result->dwz_bfd = dwz_bfd; + result->dwz_bfd = dwz_bfd.release (); - bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result); + bfd_map_over_sections (result->dwz_bfd, locate_dwz_sections, result); do_cleanups (cleanup); - gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd); + gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, result->dwz_bfd); dwarf2_per_objfile->dwz_file = result; return result; } @@ -2575,7 +2810,7 @@ hash_stmt_list_entry (const struct stmt_list_hash *stmt_list_hash) 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; + v += to_underlying (stmt_list_hash->line_sect_off); return v; } @@ -2591,7 +2826,7 @@ eq_stmt_list_entry (const struct stmt_list_hash *lhs, && lhs->dwo_unit->dwo_file != rhs->dwo_unit->dwo_file) return 0; - return lhs->line_offset.sect_off == rhs->line_offset.sect_off; + return lhs->line_sect_off == rhs->line_sect_off; } /* Hash function for a quick_file_names. */ @@ -2599,7 +2834,8 @@ eq_stmt_list_entry (const struct stmt_list_hash *lhs, static hashval_t hash_file_name_entry (const void *e) { - const struct quick_file_names *file_data = e; + const struct quick_file_names *file_data + = (const struct quick_file_names *) e; return hash_stmt_list_entry (&file_data->hash); } @@ -2609,8 +2845,8 @@ hash_file_name_entry (const void *e) static int eq_file_name_entry (const void *a, const void *b) { - const struct quick_file_names *ea = a; - const struct quick_file_names *eb = b; + const struct quick_file_names *ea = (const struct quick_file_names *) a; + const struct quick_file_names *eb = (const struct quick_file_names *) b; return eq_stmt_list_entry (&ea->hash, &eb->hash); } @@ -2620,7 +2856,7 @@ eq_file_name_entry (const void *a, const void *b) static void delete_file_name_entry (void *e) { - struct quick_file_names *file_data = e; + struct quick_file_names *file_data = (struct quick_file_names *) e; int i; for (i = 0; i < file_data->num_file_names; ++i) @@ -2716,7 +2952,7 @@ dw2_instantiate_symtab (struct dwarf2_per_cu_data *per_cu) if (!per_cu->v.quick->compunit_symtab) { struct cleanup *back_to = make_cleanup (free_cached_comp_units, NULL); - increment_reading_symtab (); + scoped_restore decrementer = increment_reading_symtab (); dw2_do_instantiate_symtab (per_cu); process_cu_includes (); do_cleanups (back_to); @@ -2777,17 +3013,17 @@ create_cus_from_index_list (struct objfile *objfile, for (i = 0; i < n_elements; i += 2) { - struct dwarf2_per_cu_data *the_cu; - ULONGEST offset, length; - gdb_static_assert (sizeof (ULONGEST) >= 8); - offset = extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE); - length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); + + sect_offset sect_off + = (sect_offset) extract_unsigned_integer (cu_list, 8, BFD_ENDIAN_LITTLE); + ULONGEST length = extract_unsigned_integer (cu_list + 8, 8, BFD_ENDIAN_LITTLE); cu_list += 2 * 8; - the_cu = OBSTACK_ZALLOC (&objfile->objfile_obstack, - struct dwarf2_per_cu_data); - the_cu->offset.sect_off = offset; + dwarf2_per_cu_data *the_cu + = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwarf2_per_cu_data); + the_cu->sect_off = sect_off; the_cu->length = length; the_cu->objfile = objfile; the_cu->section = section; @@ -2809,10 +3045,9 @@ create_cus_from_index (struct objfile *objfile, struct dwz_file *dwz; dwarf2_per_objfile->n_comp_units = (cu_list_elements + dwz_elements) / 2; - dwarf2_per_objfile->all_comp_units - = obstack_alloc (&objfile->objfile_obstack, - dwarf2_per_objfile->n_comp_units - * sizeof (struct dwarf2_per_cu_data *)); + dwarf2_per_objfile->all_comp_units = + XOBNEWVEC (&objfile->objfile_obstack, struct dwarf2_per_cu_data *, + dwarf2_per_objfile->n_comp_units); create_cus_from_index_list (objfile, cu_list, cu_list_elements, &dwarf2_per_objfile->info, 0, 0); @@ -2839,32 +3074,34 @@ create_signatured_type_table_from_index (struct objfile *objfile, dwarf2_per_objfile->n_type_units = dwarf2_per_objfile->n_allocated_type_units = elements / 3; - dwarf2_per_objfile->all_type_units - = xmalloc (dwarf2_per_objfile->n_type_units - * sizeof (struct signatured_type *)); + dwarf2_per_objfile->all_type_units = + XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units); sig_types_hash = allocate_signatured_type_table (objfile); for (i = 0; i < elements; i += 3) { struct signatured_type *sig_type; - ULONGEST offset, type_offset_in_tu, signature; + ULONGEST signature; void **slot; + cu_offset type_offset_in_tu; gdb_static_assert (sizeof (ULONGEST) >= 8); - offset = extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); - type_offset_in_tu = extract_unsigned_integer (bytes + 8, 8, - BFD_ENDIAN_LITTLE); + sect_offset sect_off + = (sect_offset) extract_unsigned_integer (bytes, 8, BFD_ENDIAN_LITTLE); + type_offset_in_tu + = (cu_offset) extract_unsigned_integer (bytes + 8, 8, + BFD_ENDIAN_LITTLE); signature = extract_unsigned_integer (bytes + 16, 8, BFD_ENDIAN_LITTLE); bytes += 3 * 8; sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct signatured_type); sig_type->signature = signature; - sig_type->type_offset_in_tu.cu_off = type_offset_in_tu; + sig_type->type_offset_in_tu = type_offset_in_tu; sig_type->per_cu.is_debug_types = 1; sig_type->per_cu.section = section; - sig_type->per_cu.offset.sect_off = offset; + sig_type->per_cu.sect_off = sect_off; sig_type->per_cu.objfile = objfile; sig_type->per_cu.v.quick = OBSTACK_ZALLOC (&objfile->objfile_obstack, @@ -2887,13 +3124,11 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index) { struct gdbarch *gdbarch = get_objfile_arch (objfile); const gdb_byte *iter, *end; - struct obstack temp_obstack; struct addrmap *mutable_map; - struct cleanup *cleanup; CORE_ADDR baseaddr; - obstack_init (&temp_obstack); - cleanup = make_cleanup_obstack_free (&temp_obstack); + auto_obstack temp_obstack; + mutable_map = addrmap_create_mutable (&temp_obstack); iter = index->address_table; @@ -2934,7 +3169,6 @@ create_addrmap_from_index (struct objfile *objfile, struct mapped_index *index) objfile->psymtabs_addrmap = addrmap_create_fixed (mutable_map, &objfile->objfile_obstack); - do_cleanups (cleanup); } /* The hash function for strings in the mapped index. This is the same as @@ -2976,7 +3210,6 @@ find_slot_in_mapped_hash (struct mapped_index *index, const char *name, int (*cmp) (const char *, const char *); if (current_language->la_language == language_cplus - || current_language->la_language == language_java || current_language->la_language == language_fortran || current_language->la_language == language_d) { @@ -3220,7 +3453,7 @@ dwarf2_read_index (struct objfile *objfile) create_addrmap_from_index (objfile, &local_map); - map = obstack_alloc (&objfile->objfile_obstack, sizeof (struct mapped_index)); + map = XOBNEW (&objfile->objfile_obstack, struct mapped_index); *map = local_map; dwarf2_per_objfile->index_table = map; @@ -3237,7 +3470,8 @@ dwarf2_read_index (struct objfile *objfile) static void dw2_setup (struct objfile *objfile) { - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + dwarf2_per_objfile = ((struct dwarf2_per_objfile *) + objfile_data (objfile, dwarf2_objfile_data_key)); gdb_assert (dwarf2_per_objfile); } @@ -3254,13 +3488,10 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader, 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; int i; - const char *name, *comp_dir; void **slot; struct quick_file_names *qfn; - unsigned int line_offset; gdb_assert (! this_cu->is_debug_types); @@ -3273,26 +3504,27 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader, } lh_cu = this_cu; - lh = NULL; slot = NULL; - line_offset = 0; + + line_header_up lh; + sect_offset line_offset {}; attr = dwarf2_attr (comp_unit_die, DW_AT_stmt_list, cu); if (attr) { struct quick_file_names find_entry; - line_offset = DW_UNSND (attr); + line_offset = (sect_offset) DW_UNSND (attr); /* We may have already read in this line header (TU line header sharing). If we have we're done. */ find_entry.hash.dwo_unit = cu->dwo_unit; - find_entry.hash.line_offset.sect_off = line_offset; + find_entry.hash.line_sect_off = line_offset; slot = htab_find_slot (dwarf2_per_objfile->quick_file_names_table, &find_entry, INSERT); if (*slot != NULL) { - lh_cu->v.quick->file_names = *slot; + lh_cu->v.quick->file_names = (struct quick_file_names *) *slot; return; } @@ -3304,23 +3536,21 @@ dw2_get_file_names_reader (const struct die_reader_specs *reader, return; } - qfn = obstack_alloc (&objfile->objfile_obstack, sizeof (*qfn)); + qfn = XOBNEW (&objfile->objfile_obstack, struct quick_file_names); qfn->hash.dwo_unit = cu->dwo_unit; - qfn->hash.line_offset.sect_off = line_offset; + qfn->hash.line_sect_off = line_offset; gdb_assert (slot != NULL); *slot = qfn; - find_file_and_directory (comp_unit_die, cu, &name, &comp_dir); + file_and_directory fnd = find_file_and_directory (comp_unit_die, cu); - qfn->num_file_names = lh->num_file_names; - qfn->file_names = obstack_alloc (&objfile->objfile_obstack, - lh->num_file_names * sizeof (char *)); - for (i = 0; i < lh->num_file_names; ++i) - qfn->file_names[i] = file_full_name (i + 1, lh, comp_dir); + qfn->num_file_names = lh->file_names.size (); + qfn->file_names = + XOBNEWVEC (&objfile->objfile_obstack, const char *, lh->file_names.size ()); + for (i = 0; i < lh->file_names.size (); ++i) + qfn->file_names[i] = file_full_name (i + 1, lh.get (), fnd.comp_dir); qfn->real_names = NULL; - free_line_header (lh); - lh_cu->v.quick->file_names = qfn; } @@ -3360,7 +3590,7 @@ dw2_get_real_path (struct objfile *objfile, qfn->num_file_names, const char *); if (qfn->real_names[index] == NULL) - qfn->real_names[index] = gdb_realpath (qfn->file_names[index]); + qfn->real_names[index] = gdb_realpath (qfn->file_names[index]).release (); return qfn->real_names[index]; } @@ -3416,8 +3646,7 @@ static int dw2_map_expand_apply (struct objfile *objfile, struct dwarf2_per_cu_data *per_cu, const char *name, const char *real_path, - int (*callback) (struct symtab *, void *), - void *data) + gdb::function_view callback) { struct compunit_symtab *last_made = objfile->compunit_symtabs; @@ -3429,17 +3658,16 @@ dw2_map_expand_apply (struct objfile *objfile, all of them. */ dw2_instantiate_symtab (per_cu); - return iterate_over_some_symtabs (name, real_path, callback, data, - objfile->compunit_symtabs, last_made); + return iterate_over_some_symtabs (name, real_path, objfile->compunit_symtabs, + last_made, callback); } /* Implementation of the map_symtabs_matching_filename method. */ -static int -dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, - const char *real_path, - int (*callback) (struct symtab *, void *), - void *data) +static bool +dw2_map_symtabs_matching_filename + (struct objfile *objfile, const char *name, const char *real_path, + gdb::function_view callback) { int i; const char *name_basename = lbasename (name); @@ -3471,8 +3699,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, if (compare_filenames_for_search (this_name, name)) { if (dw2_map_expand_apply (objfile, per_cu, name, real_path, - callback, data)) - return 1; + callback)) + return true; continue; } @@ -3486,8 +3714,8 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, if (compare_filenames_for_search (this_real_name, name)) { if (dw2_map_expand_apply (objfile, per_cu, name, real_path, - callback, data)) - return 1; + callback)) + return true; continue; } @@ -3499,15 +3727,15 @@ dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name, && FILENAME_CMP (real_path, this_real_name) == 0) { if (dw2_map_expand_apply (objfile, per_cu, name, real_path, - callback, data)) - return 1; + callback)) + return true; continue; } } } } - return 0; + return false; } /* Struct used to manage iterating over all CUs looking for a symbol. */ @@ -3686,10 +3914,10 @@ dw2_lookup_symbol (struct objfile *objfile, int block_index, information (but NAME might contain it). */ if (sym != NULL - && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0) + && SYMBOL_MATCHES_SEARCH_NAME (sym, name)) return stab; if (with_opaque != NULL - && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0) + && SYMBOL_MATCHES_SEARCH_NAME (with_opaque, name)) stab_best = stab; /* Keep looking through other CUs. */ @@ -3845,11 +4073,10 @@ dw2_map_matching_symbols (struct objfile *objfile, static void dw2_expand_symtabs_matching (struct objfile *objfile, - expand_symtabs_file_matcher_ftype *file_matcher, - expand_symtabs_symbol_matcher_ftype *symbol_matcher, - expand_symtabs_exp_notify_ftype *expansion_notify, - enum search_domain kind, - void *data) + gdb::function_view file_matcher, + gdb::function_view symbol_matcher, + gdb::function_view expansion_notify, + enum search_domain kind) { int i; offset_type iter; @@ -3864,17 +4091,12 @@ dw2_expand_symtabs_matching if (file_matcher != NULL) { - struct cleanup *cleanup; - htab_t visited_found, visited_not_found; - - 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); + htab_up visited_found (htab_create_alloc (10, htab_hash_pointer, + htab_eq_pointer, + NULL, xcalloc, xfree)); + htab_up visited_not_found (htab_create_alloc (10, htab_hash_pointer, + htab_eq_pointer, + NULL, xcalloc, xfree)); /* The rule is CUs specify all the files, including those used by any TU, so there's no need to scan TUs here. */ @@ -3898,9 +4120,9 @@ dw2_expand_symtabs_matching if (file_data == NULL) continue; - if (htab_find (visited_not_found, file_data) != NULL) + if (htab_find (visited_not_found.get (), file_data) != NULL) continue; - else if (htab_find (visited_found, file_data) != NULL) + else if (htab_find (visited_found.get (), file_data) != NULL) { per_cu->v.quick->mark = 1; continue; @@ -3910,7 +4132,7 @@ dw2_expand_symtabs_matching { const char *this_real_name; - if (file_matcher (file_data->file_names[j], data, 0)) + if (file_matcher (file_data->file_names[j], false)) { per_cu->v.quick->mark = 1; break; @@ -3920,11 +4142,11 @@ dw2_expand_symtabs_matching files are involved, do a quick comparison of the basenames. */ if (!basenames_may_differ && !file_matcher (lbasename (file_data->file_names[j]), - data, 1)) + true)) continue; this_real_name = dw2_get_real_path (objfile, file_data, j); - if (file_matcher (this_real_name, data, 0)) + if (file_matcher (this_real_name, false)) { per_cu->v.quick->mark = 1; break; @@ -3932,13 +4154,11 @@ dw2_expand_symtabs_matching } slot = htab_find_slot (per_cu->v.quick->mark - ? visited_found - : visited_not_found, + ? visited_found.get () + : visited_not_found.get (), file_data, INSERT); *slot = file_data; } - - do_cleanups (cleanup); } for (iter = 0; iter < index->symbol_table_slots; ++iter) @@ -3955,7 +4175,7 @@ dw2_expand_symtabs_matching name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]); - if (! (*symbol_matcher) (name, data)) + if (!symbol_matcher (name)) continue; /* The name was matched, now expand corresponding CUs that were @@ -4033,8 +4253,7 @@ dw2_expand_symtabs_matching && symtab_was_null && per_cu->v.quick->compunit_symtab != NULL) { - expansion_notify (per_cu->v.quick->compunit_symtab, - data); + expansion_notify (per_cu->v.quick->compunit_symtab); } } } @@ -4084,7 +4303,8 @@ dw2_find_pc_sect_compunit_symtab (struct objfile *objfile, if (!objfile->psymtabs_addrmap) return NULL; - data = addrmap_find (objfile->psymtabs_addrmap, pc); + data = (struct dwarf2_per_cu_data *) addrmap_find (objfile->psymtabs_addrmap, + pc); if (!data) return NULL; @@ -4103,67 +4323,73 @@ static void 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); - /* The rule is CUs specify all the files, including those used by - any TU, so there's no need to scan TUs here. - We can ignore file names coming from already-expanded CUs. */ - - for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + if (!dwarf2_per_objfile->filenames_cache) { - struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i); + dwarf2_per_objfile->filenames_cache.emplace (); - if (per_cu->v.quick->compunit_symtab) - { - void **slot = htab_find_slot (visited, per_cu->v.quick->file_names, - INSERT); - - *slot = per_cu->v.quick->file_names; - } - } + htab_up visited (htab_create_alloc (10, + htab_hash_pointer, htab_eq_pointer, + NULL, xcalloc, xfree)); - for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) - { - int j; - struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); - struct quick_file_names *file_data; - void **slot; + /* The rule is CUs specify all the files, including those used + by any TU, so there's no need to scan TUs here. We can + ignore file names coming from already-expanded CUs. */ - /* We only need to look at symtabs not already expanded. */ - if (per_cu->v.quick->compunit_symtab) - continue; + for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + { + struct dwarf2_per_cu_data *per_cu = dw2_get_cutu (i); - file_data = dw2_get_file_names (per_cu); - if (file_data == NULL) - continue; + if (per_cu->v.quick->compunit_symtab) + { + void **slot = htab_find_slot (visited.get (), + per_cu->v.quick->file_names, + INSERT); - slot = htab_find_slot (visited, file_data, INSERT); - if (*slot) - { - /* Already visited. */ - continue; + *slot = per_cu->v.quick->file_names; + } } - *slot = file_data; - for (j = 0; j < file_data->num_file_names; ++j) + for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) { - const char *this_real_name; + int j; + struct dwarf2_per_cu_data *per_cu = dw2_get_cu (i); + struct quick_file_names *file_data; + void **slot; - if (need_fullname) - this_real_name = dw2_get_real_path (objfile, file_data, j); - else - this_real_name = NULL; - (*fun) (file_data->file_names[j], this_real_name, data); + /* We only need to look at symtabs not already expanded. */ + if (per_cu->v.quick->compunit_symtab) + continue; + + file_data = dw2_get_file_names (per_cu); + if (file_data == NULL) + continue; + + slot = htab_find_slot (visited.get (), file_data, INSERT); + if (*slot) + { + /* Already visited. */ + continue; + } + *slot = file_data; + + for (int j = 0; j < file_data->num_file_names; ++j) + { + const char *filename = file_data->file_names[j]; + dwarf2_per_objfile->filenames_cache->seen (filename); + } } } - do_cleanups (cleanup); + dwarf2_per_objfile->filenames_cache->traverse ([&] (const char *filename) + { + gdb::unique_xmalloc_ptr this_real_name; + + if (need_fullname) + this_real_name = gdb_realpath (filename); + (*fun) (filename, this_real_name.get (), data); + }); } static int @@ -4250,10 +4476,9 @@ dwarf2_build_psymtabs (struct objfile *objfile) /* This isn't really ideal: all the data we allocate on the objfile's obstack is still uselessly kept around. However, freeing it seems unsafe. */ - struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile); - + psymtab_discarder psymtabs (objfile); dwarf2_build_psymtabs_hard (objfile); - discard_cleanups (cleanups); + psymtabs.keep (); } CATCH (except, RETURN_MASK_ERROR) { @@ -4270,15 +4495,15 @@ get_cu_length (const struct comp_unit_head *header) return header->initial_length_size + header->length; } -/* Return TRUE if OFFSET is within CU_HEADER. */ +/* Return TRUE if SECT_OFF is within CU_HEADER. */ -static inline int -offset_in_cu_p (const struct comp_unit_head *cu_header, sect_offset offset) +static inline bool +offset_in_cu_p (const comp_unit_head *cu_header, sect_offset sect_off) { - sect_offset bottom = { cu_header->offset.sect_off }; - sect_offset top = { cu_header->offset.sect_off + get_cu_length (cu_header) }; + sect_offset bottom = cu_header->sect_off; + sect_offset top = cu_header->sect_off + get_cu_length (cu_header); - return (offset.sect_off >= bottom.sect_off && offset.sect_off < top.sect_off); + return sect_off >= bottom && sect_off < top; } /* Find the base address of the compilation unit for range lists and @@ -4313,15 +4538,20 @@ dwarf2_find_base_address (struct die_info *die, struct dwarf2_cu *cu) } /* Read in the comp unit header information from the debug_info at info_ptr. + Use rcuh_kind::COMPILE as the default type if not known by the caller. NOTE: This leaves members offset, first_die_offset to be filled in by the caller. */ static const gdb_byte * read_comp_unit_head (struct comp_unit_head *cu_header, - const gdb_byte *info_ptr, bfd *abfd) + const gdb_byte *info_ptr, + struct dwarf2_section_info *section, + rcuh_kind section_kind) { int signed_addr; unsigned int bytes_read; + const char *filename = get_section_file_name (section); + bfd *abfd = get_section_bfd_owner (section); cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read); cu_header->initial_length_size = bytes_read; @@ -4329,17 +4559,75 @@ 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.sect_off = read_offset (abfd, info_ptr, cu_header, - &bytes_read); + if (cu_header->version < 5) + switch (section_kind) + { + case rcuh_kind::COMPILE: + cu_header->unit_type = DW_UT_compile; + break; + case rcuh_kind::TYPE: + cu_header->unit_type = DW_UT_type; + break; + default: + internal_error (__FILE__, __LINE__, + _("read_comp_unit_head: invalid section_kind")); + } + else + { + cu_header->unit_type = static_cast + (read_1_byte (abfd, info_ptr)); + info_ptr += 1; + switch (cu_header->unit_type) + { + case DW_UT_compile: + if (section_kind != rcuh_kind::COMPILE) + error (_("Dwarf Error: wrong unit_type in compilation unit header " + "(is DW_UT_compile, should be DW_UT_type) [in module %s]"), + filename); + break; + case DW_UT_type: + section_kind = rcuh_kind::TYPE; + break; + default: + error (_("Dwarf Error: wrong unit_type in compilation unit header " + "(is %d, should be %d or %d) [in module %s]"), + cu_header->unit_type, DW_UT_compile, DW_UT_type, filename); + } + + cu_header->addr_size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + } + cu_header->abbrev_sect_off = (sect_offset) 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; + if (cu_header->version < 5) + { + cu_header->addr_size = read_1_byte (abfd, info_ptr); + info_ptr += 1; + } signed_addr = bfd_get_sign_extend_vma (abfd); if (signed_addr < 0) internal_error (__FILE__, __LINE__, _("read_comp_unit_head: dwarf from non elf file")); cu_header->signed_addr_p = signed_addr; + if (section_kind == rcuh_kind::TYPE) + { + LONGEST type_offset; + + cu_header->signature = read_8_bytes (abfd, info_ptr); + info_ptr += 8; + + type_offset = read_offset (abfd, info_ptr, cu_header, &bytes_read); + info_ptr += bytes_read; + cu_header->type_cu_offset_in_tu = (cu_offset) type_offset; + if (to_underlying (cu_header->type_cu_offset_in_tu) != type_offset) + error (_("Dwarf Error: Too big type_offset in compilation unit " + "header (is %s) [in module %s]"), plongest (type_offset), + filename); + } + return info_ptr; } @@ -4368,28 +4656,28 @@ error_check_comp_unit_head (struct comp_unit_head *header, struct dwarf2_section_info *section, struct dwarf2_section_info *abbrev_section) { - bfd *abfd = get_section_bfd_owner (section); const char *filename = get_section_file_name (section); - if (header->version != 2 && header->version != 3 && header->version != 4) + if (header->version < 2 || header->version > 5) error (_("Dwarf Error: wrong version in compilation unit header " - "(is %d, should be 2, 3, or 4) [in module %s]"), header->version, + "(is %d, should be 2, 3, 4 or 5) [in module %s]"), header->version, filename); - if (header->abbrev_offset.sect_off + if (to_underlying (header->abbrev_sect_off) >= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section)) - error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header " - "(offset 0x%lx + 6) [in module %s]"), - (long) header->abbrev_offset.sect_off, (long) header->offset.sect_off, + error (_("Dwarf Error: bad offset (0x%x) in compilation unit header " + "(offset 0x%x + 6) [in module %s]"), + to_underlying (header->abbrev_sect_off), + to_underlying (header->sect_off), filename); - /* Cast to unsigned long to use 64-bit arithmetic when possible to + /* Cast to ULONGEST to use 64-bit arithmetic when possible to avoid potential 32-bit overflow. */ - if (((unsigned long) header->offset.sect_off + get_cu_length (header)) + if (((ULONGEST) header->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) header->offset.sect_off, + error (_("Dwarf Error: bad length (0x%x) in compilation unit header " + "(offset 0x%x + 0) [in module %s]"), + header->length, to_underlying (header->sect_off), filename); } @@ -4402,56 +4690,16 @@ read_and_check_comp_unit_head (struct comp_unit_head *header, struct dwarf2_section_info *section, struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr, - int is_debug_types_section) -{ - const gdb_byte *beg_of_comp_unit = info_ptr; - bfd *abfd = get_section_bfd_owner (section); - - header->offset.sect_off = beg_of_comp_unit - section->buffer; - - 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; -} - -/* Read in the types comp unit header information from .debug_types entry at - types_ptr. The result is a pointer to one past the end of the header. */ - -static const gdb_byte * -read_and_check_type_unit_head (struct comp_unit_head *header, - struct dwarf2_section_info *section, - struct dwarf2_section_info *abbrev_section, - const gdb_byte *info_ptr, - ULONGEST *signature, - cu_offset *type_offset_in_tu) + rcuh_kind section_kind) { const gdb_byte *beg_of_comp_unit = info_ptr; bfd *abfd = get_section_bfd_owner (section); - header->offset.sect_off = beg_of_comp_unit - section->buffer; + header->sect_off = (sect_offset) (beg_of_comp_unit - section->buffer); - info_ptr = read_comp_unit_head (header, info_ptr, abfd); + info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind); - /* 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; + header->first_die_cu_offset = (cu_offset) (info_ptr - beg_of_comp_unit); error_check_comp_unit_head (header, section, abbrev_section); @@ -4462,24 +4710,32 @@ read_and_check_type_unit_head (struct comp_unit_head *header, static sect_offset read_abbrev_offset (struct dwarf2_section_info *section, - sect_offset offset) + sect_offset sect_off) { bfd *abfd = get_section_bfd_owner (section); const gdb_byte *info_ptr; - unsigned int length, initial_length_size, offset_size; - sect_offset abbrev_offset; + unsigned int initial_length_size, offset_size; + uint16_t version; 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); + info_ptr = section->buffer + to_underlying (sect_off); + 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 - partial symtab as being an include of PST. */ + info_ptr += initial_length_size; + + version = read_2_bytes (abfd, info_ptr); + info_ptr += 2; + if (version >= 5) + { + /* Skip unit type and address size. */ + info_ptr += 2; + } + + return (sect_offset) read_offset_1 (abfd, info_ptr, offset_size); +} + +/* Allocate a new partial symtab for file named NAME and mark this new + partial symtab as being an include of PST. */ static void dwarf2_create_include_psymtab (const char *name, struct partial_symtab *pst, @@ -4496,9 +4752,8 @@ dwarf2_create_include_psymtab (const char *name, struct partial_symtab *pst, subpst->textlow = 0; subpst->texthigh = 0; - subpst->dependencies = (struct partial_symtab **) - obstack_alloc (&objfile->objfile_obstack, - sizeof (struct partial_symtab *)); + subpst->dependencies + = XOBNEW (&objfile->objfile_obstack, struct partial_symtab *); subpst->dependencies[0] = pst; subpst->number_of_dependencies = 1; @@ -4525,25 +4780,24 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu, struct die_info *die, struct partial_symtab *pst) { - struct line_header *lh = NULL; + line_header_up lh; struct attribute *attr; attr = dwarf2_attr (die, DW_AT_stmt_list, cu); if (attr) - lh = dwarf_decode_line_header (DW_UNSND (attr), cu); + lh = dwarf_decode_line_header ((sect_offset) DW_UNSND (attr), cu); if (lh == NULL) return; /* No linetable, so no includes. */ /* NOTE: pst->dirname is DW_AT_comp_dir (if present). */ - dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow, 1); - - free_line_header (lh); + dwarf_decode_lines (lh.get (), pst->dirname, cu, pst, pst->textlow, 1); } static hashval_t hash_signatured_type (const void *item) { - const struct signatured_type *sig_type = item; + const struct signatured_type *sig_type + = (const struct signatured_type *) item; /* This drops the top 32 bits of the signature, but is ok for a hash. */ return sig_type->signature; @@ -4552,8 +4806,8 @@ hash_signatured_type (const void *item) static int 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; + const struct signatured_type *lhs = (const struct signatured_type *) item_lhs; + const struct signatured_type *rhs = (const struct signatured_type *) item_rhs; return lhs->signature == rhs->signature; } @@ -4577,8 +4831,8 @@ allocate_signatured_type_table (struct objfile *objfile) static int add_signatured_type_cu_to_table (void **slot, void *datum) { - struct signatured_type *sigt = *slot; - struct signatured_type ***datap = datum; + struct signatured_type *sigt = (struct signatured_type *) *slot; + struct signatured_type ***datap = (struct signatured_type ***) datum; **datap = sigt; ++*datap; @@ -4586,165 +4840,177 @@ add_signatured_type_cu_to_table (void **slot, void *datum) return 1; } -/* Create the hash table of all entries in the .debug_types - (or .debug_types.dwo) section(s). - If reading a DWO file, then DWO_FILE is a pointer to the DWO file object, - otherwise it is NULL. - - The result is a pointer to the hash table or NULL if there are no types. - - Note: This function processes DWO files only, not DWP files. */ +/* A helper for create_debug_types_hash_table. Read types from SECTION + and fill them into TYPES_HTAB. It will process only type units, + therefore DW_UT_type. */ -static htab_t -create_debug_types_hash_table (struct dwo_file *dwo_file, - VEC (dwarf2_section_info_def) *types) +static void +create_debug_type_hash_table (struct dwo_file *dwo_file, + dwarf2_section_info *section, htab_t &types_htab, + rcuh_kind section_kind) { struct objfile *objfile = dwarf2_per_objfile->objfile; - htab_t types_htab = NULL; - int ix; - struct dwarf2_section_info *section; struct dwarf2_section_info *abbrev_section; - - if (VEC_empty (dwarf2_section_info_def, types)) - return NULL; + bfd *abfd; + const gdb_byte *info_ptr, *end_ptr; abbrev_section = (dwo_file != NULL ? &dwo_file->sections.abbrev : &dwarf2_per_objfile->abbrev); if (dwarf_read_debug) - fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n", - dwo_file ? ".dwo" : "", + fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n", + get_section_name (section), get_section_file_name (abbrev_section)); - for (ix = 0; - VEC_iterate (dwarf2_section_info_def, types, ix, section); - ++ix) - { - bfd *abfd; - const gdb_byte *info_ptr, *end_ptr; + dwarf2_read_section (objfile, section); + info_ptr = section->buffer; - dwarf2_read_section (objfile, section); - info_ptr = section->buffer; + if (info_ptr == NULL) + return; - if (info_ptr == NULL) - continue; + /* We can't set abfd until now because the section may be empty or + not present, in which case the bfd is unknown. */ + abfd = get_section_bfd_owner (section); - /* We can't set abfd until now because the section may be empty or - not present, in which case the bfd is unknown. */ - abfd = get_section_bfd_owner (section); + /* We don't use init_cutu_and_read_dies_simple, or some such, here + because we don't need to read any dies: the signature is in the + header. */ - /* 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) + { + struct signatured_type *sig_type; + struct dwo_unit *dwo_tu; + void **slot; + const gdb_byte *ptr = info_ptr; + struct comp_unit_head header; + unsigned int length; - end_ptr = info_ptr + section->size; - while (info_ptr < end_ptr) - { - sect_offset offset; - cu_offset type_offset_in_tu; - ULONGEST signature; - struct signatured_type *sig_type; - struct dwo_unit *dwo_tu; - void **slot; - const gdb_byte *ptr = info_ptr; - struct comp_unit_head header; - unsigned int length; + sect_offset sect_off = (sect_offset) (ptr - section->buffer); - offset.sect_off = ptr - section->buffer; + /* Initialize it due to a false compiler warning. */ + header.signature = -1; + header.type_cu_offset_in_tu = (cu_offset) -1; - /* We need to read the type's signature in order to build the hash - table, but we don't need anything else just yet. */ + /* We need to read the type's signature in order to build the hash + table, but we don't need anything else just yet. */ - ptr = read_and_check_type_unit_head (&header, section, - abbrev_section, ptr, - &signature, &type_offset_in_tu); + ptr = read_and_check_comp_unit_head (&header, section, + abbrev_section, ptr, section_kind); - length = get_cu_length (&header); + length = get_cu_length (&header); - /* Skip dummy type units. */ - if (ptr >= info_ptr + length - || peek_abbrev_code (abfd, ptr) == 0) - { - info_ptr += length; - continue; - } + /* Skip dummy type units. */ + if (ptr >= info_ptr + length + || peek_abbrev_code (abfd, ptr) == 0 + || header.unit_type != DW_UT_type) + { + info_ptr += length; + continue; + } - if (types_htab == NULL) - { - if (dwo_file) - types_htab = allocate_dwo_unit_table (objfile); - else - types_htab = allocate_signatured_type_table (objfile); - } + if (types_htab == NULL) + { + if (dwo_file) + types_htab = allocate_dwo_unit_table (objfile); + else + types_htab = allocate_signatured_type_table (objfile); + } + + if (dwo_file) + { + sig_type = NULL; + dwo_tu = OBSTACK_ZALLOC (&objfile->objfile_obstack, + struct dwo_unit); + dwo_tu->dwo_file = dwo_file; + dwo_tu->signature = header.signature; + dwo_tu->type_offset_in_tu = header.type_cu_offset_in_tu; + dwo_tu->section = section; + dwo_tu->sect_off = sect_off; + 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 = header.signature; + sig_type->type_offset_in_tu = header.type_cu_offset_in_tu; + sig_type->per_cu.objfile = objfile; + sig_type->per_cu.is_debug_types = 1; + sig_type->per_cu.section = section; + sig_type->per_cu.sect_off = sect_off; + sig_type->per_cu.length = length; + } + + slot = htab_find_slot (types_htab, + dwo_file ? (void*) dwo_tu : (void *) sig_type, + INSERT); + gdb_assert (slot != NULL); + if (*slot != NULL) + { + sect_offset dup_sect_off; 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->section = section; - dwo_tu->offset = offset; - dwo_tu->length = length; + const struct dwo_unit *dup_tu + = (const struct dwo_unit *) *slot; + + dup_sect_off = dup_tu->sect_off; } 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.section = section; - sig_type->per_cu.offset = offset; - sig_type->per_cu.length = length; + const struct signatured_type *dup_tu + = (const struct signatured_type *) *slot; + + dup_sect_off = dup_tu->per_cu.sect_off; } - slot = htab_find_slot (types_htab, - dwo_file ? (void*) dwo_tu : (void *) sig_type, - INSERT); - gdb_assert (slot != NULL); - if (*slot != NULL) - { - sect_offset dup_offset; + complaint (&symfile_complaints, + _("debug type entry at offset 0x%x is duplicate to" + " the entry at offset 0x%x, signature %s"), + to_underlying (sect_off), to_underlying (dup_sect_off), + hex_string (header.signature)); + } + *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type; - if (dwo_file) - { - const struct dwo_unit *dup_tu = *slot; + if (dwarf_read_debug > 1) + fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n", + to_underlying (sect_off), + hex_string (header.signature)); - dup_offset = dup_tu->offset; - } - else - { - const struct signatured_type *dup_tu = *slot; + info_ptr += length; + } +} - dup_offset = dup_tu->per_cu.offset; - } +/* Create the hash table of all entries in the .debug_types + (or .debug_types.dwo) section(s). + If reading a DWO file, then DWO_FILE is a pointer to the DWO file object, + otherwise it is NULL. - complaint (&symfile_complaints, - _("debug type entry at offset 0x%x is duplicate to" - " the entry at offset 0x%x, signature %s"), - offset.sect_off, dup_offset.sect_off, - hex_string (signature)); - } - *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type; + The result is a pointer to the hash table or NULL if there are no types. - if (dwarf_read_debug > 1) - fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n", - offset.sect_off, - hex_string (signature)); + Note: This function processes DWO files only, not DWP files. */ - info_ptr += length; - } - } +static void +create_debug_types_hash_table (struct dwo_file *dwo_file, + VEC (dwarf2_section_info_def) *types, + htab_t &types_htab) +{ + int ix; + struct dwarf2_section_info *section; + + if (VEC_empty (dwarf2_section_info_def, types)) + return; - return types_htab; + for (ix = 0; + VEC_iterate (dwarf2_section_info_def, types, ix, section); + ++ix) + create_debug_type_hash_table (dwo_file, section, types_htab, + rcuh_kind::TYPE); } /* Create the hash table of all entries in the .debug_types section, @@ -4755,10 +5021,12 @@ create_debug_types_hash_table (struct dwo_file *dwo_file, static int create_all_type_units (struct objfile *objfile) { - htab_t types_htab; + htab_t types_htab = NULL; struct signatured_type **iter; - types_htab = create_debug_types_hash_table (NULL, dwarf2_per_objfile->types); + create_debug_type_hash_table (NULL, &dwarf2_per_objfile->info, types_htab, + rcuh_kind::COMPILE); + create_debug_types_hash_table (NULL, dwarf2_per_objfile->types, types_htab); if (types_htab == NULL) { dwarf2_per_objfile->signatured_types = NULL; @@ -4770,9 +5038,8 @@ create_all_type_units (struct objfile *objfile) dwarf2_per_objfile->n_type_units = dwarf2_per_objfile->n_allocated_type_units = htab_elements (types_htab); - dwarf2_per_objfile->all_type_units - = xmalloc (dwarf2_per_objfile->n_type_units - * sizeof (struct signatured_type *)); + dwarf2_per_objfile->all_type_units = + XNEWVEC (struct signatured_type *, dwarf2_per_objfile->n_type_units); 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] @@ -4800,9 +5067,9 @@ add_type_unit (ULONGEST sig, void **slot) dwarf2_per_objfile->n_allocated_type_units = 1; dwarf2_per_objfile->n_allocated_type_units *= 2; dwarf2_per_objfile->all_type_units - = xrealloc (dwarf2_per_objfile->all_type_units, - dwarf2_per_objfile->n_allocated_type_units - * sizeof (struct signatured_type *)); + = XRESIZEVEC (struct signatured_type *, + dwarf2_per_objfile->all_type_units, + dwarf2_per_objfile->n_allocated_type_units); ++dwarf2_per_objfile->tu_stats.nr_all_type_units_reallocs; } dwarf2_per_objfile->n_type_units = n_type_units; @@ -4849,12 +5116,12 @@ fill_in_sig_entry_from_dwo_entry (struct objfile *objfile, else gdb_assert (sig_entry->per_cu.v.psymtab == NULL); gdb_assert (sig_entry->signature == dwo_entry->signature); - gdb_assert (sig_entry->type_offset_in_section.sect_off == 0); + gdb_assert (to_underlying (sig_entry->type_offset_in_section) == 0); gdb_assert (sig_entry->type_unit_group == NULL); gdb_assert (sig_entry->dwo_unit == NULL); sig_entry->per_cu.section = dwo_entry->section; - sig_entry->per_cu.offset = dwo_entry->offset; + sig_entry->per_cu.sect_off = dwo_entry->sect_off; sig_entry->per_cu.length = dwo_entry->length; sig_entry->per_cu.reading_dwo_directly = 1; sig_entry->per_cu.objfile = objfile; @@ -4902,7 +5169,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) find_sig_entry.signature = sig; slot = htab_find_slot (dwarf2_per_objfile->signatured_types, &find_sig_entry, INSERT); - sig_entry = *slot; + sig_entry = (struct signatured_type *) *slot; /* We can get here with the TU already read, *or* in the process of being read. Don't reassign the global entry to point to this DWO if that's @@ -4924,7 +5191,7 @@ lookup_dwo_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) if (dwo_file->tus == NULL) return NULL; find_dwo_entry.signature = sig; - dwo_entry = htab_find (dwo_file->tus, &find_dwo_entry); + dwo_entry = (struct dwo_unit *) htab_find (dwo_file->tus, &find_dwo_entry); if (dwo_entry == NULL) return NULL; @@ -4965,7 +5232,7 @@ lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) find_sig_entry.signature = sig; slot = htab_find_slot (dwarf2_per_objfile->signatured_types, &find_sig_entry, INSERT); - sig_entry = *slot; + sig_entry = (struct signatured_type *) *slot; /* Have we already tried to read this TU? Note: sig_entry can be NULL if the skeleton TU was removed (thus it @@ -5010,7 +5277,8 @@ lookup_signatured_type (struct dwarf2_cu *cu, ULONGEST sig) if (dwarf2_per_objfile->signatured_types == NULL) return NULL; find_entry.signature = sig; - entry = htab_find (dwarf2_per_objfile->signatured_types, &find_entry); + entry = ((struct signatured_type *) + htab_find (dwarf2_per_objfile->signatured_types, &find_entry)); return entry; } } @@ -5120,8 +5388,7 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu, else if (stub_comp_dir != NULL) { /* Reconstruct the comp_dir attribute to simplify the code below. */ - comp_dir = (struct attribute *) - obstack_alloc (&cu->comp_unit_obstack, sizeof (*comp_dir)); + comp_dir = XOBNEW (&cu->comp_unit_obstack, struct attribute); comp_dir->name = DW_AT_comp_dir; comp_dir->form = DW_FORM_string; DW_STRING_IS_CANONICAL (comp_dir) = 0; @@ -5133,48 +5400,45 @@ read_cutu_die_from_dwo (struct dwarf2_per_cu_data *this_cu, section = dwo_unit->section; dwarf2_read_section (objfile, section); abfd = get_section_bfd_owner (section); - begin_info_ptr = info_ptr = section->buffer + dwo_unit->offset.sect_off; + begin_info_ptr = info_ptr = (section->buffer + + to_underlying (dwo_unit->sect_off)); dwo_abbrev_section = &dwo_unit->dwo_file->sections.abbrev; init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file); if (this_cu->is_debug_types) { - ULONGEST header_signature; - cu_offset type_offset_in_tu; struct signatured_type *sig_type = (struct signatured_type *) this_cu; - info_ptr = read_and_check_type_unit_head (&cu->header, section, + info_ptr = read_and_check_comp_unit_head (&cu->header, section, dwo_abbrev_section, - info_ptr, - &header_signature, - &type_offset_in_tu); + info_ptr, rcuh_kind::TYPE); /* This is not an assert because it can be caused by bad debug info. */ - if (sig_type->signature != header_signature) + if (sig_type->signature != cu->header.signature) { error (_("Dwarf Error: signature mismatch %s vs %s while reading" " TU at offset 0x%x [in module %s]"), hex_string (sig_type->signature), - hex_string (header_signature), - dwo_unit->offset.sect_off, + hex_string (cu->header.signature), + to_underlying (dwo_unit->sect_off), bfd_get_filename (abfd)); } - gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off); + gdb_assert (dwo_unit->sect_off == cu->header.sect_off); /* For DWOs coming from DWP files, we don't know the CU length nor the type's offset in the TU until now. */ dwo_unit->length = get_cu_length (&cu->header); - dwo_unit->type_offset_in_tu = type_offset_in_tu; + dwo_unit->type_offset_in_tu = cu->header.type_cu_offset_in_tu; /* Establish the type offset that can be used to lookup the type. For DWO files, we don't know it until now. */ - sig_type->type_offset_in_section.sect_off = - dwo_unit->offset.sect_off + dwo_unit->type_offset_in_tu.cu_off; + sig_type->type_offset_in_section + = dwo_unit->sect_off + to_underlying (dwo_unit->type_offset_in_tu); } 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); + info_ptr, rcuh_kind::COMPILE); + gdb_assert (dwo_unit->sect_off == cu->header.sect_off); /* For DWOs coming from DWP files, we don't know the CU length until now. */ dwo_unit->length = get_cu_length (&cu->header); @@ -5267,13 +5531,8 @@ lookup_dwo_unit (struct dwarf2_per_cu_data *this_cu, gdb_assert (cu != NULL); /* Yeah, we look dwo_name up again, but it simplifies the code. */ - attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu); - gdb_assert (attr != NULL); - dwo_name = DW_STRING (attr); - comp_dir = NULL; - attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu); - if (attr) - comp_dir = DW_STRING (attr); + dwo_name = dwarf2_string_attr (comp_unit_die, DW_AT_GNU_dwo_name, cu); + comp_dir = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu); if (this_cu->is_debug_types) { @@ -5344,7 +5603,7 @@ init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, { /* If !use_existing_cu, this_cu->cu must be NULL. */ gdb_assert (this_cu->cu == NULL); - cu = xmalloc (sizeof (*cu)); + cu = XNEW (struct dwarf2_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); @@ -5439,7 +5698,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu, if (dwarf_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); + to_underlying (this_cu->sect_off)); if (use_existing_cu) gdb_assert (keep); @@ -5461,7 +5720,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu, /* 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; + begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off); abbrev_section = get_abbrev_section_for_cu (this_cu); @@ -5481,54 +5740,54 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu, { /* If !use_existing_cu, this_cu->cu must be NULL. */ gdb_assert (this_cu->cu == NULL); - cu = xmalloc (sizeof (*cu)); + cu = XNEW (struct dwarf2_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); } /* Get the header. */ - if (cu->header.first_die_offset.cu_off != 0 && ! rereading_dwo_cu) + if (to_underlying (cu->header.first_die_cu_offset) != 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; + info_ptr += to_underlying (cu->header.first_die_cu_offset); } 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, + info_ptr = read_and_check_comp_unit_head (&cu->header, section, abbrev_section, info_ptr, - &signature, - &type_offset_in_tu); + rcuh_kind::TYPE); /* 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); + gdb_assert (sig_type->signature == cu->header.signature); + gdb_assert (sig_type->type_offset_in_tu + == cu->header.type_cu_offset_in_tu); + gdb_assert (this_cu->sect_off == cu->header.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; + sig_type->type_offset_in_section = + this_cu->sect_off + to_underlying (sig_type->type_offset_in_tu); + + this_cu->dwarf_version = cu->header.version; } else { info_ptr = read_and_check_comp_unit_head (&cu->header, section, abbrev_section, - info_ptr, 0); + info_ptr, + rcuh_kind::COMPILE); - gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off); + gdb_assert (this_cu->sect_off == cu->header.sect_off); gdb_assert (this_cu->length == get_cu_length (&cu->header)); + this_cu->dwarf_version = cu->header.version; } } @@ -5548,8 +5807,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu, if (abbrev_table != NULL) { gdb_assert (cu->abbrev_table == NULL); - gdb_assert (cu->header.abbrev_offset.sect_off - == abbrev_table->offset.sect_off); + gdb_assert (cu->header.abbrev_sect_off == abbrev_table->sect_off); cu->abbrev_table = abbrev_table; } else if (cu->abbrev_table == NULL) @@ -5582,7 +5840,7 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu, complaint (&symfile_complaints, _("compilation unit with DW_AT_GNU_dwo_name" " has children (offset 0x%x) [in module %s]"), - this_cu->offset.sect_off, bfd_get_filename (abfd)); + to_underlying (this_cu->sect_off), bfd_get_filename (abfd)); } dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die); if (dwo_unit != NULL) @@ -5672,7 +5930,7 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu, if (dwarf_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); + to_underlying (this_cu->sect_off)); gdb_assert (this_cu->cu == NULL); @@ -5687,10 +5945,12 @@ init_cutu_and_read_dies_no_follow (struct dwarf2_per_cu_data *this_cu, cleanups = make_cleanup (free_stack_comp_unit, &cu); - begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off; + begin_info_ptr = info_ptr = section->buffer + to_underlying (this_cu->sect_off); info_ptr = read_and_check_comp_unit_head (&cu.header, section, abbrev_section, info_ptr, - this_cu->is_debug_types); + (this_cu->is_debug_types + ? rcuh_kind::TYPE + : rcuh_kind::COMPILE)); this_cu->length = get_cu_length (&cu.header); @@ -5741,7 +6001,8 @@ init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu, static hashval_t hash_type_unit_group (const void *item) { - const struct type_unit_group *tu_group = item; + const struct type_unit_group *tu_group + = (const struct type_unit_group *) item; return hash_stmt_list_entry (&tu_group->hash); } @@ -5749,8 +6010,8 @@ hash_type_unit_group (const void *item) static int eq_type_unit_group (const void *item_lhs, const void *item_rhs) { - const struct type_unit_group *lhs = item_lhs; - const struct type_unit_group *rhs = item_rhs; + const struct type_unit_group *lhs = (const struct type_unit_group *) item_lhs; + const struct type_unit_group *rhs = (const struct type_unit_group *) item_rhs; return eq_stmt_list_entry (&lhs->hash, &rhs->hash); } @@ -5797,7 +6058,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct) } else { - unsigned int line_offset = line_offset_struct.sect_off; + unsigned int line_offset = to_underlying (line_offset_struct); struct partial_symtab *pst; char *name; @@ -5815,7 +6076,7 @@ create_type_unit_group (struct dwarf2_cu *cu, sect_offset line_offset_struct) } tu_group->hash.dwo_unit = cu->dwo_unit; - tu_group->hash.line_offset = line_offset_struct; + tu_group->hash.line_sect_off = line_offset_struct; return tu_group; } @@ -5859,19 +6120,17 @@ get_type_unit_group (struct dwarf2_cu *cu, const struct attribute *stmt_list) } type_unit_group_for_lookup.hash.dwo_unit = cu->dwo_unit; - type_unit_group_for_lookup.hash.line_offset.sect_off = line_offset; + type_unit_group_for_lookup.hash.line_sect_off = (sect_offset) line_offset; slot = htab_find_slot (dwarf2_per_objfile->type_unit_groups, &type_unit_group_for_lookup, INSERT); if (*slot != NULL) { - tu_group = *slot; + tu_group = (struct type_unit_group *) *slot; gdb_assert (tu_group != NULL); } else { - sect_offset line_offset_struct; - - line_offset_struct.sect_off = line_offset; + sect_offset line_offset_struct = (sect_offset) line_offset; tu_group = create_type_unit_group (cu, line_offset_struct); *slot = tu_group; ++tu_stats->nr_symtabs; @@ -5935,13 +6194,13 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, struct objfile *objfile = cu->objfile; struct gdbarch *gdbarch = get_objfile_arch (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; + enum pc_bounds_kind cu_bounds_kind; const char *filename; - struct process_psymtab_comp_unit_data *info = data; + struct process_psymtab_comp_unit_data *info + = (struct process_psymtab_comp_unit_data *) data; if (comp_unit_die->tag == DW_TAG_partial_unit && !info->want_partial_unit) return; @@ -5953,18 +6212,14 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, cu->list_in_scope = &file_symbols; /* Allocate a new partial symbol table structure. */ - attr = dwarf2_attr (comp_unit_die, DW_AT_name, cu); - if (attr == NULL || !DW_STRING (attr)) + filename = dwarf2_string_attr (comp_unit_die, DW_AT_name, cu); + if (filename == NULL) filename = ""; - else - filename = DW_STRING (attr); pst = create_partial_symtab (per_cu, filename); /* This must be done before calling dwarf2_build_include_psymtabs. */ - attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu); - if (attr != NULL) - pst->dirname = DW_STRING (attr); + pst->dirname = dwarf2_string_attr (comp_unit_die, DW_AT_comp_dir, cu); baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -5972,9 +6227,9 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, /* Possibly set the default values of LOWPC and HIGHPC from `DW_AT_ranges'. */ - has_pc_info = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc, - &best_highpc, cu, pst); - if (has_pc_info == 1 && best_lowpc < best_highpc) + cu_bounds_kind = dwarf2_get_pc_bounds (comp_unit_die, &best_lowpc, + &best_highpc, cu, pst); + if (cu_bounds_kind == PC_BOUNDS_HIGH_LOW && best_lowpc < best_highpc) /* Store the contiguous range if it is not empty; it can be empty for CUs with no code. */ addrmap_set_empty (objfile->psymtabs_addrmap, @@ -5998,7 +6253,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, first_die = load_partial_dies (reader, info_ptr, 1); scan_partial_symbols (first_die, &lowpc, &highpc, - ! has_pc_info, cu); + cu_bounds_kind <= PC_BOUNDS_INVALID, cu); /* If we didn't find a lowpc, set it to highpc to avoid complaints from `maint check'. */ @@ -6007,7 +6262,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, /* If the compilation unit didn't have an explicit address range, then use the information extracted from its child dies. */ - if (! has_pc_info) + if (cu_bounds_kind <= PC_BOUNDS_INVALID) { best_lowpc = lowpc; best_highpc = highpc; @@ -6016,11 +6271,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, pst->textlow = gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr); pst->texthigh = gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr); - pst->n_global_syms = objfile->global_psymbols.next - - (objfile->global_psymbols.list + pst->globals_offset); - pst->n_static_syms = objfile->static_psymbols.next - - (objfile->static_psymbols.list + pst->statics_offset); - sort_pst_symbols (objfile, pst); + end_psymtab_common (objfile, pst); if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs)) { @@ -6031,8 +6282,8 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, /* 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 *)); + pst->dependencies = + XOBNEWVEC (&objfile->objfile_obstack, struct partial_symtab *, len); for (i = 0; VEC_iterate (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs, i, iter); @@ -6054,7 +6305,7 @@ process_psymtab_comp_unit_reader (const struct die_reader_specs *reader, "Psymtab for %s unit @0x%x: %s - %s" ", %d global, %d static syms\n", per_cu->is_debug_types ? "type" : "comp", - per_cu->offset.sect_off, + to_underlying (per_cu->sect_off), paddress (gdbarch, pst->textlow), paddress (gdbarch, pst->texthigh), pst->n_global_syms, pst->n_static_syms); @@ -6069,8 +6320,6 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu, int want_partial_unit, enum language pretend_language) { - struct process_psymtab_comp_unit_data info; - /* If this compilation unit was already read in, free the cached copy in order to read it in again. This is necessary because we skipped some symbols when we first @@ -6079,12 +6328,17 @@ process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu, if (this_cu->cu != NULL) free_one_cached_comp_unit (this_cu); - gdb_assert (! this_cu->is_debug_types); - info.want_partial_unit = want_partial_unit; - info.pretend_language = pretend_language; - init_cutu_and_read_dies (this_cu, NULL, 0, 0, - process_psymtab_comp_unit_reader, - &info); + if (this_cu->is_debug_types) + init_cutu_and_read_dies (this_cu, NULL, 0, 0, build_type_psymtabs_reader, + NULL); + else + { + process_psymtab_comp_unit_data info; + info.want_partial_unit = want_partial_unit; + info.pretend_language = pretend_language; + init_cutu_and_read_dies (this_cu, NULL, 0, 0, + process_psymtab_comp_unit_reader, &info); + } /* Age out any secondary CUs. */ age_cached_comp_units (); @@ -6132,11 +6386,7 @@ build_type_psymtabs_reader (const struct die_reader_specs *reader, highpc = (CORE_ADDR) 0; scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu); - pst->n_global_syms = objfile->global_psymbols.next - - (objfile->global_psymbols.list + pst->globals_offset); - pst->n_static_syms = objfile->static_psymbols.next - - (objfile->static_psymbols.list + pst->statics_offset); - sort_pst_symbols (objfile, pst); + end_psymtab_common (objfile, pst); } /* Struct used to sort TUs by their abbreviation table offset. */ @@ -6152,10 +6402,12 @@ struct tu_abbrev_offset 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; + const struct tu_abbrev_offset * const *a + = (const struct tu_abbrev_offset * const*) ap; + const struct tu_abbrev_offset * const *b + = (const struct tu_abbrev_offset * const*) bp; + sect_offset aoff = (*a)->abbrev_offset; + sect_offset boff = (*b)->abbrev_offset; return (aoff > boff) - (aoff < boff); } @@ -6181,13 +6433,11 @@ sort_tu_by_abbrev_offset (const void *ap, const void *bp) static void build_type_psymtabs_1 (void) { - 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. */ @@ -6229,13 +6479,13 @@ build_type_psymtabs_1 (void) sorted_by_abbrev[i].sig_type = sig_type; sorted_by_abbrev[i].abbrev_offset = read_abbrev_offset (sig_type->per_cu.section, - sig_type->per_cu.offset); + sig_type->per_cu.sect_off); } 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); - abbrev_offset.sect_off = ~(unsigned) 0; + abbrev_offset = (sect_offset) ~(unsigned) 0; abbrev_table = NULL; make_cleanup (abbrev_table_free_cleanup, &abbrev_table); @@ -6245,7 +6495,7 @@ build_type_psymtabs_1 (void) /* Switch to the next abbrev table if necessary. */ if (abbrev_table == NULL - || tu->abbrev_offset.sect_off != abbrev_offset.sect_off) + || tu->abbrev_offset != abbrev_offset) { if (abbrev_table != NULL) { @@ -6307,8 +6557,8 @@ build_type_psymtab_dependencies (void **slot, void *info) gdb_assert (IS_TYPE_UNIT_GROUP (per_cu)); pst->number_of_dependencies = len; - pst->dependencies = obstack_alloc (&objfile->objfile_obstack, - len * sizeof (struct psymtab *)); + pst->dependencies = + XOBNEWVEC (&objfile->objfile_obstack, struct partial_symtab *, len); for (i = 0; VEC_iterate (sig_type_ptr, tu_group->tus, i, iter); ++i) @@ -6342,7 +6592,7 @@ static int process_skeletonless_type_unit (void **slot, void *info) { struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot; - struct objfile *objfile = info; + struct objfile *objfile = (struct objfile *) info; struct signatured_type find_entry, *entry; /* If this TU doesn't exist in the global table, add it and read it in. */ @@ -6412,7 +6662,7 @@ process_skeletonless_type_units (struct objfile *objfile) static void psymtabs_addrmap_cleanup (void *o) { - struct objfile *objfile = o; + struct objfile *objfile = (struct objfile *) o; objfile->psymtabs_addrmap = NULL; } @@ -6449,7 +6699,6 @@ static void dwarf2_build_psymtabs_hard (struct objfile *objfile) { struct cleanup *back_to, *addrmap_cleanup; - struct obstack temp_obstack; int i; if (dwarf_read_debug) @@ -6472,8 +6721,7 @@ dwarf2_build_psymtabs_hard (struct objfile *objfile) /* Create a temporary address map on a temporary obstack. We later copy this to the final obstack. */ - obstack_init (&temp_obstack); - make_cleanup_obstack_free (&temp_obstack); + auto_obstack temp_obstack; objfile->psymtabs_addrmap = addrmap_create_mutable (&temp_obstack); addrmap_cleanup = make_cleanup (psymtabs_addrmap_cleanup, objfile); @@ -6543,6 +6791,7 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu) static void read_comp_units_from_section (struct objfile *objfile, struct dwarf2_section_info *section, + struct dwarf2_section_info *abbrev_section, unsigned int is_dwz, int *n_allocated, int *n_comp_units, @@ -6562,22 +6811,33 @@ read_comp_units_from_section (struct objfile *objfile, while (info_ptr < section->buffer + section->size) { - unsigned int length, initial_length_size; struct dwarf2_per_cu_data *this_cu; - sect_offset offset; - offset.sect_off = info_ptr - section->buffer; + sect_offset sect_off = (sect_offset) (info_ptr - section->buffer); - /* Read just enough information to find out where the next - compilation unit is. */ - length = read_initial_length (abfd, info_ptr, &initial_length_size); + comp_unit_head cu_header; + read_and_check_comp_unit_head (&cu_header, section, abbrev_section, + info_ptr, rcuh_kind::COMPILE); /* Save the compilation unit for later lookup. */ - this_cu = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_per_cu_data)); - memset (this_cu, 0, sizeof (*this_cu)); - this_cu->offset = offset; - this_cu->length = length + initial_length_size; + if (cu_header.unit_type != DW_UT_type) + { + this_cu = XOBNEW (&objfile->objfile_obstack, + struct dwarf2_per_cu_data); + memset (this_cu, 0, sizeof (*this_cu)); + } + else + { + auto sig_type = XOBNEW (&objfile->objfile_obstack, + struct signatured_type); + memset (sig_type, 0, sizeof (*sig_type)); + sig_type->signature = cu_header.signature; + sig_type->type_offset_in_tu = cu_header.type_cu_offset_in_tu; + this_cu = &sig_type->per_cu; + } + this_cu->is_debug_types = (cu_header.unit_type == DW_UT_type); + this_cu->sect_off = sect_off; + this_cu->length = cu_header.length + cu_header.initial_length_size; this_cu->is_dwz = is_dwz; this_cu->objfile = objfile; this_cu->section = section; @@ -6585,9 +6845,8 @@ read_comp_units_from_section (struct objfile *objfile, if (*n_comp_units == *n_allocated) { *n_allocated *= 2; - *all_comp_units = xrealloc (*all_comp_units, - *n_allocated - * sizeof (struct dwarf2_per_cu_data *)); + *all_comp_units = XRESIZEVEC (struct dwarf2_per_cu_data *, + *all_comp_units, *n_allocated); } (*all_comp_units)[*n_comp_units] = this_cu; ++*n_comp_units; @@ -6609,21 +6868,21 @@ create_all_comp_units (struct objfile *objfile) n_comp_units = 0; n_allocated = 10; - all_comp_units = xmalloc (n_allocated - * sizeof (struct dwarf2_per_cu_data *)); + all_comp_units = XNEWVEC (struct dwarf2_per_cu_data *, n_allocated); - read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, 0, + read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, + &dwarf2_per_objfile->abbrev, 0, &n_allocated, &n_comp_units, &all_comp_units); dwz = dwarf2_get_dwz_file (); if (dwz != NULL) - read_comp_units_from_section (objfile, &dwz->info, 1, + read_comp_units_from_section (objfile, &dwz->info, &dwz->abbrev, 1, &n_allocated, &n_comp_units, &all_comp_units); - dwarf2_per_objfile->all_comp_units - = obstack_alloc (&objfile->objfile_obstack, - n_comp_units * sizeof (struct dwarf2_per_cu_data *)); + dwarf2_per_objfile->all_comp_units = XOBNEWVEC (&objfile->objfile_obstack, + struct dwarf2_per_cu_data *, + n_comp_units); memcpy (dwarf2_per_objfile->all_comp_units, all_comp_units, n_comp_units * sizeof (struct dwarf2_per_cu_data *)); xfree (all_comp_units); @@ -6682,6 +6941,9 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, { add_partial_symbol (pdi, cu); } + if (cu->language == language_rust && pdi->has_children) + scan_partial_symbols (pdi->die_child, lowpc, highpc, + set_addrmap, cu); break; case DW_TAG_enumeration_type: if (!pdi->is_declaration) @@ -6711,7 +6973,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, objfile_name (cu->objfile)); } - per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset, + per_cu = dwarf2_find_containing_comp_unit (pdi->d.sect_off, pdi->is_dwz, cu->objfile); @@ -6740,8 +7002,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc, /* Functions used to compute the fully scoped name of a partial DIE. Normally, this is simple. For C++, the parent DIE's fully scoped - name is concatenated with "::" and the partial DIE's name. For - Java, the same thing occurs except that "." is used instead of "::". + name is concatenated with "::" and the partial DIE's name. Enumerators are an exception; they use the scope of their parent enumeration type, i.e. the name of the enumeration type is not prepended to the enumerator. @@ -6825,7 +7086,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.sect_off); + parent->tag, to_underlying (pdi->sect_off)); parent->scope = grandparent_scope; } @@ -6857,9 +7118,9 @@ partial_die_full_name (struct partial_die_info *pdi, struct dwarf2_cu *ref_cu = cu; /* DW_FORM_ref_addr is using section offset. */ - attr.name = 0; + attr.name = (enum dwarf_attribute) 0; attr.form = DW_FORM_ref_addr; - attr.u.unsnd = pdi->offset.sect_off; + attr.u.unsnd = to_underlying (pdi->sect_off); die = follow_die_ref (NULL, &attr, &ref_cu); return xstrdup (dwarf2_full_name (NULL, die, ref_cu)); @@ -6902,24 +7163,23 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) of the global scope. But in Ada, we want to be able to access nested procedures globally. So all Ada subprograms are stored in the global scope. */ - /* prim_record_minimal_symbol (actual_name, addr, mst_text, - objfile); */ add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, VAR_DOMAIN, LOC_BLOCK, &objfile->global_psymbols, - 0, addr, cu->language, objfile); + addr, cu->language, objfile); } else { - /* prim_record_minimal_symbol (actual_name, addr, mst_file_text, - objfile); */ add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, VAR_DOMAIN, LOC_BLOCK, &objfile->static_psymbols, - 0, addr, cu->language, objfile); + addr, cu->language, objfile); } + + if (pdi->main_subprogram && actual_name != NULL) + set_objfile_main_name (objfile, actual_name, cu->language); break; case DW_TAG_constant: { @@ -6931,7 +7191,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) list = &objfile->static_psymbols; add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC, - list, 0, 0, cu->language, objfile); + list, 0, cu->language, objfile); } break; case DW_TAG_variable: @@ -6967,7 +7227,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC, &objfile->global_psymbols, - 0, addr + baseaddr, + addr + baseaddr, cu->language, objfile); } else @@ -6982,13 +7242,10 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) return; } - /* prim_record_minimal_symbol (actual_name, addr + baseaddr, - mst_file_data, objfile); */ add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC, &objfile->static_psymbols, - 0, has_loc ? addr + baseaddr : (CORE_ADDR) 0, cu->language, objfile); } @@ -7000,7 +7257,7 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) built_actual_name != NULL, VAR_DOMAIN, LOC_TYPEDEF, &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); break; case DW_TAG_imported_declaration: case DW_TAG_namespace: @@ -7008,14 +7265,14 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) built_actual_name != NULL, VAR_DOMAIN, LOC_TYPEDEF, &objfile->global_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); break; case DW_TAG_module: add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, MODULE_DOMAIN, LOC_TYPEDEF, &objfile->global_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); break; case DW_TAG_class_type: case DW_TAG_interface_type: @@ -7038,22 +7295,20 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu) add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, STRUCT_DOMAIN, LOC_TYPEDEF, - (cu->language == language_cplus - || cu->language == language_java) + cu->language == language_cplus ? &objfile->global_psymbols : &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); break; case DW_TAG_enumerator: add_psymbol_to_list (actual_name, strlen (actual_name), built_actual_name != NULL, VAR_DOMAIN, LOC_CONST, - (cu->language == language_cplus - || cu->language == language_java) + cu->language == language_cplus ? &objfile->global_psymbols : &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); break; default: break; @@ -7225,7 +7480,7 @@ peek_die_abbrev (const gdb_byte *info_ptr, unsigned int *bytes_read, error (_("Dwarf Error: Could not find abbrev number %d in %s" " at offset 0x%x [in module %s]"), abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU", - cu->header.offset.sect_off, bfd_get_filename (abfd)); + to_underlying (cu->header.sect_off), bfd_get_filename (abfd)); } return abbrev; @@ -7268,7 +7523,6 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, struct dwarf2_cu *cu = reader->cu; const gdb_byte *buffer = reader->buffer; const gdb_byte *buffer_end = reader->buffer_end; - const gdb_byte *start_info_ptr = info_ptr; unsigned int form, i; for (i = 0; i < abbrev->num_attrs; i++) @@ -7282,8 +7536,8 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, _("ignoring absolute DW_AT_sibling")); else { - unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off; - const gdb_byte *sibling_ptr = buffer + off; + sect_offset off = dwarf2_get_ref_die_offset (&attr); + const gdb_byte *sibling_ptr = buffer + to_underlying (off); if (sibling_ptr < info_ptr) complaint (&symfile_complaints, @@ -7320,6 +7574,7 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, info_ptr += 1; break; case DW_FORM_flag_present: + case DW_FORM_implicit_const: break; case DW_FORM_data2: case DW_FORM_ref2: @@ -7334,6 +7589,9 @@ skip_one_die (const struct die_reader_specs *reader, const gdb_byte *info_ptr, case DW_FORM_ref_sig8: info_ptr += 8; break; + case DW_FORM_data16: + info_ptr += 16; + break; case DW_FORM_string: read_direct_string (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; @@ -7430,7 +7688,9 @@ dwarf2_read_symtab (struct partial_symtab *self, } /* Restore our global data. */ - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + dwarf2_per_objfile + = (struct dwarf2_per_objfile *) objfile_data (objfile, + dwarf2_objfile_data_key); /* If this psymtab is constructed from a debug-only objfile, the has_section_at_zero flag will not necessarily be correct. We @@ -7439,8 +7699,9 @@ dwarf2_read_symtab (struct partial_symtab *self, if (objfile->separate_debug_objfile_backlink) { struct dwarf2_per_objfile *dpo_backlink - = objfile_data (objfile->separate_debug_objfile_backlink, - dwarf2_objfile_data_key); + = ((struct dwarf2_per_objfile *) + objfile_data (objfile->separate_debug_objfile_backlink, + dwarf2_objfile_data_key)); dwarf2_per_objfile->has_section_at_zero = dpo_backlink->has_section_at_zero; @@ -7469,7 +7730,7 @@ queue_comp_unit (struct dwarf2_per_cu_data *per_cu, struct dwarf2_queue_item *item; per_cu->queued = 1; - item = xmalloc (sizeof (*item)); + item = XNEW (struct dwarf2_queue_item); item->per_cu = per_cu; item->pretend_language = pretend_language; item->next = NULL; @@ -7564,14 +7825,15 @@ process_queue (void) sprintf (buf, "TU %s at offset 0x%x", hex_string (sig_type->signature), - per_cu->offset.sect_off); + to_underlying (per_cu->sect_off)); /* There can be 100s of TUs. Only print them in verbose mode. */ debug_print_threshold = 2; } else { - sprintf (buf, "CU at offset 0x%x", per_cu->offset.sect_off); + sprintf (buf, "CU at offset 0x%x", + to_underlying (per_cu->sect_off)); debug_print_threshold = 1; } @@ -7660,7 +7922,7 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) psymtab_to_symtab_1 (pst->dependencies[i]); } - per_cu = pst->read_symtab_private; + per_cu = (struct dwarf2_per_cu_data *) pst->read_symtab_private; if (per_cu == NULL) { @@ -7679,9 +7941,9 @@ psymtab_to_symtab_1 (struct partial_symtab *pst) static hashval_t die_hash (const void *item) { - const struct die_info *die = item; + const struct die_info *die = (const struct die_info *) item; - return die->offset.sect_off; + return to_underlying (die->sect_off); } /* Trivial comparison function for die_info structures: two DIEs @@ -7690,10 +7952,10 @@ die_hash (const void *item) 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; + const struct die_info *die_lhs = (const struct die_info *) item_lhs; + const struct die_info *die_rhs = (const struct die_info *) item_rhs; - return die_lhs->offset.sect_off == die_rhs->offset.sect_off; + return die_lhs->sect_off == die_rhs->sect_off; } /* die_reader_func for load_full_comp_unit. @@ -7708,7 +7970,7 @@ load_full_comp_unit_reader (const struct die_reader_specs *reader, void *data) { struct dwarf2_cu *cu = reader->cu; - enum language *language_ptr = data; + enum language *language_ptr = (enum language *) data; gdb_assert (cu->die_hash == NULL); cu->die_hash = @@ -7776,6 +8038,23 @@ free_delayed_list (void *ptr) } } +/* Check whether [PHYSNAME, PHYSNAME+LEN) ends with a modifier like + "const" / "volatile". If so, decrements LEN by the length of the + modifier and return true. Otherwise return false. */ + +template +static bool +check_modifier (const char *physname, size_t &len, const char (&mod)[N]) +{ + size_t mod_len = sizeof (mod) - 1; + if (len > mod_len && startswith (physname + (len - mod_len), mod)) + { + len -= mod_len; + return true; + } + return false; +} + /* Compute the physnames of any methods on the CU's method list. The computation of method physnames is delayed in order to avoid the @@ -7787,6 +8066,12 @@ compute_delayed_physnames (struct dwarf2_cu *cu) { int i; struct delayed_method_info *mi; + + /* Only C++ delays computing physnames. */ + if (VEC_empty (delayed_method_info, cu->method_list)) + return; + gdb_assert (cu->language == language_cplus); + for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i) { const char *physname; @@ -7795,6 +8080,26 @@ compute_delayed_physnames (struct dwarf2_cu *cu) physname = dwarf2_physname (mi->name, mi->die, cu); TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi->index) = physname ? physname : ""; + + /* Since there's no tag to indicate whether a method is a + const/volatile overload, extract that information out of the + demangled name. */ + if (physname != NULL) + { + size_t len = strlen (physname); + + while (1) + { + if (physname[len] == ')') /* shortcut */ + break; + else if (check_modifier (physname, len, " const")) + TYPE_FN_FIELD_CONST (fn_flp->fn_fields, mi->index) = 1; + else if (check_modifier (physname, len, " volatile")) + TYPE_FN_FIELD_VOLATILE (fn_flp->fn_fields, mi->index) = 1; + else + break; + } + } } } @@ -7851,11 +8156,11 @@ fixup_go_packaging (struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; const char *saved_package_name - = obstack_copy0 (&objfile->per_bfd->storage_obstack, - package_name, - strlen (package_name)); - struct type *type = init_type (TYPE_CODE_MODULE, 0, 0, - saved_package_name, objfile); + = (const char *) obstack_copy0 (&objfile->per_bfd->storage_obstack, + package_name, + strlen (package_name)); + struct type *type = init_type (objfile, TYPE_CODE_MODULE, 0, + saved_package_name); struct symbol *sym; TYPE_TAG_NAME (type) = TYPE_NAME (type); @@ -7982,8 +8287,8 @@ compute_compunit_symtab_includes (struct dwarf2_per_cu_data *per_cu) /* Now we have a transitive closure of all the included symtabs. */ len = VEC_length (compunit_symtab_ptr, result_symtabs); cust->includes - = obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack, - (len + 1) * sizeof (struct symtab *)); + = XOBNEWVEC (&dwarf2_per_objfile->objfile->objfile_obstack, + struct compunit_symtab *, len + 1); for (ix = 0; VEC_iterate (compunit_symtab_ptr, result_symtabs, ix, compunit_symtab_iter); @@ -8085,7 +8390,7 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu, 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 - && COMPUNIT_FILETABS (cust)->language != language_c)) + && COMPUNIT_FILETABS (cust)->language != language_unknown)) COMPUNIT_FILETABS (cust)->language = cu->language; /* GCC-4.0 has started to support -fvar-tracking. GCC-3.x still can @@ -8218,14 +8523,10 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu) 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; - int is_dwz; - - offset = dwarf2_get_ref_die_offset (attr); - is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz); - per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile); + sect_offset sect_off = dwarf2_get_ref_die_offset (attr); + bool is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz); + dwarf2_per_cu_data *per_cu + = dwarf2_find_containing_comp_unit (sect_off, is_dwz, cu->objfile); /* If necessary, add it to the queue and load its DIEs. */ if (maybe_queue_comp_unit (cu, per_cu, cu->language)) @@ -8236,28 +8537,44 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu) } } -/* Reset the in_process bit of a die. */ - -static void -reset_die_in_process (void *arg) +/* RAII object that represents a process_die scope: i.e., + starts/finishes processing a DIE. */ +class process_die_scope { - struct die_info *die = arg; +public: + process_die_scope (die_info *die, dwarf2_cu *cu) + : m_die (die), m_cu (cu) + { + /* We should only be processing DIEs not already in process. */ + gdb_assert (!m_die->in_process); + m_die->in_process = true; + } - die->in_process = 0; -} + ~process_die_scope () + { + m_die->in_process = false; + + /* If we're done processing the DIE for the CU that owns the line + header, we don't need the line header anymore. */ + if (m_cu->line_header_die_owner == m_die) + { + delete m_cu->line_header; + m_cu->line_header = NULL; + m_cu->line_header_die_owner = NULL; + } + } + +private: + die_info *m_die; + dwarf2_cu *m_cu; +}; /* Process a die and its children. */ static void process_die (struct die_info *die, struct dwarf2_cu *cu) { - struct cleanup *in_process; - - /* We should only be processing those not already in process. */ - gdb_assert (!die->in_process); - - die->in_process = 1; - in_process = make_cleanup (reset_die_in_process,die); + process_die_scope scope (die, cu); switch (die->tag) { @@ -8279,6 +8596,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_catch_block: read_lexical_block_scope (die, cu); break; + case DW_TAG_call_site: case DW_TAG_GNU_call_site: read_call_site_scope (die, cu); break; @@ -8301,6 +8619,7 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) case DW_TAG_pointer_type: case DW_TAG_ptr_to_member_type: case DW_TAG_reference_type: + case DW_TAG_rvalue_reference_type: case DW_TAG_string_type: break; @@ -8346,8 +8665,6 @@ process_die (struct die_info *die, struct dwarf2_cu *cu) new_symbol (die, NULL, cu); break; } - - do_cleanups (in_process); } /* DWARF name computation. */ @@ -8411,22 +8728,42 @@ die_needs_namespace (struct die_info *die, struct dwarf2_cu *cu) } } -/* Retrieve the last character from a mem_file. */ +/* Return the DIE's linkage name attribute, either DW_AT_linkage_name + or DW_AT_MIPS_linkage_name. Returns NULL if the attribute is not + defined for the given DIE. */ -static void -do_ui_file_peek_last (void *object, const char *buffer, long length) +static struct attribute * +dw2_linkage_name_attr (struct die_info *die, struct dwarf2_cu *cu) +{ + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_linkage_name, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + + return attr; +} + +/* Return the DIE's linkage name as a string, either DW_AT_linkage_name + or DW_AT_MIPS_linkage_name. Returns NULL if the attribute is not + defined for the given DIE. */ + +static const char * +dw2_linkage_name (struct die_info *die, struct dwarf2_cu *cu) { - char *last_char_p = (char *) object; + const char *linkage_name; + + linkage_name = dwarf2_string_attr (die, DW_AT_linkage_name, cu); + if (linkage_name == NULL) + linkage_name = dwarf2_string_attr (die, DW_AT_MIPS_linkage_name, cu); - if (length > 0) - *last_char_p = buffer[length - 1]; + return linkage_name; } /* 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), + - formal parameters (C++), - receiver type (Go), - - return type (Java). The term "physname" is a bit confusing. For C++, for example, it is the demangled name. @@ -8447,8 +8784,13 @@ dwarf2_compute_name (const char *name, if (name == NULL) name = dwarf2_name (die, cu); - /* For Fortran GDB prefers DW_AT_*linkage_name if present but otherwise - compute it by typename_concat inside GDB. */ + /* For Fortran GDB prefers DW_AT_*linkage_name for the physname if present + but otherwise compute it by typename_concat inside GDB. + FIXME: Actually this is not really true, or at least not always true. + It's all very confusing. SYMBOL_SET_NAMES doesn't try to demangle + Fortran names because there is no mangling standard. So new_symbol_full + will set the demangled name to the result of dwarf2_full_name, and it is + the demangled name that GDB uses if it exists. */ if (cu->language == language_ada || (cu->language == language_fortran && physname)) { @@ -8457,40 +8799,37 @@ dwarf2_compute_name (const char *name, to be able to reference. Ideally, we want the user to be able to reference this entity using either natural or linkage name, but we haven't started looking at this enhancement yet. */ - struct attribute *attr; + const char *linkage_name = dw2_linkage_name (die, cu); - attr = dwarf2_attr (die, DW_AT_linkage_name, cu); - if (attr == NULL) - attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); - if (attr && DW_STRING (attr)) - return DW_STRING (attr); + if (linkage_name != NULL) + return linkage_name; } /* These are the only languages we know how to qualify names in. */ if (name != NULL - && (cu->language == language_cplus || cu->language == language_java - || cu->language == language_fortran || cu->language == language_d)) + && (cu->language == language_cplus + || cu->language == language_fortran || cu->language == language_d + || cu->language == language_rust)) { if (die_needs_namespace (die, cu)) { long length; const char *prefix; - struct ui_file *buf; - char *intermediate_name; const char *canonical_name = NULL; + string_file buf; + prefix = determine_prefix (die, cu); - buf = mem_fileopen (); if (*prefix != '\0') { char *prefixed_name = typename_concat (NULL, prefix, name, physname, cu); - fputs_unfiltered (prefixed_name, buf); + buf.puts (prefixed_name); xfree (prefixed_name); } else - fputs_unfiltered (name, buf); + buf.puts (name); /* Template parameters may be specified in the DIE's DW_AT_name, or as children with DW_TAG_template_type_param or @@ -8535,25 +8874,25 @@ dwarf2_compute_name (const char *name, if (first) { - fputs_unfiltered ("<", buf); + buf.puts ("<"); first = 0; } else - fputs_unfiltered (", ", buf); + buf.puts (", "); attr = dwarf2_attr (child, DW_AT_type, cu); if (attr == NULL) { complaint (&symfile_complaints, _("template parameter missing DW_AT_type")); - fputs_unfiltered ("UNKNOWN_TYPE", buf); + buf.puts ("UNKNOWN_TYPE"); continue; } type = die_type (child, cu); if (child->tag == DW_TAG_template_type_param) { - c_print_type (type, "", buf, -1, 0, &type_print_raw_options); + c_print_type (type, "", &buf, -1, 0, &type_print_raw_options); continue; } @@ -8563,7 +8902,7 @@ dwarf2_compute_name (const char *name, complaint (&symfile_complaints, _("template parameter missing " "DW_AT_const_value")); - fputs_unfiltered ("UNKNOWN_VALUE", buf); + buf.puts ("UNKNOWN_VALUE"); continue; } @@ -8574,7 +8913,7 @@ dwarf2_compute_name (const char *name, if (TYPE_NOSIGN (type)) /* GDB prints characters as NUMBER 'CHAR'. If that's changed, this can use value_print instead. */ - c_printchar (value, type, buf); + c_printchar (value, type, &buf); else { struct value_print_options opts; @@ -8597,7 +8936,7 @@ dwarf2_compute_name (const char *name, the radix. */ get_formatted_print_options (&opts, 'd'); opts.raw = 1; - value_print (v, buf, &opts); + value_print (v, &buf, &opts); release_value (v); value_free (v); } @@ -8609,36 +8948,25 @@ dwarf2_compute_name (const char *name, { /* Close the argument list, with a space if necessary (nested templates). */ - char last_char = '\0'; - ui_file_put (buf, do_ui_file_peek_last, &last_char); - if (last_char == '>') - fputs_unfiltered (" >", buf); + if (!buf.empty () && buf.string ().back () == '>') + buf.puts (" >"); else - fputs_unfiltered (">", buf); + buf.puts (">"); } } - /* For Java and C++ methods, append formal parameter type + /* For C++ methods, append formal parameter type information, if PHYSNAME. */ if (physname && die->tag == DW_TAG_subprogram - && (cu->language == language_cplus - || cu->language == language_java)) + && cu->language == language_cplus) { struct type *type = read_type_die (die, cu); - c_type_print_args (type, buf, 1, cu->language, + c_type_print_args (type, &buf, 1, cu->language, &type_print_raw_options); - if (cu->language == language_java) - { - /* For java, we must append the return type to method - names. */ - if (die->tag == DW_TAG_subprogram) - java_print_type (TYPE_TARGET_TYPE (type), "", buf, - 0, 0, &type_print_raw_options); - } - else if (cu->language == language_cplus) + if (cu->language == language_cplus) { /* Assume that an artificial first parameter is "this", but do not crash if it is not. RealView @@ -8650,29 +8978,27 @@ dwarf2_compute_name (const char *name, && TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR && TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type, 0)))) - fputs_unfiltered (" const", buf); + buf.puts (" const"); } } - intermediate_name = ui_file_xstrdup (buf, &length); - ui_file_delete (buf); + const std::string &intermediate_name = buf.string (); if (cu->language == language_cplus) canonical_name - = dwarf2_canonicalize_name (intermediate_name, cu, + = dwarf2_canonicalize_name (intermediate_name.c_str (), cu, &objfile->per_bfd->storage_obstack); /* If we only computed INTERMEDIATE_NAME, or if INTERMEDIATE_NAME is already canonical, then we need to copy it to the appropriate obstack. */ - if (canonical_name == NULL || canonical_name == intermediate_name) - name = obstack_copy0 (&objfile->per_bfd->storage_obstack, - intermediate_name, - strlen (intermediate_name)); + if (canonical_name == NULL || canonical_name == intermediate_name.c_str ()) + name = ((const char *) + obstack_copy0 (&objfile->per_bfd->storage_obstack, + intermediate_name.c_str (), + intermediate_name.length ())); else name = canonical_name; - - xfree (intermediate_name); } } @@ -8685,7 +9011,7 @@ dwarf2_compute_name (const char *name, not have a name. NAME may either be from a previous call to dwarf2_name or NULL. - The output string will be canonicalized (if C++/Java). */ + The output string will be canonicalized (if C++). */ static const char * dwarf2_full_name (const char *name, struct die_info *die, struct dwarf2_cu *cu) @@ -8698,13 +9024,12 @@ dwarf2_full_name (const char *name, struct die_info *die, struct dwarf2_cu *cu) allocated on the objfile_objstack or NULL if the DIE does not have a name. - The output string will be canonicalized (if C++/Java). */ + The output string will be canonicalized (if C++). */ static const char * dwarf2_physname (const 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; int need_copy = 1; @@ -8716,18 +9041,20 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu) back_to = make_cleanup (null_cleanup, NULL); - attr = dwarf2_attr (die, DW_AT_linkage_name, cu); - if (!attr) - attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + mangled = dw2_linkage_name (die, cu); + + /* rustc emits invalid values for DW_AT_linkage_name. Ignore these. + See https://github.com/rust-lang/rust/issues/32925. */ + if (cu->language == language_rust && mangled != NULL + && strchr (mangled, '{') != NULL) + mangled = NULL; /* DW_AT_linkage_name is missing in some cases - depend on what GDB has computed. */ - if (attr && DW_STRING (attr)) + if (mangled != NULL) { char *demangled; - mangled = DW_STRING (attr); - /* Use DMGL_RET_DROP for C++ template functions to suppress their return type. It is easier for GDB users to search for such functions as `name(params)' than `long name(params)'. In such case the minimal @@ -8747,10 +9074,7 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu) else { demangled = gdb_demangle (mangled, - (DMGL_PARAMS | DMGL_ANSI - | (cu->language == language_java - ? DMGL_JAVA | DMGL_RET_POSTFIX - : DMGL_RET_DROP))); + (DMGL_PARAMS | DMGL_ANSI | DMGL_RET_DROP)); } if (demangled) { @@ -8777,7 +9101,7 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu) complaint (&symfile_complaints, _("Computed physname <%s> does not match demangled <%s> " "(from linkage <%s>) - DIE at 0x%x [in module %s]"), - physname, canon, mangled, die->offset.sect_off, + physname, canon, mangled, to_underlying (die->sect_off), objfile_name (objfile)); /* Prefer DW_AT_linkage_name (in the CANON form) - when it @@ -8796,8 +9120,9 @@ dwarf2_physname (const char *name, struct die_info *die, struct dwarf2_cu *cu) retval = canon; if (need_copy) - retval = obstack_copy0 (&objfile->per_bfd->storage_obstack, - retval, strlen (retval)); + retval = ((const char *) + obstack_copy0 (&objfile->per_bfd->storage_obstack, + retval, strlen (retval))); do_cleanups (back_to); return retval; @@ -8840,16 +9165,16 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu) { complaint (&symfile_complaints, _("DIE at 0x%x has too many recursively imported " - "declarations"), d->offset.sect_off); + "declarations"), to_underlying (d->sect_off)); return 0; } if (attr != NULL) { struct type *type; - sect_offset offset = dwarf2_get_ref_die_offset (attr); + sect_offset sect_off = dwarf2_get_ref_die_offset (attr); - type = get_die_type_at_offset (offset, cu->per_cu); + type = get_die_type_at_offset (sect_off, cu->per_cu); if (type != NULL && TYPE_CODE (type) == TYPE_CODE_NAMESPACE) { /* This declaration is a global namespace alias. Add @@ -8863,6 +9188,24 @@ read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu) return 0; } +/* Return the using directives repository (global or local?) to use in the + current context for LANGUAGE. + + For Ada, imported declarations can materialize renamings, which *may* be + global. However it is impossible (for now?) in DWARF to distinguish + "external" imported declarations and "static" ones. As all imported + declarations seem to be static in all other languages, make them all CU-wide + global only in Ada. */ + +static struct using_direct ** +using_directives (enum language language) +{ + if (language == language_ada && context_stack_depth == 0) + return &global_using_directives; + else + return &local_using_directives; +} + /* Read the import statement specified by the given die and record it. */ static void @@ -8878,8 +9221,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu) const char *import_alias; const char *imported_declaration = NULL; const char *import_prefix; - VEC (const_char_ptr) *excludes = NULL; - struct cleanup *cleanups; + std::vector excludes; import_attr = dwarf2_attr (die, DW_AT_import, cu); if (import_attr == NULL) @@ -8953,8 +9295,6 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu) else canonical_name = imported_name; - cleanups = make_cleanup (VEC_cleanup (const_char_ptr), &excludes); - if (die->tag == DW_TAG_imported_module && cu->language == language_fortran) for (child_die = die->child; child_die && child_die->tag; child_die = sibling_die (child_die)) @@ -8969,7 +9309,7 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu) complaint (&symfile_complaints, _("child DW_TAG_imported_declaration expected " "- DIE at 0x%x [in module %s]"), - child_die->offset.sect_off, objfile_name (objfile)); + to_underlying (child_die->sect_off), objfile_name (objfile)); continue; } @@ -8990,35 +9330,23 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu) complaint (&symfile_complaints, _("child DW_TAG_imported_declaration has unknown " "imported name - DIE at 0x%x [in module %s]"), - child_die->offset.sect_off, objfile_name (objfile)); + to_underlying (child_die->sect_off), objfile_name (objfile)); continue; } - VEC_safe_push (const_char_ptr, excludes, imported_name); + excludes.push_back (imported_name); process_die (child_die, cu); } - cp_add_using_directive (import_prefix, - canonical_name, - import_alias, - imported_declaration, - excludes, - 0, - &objfile->objfile_obstack); - - do_cleanups (cleanups); -} - -/* Cleanup function for handle_DW_AT_stmt_list. */ - -static void -free_cu_line_header (void *arg) -{ - struct dwarf2_cu *cu = arg; - - free_line_header (cu->line_header); - cu->line_header = NULL; + add_using_directive (using_directives (cu->language), + import_prefix, + canonical_name, + import_alias, + imported_declaration, + excludes, + 0, + &objfile->objfile_obstack); } /* Check for possibly missing DW_AT_comp_dir with relative .debug_line @@ -9034,47 +9362,38 @@ producer_is_gcc_lt_4_3 (struct dwarf2_cu *cu) return cu->producer_is_gcc_lt_4_3; } -static void -find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu, - const char **name, const char **comp_dir) +static file_and_directory +find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu) { - struct attribute *attr; - - *name = NULL; - *comp_dir = NULL; + file_and_directory res; /* 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); - } + res.name = dwarf2_string_attr (die, DW_AT_name, cu); + res.comp_dir = dwarf2_string_attr (die, DW_AT_comp_dir, cu); - attr = dwarf2_attr (die, DW_AT_comp_dir, cu); - if (attr) - *comp_dir = DW_STRING (attr); - else if (producer_is_gcc_lt_4_3 (cu) && *name != NULL - && IS_ABSOLUTE_PATH (*name)) + if (res.comp_dir == NULL + && producer_is_gcc_lt_4_3 (cu) && res.name != NULL + && IS_ABSOLUTE_PATH (res.name)) { - char *d = ldirname (*name); - - *comp_dir = d; - if (d != NULL) - make_cleanup (xfree, d); + res.comp_dir_storage = ldirname (res.name); + if (!res.comp_dir_storage.empty ()) + res.comp_dir = res.comp_dir_storage.c_str (); } - if (*comp_dir != NULL) + if (res.comp_dir != NULL) { /* Irix 6.2 native cc prepends .: to the compilation directory, get rid of it. */ - char *cp = strchr (*comp_dir, ':'); + const char *cp = strchr (res.comp_dir, ':'); - if (cp && cp != *comp_dir && cp[-1] == '.' && cp[1] == '/') - *comp_dir = cp + 1; + if (cp && cp != res.comp_dir && cp[-1] == '.' && cp[1] == '/') + res.comp_dir = cp + 1; } - if (*name == NULL) - *name = ""; + if (res.name == NULL) + res.name = ""; + + return res; } /* Handle DW_AT_stmt_list for a compilation unit. @@ -9088,7 +9407,6 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, { struct objfile *objfile = dwarf2_per_objfile->objfile; struct attribute *attr; - unsigned int line_offset; struct line_header line_header_local; hashval_t line_header_local_hash; unsigned u; @@ -9101,7 +9419,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, if (attr == NULL) return; - line_offset = DW_UNSND (attr); + sect_offset line_offset = (sect_offset) DW_UNSND (attr); /* The line header hash table is only created if needed (it exists to prevent redundant reading of the line table for partial_units). @@ -9121,7 +9439,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, dummy_obstack_deallocate); } - line_header_local.offset.sect_off = line_offset; + line_header_local.sect_off = line_offset; line_header_local.offset_in_dwz = cu->per_cu->is_dwz; line_header_local_hash = line_header_hash (&line_header_local); if (dwarf2_per_objfile->line_header_hash != NULL) @@ -9136,17 +9454,20 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, if (die->tag == DW_TAG_partial_unit && slot != NULL) { gdb_assert (*slot != NULL); - cu->line_header = *slot; + cu->line_header = (struct line_header *) *slot; return; } } /* dwarf_decode_line_header does not yet provide sufficient information. We always have to call also dwarf_decode_lines for it. */ - cu->line_header = dwarf_decode_line_header (line_offset, cu); - if (cu->line_header == NULL) + line_header_up lh = dwarf_decode_line_header (line_offset, cu); + if (lh == NULL) return; + cu->line_header = lh.release (); + cu->line_header_die_owner = die; + if (dwarf2_per_objfile->line_header_hash == NULL) slot = NULL; else @@ -9161,6 +9482,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, /* This newly decoded line number information unit will be owned by line_header_hash hash table. */ *slot = cu->line_header; + cu->line_header_die_owner = NULL; } else { @@ -9170,11 +9492,11 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu, number information unit. And if we're not using line_header_hash then this is what we want as well. */ gdb_assert (die->tag != DW_TAG_partial_unit); - make_cleanup (free_cu_line_header, cu); } decode_mapping = (die->tag != DW_TAG_partial_unit); dwarf_decode_lines (cu->line_header, comp_dir, cu, NULL, lowpc, decode_mapping); + } /* Process DW_TAG_compile_unit or DW_TAG_partial_unit. */ @@ -9184,14 +9506,10 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) { struct objfile *objfile = dwarf2_per_objfile->objfile; struct gdbarch *gdbarch = get_objfile_arch (objfile); - struct cleanup *back_to = make_cleanup (null_cleanup, 0); CORE_ADDR lowpc = ((CORE_ADDR) -1); CORE_ADDR highpc = ((CORE_ADDR) 0); struct attribute *attr; - const char *name = NULL; - const char *comp_dir = NULL; struct die_info *child_die; - bfd *abfd = objfile->obfd; CORE_ADDR baseaddr; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -9204,7 +9522,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) lowpc = highpc; lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); - find_file_and_directory (die, cu, &name, &comp_dir); + file_and_directory fnd = find_file_and_directory (die, cu); prepare_one_comp_unit (cu, die, cu->language); @@ -9218,12 +9536,12 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) if (cu->producer && strstr (cu->producer, "GNU Go ") != NULL) set_cu_language (DW_LANG_Go, cu); - dwarf2_start_symtab (cu, name, comp_dir, lowpc); + dwarf2_start_symtab (cu, fnd.name, fnd.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, lowpc); + handle_DW_AT_stmt_list (die, cu, fnd.comp_dir, lowpc); /* Process all dies in compilation unit. */ if (die->child != NULL) @@ -9240,12 +9558,14 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) refers to information in the line number info statement program header, so we can only read it if we've read the header successfully. */ - attr = dwarf2_attr (die, DW_AT_GNU_macros, cu); + attr = dwarf2_attr (die, DW_AT_macros, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_GNU_macros, cu); if (attr && cu->line_header) { if (dwarf2_attr (die, DW_AT_macro_info, cu)) complaint (&symfile_complaints, - _("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info")); + _("CU refers to both DW_AT_macros and DW_AT_macro_info")); dwarf_decode_macros (cu, DW_UNSND (attr), 1); } @@ -9259,8 +9579,6 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) dwarf_decode_macros (cu, macro_offset, 0); } } - - do_cleanups (back_to); } /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope. @@ -9272,13 +9590,11 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu) 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; + unsigned int i; struct signatured_type *sig_type; gdb_assert (per_cu->is_debug_types); @@ -9300,10 +9616,10 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu) /* We have to handle the case of both a missing DW_AT_stmt_list or bad debug info. */ - lh = NULL; + line_header_up lh; if (attr != NULL) { - line_offset = DW_UNSND (attr); + sect_offset line_offset = (sect_offset) DW_UNSND (attr); lh = dwarf_decode_line_header (line_offset, cu); } if (lh == NULL) @@ -9318,48 +9634,52 @@ setup_type_unit_groups (struct die_info *die, struct dwarf2_cu *cu) return; } - cu->line_header = lh; - make_cleanup (free_cu_line_header, cu); + cu->line_header = lh.release (); + cu->line_header_die_owner = die; if (first_time) { struct compunit_symtab *cust = dwarf2_start_symtab (cu, "", NULL, 0); - tu_group->num_symtabs = lh->num_file_names; - tu_group->symtabs = XNEWVEC (struct symtab *, lh->num_file_names); + /* Note: We don't assign tu_group->compunit_symtab yet because we're + still initializing it, and our caller (a few levels up) + process_full_type_unit still needs to know if this is the first + time. */ + + tu_group->num_symtabs = cu->line_header->file_names.size (); + tu_group->symtabs = XNEWVEC (struct symtab *, + cu->line_header->file_names.size ()); - for (i = 0; i < lh->num_file_names; ++i) + for (i = 0; i < cu->line_header->file_names.size (); ++i) { - const char *dir = NULL; - struct file_entry *fe = &lh->file_names[i]; + file_entry &fe = cu->line_header->file_names[i]; - if (fe->dir_index && lh->include_dirs != NULL) - dir = lh->include_dirs[fe->dir_index - 1]; - dwarf2_start_subfile (fe->name, dir); + dwarf2_start_subfile (fe.name, fe.include_dir (cu->line_header)); 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, plus - lh->file_names may contain dups. */ + /* 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 + cu->line_header->file_names to subfiles, plus + cu->line_header->file_names may contain dups. */ current_subfile->symtab = allocate_symtab (cust, current_subfile->name); } - fe->symtab = current_subfile->symtab; - tu_group->symtabs[i] = fe->symtab; + fe.symtab = current_subfile->symtab; + tu_group->symtabs[i] = fe.symtab; } } else { restart_symtab (tu_group->compunit_symtab, "", 0); - for (i = 0; i < lh->num_file_names; ++i) + for (i = 0; i < cu->line_header->file_names.size (); ++i) { - struct file_entry *fe = &lh->file_names[i]; + file_entry &fe = cu->line_header->file_names[i]; - fe->symtab = tu_group->symtabs[i]; + fe.symtab = tu_group->symtabs[i]; } } @@ -9410,7 +9730,7 @@ read_type_unit_scope (struct die_info *die, struct dwarf2_cu *cu) static hashval_t hash_dwo_file (const void *item) { - const struct dwo_file *dwo_file = item; + const struct dwo_file *dwo_file = (const struct dwo_file *) item; hashval_t hash; hash = htab_hash_string (dwo_file->dwo_name); @@ -9422,8 +9742,8 @@ hash_dwo_file (const void *item) 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; + const struct dwo_file *lhs = (const struct dwo_file *) item_lhs; + const struct dwo_file *rhs = (const struct dwo_file *) item_rhs; if (strcmp (lhs->dwo_name, rhs->dwo_name) != 0) return 0; @@ -9470,7 +9790,7 @@ lookup_dwo_file_slot (const char *dwo_name, const char *comp_dir) static hashval_t hash_dwo_unit (const void *item) { - const struct dwo_unit *dwo_unit = item; + const struct dwo_unit *dwo_unit = (const struct dwo_unit *) item; /* This drops the top 32 bits of the id, but is ok for a hash. */ return dwo_unit->signature; @@ -9479,8 +9799,8 @@ hash_dwo_unit (const void *item) 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; + const struct dwo_unit *lhs = (const struct dwo_unit *) item_lhs; + const struct dwo_unit *rhs = (const struct dwo_unit *) 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, @@ -9524,10 +9844,9 @@ create_dwo_cu_reader (const struct die_reader_specs *reader, void *datap) { struct dwarf2_cu *cu = reader->cu; - struct objfile *objfile = dwarf2_per_objfile->objfile; - sect_offset offset = cu->per_cu->offset; + sect_offset sect_off = cu->per_cu->sect_off; struct dwarf2_section_info *section = cu->per_cu->section; - struct create_dwo_cu_data *data = datap; + struct create_dwo_cu_data *data = (struct create_dwo_cu_data *) datap; struct dwo_file *dwo_file = data->dwo_file; struct dwo_unit *dwo_unit = &data->dwo_unit; struct attribute *attr; @@ -9538,93 +9857,92 @@ create_dwo_cu_reader (const struct die_reader_specs *reader, complaint (&symfile_complaints, _("Dwarf Error: debug entry at offset 0x%x is missing" " its dwo_id [in module %s]"), - offset.sect_off, dwo_file->dwo_name); + to_underlying (sect_off), dwo_file->dwo_name); return; } dwo_unit->dwo_file = dwo_file; dwo_unit->signature = DW_UNSND (attr); dwo_unit->section = section; - dwo_unit->offset = offset; + dwo_unit->sect_off = sect_off; dwo_unit->length = cu->per_cu->length; if (dwarf_read_debug) fprintf_unfiltered (gdb_stdlog, " offset 0x%x, dwo_id %s\n", - offset.sect_off, hex_string (dwo_unit->signature)); + to_underlying (sect_off), + hex_string (dwo_unit->signature)); } -/* Create the dwo_unit for the lone CU in DWO_FILE. +/* Create the dwo_units for the CUs in a DWO_FILE. Note: This function processes DWO files only, not DWP files. */ -static struct dwo_unit * -create_dwo_cu (struct dwo_file *dwo_file) +static void +create_cus_hash_table (struct dwo_file &dwo_file, dwarf2_section_info §ion, + htab_t &cus_htab) { struct objfile *objfile = dwarf2_per_objfile->objfile; - struct dwarf2_section_info *section = &dwo_file->sections.info; - bfd *abfd; - htab_t cu_htab; + const struct dwarf2_section_info *abbrev_section = &dwo_file.sections.abbrev; const gdb_byte *info_ptr, *end_ptr; - struct create_dwo_cu_data create_dwo_cu_data; - struct dwo_unit *dwo_unit; - dwarf2_read_section (objfile, section); - info_ptr = section->buffer; + dwarf2_read_section (objfile, §ion); + 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 = get_section_bfd_owner (section); + return; if (dwarf_read_debug) { fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n", - get_section_name (section), - get_section_file_name (section)); + get_section_name (§ion), + get_section_file_name (§ion)); } - create_dwo_cu_data.dwo_file = dwo_file; - dwo_unit = NULL; - - end_ptr = info_ptr + section->size; + end_ptr = info_ptr + section.size; while (info_ptr < end_ptr) { struct dwarf2_per_cu_data per_cu; + struct create_dwo_cu_data create_dwo_cu_data; + struct dwo_unit *dwo_unit; + void **slot; + sect_offset sect_off = (sect_offset) (info_ptr - section.buffer); memset (&create_dwo_cu_data.dwo_unit, 0, sizeof (create_dwo_cu_data.dwo_unit)); memset (&per_cu, 0, sizeof (per_cu)); per_cu.objfile = objfile; per_cu.is_debug_types = 0; - per_cu.offset.sect_off = info_ptr - section->buffer; - per_cu.section = section; + per_cu.sect_off = sect_offset (info_ptr - section.buffer); + per_cu.section = §ion; + create_dwo_cu_data.dwo_file = &dwo_file; - init_cutu_and_read_dies_no_follow (&per_cu, dwo_file, - create_dwo_cu_reader, - &create_dwo_cu_data); + init_cutu_and_read_dies_no_follow ( + &per_cu, &dwo_file, create_dwo_cu_reader, &create_dwo_cu_data); + info_ptr += per_cu.length; - if (create_dwo_cu_data.dwo_unit.dwo_file != NULL) - { - /* If we've already found one, complain. We only support one - because having more than one requires hacking the dwo_name of - each to match, which is highly unlikely to happen. */ - if (dwo_unit != NULL) - { - complaint (&symfile_complaints, - _("Multiple CUs in DWO file %s [in module %s]"), - dwo_file->dwo_name, objfile_name (objfile)); - break; - } + // If the unit could not be parsed, skip it. + if (create_dwo_cu_data.dwo_unit.dwo_file == NULL) + continue; - dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit); - *dwo_unit = create_dwo_cu_data.dwo_unit; - } + if (cus_htab == NULL) + cus_htab = allocate_dwo_unit_table (objfile); - info_ptr += per_cu.length; - } + dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit); + *dwo_unit = create_dwo_cu_data.dwo_unit; + slot = htab_find_slot (cus_htab, dwo_unit, INSERT); + gdb_assert (slot != NULL); + if (*slot != NULL) + { + const struct dwo_unit *dup_cu = (const struct dwo_unit *)*slot; + sect_offset dup_sect_off = dup_cu->sect_off; - return dwo_unit; + complaint (&symfile_complaints, + _("debug cu entry at offset 0x%x is duplicate to" + " the entry at offset 0x%x, signature %s"), + to_underlying (sect_off), to_underlying (dup_sect_off), + hex_string (dwo_unit->signature)); + } + *slot = (void *)dwo_unit; + } } /* DWP file .debug_{cu,tu}_index section format: @@ -9933,58 +10251,58 @@ locate_v1_virtual_dwo_sections (asection *sectp, if (section_is_p (sectp->name, &names->abbrev_dwo)) { /* There can be only one. */ - if (sections->abbrev.s.asection != NULL) + if (sections->abbrev.s.section != NULL) return 0; - sections->abbrev.s.asection = sectp; + sections->abbrev.s.section = sectp; sections->abbrev.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->info_dwo) || section_is_p (sectp->name, &names->types_dwo)) { /* There can be only one. */ - if (sections->info_or_types.s.asection != NULL) + if (sections->info_or_types.s.section != NULL) return 0; - sections->info_or_types.s.asection = sectp; + sections->info_or_types.s.section = sectp; sections->info_or_types.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->line_dwo)) { /* There can be only one. */ - if (sections->line.s.asection != NULL) + if (sections->line.s.section != NULL) return 0; - sections->line.s.asection = sectp; + sections->line.s.section = sectp; sections->line.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->loc_dwo)) { /* There can be only one. */ - if (sections->loc.s.asection != NULL) + if (sections->loc.s.section != NULL) return 0; - sections->loc.s.asection = sectp; + sections->loc.s.section = sectp; sections->loc.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->macinfo_dwo)) { /* There can be only one. */ - if (sections->macinfo.s.asection != NULL) + if (sections->macinfo.s.section != NULL) return 0; - sections->macinfo.s.asection = sectp; + sections->macinfo.s.section = sectp; sections->macinfo.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->macro_dwo)) { /* There can be only one. */ - if (sections->macro.s.asection != NULL) + if (sections->macro.s.section != NULL) return 0; - sections->macro.s.asection = sectp; + sections->macro.s.section = sectp; sections->macro.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->str_offsets_dwo)) { /* There can be only one. */ - if (sections->str_offsets.s.asection != NULL) + if (sections->str_offsets.s.section != NULL) return 0; - sections->str_offsets.s.asection = sectp; + sections->str_offsets.s.section = sectp; sections->str_offsets.size = bfd_get_section_size (sectp); } else @@ -10017,7 +10335,6 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file, struct virtual_v1_dwo_sections sections; void **dwo_file_slot; char *virtual_dwo_name; - struct dwarf2_section_info *cutu; struct cleanup *cleanups; int i; @@ -10115,9 +10432,10 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file, virtual_dwo_name); } dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file); - dwo_file->dwo_name = obstack_copy0 (&objfile->objfile_obstack, - virtual_dwo_name, - strlen (virtual_dwo_name)); + dwo_file->dwo_name + = (const char *) obstack_copy0 (&objfile->objfile_obstack, + virtual_dwo_name, + strlen (virtual_dwo_name)); dwo_file->comp_dir = comp_dir; dwo_file->sections.abbrev = sections.abbrev; dwo_file->sections.line = sections.line; @@ -10143,15 +10461,15 @@ create_dwo_unit_in_dwp_v1 (struct dwp_file *dwp_file, fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n", virtual_dwo_name); } - dwo_file = *dwo_file_slot; + dwo_file = (struct dwo_file *) *dwo_file_slot; } do_cleanups (cleanups); dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit); dwo_unit->dwo_file = dwo_file; dwo_unit->signature = signature; - dwo_unit->section = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_section_info)); + dwo_unit->section = + XOBNEW (&objfile->objfile_obstack, struct dwarf2_section_info); *dwo_unit->section = sections.info_or_types; /* dwo_unit->{offset,length,type_offset_in_tu} are set later. */ @@ -10222,7 +10540,6 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file, struct virtual_v2_dwo_sections sections; void **dwo_file_slot; char *virtual_dwo_name; - struct dwarf2_section_info *cutu; struct cleanup *cleanups; int i; @@ -10316,9 +10633,10 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file, virtual_dwo_name); } dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file); - dwo_file->dwo_name = obstack_copy0 (&objfile->objfile_obstack, - virtual_dwo_name, - strlen (virtual_dwo_name)); + dwo_file->dwo_name + = (const char *) obstack_copy0 (&objfile->objfile_obstack, + virtual_dwo_name, + strlen (virtual_dwo_name)); dwo_file->comp_dir = comp_dir; dwo_file->sections.abbrev = create_dwp_v2_section (&dwp_file->sections.abbrev, @@ -10357,15 +10675,15 @@ create_dwo_unit_in_dwp_v2 (struct dwp_file *dwp_file, fprintf_unfiltered (gdb_stdlog, "Using existing virtual DWO: %s\n", virtual_dwo_name); } - dwo_file = *dwo_file_slot; + dwo_file = (struct dwo_file *) *dwo_file_slot; } do_cleanups (cleanups); dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit); dwo_unit->dwo_file = dwo_file; dwo_unit->signature = signature; - dwo_unit->section = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_section_info)); + dwo_unit->section = + XOBNEW (&objfile->objfile_obstack, struct dwarf2_section_info); *dwo_unit->section = create_dwp_v2_section (is_debug_types ? &dwp_file->sections.types : &dwp_file->sections.info, @@ -10391,7 +10709,7 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir, uint32_t hash2 = ((signature >> 32) & mask) | 1; unsigned int i; void **slot; - struct dwo_unit find_dwo_cu, *dwo_cu; + struct dwo_unit find_dwo_cu; memset (&find_dwo_cu, 0, sizeof (find_dwo_cu)); find_dwo_cu.signature = signature; @@ -10401,7 +10719,7 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir, &find_dwo_cu, INSERT); if (*slot != NULL) - return *slot; + return (struct dwo_unit *) *slot; /* Use a for loop so that we don't loop forever on bad debug info. */ for (i = 0; i < dwp_htab->nr_slots; ++i) @@ -10428,7 +10746,7 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir, comp_dir, signature, is_debug_types); } - return *slot; + return (struct dwo_unit *) *slot; } if (signature_in_table == 0) return NULL; @@ -10452,10 +10770,9 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir, If unable to find/open the file, return NULL. NOTE: This function is derived from symfile_bfd_open. */ -static bfd * +static gdb_bfd_ref_ptr try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd) { - bfd *sym_bfd; int desc, flags; char *absolute_name; /* Blech. OPF_TRY_CWD_FIRST also disables searching the path list if @@ -10468,7 +10785,7 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd) { if (*debug_file_directory != '\0') search_path = concat (".", dirname_separator_string, - debug_file_directory, NULL); + debug_file_directory, (char *) NULL); else search_path = xstrdup ("."); } @@ -10484,23 +10801,20 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd) if (desc < 0) return NULL; - sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc); + gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc)); xfree (absolute_name); if (sym_bfd == NULL) return NULL; - bfd_set_cacheable (sym_bfd, 1); + bfd_set_cacheable (sym_bfd.get (), 1); - if (!bfd_check_format (sym_bfd, bfd_object)) - { - gdb_bfd_unref (sym_bfd); /* This also closes desc. */ - return NULL; - } + if (!bfd_check_format (sym_bfd.get (), bfd_object)) + return NULL; /* Success. Record the bfd as having been included by the objfile's bfd. This is important because things like demangled_names_hash lives in the objfile's per_bfd space and may have references to things like symbol names that live in the DWO/DWP file's per_bfd space. PR 16426. */ - gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd); + gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd.get ()); return sym_bfd; } @@ -10512,11 +10826,9 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd) Upon success, the canonicalized path of the file is stored in the bfd, same as symfile_bfd_open. */ -static bfd * +static gdb_bfd_ref_ptr open_dwo_file (const char *file_name, const char *comp_dir) { - bfd *abfd; - if (IS_ABSOLUTE_PATH (file_name)) return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/); @@ -10524,11 +10836,13 @@ open_dwo_file (const char *file_name, const char *comp_dir) if (comp_dir != NULL) { - char *path_to_try = concat (comp_dir, SLASH_STRING, file_name, NULL); + char *path_to_try = concat (comp_dir, SLASH_STRING, + file_name, (char *) NULL); /* NOTE: If comp_dir is a relative path, this will also try the search path, which seems useful. */ - abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/); + gdb_bfd_ref_ptr abfd (try_open_dwop_file (path_to_try, 0 /*is_dwp*/, + 1 /*search_cwd*/)); xfree (path_to_try); if (abfd != NULL) return abfd; @@ -10549,47 +10863,47 @@ open_dwo_file (const char *file_name, const char *comp_dir) static void dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr) { - struct dwo_sections *dwo_sections = dwo_sections_ptr; + struct dwo_sections *dwo_sections = (struct dwo_sections *) dwo_sections_ptr; const struct dwop_section_names *names = &dwop_section_names; if (section_is_p (sectp->name, &names->abbrev_dwo)) { - dwo_sections->abbrev.s.asection = sectp; + dwo_sections->abbrev.s.section = sectp; dwo_sections->abbrev.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->info_dwo)) { - dwo_sections->info.s.asection = sectp; + dwo_sections->info.s.section = sectp; dwo_sections->info.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->line_dwo)) { - dwo_sections->line.s.asection = sectp; + dwo_sections->line.s.section = sectp; dwo_sections->line.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->loc_dwo)) { - dwo_sections->loc.s.asection = sectp; + dwo_sections->loc.s.section = sectp; dwo_sections->loc.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->macinfo_dwo)) { - dwo_sections->macinfo.s.asection = sectp; + dwo_sections->macinfo.s.section = sectp; dwo_sections->macinfo.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->macro_dwo)) { - dwo_sections->macro.s.asection = sectp; + dwo_sections->macro.s.section = sectp; dwo_sections->macro.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->str_dwo)) { - dwo_sections->str.s.asection = sectp; + dwo_sections->str.s.section = sectp; dwo_sections->str.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->str_offsets_dwo)) { - dwo_sections->str_offsets.s.asection = sectp; + dwo_sections->str_offsets.s.section = sectp; dwo_sections->str_offsets.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->types_dwo)) @@ -10597,7 +10911,7 @@ dwarf2_locate_dwo_sections (bfd *abfd, asection *sectp, void *dwo_sections_ptr) struct dwarf2_section_info type_section; memset (&type_section, 0, sizeof (type_section)); - type_section.s.asection = sectp; + type_section.s.section = sectp; type_section.size = bfd_get_section_size (sectp); VEC_safe_push (dwarf2_section_info_def, dwo_sections->types, &type_section); @@ -10614,10 +10928,9 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu, { struct objfile *objfile = dwarf2_per_objfile->objfile; struct dwo_file *dwo_file; - bfd *dbfd; struct cleanup *cleanups; - dbfd = open_dwo_file (dwo_name, comp_dir); + gdb_bfd_ref_ptr dbfd (open_dwo_file (dwo_name, comp_dir)); if (dbfd == NULL) { if (dwarf_read_debug) @@ -10627,16 +10940,17 @@ open_and_init_dwo_file (struct dwarf2_per_cu_data *per_cu, dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file); dwo_file->dwo_name = dwo_name; dwo_file->comp_dir = comp_dir; - dwo_file->dbfd = dbfd; + dwo_file->dbfd = dbfd.release (); cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file); - bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections); + bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections, + &dwo_file->sections); - dwo_file->cu = create_dwo_cu (dwo_file); + create_cus_hash_table (*dwo_file, dwo_file->sections.info, dwo_file->cus); - dwo_file->tus = create_debug_types_hash_table (dwo_file, - dwo_file->sections.types); + create_debug_types_hash_table (dwo_file, dwo_file->sections.types, + dwo_file->tus); discard_cleanups (cleanups); @@ -10654,7 +10968,7 @@ static void dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) { - struct dwp_file *dwp_file = dwp_file_ptr; + struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr; const struct dwop_section_names *names = &dwop_section_names; unsigned int elf_section_nr = elf_section_data (sectp)->this_idx; @@ -10666,17 +10980,17 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp, /* Look for specific sections that we need. */ if (section_is_p (sectp->name, &names->str_dwo)) { - dwp_file->sections.str.s.asection = sectp; + dwp_file->sections.str.s.section = sectp; dwp_file->sections.str.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->cu_index)) { - dwp_file->sections.cu_index.s.asection = sectp; + dwp_file->sections.cu_index.s.section = sectp; dwp_file->sections.cu_index.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->tu_index)) { - dwp_file->sections.tu_index.s.asection = sectp; + dwp_file->sections.tu_index.s.section = sectp; dwp_file->sections.tu_index.size = bfd_get_section_size (sectp); } } @@ -10689,7 +11003,7 @@ dwarf2_locate_common_dwp_sections (bfd *abfd, asection *sectp, static void dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) { - struct dwp_file *dwp_file = dwp_file_ptr; + struct dwp_file *dwp_file = (struct dwp_file *) dwp_file_ptr; const struct dwop_section_names *names = &dwop_section_names; unsigned int elf_section_nr = elf_section_data (sectp)->this_idx; @@ -10701,42 +11015,42 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) /* Look for specific sections that we need. */ if (section_is_p (sectp->name, &names->abbrev_dwo)) { - dwp_file->sections.abbrev.s.asection = sectp; + dwp_file->sections.abbrev.s.section = sectp; dwp_file->sections.abbrev.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->info_dwo)) { - dwp_file->sections.info.s.asection = sectp; + dwp_file->sections.info.s.section = sectp; dwp_file->sections.info.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->line_dwo)) { - dwp_file->sections.line.s.asection = sectp; + dwp_file->sections.line.s.section = sectp; dwp_file->sections.line.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->loc_dwo)) { - dwp_file->sections.loc.s.asection = sectp; + dwp_file->sections.loc.s.section = sectp; dwp_file->sections.loc.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->macinfo_dwo)) { - dwp_file->sections.macinfo.s.asection = sectp; + dwp_file->sections.macinfo.s.section = sectp; dwp_file->sections.macinfo.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->macro_dwo)) { - dwp_file->sections.macro.s.asection = sectp; + dwp_file->sections.macro.s.section = sectp; dwp_file->sections.macro.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->str_offsets_dwo)) { - dwp_file->sections.str_offsets.s.asection = sectp; + dwp_file->sections.str_offsets.s.section = sectp; dwp_file->sections.str_offsets.size = bfd_get_section_size (sectp); } else if (section_is_p (sectp->name, &names->types_dwo)) { - dwp_file->sections.types.s.asection = sectp; + dwp_file->sections.types.s.section = sectp; dwp_file->sections.types.size = bfd_get_section_size (sectp); } } @@ -10746,7 +11060,7 @@ dwarf2_locate_v2_dwp_sections (bfd *abfd, asection *sectp, void *dwp_file_ptr) static hashval_t hash_dwp_loaded_cutus (const void *item) { - const struct dwo_unit *dwo_unit = item; + const struct dwo_unit *dwo_unit = (const struct dwo_unit *) item; /* This drops the top 32 bits of the signature, but is ok for a hash. */ return dwo_unit->signature; @@ -10757,8 +11071,8 @@ hash_dwp_loaded_cutus (const void *item) static int eq_dwp_loaded_cutus (const void *a, const void *b) { - const struct dwo_unit *dua = a; - const struct dwo_unit *dub = b; + const struct dwo_unit *dua = (const struct dwo_unit *) a; + const struct dwo_unit *dub = (const struct dwo_unit *) b; return dua->signature == dub->signature; } @@ -10783,12 +11097,11 @@ allocate_dwp_loaded_cutus_table (struct objfile *objfile) Upon success, the canonicalized path of the file is stored in the bfd, same as symfile_bfd_open. */ -static bfd * +static gdb_bfd_ref_ptr open_dwp_file (const char *file_name) { - bfd *abfd; - - abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/); + gdb_bfd_ref_ptr abfd (try_open_dwop_file (file_name, 1 /*is_dwp*/, + 1 /*search_cwd*/)); if (abfd != NULL) return abfd; @@ -10821,44 +11134,53 @@ open_and_init_dwp_file (void) { struct objfile *objfile = dwarf2_per_objfile->objfile; struct dwp_file *dwp_file; - char *dwp_name; - bfd *dbfd; - struct cleanup *cleanups; /* Try to find first .dwp for the binary file before any symbolic links resolving. */ - dwp_name = xstrprintf ("%s.dwp", objfile->original_name); - cleanups = make_cleanup (xfree, dwp_name); - dbfd = open_dwp_file (dwp_name); + /* If the objfile is a debug file, find the name of the real binary + file and get the name of dwp file from there. */ + std::string dwp_name; + if (objfile->separate_debug_objfile_backlink != NULL) + { + struct objfile *backlink = objfile->separate_debug_objfile_backlink; + const char *backlink_basename = lbasename (backlink->original_name); + + dwp_name = ldirname (objfile->original_name) + SLASH_STRING + backlink_basename; + } + else + dwp_name = objfile->original_name; + + dwp_name += ".dwp"; + + gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name.c_str ())); if (dbfd == NULL && strcmp (objfile->original_name, objfile_name (objfile)) != 0) { /* Try to find .dwp for the binary file after gdb_realpath resolving. */ - dwp_name = xstrprintf ("%s.dwp", objfile_name (objfile)); - make_cleanup (xfree, dwp_name); - dbfd = open_dwp_file (dwp_name); + dwp_name = objfile_name (objfile); + dwp_name += ".dwp"; + dbfd = open_dwp_file (dwp_name.c_str ()); } if (dbfd == NULL) { if (dwarf_read_debug) - fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name); - do_cleanups (cleanups); + fprintf_unfiltered (gdb_stdlog, "DWP file not found: %s\n", dwp_name.c_str ()); return NULL; } dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file); - dwp_file->name = bfd_get_filename (dbfd); - dwp_file->dbfd = dbfd; - do_cleanups (cleanups); + dwp_file->name = bfd_get_filename (dbfd.get ()); + dwp_file->dbfd = dbfd.release (); /* +1: section 0 is unused */ - dwp_file->num_sections = bfd_count_sections (dbfd) + 1; + dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1; dwp_file->elf_sections = OBSTACK_CALLOC (&objfile->objfile_obstack, dwp_file->num_sections, asection *); - bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file); + bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_common_dwp_sections, + dwp_file); dwp_file->cus = create_dwp_hash_table (dwp_file, 0); @@ -10873,12 +11195,13 @@ open_and_init_dwp_file (void) error (_("Dwarf Error: DWP file CU version %s doesn't match" " TU version %s [in DWP file %s]"), pulongest (dwp_file->cus->version), - pulongest (dwp_file->tus->version), dwp_name); + pulongest (dwp_file->tus->version), dwp_name.c_str ()); } dwp_file->version = dwp_file->cus->version; if (dwp_file->version == 2) - bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file); + bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_v2_dwp_sections, + dwp_file); dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile); dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile); @@ -10976,7 +11299,7 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit, *dwo_file_slot = open_and_init_dwo_file (this_unit, dwo_name, comp_dir); } /* NOTE: This will be NULL if unable to open the file. */ - dwo_file = *dwo_file_slot; + dwo_file = (struct dwo_file *) *dwo_file_slot; if (dwo_file != NULL) { @@ -10988,12 +11311,17 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit, memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu)); find_dwo_cutu.signature = signature; - dwo_cutu = htab_find (dwo_file->tus, &find_dwo_cutu); + dwo_cutu + = (struct dwo_unit *) htab_find (dwo_file->tus, &find_dwo_cutu); } - else if (!is_debug_types && dwo_file->cu) + else if (!is_debug_types && dwo_file->cus) { - if (signature == dwo_file->cu->signature) - dwo_cutu = dwo_file->cu; + struct dwo_unit find_dwo_cutu; + + memset (&find_dwo_cutu, 0, sizeof (find_dwo_cutu)); + find_dwo_cutu.signature = signature; + dwo_cutu = (struct dwo_unit *)htab_find (dwo_file->cus, + &find_dwo_cutu); } if (dwo_cutu != NULL) @@ -11036,7 +11364,7 @@ lookup_dwo_cutu (struct dwarf2_per_cu_data *this_unit, kind, dwo_name, hex_string (signature), dwp_text != NULL ? dwp_text : "", this_unit->is_debug_types ? "TU" : "CU", - this_unit->offset.sect_off, objfile_name (objfile)); + to_underlying (this_unit->sect_off), objfile_name (objfile)); do_cleanups (cleanups); } @@ -11120,8 +11448,6 @@ queue_and_load_all_dwo_tus (struct dwarf2_per_cu_data *per_cu) static void free_dwo_file (struct dwo_file *dwo_file, struct objfile *objfile) { - int ix; - struct dwarf2_section_info *section; /* Note: dbfd is NULL for virtual DWO files. */ gdb_bfd_unref (dwo_file->dbfd); @@ -11216,7 +11542,8 @@ 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.sect_off, origin_die->offset.sect_off); + to_underlying (die->sect_off), + to_underlying (origin_die->sect_off)); child_die = die->child; die_children_count = 0; @@ -11225,7 +11552,7 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) child_die = sibling_die (child_die); die_children_count++; } - offsets = xmalloc (sizeof (*offsets) * die_children_count); + offsets = XNEWVEC (sect_offset, die_children_count); cleanups = make_cleanup (xfree, offsets); offsets_end = offsets; @@ -11237,11 +11564,12 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) struct dwarf2_cu *child_origin_cu; /* We are trying to process concrete instance entries: - DW_TAG_GNU_call_site DIEs indeed have a DW_AT_abstract_origin tag, but + DW_TAG_call_site DIEs indeed have a DW_AT_abstract_origin tag, but it's not relevant to our analysis here. i.e. detecting DIEs that are present in the abstract instance but not referenced in the concrete one. */ - if (child_die->tag == DW_TAG_GNU_call_site) + if (child_die->tag == DW_TAG_call_site + || child_die->tag == DW_TAG_GNU_call_site) continue; /* For each CHILD_DIE, find the corresponding child of @@ -11270,25 +11598,27 @@ 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.sect_off, - child_origin_die->offset.sect_off); + "different tags"), + to_underlying (child_die->sect_off), + to_underlying (child_origin_die->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.sect_off, - child_origin_die->offset.sect_off); + "different parents"), + to_underlying (child_die->sect_off), + to_underlying (child_origin_die->sect_off)); else - *offsets_end++ = child_origin_die->offset; + *offsets_end++ = child_origin_die->sect_off; } } qsort (offsets, offsets_end - offsets, sizeof (*offsets), unsigned_int_compar); for (offsetp = offsets + 1; offsetp < offsets_end; offsetp++) - if (offsetp[-1].sect_off == offsetp->sect_off) + if (offsetp[-1] == *offsetp) complaint (&symfile_complaints, _("Multiple children of DIE 0x%x refer " "to DIE 0x%x as their abstract origin"), - die->offset.sect_off, offsetp->sect_off); + to_underlying (die->sect_off), to_underlying (*offsetp)); offsetp = offsets; origin_child_die = origin_die->child; @@ -11296,10 +11626,10 @@ inherit_abstract_dies (struct die_info *die, struct dwarf2_cu *cu) { /* Is ORIGIN_CHILD_DIE referenced by any of the DIE children? */ while (offsetp < offsets_end - && offsetp->sect_off < origin_child_die->offset.sect_off) + && *offsetp < origin_child_die->sect_off) offsetp++; if (offsetp >= offsets_end - || offsetp->sect_off > origin_child_die->offset.sect_off) + || *offsetp > origin_child_die->sect_off) { /* Found that ORIGIN_CHILD_DIE is really not referenced. Check whether we're already processing ORIGIN_CHILD_DIE. @@ -11356,19 +11686,20 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { complaint (&symfile_complaints, _("missing name for subprogram DIE at %d"), - die->offset.sect_off); + to_underlying (die->sect_off)); return; } /* Ignore functions with missing or invalid low and high pc attributes. */ - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) + if (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL) + <= PC_BOUNDS_INVALID) { attr = dwarf2_attr (die, DW_AT_external, cu); if (!attr || !DW_UNSND (attr)) complaint (&symfile_complaints, _("cannot get low and high bounds " "for subprogram DIE at %d"), - die->offset.sect_off); + to_underlying (die->sect_off)); return; } @@ -11398,6 +11729,16 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) if (attr) dwarf2_symbol_mark_computed (attr, newobj->name, cu, 1); + /* If there is a location for the static link, record it. */ + newobj->static_link = NULL; + attr = dwarf2_attr (die, DW_AT_static_link, cu); + if (attr) + { + newobj->static_link + = XOBNEW (&objfile->objfile_obstack, struct dynamic_prop); + attr_to_dynamic_prop (attr, die, cu, newobj->static_link); + } + cu->list_in_scope = &local_symbols; if (die->child != NULL) @@ -11449,12 +11790,13 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) newobj = pop_context (); /* Make a block for the local symbols within. */ block = finish_block (newobj->name, &local_symbols, newobj->old_blocks, - lowpc, highpc); + newobj->static_link, lowpc, highpc); /* For C++, set the block's scope. */ if ((cu->language == language_cplus || cu->language == language_fortran - || cu->language == language_d) + || cu->language == language_d + || cu->language == language_rust) && cu->processing_has_namespace_info) block_set_scope (block, determine_prefix (die, cu), &objfile->objfile_obstack); @@ -11471,9 +11813,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) templ_func->n_template_arguments = VEC_length (symbolp, template_args); templ_func->template_arguments - = obstack_alloc (&objfile->objfile_obstack, - (templ_func->n_template_arguments - * sizeof (struct symbol *))); + = XOBNEWVEC (&objfile->objfile_obstack, struct symbol *, + templ_func->n_template_arguments); memcpy (templ_func->template_arguments, VEC_address (symbolp, template_args), (templ_func->n_template_arguments * sizeof (struct symbol *))); @@ -11485,7 +11826,7 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) when we finish processing a function scope, we may need to go back to building a containing block's symbol lists. */ local_symbols = newobj->locals; - using_directives = newobj->using_directives; + local_using_directives = newobj->local_using_directives; /* If we've finished processing a top-level function, subsequent symbols go in the file symbol list. */ @@ -11513,8 +11854,20 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) as multiple lexical blocks? Handling children in a sane way would be nasty. Might be easier to properly extend generic blocks to describe ranges. */ - if (!dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) - return; + switch (dwarf2_get_pc_bounds (die, &lowpc, &highpc, cu, NULL)) + { + case PC_BOUNDS_NOT_PRESENT: + /* DW_TAG_lexical_block has no attributes, process its children as if + there was no wrapping by that DW_TAG_lexical_block. + GCC does no longer produces such DWARF since GCC r224161. */ + for (child_die = die->child; + child_die != NULL && child_die->tag; + child_die = sibling_die (child_die)) + process_die (child_die, cu); + return; + case PC_BOUNDS_INVALID: + return; + } lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); highpc = gdbarch_adjust_dwarf2_addr (gdbarch, highpc + baseaddr); @@ -11531,10 +11884,10 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) inherit_abstract_dies (die, cu); newobj = pop_context (); - if (local_symbols != NULL || using_directives != NULL) + if (local_symbols != NULL || local_using_directives != NULL) { struct block *block - = finish_block (0, &local_symbols, newobj->old_blocks, + = finish_block (0, &local_symbols, newobj->old_blocks, NULL, newobj->start_addr, highpc); /* Note that recording ranges after traversing children, as we @@ -11550,10 +11903,10 @@ read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu) dwarf2_record_block_ranges (die, block, baseaddr, cu); } local_symbols = newobj->locals; - using_directives = newobj->using_directives; + local_using_directives = newobj->local_using_directives; } -/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab. */ +/* Read in DW_TAG_call_site and insert it to CU->call_site_htab. */ static void read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) @@ -11569,13 +11922,19 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - attr = dwarf2_attr (die, DW_AT_low_pc, cu); + attr = dwarf2_attr (die, DW_AT_call_return_pc, cu); + if (attr == NULL) + { + /* This was a pre-DWARF-5 GNU extension alias + for DW_AT_call_return_pc. */ + attr = dwarf2_attr (die, DW_AT_low_pc, cu); + } if (!attr) { complaint (&symfile_complaints, - _("missing DW_AT_low_pc for DW_TAG_GNU_call_site " + _("missing DW_AT_call_return_pc for DW_TAG_call_site " "DIE 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (objfile)); + to_underlying (die->sect_off), objfile_name (objfile)); return; } pc = attr_value_as_address (attr) + baseaddr; @@ -11590,9 +11949,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) if (*slot != NULL) { complaint (&symfile_complaints, - _("Duplicate PC %s for DW_TAG_GNU_call_site " + _("Duplicate PC %s for DW_TAG_call_site " "DIE 0x%x [in module %s]"), - paddress (gdbarch, pc), die->offset.sect_off, + paddress (gdbarch, pc), to_underlying (die->sect_off), objfile_name (objfile)); return; } @@ -11603,12 +11962,13 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) for (child_die = die->child; child_die && child_die->tag; child_die = sibling_die (child_die)) { - if (child_die->tag != DW_TAG_GNU_call_site_parameter) + if (child_die->tag != DW_TAG_call_site_parameter + && child_die->tag != DW_TAG_GNU_call_site_parameter) { complaint (&symfile_complaints, - _("Tag %d is not DW_TAG_GNU_call_site_parameter in " - "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), - child_die->tag, child_die->offset.sect_off, + _("Tag %d is not DW_TAG_call_site_parameter in " + "DW_TAG_call_site child DIE 0x%x [in module %s]"), + child_die->tag, to_underlying (child_die->sect_off), objfile_name (objfile)); continue; } @@ -11616,15 +11976,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) nparams++; } - call_site = obstack_alloc (&objfile->objfile_obstack, - (sizeof (*call_site) - + (sizeof (*call_site->parameter) - * (nparams - 1)))); + call_site + = ((struct call_site *) + obstack_alloc (&objfile->objfile_obstack, + sizeof (*call_site) + + (sizeof (*call_site->parameter) * (nparams - 1)))); *slot = call_site; memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter)); call_site->pc = pc; - if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu)) + if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu) + || dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu)) { struct die_info *func_die; @@ -11634,10 +11996,12 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) && func_die->tag != DW_TAG_subroutine_type; func_die = func_die->parent); - /* DW_AT_GNU_all_call_sites is a superset - of DW_AT_GNU_all_tail_call_sites. */ + /* DW_AT_call_all_calls is a superset + of DW_AT_call_all_tail_calls. */ if (func_die + && !dwarf2_flag_true_p (func_die, DW_AT_call_all_calls, cu) && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu) + && !dwarf2_flag_true_p (func_die, DW_AT_call_all_tail_calls, cu) && !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu)) { /* TYPE_TAIL_CALL_LIST is not interesting in functions where it is @@ -11665,15 +12029,22 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) } else complaint (&symfile_complaints, - _("Cannot find function owning DW_TAG_GNU_call_site " + _("Cannot find function owning DW_TAG_call_site " "DIE 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (objfile)); + to_underlying (die->sect_off), objfile_name (objfile)); } } - attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu); + attr = dwarf2_attr (die, DW_AT_call_target, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu); if (attr == NULL) - attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); + attr = dwarf2_attr (die, DW_AT_call_origin, cu); + if (attr == NULL) + { + /* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin. */ + attr = dwarf2_attr (die, DW_AT_abstract_origin, cu); + } SET_FIELD_DWARF_BLOCK (call_site->target, NULL); if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0)) /* Keep NULL DWARF_BLOCK. */; @@ -11681,7 +12052,7 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) { struct dwarf2_locexpr_baton *dlbaton; - dlbaton = obstack_alloc (&objfile->objfile_obstack, sizeof (*dlbaton)); + dlbaton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton); dlbaton->data = DW_BLOCK (attr)->data; dlbaton->size = DW_BLOCK (attr)->size; dlbaton->per_cu = cu->per_cu; @@ -11697,23 +12068,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) gdb_assert (target_cu->objfile == objfile); if (die_is_declaration (target_die, target_cu)) { - const char *target_physname = NULL; - struct attribute *target_attr; + const char *target_physname; /* Prefer the mangled name; otherwise compute the demangled one. */ - target_attr = dwarf2_attr (target_die, DW_AT_linkage_name, target_cu); - if (target_attr == NULL) - target_attr = dwarf2_attr (target_die, DW_AT_MIPS_linkage_name, - target_cu); - if (target_attr != NULL && DW_STRING (target_attr) != NULL) - target_physname = DW_STRING (target_attr); - else + target_physname = dw2_linkage_name (target_die, target_cu); + if (target_physname == NULL) target_physname = dwarf2_physname (NULL, target_die, target_cu); if (target_physname == NULL) complaint (&symfile_complaints, - _("DW_AT_GNU_call_site_target target DIE has invalid " + _("DW_AT_call_target target DIE has invalid " "physname, for referencing DIE 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (objfile)); + to_underlying (die->sect_off), objfile_name (objfile)); else SET_FIELD_PHYSNAME (call_site->target, target_physname); } @@ -11722,11 +12087,12 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) CORE_ADDR lowpc; /* DW_AT_entry_pc should be preferred. */ - if (!dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)) + if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL) + <= PC_BOUNDS_INVALID) complaint (&symfile_complaints, - _("DW_AT_GNU_call_site_target target DIE has invalid " + _("DW_AT_call_target target DIE has invalid " "low pc, for referencing DIE 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (objfile)); + to_underlying (die->sect_off), objfile_name (objfile)); else { lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr); @@ -11736,9 +12102,9 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) } else complaint (&symfile_complaints, - _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither " + _("DW_TAG_call_site DW_AT_call_target is neither " "block nor reference, for DIE 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (objfile)); + to_underlying (die->sect_off), objfile_name (objfile)); call_site->per_cu = cu->per_cu; @@ -11749,7 +12115,8 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) struct call_site_parameter *parameter; struct attribute *loc, *origin; - if (child_die->tag != DW_TAG_GNU_call_site_parameter) + if (child_die->tag != DW_TAG_call_site_parameter + && child_die->tag != DW_TAG_GNU_call_site_parameter) { /* Already printed the complaint above. */ continue; @@ -11760,37 +12127,43 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) /* 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. */ + register is contained in DW_AT_call_value. */ loc = dwarf2_attr (child_die, DW_AT_location, cu); - origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu); + origin = dwarf2_attr (child_die, DW_AT_call_parameter, cu); + if (origin == NULL) + { + /* This was a pre-DWARF-5 GNU extension alias + for DW_AT_call_parameter. */ + origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu); + } if (loc == NULL && origin != NULL && attr_form_is_ref (origin)) { - sect_offset offset; - parameter->kind = CALL_SITE_PARAMETER_PARAM_OFFSET; - offset = dwarf2_get_ref_die_offset (origin); - if (!offset_in_cu_p (&cu->header, offset)) + + sect_offset sect_off + = (sect_offset) dwarf2_get_ref_die_offset (origin); + if (!offset_in_cu_p (&cu->header, sect_off)) { /* 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 (objfile)); + _("DW_AT_call_parameter offset is not in CU for " + "DW_TAG_call_site child DIE 0x%x [in module %s]"), + to_underlying (child_die->sect_off), + objfile_name (objfile)); continue; } - parameter->u.param_offset.cu_off = (offset.sect_off - - cu->header.offset.sect_off); + parameter->u.param_cu_off + = (cu_offset) (sect_off - cu->header.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.sect_off, objfile_name (objfile)); + "DW_TAG_call_site child DIE 0x%x [in module %s]"), + to_underlying (child_die->sect_off), objfile_name (objfile)); continue; } else @@ -11808,20 +12181,24 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) 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 " + "DW_TAG_call_site child DIE 0x%x " "[in module %s]"), - child_die->offset.sect_off, objfile_name (objfile)); + to_underlying (child_die->sect_off), + objfile_name (objfile)); continue; } } - attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu); + attr = dwarf2_attr (child_die, DW_AT_call_value, cu); + if (attr == NULL) + attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu); if (!attr_form_is_block (attr)) { complaint (&symfile_complaints, - _("No DW_FORM_block* DW_AT_GNU_call_site_value for " - "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), - child_die->offset.sect_off, objfile_name (objfile)); + _("No DW_FORM_block* DW_AT_call_value for " + "DW_TAG_call_site child DIE 0x%x [in module %s]"), + to_underlying (child_die->sect_off), + objfile_name (objfile)); continue; } parameter->value = DW_BLOCK (attr)->data; @@ -11832,14 +12209,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) parameter->data_value_size = 0; call_site->parameter_count++; - attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu); + attr = dwarf2_attr (child_die, DW_AT_call_data_value, cu); + if (attr == NULL) + attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu); if (attr) { if (!attr_form_is_block (attr)) complaint (&symfile_complaints, - _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for " - "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"), - child_die->offset.sect_off, objfile_name (objfile)); + _("No DW_FORM_block* DW_AT_call_data_value for " + "DW_TAG_call_site child DIE 0x%x [in module %s]"), + to_underlying (child_die->sect_off), + objfile_name (objfile)); else { parameter->data_value = DW_BLOCK (attr)->data; @@ -11849,14 +12229,17 @@ read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu) } } -/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. - Return 1 if the attributes are present and valid, otherwise, return 0. - If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */ +/* Call CALLBACK from DW_AT_ranges attribute value OFFSET + reading .debug_rnglists. + Callback's type should be: + void (CORE_ADDR range_beginning, CORE_ADDR range_end) + Return true if the attributes are present and valid, otherwise, + return false. */ -static int -dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, - CORE_ADDR *high_return, struct dwarf2_cu *cu, - struct partial_symtab *ranges_pst) +template +static bool +dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu, + Callback &&callback) { struct objfile *objfile = cu->objfile; struct gdbarch *gdbarch = get_objfile_arch (objfile); @@ -11869,38 +12252,196 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, int found_base; unsigned int dummy; const gdb_byte *buffer; - CORE_ADDR marker; - int low_set; CORE_ADDR low = 0; CORE_ADDR high = 0; CORE_ADDR baseaddr; + bool overflow = false; found_base = cu->base_known; base = cu->base_address; - dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); - if (offset >= dwarf2_per_objfile->ranges.size) + dwarf2_read_section (objfile, &dwarf2_per_objfile->rnglists); + if (offset >= dwarf2_per_objfile->rnglists.size) { complaint (&symfile_complaints, _("Offset %d out of bounds for DW_AT_ranges attribute"), offset); - return 0; + return false; } - buffer = dwarf2_per_objfile->ranges.buffer + offset; + buffer = dwarf2_per_objfile->rnglists.buffer + offset; - /* Read in the largest possible address. */ - marker = read_address (obfd, buffer, cu, &dummy); - if ((marker & mask) == mask) + baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); + + while (1) { - /* If we found the largest possible address, then - read the base address. */ - base = read_address (obfd, buffer + addr_size, cu, &dummy); - buffer += 2 * addr_size; - offset += 2 * addr_size; - found_base = 1; + /* Initialize it due to a false compiler warning. */ + CORE_ADDR range_beginning = 0, range_end = 0; + const gdb_byte *buf_end = (dwarf2_per_objfile->rnglists.buffer + + dwarf2_per_objfile->rnglists.size); + unsigned int bytes_read; + + if (buffer == buf_end) + { + overflow = true; + break; + } + const auto rlet = static_cast(*buffer++); + switch (rlet) + { + case DW_RLE_end_of_list: + break; + case DW_RLE_base_address: + if (buffer + cu->header.addr_size > buf_end) + { + overflow = true; + break; + } + base = read_address (obfd, buffer, cu, &bytes_read); + found_base = 1; + buffer += bytes_read; + break; + case DW_RLE_start_length: + if (buffer + cu->header.addr_size > buf_end) + { + overflow = true; + break; + } + range_beginning = read_address (obfd, buffer, cu, &bytes_read); + buffer += bytes_read; + range_end = (range_beginning + + read_unsigned_leb128 (obfd, buffer, &bytes_read)); + buffer += bytes_read; + if (buffer > buf_end) + { + overflow = true; + break; + } + break; + case DW_RLE_offset_pair: + range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read); + buffer += bytes_read; + if (buffer > buf_end) + { + overflow = true; + break; + } + range_end = read_unsigned_leb128 (obfd, buffer, &bytes_read); + buffer += bytes_read; + if (buffer > buf_end) + { + overflow = true; + break; + } + break; + case DW_RLE_start_end: + if (buffer + 2 * cu->header.addr_size > buf_end) + { + overflow = true; + break; + } + range_beginning = read_address (obfd, buffer, cu, &bytes_read); + buffer += bytes_read; + range_end = read_address (obfd, buffer, cu, &bytes_read); + buffer += bytes_read; + break; + default: + complaint (&symfile_complaints, + _("Invalid .debug_rnglists data (no base address)")); + return false; + } + if (rlet == DW_RLE_end_of_list || overflow) + break; + if (rlet == DW_RLE_base_address) + continue; + + if (!found_base) + { + /* We have no valid base address for the ranges + data. */ + complaint (&symfile_complaints, + _("Invalid .debug_rnglists data (no base address)")); + return false; + } + + if (range_beginning > range_end) + { + /* Inverted range entries are invalid. */ + complaint (&symfile_complaints, + _("Invalid .debug_rnglists data (inverted range)")); + return false; + } + + /* Empty range entries have no effect. */ + if (range_beginning == range_end) + continue; + + range_beginning += base; + range_end += base; + + /* A not-uncommon case of bad debug info. + Don't pollute the addrmap with bad data. */ + if (range_beginning + baseaddr == 0 + && !dwarf2_per_objfile->has_section_at_zero) + { + complaint (&symfile_complaints, + _(".debug_rnglists entry has start address of zero" + " [in module %s]"), objfile_name (objfile)); + continue; + } + + callback (range_beginning, range_end); + } + + if (overflow) + { + complaint (&symfile_complaints, + _("Offset %d is not terminated " + "for DW_AT_ranges attribute"), + offset); + return false; } - low_set = 0; + return true; +} + +/* Call CALLBACK from DW_AT_ranges attribute value OFFSET reading .debug_ranges. + Callback's type should be: + void (CORE_ADDR range_beginning, CORE_ADDR range_end) + Return 1 if the attributes are present and valid, otherwise, return 0. */ + +template +static int +dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu, + Callback &&callback) +{ + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + struct comp_unit_head *cu_header = &cu->header; + bfd *obfd = objfile->obfd; + unsigned int addr_size = cu_header->addr_size; + CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1)); + /* Base address selection entry. */ + CORE_ADDR base; + int found_base; + unsigned int dummy; + const gdb_byte *buffer; + CORE_ADDR baseaddr; + + if (cu_header->version >= 5) + return dwarf2_rnglists_process (offset, cu, callback); + + found_base = cu->base_known; + base = cu->base_address; + + dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); + if (offset >= dwarf2_per_objfile->ranges.size) + { + complaint (&symfile_complaints, + _("Offset %d out of bounds for DW_AT_ranges attribute"), + offset); + return 0; + } + buffer = dwarf2_per_objfile->ranges.buffer + offset; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); @@ -11924,9 +12465,9 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, the base address. Check for a base address here. */ if ((range_beginning & mask) == mask) { - /* If we found the largest possible address, then - read the base address. */ - base = read_address (obfd, buffer + addr_size, cu, &dummy); + /* If we found the largest possible address, then we already + have the base address in range_end. */ + base = range_end; found_base = 1; continue; } @@ -11966,6 +12507,33 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, continue; } + callback (range_beginning, range_end); + } + + return 1; +} + +/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET. + Return 1 if the attributes are present and valid, otherwise, return 0. + If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */ + +static int +dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, + CORE_ADDR *high_return, struct dwarf2_cu *cu, + struct partial_symtab *ranges_pst) +{ + struct objfile *objfile = cu->objfile; + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets, + SECT_OFF_TEXT (objfile)); + int low_set = 0; + CORE_ADDR low = 0; + CORE_ADDR high = 0; + int retval; + + retval = dwarf2_ranges_process (offset, cu, + [&] (CORE_ADDR range_beginning, CORE_ADDR range_end) + { if (ranges_pst != NULL) { CORE_ADDR lowpc; @@ -11996,7 +12564,9 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, if (range_end > high) high = range_end; } - } + }); + if (!retval) + return 0; if (! low_set) /* If the first entry is an end-of-list marker, the range @@ -12010,11 +12580,11 @@ dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return, return 1; } -/* 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. */ +/* Get low and high pc attributes from a die. See enum pc_bounds_kind + definition for the return value. *LOWPC and *HIGHPC are set iff + neither PC_BOUNDS_NOT_PRESENT nor PC_BOUNDS_INVALID are returned. */ -static int +static enum pc_bounds_kind dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, CORE_ADDR *highpc, struct dwarf2_cu *cu, struct partial_symtab *pst) @@ -12023,7 +12593,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, struct attribute *attr_high; CORE_ADDR low = 0; CORE_ADDR high = 0; - int ret = 0; + enum pc_bounds_kind ret; attr_high = dwarf2_attr (die, DW_AT_high_pc, cu); if (attr_high) @@ -12038,10 +12608,10 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, } else /* Found high w/o low attribute. */ - return 0; + return PC_BOUNDS_INVALID; /* Found consecutive range of addresses. */ - ret = 1; + ret = PC_BOUNDS_HIGH_LOW; } else { @@ -12060,15 +12630,17 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, /* Value of the DW_AT_ranges attribute is the offset in the .debug_ranges section. */ if (!dwarf2_ranges_read (ranges_offset, &low, &high, cu, pst)) - return 0; + return PC_BOUNDS_INVALID; /* Found discontinuous range of addresses. */ - ret = -1; + ret = PC_BOUNDS_RANGES; } + else + return PC_BOUNDS_NOT_PRESENT; } /* read_partial_die has also the strict LOW < HIGH requirement. */ if (high <= low) - return 0; + return PC_BOUNDS_INVALID; /* When using the GNU linker, .gnu.linkonce. sections are used to eliminate duplicate copies of functions and vtables and such. @@ -12079,7 +12651,7 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc, If this is a discarded function, mark the pc bounds as invalid, so that GDB will ignore it. */ if (low == 0 && !dwarf2_per_objfile->has_section_at_zero) - return 0; + return PC_BOUNDS_INVALID; *lowpc = low; if (highpc) @@ -12100,10 +12672,10 @@ dwarf2_get_subprogram_pc_bounds (struct die_info *die, CORE_ADDR low, high; struct die_info *child = die->child; - if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL)) + if (dwarf2_get_pc_bounds (die, &low, &high, cu, NULL) >= PC_BOUNDS_RANGES) { - *lowpc = min (*lowpc, low); - *highpc = max (*highpc, high); + *lowpc = std::min (*lowpc, low); + *highpc = std::max (*highpc, high); } /* If the language does not allow nested subprograms (either inside @@ -12137,7 +12709,8 @@ get_scope_pc_bounds (struct die_info *die, CORE_ADDR best_high = (CORE_ADDR) 0; CORE_ADDR current_low, current_high; - if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL)) + if (dwarf2_get_pc_bounds (die, ¤t_low, ¤t_high, cu, NULL) + >= PC_BOUNDS_RANGES) { best_low = current_low; best_high = current_high; @@ -12166,8 +12739,8 @@ get_scope_pc_bounds (struct die_info *die, if (current_low != ((CORE_ADDR) -1)) { - best_low = min (best_low, current_low); - best_high = max (best_high, current_high); + best_low = std::min (best_low, current_low); + best_high = std::max (best_high, current_high); } break; default: @@ -12245,79 +12818,15 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block, CORE_ADDR base = cu->base_address; int base_known = cu->base_known; - dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges); - if (offset >= dwarf2_per_objfile->ranges.size) - { - complaint (&symfile_complaints, - _("Offset %lu out of bounds for DW_AT_ranges attribute"), - offset); - return; - } - buffer = dwarf2_per_objfile->ranges.buffer + offset; - - for (;;) - { - unsigned int bytes_read; - CORE_ADDR start, end; - - start = read_address (obfd, buffer, cu, &bytes_read); - buffer += bytes_read; - end = read_address (obfd, buffer, cu, &bytes_read); - buffer += bytes_read; - - /* Did we find the end of the range list? */ - if (start == 0 && end == 0) - break; - - /* Did we find a base address selection entry? */ - else if ((start & base_select_mask) == base_select_mask) - { - base = end; - base_known = 1; - } - - /* We found an ordinary address range. */ - else - { - if (!base_known) - { - complaint (&symfile_complaints, - _("Invalid .debug_ranges data " - "(no base address)")); - return; - } - - if (start > end) - { - /* Inverted range entries are invalid. */ - complaint (&symfile_complaints, - _("Invalid .debug_ranges data " - "(inverted range)")); - return; - } - - /* Empty range entries have no effect. */ - if (start == end) - continue; - - start += base + baseaddr; - end += base + baseaddr; - - /* A not-uncommon case of bad debug info. - Don't pollute the addrmap with bad data. */ - if (start == 0 && !dwarf2_per_objfile->has_section_at_zero) - { - complaint (&symfile_complaints, - _(".debug_ranges entry has start address of zero" - " [in module %s]"), objfile_name (objfile)); - continue; - } - - start = gdbarch_adjust_dwarf2_addr (gdbarch, start); - end = gdbarch_adjust_dwarf2_addr (gdbarch, end); - record_block_range (block, start, end - 1); - } - } + dwarf2_ranges_process (offset, cu, + [&] (CORE_ADDR start, CORE_ADDR end) + { + start += baseaddr; + end += baseaddr; + start = gdbarch_adjust_dwarf2_addr (gdbarch, start); + end = gdbarch_adjust_dwarf2_addr (gdbarch, end); + record_block_range (block, start, end - 1); + }); } } @@ -12327,7 +12836,6 @@ dwarf2_record_block_ranges (struct die_info *die, struct block *block, static void check_producer (struct dwarf2_cu *cu) { - const char *cs; int major, minor; if (cu->producer == NULL) @@ -12448,7 +12956,7 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, const char *fieldname = ""; /* Allocate a new field list entry and link it in. */ - new_field = (struct nextfield *) xmalloc (sizeof (struct nextfield)); + new_field = XNEW (struct nextfield); make_cleanup (xfree, new_field); memset (new_field, 0, sizeof (struct nextfield)); @@ -12550,6 +13058,10 @@ dwarf2_add_field (struct field_info *fip, struct die_info *die, - bit_offset - FIELD_BITSIZE (*fp))); } } + attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu); + if (attr != NULL) + SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp) + + dwarf2_get_attr_constant_value (attr, 0))); /* Get name of field. */ fieldname = dwarf2_name (die, cu); @@ -12627,14 +13139,11 @@ static void dwarf2_add_typedef (struct field_info *fip, struct die_info *die, struct dwarf2_cu *cu) { - struct objfile *objfile = cu->objfile; struct typedef_field_list *new_field; - struct attribute *attr; struct typedef_field *fp; - char *fieldname = ""; /* Allocate a new field list entry and link it in. */ - new_field = xzalloc (sizeof (*new_field)); + new_field = XCNEW (struct typedef_field_list); make_cleanup (xfree, new_field); gdb_assert (die->tag == DW_TAG_typedef); @@ -12693,7 +13202,7 @@ dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type, unsigned char *pointer; ALLOCATE_CPLUS_STRUCT_TYPE (type); - pointer = TYPE_ALLOC (type, num_bytes); + pointer = (unsigned char *) TYPE_ALLOC (type, num_bytes); TYPE_FIELD_VIRTUAL_BITS (type) = pointer; B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->nbaseclasses); TYPE_N_BASECLASSES (type) = fip->nbaseclasses; @@ -12838,7 +13347,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, /* Create a new member function field and chain it to the field list entry. */ - new_fnfield = (struct nextfnfield *) xmalloc (sizeof (struct nextfnfield)); + new_fnfield = XNEW (struct nextfnfield); make_cleanup (xfree, new_fnfield); memset (new_fnfield, 0, sizeof (struct nextfnfield)); new_fnfield->next = flp->head; @@ -12849,7 +13358,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, fnp = &new_fnfield->fnfield; /* Delay processing of the physname until later. */ - if (cu->language == language_cplus || cu->language == language_java) + if (cu->language == language_cplus) { add_to_method_list (type, i, flp->length - 1, fieldname, die, cu); @@ -12897,7 +13406,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, /* Get accessibility. */ attr = dwarf2_attr (die, DW_AT_accessibility, cu); if (attr) - accessibility = DW_UNSND (attr); + accessibility = (enum dwarf_access_attribute) DW_UNSND (attr); else accessibility = dwarf2_default_access_attribute (die, cu); switch (accessibility) @@ -12938,13 +13447,6 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, && DW_BLOCK (attr)->data[0] == DW_OP_deref_size && DW_BLOCK (attr)->data[1] == cu->header.addr_size)) { - struct dwarf_block blk; - int offset; - - offset = (DW_BLOCK (attr)->data[0] == DW_OP_deref - ? 1 : 2); - blk.size = DW_BLOCK (attr)->size - offset; - blk.data = DW_BLOCK (attr)->data + offset; fnp->voffset = decode_locdesc (DW_BLOCK (attr), cu); if ((fnp->voffset % cu->header.addr_size) != 0) dwarf2_complex_location_expr_complaint (); @@ -12966,7 +13468,7 @@ dwarf2_add_member_fn (struct field_info *fip, struct die_info *die, complaint (&symfile_complaints, _("cannot determine context for virtual member " "function \"%s\" (offset %d)"), - fieldname, die->offset.sect_off); + fieldname, to_underlying (die->sect_off)); } else { @@ -12994,7 +13496,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.sect_off); + fieldname, to_underlying (die->sect_off)); ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_CPLUS_DYNAMIC (type) = 1; } @@ -13042,11 +13544,8 @@ is_vtable_name (const char *name, struct dwarf2_cu *cu) static const char vptr[] = "_vptr"; static const char vtable[] = "vtable"; - /* Look for the C++ and Java forms of the vtable. */ - if ((cu->language == language_java - && startswith (name, vtable)) - || (startswith (name, vptr) - && is_cplus_marker (name[sizeof (vptr) - 1]))) + /* Look for the C++ form of the vtable. */ + if (startswith (name, vptr) && is_cplus_marker (name[sizeof (vptr) - 1])) return 1; return 0; @@ -13149,8 +13648,8 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) if (name != NULL) { if (cu->language == language_cplus - || cu->language == language_java - || cu->language == language_d) + || cu->language == language_d + || cu->language == language_rust) { const char *full_name = dwarf2_full_name (name, die, cu); @@ -13193,7 +13692,20 @@ read_structure_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr) { - TYPE_LENGTH (type) = DW_UNSND (attr); + if (attr_form_is_constant (attr)) + TYPE_LENGTH (type) = DW_UNSND (attr); + else + { + /* For the moment, dynamic type sizes are not supported + by GDB's struct type. The actual size is determined + on-demand when resolving the type of a given object, + so set the type's length to zero for now. Otherwise, + we record an expression as the length, and that expression + could lead to a very large value, which could eventually + lead to us trying to allocate that much memory when creating + a value of that type. */ + TYPE_LENGTH (type) = 0; + } } else { @@ -13266,10 +13778,18 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) } else if (child_die->tag == DW_TAG_subprogram) { - /* C++ member function. */ - dwarf2_add_member_fn (&fi, child_die, type, cu); - } - else if (child_die->tag == DW_TAG_inheritance) + /* Rust doesn't have member functions in the C++ sense. + However, it does emit ordinary functions as children + of a struct DIE. */ + if (cu->language == language_rust) + read_func_scope (child_die, cu); + else + { + /* C++ member function. */ + dwarf2_add_member_fn (&fi, child_die, type, cu); + } + } + else if (child_die->tag == DW_TAG_inheritance) { /* C++ base class field. */ dwarf2_add_field (&fi, child_die, cu); @@ -13295,9 +13815,9 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) TYPE_N_TEMPLATE_ARGUMENTS (type) = VEC_length (symbolp, template_args); TYPE_TEMPLATE_ARGUMENTS (type) - = obstack_alloc (&objfile->objfile_obstack, - (TYPE_N_TEMPLATE_ARGUMENTS (type) - * sizeof (struct symbol *))); + = XOBNEWVEC (&objfile->objfile_obstack, + struct symbol *, + TYPE_N_TEMPLATE_ARGUMENTS (type)); memcpy (TYPE_TEMPLATE_ARGUMENTS (type), VEC_address (symbolp, template_args), (TYPE_N_TEMPLATE_ARGUMENTS (type) @@ -13384,7 +13904,8 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) ALLOCATE_CPLUS_STRUCT_TYPE (type); TYPE_TYPEDEF_FIELD_ARRAY (type) - = TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i); + = ((struct typedef_field *) + TYPE_ALLOC (type, sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * i)); TYPE_TYPEDEF_FIELD_COUNT (type) = i; /* Reverse the list order to keep the debug info elements order. */ @@ -13400,9 +13921,6 @@ process_structure_scope (struct die_info *die, struct dwarf2_cu *cu) } do_cleanups (back_to); - - if (HAVE_CPLUS_STRUCT (type)) - TYPE_CPLUS_REALLY_JAVA (type) = cu->language == language_java; } quirk_gcc_member_function_pointer (type, objfile); @@ -13448,15 +13966,12 @@ update_enumeration_type_from_children (struct die_info *die, struct type *type, struct dwarf2_cu *cu) { - struct obstack obstack; struct die_info *child_die; int unsigned_enum = 1; int flag_enum = 1; ULONGEST mask = 0; - struct cleanup *old_chain; - obstack_init (&obstack); - old_chain = make_cleanup_obstack_free (&obstack); + auto_obstack obstack; for (child_die = die->child; child_die != NULL && child_die->tag; @@ -13501,8 +14016,6 @@ update_enumeration_type_from_children (struct die_info *die, TYPE_UNSIGNED (type) = 1; if (flag_enum) TYPE_FLAG_ENUM (type) = 1; - - do_cleanups (old_chain); } /* Given a DW_AT_enumeration_type die, set its type. We do not @@ -13668,8 +14181,8 @@ process_enumeration_scope (struct die_info *die, struct dwarf2_cu *cu) struct signatured_type *sig_type; sig_type = (struct signatured_type *) cu->per_cu; - gdb_assert (sig_type->type_offset_in_section.sect_off != 0); - if (sig_type->type_offset_in_section.sect_off != die->offset.sect_off) + gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0); + if (sig_type->type_offset_in_section != die->sect_off) return; } @@ -13812,7 +14325,8 @@ read_array_order (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_ordering, cu); - if (attr) return DW_SND (attr); + if (attr) + return (enum dwarf_array_dim_ordering) DW_SND (attr); /* GNU F77 is a special case, as at 08/2004 array type info is the opposite order to the dwarf2 specification, but data is still @@ -13890,8 +14404,7 @@ mark_common_block_symbol_computed (struct symbol *sym, gdb_assert (attr_form_is_block (member_loc) || attr_form_is_constant (member_loc)); - baton = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_locexpr_baton)); + baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton); baton->per_cu = cu->per_cu; gdb_assert (baton->per_cu); @@ -13905,11 +14418,11 @@ mark_common_block_symbol_computed (struct symbol *sym, else baton->size += DW_BLOCK (member_loc)->size; - ptr = obstack_alloc (&objfile->objfile_obstack, baton->size); + ptr = (gdb_byte *) obstack_alloc (&objfile->objfile_obstack, baton->size); baton->data = ptr; *ptr++ = DW_OP_call4; - cu_off = common_die->offset.sect_off - cu->per_cu->offset.sect_off; + cu_off = common_die->sect_off - cu->per_cu->sect_off; store_unsigned_integer (ptr, 4, byte_order, cu_off); ptr += 4; @@ -13981,7 +14494,9 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu) size = (sizeof (struct common_block) + (n_entries - 1) * sizeof (struct symbol *)); - common_block = obstack_alloc (&objfile->objfile_obstack, size); + common_block + = (struct common_block *) obstack_alloc (&objfile->objfile_obstack, + size); memset (common_block->contents, 0, n_entries * sizeof (struct symbol *)); common_block->n_entries = 0; @@ -14010,7 +14525,7 @@ read_common_block (struct die_info *die, struct dwarf2_cu *cu) _("Variable in common block has " "DW_AT_data_member_location " "- DIE at 0x%x [in module %s]"), - child_die->offset.sect_off, + to_underlying (child_die->sect_off), objfile_name (cu->objfile)); if (attr_form_is_section_offset (member_loc)) @@ -14067,15 +14582,13 @@ read_namespace_type (struct die_info *die, struct dwarf2_cu *cu) previous_prefix, name, 0, cu); /* Create the type. */ - type = init_type (TYPE_CODE_NAMESPACE, 0, 0, NULL, - objfile); - TYPE_NAME (type) = name; + type = init_type (objfile, TYPE_CODE_NAMESPACE, 0, name); TYPE_TAG_NAME (type) = TYPE_NAME (type); return set_die_type (die, type, cu); } -/* Read a C++ namespace. */ +/* Read a namespace scope. */ static void read_namespace (struct die_info *die, struct dwarf2_cu *cu) @@ -14099,8 +14612,10 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu) { const char *previous_prefix = determine_prefix (die, cu); - cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL, - NULL, NULL, 0, &objfile->objfile_obstack); + std::vector excludes; + add_using_directive (using_directives (cu->language), + previous_prefix, TYPE_NAME (type), NULL, + NULL, excludes, 0, &objfile->objfile_obstack); } } @@ -14131,8 +14646,8 @@ 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.sect_off); - type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile); + to_underlying (die->sect_off)); + type = init_type (objfile, TYPE_CODE_MODULE, 0, module_name); /* determine_prefix uses TYPE_TAG_NAME. */ TYPE_TAG_NAME (type) = TYPE_NAME (type); @@ -14176,10 +14691,8 @@ namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *cu) { /* We don't use dwarf2_name here so that we can detect the absence of a name -> anonymous namespace. */ - struct attribute *attr = dwarf2_attr (die, DW_AT_name, cu); + name = dwarf2_string_attr (die, DW_AT_name, cu); - if (attr != NULL) - name = DW_STRING (attr); if (name != NULL) break; } @@ -14293,16 +14806,19 @@ read_tag_ptr_to_member_type (struct die_info *die, struct dwarf2_cu *cu) return set_die_type (die, type, cu); } -/* Extract all information from a DW_TAG_reference_type DIE and add to +/* Extract all information from a DW_TAG_{rvalue_,}reference_type DIE and add to the user defined type vector. */ static struct type * -read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu) +read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu, + enum type_code refcode) { struct comp_unit_head *cu_header = &cu->header; struct type *type, *target_type; struct attribute *attr; + gdb_assert (refcode == TYPE_CODE_REF || refcode == TYPE_CODE_RVALUE_REF); + target_type = die_type (die, cu); /* The die_type call above may have already set the type for this DIE. */ @@ -14310,7 +14826,7 @@ read_tag_reference_type (struct die_info *die, struct dwarf2_cu *cu) if (type) return type; - type = lookup_reference_type (target_type); + type = lookup_reference_type (target_type, refcode); attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr) { @@ -14608,19 +15124,7 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) if (attr) TYPE_FIELD_ARTIFICIAL (ftype, iparams) = DW_UNSND (attr); else - { - TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0; - - /* GCC/43521: In java, the formal parameter - "this" is sometimes not marked with DW_AT_artificial. */ - if (cu->language == language_java) - { - const char *name = dwarf2_name (child_die, cu); - - if (name && !strcmp (name, "this")) - TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 1; - } - } + TYPE_FIELD_ARTIFICIAL (ftype, iparams) = 0; arg_type = die_type (child_die, cu); /* RealView does not mark THIS as const, which the testsuite @@ -14672,9 +15176,8 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu) 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) = name; + this_type = init_type (objfile, TYPE_CODE_TYPEDEF, 0, name); + TYPE_TARGET_STUB (this_type) = 1; set_die_type (die, this_type, cu); target_type = die_type (die, cu); if (target_type != this_type) @@ -14686,12 +15189,33 @@ read_typedef (struct die_info *die, struct dwarf2_cu *cu) complaint (&symfile_complaints, _("Self-referential DW_TAG_typedef " "- DIE at 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (objfile)); + to_underlying (die->sect_off), objfile_name (objfile)); TYPE_TARGET_TYPE (this_type) = NULL; } return this_type; } +/* Allocate a floating-point type of size BITS and name NAME. Pass NAME_HINT + (which may be different from NAME) to the architecture back-end to allow + it to guess the correct format if necessary. */ + +static struct type * +dwarf2_init_float_type (struct objfile *objfile, int bits, const char *name, + const char *name_hint) +{ + struct gdbarch *gdbarch = get_objfile_arch (objfile); + const struct floatformat **format; + struct type *type; + + format = gdbarch_floatformat_for_type (gdbarch, name_hint, bits); + if (format) + type = init_float_type (objfile, bits, name, format); + else + type = init_type (objfile, TYPE_CODE_ERROR, bits / TARGET_CHAR_BIT, name); + + return type; +} + /* Find a representation of a given base type and install it in the TYPE field of the die. */ @@ -14701,11 +15225,8 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) struct objfile *objfile = cu->objfile; struct type *type; struct attribute *attr; - int encoding = 0, size = 0; + int encoding = 0, bits = 0; const char *name; - enum type_code code = TYPE_CODE_INT; - int type_flags = 0; - struct type *target_type = NULL; attr = dwarf2_attr (die, DW_AT_encoding, cu); if (attr) @@ -14715,7 +15236,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr) { - size = DW_UNSND (attr); + bits = DW_UNSND (attr) * TARGET_CHAR_BIT; } name = dwarf2_name (die, cu); if (!name) @@ -14728,61 +15249,77 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) { case DW_ATE_address: /* Turn DW_ATE_address into a void * pointer. */ - code = TYPE_CODE_PTR; - type_flags |= TYPE_FLAG_UNSIGNED; - target_type = init_type (TYPE_CODE_VOID, 1, 0, NULL, objfile); + type = init_type (objfile, TYPE_CODE_VOID, 1, NULL); + type = init_pointer_type (objfile, bits, name, type); break; case DW_ATE_boolean: - code = TYPE_CODE_BOOL; - type_flags |= TYPE_FLAG_UNSIGNED; + type = init_boolean_type (objfile, bits, 1, name); break; case DW_ATE_complex_float: - code = TYPE_CODE_COMPLEX; - target_type = init_type (TYPE_CODE_FLT, size / 2, 0, NULL, objfile); + type = dwarf2_init_float_type (objfile, bits / 2, NULL, name); + type = init_complex_type (objfile, name, type); break; case DW_ATE_decimal_float: - code = TYPE_CODE_DECFLOAT; + type = init_decfloat_type (objfile, bits, name); break; case DW_ATE_float: - code = TYPE_CODE_FLT; + type = dwarf2_init_float_type (objfile, bits, name, name); break; case DW_ATE_signed: + type = init_integer_type (objfile, bits, 0, name); break; case DW_ATE_unsigned: - type_flags |= TYPE_FLAG_UNSIGNED; if (cu->language == language_fortran && name && startswith (name, "character(")) - code = TYPE_CODE_CHAR; + type = init_character_type (objfile, bits, 1, name); + else + type = init_integer_type (objfile, bits, 1, name); break; case DW_ATE_signed_char: if (cu->language == language_ada || cu->language == language_m2 || cu->language == language_pascal || cu->language == language_fortran) - code = TYPE_CODE_CHAR; + type = init_character_type (objfile, bits, 0, name); + else + type = init_integer_type (objfile, bits, 0, name); break; case DW_ATE_unsigned_char: if (cu->language == language_ada || cu->language == language_m2 || cu->language == language_pascal - || cu->language == language_fortran) - code = TYPE_CODE_CHAR; - type_flags |= TYPE_FLAG_UNSIGNED; + || cu->language == language_fortran + || cu->language == language_rust) + type = init_character_type (objfile, bits, 1, name); + else + type = init_integer_type (objfile, bits, 1, name); break; case DW_ATE_UTF: - /* We just treat this as an integer and then recognize the - type by name elsewhere. */ + { + gdbarch *arch = get_objfile_arch (objfile); + + if (bits == 16) + type = builtin_type (arch)->builtin_char16; + else if (bits == 32) + type = builtin_type (arch)->builtin_char32; + else + { + complaint (&symfile_complaints, + _("unsupported DW_ATE_UTF bit size: '%d'"), + bits); + type = init_integer_type (objfile, bits, 1, name); + } + return set_die_type (die, type, cu); + } break; default: complaint (&symfile_complaints, _("unsupported DW_AT_encoding: '%s'"), dwarf_type_encoding_name (encoding)); + type = init_type (objfile, TYPE_CODE_ERROR, + bits / TARGET_CHAR_BIT, name); break; } - type = init_type (code, size, type_flags, NULL, objfile); - TYPE_NAME (type) = name; - TYPE_TARGET_TYPE (type) = target_type; - if (name && strcmp (name, "char") == 0) TYPE_NOSIGN (type) = 1; @@ -14805,7 +15342,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, if (attr_form_is_block (attr)) { - baton = obstack_alloc (obstack, sizeof (*baton)); + baton = XOBNEW (obstack, struct dwarf2_property_baton); baton->referenced_type = NULL; baton->locexpr.per_cu = cu->per_cu; baton->locexpr.size = DW_BLOCK (attr)->size; @@ -14833,7 +15370,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, case DW_AT_location: if (attr_form_is_section_offset (target_attr)) { - baton = obstack_alloc (obstack, sizeof (*baton)); + baton = XOBNEW (obstack, struct dwarf2_property_baton); baton->referenced_type = die_type (target_die, target_cu); fill_in_loclist_baton (cu, &baton->loclist, target_attr); prop->data.baton = baton; @@ -14842,7 +15379,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, } else if (attr_form_is_block (target_attr)) { - baton = obstack_alloc (obstack, sizeof (*baton)); + baton = XOBNEW (obstack, struct dwarf2_property_baton); baton->referenced_type = die_type (target_die, target_cu); baton->locexpr.per_cu = cu->per_cu; baton->locexpr.size = DW_BLOCK (target_attr)->size; @@ -14866,7 +15403,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, &offset)) return 0; - baton = obstack_alloc (obstack, sizeof (*baton)); + baton = XOBNEW (obstack, struct dwarf2_property_baton); baton->referenced_type = read_type_die (target_die->parent, target_cu); baton->offset_info.offset = offset; @@ -14936,8 +15473,8 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) low_default_is_valid = 1; break; case language_d: - case language_java: case language_objc: + case language_rust: low.data.const_val = 0; low_default_is_valid = (cu->header.version >= 4); break; @@ -14959,7 +15496,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) else if (!low_default_is_valid) complaint (&symfile_complaints, _("Missing DW_AT_lower_bound " "- DIE at 0x%x [in module %s]"), - die->offset.sect_off, objfile_name (cu->objfile)); + to_underlying (die->sect_off), objfile_name (cu->objfile)); attr = dwarf2_attr (die, DW_AT_upper_bound, cu); if (!attr_to_dynamic_prop (attr, die, cu, &high)) @@ -15021,7 +15558,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) the bounds as signed, and thus sign-extend their values, when the base type is signed. */ negative_mask = - (LONGEST) -1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1); + -((LONGEST) 1 << (TYPE_LENGTH (base_type) * TARGET_CHAR_BIT - 1)); if (low.kind == PROP_CONST && !TYPE_UNSIGNED (base_type) && (low.data.const_val & negative_mask)) low.data.const_val |= negative_mask; @@ -15061,7 +15598,7 @@ read_unspecified_type (struct die_info *die, struct dwarf2_cu *cu) /* For now, we only support the C meaning of an unspecified type: void. */ - type = init_type (TYPE_CODE_VOID, 0, 0, NULL, cu->objfile); + type = init_type (cu->objfile, TYPE_CODE_VOID, 0, NULL); TYPE_NAME (type) = dwarf2_name (die, cu); return set_die_type (die, type, cu); @@ -15181,13 +15718,12 @@ read_full_die_1 (const struct die_reader_specs *reader, int *has_children, int num_extra_attrs) { 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.sect_off = info_ptr - reader->buffer; + sect_offset sect_off = (sect_offset) (info_ptr - reader->buffer); abbrev_number = read_unsigned_leb128 (abfd, info_ptr, &bytes_read); info_ptr += bytes_read; if (!abbrev_number) @@ -15204,7 +15740,7 @@ read_full_die_1 (const struct die_reader_specs *reader, bfd_get_filename (abfd)); die = dwarf_alloc_die (cu, abbrev->num_attrs + num_extra_attrs); - die->offset = offset; + die->sect_off = sect_off; die->tag = abbrev->tag; die->abbrev = abbrev_number; @@ -15263,9 +15799,9 @@ 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)); + abbrev = XOBNEW (&abbrev_table->abbrev_obstack, struct abbrev_info); memset (abbrev, 0, sizeof (struct abbrev_info)); + return abbrev; } @@ -15309,7 +15845,7 @@ abbrev_table_lookup_abbrev (const struct abbrev_table *abbrev_table, static struct abbrev_table * abbrev_table_read_table (struct dwarf2_section_info *section, - sect_offset offset) + sect_offset sect_off) { struct objfile *objfile = dwarf2_per_objfile->objfile; bfd *abfd = get_section_bfd_owner (section); @@ -15322,21 +15858,21 @@ abbrev_table_read_table (struct dwarf2_section_info *section, unsigned int allocated_attrs; abbrev_table = XNEW (struct abbrev_table); - abbrev_table->offset = offset; + abbrev_table->sect_off = sect_off; obstack_init (&abbrev_table->abbrev_obstack); - abbrev_table->abbrevs = obstack_alloc (&abbrev_table->abbrev_obstack, - (ABBREV_HASH_SIZE - * sizeof (struct abbrev_info *))); + abbrev_table->abbrevs = + XOBNEWVEC (&abbrev_table->abbrev_obstack, struct abbrev_info *, + ABBREV_HASH_SIZE); 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_ptr = section->buffer + to_underlying (sect_off); abbrev_number = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); abbrev_ptr += bytes_read; allocated_attrs = ATTR_ALLOC_CHUNK; - cur_attrs = xmalloc (allocated_attrs * sizeof (struct attr_abbrev)); + cur_attrs = XNEWVEC (struct attr_abbrev, allocated_attrs); /* Loop until we reach an abbrev number of 0. */ while (abbrev_number) @@ -15345,37 +15881,54 @@ abbrev_table_read_table (struct dwarf2_section_info *section, /* read in abbrev header */ cur_abbrev->number = abbrev_number; - cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + cur_abbrev->tag + = (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); abbrev_ptr += bytes_read; cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr); abbrev_ptr += 1; /* now read in declarations */ - abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; - while (abbrev_name) + for (;;) { + LONGEST implicit_const; + + abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); + abbrev_ptr += bytes_read; + if (abbrev_form == DW_FORM_implicit_const) + { + implicit_const = read_signed_leb128 (abfd, abbrev_ptr, + &bytes_read); + abbrev_ptr += bytes_read; + } + else + { + /* Initialize it due to a false compiler warning. */ + implicit_const = -1; + } + + if (abbrev_name == 0) + break; + if (cur_abbrev->num_attrs == allocated_attrs) { allocated_attrs += ATTR_ALLOC_CHUNK; cur_attrs - = xrealloc (cur_attrs, (allocated_attrs - * sizeof (struct attr_abbrev))); + = XRESIZEVEC (struct attr_abbrev, cur_attrs, allocated_attrs); } - 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); - abbrev_ptr += bytes_read; - abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read); - abbrev_ptr += bytes_read; + cur_attrs[cur_abbrev->num_attrs].name + = (enum dwarf_attribute) abbrev_name; + cur_attrs[cur_abbrev->num_attrs].form + = (enum dwarf_form) abbrev_form; + cur_attrs[cur_abbrev->num_attrs].implicit_const = implicit_const; + ++cur_abbrev->num_attrs; } - cur_abbrev->attrs = obstack_alloc (&abbrev_table->abbrev_obstack, - (cur_abbrev->num_attrs - * sizeof (struct attr_abbrev))); + cur_abbrev->attrs = + XOBNEWVEC (&abbrev_table->abbrev_obstack, struct attr_abbrev, + cur_abbrev->num_attrs); memcpy (cur_abbrev->attrs, cur_attrs, cur_abbrev->num_attrs * sizeof (struct attr_abbrev)); @@ -15417,7 +15970,7 @@ abbrev_table_free (struct abbrev_table *abbrev_table) static void abbrev_table_free_cleanup (void *table_ptr) { - struct abbrev_table **abbrev_table_ptr = table_ptr; + struct abbrev_table **abbrev_table_ptr = (struct abbrev_table **) table_ptr; if (*abbrev_table_ptr != NULL) abbrev_table_free (*abbrev_table_ptr); @@ -15431,7 +15984,7 @@ 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); + abbrev_table_read_table (abbrev_section, cu->header.abbrev_sect_off); } /* Release the memory used by the abbrev table for a compilation unit. */ @@ -15439,7 +15992,7 @@ dwarf2_read_abbrevs (struct dwarf2_cu *cu, static void dwarf2_free_abbrev_table (void *ptr_to_cu) { - struct dwarf2_cu *cu = ptr_to_cu; + struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr_to_cu; if (cu->abbrev_table != NULL) abbrev_table_free (cu->abbrev_table); @@ -15511,8 +16064,7 @@ load_partial_dies (const struct die_reader_specs *reader, hashtab_obstack_allocate, dummy_obstack_deallocate); - part_die = obstack_alloc (&cu->comp_unit_obstack, - sizeof (struct partial_die_info)); + part_die = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info); while (1) { @@ -15617,7 +16169,7 @@ load_partial_dies (const struct die_reader_specs *reader, add_psymbol_to_list (part_die->name, strlen (part_die->name), 0, VAR_DOMAIN, LOC_TYPEDEF, &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); info_ptr = locate_pdi_sibling (reader, part_die, info_ptr); continue; } @@ -15634,7 +16186,7 @@ load_partial_dies (const struct die_reader_specs *reader, complaint (&symfile_complaints, _("DW_TAG_typedef has childen - GCC PR debug/47510 bug " "- DIE at 0x%x [in module %s]"), - part_die->offset.sect_off, objfile_name (objfile)); + to_underlying (part_die->sect_off), objfile_name (objfile)); /* If we're at the second level, and we're an enumerator, and our parent has no specification (meaning possibly lives in a @@ -15652,11 +16204,10 @@ load_partial_dies (const struct die_reader_specs *reader, else if (building_psymtab) add_psymbol_to_list (part_die->name, strlen (part_die->name), 0, VAR_DOMAIN, LOC_CONST, - (cu->language == language_cplus - || cu->language == language_java) + cu->language == language_cplus ? &objfile->global_psymbols : &objfile->static_psymbols, - 0, (CORE_ADDR) 0, cu->language, objfile); + 0, cu->language, objfile); info_ptr = locate_pdi_sibling (reader, part_die, info_ptr); continue; @@ -15708,12 +16259,12 @@ load_partial_dies (const struct die_reader_specs *reader, void **slot; slot = htab_find_slot_with_hash (cu->partial_dies, part_die, - part_die->offset.sect_off, INSERT); + to_underlying (part_die->sect_off), + INSERT); *slot = part_die; } - part_die = obstack_alloc (&cu->comp_unit_obstack, - sizeof (struct partial_die_info)); + part_die = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info); /* For some DIEs we want to follow their children (if any). For C we have no reason to follow the children of structures; for other @@ -15776,7 +16327,7 @@ read_partial_die (const struct die_reader_specs *reader, memset (part_die, 0, sizeof (struct partial_die_info)); - part_die->offset.sect_off = info_ptr - buffer; + part_die->sect_off = (sect_offset) (info_ptr - buffer); info_ptr += abbrev_len; @@ -15875,8 +16426,8 @@ read_partial_die (const struct die_reader_specs *reader, _("ignoring absolute DW_AT_sibling")); else { - unsigned int off = dwarf2_get_ref_die_offset (&attr).sect_off; - const gdb_byte *sibling_ptr = buffer + off; + sect_offset off = dwarf2_get_ref_die_offset (&attr); + const gdb_byte *sibling_ptr = buffer + to_underlying (off); if (sibling_ptr < info_ptr) complaint (&symfile_complaints, @@ -15899,18 +16450,18 @@ read_partial_die (const struct die_reader_specs *reader, to describe functions' calling conventions. However, because it's a necessary piece of information in - Fortran, and because DW_CC_program is the only piece of debugging - information whose definition refers to a 'main program' at all, - several compilers have begun marking Fortran main programs with - DW_CC_program --- even when those functions use the standard - calling conventions. - - So until DWARF specifies a way to provide this information and - compilers pick up the new representation, we'll support this - practice. */ + Fortran, and before DWARF 4 DW_CC_program was the only + piece of debugging information whose definition refers to + a 'main program' at all, several compilers marked Fortran + main programs with DW_CC_program --- even when those + functions use the standard calling conventions. + + Although DWARF now specifies a way to provide this + information, we support this practice for backward + compatibility. */ if (DW_UNSND (&attr) == DW_CC_program && cu->language == language_fortran) - set_objfile_main_name (objfile, part_die->name, language_fortran); + part_die->main_subprogram = 1; break; case DW_AT_inline: if (DW_UNSND (&attr) == DW_INL_inlined @@ -15921,12 +16472,16 @@ read_partial_die (const struct die_reader_specs *reader, case DW_AT_import: if (part_die->tag == DW_TAG_imported_unit) { - part_die->d.offset = dwarf2_get_ref_die_offset (&attr); + part_die->d.sect_off = dwarf2_get_ref_die_offset (&attr); part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz); } break; + case DW_AT_main_subprogram: + part_die->main_subprogram = DW_UNSND (&attr); + break; + default: break; } @@ -15953,7 +16508,7 @@ read_partial_die (const struct die_reader_specs *reader, _("DW_AT_low_pc %s is zero " "for DIE at 0x%x [in module %s]"), paddress (gdbarch, part_die->lowpc), - part_die->offset.sect_off, objfile_name (objfile)); + to_underlying (part_die->sect_off), objfile_name (objfile)); } /* dwarf2_get_pc_bounds has also the strict low < high requirement. */ else if (part_die->lowpc >= part_die->highpc) @@ -15965,7 +16520,8 @@ read_partial_die (const struct die_reader_specs *reader, "for DIE at 0x%x [in module %s]"), paddress (gdbarch, part_die->lowpc), paddress (gdbarch, part_die->highpc), - part_die->offset.sect_off, objfile_name (objfile)); + to_underlying (part_die->sect_off), + objfile_name (objfile)); } else part_die->has_pc_info = 1; @@ -15977,14 +16533,15 @@ read_partial_die (const struct die_reader_specs *reader, /* Find a cached partial DIE at OFFSET in CU. */ static struct partial_die_info * -find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu) +find_partial_die_in_comp_unit (sect_offset sect_off, 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.sect_off); + part_die.sect_off = sect_off; + lookup_die = ((struct partial_die_info *) + htab_find_with_hash (cu->partial_dies, &part_die, + to_underlying (sect_off))); return lookup_die; } @@ -15995,16 +16552,16 @@ find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu) DW_FORM_ref_sig8). */ static struct partial_die_info * -find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu) +find_partial_die (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; struct dwarf2_per_cu_data *per_cu = NULL; struct partial_die_info *pd = NULL; if (offset_in_dwz == cu->per_cu->is_dwz - && offset_in_cu_p (&cu->header, offset)) + && offset_in_cu_p (&cu->header, sect_off)) { - pd = find_partial_die_in_comp_unit (offset, cu); + pd = find_partial_die_in_comp_unit (sect_off, cu); if (pd != NULL) return pd; /* We missed recording what we needed. @@ -16016,19 +16573,19 @@ find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu) /* 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, + error (_("Dwarf Error: Type Unit at offset 0x%x contains" + " external reference to offset 0x%x [in module %s].\n"), + to_underlying (cu->header.sect_off), to_underlying (sect_off), bfd_get_filename (objfile->obfd)); } - per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz, + per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, objfile); if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL) load_partial_comp_unit (per_cu); per_cu->cu->last_used = 0; - pd = find_partial_die_in_comp_unit (offset, per_cu->cu); + pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu); } /* If we didn't find it, and not all dies have been loaded, @@ -16046,14 +16603,14 @@ find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu) set. */ load_partial_comp_unit (per_cu); - pd = find_partial_die_in_comp_unit (offset, per_cu->cu); + pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu); } if (pd == NULL) internal_error (__FILE__, __LINE__, _("could not find partial DIE 0x%x " "in cache [from module %s]\n"), - offset.sect_off, bfd_get_filename (objfile->obfd)); + to_underlying (sect_off), bfd_get_filename (objfile->obfd)); return pd; } @@ -16099,9 +16656,10 @@ guess_partial_die_structure_name (struct partial_die_info *struct_pdi, if (actual_class_name != NULL) { struct_pdi->name - = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, - actual_class_name, - strlen (actual_class_name)); + = ((const char *) + obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, + actual_class_name, + strlen (actual_class_name))); xfree (actual_class_name); } break; @@ -16186,8 +16744,9 @@ fixup_partial_die (struct partial_die_info *part_die, base = demangled; part_die->name - = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, - base, strlen (base)); + = ((const char *) + obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, + base, strlen (base))); xfree (demangled); } } @@ -16200,7 +16759,7 @@ fixup_partial_die (struct partial_die_info *part_die, static const gdb_byte * read_attribute_value (const struct die_reader_specs *reader, struct attribute *attr, unsigned form, - const gdb_byte *info_ptr) + LONGEST implicit_const, const gdb_byte *info_ptr) { struct dwarf2_cu *cu = reader->cu; struct objfile *objfile = cu->objfile; @@ -16210,7 +16769,7 @@ read_attribute_value (const struct die_reader_specs *reader, unsigned int bytes_read; struct dwarf_block *blk; - attr->form = form; + attr->form = (enum dwarf_form) form; switch (form) { case DW_FORM_ref_addr: @@ -16258,6 +16817,13 @@ read_attribute_value (const struct die_reader_specs *reader, DW_UNSND (attr) = read_8_bytes (abfd, info_ptr); info_ptr += 8; break; + case DW_FORM_data16: + blk = dwarf_alloc_block (cu); + blk->size = 16; + blk->data = read_n_bytes (abfd, info_ptr, 16); + info_ptr += 16; + DW_BLOCK (attr) = blk; + break; case DW_FORM_sec_offset: DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read); info_ptr += bytes_read; @@ -16277,6 +16843,16 @@ read_attribute_value (const struct die_reader_specs *reader, break; } /* FALLTHROUGH */ + case DW_FORM_line_strp: + if (!cu->per_cu->is_dwz) + { + DW_STRING (attr) = read_indirect_line_string (abfd, info_ptr, + cu_header, &bytes_read); + DW_STRING_IS_CANONICAL (attr) = 0; + info_ptr += bytes_read; + break; + } + /* FALLTHROUGH */ case DW_FORM_GNU_strp_alt: { struct dwz_file *dwz = dwarf2_get_dwz_file (); @@ -16325,22 +16901,22 @@ read_attribute_value (const struct die_reader_specs *reader, info_ptr += bytes_read; break; case DW_FORM_ref1: - DW_UNSND (attr) = (cu->header.offset.sect_off + DW_UNSND (attr) = (to_underlying (cu->header.sect_off) + read_1_byte (abfd, info_ptr)); info_ptr += 1; break; case DW_FORM_ref2: - DW_UNSND (attr) = (cu->header.offset.sect_off + DW_UNSND (attr) = (to_underlying (cu->header.sect_off) + read_2_bytes (abfd, info_ptr)); info_ptr += 2; break; case DW_FORM_ref4: - DW_UNSND (attr) = (cu->header.offset.sect_off + DW_UNSND (attr) = (to_underlying (cu->header.sect_off) + read_4_bytes (abfd, info_ptr)); info_ptr += 4; break; case DW_FORM_ref8: - DW_UNSND (attr) = (cu->header.offset.sect_off + DW_UNSND (attr) = (to_underlying (cu->header.sect_off) + read_8_bytes (abfd, info_ptr)); info_ptr += 8; break; @@ -16349,14 +16925,23 @@ read_attribute_value (const struct die_reader_specs *reader, info_ptr += 8; break; case DW_FORM_ref_udata: - DW_UNSND (attr) = (cu->header.offset.sect_off + DW_UNSND (attr) = (to_underlying (cu->header.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 (reader, attr, form, info_ptr); + if (form == DW_FORM_implicit_const) + { + implicit_const = read_signed_leb128 (abfd, info_ptr, &bytes_read); + info_ptr += bytes_read; + } + info_ptr = read_attribute_value (reader, attr, form, implicit_const, + info_ptr); + break; + case DW_FORM_implicit_const: + DW_SND (attr) = implicit_const; break; case DW_FORM_GNU_addr_index: if (reader->dwo_file == NULL) @@ -16426,7 +17011,8 @@ read_attribute (const struct die_reader_specs *reader, const gdb_byte *info_ptr) { attr->name = abbrev->name; - return read_attribute_value (reader, attr, abbrev->form, info_ptr); + return read_attribute_value (reader, attr, abbrev->form, + abbrev->implicit_const, info_ptr); } /* Read dwarf information from a buffer. */ @@ -16679,21 +17265,47 @@ read_direct_string (bfd *abfd, const gdb_byte *buf, return (const char *) buf; } +/* Return pointer to string at section SECT offset STR_OFFSET with error + reporting strings FORM_NAME and SECT_NAME. */ + static const char * -read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset) -{ - dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str); - if (dwarf2_per_objfile->str.buffer == NULL) - error (_("DW_FORM_strp used without .debug_str section [in module %s]"), - bfd_get_filename (abfd)); - if (str_offset >= dwarf2_per_objfile->str.size) - error (_("DW_FORM_strp pointing outside of " - ".debug_str section [in module %s]"), - bfd_get_filename (abfd)); +read_indirect_string_at_offset_from (bfd *abfd, LONGEST str_offset, + struct dwarf2_section_info *sect, + const char *form_name, + const char *sect_name) +{ + dwarf2_read_section (dwarf2_per_objfile->objfile, sect); + if (sect->buffer == NULL) + error (_("%s used without %s section [in module %s]"), + form_name, sect_name, bfd_get_filename (abfd)); + if (str_offset >= sect->size) + error (_("%s pointing outside of %s section [in module %s]"), + form_name, sect_name, bfd_get_filename (abfd)); gdb_assert (HOST_CHAR_BIT == 8); - if (dwarf2_per_objfile->str.buffer[str_offset] == '\0') + if (sect->buffer[str_offset] == '\0') return NULL; - return (const char *) (dwarf2_per_objfile->str.buffer + str_offset); + return (const char *) (sect->buffer + str_offset); +} + +/* Return pointer to string at .debug_str offset STR_OFFSET. */ + +static const char * +read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset) +{ + return read_indirect_string_at_offset_from (abfd, str_offset, + &dwarf2_per_objfile->str, + "DW_FORM_strp", ".debug_str"); +} + +/* Return pointer to string at .debug_line_str offset STR_OFFSET. */ + +static const char * +read_indirect_line_string_at_offset (bfd *abfd, LONGEST str_offset) +{ + return read_indirect_string_at_offset_from (abfd, str_offset, + &dwarf2_per_objfile->line_str, + "DW_FORM_line_strp", + ".debug_line_str"); } /* Read a string at offset STR_OFFSET in the .debug_str section from @@ -16720,6 +17332,10 @@ read_indirect_string_from_dwz (struct dwz_file *dwz, LONGEST str_offset) return (const char *) (dwz->str.buffer + str_offset); } +/* Return pointer to string at .debug_str offset as read from BUF. + BUF is assumed to be in a compilation unit described by CU_HEADER. + Return *BYTES_READ_PTR count of bytes read from BUF. */ + static const char * read_indirect_string (bfd *abfd, const gdb_byte *buf, const struct comp_unit_head *cu_header, @@ -16730,19 +17346,32 @@ read_indirect_string (bfd *abfd, const gdb_byte *buf, return read_indirect_string_at_offset (abfd, str_offset); } -static ULONGEST +/* Return pointer to string at .debug_line_str offset as read from BUF. + BUF is assumed to be in a compilation unit described by CU_HEADER. + Return *BYTES_READ_PTR count of bytes read from BUF. */ + +static const char * +read_indirect_line_string (bfd *abfd, const gdb_byte *buf, + const struct comp_unit_head *cu_header, + unsigned int *bytes_read_ptr) +{ + LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr); + + return read_indirect_line_string_at_offset (abfd, str_offset); +} + +ULONGEST read_unsigned_leb128 (bfd *abfd, const gdb_byte *buf, - unsigned int *bytes_read_ptr) + unsigned int *bytes_read_ptr) { ULONGEST result; unsigned int num_read; - int i, shift; + int shift; unsigned char byte; result = 0; shift = 0; num_read = 0; - i = 0; while (1) { byte = bfd_get_8 (abfd, buf); @@ -16764,13 +17393,12 @@ read_signed_leb128 (bfd *abfd, const gdb_byte *buf, unsigned int *bytes_read_ptr) { LONGEST result; - int i, shift, num_read; + int shift, num_read; unsigned char byte; result = 0; shift = 0; num_read = 0; - i = 0; while (1) { byte = bfd_get_8 (abfd, buf); @@ -16936,16 +17564,16 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index) dwarf2_read_section (objfile, str_offsets_section); if (str_section->buffer == NULL) error (_("%s used without .debug_str.dwo section" - " in CU at offset 0x%lx [in module %s]"), - form_name, (long) cu->header.offset.sect_off, objf_name); + " in CU at offset 0x%x [in module %s]"), + form_name, to_underlying (cu->header.sect_off), objf_name); if (str_offsets_section->buffer == NULL) error (_("%s used without .debug_str_offsets.dwo section" - " in CU at offset 0x%lx [in module %s]"), - form_name, (long) cu->header.offset.sect_off, objf_name); + " in CU at offset 0x%x [in module %s]"), + form_name, to_underlying (cu->header.sect_off), objf_name); if (str_index * cu->header.offset_size >= str_offsets_section->size) error (_("%s pointing outside of .debug_str_offsets.dwo" - " section in CU at offset 0x%lx [in module %s]"), - form_name, (long) cu->header.offset.sect_off, objf_name); + " section in CU at offset 0x%x [in module %s]"), + form_name, to_underlying (cu->header.sect_off), objf_name); info_ptr = (str_offsets_section->buffer + str_index * cu->header.offset_size); if (cu->header.offset_size == 4) @@ -16954,8 +17582,8 @@ read_str_index (const struct die_reader_specs *reader, ULONGEST str_index) str_offset = bfd_get_64 (abfd, info_ptr); if (str_offset >= str_section->size) error (_("Offset from %s pointing outside of" - " .debug_str.dwo section in CU at offset 0x%lx [in module %s]"), - form_name, (long) cu->header.offset.sect_off, objf_name); + " .debug_str.dwo section in CU at offset 0x%x [in module %s]"), + form_name, to_underlying (cu->header.sect_off), objf_name); return (const char *) (str_section->buffer + str_offset); } @@ -16987,6 +17615,7 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu) case DW_LANG_UPC: cu->language = language_c; break; + case DW_LANG_Java: case DW_LANG_C_plus_plus: case DW_LANG_C_plus_plus_11: case DW_LANG_C_plus_plus_14: @@ -17008,9 +17637,6 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu) case DW_LANG_Mips_Assembler: cu->language = language_asm; break; - case DW_LANG_Java: - cu->language = language_java; - break; case DW_LANG_Ada83: case DW_LANG_Ada95: cu->language = language_ada; @@ -17024,6 +17650,10 @@ set_cu_language (unsigned int lang, struct dwarf2_cu *cu) case DW_LANG_ObjC: cu->language = language_objc; break; + case DW_LANG_Rust: + case DW_LANG_Rust_old: + cu->language = language_rust; + break; case DW_LANG_Cobol74: case DW_LANG_Cobol85: default: @@ -17079,6 +17709,35 @@ dwarf2_attr_no_follow (struct die_info *die, unsigned int name) return NULL; } +/* Return the string associated with a string-typed attribute, or NULL if it + is either not found or is of an incorrect type. */ + +static const char * +dwarf2_string_attr (struct die_info *die, unsigned int name, struct dwarf2_cu *cu) +{ + struct attribute *attr; + const char *str = NULL; + + attr = dwarf2_attr (die, name, cu); + + if (attr != NULL) + { + if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp + || attr->form == DW_FORM_string + || attr->form == DW_FORM_GNU_str_index + || attr->form == DW_FORM_GNU_strp_alt) + str = DW_STRING (attr); + else + complaint (&symfile_complaints, + _("string type expected for attribute %s for " + "DIE at 0x%x in module %s"), + dwarf_attr_name (name), to_underlying (die->sect_off), + objfile_name (cu->objfile)); + } + + return str; +} + /* Return non-zero iff the attribute NAME is defined for the given DIE, and holds a non-zero value. This function should only be used for DW_FORM_flag or DW_FORM_flag_present attributes. */ @@ -17126,102 +17785,37 @@ die_specification (struct die_info *die, struct dwarf2_cu **spec_cu) return follow_die_ref (die, spec_attr, spec_cu); } -/* Free the line_header structure *LH, and any arrays and strings it - refers to. - NOTE: This is also used as a "cleanup" function. */ - -static void -free_line_header (struct line_header *lh) -{ - if (lh->standard_opcode_lengths) - xfree (lh->standard_opcode_lengths); - - /* Remember that all the lh->file_names[i].name pointers are - pointers into debug_line_buffer, and don't need to be freed. */ - if (lh->file_names) - xfree (lh->file_names); - - /* Similarly for the include directory names. */ - if (lh->include_dirs) - xfree (lh->include_dirs); - - xfree (lh); -} - /* Stub for free_line_header to match void * callback types. */ static void free_line_header_voidp (void *arg) { - struct line_header *lh = arg; + struct line_header *lh = (struct line_header *) arg; - free_line_header (lh); + delete lh; } -/* Add an entry to LH's include directory table. */ - -static void -add_include_dir (struct line_header *lh, const char *include_dir) +void +line_header::add_include_dir (const char *include_dir) { if (dwarf_line_debug >= 2) - fprintf_unfiltered (gdb_stdlog, "Adding dir %u: %s\n", - lh->num_include_dirs + 1, include_dir); - - /* Grow the array if necessary. */ - if (lh->include_dirs_size == 0) - { - lh->include_dirs_size = 1; /* for testing */ - lh->include_dirs = xmalloc (lh->include_dirs_size - * sizeof (*lh->include_dirs)); - } - else if (lh->num_include_dirs >= lh->include_dirs_size) - { - lh->include_dirs_size *= 2; - lh->include_dirs = xrealloc (lh->include_dirs, - (lh->include_dirs_size - * sizeof (*lh->include_dirs))); - } + fprintf_unfiltered (gdb_stdlog, "Adding dir %zu: %s\n", + include_dirs.size () + 1, include_dir); - lh->include_dirs[lh->num_include_dirs++] = include_dir; + include_dirs.push_back (include_dir); } -/* Add an entry to LH's file name table. */ - -static void -add_file_name (struct line_header *lh, - const char *name, - unsigned int dir_index, - unsigned int mod_time, - unsigned int length) +void +line_header::add_file_name (const char *name, + dir_index d_index, + unsigned int mod_time, + unsigned int length) { - struct file_entry *fe; - if (dwarf_line_debug >= 2) fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n", - lh->num_file_names + 1, name); + (unsigned) file_names.size () + 1, name); - /* Grow the array if necessary. */ - if (lh->file_names_size == 0) - { - lh->file_names_size = 1; /* for testing */ - lh->file_names = xmalloc (lh->file_names_size - * sizeof (*lh->file_names)); - } - else if (lh->num_file_names >= lh->file_names_size) - { - lh->file_names_size *= 2; - lh->file_names = xrealloc (lh->file_names, - (lh->file_names_size - * sizeof (*lh->file_names))); - } - - fe = &lh->file_names[lh->num_file_names++]; - fe->name = name; - fe->dir_index = dir_index; - fe->mod_time = mod_time; - fe->length = length; - fe->included_p = 0; - fe->symtab = NULL; + file_names.emplace_back (name, d_index, mod_time, length); } /* A convenience function to find the proper .debug_line section for a CU. */ @@ -17247,6 +17841,135 @@ get_debug_line_section (struct dwarf2_cu *cu) return section; } +/* Read directory or file name entry format, starting with byte of + format count entries, ULEB128 pairs of entry formats, ULEB128 of + entries count and the entries themselves in the described entry + format. */ + +static void +read_formatted_entries (bfd *abfd, const gdb_byte **bufp, + struct line_header *lh, + const struct comp_unit_head *cu_header, + void (*callback) (struct line_header *lh, + const char *name, + dir_index d_index, + unsigned int mod_time, + unsigned int length)) +{ + gdb_byte format_count, formati; + ULONGEST data_count, datai; + const gdb_byte *buf = *bufp; + const gdb_byte *format_header_data; + int i; + unsigned int bytes_read; + + format_count = read_1_byte (abfd, buf); + buf += 1; + format_header_data = buf; + for (formati = 0; formati < format_count; formati++) + { + read_unsigned_leb128 (abfd, buf, &bytes_read); + buf += bytes_read; + read_unsigned_leb128 (abfd, buf, &bytes_read); + buf += bytes_read; + } + + data_count = read_unsigned_leb128 (abfd, buf, &bytes_read); + buf += bytes_read; + for (datai = 0; datai < data_count; datai++) + { + const gdb_byte *format = format_header_data; + struct file_entry fe; + + for (formati = 0; formati < format_count; formati++) + { + ULONGEST content_type = read_unsigned_leb128 (abfd, format, &bytes_read); + format += bytes_read; + + ULONGEST form = read_unsigned_leb128 (abfd, format, &bytes_read); + format += bytes_read; + + gdb::optional string; + gdb::optional uint; + + switch (form) + { + case DW_FORM_string: + string.emplace (read_direct_string (abfd, buf, &bytes_read)); + buf += bytes_read; + break; + + case DW_FORM_line_strp: + string.emplace (read_indirect_line_string (abfd, buf, + cu_header, + &bytes_read)); + buf += bytes_read; + break; + + case DW_FORM_data1: + uint.emplace (read_1_byte (abfd, buf)); + buf += 1; + break; + + case DW_FORM_data2: + uint.emplace (read_2_bytes (abfd, buf)); + buf += 2; + break; + + case DW_FORM_data4: + uint.emplace (read_4_bytes (abfd, buf)); + buf += 4; + break; + + case DW_FORM_data8: + uint.emplace (read_8_bytes (abfd, buf)); + buf += 8; + break; + + case DW_FORM_udata: + uint.emplace (read_unsigned_leb128 (abfd, buf, &bytes_read)); + buf += bytes_read; + break; + + case DW_FORM_block: + /* It is valid only for DW_LNCT_timestamp which is ignored by + current GDB. */ + break; + } + + switch (content_type) + { + case DW_LNCT_path: + if (string.has_value ()) + fe.name = *string; + break; + case DW_LNCT_directory_index: + if (uint.has_value ()) + fe.d_index = (dir_index) *uint; + break; + case DW_LNCT_timestamp: + if (uint.has_value ()) + fe.mod_time = *uint; + break; + case DW_LNCT_size: + if (uint.has_value ()) + fe.length = *uint; + break; + case DW_LNCT_MD5: + break; + default: + complaint (&symfile_complaints, + _("Unknown format content type %s"), + pulongest (content_type)); + } + } + + callback (lh, fe.name, fe.d_index, fe.mod_time, fe.length); + } + + *bufp = buf; +} + /* Read the statement program header starting at OFFSET in .debug_line, or .debug_line.dwo. Return a pointer to a struct line_header, allocated using xmalloc. @@ -17257,11 +17980,9 @@ get_debug_line_section (struct dwarf2_cu *cu) 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, struct dwarf2_cu *cu) +static line_header_up +dwarf_decode_line_header (sect_offset sect_off, struct dwarf2_cu *cu) { - struct cleanup *back_to; - struct line_header *lh; const gdb_byte *line_ptr; unsigned int bytes_read, offset_size; int i; @@ -17286,21 +18007,18 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu) /* 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 >= section->size) + if (to_underlying (sect_off) + 4 >= section->size) { dwarf2_statement_list_fits_in_line_number_section_complaint (); return 0; } - lh = xmalloc (sizeof (*lh)); - memset (lh, 0, sizeof (*lh)); - back_to = make_cleanup ((make_cleanup_ftype *) free_line_header, - (void *) lh); + line_header_up lh (new line_header ()); - lh->offset.sect_off = offset; + lh->sect_off = sect_off; lh->offset_in_dwz = cu->per_cu->is_dwz; - line_ptr = section->buffer + offset; + line_ptr = section->buffer + to_underlying (sect_off); /* Read in the header. */ lh->total_length = @@ -17310,13 +18028,12 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu) if (line_ptr + lh->total_length > (section->buffer + section->size)) { dwarf2_statement_list_fits_in_line_number_section_complaint (); - do_cleanups (back_to); return 0; } lh->statement_program_end = line_ptr + lh->total_length; lh->version = read_2_bytes (abfd, line_ptr); line_ptr += 2; - if (lh->version > 4) + if (lh->version > 5) { /* This is a version we don't understand. The format could have changed in ways we don't handle properly so just punt. */ @@ -17324,6 +18041,25 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu) _("unsupported version in .debug_line section")); return NULL; } + if (lh->version >= 5) + { + gdb_byte segment_selector_size; + + /* Skip address size. */ + read_1_byte (abfd, line_ptr); + line_ptr += 1; + + segment_selector_size = read_1_byte (abfd, line_ptr); + line_ptr += 1; + if (segment_selector_size != 0) + { + complaint (&symfile_complaints, + _("unsupported segment selector size %u " + "in .debug_line section"), + segment_selector_size); + return NULL; + } + } lh->header_length = read_offset_1 (abfd, line_ptr, offset_size); line_ptr += offset_size; lh->minimum_instruction_length = read_1_byte (abfd, line_ptr); @@ -17352,8 +18088,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu) line_ptr += 1; lh->opcode_base = read_1_byte (abfd, line_ptr); line_ptr += 1; - lh->standard_opcode_lengths - = xmalloc (lh->opcode_base * sizeof (lh->standard_opcode_lengths[0])); + lh->standard_opcode_lengths.reset (new unsigned char[lh->opcode_base]); lh->standard_opcode_lengths[0] = 1; /* This should never be used anyway. */ for (i = 1; i < lh->opcode_base; ++i) @@ -17362,30 +18097,54 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu) line_ptr += 1; } - /* Read directory table. */ - while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) + if (lh->version >= 5) { - line_ptr += bytes_read; - add_include_dir (lh, cur_dir); + /* Read directory table. */ + read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header, + [] (struct line_header *lh, const char *name, + dir_index d_index, unsigned int mod_time, + unsigned int length) + { + lh->add_include_dir (name); + }); + + /* Read file name table. */ + read_formatted_entries (abfd, &line_ptr, lh.get (), &cu->header, + [] (struct line_header *lh, const char *name, + dir_index d_index, unsigned int mod_time, + unsigned int length) + { + lh->add_file_name (name, d_index, mod_time, length); + }); } - line_ptr += bytes_read; - - /* Read file name table. */ - while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) + else { - unsigned int dir_index, mod_time, length; - - line_ptr += bytes_read; - dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - line_ptr += bytes_read; - length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + /* Read directory table. */ + while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) + { + line_ptr += bytes_read; + lh->add_include_dir (cur_dir); + } line_ptr += bytes_read; - add_file_name (lh, cur_file, dir_index, mod_time, length); + /* Read file name table. */ + while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL) + { + unsigned int mod_time, length; + dir_index d_index; + + line_ptr += bytes_read; + d_index = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + + lh->add_file_name (cur_file, d_index, mod_time, length); + } + line_ptr += bytes_read; } - line_ptr += bytes_read; lh->statement_program_start = line_ptr; if (line_ptr > (section->buffer + section->size)) @@ -17393,7 +18152,6 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu) _("line number info header doesn't " "fit in `.debug_line' section")); - discard_cleanups (back_to); return lh; } @@ -17411,16 +18169,14 @@ psymtab_include_file_name (const struct line_header *lh, int file_index, const struct partial_symtab *pst, const char *comp_dir) { - const struct file_entry fe = lh->file_names [file_index]; + const file_entry &fe = lh->file_names[file_index]; const char *include_name = fe.name; const char *include_name_to_compare = include_name; - const char *dir_name = NULL; const char *pst_filename; char *copied_name = NULL; int file_is_pst; - if (fe.dir_index && lh->include_dirs != NULL) - dir_name = lh->include_dirs[fe.dir_index - 1]; + const char *dir_name = fe.include_dir (lh); if (!IS_ABSOLUTE_PATH (include_name) && (dir_name != NULL || comp_dir != NULL)) @@ -17485,63 +18241,215 @@ psymtab_include_file_name (const struct line_header *lh, int file_index, /* State machine to track the state of the line number program. */ -typedef struct +class lnp_state_machine { - /* These are part of the standard DWARF line number state machine. */ +public: + /* Initialize a machine state for the start of a line number + program. */ + lnp_state_machine (gdbarch *arch, line_header *lh, bool record_lines_p); - unsigned char op_index; - unsigned int file; - unsigned int line; - CORE_ADDR address; - int is_stmt; - unsigned int discriminator; + file_entry *current_file () + { + /* lh->file_names is 0-based, but the file name numbers in the + statement program are 1-based. */ + return m_line_header->file_name_at (m_file); + } - /* Additional bits of state we need to track. */ + /* Record the line in the state machine. END_SEQUENCE is true if + we're processing the end of a sequence. */ + void record_line (bool end_sequence); - /* The last file that we called dwarf2_start_subfile for. - This is only used for TLLs. */ - unsigned int last_file; - /* The last file a line number was recorded for. */ - struct subfile *last_subfile; + /* Check address and if invalid nop-out the rest of the lines in this + sequence. */ + void check_line_address (struct dwarf2_cu *cu, + const gdb_byte *line_ptr, + CORE_ADDR lowpc, CORE_ADDR address); - /* The function to call to record a line. */ - record_line_ftype *record_line; + void handle_set_discriminator (unsigned int discriminator) + { + m_discriminator = discriminator; + m_line_has_non_zero_discriminator |= discriminator != 0; + } - /* The last line number that was recorded, used to coalesce - consecutive entries for the same line. This can happen, for - example, when discriminators are present. PR 17276. */ - unsigned int last_line; - int line_has_non_zero_discriminator; -} lnp_state_machine; + /* Handle DW_LNE_set_address. */ + void handle_set_address (CORE_ADDR baseaddr, CORE_ADDR address) + { + m_op_index = 0; + address += baseaddr; + m_address = gdbarch_adjust_dwarf2_line (m_gdbarch, address, false); + } -/* There's a lot of static state to pass to dwarf_record_line. - This keeps it all together. */ + /* Handle DW_LNS_advance_pc. */ + void handle_advance_pc (CORE_ADDR adjust); -typedef struct -{ - /* The gdbarch. */ - struct gdbarch *gdbarch; + /* Handle a special opcode. */ + void handle_special_opcode (unsigned char op_code); - /* The line number header. */ - struct line_header *line_header; + /* Handle DW_LNS_advance_line. */ + void handle_advance_line (int line_delta) + { + advance_line (line_delta); + } - /* Non-zero if we're recording lines. - Otherwise we're building partial symtabs and are just interested in - finding include files mentioned by the line number program. */ - int record_lines_p; -} lnp_reader_state; + /* Handle DW_LNS_set_file. */ + void handle_set_file (file_name_index file); -/* Ignore this record_line request. */ + /* Handle DW_LNS_negate_stmt. */ + void handle_negate_stmt () + { + m_is_stmt = !m_is_stmt; + } -static void -noop_record_line (struct subfile *subfile, int line, CORE_ADDR pc) -{ - return; -} + /* Handle DW_LNS_const_add_pc. */ + void handle_const_add_pc (); -/* Return non-zero if we should add LINE to the line number table. - LINE is the line to add, LAST_LINE is the last line that was added, - LAST_SUBFILE is the subfile for LAST_LINE. + /* Handle DW_LNS_fixed_advance_pc. */ + void handle_fixed_advance_pc (CORE_ADDR addr_adj) + { + m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true); + m_op_index = 0; + } + + /* Handle DW_LNS_copy. */ + void handle_copy () + { + record_line (false); + m_discriminator = 0; + } + + /* Handle DW_LNE_end_sequence. */ + void handle_end_sequence () + { + m_record_line_callback = ::record_line; + } + +private: + /* Advance the line by LINE_DELTA. */ + void advance_line (int line_delta) + { + m_line += line_delta; + + if (line_delta != 0) + m_line_has_non_zero_discriminator = m_discriminator != 0; + } + + gdbarch *m_gdbarch; + + /* True if we're recording lines. + Otherwise we're building partial symtabs and are just interested in + finding include files mentioned by the line number program. */ + bool m_record_lines_p; + + /* The line number header. */ + line_header *m_line_header; + + /* These are part of the standard DWARF line number state machine, + and initialized according to the DWARF spec. */ + + unsigned char m_op_index = 0; + /* The line table index (1-based) of the current file. */ + file_name_index m_file = (file_name_index) 1; + unsigned int m_line = 1; + + /* These are initialized in the constructor. */ + + CORE_ADDR m_address; + bool m_is_stmt; + unsigned int m_discriminator; + + /* Additional bits of state we need to track. */ + + /* The last file that we called dwarf2_start_subfile for. + This is only used for TLLs. */ + unsigned int m_last_file = 0; + /* The last file a line number was recorded for. */ + struct subfile *m_last_subfile = NULL; + + /* The function to call to record a line. */ + record_line_ftype *m_record_line_callback = NULL; + + /* The last line number that was recorded, used to coalesce + consecutive entries for the same line. This can happen, for + example, when discriminators are present. PR 17276. */ + unsigned int m_last_line = 0; + bool m_line_has_non_zero_discriminator = false; +}; + +void +lnp_state_machine::handle_advance_pc (CORE_ADDR adjust) +{ + CORE_ADDR addr_adj = (((m_op_index + adjust) + / m_line_header->maximum_ops_per_instruction) + * m_line_header->minimum_instruction_length); + m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true); + m_op_index = ((m_op_index + adjust) + % m_line_header->maximum_ops_per_instruction); +} + +void +lnp_state_machine::handle_special_opcode (unsigned char op_code) +{ + unsigned char adj_opcode = op_code - m_line_header->opcode_base; + CORE_ADDR addr_adj = (((m_op_index + + (adj_opcode / m_line_header->line_range)) + / m_line_header->maximum_ops_per_instruction) + * m_line_header->minimum_instruction_length); + m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true); + m_op_index = ((m_op_index + (adj_opcode / m_line_header->line_range)) + % m_line_header->maximum_ops_per_instruction); + + int line_delta = (m_line_header->line_base + + (adj_opcode % m_line_header->line_range)); + advance_line (line_delta); + record_line (false); + m_discriminator = 0; +} + +void +lnp_state_machine::handle_set_file (file_name_index file) +{ + m_file = file; + + const file_entry *fe = current_file (); + if (fe == NULL) + dwarf2_debug_line_missing_file_complaint (); + else if (m_record_lines_p) + { + const char *dir = fe->include_dir (m_line_header); + + m_last_subfile = current_subfile; + m_line_has_non_zero_discriminator = m_discriminator != 0; + dwarf2_start_subfile (fe->name, dir); + } +} + +void +lnp_state_machine::handle_const_add_pc () +{ + CORE_ADDR adjust + = (255 - m_line_header->opcode_base) / m_line_header->line_range; + + CORE_ADDR addr_adj + = (((m_op_index + adjust) + / m_line_header->maximum_ops_per_instruction) + * m_line_header->minimum_instruction_length); + + m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true); + m_op_index = ((m_op_index + adjust) + % m_line_header->maximum_ops_per_instruction); +} + +/* Ignore this record_line request. */ + +static void +noop_record_line (struct subfile *subfile, int line, CORE_ADDR pc) +{ + return; +} + +/* Return non-zero if we should add LINE to the line number table. + LINE is the line to add, LAST_LINE is the last line that was added, + LAST_SUBFILE is the subfile for LAST_LINE. LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever had a non-zero discriminator. @@ -17630,102 +18538,76 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile, dwarf_record_line_1 (gdbarch, subfile, 0, address, p_record_line); } -/* Record the line in STATE. - END_SEQUENCE is non-zero if we're processing the end of a sequence. */ - -static void -dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state, - int end_sequence) +void +lnp_state_machine::record_line (bool end_sequence) { - const struct line_header *lh = reader->line_header; - unsigned int file, line, discriminator; - int is_stmt; - - file = state->file; - line = state->line; - is_stmt = state->is_stmt; - discriminator = state->discriminator; - if (dwarf_line_debug) { fprintf_unfiltered (gdb_stdlog, "Processing actual line %u: file %u," " address %s, is_stmt %u, discrim %u\n", - line, file, - paddress (reader->gdbarch, state->address), - is_stmt, discriminator); + m_line, to_underlying (m_file), + paddress (m_gdbarch, m_address), + m_is_stmt, m_discriminator); } - if (file == 0 || file - 1 >= lh->num_file_names) + file_entry *fe = current_file (); + + if (fe == NULL) dwarf2_debug_line_missing_file_complaint (); /* For now we ignore lines not starting on an instruction boundary. But not when processing end_sequence for compatibility with the previous version of the code. */ - else if (state->op_index == 0 || end_sequence) + else if (m_op_index == 0 || end_sequence) { - lh->file_names[file - 1].included_p = 1; - if (reader->record_lines_p && is_stmt) + fe->included_p = 1; + if (m_record_lines_p && m_is_stmt) { - if (state->last_subfile != current_subfile || end_sequence) + if (m_last_subfile != current_subfile || end_sequence) { - dwarf_finish_line (reader->gdbarch, state->last_subfile, - state->address, state->record_line); + dwarf_finish_line (m_gdbarch, m_last_subfile, + m_address, m_record_line_callback); } if (!end_sequence) { - if (dwarf_record_line_p (line, state->last_line, - state->line_has_non_zero_discriminator, - state->last_subfile)) + if (dwarf_record_line_p (m_line, m_last_line, + m_line_has_non_zero_discriminator, + m_last_subfile)) { - dwarf_record_line_1 (reader->gdbarch, current_subfile, - line, state->address, - state->record_line); + dwarf_record_line_1 (m_gdbarch, current_subfile, + m_line, m_address, + m_record_line_callback); } - state->last_subfile = current_subfile; - state->last_line = line; + m_last_subfile = current_subfile; + m_last_line = m_line; } } } } -/* Initialize STATE for the start of a line number program. */ - -static void -init_lnp_state_machine (lnp_state_machine *state, - const lnp_reader_state *reader) +lnp_state_machine::lnp_state_machine (gdbarch *arch, line_header *lh, + bool record_lines_p) { - memset (state, 0, sizeof (*state)); - - /* Just starting, there is no "last file". */ - state->last_file = 0; - state->last_subfile = NULL; + m_gdbarch = arch; + m_record_lines_p = record_lines_p; + m_line_header = lh; - state->record_line = record_line; + m_record_line_callback = ::record_line; - state->last_line = 0; - state->line_has_non_zero_discriminator = 0; - - /* Initialize these according to the DWARF spec. */ - state->op_index = 0; - state->file = 1; - state->line = 1; /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as if there was a line entry for it so that the backend has a chance to adjust it and also record it in case it needs it. This is currently used by MIPS code, cf. `mips_adjust_dwarf2_line'. */ - state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0); - state->is_stmt = reader->line_header->default_is_stmt; - state->discriminator = 0; + m_address = gdbarch_adjust_dwarf2_line (arch, 0, 0); + m_is_stmt = lh->default_is_stmt; + m_discriminator = 0; } -/* Check address and if invalid nop-out the rest of the lines in this - sequence. */ - -static void -check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state, - const gdb_byte *line_ptr, - CORE_ADDR lowpc, CORE_ADDR address) +void +lnp_state_machine::check_line_address (struct dwarf2_cu *cu, + const gdb_byte *line_ptr, + CORE_ADDR lowpc, CORE_ADDR address) { /* If address < lowpc then it's not a usable value, it's outside the pc range of the CU. However, we restrict the test to only address @@ -17743,9 +18625,9 @@ check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state, complaint (&symfile_complaints, _(".debug_line address at offset 0x%lx is 0 [in module %s]"), line_offset, objfile_name (objfile)); - state->record_line = noop_record_line; - /* Note: sm.record_line is left as noop_record_line - until we see DW_LNE_end_sequence. */ + m_record_line_callback = noop_record_line; + /* Note: record_line_callback is left as noop_record_line until + we see DW_LNE_end_sequence. */ } } @@ -17766,44 +18648,32 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, struct objfile *objfile = cu->objfile; bfd *abfd = objfile->obfd; struct gdbarch *gdbarch = get_objfile_arch (objfile); - /* Non-zero if we're recording line info (as opposed to building partial - symtabs). */ - int record_lines_p = !decode_for_pst_p; - /* A collection of things we need to pass to dwarf_record_line. */ - lnp_reader_state reader_state; + /* True if we're recording line info (as opposed to building partial + symtabs and just interested in finding include files mentioned by + the line number program). */ + bool record_lines_p = !decode_for_pst_p; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); line_ptr = lh->statement_program_start; line_end = lh->statement_program_end; - reader_state.gdbarch = gdbarch; - reader_state.line_header = lh; - reader_state.record_lines_p = record_lines_p; - /* Read the statement sequences until there's nothing left. */ while (line_ptr < line_end) { - /* The DWARF line number program state machine. */ - lnp_state_machine state_machine; - int end_sequence = 0; - - /* Reset the state machine at the start of each sequence. */ - init_lnp_state_machine (&state_machine, &reader_state); + /* The DWARF line number program state machine. Reset the state + machine at the start of each sequence. */ + lnp_state_machine state_machine (gdbarch, lh, record_lines_p); + bool end_sequence = false; - if (record_lines_p && lh->num_file_names >= state_machine.file) + if (record_lines_p) { - /* Start a subfile for the current file of the state machine. */ - /* lh->include_dirs and lh->file_names are 0-based, but the - directory and file name numbers in the statement program - are 1-based. */ - struct file_entry *fe = &lh->file_names[state_machine.file - 1]; - const char *dir = NULL; + /* Start a subfile for the current file of the state + machine. */ + const file_entry *fe = state_machine.current_file (); - if (fe->dir_index && lh->include_dirs != NULL) - dir = lh->include_dirs[fe->dir_index - 1]; - - dwarf2_start_subfile (fe->name, dir); + if (fe != NULL) + dwarf2_start_subfile (fe->name, fe->include_dir (lh)); } /* Decode the table. */ @@ -17815,28 +18685,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, if (op_code >= lh->opcode_base) { /* Special opcode. */ - unsigned char adj_opcode; - CORE_ADDR addr_adj; - int line_delta; - - adj_opcode = op_code - lh->opcode_base; - addr_adj = (((state_machine.op_index - + (adj_opcode / lh->line_range)) - / lh->maximum_ops_per_instruction) - * lh->minimum_instruction_length); - state_machine.address - += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1); - state_machine.op_index = ((state_machine.op_index - + (adj_opcode / lh->line_range)) - % lh->maximum_ops_per_instruction); - line_delta = lh->line_base + (adj_opcode % lh->line_range); - state_machine.line += line_delta; - if (line_delta != 0) - state_machine.line_has_non_zero_discriminator - = state_machine.discriminator != 0; - - dwarf_record_line (&reader_state, &state_machine, 0); - state_machine.discriminator = 0; + state_machine.handle_special_opcode (op_code); } else switch (op_code) { @@ -17850,32 +18699,30 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, switch (extended_op) { case DW_LNE_end_sequence: - state_machine.record_line = record_line; - end_sequence = 1; + state_machine.handle_end_sequence (); + end_sequence = true; break; case DW_LNE_set_address: { CORE_ADDR address = read_address (abfd, line_ptr, cu, &bytes_read); - line_ptr += bytes_read; - check_line_address (cu, &state_machine, line_ptr, - lowpc, address); - state_machine.op_index = 0; - address += baseaddr; - state_machine.address - = gdbarch_adjust_dwarf2_line (gdbarch, address, 0); + + state_machine.check_line_address (cu, line_ptr, + lowpc, address); + state_machine.handle_set_address (baseaddr, address); } break; case DW_LNE_define_file: { const char *cur_file; - unsigned int dir_index, mod_time, length; + unsigned int mod_time, length; + dir_index dindex; cur_file = read_direct_string (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - dir_index = + dindex = (dir_index) read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; mod_time = @@ -17884,20 +18731,23 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); line_ptr += bytes_read; - add_file_name (lh, cur_file, dir_index, mod_time, length); + lh->add_file_name (cur_file, dindex, mod_time, length); } break; case DW_LNE_set_discriminator: - /* The discriminator is not interesting to the debugger; - just ignore it. We still need to check its value though: - if there are consecutive entries for the same - (non-prologue) line we want to coalesce them. - PR 17276. */ - state_machine.discriminator - = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - state_machine.line_has_non_zero_discriminator - |= state_machine.discriminator != 0; - line_ptr += bytes_read; + { + /* The discriminator is not interesting to the + debugger; just ignore it. We still need to + check its value though: + if there are consecutive entries for the same + (non-prologue) line we want to coalesce them. + PR 17276. */ + unsigned int discr + = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); + line_ptr += bytes_read; + + state_machine.handle_set_discriminator (discr); + } break; default: complaint (&symfile_complaints, @@ -17915,64 +18765,34 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, } break; case DW_LNS_copy: - dwarf_record_line (&reader_state, &state_machine, 0); - state_machine.discriminator = 0; + state_machine.handle_copy (); break; case DW_LNS_advance_pc: { CORE_ADDR adjust = read_unsigned_leb128 (abfd, line_ptr, &bytes_read); - CORE_ADDR addr_adj; - - addr_adj = (((state_machine.op_index + adjust) - / lh->maximum_ops_per_instruction) - * lh->minimum_instruction_length); - state_machine.address - += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1); - state_machine.op_index = ((state_machine.op_index + adjust) - % lh->maximum_ops_per_instruction); line_ptr += bytes_read; + + state_machine.handle_advance_pc (adjust); } break; case DW_LNS_advance_line: { int line_delta = read_signed_leb128 (abfd, line_ptr, &bytes_read); - - state_machine.line += line_delta; - if (line_delta != 0) - state_machine.line_has_non_zero_discriminator - = state_machine.discriminator != 0; line_ptr += bytes_read; + + state_machine.handle_advance_line (line_delta); } break; case DW_LNS_set_file: { - /* The arrays lh->include_dirs and lh->file_names are - 0-based, but the directory and file name numbers in - the statement program are 1-based. */ - struct file_entry *fe; - const char *dir = NULL; - - state_machine.file = read_unsigned_leb128 (abfd, line_ptr, - &bytes_read); + file_name_index file + = (file_name_index) read_unsigned_leb128 (abfd, line_ptr, + &bytes_read); line_ptr += bytes_read; - if (state_machine.file == 0 - || state_machine.file - 1 >= lh->num_file_names) - dwarf2_debug_line_missing_file_complaint (); - else - { - fe = &lh->file_names[state_machine.file - 1]; - if (fe->dir_index && lh->include_dirs != NULL) - dir = lh->include_dirs[fe->dir_index - 1]; - if (record_lines_p) - { - state_machine.last_subfile = current_subfile; - state_machine.line_has_non_zero_discriminator - = state_machine.discriminator != 0; - dwarf2_start_subfile (fe->name, dir); - } - } + + state_machine.handle_set_file (file); } break; case DW_LNS_set_column: @@ -17980,7 +18800,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, line_ptr += bytes_read; break; case DW_LNS_negate_stmt: - state_machine.is_stmt = (!state_machine.is_stmt); + state_machine.handle_negate_stmt (); break; case DW_LNS_set_basic_block: break; @@ -17990,28 +18810,14 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, instruction length since special opcode 255 would have scaled the increment. */ case DW_LNS_const_add_pc: - { - CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range; - CORE_ADDR addr_adj; - - addr_adj = (((state_machine.op_index + adjust) - / lh->maximum_ops_per_instruction) - * lh->minimum_instruction_length); - state_machine.address - += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1); - state_machine.op_index = ((state_machine.op_index + adjust) - % lh->maximum_ops_per_instruction); - } + state_machine.handle_const_add_pc (); break; case DW_LNS_fixed_advance_pc: { - CORE_ADDR addr_adj; - - addr_adj = read_2_bytes (abfd, line_ptr); - state_machine.address - += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1); - state_machine.op_index = 0; + CORE_ADDR addr_adj = read_2_bytes (abfd, line_ptr); line_ptr += 2; + + state_machine.handle_fixed_advance_pc (addr_adj); } break; default: @@ -18033,7 +18839,7 @@ dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu, /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer, in which case we still finish recording the last line). */ - dwarf_record_line (&reader_state, &state_machine, 1); + state_machine.record_line (true); } } @@ -18082,7 +18888,7 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir, /* Now that we're done scanning the Line Header Program, we can create the psymtab of each included file. */ - for (file_index = 0; file_index < lh->num_file_names; file_index++) + for (file_index = 0; file_index < lh->file_names.size (); file_index++) if (lh->file_names[file_index].included_p == 1) { const char *include_name = @@ -18099,22 +18905,18 @@ dwarf_decode_lines (struct line_header *lh, const char *comp_dir, struct compunit_symtab *cust = buildsym_compunit_symtab (); int i; - for (i = 0; i < lh->num_file_names; i++) + for (i = 0; i < lh->file_names.size (); i++) { - const char *dir = NULL; - struct file_entry *fe; + file_entry &fe = lh->file_names[i]; - fe = &lh->file_names[i]; - if (fe->dir_index && lh->include_dirs != NULL) - dir = lh->include_dirs[fe->dir_index - 1]; - dwarf2_start_subfile (fe->name, dir); + dwarf2_start_subfile (fe.name, fe.include_dir (lh)); if (current_subfile->symtab == NULL) { current_subfile->symtab = allocate_symtab (cust, current_subfile->name); } - fe->symtab = current_subfile->symtab; + fe.symtab = current_subfile->symtab; } } } @@ -18323,19 +19125,19 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, cu); if (attr) { - int file_index = DW_UNSND (attr); + file_name_index file_index = (file_name_index) DW_UNSND (attr); + struct file_entry *fe; + + if (cu->line_header != NULL) + fe = cu->line_header->file_name_at (file_index); + else + fe = NULL; - if (cu->line_header == NULL - || file_index > cu->line_header->num_file_names) + if (fe == NULL) complaint (&symfile_complaints, _("file index out of range")); - else if (file_index > 0) - { - struct file_entry *fe; - - fe = &cu->line_header->file_names[file_index - 1]; - symbol_set_symtab (sym, fe->symtab); - } + else + symbol_set_symtab (sym, fe->symtab); } switch (die->tag) @@ -18393,8 +19195,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, variables with missing type entries. Change the misleading `void' type to something sensible. */ if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_VOID) - SYMBOL_TYPE (sym) - = objfile_type (objfile)->nodebug_data_symbol; + SYMBOL_TYPE (sym) = objfile_type (objfile)->builtin_int; attr = dwarf2_attr (die, DW_AT_const_value, cu); /* In the case of DW_TAG_member, we should only be called for @@ -18453,7 +19254,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, if (cu->language == language_fortran && die->parent && die->parent->tag == DW_TAG_module && cu->producer - && startswith (cu->producer, "GNU Fortran ")) + && startswith (cu->producer, "GNU Fortran")) SYMBOL_ACLASS_INDEX (sym) = LOC_UNRESOLVED; /* A variable with DW_AT_external is never static, @@ -18543,7 +19344,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, SYMBOL_DOMAIN (sym) = STRUCT_DOMAIN; { - /* NOTE: carlton/2003-11-10: C++ and Java class symbols shouldn't + /* NOTE: carlton/2003-11-10: C++ class symbols shouldn't really ever be static objects: otherwise, if you try to, say, break of a class's method and you're in a file which doesn't mention that class, it won't work unless @@ -18554,18 +19355,15 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, if (!suppress_add) { list_to_add = (cu->list_in_scope == &file_symbols - && (cu->language == language_cplus - || cu->language == language_java) + && cu->language == language_cplus ? &global_symbols : cu->list_in_scope); /* The semantics of C++ state that "struct foo { - ... }" also defines a typedef for "foo". A Java - class declaration also defines a typedef for the - class. */ + ... }" also defines a typedef for "foo". */ if (cu->language == language_cplus - || cu->language == language_java || cu->language == language_ada - || cu->language == language_d) + || cu->language == language_d + || cu->language == language_rust) { /* The symbol's name is already allocated along with this objfile, so we don't need to @@ -18598,8 +19396,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu, DW_TAG_class_type, etc. block. */ list_to_add = (cu->list_in_scope == &file_symbols - && (cu->language == language_cplus - || cu->language == language_java) + && cu->language == language_cplus ? &global_symbols : cu->list_in_scope); } break; @@ -18681,7 +19478,7 @@ dwarf2_const_value_data (const struct attribute *attr, struct obstack *obstack, *value = l; else { - gdb_byte *bytes = obstack_alloc (obstack, bits / 8); + gdb_byte *bytes = (gdb_byte *) obstack_alloc (obstack, bits / 8); store_unsigned_integer (bytes, bits / 8, byte_order, l); return bytes; } @@ -18726,12 +19523,12 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type, /* Symbols of this form are reasonably rare, so we just piggyback on the existing location code rather than writing a new implementation of symbol_computed_ops. */ - *baton = obstack_alloc (obstack, sizeof (struct dwarf2_locexpr_baton)); + *baton = XOBNEW (obstack, struct dwarf2_locexpr_baton); (*baton)->per_cu = cu->per_cu; gdb_assert ((*baton)->per_cu); (*baton)->size = 2 + cu_header->addr_size; - data = obstack_alloc (obstack, (*baton)->size); + data = (gdb_byte *) obstack_alloc (obstack, (*baton)->size); (*baton)->data = data; data[0] = DW_OP_addr; @@ -18753,6 +19550,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type, case DW_FORM_block4: case DW_FORM_block: case DW_FORM_exprloc: + case DW_FORM_data16: blk = DW_BLOCK (attr); if (TYPE_LENGTH (type) != blk->size) dwarf2_const_value_length_mismatch_complaint (name, blk->size, @@ -18779,6 +19577,7 @@ dwarf2_const_value_attr (const struct attribute *attr, struct type *type, break; case DW_FORM_sdata: + case DW_FORM_implicit_const: *value = DW_SND (attr); break; @@ -18803,7 +19602,6 @@ dwarf2_const_value (const struct attribute *attr, struct symbol *sym, struct dwarf2_cu *cu) { struct objfile *objfile = cu->objfile; - struct comp_unit_head *cu_header = &cu->header; LONGEST value; const gdb_byte *bytes; struct dwarf2_locexpr_baton *baton; @@ -18923,13 +19721,13 @@ build_error_marker_type (struct dwarf2_cu *cu, struct die_info *die) message = xstrprintf (_(""), objfile_name (objfile), - cu->header.offset.sect_off, - die->offset.sect_off); - saved = obstack_copy0 (&objfile->objfile_obstack, - message, strlen (message)); + to_underlying (cu->header.sect_off), + to_underlying (die->sect_off)); + saved = (char *) obstack_copy0 (&objfile->objfile_obstack, + message, strlen (message)); xfree (message); - return init_type (TYPE_CODE_ERROR, 0, 0, saved, objfile); + return init_type (objfile, TYPE_CODE_ERROR, 0, saved); } /* Look up the type of DIE in CU using its type attribute ATTR. @@ -18953,16 +19751,16 @@ lookup_die_type (struct die_info *die, const struct attribute *attr, if (attr->form == DW_FORM_GNU_ref_alt) { struct dwarf2_per_cu_data *per_cu; - sect_offset offset = dwarf2_get_ref_die_offset (attr); + sect_offset sect_off = dwarf2_get_ref_die_offset (attr); - per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile); - this_type = get_die_type_at_offset (offset, per_cu); + per_cu = dwarf2_find_containing_comp_unit (sect_off, 1, cu->objfile); + this_type = get_die_type_at_offset (sect_off, per_cu); } else if (attr_form_is_ref (attr)) { - sect_offset offset = dwarf2_get_ref_die_offset (attr); + sect_offset sect_off = dwarf2_get_ref_die_offset (attr); - this_type = get_die_type_at_offset (offset, cu->per_cu); + this_type = get_die_type_at_offset (sect_off, cu->per_cu); } else if (attr->form == DW_FORM_ref_sig8) { @@ -18975,7 +19773,7 @@ lookup_die_type (struct die_info *die, const struct attribute *attr, complaint (&symfile_complaints, _("Dwarf Error: Bad type attribute %s in DIE" " at 0x%x [in module %s]"), - dwarf_attr_name (attr->name), die->offset.sect_off, + dwarf_attr_name (attr->name), to_underlying (die->sect_off), objfile_name (objfile)); return build_error_marker_type (cu, die); } @@ -19062,7 +19860,10 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu) this_type = read_tag_ptr_to_member_type (die, cu); break; case DW_TAG_reference_type: - this_type = read_tag_reference_type (die, cu); + this_type = read_tag_reference_type (die, cu, TYPE_CODE_REF); + break; + case DW_TAG_rvalue_reference_type: + this_type = read_tag_reference_type (die, cu, TYPE_CODE_RVALUE_REF); break; case DW_TAG_const_type: this_type = read_tag_const_type (die, cu); @@ -19136,16 +19937,13 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu) { if (child->tag == DW_TAG_subprogram) { - struct attribute *attr; + const char *linkage_name = dw2_linkage_name (child, cu); - attr = dwarf2_attr (child, DW_AT_linkage_name, cu); - if (attr == NULL) - attr = dwarf2_attr (child, DW_AT_MIPS_linkage_name, cu); - if (attr != NULL) + if (linkage_name != NULL) { char *actual_name = language_class_name_from_physname (cu->language_defn, - DW_STRING (attr)); + linkage_name); char *name = NULL; if (actual_name != NULL) @@ -19164,10 +19962,9 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu) if (actual_name_len > die_name_len + 2 && actual_name[actual_name_len - die_name_len - 1] == ':') - name = - obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, - actual_name, - actual_name_len - die_name_len - 2); + name = (char *) obstack_copy0 ( + &cu->objfile->per_bfd->storage_obstack, + actual_name, actual_name_len - die_name_len - 2); } } xfree (actual_name); @@ -19183,23 +19980,20 @@ guess_full_die_structure_name (struct die_info *die, struct dwarf2_cu *cu) prefix part in such case. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */ -static char * +static const char * anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu) { struct attribute *attr; - char *base; + const char *base; if (die->tag != DW_TAG_class_type && die->tag != DW_TAG_interface_type && die->tag != DW_TAG_structure_type && die->tag != DW_TAG_union_type) return NULL; - attr = dwarf2_attr (die, DW_AT_name, cu); - if (attr != NULL && DW_STRING (attr) != NULL) + if (dwarf2_string_attr (die, DW_AT_name, cu) != NULL) return NULL; - attr = dwarf2_attr (die, DW_AT_linkage_name, cu); - if (attr == NULL) - attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + attr = dw2_linkage_name_attr (die, cu); if (attr == NULL || DW_STRING (attr) == NULL) return NULL; @@ -19211,8 +20005,9 @@ anonymous_struct_prefix (struct die_info *die, struct dwarf2_cu *cu) if (base == NULL || base == DW_STRING (attr) || base[-1] != ':') return ""; - return obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, - DW_STRING (attr), &base[-1] - DW_STRING (attr)); + return (char *) obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, + DW_STRING (attr), + &base[-1] - DW_STRING (attr)); } /* Return the name of the namespace/class that DIE is defined within, @@ -19236,10 +20031,11 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu) struct die_info *parent, *spec_die; struct dwarf2_cu *spec_cu; struct type *parent_type; - char *retval; + const char *retval; - if (cu->language != language_cplus && cu->language != language_java - && cu->language != language_fortran && cu->language != language_d) + if (cu->language != language_cplus + && cu->language != language_fortran && cu->language != language_d + && cu->language != language_rust) return ""; retval = anonymous_struct_prefix (die, cu); @@ -19393,8 +20189,6 @@ typename_concat (struct obstack *obs, const char *prefix, const char *suffix, if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0') sep = ""; - else if (cu->language == language_java) - sep = "."; else if (cu->language == language_d) { /* For D, the 'main' function could be defined in any module, but it @@ -19426,7 +20220,8 @@ typename_concat (struct obstack *obs, const char *prefix, const char *suffix, if (obs == NULL) { char *retval - = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1); + = ((char *) + xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1)); strcpy (retval, lead); strcat (retval, prefix); @@ -19457,13 +20252,14 @@ dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu, { if (name && cu->language == language_cplus) { - char *canon_name = cp_canonicalize_string (name); + std::string canon_name = cp_canonicalize_string (name); - if (canon_name != NULL) + if (!canon_name.empty ()) { - if (strcmp (canon_name, name) != 0) - name = obstack_copy0 (obstack, canon_name, strlen (canon_name)); - xfree (canon_name); + if (canon_name != name) + name = (const char *) obstack_copy0 (obstack, + canon_name.c_str (), + canon_name.length ()); } } @@ -19504,36 +20300,6 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) return DW_STRING (attr); return CP_ANONYMOUS_NAMESPACE_STR; - case DW_TAG_subprogram: - /* Java constructors will all be named "", so return - the class name when we see this special case. */ - if (cu->language == language_java - && DW_STRING (attr) != NULL - && strcmp (DW_STRING (attr), "") == 0) - { - struct dwarf2_cu *spec_cu = cu; - struct die_info *spec_die; - - /* GCJ will output '' for Java constructor names. - For this special case, return the name of the parent class. */ - - /* GCJ may output subprogram DIEs with AT_specification set. - If so, use the name of the specified DIE. */ - spec_die = die_specification (die, &spec_cu); - if (spec_die != NULL) - return dwarf2_name (spec_die, spec_cu); - - do - { - die = die->parent; - if (die->tag == DW_TAG_class_type) - return dwarf2_name (die, cu); - } - while (die->tag != DW_TAG_compile_unit - && die->tag != DW_TAG_partial_unit); - } - break; - case DW_TAG_class_type: case DW_TAG_interface_type: case DW_TAG_structure_type: @@ -19553,10 +20319,7 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) { char *demangled = NULL; - attr = dwarf2_attr (die, DW_AT_linkage_name, cu); - if (attr == NULL) - attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); - + attr = dw2_linkage_name_attr (die, cu); if (attr == NULL || DW_STRING (attr) == NULL) return NULL; @@ -19567,12 +20330,13 @@ dwarf2_name (struct die_info *die, struct dwarf2_cu *cu) if (demangled) { - char *base; + const char *base; /* FIXME: we already did this for the partial symbol... */ DW_STRING (attr) - = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, - demangled, strlen (demangled)); + = ((const char *) + obstack_copy0 (&cu->objfile->per_bfd->storage_obstack, + demangled, strlen (demangled))); DW_STRING_IS_CANONICAL (attr) = 1; xfree (demangled); @@ -19666,7 +20430,7 @@ dwarf_form_name (unsigned form) return name; } -static char * +static const char * dwarf_bool_name (unsigned mybool) { if (mybool) @@ -19695,13 +20459,14 @@ 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.sect_off); + dwarf_tag_name (die->tag), die->abbrev, + to_underlying (die->sect_off)); if (die->parent != NULL) { print_spaces (indent, f); fprintf_unfiltered (f, " parent at offset: 0x%x\n", - die->parent->offset.sect_off); + to_underlying (die->parent->sect_off)); } print_spaces (indent, f); @@ -19736,6 +20501,9 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) fprintf_unfiltered (f, "expression: size %s", pulongest (DW_BLOCK (&die->attrs[i])->size)); break; + case DW_FORM_data16: + fprintf_unfiltered (f, "constant of 16 bytes"); + break; case DW_FORM_ref_addr: fprintf_unfiltered (f, "ref address: "); fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f); @@ -19771,6 +20539,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) break; case DW_FORM_string: case DW_FORM_strp: + case DW_FORM_line_strp: case DW_FORM_GNU_str_index: case DW_FORM_GNU_strp_alt: fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)", @@ -19793,6 +20562,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die) fprintf_unfiltered (f, "unexpected attribute form: DW_FORM_indirect"); break; + case DW_FORM_implicit_const: + fprintf_unfiltered (f, "constant: %s", + plongest (DW_SND (&die->attrs[i]))); + break; default: fprintf_unfiltered (f, "unsupported attribute form: %d.", die->attrs[i].form); @@ -19856,7 +20629,8 @@ 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.sect_off, + slot = htab_find_slot_with_hash (cu->die_hash, die, + to_underlying (die->sect_off), INSERT); *slot = die; @@ -19868,16 +20642,13 @@ store_in_ref_table (struct die_info *die, struct dwarf2_cu *cu) static sect_offset dwarf2_get_ref_die_offset (const struct attribute *attr) { - sect_offset retval = { DW_UNSND (attr) }; - if (attr_form_is_ref (attr)) - return retval; + return (sect_offset) DW_UNSND (attr); - retval.sect_off = 0; complaint (&symfile_complaints, _("unsupported die ref attribute form: '%s'"), dwarf_form_name (attr->form)); - return retval; + return {}; } /* Return the constant value held by ATTR. Return DEFAULT_VALUE if @@ -19886,7 +20657,7 @@ dwarf2_get_ref_die_offset (const struct attribute *attr) static LONGEST dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value) { - if (attr->form == DW_FORM_sdata) + if (attr->form == DW_FORM_sdata || attr->form == DW_FORM_implicit_const) return DW_SND (attr); else if (attr->form == DW_FORM_udata || attr->form == DW_FORM_data1 @@ -19896,6 +20667,7 @@ dwarf2_get_attr_constant_value (const struct attribute *attr, int default_value) return DW_UNSND (attr); else { + /* For DW_FORM_data16 see attr_form_is_constant. */ complaint (&symfile_complaints, _("Attribute value is not a constant (%s)"), dwarf_form_name (attr->form)); @@ -19933,7 +20705,7 @@ follow_die_ref_or_sig (struct die_info *src_die, const struct attribute *attr, Returns NULL if OFFSET is invalid. */ static struct die_info * -follow_die_offset (sect_offset offset, int offset_in_dwz, +follow_die_offset (sect_offset sect_off, int offset_in_dwz, struct dwarf2_cu **ref_cu) { struct die_info temp_die; @@ -19948,15 +20720,15 @@ follow_die_offset (sect_offset offset, int offset_in_dwz, /* .debug_types CUs cannot reference anything outside their CU. If they need to, they have to reference a signatured type via DW_FORM_ref_sig8. */ - if (! offset_in_cu_p (&cu->header, offset)) + if (!offset_in_cu_p (&cu->header, sect_off)) return NULL; } else if (offset_in_dwz != cu->per_cu->is_dwz - || ! offset_in_cu_p (&cu->header, offset)) + || !offset_in_cu_p (&cu->header, sect_off)) { struct dwarf2_per_cu_data *per_cu; - per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz, + per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz, cu->objfile); /* If necessary, add it to the queue and load its DIEs. */ @@ -19973,8 +20745,10 @@ follow_die_offset (sect_offset offset, int offset_in_dwz, } *ref_cu = target_cu; - temp_die.offset = offset; - return htab_find_with_hash (target_cu->die_hash, &temp_die, offset.sect_off); + temp_die.sect_off = sect_off; + return (struct die_info *) htab_find_with_hash (target_cu->die_hash, + &temp_die, + to_underlying (sect_off)); } /* Follow reference attribute ATTR of SRC_DIE. @@ -19985,29 +20759,29 @@ static struct die_info * follow_die_ref (struct die_info *src_die, const struct attribute *attr, struct dwarf2_cu **ref_cu) { - sect_offset offset = dwarf2_get_ref_die_offset (attr); + sect_offset sect_off = dwarf2_get_ref_die_offset (attr); struct dwarf2_cu *cu = *ref_cu; struct die_info *die; - die = follow_die_offset (offset, + die = follow_die_offset (sect_off, (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz), ref_cu); if (!die) error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE " "at 0x%x [in module %s]"), - offset.sect_off, src_die->offset.sect_off, + to_underlying (sect_off), to_underlying (src_die->sect_off), objfile_name (cu->objfile)); return die; } -/* Return DWARF block referenced by DW_AT_location of DIE at OFFSET at PER_CU. +/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU. Returned value is intended for DW_OP_call*. Returned dwarf2_locexpr_baton->data has lifetime of PER_CU->OBJFILE. */ struct dwarf2_locexpr_baton -dwarf2_fetch_die_loc_sect_off (sect_offset offset, +dwarf2_fetch_die_loc_sect_off (sect_offset sect_off, struct dwarf2_per_cu_data *per_cu, CORE_ADDR (*get_frame_pc) (void *baton), void *baton) @@ -20027,13 +20801,13 @@ dwarf2_fetch_die_loc_sect_off (sect_offset offset, /* We shouldn't get here for a dummy CU, but don't crash on the user. Instead just throw an error, not much else we can do. */ error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"), - offset.sect_off, objfile_name (per_cu->objfile)); + to_underlying (sect_off), objfile_name (per_cu->objfile)); } - die = follow_die_offset (offset, per_cu->is_dwz, &cu); + die = follow_die_offset (sect_off, per_cu->is_dwz, &cu); if (!die) error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"), - offset.sect_off, objfile_name (per_cu->objfile)); + to_underlying (sect_off), objfile_name (per_cu->objfile)); attr = dwarf2_attr (die, DW_AT_location, cu); if (!attr) @@ -20061,7 +20835,7 @@ dwarf2_fetch_die_loc_sect_off (sect_offset 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.sect_off, objfile_name (per_cu->objfile)); + to_underlying (sect_off), objfile_name (per_cu->objfile)); retval.data = DW_BLOCK (attr)->data; retval.size = DW_BLOCK (attr)->size; @@ -20082,9 +20856,9 @@ dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu, CORE_ADDR (*get_frame_pc) (void *baton), void *baton) { - sect_offset offset = { per_cu->offset.sect_off + offset_in_cu.cu_off }; + sect_offset sect_off = per_cu->sect_off + to_underlying (offset_in_cu); - return dwarf2_fetch_die_loc_sect_off (offset, per_cu, get_frame_pc, baton); + return dwarf2_fetch_die_loc_sect_off (sect_off, per_cu, get_frame_pc, baton); } /* Write a constant of a given type as target-ordered bytes into @@ -20100,7 +20874,7 @@ write_constant_as_bytes (struct obstack *obstack, gdb_byte *result; *len = TYPE_LENGTH (type); - result = obstack_alloc (obstack, *len); + result = (gdb_byte *) obstack_alloc (obstack, *len); store_unsigned_integer (result, *len, byte_order, value); return result; @@ -20112,7 +20886,7 @@ write_constant_as_bytes (struct obstack *obstack, does not have a DW_AT_const_value, return NULL. */ const gdb_byte * -dwarf2_fetch_constant_bytes (sect_offset offset, +dwarf2_fetch_constant_bytes (sect_offset sect_off, struct dwarf2_per_cu_data *per_cu, struct obstack *obstack, LONGEST *len) @@ -20135,13 +20909,13 @@ dwarf2_fetch_constant_bytes (sect_offset offset, /* We shouldn't get here for a dummy CU, but don't crash on the user. Instead just throw an error, not much else we can do. */ error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"), - offset.sect_off, objfile_name (per_cu->objfile)); + to_underlying (sect_off), objfile_name (per_cu->objfile)); } - die = follow_die_offset (offset, per_cu->is_dwz, &cu); + die = follow_die_offset (sect_off, per_cu->is_dwz, &cu); if (!die) error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"), - offset.sect_off, objfile_name (per_cu->objfile)); + to_underlying (sect_off), objfile_name (per_cu->objfile)); attr = dwarf2_attr (die, DW_AT_const_value, cu); @@ -20159,7 +20933,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset, gdb_byte *tem; *len = cu->header.addr_size; - tem = obstack_alloc (obstack, *len); + tem = (gdb_byte *) obstack_alloc (obstack, *len); store_unsigned_integer (tem, *len, byte_order, DW_ADDR (attr)); result = tem; } @@ -20178,6 +20952,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset, case DW_FORM_block4: case DW_FORM_block: case DW_FORM_exprloc: + case DW_FORM_data16: result = DW_BLOCK (attr)->data; *len = DW_BLOCK (attr)->size; break; @@ -20217,6 +20992,7 @@ dwarf2_fetch_constant_bytes (sect_offset offset, break; case DW_FORM_sdata: + case DW_FORM_implicit_const: type = die_type (die, cu); result = write_constant_as_bytes (obstack, byte_order, type, DW_SND (attr), len); @@ -20238,6 +21014,31 @@ dwarf2_fetch_constant_bytes (sect_offset offset, return result; } +/* Return the type of the die at OFFSET in PER_CU. Return NULL if no + valid type for this die is found. */ + +struct type * +dwarf2_fetch_die_type_sect_off (sect_offset sect_off, + struct dwarf2_per_cu_data *per_cu) +{ + struct dwarf2_cu *cu; + struct die_info *die; + + dw2_setup (per_cu->objfile); + + if (per_cu->cu == NULL) + load_cu (per_cu); + cu = per_cu->cu; + if (!cu) + return NULL; + + die = follow_die_offset (sect_off, per_cu->is_dwz, &cu); + if (!die) + return NULL; + + return die_type (die, cu); +} + /* Return the type of the DIE at DIE_OFFSET in the CU named by PER_CU. */ @@ -20245,11 +21046,9 @@ struct type * 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); - die_offset_sect.sect_off = per_cu->offset.sect_off + die_offset.cu_off; + sect_offset die_offset_sect = per_cu->sect_off + to_underlying (die_offset); return get_die_type_at_offset (die_offset_sect, per_cu); } @@ -20262,7 +21061,6 @@ static struct die_info * follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type, struct dwarf2_cu **ref_cu) { - struct objfile *objfile = (*ref_cu)->objfile; struct die_info temp_die; struct dwarf2_cu *sig_cu; struct die_info *die; @@ -20278,10 +21076,10 @@ follow_die_sig_1 (struct die_info *src_die, struct signatured_type *sig_type, sig_cu = sig_type->per_cu.cu; gdb_assert (sig_cu != NULL); - gdb_assert (sig_type->type_offset_in_section.sect_off != 0); - temp_die.offset = sig_type->type_offset_in_section; - die = htab_find_with_hash (sig_cu->die_hash, &temp_die, - temp_die.offset.sect_off); + gdb_assert (to_underlying (sig_type->type_offset_in_section) != 0); + temp_die.sect_off = sig_type->type_offset_in_section; + die = (struct die_info *) htab_find_with_hash (sig_cu->die_hash, &temp_die, + to_underlying (temp_die.sect_off)); if (die) { /* For .gdb_index version 7 keep track of included TUs. @@ -20324,7 +21122,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr, { error (_("Dwarf Error: Cannot find signatured DIE %s referenced" " from DIE at 0x%x [in module %s]"), - hex_string (signature), src_die->offset.sect_off, + hex_string (signature), to_underlying (src_die->sect_off), objfile_name ((*ref_cu)->objfile)); } @@ -20334,7 +21132,7 @@ follow_die_sig (struct die_info *src_die, const struct attribute *attr, dump_die_for_error (src_die); error (_("Dwarf Error: Problem reading signatured DIE %s referenced" " from DIE at 0x%x [in module %s]"), - hex_string (signature), src_die->offset.sect_off, + hex_string (signature), to_underlying (src_die->sect_off), objfile_name ((*ref_cu)->objfile)); } @@ -20361,7 +21159,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature, complaint (&symfile_complaints, _("Dwarf Error: Cannot find signatured DIE %s referenced" " from DIE at 0x%x [in module %s]"), - hex_string (signature), die->offset.sect_off, + hex_string (signature), to_underlying (die->sect_off), objfile_name (dwarf2_per_objfile->objfile)); return build_error_marker_type (cu, die); } @@ -20383,7 +21181,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature, complaint (&symfile_complaints, _("Dwarf Error: Cannot build signatured type %s" " referenced from DIE at 0x%x [in module %s]"), - hex_string (signature), die->offset.sect_off, + hex_string (signature), to_underlying (die->sect_off), objfile_name (dwarf2_per_objfile->objfile)); type = build_error_marker_type (cu, die); } @@ -20393,7 +21191,7 @@ get_signatured_type (struct die_info *die, ULONGEST signature, complaint (&symfile_complaints, _("Dwarf Error: Problem reading signatured DIE %s referenced" " from DIE at 0x%x [in module %s]"), - hex_string (signature), die->offset.sect_off, + hex_string (signature), to_underlying (die->sect_off), objfile_name (dwarf2_per_objfile->objfile)); type = build_error_marker_type (cu, die); } @@ -20426,7 +21224,7 @@ get_DW_AT_signature_type (struct die_info *die, const struct attribute *attr, complaint (&symfile_complaints, _("Dwarf Error: DW_AT_signature has bad form %s in DIE" " at 0x%x [in module %s]"), - dwarf_form_name (attr->form), die->offset.sect_off, + dwarf_form_name (attr->form), to_underlying (die->sect_off), objfile_name (dwarf2_per_objfile->objfile)); return build_error_marker_type (cu, die); } @@ -20715,6 +21513,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) break; case DW_OP_GNU_push_tls_address: + case DW_OP_form_tls_address: /* The top of the stack has the offset from the beginning of the thread control block at which the variable is located. */ /* Nothing should follow this operator, so the top of stack would @@ -20777,11 +21576,7 @@ decode_locdesc (struct dwarf_block *blk, struct dwarf2_cu *cu) static struct dwarf_block * dwarf_alloc_block (struct dwarf2_cu *cu) { - struct dwarf_block *blk; - - blk = (struct dwarf_block *) - obstack_alloc (&cu->comp_unit_obstack, sizeof (struct dwarf_block)); - return (blk); + return XOBNEW (&cu->comp_unit_obstack, struct dwarf_block); } static struct die_info * @@ -20810,15 +21605,17 @@ file_file_name (int file, struct line_header *lh) { /* Is the file number a valid index into the line header's file name table? Remember that file numbers start with one, not zero. */ - if (1 <= file && file <= lh->num_file_names) + if (1 <= file && file <= lh->file_names.size ()) { - struct file_entry *fe = &lh->file_names[file - 1]; + const file_entry &fe = lh->file_names[file - 1]; - if (IS_ABSOLUTE_PATH (fe->name) || fe->dir_index == 0 - || lh->include_dirs == NULL) - return xstrdup (fe->name); - return concat (lh->include_dirs[fe->dir_index - 1], SLASH_STRING, - fe->name, NULL); + if (!IS_ABSOLUTE_PATH (fe.name)) + { + const char *dir = fe.include_dir (lh); + if (dir != NULL) + return concat (dir, SLASH_STRING, fe.name, (char *) NULL); + } + return xstrdup (fe.name); } else { @@ -20847,13 +21644,14 @@ file_full_name (int file, struct line_header *lh, const char *comp_dir) { /* Is the file number a valid index into the line header's file name table? Remember that file numbers start with one, not zero. */ - if (1 <= file && file <= lh->num_file_names) + if (1 <= file && file <= lh->file_names.size ()) { char *relative = file_file_name (file, lh); if (IS_ABSOLUTE_PATH (relative) || comp_dir == NULL) return relative; - return reconcat (relative, comp_dir, SLASH_STRING, relative, NULL); + return reconcat (relative, comp_dir, SLASH_STRING, + relative, (char *) NULL); } else return file_file_name (file, lh); @@ -20893,7 +21691,7 @@ macro_start_file (int file, int line, static char * copy_string (const char *buf, int len) { - char *s = xmalloc (len + 1); + char *s = (char *) xmalloc (len + 1); memcpy (s, buf, len); s[len] = '\0'; @@ -20981,7 +21779,7 @@ parse_macro_definition (struct macro_source_file *file, int line, char *name = copy_string (body, p - body); int argc = 0; int argv_size = 1; - char **argv = xmalloc (argv_size * sizeof (*argv)); + char **argv = XNEWVEC (char *, argv_size); p++; @@ -21004,7 +21802,7 @@ parse_macro_definition (struct macro_source_file *file, int line, if (argc >= argv_size) { argv_size *= 2; - argv = xrealloc (argv, argv_size * sizeof (*argv)); + argv = XRESIZEVEC (char *, argv, argv_size); } argv[argc++] = copy_string (arg_start, p - arg_start); @@ -21089,6 +21887,10 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end, bytes += 8; break; + case DW_FORM_data16: + bytes += 16; + break; + case DW_FORM_string: read_direct_string (abfd, bytes, &bytes_read); bytes += bytes_read; @@ -21127,6 +21929,9 @@ skip_form_bytes (bfd *abfd, const gdb_byte *bytes, const gdb_byte *buffer_end, } break; + case DW_FORM_implicit_const: + break; + default: { complain: @@ -21170,7 +21975,8 @@ skip_unknown_opcode (unsigned int opcode, for (i = 0; i < arg; ++i) { - mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end, defn[i], offset_size, + mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end, + (enum dwarf_form) defn[i], offset_size, section); if (mac_ptr == NULL) { @@ -21201,7 +22007,7 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions, unsigned int version, flags; version = read_2_bytes (abfd, mac_ptr); - if (version != 4) + if (version != 4 && version != 5) { complaint (&symfile_complaints, _("unrecognized version `%d' in .debug_macro section"), @@ -21244,7 +22050,7 @@ dwarf_parse_macro_header (const gdb_byte **opcode_definitions, } /* A helper for dwarf_decode_macros that handles the GNU extensions, - including DW_MACRO_GNU_transparent_include. */ + including DW_MACRO_import. */ static void dwarf_decode_macro_bytes (bfd *abfd, @@ -21287,7 +22093,7 @@ dwarf_decode_macro_bytes (bfd *abfd, break; } - macinfo_type = read_1_byte (abfd, mac_ptr); + macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr); mac_ptr++; /* Note that we rely on the fact that the corresponding GNU and @@ -21299,12 +22105,12 @@ dwarf_decode_macro_bytes (bfd *abfd, case 0: break; - case DW_MACRO_GNU_define: - case DW_MACRO_GNU_undef: - case DW_MACRO_GNU_define_indirect: - case DW_MACRO_GNU_undef_indirect: - case DW_MACRO_GNU_define_indirect_alt: - case DW_MACRO_GNU_undef_indirect_alt: + case DW_MACRO_define: + case DW_MACRO_undef: + case DW_MACRO_define_strp: + case DW_MACRO_undef_strp: + case DW_MACRO_define_sup: + case DW_MACRO_undef_sup: { unsigned int bytes_read; int line; @@ -21314,8 +22120,8 @@ dwarf_decode_macro_bytes (bfd *abfd, line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); mac_ptr += bytes_read; - if (macinfo_type == DW_MACRO_GNU_define - || macinfo_type == DW_MACRO_GNU_undef) + if (macinfo_type == DW_MACRO_define + || macinfo_type == DW_MACRO_undef) { body = read_direct_string (abfd, mac_ptr, &bytes_read); mac_ptr += bytes_read; @@ -21327,8 +22133,8 @@ dwarf_decode_macro_bytes (bfd *abfd, str_offset = read_offset_1 (abfd, mac_ptr, offset_size); mac_ptr += offset_size; - if (macinfo_type == DW_MACRO_GNU_define_indirect_alt - || macinfo_type == DW_MACRO_GNU_undef_indirect_alt + if (macinfo_type == DW_MACRO_define_sup + || macinfo_type == DW_MACRO_undef_sup || section_is_dwz) { struct dwz_file *dwz = dwarf2_get_dwz_file (); @@ -21339,9 +22145,9 @@ dwarf_decode_macro_bytes (bfd *abfd, body = read_indirect_string_at_offset (abfd, str_offset); } - is_define = (macinfo_type == DW_MACRO_GNU_define - || macinfo_type == DW_MACRO_GNU_define_indirect - || macinfo_type == DW_MACRO_GNU_define_indirect_alt); + is_define = (macinfo_type == DW_MACRO_define + || macinfo_type == DW_MACRO_define_strp + || macinfo_type == DW_MACRO_define_sup); if (! current_file) { /* DWARF violation as no main source is present. */ @@ -21364,15 +22170,15 @@ dwarf_decode_macro_bytes (bfd *abfd, parse_macro_definition (current_file, line, body); else { - gdb_assert (macinfo_type == DW_MACRO_GNU_undef - || macinfo_type == DW_MACRO_GNU_undef_indirect - || macinfo_type == DW_MACRO_GNU_undef_indirect_alt); + gdb_assert (macinfo_type == DW_MACRO_undef + || macinfo_type == DW_MACRO_undef_strp + || macinfo_type == DW_MACRO_undef_sup); macro_undef (current_file, line, body); } } break; - case DW_MACRO_GNU_start_file: + case DW_MACRO_start_file: { unsigned int bytes_read; int line, file; @@ -21392,7 +22198,7 @@ dwarf_decode_macro_bytes (bfd *abfd, if (at_commandline) { - /* This DW_MACRO_GNU_start_file was executed in the + /* This DW_MACRO_start_file was executed in the pass one. */ at_commandline = 0; } @@ -21401,7 +22207,7 @@ dwarf_decode_macro_bytes (bfd *abfd, } break; - case DW_MACRO_GNU_end_file: + case DW_MACRO_end_file: if (! current_file) complaint (&symfile_complaints, _("macro debug info has an unmatched " @@ -21427,7 +22233,9 @@ dwarf_decode_macro_bytes (bfd *abfd, /* We don't increment mac_ptr here, so this is just a look-ahead. */ - next_type = read_1_byte (abfd, mac_ptr); + next_type + = (enum dwarf_macro_record_type) read_1_byte (abfd, + mac_ptr); if (next_type != 0) complaint (&symfile_complaints, _("no terminating 0-type entry for " @@ -21438,14 +22246,13 @@ dwarf_decode_macro_bytes (bfd *abfd, } break; - case DW_MACRO_GNU_transparent_include: - case DW_MACRO_GNU_transparent_include_alt: + case DW_MACRO_import: + case DW_MACRO_import_sup: { LONGEST offset; void **slot; bfd *include_bfd = abfd; struct dwarf2_section_info *include_section = section; - struct dwarf2_section_info alt_section; const gdb_byte *include_mac_end = mac_end; int is_dwz = section_is_dwz; const gdb_byte *new_mac_ptr; @@ -21453,7 +22260,7 @@ dwarf_decode_macro_bytes (bfd *abfd, offset = read_offset_1 (abfd, mac_ptr, offset_size); mac_ptr += offset_size; - if (macinfo_type == DW_MACRO_GNU_transparent_include_alt) + if (macinfo_type == DW_MACRO_import_sup) { struct dwz_file *dwz = dwarf2_get_dwz_file (); @@ -21473,7 +22280,7 @@ dwarf_decode_macro_bytes (bfd *abfd, /* This has actually happened; see http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */ complaint (&symfile_complaints, - _("recursive DW_MACRO_GNU_transparent_include in " + _("recursive DW_MACRO_import in " ".debug_macro section")); } else @@ -21494,9 +22301,10 @@ dwarf_decode_macro_bytes (bfd *abfd, if (!section_is_gnu) { unsigned int bytes_read; - int constant; - constant = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); + /* This reads the constant, but since we don't recognize + any vendor extensions, we ignore it. */ + read_unsigned_leb128 (abfd, mac_ptr, &bytes_read); mac_ptr += bytes_read; read_direct_string (abfd, mac_ptr, &bytes_read); mac_ptr += bytes_read; @@ -21530,7 +22338,6 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, unsigned int offset_size = cu->header.offset_size; const gdb_byte *opcode_definitions[256]; struct cleanup *cleanup; - htab_t include_hash; void **slot; struct dwarf2_section_info *section; const char *section_name; @@ -21603,7 +22410,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, break; } - macinfo_type = read_1_byte (abfd, mac_ptr); + macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr); mac_ptr++; /* Note that we rely on the fact that the corresponding GNU and @@ -21615,8 +22422,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, case 0: break; - case DW_MACRO_GNU_define: - case DW_MACRO_GNU_undef: + case DW_MACRO_define: + case DW_MACRO_undef: /* Only skip the data by MAC_PTR. */ { unsigned int bytes_read; @@ -21628,7 +22435,7 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, } break; - case DW_MACRO_GNU_start_file: + case DW_MACRO_start_file: { unsigned int bytes_read; int line, file; @@ -21642,14 +22449,14 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, } break; - case DW_MACRO_GNU_end_file: + case DW_MACRO_end_file: /* No data to skip by MAC_PTR. */ break; - case DW_MACRO_GNU_define_indirect: - case DW_MACRO_GNU_undef_indirect: - case DW_MACRO_GNU_define_indirect_alt: - case DW_MACRO_GNU_undef_indirect_alt: + case DW_MACRO_define_strp: + case DW_MACRO_undef_strp: + case DW_MACRO_define_sup: + case DW_MACRO_undef_sup: { unsigned int bytes_read; @@ -21659,10 +22466,10 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, } break; - case DW_MACRO_GNU_transparent_include: - case DW_MACRO_GNU_transparent_include_alt: + case DW_MACRO_import: + case DW_MACRO_import_sup: /* Note that, according to the spec, a transparent include - chain cannot call DW_MACRO_GNU_start_file. So, we can just + chain cannot call DW_MACRO_start_file. So, we can just skip this opcode. */ mac_ptr += offset_size; break; @@ -21696,16 +22503,16 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, command-line macro definitions/undefinitions. This flag is unset when we reach the first DW_MACINFO_start_file entry. */ - include_hash = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer, - NULL, xcalloc, xfree); - cleanup = make_cleanup_htab_delete (include_hash); + htab_up include_hash (htab_create_alloc (1, htab_hash_pointer, + htab_eq_pointer, + NULL, xcalloc, xfree)); mac_ptr = section->buffer + offset; - slot = htab_find_slot (include_hash, mac_ptr, INSERT); + slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT); *slot = (void *) mac_ptr; dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end, current_file, lh, section, - section_is_gnu, 0, offset_size, include_hash); - do_cleanups (cleanup); + section_is_gnu, 0, offset_size, + include_hash.get ()); } /* Check if the attribute's form is a DW_FORM_block* @@ -21750,7 +22557,10 @@ attr_form_is_section_offset (const struct attribute *attr) (lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says 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. */ + taken as section offsets, not constants. + + DW_FORM_data16 is not considered as dwarf2_get_attr_constant_value + cannot handle that. */ static int attr_form_is_constant (const struct attribute *attr) @@ -21763,6 +22573,7 @@ attr_form_is_constant (const struct attribute *attr) case DW_FORM_data2: case DW_FORM_data4: case DW_FORM_data8: + case DW_FORM_implicit_const: return 1; default: return 0; @@ -21798,8 +22609,13 @@ 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; + { + struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections; + + return cu->header.version >= 5 ? §ions->loclists : §ions->loc; + } + return (cu->header.version >= 5 ? &dwarf2_per_objfile->loclists + : &dwarf2_per_objfile->loc); } /* A helper function that fills in a dwarf2_loclist_baton. */ @@ -21838,8 +22654,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, { struct dwarf2_loclist_baton *baton; - baton = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_loclist_baton)); + baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_loclist_baton); fill_in_loclist_baton (cu, baton, attr); @@ -21857,8 +22672,7 @@ dwarf2_symbol_mark_computed (const struct attribute *attr, struct symbol *sym, { struct dwarf2_locexpr_baton *baton; - baton = obstack_alloc (&objfile->objfile_obstack, - sizeof (struct dwarf2_locexpr_baton)); + baton = XOBNEW (&objfile->objfile_obstack, struct dwarf2_locexpr_baton); baton->per_cu = cu->per_cu; gdb_assert (baton->per_cu); @@ -21916,10 +22730,11 @@ per_cu_header_read_in (struct comp_unit_head *cu_headerp, if (per_cu->cu) return &per_cu->cu->header; - info_ptr = per_cu->section->buffer + per_cu->offset.sect_off; + info_ptr = per_cu->section->buffer + to_underlying (per_cu->sect_off); memset (cu_headerp, 0, sizeof (*cu_headerp)); - read_comp_unit_head (cu_headerp, info_ptr, per_cu->objfile->obfd); + read_comp_unit_head (cu_headerp, info_ptr, per_cu->section, + rcuh_kind::COMPILE); return cu_headerp; } @@ -21979,11 +22794,19 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu) return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); } +/* Return DWARF version number of PER_CU. */ + +short +dwarf2_version (struct dwarf2_per_cu_data *per_cu) +{ + return per_cu->dwarf_version; +} + /* Locate the .debug_info compilation unit from CU's objfile which contains the DIE at OFFSET. Raises an error on failure. */ static struct dwarf2_per_cu_data * -dwarf2_find_containing_comp_unit (sect_offset offset, +dwarf2_find_containing_comp_unit (sect_offset sect_off, unsigned int offset_in_dwz, struct objfile *objfile) { @@ -21999,35 +22822,34 @@ dwarf2_find_containing_comp_unit (sect_offset offset, int mid = low + (high - low) / 2; mid_cu = dwarf2_per_objfile->all_comp_units[mid]; - cu_off = &mid_cu->offset; + cu_off = &mid_cu->sect_off; if (mid_cu->is_dwz > offset_in_dwz - || (mid_cu->is_dwz == offset_in_dwz - && cu_off->sect_off >= offset.sect_off)) + || (mid_cu->is_dwz == offset_in_dwz && *cu_off >= sect_off)) high = mid; else low = mid + 1; } gdb_assert (low == high); this_cu = dwarf2_per_objfile->all_comp_units[low]; - cu_off = &this_cu->offset; - if (this_cu->is_dwz != offset_in_dwz || cu_off->sect_off > offset.sect_off) + cu_off = &this_cu->sect_off; + if (this_cu->is_dwz != offset_in_dwz || *cu_off > sect_off) { if (low == 0 || this_cu->is_dwz != offset_in_dwz) error (_("Dwarf Error: could not find partial DIE containing " - "offset 0x%lx [in module %s]"), - (long) offset.sect_off, bfd_get_filename (objfile->obfd)); + "offset 0x%x [in module %s]"), + to_underlying (sect_off), bfd_get_filename (objfile->obfd)); - gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->offset.sect_off - <= offset.sect_off); + gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->sect_off + <= 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.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); + && sect_off >= this_cu->sect_off + this_cu->length) + error (_("invalid dwarf2 offset %u"), to_underlying (sect_off)); + gdb_assert (sect_off < this_cu->sect_off + this_cu->length); return this_cu; } } @@ -22062,9 +22884,7 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die, cu->language_defn = language_def (cu->language); } - attr = dwarf2_attr (comp_unit_die, DW_AT_producer, cu); - if (attr) - cu->producer = DW_STRING (attr); + cu->producer = dwarf2_string_attr (comp_unit_die, DW_AT_producer, cu); } /* Release one cached compilation unit, CU. We unlink it from the tree @@ -22076,7 +22896,7 @@ prepare_one_comp_unit (struct dwarf2_cu *cu, struct die_info *comp_unit_die, static void free_heap_comp_unit (void *data) { - struct dwarf2_cu *cu = data; + struct dwarf2_cu *cu = (struct dwarf2_cu *) data; gdb_assert (cu->per_cu != NULL); cu->per_cu->cu = NULL; @@ -22094,7 +22914,7 @@ free_heap_comp_unit (void *data) static void free_stack_comp_unit (void *data) { - struct dwarf2_cu *cu = data; + struct dwarf2_cu *cu = (struct dwarf2_cu *) data; gdb_assert (cu->per_cu != NULL); cu->per_cu->cu = NULL; @@ -22109,21 +22929,7 @@ free_stack_comp_unit (void *data) static void free_cached_comp_units (void *data) { - struct dwarf2_per_cu_data *per_cu, **last_chain; - - per_cu = dwarf2_per_objfile->read_in_chain; - last_chain = &dwarf2_per_objfile->read_in_chain; - while (per_cu != NULL) - { - struct dwarf2_per_cu_data *next_cu; - - next_cu = per_cu->cu->read_in_chain; - - free_heap_comp_unit (per_cu->cu); - *last_chain = next_cu; - - per_cu = next_cu; - } + dwarf2_per_objfile->free_cached_comp_units (); } /* Increase the age counter on each cached compilation unit, and free @@ -22198,21 +23004,14 @@ free_one_cached_comp_unit (struct dwarf2_per_cu_data *target_per_cu) void dwarf2_free_objfile (struct objfile *objfile) { - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + dwarf2_per_objfile + = (struct dwarf2_per_objfile *) objfile_data (objfile, + dwarf2_objfile_data_key); if (dwarf2_per_objfile == NULL) return; - /* Cached DIE trees use xmalloc and the comp_unit_obstack. */ - free_cached_comp_units (NULL); - - if (dwarf2_per_objfile->quick_file_names_table) - htab_delete (dwarf2_per_objfile->quick_file_names_table); - - if (dwarf2_per_objfile->line_header_hash) - htab_delete (dwarf2_per_objfile->line_header_hash); - - /* Everything else should be on the objfile obstack. */ + dwarf2_per_objfile->~dwarf2_per_objfile (); } /* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer. @@ -22232,7 +23031,7 @@ dwarf2_free_objfile (struct objfile *objfile) struct dwarf2_per_cu_offset_and_type { const struct dwarf2_per_cu_data *per_cu; - sect_offset offset; + sect_offset sect_off; struct type *type; }; @@ -22241,9 +23040,10 @@ struct dwarf2_per_cu_offset_and_type static hashval_t per_cu_offset_and_type_hash (const void *item) { - const struct dwarf2_per_cu_offset_and_type *ofs = item; + const struct dwarf2_per_cu_offset_and_type *ofs + = (const struct dwarf2_per_cu_offset_and_type *) item; - return (uintptr_t) ofs->per_cu + ofs->offset.sect_off; + return (uintptr_t) ofs->per_cu + to_underlying (ofs->sect_off); } /* Equality function for a dwarf2_per_cu_offset_and_type. */ @@ -22251,11 +23051,13 @@ per_cu_offset_and_type_hash (const void *item) static int per_cu_offset_and_type_eq (const void *item_lhs, const void *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; + const struct dwarf2_per_cu_offset_and_type *ofs_lhs + = (const struct dwarf2_per_cu_offset_and_type *) item_lhs; + const struct dwarf2_per_cu_offset_and_type *ofs_rhs + = (const struct dwarf2_per_cu_offset_and_type *) item_rhs; return (ofs_lhs->per_cu == ofs_rhs->per_cu - && ofs_lhs->offset.sect_off == ofs_rhs->offset.sect_off); + && ofs_lhs->sect_off == ofs_rhs->sect_off); } /* Set the type associated with DIE to TYPE. Save it in CU's hash @@ -22300,6 +23102,36 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) && !HAVE_GNAT_AUX_INFO (type)) INIT_GNAT_SPECIFIC (type); + /* Read DW_AT_allocated and set in type. */ + attr = dwarf2_attr (die, DW_AT_allocated, cu); + if (attr_form_is_block (attr)) + { + if (attr_to_dynamic_prop (attr, die, cu, &prop)) + add_dyn_prop (DYN_PROP_ALLOCATED, prop, type, objfile); + } + else if (attr != NULL) + { + complaint (&symfile_complaints, + _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"), + (attr != NULL ? dwarf_form_name (attr->form) : "n/a"), + to_underlying (die->sect_off)); + } + + /* Read DW_AT_associated and set in type. */ + attr = dwarf2_attr (die, DW_AT_associated, cu); + if (attr_form_is_block (attr)) + { + if (attr_to_dynamic_prop (attr, die, cu, &prop)) + add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type, objfile); + } + else if (attr != NULL) + { + complaint (&symfile_complaints, + _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"), + (attr != NULL ? dwarf_form_name (attr->form) : "n/a"), + to_underlying (die->sect_off)); + } + /* Read DW_AT_data_location and set in type. */ attr = dwarf2_attr (die, DW_AT_data_location, cu); if (attr_to_dynamic_prop (attr, die, cu, &prop)) @@ -22318,24 +23150,25 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) } ofs.per_cu = cu->per_cu; - ofs.offset = die->offset; + ofs.sect_off = die->sect_off; ofs.type = type; 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.sect_off); - *slot = obstack_alloc (&objfile->objfile_obstack, sizeof (**slot)); + to_underlying (die->sect_off)); + *slot = XOBNEW (&objfile->objfile_obstack, + struct dwarf2_per_cu_offset_and_type); **slot = ofs; return type; } -/* Look up the type for the die at OFFSET in PER_CU in die_type_hash, +/* Look up the type for the die at SECT_OFF in PER_CU in die_type_hash, or return NULL if the die does not have a saved type. */ static struct type * -get_die_type_at_offset (sect_offset offset, +get_die_type_at_offset (sect_offset sect_off, struct dwarf2_per_cu_data *per_cu) { struct dwarf2_per_cu_offset_and_type *slot, ofs; @@ -22344,8 +23177,9 @@ get_die_type_at_offset (sect_offset offset, return NULL; ofs.per_cu = per_cu; - ofs.offset = offset; - slot = htab_find (dwarf2_per_objfile->die_type_hash, &ofs); + ofs.sect_off = sect_off; + slot = ((struct dwarf2_per_cu_offset_and_type *) + htab_find (dwarf2_per_objfile->die_type_hash, &ofs)); if (slot) return slot->type; else @@ -22358,7 +23192,7 @@ get_die_type_at_offset (sect_offset offset, static struct type * get_die_type (struct die_info *die, struct dwarf2_cu *cu) { - return get_die_type_at_offset (die->offset, cu->per_cu); + return get_die_type_at_offset (die->sect_off, cu->per_cu); } /* Add a dependence relationship from CU to REF_PER_CU. */ @@ -22437,9 +23271,10 @@ dwarf2_clear_marks (struct dwarf2_per_cu_data *per_cu) static hashval_t partial_die_hash (const void *item) { - const struct partial_die_info *part_die = item; + const struct partial_die_info *part_die + = (const struct partial_die_info *) item; - return part_die->offset.sect_off; + return to_underlying (part_die->sect_off); } /* Trivial comparison function for partial_die_info structures: two DIEs @@ -22448,10 +23283,12 @@ partial_die_hash (const void *item) static int 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; + const struct partial_die_info *part_die_lhs + = (const struct partial_die_info *) item_lhs; + const struct partial_die_info *part_die_rhs + = (const struct partial_die_info *) item_rhs; - return part_die_lhs->offset.sect_off == part_die_rhs->offset.sect_off; + return part_die_lhs->sect_off == part_die_rhs->sect_off; } static struct cmd_list_element *set_dwarf_cmdlist; @@ -22475,7 +23312,7 @@ show_dwarf_cmd (char *args, int from_tty) static void dwarf2_per_objfile_free (struct objfile *objfile, void *d) { - struct dwarf2_per_objfile *data = d; + struct dwarf2_per_objfile *data = (struct dwarf2_per_objfile *) d; int ix; /* Make sure we don't accidentally use dwarf2_per_objfile while @@ -22504,69 +23341,58 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d) /* The "save gdb-index" command. */ -/* The contents of the hash table we create when building the string - table. */ -struct strtab_entry -{ - offset_type offset; - const char *str; -}; - -/* Hash function for a strtab_entry. - - Function is used only during write_hash_table so no index format backward - compatibility is needed. */ - -static hashval_t -hash_strtab_entry (const void *e) +/* In-memory buffer to prepare data to be written later to a file. */ +class data_buf { - const struct strtab_entry *entry = e; - return mapped_index_string_hash (INT_MAX, entry->str); -} - -/* Equality function for a strtab_entry. */ +public: + /* Copy DATA to the end of the buffer. */ + template + void append_data (const T &data) + { + std::copy (reinterpret_cast (&data), + reinterpret_cast (&data + 1), + grow (sizeof (data))); + } -static int -eq_strtab_entry (const void *a, const void *b) -{ - const struct strtab_entry *ea = a; - const struct strtab_entry *eb = b; - return !strcmp (ea->str, eb->str); -} + /* Copy CSTR (a zero-terminated string) to the end of buffer. The + terminating zero is appended too. */ + void append_cstr0 (const char *cstr) + { + const size_t size = strlen (cstr) + 1; + std::copy (cstr, cstr + size, grow (size)); + } -/* Create a strtab_entry hash table. */ + /* Accept a host-format integer in VAL and append it to the buffer + as a target-format integer which is LEN bytes long. */ + void append_uint (size_t len, bfd_endian byte_order, ULONGEST val) + { + ::store_unsigned_integer (grow (len), len, byte_order, val); + } -static htab_t -create_strtab (void) -{ - return htab_create_alloc (100, hash_strtab_entry, eq_strtab_entry, - xfree, xcalloc, xfree); -} + /* Return the size of the buffer. */ + size_t size () const + { + return m_vec.size (); + } -/* Add a string to the constant pool. Return the string's offset in - host order. */ + /* Write the buffer to FILE. */ + void file_write (FILE *file) const + { + if (::fwrite (m_vec.data (), 1, m_vec.size (), file) != m_vec.size ()) + error (_("couldn't write data to file")); + } -static offset_type -add_string (htab_t table, struct obstack *cpool, const char *str) -{ - void **slot; - struct strtab_entry entry; - struct strtab_entry *result; +private: + /* Grow SIZE bytes at the end of the buffer. Returns a pointer to + the start of the new block. */ + gdb_byte *grow (size_t size) + { + m_vec.resize (m_vec.size () + size); + return &*m_vec.end () - size; + } - entry.str = str; - slot = htab_find_slot (table, &entry, INSERT); - if (*slot) - result = *slot; - else - { - result = XNEW (struct strtab_entry); - result->offset = obstack_object_size (cpool); - result->str = str; - obstack_grow_str0 (cpool, str); - *slot = result; - } - return result->offset; -} + gdb::byte_vector m_vec; +}; /* An entry in the symbol table. */ struct symtab_index_entry @@ -22577,106 +23403,41 @@ struct symtab_index_entry offset_type index_offset; /* A sorted vector of the indices of all the CUs that hold an object of this name. */ - VEC (offset_type) *cu_indices; + std::vector cu_indices; }; /* The symbol table. This is a power-of-2-sized hash table. */ struct mapped_symtab { - offset_type n_elements; - offset_type size; - struct symtab_index_entry **data; -}; - -/* Hash function for a symtab_index_entry. */ - -static hashval_t -hash_symtab_entry (const void *e) -{ - const struct symtab_index_entry *entry = e; - return iterative_hash (VEC_address (offset_type, entry->cu_indices), - sizeof (offset_type) * VEC_length (offset_type, - entry->cu_indices), - 0); -} - -/* Equality function for a symtab_index_entry. */ - -static int -eq_symtab_entry (const void *a, const void *b) -{ - const struct symtab_index_entry *ea = a; - const struct symtab_index_entry *eb = b; - int len = VEC_length (offset_type, ea->cu_indices); - if (len != VEC_length (offset_type, eb->cu_indices)) - return 0; - return !memcmp (VEC_address (offset_type, ea->cu_indices), - VEC_address (offset_type, eb->cu_indices), - sizeof (offset_type) * len); -} - -/* Destroy a symtab_index_entry. */ - -static void -delete_symtab_entry (void *p) -{ - struct symtab_index_entry *entry = p; - VEC_free (offset_type, entry->cu_indices); - xfree (entry); -} - -/* Create a hash table holding symtab_index_entry objects. */ - -static htab_t -create_symbol_hash_table (void) -{ - return htab_create_alloc (100, hash_symtab_entry, eq_symtab_entry, - delete_symtab_entry, xcalloc, xfree); -} - -/* Create a new mapped symtab object. */ - -static struct mapped_symtab * -create_mapped_symtab (void) -{ - struct mapped_symtab *symtab = XNEW (struct mapped_symtab); - symtab->n_elements = 0; - symtab->size = 1024; - symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size); - return symtab; -} - -/* Destroy a mapped_symtab. */ + mapped_symtab () + { + data.resize (1024); + } -static void -cleanup_mapped_symtab (void *p) -{ - struct mapped_symtab *symtab = p; - /* The contents of the array are freed when the other hash table is - destroyed. */ - xfree (symtab->data); - xfree (symtab); -} + offset_type n_elements = 0; + std::vector data; +}; -/* Find a slot in SYMTAB for the symbol NAME. Returns a pointer to +/* Find a slot in SYMTAB for the symbol NAME. Returns a reference to the slot. Function is used only during write_hash_table so no index format backward compatibility is needed. */ -static struct symtab_index_entry ** +static symtab_index_entry & find_slot (struct mapped_symtab *symtab, const char *name) { offset_type index, step, hash = mapped_index_string_hash (INT_MAX, name); - index = hash & (symtab->size - 1); - step = ((hash * 17) & (symtab->size - 1)) | 1; + index = hash & (symtab->data.size () - 1); + step = ((hash * 17) & (symtab->data.size () - 1)) | 1; for (;;) { - if (!symtab->data[index] || !strcmp (name, symtab->data[index]->name)) - return &symtab->data[index]; - index = (index + step) & (symtab->size - 1); + if (symtab->data[index].name == NULL + || strcmp (name, symtab->data[index].name) == 0) + return symtab->data[index]; + index = (index + step) & (symtab->data.size () - 1); } } @@ -22685,24 +23446,17 @@ find_slot (struct mapped_symtab *symtab, const char *name) static void hash_expand (struct mapped_symtab *symtab) { - offset_type old_size = symtab->size; - offset_type i; - struct symtab_index_entry **old_entries = symtab->data; + auto old_entries = std::move (symtab->data); - symtab->size *= 2; - symtab->data = XCNEWVEC (struct symtab_index_entry *, symtab->size); + symtab->data.clear (); + symtab->data.resize (old_entries.size () * 2); - for (i = 0; i < old_size; ++i) - { - if (old_entries[i]) - { - struct symtab_index_entry **slot = find_slot (symtab, - old_entries[i]->name); - *slot = old_entries[i]; - } - } - - xfree (old_entries); + for (auto &it : old_entries) + if (it.name != NULL) + { + auto &ref = find_slot (symtab, it.name); + ref = std::move (it); + } } /* Add an entry to SYMTAB. NAME is the name of the symbol. @@ -22714,20 +23468,17 @@ 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) + if (4 * symtab->n_elements / 3 >= symtab->data.size ()) hash_expand (symtab); - slot = find_slot (symtab, name); - if (!*slot) + symtab_index_entry &slot = find_slot (symtab, name); + if (slot.name == NULL) { - *slot = XNEW (struct symtab_index_entry); - (*slot)->name = name; + slot.name = name; /* index_offset is set later. */ - (*slot)->cu_indices = NULL; } cu_index_and_attrs = 0; @@ -22742,18 +23493,7 @@ add_index_entry (struct mapped_symtab *symtab, const char *name, 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); + slot.cu_indices.push_back (cu_index_and_attrs); } /* Sort and remove duplicates of all symbols' cu_indices lists. */ @@ -22761,111 +23501,116 @@ offset_type_compare (const void *ap, const void *bp) static void uniquify_cu_indices (struct mapped_symtab *symtab) { - int i; - - for (i = 0; i < symtab->size; ++i) + for (auto &entry : symtab->data) { - struct symtab_index_entry *entry = symtab->data[i]; - - if (entry - && entry->cu_indices != NULL) + if (entry.name != NULL && !entry.cu_indices.empty ()) { - 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); + auto &cu_indices = entry.cu_indices; + std::sort (cu_indices.begin (), cu_indices.end ()); + auto from = std::unique (cu_indices.begin (), cu_indices.end ()); + cu_indices.erase (from, cu_indices.end ()); } } } -/* Add a vector of indices to the constant pool. */ - -static offset_type -add_indices_to_cpool (htab_t symbol_hash_table, struct obstack *cpool, - struct symtab_index_entry *entry) +/* A form of 'const char *' suitable for container keys. Only the + pointer is stored. The strings themselves are compared, not the + pointers. */ +class c_str_view { - void **slot; +public: + c_str_view (const char *cstr) + : m_cstr (cstr) + {} - slot = htab_find_slot (symbol_hash_table, entry, INSERT); - if (!*slot) - { - offset_type len = VEC_length (offset_type, entry->cu_indices); - offset_type val = MAYBE_SWAP (len); - offset_type iter; - int i; + bool operator== (const c_str_view &other) const + { + return strcmp (m_cstr, other.m_cstr) == 0; + } - *slot = entry; - entry->index_offset = obstack_object_size (cpool); +private: + friend class c_str_view_hasher; + const char *const m_cstr; +}; - obstack_grow (cpool, &val, sizeof (val)); - for (i = 0; - VEC_iterate (offset_type, entry->cu_indices, i, iter); - ++i) - { - val = MAYBE_SWAP (iter); - obstack_grow (cpool, &val, sizeof (val)); - } - } - else - { - struct symtab_index_entry *old_entry = *slot; - entry->index_offset = old_entry->index_offset; - entry = old_entry; - } - return entry->index_offset; -} +/* A std::unordered_map::hasher for c_str_view that uses the right + hash function for strings in a mapped index. */ +class c_str_view_hasher +{ +public: + size_t operator () (const c_str_view &x) const + { + return mapped_index_string_hash (INT_MAX, x.m_cstr); + } +}; + +/* A std::unordered_map::hasher for std::vector<>. */ +template +class vector_hasher +{ +public: + size_t operator () (const std::vector &key) const + { + return iterative_hash (key.data (), + sizeof (key.front ()) * key.size (), 0); + } +}; -/* Write the mapped hash table SYMTAB to the obstack OUTPUT, with - constant pool entries going into the obstack CPOOL. */ +/* Write the mapped hash table SYMTAB to the data buffer OUTPUT, with + constant pool entries going into the data buffer CPOOL. */ static void -write_hash_table (struct mapped_symtab *symtab, - struct obstack *output, struct obstack *cpool) +write_hash_table (mapped_symtab *symtab, data_buf &output, data_buf &cpool) { - offset_type i; - htab_t symbol_hash_table; - htab_t str_table; - - symbol_hash_table = create_symbol_hash_table (); - str_table = create_strtab (); + { + /* Elements are sorted vectors of the indices of all the CUs that + hold an object of this name. */ + std::unordered_map, offset_type, + vector_hasher> + symbol_hash_table; + + /* We add all the index vectors to the constant pool first, to + ensure alignment is ok. */ + for (symtab_index_entry &entry : symtab->data) + { + if (entry.name == NULL) + continue; + gdb_assert (entry.index_offset == 0); + + /* Finding before inserting is faster than always trying to + insert, because inserting always allocates a node, does the + lookup, and then destroys the new node if another node + already had the same key. C++17 try_emplace will avoid + this. */ + const auto found + = symbol_hash_table.find (entry.cu_indices); + if (found != symbol_hash_table.end ()) + { + entry.index_offset = found->second; + continue; + } - /* We add all the index vectors to the constant pool first, to - ensure alignment is ok. */ - for (i = 0; i < symtab->size; ++i) - { - if (symtab->data[i]) - add_indices_to_cpool (symbol_hash_table, cpool, symtab->data[i]); - } + symbol_hash_table.emplace (entry.cu_indices, cpool.size ()); + entry.index_offset = cpool.size (); + cpool.append_data (MAYBE_SWAP (entry.cu_indices.size ())); + for (const auto index : entry.cu_indices) + cpool.append_data (MAYBE_SWAP (index)); + } + } /* Now write out the hash table. */ - for (i = 0; i < symtab->size; ++i) + std::unordered_map str_table; + for (const auto &entry : symtab->data) { offset_type str_off, vec_off; - if (symtab->data[i]) + if (entry.name != NULL) { - str_off = add_string (str_table, cpool, symtab->data[i]->name); - vec_off = symtab->data[i]->index_offset; + const auto insertpair = str_table.emplace (entry.name, cpool.size ()); + if (insertpair.second) + cpool.append_cstr0 (entry.name); + str_off = insertpair.first->second; + vec_off = entry.index_offset; } else { @@ -22875,47 +23620,23 @@ write_hash_table (struct mapped_symtab *symtab, vec_off = 0; } - str_off = MAYBE_SWAP (str_off); - vec_off = MAYBE_SWAP (vec_off); - - obstack_grow (output, &str_off, sizeof (str_off)); - obstack_grow (output, &vec_off, sizeof (vec_off)); + output.append_data (MAYBE_SWAP (str_off)); + output.append_data (MAYBE_SWAP (vec_off)); } - - htab_delete (str_table); - htab_delete (symbol_hash_table); -} - -/* Struct to map psymtab to CU index in the index file. */ -struct psymtab_cu_index_map -{ - struct partial_symtab *psymtab; - unsigned int cu_index; -}; - -static hashval_t -hash_psymtab_cu_index (const void *item) -{ - const struct psymtab_cu_index_map *map = item; - - return htab_hash_pointer (map->psymtab); } -static int -eq_psymtab_cu_index (const void *item_lhs, const void *item_rhs) -{ - const struct psymtab_cu_index_map *lhs = item_lhs; - const struct psymtab_cu_index_map *rhs = item_rhs; - - return lhs->psymtab == rhs->psymtab; -} +typedef std::unordered_map psym_index_map; /* Helper struct for building the address table. */ struct addrmap_index_data { + addrmap_index_data (data_buf &addr_vec_, psym_index_map &cu_index_htab_) + : addr_vec (addr_vec_), cu_index_htab (cu_index_htab_) + {} + struct objfile *objfile; - struct obstack *addr_obstack; - htab_t cu_index_htab; + data_buf &addr_vec; + psym_index_map &cu_index_htab; /* Non-zero if the previous_* fields are valid. We can't write an entry until we see the next entry (since it is only then @@ -22927,24 +23648,19 @@ struct addrmap_index_data CORE_ADDR previous_cu_start; }; -/* Write an address entry to OBSTACK. */ +/* Write an address entry to ADDR_VEC. */ static void -add_address_entry (struct objfile *objfile, struct obstack *obstack, +add_address_entry (struct objfile *objfile, data_buf &addr_vec, CORE_ADDR start, CORE_ADDR end, unsigned int cu_index) { - offset_type cu_index_to_write; - gdb_byte addr[8]; CORE_ADDR baseaddr; baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); - store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, start - baseaddr); - obstack_grow (obstack, addr, 8); - store_unsigned_integer (addr, 8, BFD_ENDIAN_LITTLE, end - baseaddr); - obstack_grow (obstack, addr, 8); - cu_index_to_write = MAYBE_SWAP (cu_index); - obstack_grow (obstack, &cu_index_to_write, sizeof (offset_type)); + addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, start - baseaddr); + addr_vec.append_uint (8, BFD_ENDIAN_LITTLE, end - baseaddr); + addr_vec.append_data (MAYBE_SWAP (cu_index)); } /* Worker function for traversing an addrmap to build the address table. */ @@ -22952,47 +23668,43 @@ add_address_entry (struct objfile *objfile, struct obstack *obstack, static int add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *obj) { - struct addrmap_index_data *data = datap; - struct partial_symtab *pst = obj; + struct addrmap_index_data *data = (struct addrmap_index_data *) datap; + struct partial_symtab *pst = (struct partial_symtab *) obj; if (data->previous_valid) - add_address_entry (data->objfile, data->addr_obstack, + add_address_entry (data->objfile, data->addr_vec, data->previous_cu_start, start_addr, data->previous_cu_index); data->previous_cu_start = start_addr; if (pst != NULL) { - struct psymtab_cu_index_map find_map, *map; - find_map.psymtab = pst; - map = htab_find (data->cu_index_htab, &find_map); - gdb_assert (map != NULL); - data->previous_cu_index = map->cu_index; + const auto it = data->cu_index_htab.find (pst); + gdb_assert (it != data->cu_index_htab.cend ()); + data->previous_cu_index = it->second; data->previous_valid = 1; } else - data->previous_valid = 0; + data->previous_valid = 0; return 0; } -/* Write OBJFILE's address map to OBSTACK. +/* Write OBJFILE's address map to ADDR_VEC. CU_INDEX_HTAB is used to map addrmap entries to their CU indices in the index file. */ static void -write_address_map (struct objfile *objfile, struct obstack *obstack, - htab_t cu_index_htab) +write_address_map (struct objfile *objfile, data_buf &addr_vec, + psym_index_map &cu_index_htab) { - struct addrmap_index_data addrmap_index_data; + struct addrmap_index_data addrmap_index_data (addr_vec, cu_index_htab); /* When writing the address table, we have to cope with the fact that the addrmap iterator only provides the start of a region; we have to wait until the next invocation to get the start of the next region. */ addrmap_index_data.objfile = objfile; - addrmap_index_data.addr_obstack = obstack; - addrmap_index_data.cu_index_htab = cu_index_htab; addrmap_index_data.previous_valid = 0; addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker, @@ -23004,7 +23716,7 @@ write_address_map (struct objfile *objfile, struct obstack *obstack, doesn't work here. To cope we pass 0xff...ff, this is a rare situation anyway. */ if (addrmap_index_data.previous_valid) - add_address_entry (objfile, obstack, + add_address_entry (objfile, addr_vec, addrmap_index_data.previous_cu_start, (CORE_ADDR) -1, addrmap_index_data.previous_cu_index); } @@ -23051,7 +23763,7 @@ symbol_kind (struct partial_symbol *psym) static void write_psymbols (struct mapped_symtab *symtab, - htab_t psyms_seen, + std::unordered_set &psyms_seen, struct partial_symbol **psymp, int count, offset_type cu_index, @@ -23060,53 +23772,33 @@ write_psymbols (struct mapped_symtab *symtab, for (; count-- > 0; ++psymp) { struct partial_symbol *psym = *psymp; - void **slot; if (SYMBOL_LANGUAGE (psym) == language_ada) error (_("Ada is not currently supported by the index")); /* Only add a given psymbol once. */ - slot = htab_find_slot (psyms_seen, psym, INSERT); - if (!*slot) + if (psyms_seen.insert (psym).second) { gdb_index_symbol_kind kind = symbol_kind (psym); - *slot = psym; add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym), is_static, kind, cu_index); } } } -/* Write the contents of an ("unfinished") obstack to FILE. Throw an - exception if there is an error. */ - -static void -write_obstack (FILE *file, struct obstack *obstack) -{ - if (fwrite (obstack_base (obstack), 1, obstack_object_size (obstack), - file) - != obstack_object_size (obstack)) - error (_("couldn't data write to file")); -} - -/* Unlink a file if the argument is not NULL. */ - -static void -unlink_if_set (void *p) -{ - char **filename = p; - if (*filename) - unlink (*filename); -} - /* A helper struct used when iterating over debug_types. */ struct signatured_type_index_data { + signatured_type_index_data (data_buf &types_list_, + std::unordered_set &psyms_seen_) + : types_list (types_list_), psyms_seen (psyms_seen_) + {} + struct objfile *objfile; struct mapped_symtab *symtab; - struct obstack *types_list; - htab_t psyms_seen; + data_buf &types_list; + std::unordered_set &psyms_seen; int cu_index; }; @@ -23116,10 +23808,10 @@ struct signatured_type_index_data static int write_one_signatured_type (void **slot, void *d) { - struct signatured_type_index_data *info = d; + struct signatured_type_index_data *info + = (struct signatured_type_index_data *) d; struct signatured_type *entry = (struct signatured_type *) *slot; struct partial_symtab *psymtab = entry->per_cu.v.psymtab; - gdb_byte val[8]; write_psymbols (info->symtab, info->psyms_seen, @@ -23134,20 +23826,33 @@ 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.sect_off); - obstack_grow (info->types_list, val, 8); - 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); + info->types_list.append_uint (8, BFD_ENDIAN_LITTLE, + to_underlying (entry->per_cu.sect_off)); + info->types_list.append_uint (8, BFD_ENDIAN_LITTLE, + to_underlying (entry->type_offset_in_tu)); + info->types_list.append_uint (8, BFD_ENDIAN_LITTLE, entry->signature); ++info->cu_index; return 1; } +/* Recurse into all "included" dependencies and count their symbols as + if they appeared in this psymtab. */ + +static void +recursively_count_psymbols (struct partial_symtab *psymtab, + size_t &psyms_seen) +{ + for (int i = 0; i < psymtab->number_of_dependencies; ++i) + if (psymtab->dependencies[i]->user != NULL) + recursively_count_psymbols (psymtab->dependencies[i], + psyms_seen); + + psyms_seen += psymtab->n_global_syms; + psyms_seen += psymtab->n_static_syms; +} + /* Recurse into all "included" dependencies and write their symbols as if they appeared in this psymtab. */ @@ -23155,7 +23860,7 @@ static void recursively_write_psymbols (struct objfile *objfile, struct partial_symtab *psymtab, struct mapped_symtab *symtab, - htab_t psyms_seen, + std::unordered_set &psyms_seen, offset_type cu_index) { int i; @@ -23182,19 +23887,6 @@ recursively_write_psymbols (struct objfile *objfile, static void write_psymtabs_to_index (struct objfile *objfile, const char *dir) { - struct cleanup *cleanup; - char *filename, *cleanup_filename; - struct obstack contents, addr_obstack, constant_pool, symtab_obstack; - struct obstack cu_list, types_cu_list; - int i; - FILE *out_file; - struct mapped_symtab *symtab; - offset_type val, size_of_contents, total_len; - struct stat st; - htab_t psyms_seen; - htab_t cu_index_htab; - struct psymtab_cu_index_map *psymtab_cu_index_map; - if (dwarf2_per_objfile->using_index) error (_("Cannot use an index to create the index")); @@ -23204,61 +23896,61 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) if (!objfile->psymtabs || !objfile->psymtabs_addrmap) return; + struct stat st; if (stat (objfile_name (objfile), &st) < 0) perror_with_name (objfile_name (objfile)); - filename = concat (dir, SLASH_STRING, lbasename (objfile_name (objfile)), - INDEX_SUFFIX, (char *) NULL); - cleanup = make_cleanup (xfree, filename); + std::string filename (std::string (dir) + SLASH_STRING + + lbasename (objfile_name (objfile)) + INDEX_SUFFIX); - out_file = gdb_fopen_cloexec (filename, "wb"); + FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release (); if (!out_file) - error (_("Can't open `%s' for writing"), filename); + error (_("Can't open `%s' for writing"), filename.c_str ()); - cleanup_filename = filename; - make_cleanup (unlink_if_set, &cleanup_filename); + /* Order matters here; we want FILE to be closed before FILENAME is + unlinked, because on MS-Windows one cannot delete a file that is + still open. (Don't call anything here that might throw until + file_closer is created.) */ + gdb::unlinker unlink_file (filename.c_str ()); + gdb_file_up close_out_file (out_file); - symtab = create_mapped_symtab (); - make_cleanup (cleanup_mapped_symtab, symtab); - - obstack_init (&addr_obstack); - make_cleanup_obstack_free (&addr_obstack); - - obstack_init (&cu_list); - make_cleanup_obstack_free (&cu_list); - - obstack_init (&types_cu_list); - make_cleanup_obstack_free (&types_cu_list); - - psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer, - NULL, xcalloc, xfree); - make_cleanup_htab_delete (psyms_seen); + mapped_symtab symtab; + data_buf cu_list; /* While we're scanning CU's create a table that maps a psymtab pointer (which is what addrmap records) to its index (which is what is recorded in the index file). This will later be needed to write the address table. */ - cu_index_htab = htab_create_alloc (100, - hash_psymtab_cu_index, - eq_psymtab_cu_index, - NULL, xcalloc, xfree); - make_cleanup_htab_delete (cu_index_htab); - psymtab_cu_index_map = (struct psymtab_cu_index_map *) - xmalloc (sizeof (struct psymtab_cu_index_map) - * dwarf2_per_objfile->n_comp_units); - make_cleanup (xfree, psymtab_cu_index_map); + psym_index_map cu_index_htab; + cu_index_htab.reserve (dwarf2_per_objfile->n_comp_units); /* The CU list is already sorted, so we don't need to do additional work here. Also, the debug_types entries do not appear in all_comp_units, but only in their own hash table. */ - for (i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + + /* The psyms_seen set is potentially going to be largish (~40k + elements when indexing a -g3 build of GDB itself). Estimate the + number of elements in order to avoid too many rehashes, which + require rebuilding buckets and thus many trips to + malloc/free. */ + size_t psyms_count = 0; + for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) + { + struct dwarf2_per_cu_data *per_cu + = dwarf2_per_objfile->all_comp_units[i]; + struct partial_symtab *psymtab = per_cu->v.psymtab; + + if (psymtab != NULL && psymtab->user == NULL) + recursively_count_psymbols (psymtab, psyms_count); + } + /* Generating an index for gdb itself shows a ratio of + TOTAL_SEEN_SYMS/UNIQUE_SYMS or ~5. 4 seems like a good bet. */ + std::unordered_set psyms_seen (psyms_count / 4); + for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i) { struct dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->all_comp_units[i]; struct partial_symtab *psymtab = per_cu->v.psymtab; - gdb_byte val[8]; - struct psymtab_cu_index_map *map; - void **slot; /* CU of a shared file from 'dwz -m' may be unused by this main file. It may be referenced from a local scope but in such case it does not @@ -23267,35 +23959,30 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) continue; if (psymtab->user == NULL) - recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, i); + recursively_write_psymbols (objfile, psymtab, &symtab, + psyms_seen, i); - map = &psymtab_cu_index_map[i]; - map->psymtab = psymtab; - map->cu_index = i; - slot = htab_find_slot (cu_index_htab, map, INSERT); - gdb_assert (slot != NULL); - gdb_assert (*slot == NULL); - *slot = map; + const auto insertpair = cu_index_htab.emplace (psymtab, i); + gdb_assert (insertpair.second); - 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); + cu_list.append_uint (8, BFD_ENDIAN_LITTLE, + to_underlying (per_cu->sect_off)); + cu_list.append_uint (8, BFD_ENDIAN_LITTLE, per_cu->length); } /* Dump the address map. */ - write_address_map (objfile, &addr_obstack, cu_index_htab); + data_buf addr_vec; + write_address_map (objfile, addr_vec, cu_index_htab); /* Write out the .debug_type entries, if any. */ + data_buf types_cu_list; if (dwarf2_per_objfile->signatured_types) { - struct signatured_type_index_data sig_data; + signatured_type_index_data sig_data (types_cu_list, + psyms_seen); sig_data.objfile = objfile; - sig_data.symtab = symtab; - sig_data.types_list = &types_cu_list; - sig_data.psyms_seen = psyms_seen; + sig_data.symtab = &symtab; sig_data.cu_index = dwarf2_per_objfile->n_comp_units; htab_traverse_noresize (dwarf2_per_objfile->signatured_types, write_one_signatured_type, &sig_data); @@ -23303,64 +23990,49 @@ write_psymtabs_to_index (struct objfile *objfile, const char *dir) /* Now that we've processed all symbols we can shrink their cu_indices lists. */ - uniquify_cu_indices (symtab); + uniquify_cu_indices (&symtab); - obstack_init (&constant_pool); - make_cleanup_obstack_free (&constant_pool); - obstack_init (&symtab_obstack); - make_cleanup_obstack_free (&symtab_obstack); - write_hash_table (symtab, &symtab_obstack, &constant_pool); + data_buf symtab_vec, constant_pool; + write_hash_table (&symtab, symtab_vec, constant_pool); - obstack_init (&contents); - make_cleanup_obstack_free (&contents); - size_of_contents = 6 * sizeof (offset_type); - total_len = size_of_contents; + data_buf contents; + const offset_type size_of_contents = 6 * sizeof (offset_type); + offset_type total_len = size_of_contents; /* The version number. */ - val = MAYBE_SWAP (8); - obstack_grow (&contents, &val, sizeof (val)); + contents.append_data (MAYBE_SWAP (8)); /* The offset of the CU list from the start of the file. */ - val = MAYBE_SWAP (total_len); - obstack_grow (&contents, &val, sizeof (val)); - total_len += obstack_object_size (&cu_list); + contents.append_data (MAYBE_SWAP (total_len)); + total_len += cu_list.size (); /* The offset of the types CU list from the start of the file. */ - val = MAYBE_SWAP (total_len); - obstack_grow (&contents, &val, sizeof (val)); - total_len += obstack_object_size (&types_cu_list); + contents.append_data (MAYBE_SWAP (total_len)); + total_len += types_cu_list.size (); /* The offset of the address table from the start of the file. */ - val = MAYBE_SWAP (total_len); - obstack_grow (&contents, &val, sizeof (val)); - total_len += obstack_object_size (&addr_obstack); + contents.append_data (MAYBE_SWAP (total_len)); + total_len += addr_vec.size (); /* The offset of the symbol table from the start of the file. */ - val = MAYBE_SWAP (total_len); - obstack_grow (&contents, &val, sizeof (val)); - total_len += obstack_object_size (&symtab_obstack); + contents.append_data (MAYBE_SWAP (total_len)); + total_len += symtab_vec.size (); /* The offset of the constant pool from the start of the file. */ - val = MAYBE_SWAP (total_len); - obstack_grow (&contents, &val, sizeof (val)); - total_len += obstack_object_size (&constant_pool); - - gdb_assert (obstack_object_size (&contents) == size_of_contents); + contents.append_data (MAYBE_SWAP (total_len)); + total_len += constant_pool.size (); - write_obstack (out_file, &contents); - write_obstack (out_file, &cu_list); - write_obstack (out_file, &types_cu_list); - write_obstack (out_file, &addr_obstack); - write_obstack (out_file, &symtab_obstack); - write_obstack (out_file, &constant_pool); + gdb_assert (contents.size () == size_of_contents); - fclose (out_file); + contents.file_write (out_file); + cu_list.file_write (out_file); + types_cu_list.file_write (out_file); + addr_vec.file_write (out_file); + symtab_vec.file_write (out_file); + constant_pool.file_write (out_file); - /* We want to keep the file, so we set cleanup_filename to NULL - here. See unlink_if_set. */ - cleanup_filename = NULL; - - do_cleanups (cleanup); + /* We want to keep the file. */ + unlink_file.keep (); } /* Implementation of the `save gdb-index' command. @@ -23384,7 +24056,9 @@ save_gdb_index_command (char *arg, int from_tty) if (stat (objfile_name (objfile), &st) < 0) continue; - dwarf2_per_objfile = objfile_data (objfile, dwarf2_objfile_data_key); + dwarf2_per_objfile + = (struct dwarf2_per_objfile *) objfile_data (objfile, + dwarf2_objfile_data_key); if (dwarf2_per_objfile) { @@ -23426,8 +24100,6 @@ show_check_physname (struct ui_file *file, int from_tty, value); } -void _initialize_dwarf2_read (void); - void _initialize_dwarf2_read (void) {