E.g., load_partial_dies, read_partial_die. */
#include "defs.h"
+#include "dwarf2read.h"
+#include "dwarf-index-common.h"
#include "bfd.h"
#include "elf-bfd.h"
#include "symtab.h"
#include <cmath>
#include <set>
#include <forward_list>
-
-typedef struct symbol *symbolp;
-DEF_VEC_P (symbolp);
+#include "rust-lang.h"
+#include "common/pathstuff.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
static int dwarf2_locexpr_block_index;
static int dwarf2_loclist_block_index;
-/* A descriptor for dwarf sections.
-
- S.ASECTION, SIZE are typically initialized when the objfile is first
- scanned. BUFFER, READIN are filled in later when the section is read.
- If the section contained compressed data then SIZE is updated to record
- the uncompressed size of the section.
-
- DWP file format V2 introduces a wrinkle that is easiest to handle by
- creating the concept of virtual sections contained within a real section.
- In DWP V2 the sections of the input DWO files are concatenated together
- into one section, but section offsets are kept relative to the original
- input section.
- If this is a virtual dwp-v2 section, S.CONTAINING_SECTION is a backlink to
- the real section this "virtual" section is contained in, and BUFFER,SIZE
- describe the virtual section. */
-
-struct dwarf2_section_info
-{
- union
- {
- /* If this is a real section, the bfd section. */
- asection *section;
- /* If this is a virtual section, pointer to the containing ("real")
- section. */
- struct dwarf2_section_info *containing_section;
- } s;
- /* Pointer to section data, only valid if readin. */
- const gdb_byte *buffer;
- /* The size of the section, real or virtual. */
- bfd_size_type size;
- /* If this is a virtual section, the offset in the real section.
- Only valid if is_virtual. */
- bfd_size_type virtual_offset;
- /* True if we have tried to read this section. */
- char readin;
- /* True if this is a virtual section, False otherwise.
- This specifies which of s.section and s.containing_section to use. */
- char is_virtual;
-};
-
-typedef struct dwarf2_section_info dwarf2_section_info_def;
-DEF_VEC_O (dwarf2_section_info_def);
-
-/* All offsets in the index are of this type. It must be
- architecture-independent. */
-typedef uint32_t offset_type;
-
-DEF_VEC_I (offset_type);
-
-/* Ensure only legit values are used. */
-#define DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE(cu_index, value) \
- do { \
- gdb_assert ((unsigned int) (value) <= 1); \
- GDB_INDEX_SYMBOL_STATIC_SET_VALUE((cu_index), (value)); \
- } while (0)
-
-/* Ensure only legit values are used. */
-#define DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE(cu_index, value) \
- do { \
- gdb_assert ((value) >= GDB_INDEX_SYMBOL_KIND_TYPE \
- && (value) <= GDB_INDEX_SYMBOL_KIND_OTHER); \
- GDB_INDEX_SYMBOL_KIND_SET_VALUE((cu_index), (value)); \
- } while (0)
-
-/* Ensure we don't use more than the alloted nuber of bits for the CU. */
-#define DW2_GDB_INDEX_CU_SET_VALUE(cu_index, value) \
- do { \
- gdb_assert (((value) & ~GDB_INDEX_CU_MASK) == 0); \
- GDB_INDEX_CU_SET_VALUE((cu_index), (value)); \
- } while (0)
-
-#if WORDS_BIGENDIAN
-
-/* Convert VALUE between big- and little-endian. */
-
-static offset_type
-byte_swap (offset_type value)
-{
- offset_type result;
-
- result = (value & 0xff) << 24;
- result |= (value & 0xff00) << 8;
- result |= (value & 0xff0000) >> 8;
- result |= (value & 0xff000000) >> 24;
- return result;
-}
-
-#define MAYBE_SWAP(V) byte_swap (V)
-
-#else
-#define MAYBE_SWAP(V) static_cast<offset_type> (V)
-#endif /* WORDS_BIGENDIAN */
-
/* An index into a (C++) symbol name component in a symbol name as
recorded in the mapped_index's symbol table. For each C++ symbol
in the symbol table, we record one entry for the start of each
{ return this->name_count; }
};
-typedef struct dwarf2_per_cu_data *dwarf2_per_cu_ptr;
-DEF_VEC_P (dwarf2_per_cu_ptr);
-
-struct tu_stats
-{
- int nr_uniq_abbrev_tables;
- int nr_symtabs;
- int nr_symtab_sharers;
- int nr_stmt_less_type_units;
- int nr_all_type_units_reallocs;
-};
-
-/* Collection of data recorded per objfile.
- This hangs off of dwarf2_objfile_data_key. */
-
-struct dwarf2_per_objfile
-{
- /* 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_AND_ASSIGN (dwarf2_per_objfile);
-
- /* 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 {};
- dwarf2_section_info debug_names {};
- dwarf2_section_info debug_aranges {};
-
- VEC (dwarf2_section_info_def) *types = NULL;
-
- /* Back link. */
- 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 = NULL;
-
- /* The number of compilation units in ALL_COMP_UNITS. */
- int n_comp_units = 0;
-
- /* The number of .debug_types-related CUs. */
- 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 = 0;
-
- /* The .debug_types-related CUs (TUs).
- This is stored in malloc space because we may realloc it. */
- 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 {};
-
- /* A table mapping .debug_types signatures to its signatured_type entry.
- This is NULL if the .debug_types section hasn't been read in yet. */
- htab_t signatured_types {};
-
- /* Type unit statistics, to see how well the scaling improvements
- are doing. */
- struct tu_stats tu_stats {};
-
- /* A chain of compilation units that are currently read in, so that
- they can be freed later. */
- 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 {};
-
- /* 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 = 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 = NULL;
-
- /* A flag indicating whether this objfile has a section loaded at a
- VMA of 0. */
- bool has_section_at_zero = false;
-
- /* True if we are using the mapped index,
- or we are faking it for OBJF_READNOW's sake. */
- bool using_index = false;
-
- /* The mapped index, or NULL if .gdb_index is missing or not being used. */
- mapped_index *index_table = NULL;
-
- /* The mapped index, or NULL if .debug_names is missing or not being used. */
- std::unique_ptr<mapped_debug_names> debug_names_table;
-
- /* When using index_table, this keeps track of all quick_file_names entries.
- TUs typically share line table entries with a CU, so we maintain a
- separate table of all line table entries to support the sharing.
- Note that while there can be way more TUs than CUs, we've already
- sorted all the TUs into "type unit groups", grouped by their
- DW_AT_stmt_list value. Therefore the only sharing done here is with a
- CU and its associated TU group if there is one. */
- htab_t quick_file_names_table {};
-
- /* Set during partial symbol reading, to prevent queueing of full
- symbols. */
- 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 {};
-
- /* The CUs we recently read. */
- 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 {};
-
- /* Table containing all filenames. This is an optional because the
- table is lazily constructed on first access. */
- gdb::optional<filename_seen_cache> filenames_cache;
-};
-
-/* Get the dwarf2_per_objfile associated to OBJFILE. */
+/* See dwarf2read.h. */
-struct dwarf2_per_objfile *
+dwarf2_per_objfile *
get_dwarf2_per_objfile (struct objfile *objfile)
{
return ((struct dwarf2_per_objfile *)
struct die_info *die;
};
-typedef struct delayed_method_info delayed_method_info;
-DEF_VEC_O (delayed_method_info);
-
/* Internal state when decoding a particular compilation unit. */
struct dwarf2_cu
{
/* A list of methods which need to have physnames computed
after all type information has been read. */
- VEC (delayed_method_info) *method_list = nullptr;
+ std::vector<delayed_method_info> method_list;
/* To be copied to symtab->call_site_htab. */
htab_t call_site_htab = nullptr;
whether the DW_AT_ranges attribute came from the skeleton or DWO. */
ULONGEST ranges_base = 0;
+ /* When reading debug info generated by older versions of rustc, we
+ have to rewrite some union types to be struct types with a
+ variant part. This rewriting must be done after the CU is fully
+ read in, because otherwise at the point of rewriting some struct
+ type might not have been fully processed. So, we keep a list of
+ all such types here and process them after expansion. */
+ std::vector<struct type *> rust_unions;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
this information, but later versions do. */
unsigned int processing_has_namespace_info : 1;
-};
-
-/* Persistent data held for a compilation unit, even when not
- processing it. We put a pointer to this structure in the
- read_symtab_private field of the psymtab. */
-
-struct dwarf2_per_cu_data
-{
- /* The start offset and length of this compilation unit.
- NOTE: Unlike comp_unit_head.length, this length includes
- initial_length_size.
- If the DIE refers to a DWO file, this is always of the original die,
- not the DWO file. */
- sect_offset 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;
-
- /* This flag will be set when reading partial DIEs if we need to load
- absolutely all DIEs for this compilation unit, instead of just the ones
- we think are interesting. It gets set if we look for a DIE in the
- hash table and don't find it. */
- unsigned int load_all_dies : 1;
-
- /* Non-zero if this CU is from .debug_types.
- Struct dwarf2_per_cu_data is contained in struct signatured_type iff
- this is non-zero. */
- unsigned int is_debug_types : 1;
-
- /* Non-zero if this CU is from the .dwz file. */
- unsigned int is_dwz : 1;
-
- /* Non-zero if reading a TU directly from a DWO file, bypassing the stub.
- This flag is only valid if is_debug_types is true.
- We can't read a CU directly from a DWO file: There are required
- attributes in the stub. */
- unsigned int reading_dwo_directly : 1;
-
- /* Non-zero if the TU has been read.
- This is used to assist the "Stay in DWO Optimization" for Fission:
- When reading a DWO, it's faster to read TUs from the DWO instead of
- fetching them from random other DWOs (due to comdat folding).
- If the TU has already been read, the optimization is unnecessary
- (and unwise - we don't want to change where gdb thinks the TU lives
- "midflight").
- This flag is only valid if is_debug_types is true. */
- unsigned int tu_read : 1;
-
- /* The section this CU/TU lives in.
- If the DIE refers to a DWO file, this is always the original die,
- not the DWO file. */
- struct dwarf2_section_info *section;
-
- /* Set to non-NULL iff this CU is currently loaded. When it gets freed out
- of the CU cache it gets reset to NULL again. This is left as NULL for
- dummy CUs (a CU header, but nothing else). */
- struct dwarf2_cu *cu;
-
- /* The corresponding dwarf2_per_objfile. */
- struct dwarf2_per_objfile *dwarf2_per_objfile;
-
- /* When dwarf2_per_objfile->using_index is true, the 'quick' field
- is active. Otherwise, the 'psymtab' field is active. */
- union
- {
- /* The partial symbol table associated with this compilation unit,
- or NULL for unread partial units. */
- struct partial_symtab *psymtab;
-
- /* Data needed by the "quick" functions. */
- struct dwarf2_per_cu_quick_data *quick;
- } v;
-
- /* The CUs we import using DW_TAG_imported_unit. This is filled in
- while reading psymtabs, used to compute the psymtab dependencies,
- and then cleared. Then it is filled in again while reading full
- symbols, and only deleted when the objfile is destroyed.
-
- This is also used to work around a difference between the way gold
- generates .gdb_index version <=7 and the way gdb does. Arguably this
- is a gold bug. For symbols coming from TUs, gold records in the index
- the CU that includes the TU instead of the TU itself. This breaks
- dw2_lookup_symbol: It assumes that if the index says symbol X lives
- in CU/TU Y, then one need only expand Y and a subsequent lookup in Y
- will find X. Alas TUs live in their own symtab, so after expanding CU Y
- we need to look in TU Z to find X. Fortunately, this is akin to
- DW_TAG_imported_unit, so we just use the same mechanism: For
- .gdb_index version <=7 this also records the TUs that the CU referred
- to. Concurrently with this change gdb was modified to emit version 8
- indices so we only pay a price for gold generated indices.
- http://sourceware.org/bugzilla/show_bug.cgi?id=15021. */
- VEC (dwarf2_per_cu_ptr) *imported_symtabs;
-};
-
-/* Entry in the signatured_types hash table. */
-
-struct signatured_type
-{
- /* The "per_cu" object of this type.
- This struct is used iff per_cu.is_debug_types.
- N.B.: This is the first member so that it's easy to convert pointers
- between them. */
- struct dwarf2_per_cu_data per_cu;
-
- /* The type's signature. */
- ULONGEST signature;
-
- /* Offset in the TU of the type's DIE, as read from the TU header.
- If this TU is a DWO stub and the definition lives in a DWO file
- (specified by DW_AT_GNU_dwo_name), this value is unusable. */
- cu_offset type_offset_in_tu;
-
- /* Offset in the section of the type's DIE.
- If the definition lives in a DWO file, this is the offset in the
- .debug_types.dwo section.
- The value is zero until the actual value is known.
- Zero is otherwise not a valid section offset. */
- sect_offset type_offset_in_section;
- /* Type units are grouped by their DW_AT_stmt_list entry so that they
- can share them. This points to the containing symtab. */
- struct type_unit_group *type_unit_group;
-
- /* The type.
- The first time we encounter this type we fully read it in and install it
- in the symbol tables. Subsequent times we only need the type. */
- struct type *type;
-
- /* Containing DWO unit.
- This field is valid iff per_cu.reading_dwo_directly. */
- struct dwo_unit *dwo_unit;
+ struct partial_die_info *find_partial_die (sect_offset sect_off);
};
-typedef struct signatured_type *sig_type_ptr;
-DEF_VEC_P (sig_type_ptr);
-
/* A struct that can be used as a hash key for tables based on DW_AT_stmt_list.
This includes type_unit_group and quick_file_names. */
/* When we construct a partial symbol table entry we only
need this much information. */
-struct partial_die_info
+struct partial_die_info : public allocate_on_obstack
{
+ partial_die_info (sect_offset sect_off, struct abbrev_info *abbrev);
+
+ /* Disable assign but still keep copy ctor, which is needed
+ load_partial_dies. */
+ partial_die_info& operator=(const partial_die_info& rhs) = delete;
+
+ /* Adjust the partial die before generating a symbol for it. This
+ function may set the is_external flag or change the DIE's
+ name. */
+ void fixup (struct dwarf2_cu *cu);
+
+ /* Read a minimal amount of information into the minimal die
+ structure. */
+ const gdb_byte *read (const struct die_reader_specs *reader,
+ const struct abbrev_info &abbrev,
+ const gdb_byte *info_ptr);
+
/* Offset of this DIE. */
- sect_offset sect_off;
+ const sect_offset sect_off;
/* DWARF-2 tag for this DIE. */
- ENUM_BITFIELD(dwarf_tag) tag : 16;
+ const ENUM_BITFIELD(dwarf_tag) tag : 16;
/* Assorted flags describing the data found in this DIE. */
- unsigned int has_children : 1;
+ const unsigned int has_children : 1;
+
unsigned int is_external : 1;
unsigned int is_declaration : 1;
unsigned int has_type : 1;
/* Flag set if any of the DIE's children are template arguments. */
unsigned int has_template_arguments : 1;
- /* Flag set if fixup_partial_die has been called on this die. */
+ /* Flag set if fixup has been called on this die. */
unsigned int fixup_called : 1;
/* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
- const char *name;
+ const char *name = nullptr;
/* The linkage name, if present. */
- const char *linkage_name;
+ const char *linkage_name = nullptr;
/* The scope to prepend to our children. This is generally
allocated on the comp_unit_obstack, so will disappear
when this compilation unit leaves the cache. */
- const char *scope;
+ const char *scope = nullptr;
/* Some data associated with the partial DIE. The tag determines
which field is live. */
struct dwarf_block *locdesc;
/* The offset of an import, for DW_TAG_imported_unit. */
sect_offset sect_off;
- } d;
+ } d {};
/* If HAS_PC_INFO, the PC range associated with this DIE. */
- CORE_ADDR lowpc;
- CORE_ADDR highpc;
+ CORE_ADDR lowpc = 0;
+ CORE_ADDR highpc = 0;
/* Pointer into the info_buffer (or types_buffer) pointing at the target of
DW_AT_sibling, if any. */
- /* NOTE: This member isn't strictly necessary, read_partial_die could
- return DW_AT_sibling values to its caller load_partial_dies. */
- const gdb_byte *sibling;
+ /* NOTE: This member isn't strictly necessary, partial_die_info::read
+ could return DW_AT_sibling values to its caller load_partial_dies. */
+ const gdb_byte *sibling = nullptr;
/* If HAS_SPECIFICATION, the offset of the DIE referred to by
DW_AT_specification (or DW_AT_abstract_origin or
DW_AT_extension). */
- sect_offset spec_offset;
+ sect_offset spec_offset {};
/* Pointers to this DIE's parent, first child, and next sibling,
if any. */
- struct partial_die_info *die_parent, *die_child, *die_sibling;
+ struct partial_die_info *die_parent = nullptr;
+ struct partial_die_info *die_child = nullptr;
+ struct partial_die_info *die_sibling = nullptr;
+
+ friend struct partial_die_info *
+ dwarf2_cu::find_partial_die (sect_offset sect_off);
+
+ private:
+ /* Only need to do look up in dwarf2_cu::find_partial_die. */
+ partial_die_info (sect_offset sect_off)
+ : partial_die_info (sect_off, DW_TAG_padding, 0)
+ {
+ }
+
+ partial_die_info (sect_offset sect_off_, enum dwarf_tag tag_,
+ int has_children_)
+ : sect_off (sect_off_), tag (tag_), has_children (has_children_)
+ {
+ is_external = 0;
+ is_declaration = 0;
+ has_type = 0;
+ has_specification = 0;
+ has_pc_info = 0;
+ may_be_inlined = 0;
+ main_subprogram = 0;
+ scope_set = 0;
+ has_byte_size = 0;
+ has_const_value = 0;
+ has_template_arguments = 0;
+ fixup_called = 0;
+ is_dwz = 0;
+ spec_is_dwz = 0;
+ }
};
/* This data structure holds the information of an abbrev. */
explicit abbrev_table (sect_offset off)
: sect_off (off)
{
- abbrevs =
+ m_abbrevs =
XOBNEWVEC (&abbrev_obstack, struct abbrev_info *, ABBREV_HASH_SIZE);
- memset (abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
+ memset (m_abbrevs, 0, ABBREV_HASH_SIZE * sizeof (struct abbrev_info *));
}
DISABLE_COPY_AND_ASSIGN (abbrev_table);
/* Storage for the abbrev table. */
auto_obstack abbrev_obstack;
+private:
+
/* Hash table of abbrevs.
This is an array of size ABBREV_HASH_SIZE allocated in abbrev_obstack.
It could be statically allocated, but the previous code didn't so we
don't either. */
- struct abbrev_info **abbrevs;
+ struct abbrev_info **m_abbrevs;
};
typedef std::unique_ptr<struct abbrev_table> abbrev_table_up;
and friends. */
static int bits_per_byte = 8;
-struct nextfield
-{
- struct nextfield *next;
- int accessibility;
- int virtuality;
- struct field field;
-};
+/* When reading a variant or variant part, we track a bit more
+ information about the field, and store it in an object of this
+ type. */
-struct nextfnfield
+struct variant_field
{
- struct nextfnfield *next;
- struct fn_field fnfield;
+ /* If we see a DW_TAG_variant, then this will be the discriminant
+ value. */
+ ULONGEST discriminant_value;
+ /* If we see a DW_TAG_variant, then this will be set if this is the
+ default branch. */
+ bool default_branch;
+ /* While reading a DW_TAG_variant_part, this will be set if this
+ field is the discriminant. */
+ bool is_discriminant;
};
-struct fnfieldlist
+struct nextfield
{
- const char *name;
- int length;
- struct nextfnfield *head;
+ int accessibility = 0;
+ int virtuality = 0;
+ /* Extra information to describe a variant or variant part. */
+ struct variant_field variant {};
+ struct field field {};
};
-struct decl_field_list
+struct fnfieldlist
{
- struct decl_field field;
- struct decl_field_list *next;
+ const char *name = nullptr;
+ std::vector<struct fn_field> fnfields;
};
/* The routines that read and process dies for a C struct or C++ class
struct field_info
{
/* List of data member and baseclasses fields. */
- struct nextfield *fields, *baseclasses;
+ std::vector<struct nextfield> fields;
+ std::vector<struct nextfield> baseclasses;
/* Number of fields (including baseclasses). */
- int nfields;
-
- /* Number of baseclasses. */
- int nbaseclasses;
+ int nfields = 0;
/* Set if the accesibility of one of the fields is not public. */
- int non_public_fields;
+ int non_public_fields = 0;
/* Member function fieldlist array, contains name of possibly overloaded
member function, number of overloaded member functions and a pointer
to the head of the member function field chain. */
- struct fnfieldlist *fnfieldlists;
-
- /* Number of entries in the fnfieldlists array. */
- int nfnfields;
+ std::vector<struct fnfieldlist> fnfieldlists;
/* typedefs defined inside this class. TYPEDEF_FIELD_LIST contains head of
a NULL terminated list of TYPEDEF_FIELD_LIST_COUNT elements. */
- struct decl_field_list *typedef_field_list;
- unsigned typedef_field_list_count;
+ std::vector<struct decl_field> typedef_field_list;
/* Nested types defined by this class and the number of elements in this
list. */
- struct decl_field_list *nested_types_list;
- unsigned nested_types_list_count;
+ std::vector<struct decl_field> nested_types_list;
};
/* One item on the queue of compilation units to read in full symbols
static struct partial_die_info *load_partial_dies
(const struct die_reader_specs *, const gdb_byte *, int);
-static const gdb_byte *read_partial_die (const struct die_reader_specs *,
- struct partial_die_info *,
- struct abbrev_info *,
- unsigned int,
- const gdb_byte *);
-
static struct partial_die_info *find_partial_die (sect_offset, int,
struct dwarf2_cu *);
-static void fixup_partial_die (struct partial_die_info *,
- struct dwarf2_cu *);
-
static const gdb_byte *read_attribute (const struct die_reader_specs *,
struct attribute *, struct attr_abbrev *,
const gdb_byte *);
static struct type *get_die_type (struct die_info *die, struct dwarf2_cu *cu);
-static void dwarf2_release_queue (void *dummy);
-
static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu,
enum language pretend_language);
static void process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile);
+/* Class, the destructor of which frees all allocated queue entries. This
+ will only have work to do if an error was thrown while processing the
+ dwarf. If no error was thrown then the queue entries should have all
+ been processed, and freed, as we went along. */
+
+class dwarf2_queue_guard
+{
+public:
+ dwarf2_queue_guard () = default;
+
+ /* Free any entries remaining on the queue. There should only be
+ entries left if we hit an error while processing the dwarf. */
+ ~dwarf2_queue_guard ()
+ {
+ struct dwarf2_queue_item *item, *last;
+
+ item = dwarf2_queue;
+ while (item)
+ {
+ /* Anything still marked queued is likely to be in an
+ inconsistent state, so discard it. */
+ if (item->per_cu->queued)
+ {
+ if (item->per_cu->cu != NULL)
+ free_one_cached_comp_unit (item->per_cu);
+ item->per_cu->queued = 0;
+ }
+
+ last = item;
+ item = item->next;
+ xfree (last);
+ }
+
+ dwarf2_queue = dwarf2_queue_tail = NULL;
+ }
+};
+
/* The return type of find_file_and_directory. Note, the enclosed
string pointers are only valid while this object is valid. */
return addr;
}
-/* The suffix for an index file. */
-#define INDEX4_SUFFIX ".gdb-index"
-#define INDEX5_SUFFIX ".debug_names"
-#define DEBUG_STR_SUFFIX ".debug_str"
-
/* See declaration. */
dwarf2_per_objfile::dwarf2_per_objfile (struct objfile *objfile_,
locate_sections (obfd, sec, *names);
}
+static void free_dwo_files (htab_t dwo_files, struct objfile *objfile);
+
dwarf2_per_objfile::~dwarf2_per_objfile ()
{
/* Cached DIE trees use xmalloc and the comp_unit_obstack. */
if (line_header_hash)
htab_delete (line_header_hash);
+ for (int ix = 0; ix < n_comp_units; ++ix)
+ VEC_free (dwarf2_per_cu_ptr, all_comp_units[ix]->imported_symtabs);
+
+ for (int ix = 0; ix < n_type_units; ++ix)
+ VEC_free (dwarf2_per_cu_ptr,
+ all_type_units[ix]->per_cu.imported_symtabs);
+ xfree (all_type_units);
+
+ VEC_free (dwarf2_section_info_def, types);
+
+ if (dwo_files != NULL)
+ free_dwo_files (dwo_files, objfile);
+ if (dwp_file != NULL)
+ gdb_bfd_unref (dwp_file->dbfd);
+
+ if (dwz_file != NULL && dwz_file->dwz_bfd)
+ gdb_bfd_unref (dwz_file->dwz_bfd);
+
+ if (index_table != NULL)
+ index_table->~mapped_index ();
+
/* Everything else should be on the objfile obstack. */
}
if (dwarf2_per_objfile == NULL)
{
/* Initialize per-objfile state. */
- struct dwarf2_per_objfile *data
- = XOBNEW (&objfile->objfile_obstack, struct dwarf2_per_objfile);
-
- dwarf2_per_objfile = new (data) struct dwarf2_per_objfile (objfile, names);
+ dwarf2_per_objfile
+ = new (&objfile->objfile_obstack) struct dwarf2_per_objfile (objfile,
+ names);
set_dwarf2_per_objfile (objfile, dwarf2_per_objfile);
}
return (!dwarf2_per_objfile->info.is_virtual
return section->s.section == NULL || section->size == 0;
}
-/* Read the contents of the section INFO.
- OBJFILE is the main object file, but not necessarily the file where
- the section comes from. E.g., for DWO files the bfd of INFO is the bfd
- of the DWO file.
- If the section is compressed, uncompress it before returning. */
+/* See dwarf2read.h. */
-static void
-dwarf2_read_section (struct objfile *objfile, struct dwarf2_section_info *info)
+void
+dwarf2_read_section (struct objfile *objfile, dwarf2_section_info *info)
{
asection *sectp;
bfd *abfd;
static void
dw2_do_instantiate_symtab (struct dwarf2_per_cu_data *per_cu)
{
- struct cleanup *back_to;
struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
/* Skip type_unit_groups, reading the type units they contain
if (IS_TYPE_UNIT_GROUP (per_cu))
return;
- back_to = make_cleanup (dwarf2_release_queue, NULL);
+ /* The destructor of dwarf2_queue_guard frees any entries left on
+ the queue. After this point we're guaranteed to leave this function
+ with the dwarf queue empty. */
+ dwarf2_queue_guard q_guard;
if (dwarf2_per_objfile->using_index
? per_cu->v.quick->compunit_symtab == NULL
/* Age the cache, releasing compilation units that have not
been used recently. */
age_cached_comp_units (dwarf2_per_objfile);
-
- do_cleanups (back_to);
}
/* Ensure that the symbols for PER_CU have been read in. OBJFILE is
if (!insertpair.second)
{
warning (_("Section .debug_aranges in %s has duplicate "
- "debug_info_offset %u, ignoring .debug_aranges."),
- objfile_name (objfile), to_underlying (per_cu->sect_off));
+ "debug_info_offset %s, ignoring .debug_aranges."),
+ objfile_name (objfile), sect_offset_str (per_cu->sect_off));
return;
}
}
&objfile->objfile_obstack);
}
-/* The hash function for strings in the mapped index. This is the same as
- SYMBOL_HASH_NEXT, but we keep a separate copy to maintain control over the
- implementation. This is necessary because the hash function is tied to the
- format of the mapped index file. The hash values do not have to match with
- SYMBOL_HASH_NEXT.
-
- Use INT_MAX for INDEX_VERSION if you generate the current index format. */
-
-static hashval_t
-mapped_index_string_hash (int index_version, const void *p)
-{
- const unsigned char *str = (const unsigned char *) p;
- hashval_t r = 0;
- unsigned char c;
-
- while ((c = *str++) != 0)
- {
- if (index_version >= 5)
- c = tolower (c);
- r = r * 67 + c - 113;
- }
-
- return r;
-}
-
/* Find a slot in the mapped index INDEX for the object named NAME.
If NAME is found, set *VEC_OUT to point to the CU vector in the
constant pool and return true. If NAME cannot be found, return
return true;
}
-/* Symbol name hashing function as specified by DWARF-5. */
-
-static uint32_t
-dwarf5_djb_hash (const char *str_)
-{
- const unsigned char *str = (const unsigned char *) str_;
-
- /* Note: tolower here ignores UTF-8, which isn't fully compliant.
- See http://dwarfstd.org/ShowIssue.php?issue=161027.1. */
-
- uint32_t hash = 5381;
- while (int c = *str++)
- hash = hash * 33 + tolower (c);
- return hash;
-}
-
/* Type used to manage iterating over all CUs looking for a symbol for
.debug_names. */
if (to_underlying (header->abbrev_sect_off)
>= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
- 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),
+ error (_("Dwarf Error: bad offset (%s) in compilation unit header "
+ "(offset %s + 6) [in module %s]"),
+ sect_offset_str (header->abbrev_sect_off),
+ sect_offset_str (header->sect_off),
filename);
/* Cast to ULONGEST to use 64-bit arithmetic when possible to
if (((ULONGEST) header->sect_off + get_cu_length (header))
> section->size)
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),
+ "(offset %s + 0) [in module %s]"),
+ header->length, sect_offset_str (header->sect_off),
filename);
}
}
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),
+ _("debug type entry at offset %s is duplicate to"
+ " the entry at offset %s, signature %s"),
+ sect_offset_str (sect_off), sect_offset_str (dup_sect_off),
hex_string (header.signature));
}
*slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
if (dwarf_read_debug > 1)
- fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
- to_underlying (sect_off),
+ fprintf_unfiltered (gdb_stdlog, " offset %s, signature %s\n",
+ sect_offset_str (sect_off),
hex_string (header.signature));
info_ptr += length;
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]"),
+ " TU at offset %s [in module %s]"),
hex_string (sig_type->signature),
hex_string (cu->header.signature),
- to_underlying (dwo_unit->sect_off),
+ sect_offset_str (dwo_unit->sect_off),
bfd_get_filename (abfd));
}
gdb_assert (dwo_unit->sect_off == cu->header.sect_off);
int rereading_dwo_cu = 0;
if (dwarf_die_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
+ fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
this_cu->is_debug_types ? "type" : "comp",
- to_underlying (this_cu->sect_off));
+ sect_offset_str (this_cu->sect_off));
if (use_existing_cu)
gdb_assert (keep);
{
complaint (&symfile_complaints,
_("compilation unit with DW_AT_GNU_dwo_name"
- " has children (offset 0x%x) [in module %s]"),
- to_underlying (this_cu->sect_off), bfd_get_filename (abfd));
+ " has children (offset %s) [in module %s]"),
+ sect_offset_str (this_cu->sect_off),
+ bfd_get_filename (abfd));
}
dwo_unit = lookup_dwo_unit (this_cu, comp_unit_die);
if (dwo_unit != NULL)
int has_children;
if (dwarf_die_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset 0x%x\n",
+ fprintf_unfiltered (gdb_stdlog, "Reading %s unit at offset %s\n",
this_cu->is_debug_types ? "type" : "comp",
- to_underlying (this_cu->sect_off));
+ sect_offset_str (this_cu->sect_off));
gdb_assert (this_cu->cu == NULL);
struct gdbarch *gdbarch = get_objfile_arch (objfile);
fprintf_unfiltered (gdb_stdlog,
- "Psymtab for %s unit @0x%x: %s - %s"
+ "Psymtab for %s unit @%s: %s - %s"
", %d global, %d static syms\n",
per_cu->is_debug_types ? "type" : "comp",
- to_underlying (per_cu->sect_off),
+ sect_offset_str (per_cu->sect_off),
paddress (gdbarch, pst->textlow),
paddress (gdbarch, pst->texthigh),
pst->n_global_syms, pst->n_static_syms);
sect_offset abbrev_offset;
};
-/* Helper routine for build_type_psymtabs_1, passed to qsort. */
+/* Helper routine for build_type_psymtabs_1, passed to std::sort. */
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+static bool
+sort_tu_by_abbrev_offset (const struct tu_abbrev_offset &a,
+ const struct tu_abbrev_offset &b)
{
- 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);
+ return a.abbrev_offset < b.abbrev_offset;
}
/* Efficiently read all the type units.
build_type_psymtabs_1 (struct dwarf2_per_objfile *dwarf2_per_objfile)
{
struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- struct cleanup *cleanups;
abbrev_table_up abbrev_table;
sect_offset abbrev_offset;
- struct tu_abbrev_offset *sorted_by_abbrev;
int i;
/* It's up to the caller to not call us multiple times. */
/* Sort in a separate table to maintain the order of all_type_units
for .gdb_index: TU indices directly index all_type_units. */
- sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
- dwarf2_per_objfile->n_type_units);
+ std::vector<struct tu_abbrev_offset> sorted_by_abbrev
+ (dwarf2_per_objfile->n_type_units);
for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
{
struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
sig_type->per_cu.section,
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);
+ std::sort (sorted_by_abbrev.begin (), sorted_by_abbrev.end (),
+ sort_tu_by_abbrev_offset);
abbrev_offset = (sect_offset) ~(unsigned) 0;
init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table.get (),
0, 0, build_type_psymtabs_reader, NULL);
}
-
- do_cleanups (cleanups);
}
/* Print collected type unit statistics. */
while (pdi != NULL)
{
- fixup_partial_die (pdi, cu);
+ pdi->fixup (cu);
/* Anonymous namespaces or modules have no name but have interesting
children, so we need to look at them. Ditto for anonymous
{
add_partial_symbol (pdi, cu);
}
- if (cu->language == language_rust && pdi->has_children)
+ if ((cu->language == language_rust
+ || cu->language == language_cplus) && pdi->has_children)
scan_partial_symbols (pdi->die_child, lowpc, highpc,
set_addrmap, cu);
break;
if (parent->scope_set)
return parent->scope;
- fixup_partial_die (parent, cu);
+ parent->fixup (cu);
grandparent_scope = partial_die_parent_scope (parent, cu);
function-local names? For partial symbols, we should probably be
ignoring them. */
complaint (&symfile_complaints,
- _("unhandled containing DIE tag %d for DIE at %d"),
- parent->tag, to_underlying (pdi->sect_off));
+ _("unhandled containing DIE tag %d for DIE at %s"),
+ parent->tag, sect_offset_str (pdi->sect_off));
parent->scope = grandparent_scope;
}
types here will be reused if full symbols are loaded later. */
if (pdi->has_template_arguments)
{
- fixup_partial_die (pdi, cu);
+ pdi->fixup (cu);
if (pdi->name != NULL && strchr (pdi->name, '<') == NULL)
{
pdi = pdi->die_child;
while (pdi != NULL)
{
- fixup_partial_die (pdi, cu);
+ pdi->fixup (cu);
if (pdi->tag == DW_TAG_subprogram
|| pdi->tag == DW_TAG_inlined_subroutine
|| pdi->tag == DW_TAG_lexical_block)
if (!abbrev)
{
error (_("Dwarf Error: Could not find abbrev number %d in %s"
- " at offset 0x%x [in module %s]"),
+ " at offset %s [in module %s]"),
abbrev_number, cu->per_cu->is_debug_types ? "TU" : "CU",
- to_underlying (cu->header.sect_off), bfd_get_filename (abfd));
+ sect_offset_str (cu->header.sect_off), bfd_get_filename (abfd));
}
return abbrev;
struct signatured_type *sig_type =
(struct signatured_type *) per_cu;
- sprintf (buf, "TU %s at offset 0x%x",
+ sprintf (buf, "TU %s at offset %s",
hex_string (sig_type->signature),
- to_underlying (per_cu->sect_off));
+ sect_offset_str (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",
- to_underlying (per_cu->sect_off));
+ sprintf (buf, "CU at offset %s",
+ sect_offset_str (per_cu->sect_off));
debug_print_threshold = 1;
}
}
}
-/* Free all allocated queue entries. This function only releases anything if
- an error was thrown; if the queue was processed then it would have been
- freed as we went along. */
-
-static void
-dwarf2_release_queue (void *dummy)
-{
- struct dwarf2_queue_item *item, *last;
-
- item = dwarf2_queue;
- while (item)
- {
- /* Anything still marked queued is likely to be in an
- inconsistent state, so discard it. */
- if (item->per_cu->queued)
- {
- if (item->per_cu->cu != NULL)
- free_one_cached_comp_unit (item->per_cu);
- item->per_cu->queued = 0;
- }
-
- last = item;
- item = item->next;
- xfree (last);
- }
-
- dwarf2_queue = dwarf2_queue_tail = NULL;
-}
-
/* Read in full symbols for PST, and anything it depends on. */
static void
mi.index = index;
mi.name = name;
mi.die = die;
- VEC_safe_push (delayed_method_info, cu->method_list, &mi);
-}
-
-/* A cleanup for freeing the delayed method list. */
-
-static void
-free_delayed_list (void *ptr)
-{
- struct dwarf2_cu *cu = (struct dwarf2_cu *) ptr;
- if (cu->method_list != NULL)
- {
- VEC_free (delayed_method_info, cu->method_list);
- cu->method_list = NULL;
- }
+ cu->method_list.push_back (mi);
}
/* Check whether [PHYSNAME, PHYSNAME+LEN) ends with a modifier like
static void
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))
+ if (cu->method_list.empty ())
return;
gdb_assert (cu->language == language_cplus);
- for (i = 0; VEC_iterate (delayed_method_info, cu->method_list, i, mi) ; ++i)
+ for (struct delayed_method_info &mi : cu->method_list)
{
const char *physname;
struct fn_fieldlist *fn_flp
- = &TYPE_FN_FIELDLIST (mi->type, mi->fnfield_index);
- physname = dwarf2_physname (mi->name, mi->die, cu);
- TYPE_FN_FIELD_PHYSNAME (fn_flp->fn_fields, mi->index)
+ = &TYPE_FN_FIELDLIST (mi.type, mi.fnfield_index);
+ 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
if (physname[len] == ')') /* shortcut */
break;
else if (check_modifier (physname, len, " const"))
- TYPE_FN_FIELD_CONST (fn_flp->fn_fields, mi->index) = 1;
+ 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;
+ TYPE_FN_FIELD_VOLATILE (fn_flp->fn_fields, mi.index) = 1;
else
break;
}
}
}
+
+ /* The list is no longer needed. */
+ cu->method_list.clear ();
}
/* Go objects should be embedded in a DW_TAG_module DIE,
}
}
+/* Allocate a fully-qualified name consisting of the two parts on the
+ obstack. */
+
+static const char *
+rust_fully_qualify (struct obstack *obstack, const char *p1, const char *p2)
+{
+ return obconcat (obstack, p1, "::", p2, (char *) NULL);
+}
+
+/* A helper that allocates a struct discriminant_info to attach to a
+ union type. */
+
+static struct discriminant_info *
+alloc_discriminant_info (struct type *type, int discriminant_index,
+ int default_index)
+{
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+ gdb_assert (discriminant_index == -1
+ || (discriminant_index >= 0
+ && discriminant_index < TYPE_NFIELDS (type)));
+ gdb_assert (default_index == -1
+ || (default_index >= 0 && default_index < TYPE_NFIELDS (type)));
+
+ TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+
+ struct discriminant_info *disc
+ = ((struct discriminant_info *)
+ TYPE_ZALLOC (type,
+ offsetof (struct discriminant_info, discriminants)
+ + TYPE_NFIELDS (type) * sizeof (disc->discriminants[0])));
+ disc->default_index = default_index;
+ disc->discriminant_index = discriminant_index;
+
+ struct dynamic_prop prop;
+ prop.kind = PROP_UNDEFINED;
+ prop.data.baton = disc;
+
+ add_dyn_prop (DYN_PROP_DISCRIMINATED, prop, type);
+
+ return disc;
+}
+
+/* Some versions of rustc emitted enums in an unusual way.
+
+ Ordinary enums were emitted as unions. The first element of each
+ structure in the union was named "RUST$ENUM$DISR". This element
+ held the discriminant.
+
+ These versions of Rust also implemented the "non-zero"
+ optimization. When the enum had two values, and one is empty and
+ the other holds a pointer that cannot be zero, the pointer is used
+ as the discriminant, with a zero value meaning the empty variant.
+ Here, the union's first member is of the form
+ RUST$ENCODED$ENUM$<fieldno>$<fieldno>$...$<variantname>
+ where the fieldnos are the indices of the fields that should be
+ traversed in order to find the field (which may be several fields deep)
+ and the variantname is the name of the variant of the case when the
+ field is zero.
+
+ This function recognizes whether TYPE is of one of these forms,
+ and, if so, smashes it to be a variant type. */
+
+static void
+quirk_rust_enum (struct type *type, struct objfile *objfile)
+{
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+
+ /* We don't need to deal with empty enums. */
+ if (TYPE_NFIELDS (type) == 0)
+ return;
+
+#define RUST_ENUM_PREFIX "RUST$ENCODED$ENUM$"
+ if (TYPE_NFIELDS (type) == 1
+ && startswith (TYPE_FIELD_NAME (type, 0), RUST_ENUM_PREFIX))
+ {
+ const char *name = TYPE_FIELD_NAME (type, 0) + strlen (RUST_ENUM_PREFIX);
+
+ /* Decode the field name to find the offset of the
+ discriminant. */
+ ULONGEST bit_offset = 0;
+ struct type *field_type = TYPE_FIELD_TYPE (type, 0);
+ while (name[0] >= '0' && name[0] <= '9')
+ {
+ char *tail;
+ unsigned long index = strtoul (name, &tail, 10);
+ name = tail;
+ if (*name != '$'
+ || index >= TYPE_NFIELDS (field_type)
+ || (TYPE_FIELD_LOC_KIND (field_type, index)
+ != FIELD_LOC_KIND_BITPOS))
+ {
+ complaint (&symfile_complaints,
+ _("Could not parse Rust enum encoding string \"%s\""
+ "[in module %s]"),
+ TYPE_FIELD_NAME (type, 0),
+ objfile_name (objfile));
+ return;
+ }
+ ++name;
+
+ bit_offset += TYPE_FIELD_BITPOS (field_type, index);
+ field_type = TYPE_FIELD_TYPE (field_type, index);
+ }
+
+ /* Make a union to hold the variants. */
+ struct type *union_type = alloc_type (objfile);
+ TYPE_CODE (union_type) = TYPE_CODE_UNION;
+ TYPE_NFIELDS (union_type) = 3;
+ TYPE_FIELDS (union_type)
+ = (struct field *) TYPE_ZALLOC (type, 3 * sizeof (struct field));
+ TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+
+ /* Put the discriminant must at index 0. */
+ TYPE_FIELD_TYPE (union_type, 0) = field_type;
+ TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
+ TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
+ SET_FIELD_BITPOS (TYPE_FIELD (union_type, 0), bit_offset);
+
+ /* The order of fields doesn't really matter, so put the real
+ field at index 1 and the data-less field at index 2. */
+ struct discriminant_info *disc
+ = alloc_discriminant_info (union_type, 0, 1);
+ TYPE_FIELD (union_type, 1) = TYPE_FIELD (type, 0);
+ TYPE_FIELD_NAME (union_type, 1)
+ = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1)));
+ TYPE_NAME (TYPE_FIELD_TYPE (union_type, 1))
+ = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+ TYPE_FIELD_NAME (union_type, 1));
+
+ const char *dataless_name
+ = rust_fully_qualify (&objfile->objfile_obstack, TYPE_NAME (type),
+ name);
+ struct type *dataless_type = init_type (objfile, TYPE_CODE_VOID, 0,
+ dataless_name);
+ TYPE_FIELD_TYPE (union_type, 2) = dataless_type;
+ /* NAME points into the original discriminant name, which
+ already has the correct lifetime. */
+ TYPE_FIELD_NAME (union_type, 2) = name;
+ SET_FIELD_BITPOS (TYPE_FIELD (union_type, 2), 0);
+ disc->discriminants[2] = 0;
+
+ /* Smash this type to be a structure type. We have to do this
+ because the type has already been recorded. */
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+ TYPE_NFIELDS (type) = 1;
+ TYPE_FIELDS (type)
+ = (struct field *) TYPE_ZALLOC (type, sizeof (struct field));
+
+ /* Install the variant part. */
+ TYPE_FIELD_TYPE (type, 0) = union_type;
+ SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+ TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+ }
+ else if (TYPE_NFIELDS (type) == 1)
+ {
+ /* We assume that a union with a single field is a univariant
+ enum. */
+ /* Smash this type to be a structure type. We have to do this
+ because the type has already been recorded. */
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+ /* Make a union to hold the variants. */
+ struct type *union_type = alloc_type (objfile);
+ TYPE_CODE (union_type) = TYPE_CODE_UNION;
+ TYPE_NFIELDS (union_type) = TYPE_NFIELDS (type);
+ TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+ TYPE_FIELDS (union_type) = TYPE_FIELDS (type);
+
+ struct type *field_type = TYPE_FIELD_TYPE (union_type, 0);
+ const char *variant_name
+ = rust_last_path_segment (TYPE_NAME (field_type));
+ TYPE_FIELD_NAME (union_type, 0) = variant_name;
+ TYPE_NAME (field_type)
+ = rust_fully_qualify (&objfile->objfile_obstack,
+ TYPE_NAME (type), variant_name);
+
+ /* Install the union in the outer struct type. */
+ TYPE_NFIELDS (type) = 1;
+ TYPE_FIELDS (type)
+ = (struct field *) TYPE_ZALLOC (union_type, sizeof (struct field));
+ TYPE_FIELD_TYPE (type, 0) = union_type;
+ TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+ SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+
+ alloc_discriminant_info (union_type, -1, 0);
+ }
+ else
+ {
+ struct type *disr_type = nullptr;
+ for (int i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ disr_type = TYPE_FIELD_TYPE (type, i);
+
+ if (TYPE_NFIELDS (disr_type) == 0)
+ {
+ /* Could be data-less variant, so keep going. */
+ }
+ else if (strcmp (TYPE_FIELD_NAME (disr_type, 0),
+ "RUST$ENUM$DISR") != 0)
+ {
+ /* Not a Rust enum. */
+ return;
+ }
+ else
+ {
+ /* Found one. */
+ break;
+ }
+ }
+
+ /* If we got here without a discriminant, then it's probably
+ just a union. */
+ if (disr_type == nullptr)
+ return;
+
+ /* Smash this type to be a structure type. We have to do this
+ because the type has already been recorded. */
+ TYPE_CODE (type) = TYPE_CODE_STRUCT;
+
+ /* Make a union to hold the variants. */
+ struct field *disr_field = &TYPE_FIELD (disr_type, 0);
+ struct type *union_type = alloc_type (objfile);
+ TYPE_CODE (union_type) = TYPE_CODE_UNION;
+ TYPE_NFIELDS (union_type) = 1 + TYPE_NFIELDS (type);
+ TYPE_LENGTH (union_type) = TYPE_LENGTH (type);
+ TYPE_FIELDS (union_type)
+ = (struct field *) TYPE_ZALLOC (union_type,
+ (TYPE_NFIELDS (union_type)
+ * sizeof (struct field)));
+
+ memcpy (TYPE_FIELDS (union_type) + 1, TYPE_FIELDS (type),
+ TYPE_NFIELDS (type) * sizeof (struct field));
+
+ /* Install the discriminant at index 0 in the union. */
+ TYPE_FIELD (union_type, 0) = *disr_field;
+ TYPE_FIELD_ARTIFICIAL (union_type, 0) = 1;
+ TYPE_FIELD_NAME (union_type, 0) = "<<discriminant>>";
+
+ /* Install the union in the outer struct type. */
+ TYPE_FIELD_TYPE (type, 0) = union_type;
+ TYPE_FIELD_NAME (type, 0) = "<<variants>>";
+ TYPE_NFIELDS (type) = 1;
+
+ /* Set the size and offset of the union type. */
+ SET_FIELD_BITPOS (TYPE_FIELD (type, 0), 0);
+
+ /* We need a way to find the correct discriminant given a
+ variant name. For convenience we build a map here. */
+ struct type *enum_type = FIELD_TYPE (*disr_field);
+ std::unordered_map<std::string, ULONGEST> discriminant_map;
+ for (int i = 0; i < TYPE_NFIELDS (enum_type); ++i)
+ {
+ if (TYPE_FIELD_LOC_KIND (enum_type, i) == FIELD_LOC_KIND_ENUMVAL)
+ {
+ const char *name
+ = rust_last_path_segment (TYPE_FIELD_NAME (enum_type, i));
+ discriminant_map[name] = TYPE_FIELD_ENUMVAL (enum_type, i);
+ }
+ }
+
+ int n_fields = TYPE_NFIELDS (union_type);
+ struct discriminant_info *disc
+ = alloc_discriminant_info (union_type, 0, -1);
+ /* Skip the discriminant here. */
+ for (int i = 1; i < n_fields; ++i)
+ {
+ /* Find the final word in the name of this variant's type.
+ That name can be used to look up the correct
+ discriminant. */
+ const char *variant_name
+ = rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (union_type,
+ i)));
+
+ auto iter = discriminant_map.find (variant_name);
+ if (iter != discriminant_map.end ())
+ disc->discriminants[i] = iter->second;
+
+ /* Remove the discriminant field. */
+ struct type *sub_type = TYPE_FIELD_TYPE (union_type, i);
+ --TYPE_NFIELDS (sub_type);
+ ++TYPE_FIELDS (sub_type);
+ TYPE_FIELD_NAME (union_type, i) = variant_name;
+ TYPE_NAME (sub_type)
+ = rust_fully_qualify (&objfile->objfile_obstack,
+ TYPE_NAME (type), variant_name);
+ }
+ }
+}
+
+/* Rewrite some Rust unions to be structures with variants parts. */
+
+static void
+rust_union_quirks (struct dwarf2_cu *cu)
+{
+ gdb_assert (cu->language == language_rust);
+ for (struct type *type : cu->rust_unions)
+ quirk_rust_enum (type, cu->per_cu->dwarf2_per_objfile->objfile);
+}
+
/* Return the symtab for PER_CU. This works properly regardless of
whether we're using the index or psymtabs. */
struct gdbarch *gdbarch = get_objfile_arch (objfile);
CORE_ADDR lowpc, highpc;
struct compunit_symtab *cust;
- struct cleanup *delayed_list_cleanup;
CORE_ADDR baseaddr;
struct block *static_block;
CORE_ADDR addr;
buildsym_init ();
scoped_free_pendings free_pending;
- delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
+
+ /* Clear the list here in case something was left over. */
+ cu->method_list.clear ();
cu->list_in_scope = &file_symbols;
should be complete, and it should now be safe to compute all of the
physnames. */
compute_delayed_physnames (cu);
- do_cleanups (delayed_list_cleanup);
+
+ if (cu->language == language_rust)
+ rust_union_quirks (cu);
/* Some compilers don't define a DW_AT_high_pc attribute for the
compilation unit. If the DW_AT_high_pc is missing, synthesize
struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct compunit_symtab *cust;
- struct cleanup *delayed_list_cleanup;
struct signatured_type *sig_type;
gdb_assert (per_cu->is_debug_types);
buildsym_init ();
scoped_free_pendings free_pending;
- delayed_list_cleanup = make_cleanup (free_delayed_list, cu);
+
+ /* Clear the list here in case something was left over. */
+ cu->method_list.clear ();
cu->list_in_scope = &file_symbols;
should be complete, and it should now be safe to compute all of the
physnames. */
compute_delayed_physnames (cu);
- do_cleanups (delayed_list_cleanup);
+
+ if (cu->language == language_rust)
+ rust_union_quirks (cu);
/* TUs share symbol tables.
If this is the first TU to use this symtab, complete the construction
gdb::unique_xmalloc_ptr<char> demangled;
if (mangled != NULL)
{
- /* 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
- symbol names do not match the full symbol names but for template
- functions there is never a need to look up their definition from their
- declaration so the only disadvantage remains the minimal symbol
- variant `long name(params)' does not have the proper inferior type.
- */
- if (cu->language == language_go)
+ if (language_def (cu->language)->la_store_sym_names_in_linkage_form_p)
+ {
+ /* Do nothing (do not demangle the symbol name). */
+ }
+ else if (cu->language == language_go)
{
/* This is a lie, but we already lie to the caller new_symbol.
new_symbol assumes we return the mangled name.
}
else
{
+ /* 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 symbol names do not match the full
+ symbol names but for template functions there is never a need
+ to look up their definition from their declaration so
+ the only disadvantage remains the minimal symbol variant
+ `long name(params)' does not have the proper inferior type. */
demangled.reset (gdb_demangle (mangled,
(DMGL_PARAMS | DMGL_ANSI
| DMGL_RET_DROP)));
complaint (&symfile_complaints,
_("Computed physname <%s> does not match demangled <%s> "
- "(from linkage <%s>) - DIE at 0x%x [in module %s]"),
- physname, canon, mangled, to_underlying (die->sect_off),
+ "(from linkage <%s>) - DIE at %s [in module %s]"),
+ physname, canon, mangled, sect_offset_str (die->sect_off),
objfile_name (objfile));
/* Prefer DW_AT_linkage_name (in the CANON form) - when it
if (num == MAX_NESTED_IMPORTED_DECLARATIONS)
{
complaint (&symfile_complaints,
- _("DIE at 0x%x has too many recursively imported "
- "declarations"), to_underlying (d->sect_off));
+ _("DIE at %s has too many recursively imported "
+ "declarations"), sect_offset_str (d->sect_off));
return 0;
}
{
complaint (&symfile_complaints,
_("child DW_TAG_imported_declaration expected "
- "- DIE at 0x%x [in module %s]"),
- to_underlying (child_die->sect_off), objfile_name (objfile));
+ "- DIE at %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
+ objfile_name (objfile));
continue;
}
{
complaint (&symfile_complaints,
_("child DW_TAG_imported_declaration has unknown "
- "imported name - DIE at 0x%x [in module %s]"),
- to_underlying (child_die->sect_off), objfile_name (objfile));
+ "imported name - DIE at %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
+ objfile_name (objfile));
continue;
}
if (attr == NULL)
{
complaint (&symfile_complaints,
- _("Dwarf Error: debug entry at offset 0x%x is missing"
+ _("Dwarf Error: debug entry at offset %s is missing"
" its dwo_id [in module %s]"),
- to_underlying (sect_off), dwo_file->dwo_name);
+ sect_offset_str (sect_off), dwo_file->dwo_name);
return;
}
dwo_unit->length = cu->per_cu->length;
if (dwarf_read_debug)
- fprintf_unfiltered (gdb_stdlog, " offset 0x%x, dwo_id %s\n",
- to_underlying (sect_off),
+ fprintf_unfiltered (gdb_stdlog, " offset %s, dwo_id %s\n",
+ sect_offset_str (sect_off),
hex_string (dwo_unit->signature));
}
sect_offset dup_sect_off = dup_cu->sect_off;
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),
+ _("debug cu entry at offset %s is duplicate to"
+ " the entry at offset %s, signature %s"),
+ sect_offset_str (sect_off), sect_offset_str (dup_sect_off),
hex_string (dwo_unit->signature));
}
*slot = (void *)dwo_unit;
try_open_dwop_file (struct dwarf2_per_objfile *dwarf2_per_objfile,
const char *file_name, int is_dwp, int search_cwd)
{
- int desc, flags;
- char *absolute_name;
+ int desc;
/* Blech. OPF_TRY_CWD_FIRST also disables searching the path list if
FILE_NAME contains a '/'. So we can't use it. Instead prepend "."
to debug_file_directory. */
- char *search_path;
+ const char *search_path;
static const char dirname_separator_string[] = { DIRNAME_SEPARATOR, '\0' };
+ gdb::unique_xmalloc_ptr<char> search_path_holder;
if (search_cwd)
{
if (*debug_file_directory != '\0')
- search_path = concat (".", dirname_separator_string,
- debug_file_directory, (char *) NULL);
+ {
+ search_path_holder.reset (concat (".", dirname_separator_string,
+ debug_file_directory,
+ (char *) NULL));
+ search_path = search_path_holder.get ();
+ }
else
- search_path = xstrdup (".");
+ search_path = ".";
}
else
- search_path = xstrdup (debug_file_directory);
+ search_path = debug_file_directory;
- flags = OPF_RETURN_REALPATH;
+ openp_flags flags = OPF_RETURN_REALPATH;
if (is_dwp)
flags |= OPF_SEARCH_IN_PATH;
+
+ gdb::unique_xmalloc_ptr<char> absolute_name;
desc = openp (search_path, flags, file_name,
O_RDONLY | O_BINARY, &absolute_name);
- xfree (search_path);
if (desc < 0)
return NULL;
- gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc));
- xfree (absolute_name);
+ gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name.get (),
+ gnutarget, desc));
if (sym_bfd == NULL)
return NULL;
bfd_set_cacheable (sym_bfd.get (), 1);
dwp_text = string_printf (" [in DWP file %s]",
lbasename (dwp_file->name));
- warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset 0x%x"
+ warning (_("Could not find DWO %s %s(%s)%s referenced by %s at offset %s"
" [in module %s]"),
kind, dwo_name, hex_string (signature),
dwp_text.c_str (),
this_unit->is_debug_types ? "TU" : "CU",
- to_underlying (this_unit->sect_off), objfile_name (objfile));
+ sect_offset_str (this_unit->sect_off), objfile_name (objfile));
}
return NULL;
}
&& !(die->tag == DW_TAG_inlined_subroutine
&& origin_die->tag == DW_TAG_subprogram))
complaint (&symfile_complaints,
- _("DIE 0x%x and its abstract origin 0x%x have different tags"),
- to_underlying (die->sect_off),
- to_underlying (origin_die->sect_off));
+ _("DIE %s and its abstract origin %s have different tags"),
+ sect_offset_str (die->sect_off),
+ sect_offset_str (origin_die->sect_off));
std::vector<sect_offset> offsets;
&& !(child_die->tag == DW_TAG_inlined_subroutine
&& child_origin_die->tag == DW_TAG_subprogram))
complaint (&symfile_complaints,
- _("Child DIE 0x%x and its abstract origin 0x%x have "
+ _("Child DIE %s and its abstract origin %s have "
"different tags"),
- to_underlying (child_die->sect_off),
- to_underlying (child_origin_die->sect_off));
+ sect_offset_str (child_die->sect_off),
+ sect_offset_str (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 "
+ _("Child DIE %s and its abstract origin %s have "
"different parents"),
- to_underlying (child_die->sect_off),
- to_underlying (child_origin_die->sect_off));
+ sect_offset_str (child_die->sect_off),
+ sect_offset_str (child_origin_die->sect_off));
else
offsets.push_back (child_origin_die->sect_off);
}
for (offsetp = offsets.data () + 1; offsetp < offsets_end; offsetp++)
if (offsetp[-1] == *offsetp)
complaint (&symfile_complaints,
- _("Multiple children of DIE 0x%x refer "
- "to DIE 0x%x as their abstract origin"),
- to_underlying (die->sect_off), to_underlying (*offsetp));
+ _("Multiple children of DIE %s refer "
+ "to DIE %s as their abstract origin"),
+ sect_offset_str (die->sect_off), sect_offset_str (*offsetp));
offsetp = offsets.data ();
origin_child_die = origin_die->child;
if (name == NULL)
{
complaint (&symfile_complaints,
- _("missing name for subprogram DIE at %d"),
- to_underlying (die->sect_off));
+ _("missing name for subprogram DIE at %s"),
+ sect_offset_str (die->sect_off));
return;
}
if (!attr || !DW_UNSND (attr))
complaint (&symfile_complaints,
_("cannot get low and high bounds "
- "for subprogram DIE at %d"),
- to_underlying (die->sect_off));
+ "for subprogram DIE at %s"),
+ sect_offset_str (die->sect_off));
return;
}
{
complaint (&symfile_complaints,
_("missing DW_AT_call_return_pc for DW_TAG_call_site "
- "DIE 0x%x [in module %s]"),
- to_underlying (die->sect_off), objfile_name (objfile));
+ "DIE %s [in module %s]"),
+ sect_offset_str (die->sect_off), objfile_name (objfile));
return;
}
pc = attr_value_as_address (attr) + baseaddr;
{
complaint (&symfile_complaints,
_("Duplicate PC %s for DW_TAG_call_site "
- "DIE 0x%x [in module %s]"),
- paddress (gdbarch, pc), to_underlying (die->sect_off),
+ "DIE %s [in module %s]"),
+ paddress (gdbarch, pc), sect_offset_str (die->sect_off),
objfile_name (objfile));
return;
}
{
complaint (&symfile_complaints,
_("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),
+ "DW_TAG_call_site child DIE %s [in module %s]"),
+ child_die->tag, sect_offset_str (child_die->sect_off),
objfile_name (objfile));
continue;
}
else
complaint (&symfile_complaints,
_("Cannot find function owning DW_TAG_call_site "
- "DIE 0x%x [in module %s]"),
- to_underlying (die->sect_off), objfile_name (objfile));
+ "DIE %s [in module %s]"),
+ sect_offset_str (die->sect_off), objfile_name (objfile));
}
}
if (target_physname == NULL)
complaint (&symfile_complaints,
_("DW_AT_call_target target DIE has invalid "
- "physname, for referencing DIE 0x%x [in module %s]"),
- to_underlying (die->sect_off), objfile_name (objfile));
+ "physname, for referencing DIE %s [in module %s]"),
+ sect_offset_str (die->sect_off), objfile_name (objfile));
else
SET_FIELD_PHYSNAME (call_site->target, target_physname);
}
<= PC_BOUNDS_INVALID)
complaint (&symfile_complaints,
_("DW_AT_call_target target DIE has invalid "
- "low pc, for referencing DIE 0x%x [in module %s]"),
- to_underlying (die->sect_off), objfile_name (objfile));
+ "low pc, for referencing DIE %s [in module %s]"),
+ sect_offset_str (die->sect_off), objfile_name (objfile));
else
{
lowpc = gdbarch_adjust_dwarf2_addr (gdbarch, lowpc + baseaddr);
else
complaint (&symfile_complaints,
_("DW_TAG_call_site DW_AT_call_target is neither "
- "block nor reference, for DIE 0x%x [in module %s]"),
- to_underlying (die->sect_off), objfile_name (objfile));
+ "block nor reference, for DIE %s [in module %s]"),
+ sect_offset_str (die->sect_off), objfile_name (objfile));
call_site->per_cu = cu->per_cu;
therefore cannot be even moved to DW_TAG_partial_unit. */
complaint (&symfile_complaints,
_("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),
+ "DW_TAG_call_site child DIE %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
objfile_name (objfile));
continue;
}
{
complaint (&symfile_complaints,
_("No DW_FORM_block* DW_AT_location for "
- "DW_TAG_call_site child DIE 0x%x [in module %s]"),
- to_underlying (child_die->sect_off), objfile_name (objfile));
+ "DW_TAG_call_site child DIE %s [in module %s]"),
+ sect_offset_str (child_die->sect_off), objfile_name (objfile));
continue;
}
else
complaint (&symfile_complaints,
_("Only single DW_OP_reg or DW_OP_fbreg is supported "
"for DW_FORM_block* DW_AT_location is supported for "
- "DW_TAG_call_site child DIE 0x%x "
+ "DW_TAG_call_site child DIE %s "
"[in module %s]"),
- to_underlying (child_die->sect_off),
+ sect_offset_str (child_die->sect_off),
objfile_name (objfile));
continue;
}
{
complaint (&symfile_complaints,
_("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),
+ "DW_TAG_call_site child DIE %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
objfile_name (objfile));
continue;
}
if (!attr_form_is_block (attr))
complaint (&symfile_complaints,
_("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),
+ "DW_TAG_call_site child DIE %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
objfile_name (objfile));
else
{
return PC_BOUNDS_NOT_PRESENT;
}
- /* read_partial_die has also the strict LOW < HIGH requirement. */
+ /* partial_die_info::read has also the strict LOW < HIGH requirement. */
if (high <= low)
return PC_BOUNDS_INVALID;
struct field *fp;
const char *fieldname = "";
- /* Allocate a new field list entry and link it in. */
- new_field = XNEW (struct nextfield);
- make_cleanup (xfree, new_field);
- memset (new_field, 0, sizeof (struct nextfield));
-
if (die->tag == DW_TAG_inheritance)
{
- new_field->next = fip->baseclasses;
- fip->baseclasses = new_field;
+ fip->baseclasses.emplace_back ();
+ new_field = &fip->baseclasses.back ();
}
else
{
- new_field->next = fip->fields;
- fip->fields = new_field;
+ fip->fields.emplace_back ();
+ new_field = &fip->fields.back ();
}
+
fip->nfields++;
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
FIELD_BITSIZE (*fp) = 0;
FIELD_TYPE (*fp) = die_type (die, cu);
FIELD_NAME (*fp) = type_name_no_tag (fp->type);
- fip->nbaseclasses++;
}
+ else if (die->tag == DW_TAG_variant_part)
+ {
+ /* process_structure_scope will treat this DIE as a union. */
+ process_structure_scope (die, cu);
+
+ /* The variant part is relative to the start of the enclosing
+ structure. */
+ SET_FIELD_BITPOS (*fp, 0);
+ fp->type = get_die_type (die, cu);
+ fp->artificial = 1;
+ fp->name = "<<variant>>";
+ }
+ else
+ gdb_assert_not_reached ("missing case in dwarf2_add_field");
}
/* Can the type given by DIE define another type? */
dwarf2_add_type_defn (struct field_info *fip, struct die_info *die,
struct dwarf2_cu *cu)
{
- struct decl_field_list *new_field;
- struct decl_field *fp;
-
- /* Allocate a new field list entry and link it in. */
- new_field = XCNEW (struct decl_field_list);
- make_cleanup (xfree, new_field);
+ struct decl_field fp;
+ memset (&fp, 0, sizeof (fp));
gdb_assert (type_can_define_types (die));
- fp = &new_field->field;
-
/* Get name of field. NULL is okay here, meaning an anonymous type. */
- fp->name = dwarf2_name (die, cu);
- fp->type = read_type_die (die, cu);
+ fp.name = dwarf2_name (die, cu);
+ fp.type = read_type_die (die, cu);
/* Save accessibility. */
enum dwarf_access_attribute accessibility;
/* The assumed value if neither private nor protected. */
break;
case DW_ACCESS_private:
- fp->is_private = 1;
+ fp.is_private = 1;
break;
case DW_ACCESS_protected:
- fp->is_protected = 1;
+ fp.is_protected = 1;
break;
default:
complaint (&symfile_complaints,
}
if (die->tag == DW_TAG_typedef)
- {
- new_field->next = fip->typedef_field_list;
- fip->typedef_field_list = new_field;
- fip->typedef_field_list_count++;
- }
+ fip->typedef_field_list.push_back (fp);
else
- {
- new_field->next = fip->nested_types_list;
- fip->nested_types_list = new_field;
- fip->nested_types_list_count++;
- }
+ fip->nested_types_list.push_back (fp);
}
/* Create the vector of fields, and attach it to the type. */
and create blank accessibility bitfields if necessary. */
TYPE_NFIELDS (type) = nfields;
TYPE_FIELDS (type) = (struct field *)
- TYPE_ALLOC (type, sizeof (struct field) * nfields);
- memset (TYPE_FIELDS (type), 0, sizeof (struct field) * nfields);
+ TYPE_ZALLOC (type, sizeof (struct field) * nfields);
if (fip->non_public_fields && cu->language != language_ada)
{
/* If the type has baseclasses, allocate and clear a bit vector for
TYPE_FIELD_VIRTUAL_BITS. */
- if (fip->nbaseclasses && cu->language != language_ada)
+ if (!fip->baseclasses.empty () && cu->language != language_ada)
{
- int num_bytes = B_BYTES (fip->nbaseclasses);
+ int num_bytes = B_BYTES (fip->baseclasses.size ());
unsigned char *pointer;
ALLOCATE_CPLUS_STRUCT_TYPE (type);
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;
+ B_CLRALL (TYPE_FIELD_VIRTUAL_BITS (type), fip->baseclasses.size ());
+ TYPE_N_BASECLASSES (type) = fip->baseclasses.size ();
}
- /* Copy the saved-up fields into the field vector. Start from the head of
- the list, adding to the tail of the field array, so that they end up in
- the same order in the array in which they were added to the list. */
- while (nfields-- > 0)
+ if (TYPE_FLAG_DISCRIMINATED_UNION (type))
{
- struct nextfield *fieldp;
+ struct discriminant_info *di = alloc_discriminant_info (type, -1, -1);
- if (fip->fields)
+ for (int index = 0; index < nfields; ++index)
{
- fieldp = fip->fields;
- fip->fields = fieldp->next;
- }
- else
- {
- fieldp = fip->baseclasses;
- fip->baseclasses = fieldp->next;
+ struct nextfield &field = fip->fields[index];
+
+ if (field.variant.is_discriminant)
+ di->discriminant_index = index;
+ else if (field.variant.default_branch)
+ di->default_index = index;
+ else
+ di->discriminants[index] = field.variant.discriminant_value;
}
+ }
+
+ /* Copy the saved-up fields into the field vector. */
+ for (int i = 0; i < nfields; ++i)
+ {
+ struct nextfield &field
+ = ((i < fip->baseclasses.size ()) ? fip->baseclasses[i]
+ : fip->fields[i - fip->baseclasses.size ()]);
- TYPE_FIELD (type, nfields) = fieldp->field;
- switch (fieldp->accessibility)
+ TYPE_FIELD (type, i) = field.field;
+ switch (field.accessibility)
{
case DW_ACCESS_private:
if (cu->language != language_ada)
- SET_TYPE_FIELD_PRIVATE (type, nfields);
+ SET_TYPE_FIELD_PRIVATE (type, i);
break;
case DW_ACCESS_protected:
if (cu->language != language_ada)
- SET_TYPE_FIELD_PROTECTED (type, nfields);
+ SET_TYPE_FIELD_PROTECTED (type, i);
break;
case DW_ACCESS_public:
/* Unknown accessibility. Complain and treat it as public. */
{
complaint (&symfile_complaints, _("unsupported accessibility %d"),
- fieldp->accessibility);
+ field.accessibility);
}
break;
}
- if (nfields < fip->nbaseclasses)
+ if (i < fip->baseclasses.size ())
{
- switch (fieldp->virtuality)
+ switch (field.virtuality)
{
case DW_VIRTUALITY_virtual:
case DW_VIRTUALITY_pure_virtual:
if (cu->language == language_ada)
error (_("unexpected virtuality in component of Ada type"));
- SET_TYPE_FIELD_VIRTUAL (type, nfields);
+ SET_TYPE_FIELD_VIRTUAL (type, i);
break;
}
}
{
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
struct attribute *attr;
- struct fnfieldlist *flp;
int i;
+ struct fnfieldlist *flp = nullptr;
struct fn_field *fnp;
const char *fieldname;
- struct nextfnfield *new_fnfield;
struct type *this_type;
enum dwarf_access_attribute accessibility;
return;
/* Look up member function name in fieldlist. */
- for (i = 0; i < fip->nfnfields; i++)
+ for (i = 0; i < fip->fnfieldlists.size (); i++)
{
if (strcmp (fip->fnfieldlists[i].name, fieldname) == 0)
- break;
+ {
+ flp = &fip->fnfieldlists[i];
+ break;
+ }
}
- /* Create new list element if necessary. */
- if (i < fip->nfnfields)
- flp = &fip->fnfieldlists[i];
- else
+ /* Create a new fnfieldlist if necessary. */
+ if (flp == nullptr)
{
- if ((fip->nfnfields % DW_FIELD_ALLOC_CHUNK) == 0)
- {
- fip->fnfieldlists = (struct fnfieldlist *)
- xrealloc (fip->fnfieldlists,
- (fip->nfnfields + DW_FIELD_ALLOC_CHUNK)
- * sizeof (struct fnfieldlist));
- if (fip->nfnfields == 0)
- make_cleanup (free_current_contents, &fip->fnfieldlists);
- }
- flp = &fip->fnfieldlists[fip->nfnfields];
+ fip->fnfieldlists.emplace_back ();
+ flp = &fip->fnfieldlists.back ();
flp->name = fieldname;
- flp->length = 0;
- flp->head = NULL;
- i = fip->nfnfields++;
+ i = fip->fnfieldlists.size () - 1;
}
- /* Create a new member function field and chain it to the field list
- entry. */
- new_fnfield = XNEW (struct nextfnfield);
- make_cleanup (xfree, new_fnfield);
- memset (new_fnfield, 0, sizeof (struct nextfnfield));
- new_fnfield->next = flp->head;
- flp->head = new_fnfield;
- flp->length++;
-
- /* Fill in the member function field info. */
- fnp = &new_fnfield->fnfield;
+ /* Create a new member function field and add it to the vector of
+ fnfieldlists. */
+ flp->fnfields.emplace_back ();
+ fnp = &flp->fnfields.back ();
/* Delay processing of the physname until later. */
if (cu->language == language_cplus)
- {
- add_to_method_list (type, i, flp->length - 1, fieldname,
- die, cu);
- }
+ add_to_method_list (type, i, flp->fnfields.size () - 1, fieldname,
+ die, cu);
else
{
const char *physname = dwarf2_physname (fieldname, die, cu);
{
complaint (&symfile_complaints,
_("cannot determine context for virtual member "
- "function \"%s\" (offset %d)"),
- fieldname, to_underlying (die->sect_off));
+ "function \"%s\" (offset %s)"),
+ fieldname, sect_offset_str (die->sect_off));
}
else
{
{
/* GCC does this, as of 2008-08-25; PR debug/37237. */
complaint (&symfile_complaints,
- _("Member function \"%s\" (offset %d) is virtual "
+ _("Member function \"%s\" (offset %s) is virtual "
"but the vtable offset is not specified"),
- fieldname, to_underlying (die->sect_off));
+ fieldname, sect_offset_str (die->sect_off));
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_CPLUS_DYNAMIC (type) = 1;
}
dwarf2_attach_fn_fields_to_type (struct field_info *fip, struct type *type,
struct dwarf2_cu *cu)
{
- struct fnfieldlist *flp;
- int i;
-
if (cu->language == language_ada)
error (_("unexpected member functions in Ada type"));
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_FN_FIELDLISTS (type) = (struct fn_fieldlist *)
- TYPE_ALLOC (type, sizeof (struct fn_fieldlist) * fip->nfnfields);
+ TYPE_ALLOC (type,
+ sizeof (struct fn_fieldlist) * fip->fnfieldlists.size ());
- for (i = 0, flp = fip->fnfieldlists; i < fip->nfnfields; i++, flp++)
+ for (int i = 0; i < fip->fnfieldlists.size (); i++)
{
- struct nextfnfield *nfp = flp->head;
+ struct fnfieldlist &nf = fip->fnfieldlists[i];
struct fn_fieldlist *fn_flp = &TYPE_FN_FIELDLIST (type, i);
- int k;
- TYPE_FN_FIELDLIST_NAME (type, i) = flp->name;
- TYPE_FN_FIELDLIST_LENGTH (type, i) = flp->length;
+ TYPE_FN_FIELDLIST_NAME (type, i) = nf.name;
+ TYPE_FN_FIELDLIST_LENGTH (type, i) = nf.fnfields.size ();
fn_flp->fn_fields = (struct fn_field *)
- TYPE_ALLOC (type, sizeof (struct fn_field) * flp->length);
- for (k = flp->length; (k--, nfp); nfp = nfp->next)
- fn_flp->fn_fields[k] = nfp->fnfield;
+ TYPE_ALLOC (type, sizeof (struct fn_field) * nf.fnfields.size ());
+
+ for (int k = 0; k < nf.fnfields.size (); ++k)
+ fn_flp->fn_fields[k] = nf.fnfields[k];
}
- TYPE_NFN_FIELDS (type) = fip->nfnfields;
+ TYPE_NFN_FIELDS (type) = fip->fnfieldlists.size ();
}
/* Returns non-zero if NAME is the name of a vtable member in CU's
{
TYPE_CODE (type) = TYPE_CODE_UNION;
}
+ else if (die->tag == DW_TAG_variant_part)
+ {
+ TYPE_CODE (type) = TYPE_CODE_UNION;
+ TYPE_FLAG_DISCRIMINATED_UNION (type) = 1;
+ }
else
{
TYPE_CODE (type) = TYPE_CODE_STRUCT;
return type;
}
+/* A helper for process_structure_scope that handles a single member
+ DIE. */
+
+static void
+handle_struct_member_die (struct die_info *child_die, struct type *type,
+ struct field_info *fi,
+ std::vector<struct symbol *> *template_args,
+ struct dwarf2_cu *cu)
+{
+ if (child_die->tag == DW_TAG_member
+ || child_die->tag == DW_TAG_variable
+ || child_die->tag == DW_TAG_variant_part)
+ {
+ /* NOTE: carlton/2002-11-05: A C++ static data member
+ should be a DW_TAG_member that is a declaration, but
+ all versions of G++ as of this writing (so through at
+ least 3.2.1) incorrectly generate DW_TAG_variable
+ tags for them instead. */
+ dwarf2_add_field (fi, child_die, cu);
+ }
+ else if (child_die->tag == DW_TAG_subprogram)
+ {
+ /* 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);
+ }
+ else if (type_can_define_types (child_die))
+ dwarf2_add_type_defn (fi, child_die, cu);
+ else if (child_die->tag == DW_TAG_template_type_param
+ || child_die->tag == DW_TAG_template_value_param)
+ {
+ struct symbol *arg = new_symbol (child_die, NULL, cu);
+
+ if (arg != NULL)
+ template_args->push_back (arg);
+ }
+ else if (child_die->tag == DW_TAG_variant)
+ {
+ /* In a variant we want to get the discriminant and also add a
+ field for our sole member child. */
+ struct attribute *discr = dwarf2_attr (child_die, DW_AT_discr_value, cu);
+
+ for (struct die_info *variant_child = child_die->child;
+ variant_child != NULL;
+ variant_child = sibling_die (variant_child))
+ {
+ if (variant_child->tag == DW_TAG_member)
+ {
+ handle_struct_member_die (variant_child, type, fi,
+ template_args, cu);
+ /* Only handle the one. */
+ break;
+ }
+ }
+
+ /* We don't handle this but we might as well report it if we see
+ it. */
+ if (dwarf2_attr (child_die, DW_AT_discr_list, cu) != nullptr)
+ complaint (&symfile_complaints,
+ _("DW_AT_discr_list is not supported yet"
+ " - DIE at %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
+ objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+
+ /* The first field was just added, so we can stash the
+ discriminant there. */
+ gdb_assert (!fi->fields.empty ());
+ if (discr == NULL)
+ fi->fields.back ().variant.default_branch = true;
+ else
+ fi->fields.back ().variant.discriminant_value = DW_UNSND (discr);
+ }
+}
+
/* Finish creating a structure or union type, including filling in
its members and creating a symbol for it. */
if (type == NULL)
type = read_structure_type (die, cu);
+ /* When reading a DW_TAG_variant_part, we need to notice when we
+ read the discriminant member, so we can record it later in the
+ discriminant_info. */
+ bool is_variant_part = TYPE_FLAG_DISCRIMINATED_UNION (type);
+ sect_offset discr_offset;
+
+ if (is_variant_part)
+ {
+ struct attribute *discr = dwarf2_attr (die, DW_AT_discr, cu);
+ if (discr == NULL)
+ {
+ /* Maybe it's a univariant form, an extension we support.
+ In this case arrange not to check the offset. */
+ is_variant_part = false;
+ }
+ else if (attr_form_is_ref (discr))
+ {
+ struct dwarf2_cu *target_cu = cu;
+ struct die_info *target_die = follow_die_ref (die, discr, &target_cu);
+
+ discr_offset = target_die->sect_off;
+ }
+ else
+ {
+ complaint (&symfile_complaints,
+ _("DW_AT_discr does not have DIE reference form"
+ " - DIE at %s [in module %s]"),
+ sect_offset_str (die->sect_off),
+ objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
+ is_variant_part = false;
+ }
+ }
+
if (die->child != NULL && ! die_is_declaration (die, cu))
{
struct field_info fi;
std::vector<struct symbol *> template_args;
- struct cleanup *back_to = make_cleanup (null_cleanup, 0);
-
- memset (&fi, 0, sizeof (struct field_info));
child_die = die->child;
while (child_die && child_die->tag)
{
- if (child_die->tag == DW_TAG_member
- || child_die->tag == DW_TAG_variable)
- {
- /* NOTE: carlton/2002-11-05: A C++ static data member
- should be a DW_TAG_member that is a declaration, but
- all versions of G++ as of this writing (so through at
- least 3.2.1) incorrectly generate DW_TAG_variable
- tags for them instead. */
- dwarf2_add_field (&fi, child_die, cu);
- }
- else if (child_die->tag == DW_TAG_subprogram)
- {
- /* 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);
- }
- else if (type_can_define_types (child_die))
- dwarf2_add_type_defn (&fi, child_die, cu);
- else if (child_die->tag == DW_TAG_template_type_param
- || child_die->tag == DW_TAG_template_value_param)
- {
- struct symbol *arg = new_symbol (child_die, NULL, cu);
+ handle_struct_member_die (child_die, type, &fi, &template_args, cu);
- if (arg != NULL)
- template_args.push_back (arg);
- }
+ if (is_variant_part && discr_offset == child_die->sect_off)
+ fi.fields.back ().variant.is_discriminant = true;
child_die = sibling_die (child_die);
}
/* Attach fields and member functions to the type. */
if (fi.nfields)
dwarf2_attach_fields_to_type (&fi, type, cu);
- if (fi.nfnfields)
+ if (!fi.fnfieldlists.empty ())
{
dwarf2_attach_fn_fields_to_type (&fi, type, cu);
/* Copy fi.typedef_field_list linked list elements content into the
allocated array TYPE_TYPEDEF_FIELD_ARRAY (type). */
- if (fi.typedef_field_list)
+ if (!fi.typedef_field_list.empty ())
{
- int i = fi.typedef_field_list_count;
+ int count = fi.typedef_field_list.size ();
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_TYPEDEF_FIELD_ARRAY (type)
= ((struct decl_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. */
- while (--i >= 0)
- {
- struct decl_field *dest, *src;
+ TYPE_ALLOC (type,
+ sizeof (TYPE_TYPEDEF_FIELD (type, 0)) * count));
+ TYPE_TYPEDEF_FIELD_COUNT (type) = count;
- dest = &TYPE_TYPEDEF_FIELD (type, i);
- src = &fi.typedef_field_list->field;
- fi.typedef_field_list = fi.typedef_field_list->next;
- *dest = *src;
- }
+ for (int i = 0; i < fi.typedef_field_list.size (); ++i)
+ TYPE_TYPEDEF_FIELD (type, i) = fi.typedef_field_list[i];
}
/* Copy fi.nested_types_list linked list elements content into the
allocated array TYPE_NESTED_TYPES_ARRAY (type). */
- if (fi.nested_types_list != NULL && cu->language != language_ada)
+ if (!fi.nested_types_list.empty () && cu->language != language_ada)
{
- int i = fi.nested_types_list_count;
+ int count = fi.nested_types_list.size ();
ALLOCATE_CPLUS_STRUCT_TYPE (type);
TYPE_NESTED_TYPES_ARRAY (type)
= ((struct decl_field *)
- TYPE_ALLOC (type, sizeof (struct decl_field) * i));
- TYPE_NESTED_TYPES_COUNT (type) = i;
+ TYPE_ALLOC (type, sizeof (struct decl_field) * count));
+ TYPE_NESTED_TYPES_COUNT (type) = count;
- /* Reverse the list order to keep the debug info elements order. */
- while (--i >= 0)
- {
- struct decl_field *dest, *src;
-
- dest = &TYPE_NESTED_TYPES_FIELD (type, i);
- src = &fi.nested_types_list->field;
- fi.nested_types_list = fi.nested_types_list->next;
- *dest = *src;
- }
+ for (int i = 0; i < fi.nested_types_list.size (); ++i)
+ TYPE_NESTED_TYPES_FIELD (type, i) = fi.nested_types_list[i];
}
-
- do_cleanups (back_to);
}
quirk_gcc_member_function_pointer (type, objfile);
+ if (cu->language == language_rust && die->tag == DW_TAG_union_type)
+ cu->rust_unions.push_back (type);
/* NOTE: carlton/2004-03-16: GCC 3.4 (or at least one of its
snapshots) has been known to create a die giving a declaration
{
complaint (&symfile_complaints,
_("unable to read array DW_AT_byte_stride "
- " - DIE at 0x%x [in module %s]"),
- to_underlying (die->sect_off),
+ " - DIE at %s [in module %s]"),
+ sect_offset_str (die->sect_off),
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
/* Ignore this attribute. We will likely not be able to print
arrays of this type correctly, but there is little we can do
complaint (&symfile_complaints,
_("Variable in common block has "
"DW_AT_data_member_location "
- "- DIE at 0x%x [in module %s]"),
- to_underlying (child_die->sect_off),
+ "- DIE at %s [in module %s]"),
+ sect_offset_str (child_die->sect_off),
objfile_name (objfile));
if (attr_form_is_section_offset (member_loc))
module_name = dwarf2_name (die, cu);
if (!module_name)
complaint (&symfile_complaints,
- _("DW_TAG_module has no name, offset 0x%x"),
- to_underlying (die->sect_off));
+ _("DW_TAG_module has no name, offset %s"),
+ sect_offset_str (die->sect_off));
type = init_type (objfile, TYPE_CODE_MODULE, 0, module_name);
/* determine_prefix uses TYPE_TAG_NAME. */
spec and cause infinite loops in GDB. */
complaint (&symfile_complaints,
_("Self-referential DW_TAG_typedef "
- "- DIE at 0x%x [in module %s]"),
- to_underlying (die->sect_off), objfile_name (objfile));
+ "- DIE at %s [in module %s]"),
+ sect_offset_str (die->sect_off), objfile_name (objfile));
TYPE_TARGET_TYPE (this_type) = NULL;
}
return this_type;
attr_to_dynamic_prop (attr, die, cu, &low);
else if (!low_default_is_valid)
complaint (&symfile_complaints, _("Missing DW_AT_lower_bound "
- "- DIE at 0x%x [in module %s]"),
- to_underlying (die->sect_off),
+ "- DIE at %s [in module %s]"),
+ sect_offset_str (die->sect_off),
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
attr = dwarf2_attr (die, DW_AT_upper_bound, cu);
unsigned int hash_number;
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- abbrev->next = abbrevs[hash_number];
- abbrevs[hash_number] = abbrev;
+ abbrev->next = m_abbrevs[hash_number];
+ m_abbrevs[hash_number] = abbrev;
}
/* Look up an abbrev in the table.
struct abbrev_info *abbrev;
hash_number = abbrev_number % ABBREV_HASH_SIZE;
- abbrev = abbrevs[hash_number];
+ abbrev = m_abbrevs[hash_number];
while (abbrev)
{
{
struct dwarf2_cu *cu = reader->cu;
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- struct partial_die_info *part_die;
struct partial_die_info *parent_die, *last_die, *first_die = NULL;
unsigned int bytes_read;
unsigned int load_all = 0;
hashtab_obstack_allocate,
dummy_obstack_deallocate);
- part_die = XOBNEW (&cu->comp_unit_obstack, struct partial_die_info);
-
while (1)
{
abbrev_info *abbrev = peek_die_abbrev (*reader, info_ptr, &bytes_read);
if (abbrev == NULL)
{
if (--nesting_level == 0)
- {
- /* PART_DIE was probably the last thing allocated on the
- comp_unit_obstack, so we could call obstack_free
- here. We don't do that because the waste is small,
- and will be cleaned up when we're done with this
- compilation unit. This way, we're also more robust
- against other users of the comp_unit_obstack. */
- return first_die;
- }
+ return first_die;
+
info_ptr += bytes_read;
last_die = parent_die;
parent_die = parent_die->die_parent;
continue;
}
- info_ptr = read_partial_die (reader, part_die, abbrev, bytes_read,
- info_ptr);
+ struct partial_die_info pdi ((sect_offset) (info_ptr - reader->buffer),
+ abbrev);
+
+ info_ptr = pdi.read (reader, *abbrev, info_ptr + bytes_read);
/* This two-pass algorithm for processing partial symbols has a
high cost in cache pressure. Thus, handle some simple cases
of them, for a language without namespaces), can be processed
directly. */
if (parent_die == NULL
- && part_die->has_specification == 0
- && part_die->is_declaration == 0
- && ((part_die->tag == DW_TAG_typedef && !part_die->has_children)
- || part_die->tag == DW_TAG_base_type
- || part_die->tag == DW_TAG_subrange_type))
- {
- if (building_psymtab && part_die->name != NULL)
- add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
+ && pdi.has_specification == 0
+ && pdi.is_declaration == 0
+ && ((pdi.tag == DW_TAG_typedef && !pdi.has_children)
+ || pdi.tag == DW_TAG_base_type
+ || pdi.tag == DW_TAG_subrange_type))
+ {
+ if (building_psymtab && pdi.name != NULL)
+ add_psymbol_to_list (pdi.name, strlen (pdi.name), 0,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
0, cu->language, objfile);
- info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
+ info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
continue;
}
it could not find the child DIEs referenced later, this is checked
above. In correct DWARF DW_TAG_typedef should have no children. */
- if (part_die->tag == DW_TAG_typedef && part_die->has_children)
+ if (pdi.tag == DW_TAG_typedef && pdi.has_children)
complaint (&symfile_complaints,
_("DW_TAG_typedef has childen - GCC PR debug/47510 bug "
- "- DIE at 0x%x [in module %s]"),
- to_underlying (part_die->sect_off), objfile_name (objfile));
+ "- DIE at %s [in module %s]"),
+ sect_offset_str (pdi.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
namespace elsewhere), then we can add the partial symbol now
instead of queueing it. */
- if (part_die->tag == DW_TAG_enumerator
+ if (pdi.tag == DW_TAG_enumerator
&& parent_die != NULL
&& parent_die->die_parent == NULL
&& parent_die->tag == DW_TAG_enumeration_type
&& parent_die->has_specification == 0)
{
- if (part_die->name == NULL)
+ if (pdi.name == NULL)
complaint (&symfile_complaints,
_("malformed enumerator DIE ignored"));
else if (building_psymtab)
- add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
+ add_psymbol_to_list (pdi.name, strlen (pdi.name), 0,
VAR_DOMAIN, LOC_CONST,
cu->language == language_cplus
? &objfile->global_psymbols
: &objfile->static_psymbols,
0, cu->language, objfile);
- info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
+ info_ptr = locate_pdi_sibling (reader, &pdi, info_ptr);
continue;
}
+ struct partial_die_info *part_die
+ = new (&cu->comp_unit_obstack) partial_die_info (pdi);
+
/* We'll save this DIE so link it in. */
part_die->die_parent = parent_die;
part_die->die_sibling = NULL;
*slot = part_die;
}
- 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
languages we have to, so that we can get at method physnames
}
}
-/* Read a minimal amount of information into the minimal die structure. */
+partial_die_info::partial_die_info (sect_offset sect_off_,
+ struct abbrev_info *abbrev)
+ : partial_die_info (sect_off_, abbrev->tag, abbrev->has_children)
+{
+}
-static const gdb_byte *
-read_partial_die (const struct die_reader_specs *reader,
- struct partial_die_info *part_die,
- struct abbrev_info *abbrev, unsigned int abbrev_len,
- const gdb_byte *info_ptr)
+/* Read a minimal amount of information into the minimal die structure.
+ INFO_PTR should point just after the initial uleb128 of a DIE. */
+
+const gdb_byte *
+partial_die_info::read (const struct die_reader_specs *reader,
+ const struct abbrev_info &abbrev, const gdb_byte *info_ptr)
{
struct dwarf2_cu *cu = reader->cu;
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- const gdb_byte *buffer = reader->buffer;
unsigned int i;
- struct attribute attr;
int has_low_pc_attr = 0;
int has_high_pc_attr = 0;
int high_pc_relative = 0;
- memset (part_die, 0, sizeof (struct partial_die_info));
-
- part_die->sect_off = (sect_offset) (info_ptr - buffer);
-
- info_ptr += abbrev_len;
-
- if (abbrev == NULL)
- return info_ptr;
-
- part_die->tag = abbrev->tag;
- part_die->has_children = abbrev->has_children;
-
- for (i = 0; i < abbrev->num_attrs; ++i)
+ for (i = 0; i < abbrev.num_attrs; ++i)
{
- info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+ struct attribute attr;
+
+ info_ptr = read_attribute (reader, &attr, &abbrev.attrs[i], info_ptr);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
switch (attr.name)
{
case DW_AT_name:
- switch (part_die->tag)
+ switch (tag)
{
case DW_TAG_compile_unit:
case DW_TAG_partial_unit:
case DW_TAG_enumerator:
/* These tags always have simple identifiers already; no need
to canonicalize them. */
- part_die->name = DW_STRING (&attr);
+ name = DW_STRING (&attr);
break;
default:
- part_die->name
- = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->per_bfd->storage_obstack);
+ {
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+ name
+ = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
+ &objfile->per_bfd->storage_obstack);
+ }
break;
}
break;
assume they will be the same, and we only store the last
one we see. */
if (cu->language == language_ada)
- part_die->name = DW_STRING (&attr);
- part_die->linkage_name = DW_STRING (&attr);
+ name = DW_STRING (&attr);
+ linkage_name = DW_STRING (&attr);
break;
case DW_AT_low_pc:
has_low_pc_attr = 1;
- part_die->lowpc = attr_value_as_address (&attr);
+ lowpc = attr_value_as_address (&attr);
break;
case DW_AT_high_pc:
has_high_pc_attr = 1;
- part_die->highpc = attr_value_as_address (&attr);
+ highpc = attr_value_as_address (&attr);
if (cu->header.version >= 4 && attr_form_is_constant (&attr))
high_pc_relative = 1;
break;
/* Support the .debug_loc offsets. */
if (attr_form_is_block (&attr))
{
- part_die->d.locdesc = DW_BLOCK (&attr);
+ d.locdesc = DW_BLOCK (&attr);
}
else if (attr_form_is_section_offset (&attr))
{
}
break;
case DW_AT_external:
- part_die->is_external = DW_UNSND (&attr);
+ is_external = DW_UNSND (&attr);
break;
case DW_AT_declaration:
- part_die->is_declaration = DW_UNSND (&attr);
+ is_declaration = DW_UNSND (&attr);
break;
case DW_AT_type:
- part_die->has_type = 1;
+ has_type = 1;
break;
case DW_AT_abstract_origin:
case DW_AT_specification:
case DW_AT_extension:
- part_die->has_specification = 1;
- part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
- part_die->spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+ has_specification = 1;
+ spec_offset = dwarf2_get_ref_die_offset (&attr);
+ spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz);
break;
case DW_AT_sibling:
_("ignoring absolute DW_AT_sibling"));
else
{
+ const gdb_byte *buffer = reader->buffer;
sect_offset off = dwarf2_get_ref_die_offset (&attr);
const gdb_byte *sibling_ptr = buffer + to_underlying (off);
else if (sibling_ptr > reader->buffer_end)
dwarf2_section_buffer_overflow_complaint (reader->die_section);
else
- part_die->sibling = sibling_ptr;
+ sibling = sibling_ptr;
}
break;
case DW_AT_byte_size:
- part_die->has_byte_size = 1;
+ has_byte_size = 1;
break;
case DW_AT_const_value:
- part_die->has_const_value = 1;
+ has_const_value = 1;
break;
case DW_AT_calling_convention:
/* DWARF doesn't provide a way to identify a program's source-level
compatibility. */
if (DW_UNSND (&attr) == DW_CC_program
&& cu->language == language_fortran)
- part_die->main_subprogram = 1;
+ main_subprogram = 1;
break;
case DW_AT_inline:
if (DW_UNSND (&attr) == DW_INL_inlined
|| DW_UNSND (&attr) == DW_INL_declared_inlined)
- part_die->may_be_inlined = 1;
+ may_be_inlined = 1;
break;
case DW_AT_import:
- if (part_die->tag == DW_TAG_imported_unit)
+ if (tag == DW_TAG_imported_unit)
{
- part_die->d.sect_off = dwarf2_get_ref_die_offset (&attr);
- part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
+ d.sect_off = dwarf2_get_ref_die_offset (&attr);
+ 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);
+ main_subprogram = DW_UNSND (&attr);
break;
default:
}
if (high_pc_relative)
- part_die->highpc += part_die->lowpc;
+ highpc += lowpc;
if (has_low_pc_attr && has_high_pc_attr)
{
labels are not in the output, so the relocs get a value of 0.
If this is a discarded function, mark the pc bounds as invalid,
so that GDB will ignore it. */
- if (part_die->lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
+ if (lowpc == 0 && !dwarf2_per_objfile->has_section_at_zero)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
complaint (&symfile_complaints,
_("DW_AT_low_pc %s is zero "
- "for DIE at 0x%x [in module %s]"),
- paddress (gdbarch, part_die->lowpc),
- to_underlying (part_die->sect_off), objfile_name (objfile));
+ "for DIE at %s [in module %s]"),
+ paddress (gdbarch, lowpc),
+ sect_offset_str (sect_off),
+ objfile_name (objfile));
}
/* dwarf2_get_pc_bounds has also the strict low < high requirement. */
- else if (part_die->lowpc >= part_die->highpc)
+ else if (lowpc >= highpc)
{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
complaint (&symfile_complaints,
_("DW_AT_low_pc %s is not < DW_AT_high_pc %s "
- "for DIE at 0x%x [in module %s]"),
- paddress (gdbarch, part_die->lowpc),
- paddress (gdbarch, part_die->highpc),
- to_underlying (part_die->sect_off),
+ "for DIE at %s [in module %s]"),
+ paddress (gdbarch, lowpc),
+ paddress (gdbarch, highpc),
+ sect_offset_str (sect_off),
objfile_name (objfile));
}
else
- part_die->has_pc_info = 1;
+ has_pc_info = 1;
}
return info_ptr;
/* Find a cached partial DIE at OFFSET in CU. */
-static struct partial_die_info *
-find_partial_die_in_comp_unit (sect_offset sect_off, struct dwarf2_cu *cu)
+struct partial_die_info *
+dwarf2_cu::find_partial_die (sect_offset sect_off)
{
struct partial_die_info *lookup_die = NULL;
- struct partial_die_info part_die;
+ struct partial_die_info part_die (sect_off);
- part_die.sect_off = sect_off;
lookup_die = ((struct partial_die_info *)
- htab_find_with_hash (cu->partial_dies, &part_die,
+ htab_find_with_hash (partial_dies, &part_die,
to_underlying (sect_off)));
return lookup_die;
if (offset_in_dwz == cu->per_cu->is_dwz
&& offset_in_cu_p (&cu->header, sect_off))
{
- pd = find_partial_die_in_comp_unit (sect_off, cu);
+ pd = cu->find_partial_die (sect_off);
if (pd != NULL)
return pd;
/* We missed recording what we needed.
/* 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%x contains"
- " external reference to offset 0x%x [in module %s].\n"),
- to_underlying (cu->header.sect_off), to_underlying (sect_off),
+ error (_("Dwarf Error: Type Unit at offset %s contains"
+ " external reference to offset %s [in module %s].\n"),
+ sect_offset_str (cu->header.sect_off), sect_offset_str (sect_off),
bfd_get_filename (objfile->obfd));
}
per_cu = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
load_partial_comp_unit (per_cu);
per_cu->cu->last_used = 0;
- pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
+ pd = per_cu->cu->find_partial_die (sect_off);
}
/* If we didn't find it, and not all dies have been loaded,
set. */
load_partial_comp_unit (per_cu);
- pd = find_partial_die_in_comp_unit (sect_off, per_cu->cu);
+ pd = per_cu->cu->find_partial_die (sect_off);
}
if (pd == NULL)
internal_error (__FILE__, __LINE__,
- _("could not find partial DIE 0x%x "
+ _("could not find partial DIE %s "
"in cache [from module %s]\n"),
- to_underlying (sect_off), bfd_get_filename (objfile->obfd));
+ sect_offset_str (sect_off), bfd_get_filename (objfile->obfd));
return pd;
}
}
}
-/* Adjust PART_DIE before generating a symbol for it. This function
- may set the is_external flag or change the DIE's name. */
-
-static void
-fixup_partial_die (struct partial_die_info *part_die,
- struct dwarf2_cu *cu)
+void
+partial_die_info::fixup (struct dwarf2_cu *cu)
{
/* Once we've fixed up a die, there's no point in doing so again.
This also avoids a memory leak if we were to call
guess_partial_die_structure_name multiple times. */
- if (part_die->fixup_called)
+ if (fixup_called)
return;
/* If we found a reference attribute and the DIE has no name, try
to find a name in the referred to DIE. */
- if (part_die->name == NULL && part_die->has_specification)
+ if (name == NULL && has_specification)
{
struct partial_die_info *spec_die;
- spec_die = find_partial_die (part_die->spec_offset,
- part_die->spec_is_dwz, cu);
+ spec_die = find_partial_die (spec_offset, spec_is_dwz, cu);
- fixup_partial_die (spec_die, cu);
+ spec_die->fixup (cu);
if (spec_die->name)
{
- part_die->name = spec_die->name;
+ name = spec_die->name;
/* Copy DW_AT_external attribute if it is set. */
if (spec_die->is_external)
- part_die->is_external = spec_die->is_external;
+ is_external = spec_die->is_external;
}
}
/* Set default names for some unnamed DIEs. */
- if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
- part_die->name = CP_ANONYMOUS_NAMESPACE_STR;
+ if (name == NULL && tag == DW_TAG_namespace)
+ name = CP_ANONYMOUS_NAMESPACE_STR;
/* If there is no parent die to provide a namespace, and there are
children, see if we can determine the namespace from their linkage
if (cu->language == language_cplus
&& !VEC_empty (dwarf2_section_info_def,
cu->per_cu->dwarf2_per_objfile->types)
- && part_die->die_parent == NULL
- && part_die->has_children
- && (part_die->tag == DW_TAG_class_type
- || part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_union_type))
- guess_partial_die_structure_name (part_die, cu);
+ && die_parent == NULL
+ && has_children
+ && (tag == DW_TAG_class_type
+ || tag == DW_TAG_structure_type
+ || tag == DW_TAG_union_type))
+ guess_partial_die_structure_name (this, cu);
/* GCC might emit a nameless struct or union that has a linkage
name. See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47510. */
- if (part_die->name == NULL
- && (part_die->tag == DW_TAG_class_type
- || part_die->tag == DW_TAG_interface_type
- || part_die->tag == DW_TAG_structure_type
- || part_die->tag == DW_TAG_union_type)
- && part_die->linkage_name != NULL)
+ if (name == NULL
+ && (tag == DW_TAG_class_type
+ || tag == DW_TAG_interface_type
+ || tag == DW_TAG_structure_type
+ || tag == DW_TAG_union_type)
+ && linkage_name != NULL)
{
char *demangled;
- demangled = gdb_demangle (part_die->linkage_name, DMGL_TYPES);
+ demangled = gdb_demangle (linkage_name, DMGL_TYPES);
if (demangled)
{
const char *base;
base = demangled;
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- part_die->name
+ name
= ((const char *)
obstack_copy0 (&objfile->per_bfd->storage_obstack,
base, strlen (base)));
}
}
- part_die->fixup_called = 1;
+ fixup_called = 1;
}
/* Read an attribute value described by an attribute form. */
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%x [in module %s]"),
- form_name, to_underlying (cu->header.sect_off), objf_name);
+ " in CU at offset %s [in module %s]"),
+ form_name, sect_offset_str (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%x [in module %s]"),
- form_name, to_underlying (cu->header.sect_off), objf_name);
+ " in CU at offset %s [in module %s]"),
+ form_name, sect_offset_str (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%x [in module %s]"),
- form_name, to_underlying (cu->header.sect_off), objf_name);
+ " section in CU at offset %s [in module %s]"),
+ form_name, sect_offset_str (cu->header.sect_off), objf_name);
info_ptr = (str_offsets_section->buffer
+ str_index * cu->header.offset_size);
if (cu->header.offset_size == 4)
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%x [in module %s]"),
- form_name, to_underlying (cu->header.sect_off), objf_name);
+ " .debug_str.dwo section in CU at offset %s [in module %s]"),
+ form_name, sect_offset_str (cu->header.sect_off), objf_name);
return (const char *) (str_section->buffer + str_offset);
}
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),
+ "DIE at %s in module %s"),
+ dwarf_attr_name (name), sect_offset_str (die->sect_off),
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
}
Return the file name of the psymtab for included file FILE_INDEX
in line header LH of PST.
COMP_DIR is the compilation directory (DW_AT_comp_dir) or NULL if unknown.
- If space for the result is malloc'd, it will be freed by a cleanup.
- Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename.
-
- The function creates dangling cleanup registration. */
+ If space for the result is malloc'd, *NAME_HOLDER will be set.
+ Returns NULL if FILE_INDEX should be ignored, i.e., it is pst->filename. */
static const char *
psymtab_include_file_name (const struct line_header *lh, int file_index,
const struct partial_symtab *pst,
- const char *comp_dir)
+ const char *comp_dir,
+ gdb::unique_xmalloc_ptr<char> *name_holder)
{
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 *pst_filename;
- char *copied_name = NULL;
int file_is_pst;
const char *dir_name = fe.include_dir (lh);
+ gdb::unique_xmalloc_ptr<char> hold_compare;
if (!IS_ABSOLUTE_PATH (include_name)
&& (dir_name != NULL || comp_dir != NULL))
{
if (dir_name != NULL)
{
- char *tem = concat (dir_name, SLASH_STRING,
- include_name, (char *)NULL);
-
- make_cleanup (xfree, tem);
- include_name = tem;
+ name_holder->reset (concat (dir_name, SLASH_STRING,
+ include_name, (char *) NULL));
+ include_name = name_holder->get ();
include_name_to_compare = include_name;
}
if (!IS_ABSOLUTE_PATH (include_name) && comp_dir != NULL)
{
- char *tem = concat (comp_dir, SLASH_STRING,
- include_name, (char *)NULL);
-
- make_cleanup (xfree, tem);
- include_name_to_compare = tem;
+ hold_compare.reset (concat (comp_dir, SLASH_STRING,
+ include_name, (char *) NULL));
+ include_name_to_compare = hold_compare.get ();
}
}
pst_filename = pst->filename;
+ gdb::unique_xmalloc_ptr<char> copied_name;
if (!IS_ABSOLUTE_PATH (pst_filename) && pst->dirname != NULL)
{
- copied_name = concat (pst->dirname, SLASH_STRING,
- pst_filename, (char *)NULL);
- pst_filename = copied_name;
+ copied_name.reset (concat (pst->dirname, SLASH_STRING,
+ pst_filename, (char *) NULL));
+ pst_filename = copied_name.get ();
}
file_is_pst = FILENAME_CMP (include_name_to_compare, pst_filename) == 0;
- if (copied_name != NULL)
- xfree (copied_name);
-
if (file_is_pst)
return NULL;
return include_name;
for (file_index = 0; file_index < lh->file_names.size (); file_index++)
if (lh->file_names[file_index].included_p == 1)
{
+ gdb::unique_xmalloc_ptr<char> name_holder;
const char *include_name =
- psymtab_include_file_name (lh, file_index, pst, comp_dir);
+ psymtab_include_file_name (lh, file_index, pst, comp_dir,
+ &name_holder);
if (include_name != NULL)
dwarf2_create_include_psymtab (include_name, pst, objfile);
}
static int
need_gnat_info (struct dwarf2_cu *cu)
{
- /* FIXME: brobecker/2010-10-12: As of now, only the AdaCore version
- of GNAT produces this auxiliary information, without any indication
- that it is produced. Part of enhancing the FSF version of GNAT
- to produce that information will be to put in place an indicator
- that we can use in order to determine whether the descriptive type
- info is available or not. One suggestion that has been made is
- to use a new attribute, attached to the CU die. For now, assume
- that the descriptive type info is not available. */
- return 0;
+ /* Assume that the Ada compiler was GNAT, which always produces
+ the auxiliary information. */
+ return (cu->language == language_ada);
}
/* Return the auxiliary type of the die in question using its
struct objfile *objfile = dwarf2_per_objfile->objfile;
char *message, *saved;
- message = xstrprintf (_("<unknown type in %s, CU 0x%x, DIE 0x%x>"),
+ message = xstrprintf (_("<unknown type in %s, CU %s, DIE %s>"),
objfile_name (objfile),
- to_underlying (cu->header.sect_off),
- to_underlying (die->sect_off));
+ sect_offset_str (cu->header.sect_off),
+ sect_offset_str (die->sect_off));
saved = (char *) obstack_copy0 (&objfile->objfile_obstack,
message, strlen (message));
xfree (message);
{
complaint (&symfile_complaints,
_("Dwarf Error: Bad type attribute %s in DIE"
- " at 0x%x [in module %s]"),
- dwarf_attr_name (attr->name), to_underlying (die->sect_off),
+ " at %s [in module %s]"),
+ dwarf_attr_name (attr->name), sect_offset_str (die->sect_off),
objfile_name (objfile));
return build_error_marker_type (cu, die);
}
unsigned int i;
print_spaces (indent, f);
- fprintf_unfiltered (f, "Die: %s (abbrev %d, offset 0x%x)\n",
+ fprintf_unfiltered (f, "Die: %s (abbrev %d, offset %s)\n",
dwarf_tag_name (die->tag), die->abbrev,
- to_underlying (die->sect_off));
+ sect_offset_str (die->sect_off));
if (die->parent != NULL)
{
print_spaces (indent, f);
- fprintf_unfiltered (f, " parent at offset: 0x%x\n",
- to_underlying (die->parent->sect_off));
+ fprintf_unfiltered (f, " parent at offset: %s\n",
+ sect_offset_str (die->parent->sect_off));
}
print_spaces (indent, f);
|| 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]"),
- to_underlying (sect_off), to_underlying (src_die->sect_off),
+ error (_("Dwarf Error: Cannot find DIE at %s referenced from DIE "
+ "at %s [in module %s]"),
+ sect_offset_str (sect_off), sect_offset_str (src_die->sect_off),
objfile_name (cu->per_cu->dwarf2_per_objfile->objfile));
return die;
{
/* 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"),
- to_underlying (sect_off), objfile_name (objfile));
+ error (_("Dwarf Error: Dummy CU at %s referenced in module %s"),
+ sect_offset_str (sect_off), objfile_name (objfile));
}
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"),
- to_underlying (sect_off), objfile_name (objfile));
+ error (_("Dwarf Error: Cannot find DIE at %s referenced in module %s"),
+ sect_offset_str (sect_off), objfile_name (objfile));
attr = dwarf2_attr (die, DW_AT_location, cu);
if (!attr)
else
{
if (!attr_form_is_block (attr))
- error (_("Dwarf Error: DIE at 0x%x referenced in module %s "
+ error (_("Dwarf Error: DIE at %s referenced in module %s "
"is neither DW_FORM_block* nor DW_FORM_exprloc"),
- to_underlying (sect_off), objfile_name (objfile));
+ sect_offset_str (sect_off), objfile_name (objfile));
retval.data = DW_BLOCK (attr)->data;
retval.size = DW_BLOCK (attr)->size;
{
/* 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"),
- to_underlying (sect_off), objfile_name (objfile));
+ error (_("Dwarf Error: Dummy CU at %s referenced in module %s"),
+ sect_offset_str (sect_off), objfile_name (objfile));
}
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"),
- to_underlying (sect_off), objfile_name (objfile));
-
+ error (_("Dwarf Error: Cannot find DIE at %s referenced in module %s"),
+ sect_offset_str (sect_off), objfile_name (objfile));
attr = dwarf2_attr (die, DW_AT_const_value, cu);
if (attr == NULL)
if (sig_type == NULL)
{
error (_("Dwarf Error: Cannot find signatured DIE %s referenced"
- " from DIE at 0x%x [in module %s]"),
- hex_string (signature), to_underlying (src_die->sect_off),
+ " from DIE at %s [in module %s]"),
+ hex_string (signature), sect_offset_str (src_die->sect_off),
objfile_name ((*ref_cu)->per_cu->dwarf2_per_objfile->objfile));
}
{
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), to_underlying (src_die->sect_off),
+ " from DIE at %s [in module %s]"),
+ hex_string (signature), sect_offset_str (src_die->sect_off),
objfile_name ((*ref_cu)->per_cu->dwarf2_per_objfile->objfile));
}
{
complaint (&symfile_complaints,
_("Dwarf Error: Cannot find signatured DIE %s referenced"
- " from DIE at 0x%x [in module %s]"),
- hex_string (signature), to_underlying (die->sect_off),
+ " from DIE at %s [in module %s]"),
+ hex_string (signature), sect_offset_str (die->sect_off),
objfile_name (dwarf2_per_objfile->objfile));
return build_error_marker_type (cu, die);
}
{
complaint (&symfile_complaints,
_("Dwarf Error: Cannot build signatured type %s"
- " referenced from DIE at 0x%x [in module %s]"),
- hex_string (signature), to_underlying (die->sect_off),
+ " referenced from DIE at %s [in module %s]"),
+ hex_string (signature), sect_offset_str (die->sect_off),
objfile_name (dwarf2_per_objfile->objfile));
type = build_error_marker_type (cu, die);
}
{
complaint (&symfile_complaints,
_("Dwarf Error: Problem reading signatured DIE %s referenced"
- " from DIE at 0x%x [in module %s]"),
- hex_string (signature), to_underlying (die->sect_off),
+ " from DIE at %s [in module %s]"),
+ hex_string (signature), sect_offset_str (die->sect_off),
objfile_name (dwarf2_per_objfile->objfile));
type = build_error_marker_type (cu, die);
}
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), to_underlying (die->sect_off),
+ " at %s [in module %s]"),
+ dwarf_form_name (attr->form), sect_offset_str (die->sect_off),
objfile_name (dwarf2_per_objfile->objfile));
return build_error_marker_type (cu, die);
}
{
if (low == 0 || this_cu->is_dwz != offset_in_dwz)
error (_("Dwarf Error: could not find partial DIE containing "
- "offset 0x%x [in module %s]"),
- to_underlying (sect_off),
+ "offset %s [in module %s]"),
+ sect_offset_str (sect_off),
bfd_get_filename (dwarf2_per_objfile->objfile->obfd));
gdb_assert (dwarf2_per_objfile->all_comp_units[low-1]->sect_off
this_cu = dwarf2_per_objfile->all_comp_units[low];
if (low == dwarf2_per_objfile->n_comp_units - 1
&& sect_off >= this_cu->sect_off + this_cu->length)
- error (_("invalid dwarf2 offset %u"), to_underlying (sect_off));
+ error (_("invalid dwarf2 offset %s"), sect_offset_str (sect_off));
gdb_assert (sect_off < this_cu->sect_off + this_cu->length);
return this_cu;
}
struct dwarf2_per_objfile *dwarf2_per_objfile
= get_dwarf2_per_objfile (objfile);
- if (dwarf2_per_objfile == NULL)
- return;
-
- dwarf2_per_objfile->~dwarf2_per_objfile ();
+ delete dwarf2_per_objfile;
}
/* A set of CU "per_cu" pointer, DIE offset, and GDB type pointer.
if (attr_form_is_block (attr))
{
if (attr_to_dynamic_prop (attr, die, cu, &prop))
- add_dyn_prop (DYN_PROP_ALLOCATED, prop, type, objfile);
+ add_dyn_prop (DYN_PROP_ALLOCATED, prop, type);
}
else if (attr != NULL)
{
complaint (&symfile_complaints,
- _("DW_AT_allocated has the wrong form (%s) at DIE 0x%x"),
+ _("DW_AT_allocated has the wrong form (%s) at DIE %s"),
(attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
- to_underlying (die->sect_off));
+ sect_offset_str (die->sect_off));
}
/* Read DW_AT_associated and set in type. */
if (attr_form_is_block (attr))
{
if (attr_to_dynamic_prop (attr, die, cu, &prop))
- add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type, objfile);
+ add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type);
}
else if (attr != NULL)
{
complaint (&symfile_complaints,
- _("DW_AT_associated has the wrong form (%s) at DIE 0x%x"),
+ _("DW_AT_associated has the wrong form (%s) at DIE %s"),
(attr != NULL ? dwarf_form_name (attr->form) : "n/a"),
- to_underlying (die->sect_off));
+ sect_offset_str (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))
- add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type, objfile);
+ add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type);
if (dwarf2_per_objfile->die_type_hash == NULL)
{
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"),
- to_underlying (die->sect_off));
+ _("A problem internal to GDB: DIE %s has type already set"),
+ sect_offset_str (die->sect_off));
*slot = XOBNEW (&objfile->objfile_obstack,
struct dwarf2_per_cu_offset_and_type);
**slot = ofs;
cmd_show_list (show_dwarf_cmdlist, from_tty, "");
}
-/* Free data associated with OBJFILE, if necessary. */
-
-static void
-dwarf2_per_objfile_free (struct objfile *objfile, void *d)
-{
- struct dwarf2_per_objfile *data = (struct dwarf2_per_objfile *) d;
- int ix;
-
- for (ix = 0; ix < data->n_comp_units; ++ix)
- VEC_free (dwarf2_per_cu_ptr, data->all_comp_units[ix]->imported_symtabs);
-
- for (ix = 0; ix < data->n_type_units; ++ix)
- VEC_free (dwarf2_per_cu_ptr,
- data->all_type_units[ix]->per_cu.imported_symtabs);
- xfree (data->all_type_units);
-
- VEC_free (dwarf2_section_info_def, data->types);
-
- if (data->dwo_files)
- free_dwo_files (data->dwo_files, objfile);
- if (data->dwp_file)
- gdb_bfd_unref (data->dwp_file->dbfd);
-
- if (data->dwz_file && data->dwz_file->dwz_bfd)
- gdb_bfd_unref (data->dwz_file->dwz_bfd);
-
- if (data->index_table != NULL)
- data->index_table->~mapped_index ();
-}
-
-\f
-/* The "save gdb-index" command. */
-
-/* Write SIZE bytes from the buffer pointed to by DATA to FILE, with
- error checking. */
+int dwarf_always_disassemble;
static void
-file_write (FILE *file, const void *data, size_t size)
+show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
{
- if (fwrite (data, 1, size, file) != size)
- error (_("couldn't data write to file"));
+ fprintf_filtered (file,
+ _("Whether to always disassemble "
+ "DWARF expressions is %s.\n"),
+ value);
}
-/* Write the contents of VEC to FILE, with error checking. */
-
-template<typename Elem, typename Alloc>
static void
-file_write (FILE *file, const std::vector<Elem, Alloc> &vec)
+show_check_physname (struct ui_file *file, int from_tty,
+ struct cmd_list_element *c, const char *value)
{
- file_write (file, vec.data (), vec.size () * sizeof (vec[0]));
+ fprintf_filtered (file,
+ _("Whether to check \"physname\" is %s.\n"),
+ value);
}
-/* In-memory buffer to prepare data to be written later to a file. */
-class data_buf
+void
+_initialize_dwarf2_read (void)
{
-public:
- /* Copy DATA to the end of the buffer. */
- template<typename T>
- void append_data (const T &data)
- {
- std::copy (reinterpret_cast<const gdb_byte *> (&data),
- reinterpret_cast<const gdb_byte *> (&data + 1),
- grow (sizeof (data)));
- }
- /* 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));
- }
+ dwarf2_objfile_data_key = register_objfile_data ();
- /* Store INPUT as ULEB128 to the end of buffer. */
- void append_unsigned_leb128 (ULONGEST input)
- {
- for (;;)
- {
- gdb_byte output = input & 0x7f;
- input >>= 7;
- if (input)
- output |= 0x80;
- append_data (output);
- if (input == 0)
- break;
- }
- }
+ add_prefix_cmd ("dwarf", class_maintenance, set_dwarf_cmd, _("\
+Set DWARF specific variables.\n\
+Configure DWARF variables such as the cache size"),
+ &set_dwarf_cmdlist, "maintenance set dwarf ",
+ 0/*allow-unknown*/, &maintenance_set_cmdlist);
- /* 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);
- }
+ add_prefix_cmd ("dwarf", class_maintenance, show_dwarf_cmd, _("\
+Show DWARF specific variables\n\
+Show DWARF variables such as the cache size"),
+ &show_dwarf_cmdlist, "maintenance show dwarf ",
+ 0/*allow-unknown*/, &maintenance_show_cmdlist);
- /* Return the size of the buffer. */
- size_t size () const
- {
- return m_vec.size ();
- }
+ add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
+ &dwarf_max_cache_age, _("\
+Set the upper bound on the age of cached DWARF compilation units."), _("\
+Show the upper bound on the age of cached DWARF compilation units."), _("\
+A higher limit means that cached compilation units will be stored\n\
+in memory longer, and more total memory will be used. Zero disables\n\
+caching, which can slow down startup."),
+ NULL,
+ show_dwarf_max_cache_age,
+ &set_dwarf_cmdlist,
+ &show_dwarf_cmdlist);
- /* Return true iff the buffer is empty. */
- bool empty () const
- {
- return m_vec.empty ();
- }
+ add_setshow_boolean_cmd ("always-disassemble", class_obscure,
+ &dwarf_always_disassemble, _("\
+Set whether `info address' always disassembles DWARF expressions."), _("\
+Show whether `info address' always disassembles DWARF expressions."), _("\
+When enabled, DWARF expressions are always printed in an assembly-like\n\
+syntax. When disabled, expressions will be printed in a more\n\
+conversational style, when possible."),
+ NULL,
+ show_dwarf_always_disassemble,
+ &set_dwarf_cmdlist,
+ &show_dwarf_cmdlist);
- /* Write the buffer to FILE. */
- void file_write (FILE *file) const
- {
- ::file_write (file, m_vec);
- }
+ add_setshow_zuinteger_cmd ("dwarf-read", no_class, &dwarf_read_debug, _("\
+Set debugging of the DWARF reader."), _("\
+Show debugging of the DWARF reader."), _("\
+When enabled (non-zero), debugging messages are printed during DWARF\n\
+reading and symtab expansion. A value of 1 (one) provides basic\n\
+information. A value greater than 1 provides more verbose information."),
+ NULL,
+ NULL,
+ &setdebuglist, &showdebuglist);
-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;
- }
-
- gdb::byte_vector m_vec;
-};
-
-/* An entry in the symbol table. */
-struct symtab_index_entry
-{
- /* The name of the symbol. */
- const char *name;
- /* The offset of the name in the constant pool. */
- offset_type index_offset;
- /* A sorted vector of the indices of all the CUs that hold an object
- of this name. */
- std::vector<offset_type> cu_indices;
-};
-
-/* The symbol table. This is a power-of-2-sized hash table. */
-struct mapped_symtab
-{
- mapped_symtab ()
- {
- data.resize (1024);
- }
-
- offset_type n_elements = 0;
- std::vector<symtab_index_entry> data;
-};
-
-/* 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 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->data.size () - 1);
- step = ((hash * 17) & (symtab->data.size () - 1)) | 1;
-
- for (;;)
- {
- if (symtab->data[index].name == NULL
- || strcmp (name, symtab->data[index].name) == 0)
- return symtab->data[index];
- index = (index + step) & (symtab->data.size () - 1);
- }
-}
-
-/* Expand SYMTAB's hash table. */
-
-static void
-hash_expand (struct mapped_symtab *symtab)
-{
- auto old_entries = std::move (symtab->data);
-
- symtab->data.clear ();
- symtab->data.resize (old_entries.size () * 2);
-
- 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.
- CU_INDEX is the index of the CU in which the symbol appears.
- IS_STATIC is one if the symbol is static, otherwise zero (global). */
-
-static void
-add_index_entry (struct mapped_symtab *symtab, const char *name,
- int is_static, gdb_index_symbol_kind kind,
- offset_type cu_index)
-{
- offset_type cu_index_and_attrs;
-
- ++symtab->n_elements;
- if (4 * symtab->n_elements / 3 >= symtab->data.size ())
- hash_expand (symtab);
-
- symtab_index_entry &slot = find_slot (symtab, name);
- if (slot.name == NULL)
- {
- slot.name = name;
- /* index_offset is set later. */
- }
-
- cu_index_and_attrs = 0;
- DW2_GDB_INDEX_CU_SET_VALUE (cu_index_and_attrs, cu_index);
- DW2_GDB_INDEX_SYMBOL_STATIC_SET_VALUE (cu_index_and_attrs, is_static);
- DW2_GDB_INDEX_SYMBOL_KIND_SET_VALUE (cu_index_and_attrs, kind);
-
- /* We don't want to record an index value twice as we want to avoid the
- duplication.
- We process all global symbols and then all static symbols
- (which would allow us to avoid the duplication by only having to check
- the last entry pushed), but a symbol could have multiple kinds in one CU.
- To keep things simple we don't worry about the duplication here and
- sort and uniqufy the list after we've processed all symbols. */
- slot.cu_indices.push_back (cu_index_and_attrs);
-}
-
-/* Sort and remove duplicates of all symbols' cu_indices lists. */
-
-static void
-uniquify_cu_indices (struct mapped_symtab *symtab)
-{
- for (auto &entry : symtab->data)
- {
- if (entry.name != NULL && !entry.cu_indices.empty ())
- {
- 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 ());
- }
- }
-}
-
-/* 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
-{
-public:
- c_str_view (const char *cstr)
- : m_cstr (cstr)
- {}
-
- bool operator== (const c_str_view &other) const
- {
- return strcmp (m_cstr, other.m_cstr) == 0;
- }
-
- /* Return the underlying C string. Note, the returned string is
- only a reference with lifetime of this object. */
- const char *c_str () const
- {
- return m_cstr;
- }
-
-private:
- friend class c_str_view_hasher;
- const char *const m_cstr;
-};
-
-/* 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<typename T>
-class vector_hasher
-{
-public:
- size_t operator () (const std::vector<T> &key) const
- {
- return iterative_hash (key.data (),
- sizeof (key.front ()) * key.size (), 0);
- }
-};
-
-/* 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 (mapped_symtab *symtab, data_buf &output, data_buf &cpool)
-{
- {
- /* Elements are sorted vectors of the indices of all the CUs that
- hold an object of this name. */
- std::unordered_map<std::vector<offset_type>, offset_type,
- vector_hasher<offset_type>>
- 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;
- }
-
- 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. */
- std::unordered_map<c_str_view, offset_type, c_str_view_hasher> str_table;
- for (const auto &entry : symtab->data)
- {
- offset_type str_off, vec_off;
-
- if (entry.name != NULL)
- {
- 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
- {
- /* While 0 is a valid constant pool index, it is not valid
- to have 0 for both offsets. */
- str_off = 0;
- vec_off = 0;
- }
-
- output.append_data (MAYBE_SWAP (str_off));
- output.append_data (MAYBE_SWAP (vec_off));
- }
-}
-
-typedef std::unordered_map<partial_symtab *, unsigned int> 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;
- 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
- that we know the end of the entry). */
- int previous_valid;
- /* Index of the CU in the table of all CUs in the index file. */
- unsigned int previous_cu_index;
- /* Start address of the CU. */
- CORE_ADDR previous_cu_start;
-};
-
-/* Write an address entry to ADDR_VEC. */
-
-static void
-add_address_entry (struct objfile *objfile, data_buf &addr_vec,
- CORE_ADDR start, CORE_ADDR end, unsigned int cu_index)
-{
- CORE_ADDR baseaddr;
-
- baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-
- 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. */
-
-static int
-add_address_entry_worker (void *datap, CORE_ADDR start_addr, void *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_vec,
- data->previous_cu_start, start_addr,
- data->previous_cu_index);
-
- data->previous_cu_start = start_addr;
- if (pst != NULL)
- {
- 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;
-
- return 0;
-}
-
-/* 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, data_buf &addr_vec,
- psym_index_map &cu_index_htab)
-{
- 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.previous_valid = 0;
-
- addrmap_foreach (objfile->psymtabs_addrmap, add_address_entry_worker,
- &addrmap_index_data);
-
- /* It's highly unlikely the last entry (end address = 0xff...ff)
- is valid, but we should still handle it.
- The end address is recorded as the start of the next region, but that
- 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, addr_vec,
- addrmap_index_data.previous_cu_start, (CORE_ADDR) -1,
- addrmap_index_data.previous_cu_index);
-}
-
-/* Return the symbol kind of PSYM. */
-
-static gdb_index_symbol_kind
-symbol_kind (struct partial_symbol *psym)
-{
- domain_enum domain = PSYMBOL_DOMAIN (psym);
- enum address_class aclass = PSYMBOL_CLASS (psym);
-
- switch (domain)
- {
- case VAR_DOMAIN:
- switch (aclass)
- {
- case LOC_BLOCK:
- return GDB_INDEX_SYMBOL_KIND_FUNCTION;
- case LOC_TYPEDEF:
- return GDB_INDEX_SYMBOL_KIND_TYPE;
- case LOC_COMPUTED:
- case LOC_CONST_BYTES:
- case LOC_OPTIMIZED_OUT:
- case LOC_STATIC:
- return GDB_INDEX_SYMBOL_KIND_VARIABLE;
- case LOC_CONST:
- /* Note: It's currently impossible to recognize psyms as enum values
- short of reading the type info. For now punt. */
- return GDB_INDEX_SYMBOL_KIND_VARIABLE;
- default:
- /* There are other LOC_FOO values that one might want to classify
- as variables, but dwarf2read.c doesn't currently use them. */
- return GDB_INDEX_SYMBOL_KIND_OTHER;
- }
- case STRUCT_DOMAIN:
- return GDB_INDEX_SYMBOL_KIND_TYPE;
- default:
- return GDB_INDEX_SYMBOL_KIND_OTHER;
- }
-}
-
-/* Add a list of partial symbols to SYMTAB. */
-
-static void
-write_psymbols (struct mapped_symtab *symtab,
- std::unordered_set<partial_symbol *> &psyms_seen,
- struct partial_symbol **psymp,
- int count,
- offset_type cu_index,
- int is_static)
-{
- for (; count-- > 0; ++psymp)
- {
- struct partial_symbol *psym = *psymp;
-
- if (SYMBOL_LANGUAGE (psym) == language_ada)
- error (_("Ada is not currently supported by the index"));
-
- /* Only add a given psymbol once. */
- if (psyms_seen.insert (psym).second)
- {
- gdb_index_symbol_kind kind = symbol_kind (psym);
-
- add_index_entry (symtab, SYMBOL_SEARCH_NAME (psym),
- is_static, kind, cu_index);
- }
- }
-}
-
-/* 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<partial_symbol *> &psyms_seen_)
- : types_list (types_list_), psyms_seen (psyms_seen_)
- {}
-
- struct objfile *objfile;
- struct mapped_symtab *symtab;
- data_buf &types_list;
- std::unordered_set<partial_symbol *> &psyms_seen;
- int cu_index;
-};
-
-/* A helper function that writes a single signatured_type to an
- obstack. */
-
-static int
-write_one_signatured_type (void **slot, void *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;
-
- write_psymbols (info->symtab,
- info->psyms_seen,
- &info->objfile->global_psymbols[psymtab->globals_offset],
- psymtab->n_global_syms, info->cu_index,
- 0);
- write_psymbols (info->symtab,
- info->psyms_seen,
- &info->objfile->static_psymbols[psymtab->statics_offset],
- psymtab->n_static_syms, info->cu_index,
- 1);
-
- 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. */
-
-static void
-recursively_write_psymbols (struct objfile *objfile,
- struct partial_symtab *psymtab,
- struct mapped_symtab *symtab,
- std::unordered_set<partial_symbol *> &psyms_seen,
- offset_type cu_index)
-{
- int i;
-
- for (i = 0; i < psymtab->number_of_dependencies; ++i)
- if (psymtab->dependencies[i]->user != NULL)
- recursively_write_psymbols (objfile, psymtab->dependencies[i],
- symtab, psyms_seen, cu_index);
-
- write_psymbols (symtab,
- psyms_seen,
- &objfile->global_psymbols[psymtab->globals_offset],
- psymtab->n_global_syms, cu_index,
- 0);
- write_psymbols (symtab,
- psyms_seen,
- &objfile->static_psymbols[psymtab->statics_offset],
- psymtab->n_static_syms, cu_index,
- 1);
-}
-
-/* DWARF-5 .debug_names builder. */
-class debug_names
-{
-public:
- debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile, bool is_dwarf64,
- bfd_endian dwarf5_byte_order)
- : m_dwarf5_byte_order (dwarf5_byte_order),
- m_dwarf32 (dwarf5_byte_order),
- m_dwarf64 (dwarf5_byte_order),
- m_dwarf (is_dwarf64
- ? static_cast<dwarf &> (m_dwarf64)
- : static_cast<dwarf &> (m_dwarf32)),
- m_name_table_string_offs (m_dwarf.name_table_string_offs),
- m_name_table_entry_offs (m_dwarf.name_table_entry_offs),
- m_debugstrlookup (dwarf2_per_objfile)
- {}
-
- int dwarf5_offset_size () const
- {
- const bool dwarf5_is_dwarf64 = &m_dwarf == &m_dwarf64;
- return dwarf5_is_dwarf64 ? 8 : 4;
- }
-
- /* Is this symbol from DW_TAG_compile_unit or DW_TAG_type_unit? */
- enum class unit_kind { cu, tu };
-
- /* Insert one symbol. */
- void insert (const partial_symbol *psym, int cu_index, bool is_static,
- unit_kind kind)
- {
- const int dwarf_tag = psymbol_tag (psym);
- if (dwarf_tag == 0)
- return;
- const char *const name = SYMBOL_SEARCH_NAME (psym);
- const auto insertpair
- = m_name_to_value_set.emplace (c_str_view (name),
- std::set<symbol_value> ());
- std::set<symbol_value> &value_set = insertpair.first->second;
- value_set.emplace (symbol_value (dwarf_tag, cu_index, is_static, kind));
- }
-
- /* Build all the tables. All symbols must be already inserted.
- This function does not call file_write, caller has to do it
- afterwards. */
- void build ()
- {
- /* Verify the build method has not be called twice. */
- gdb_assert (m_abbrev_table.empty ());
- const size_t name_count = m_name_to_value_set.size ();
- m_bucket_table.resize
- (std::pow (2, std::ceil (std::log2 (name_count * 4 / 3))));
- m_hash_table.reserve (name_count);
- m_name_table_string_offs.reserve (name_count);
- m_name_table_entry_offs.reserve (name_count);
-
- /* Map each hash of symbol to its name and value. */
- struct hash_it_pair
- {
- uint32_t hash;
- decltype (m_name_to_value_set)::const_iterator it;
- };
- std::vector<std::forward_list<hash_it_pair>> bucket_hash;
- bucket_hash.resize (m_bucket_table.size ());
- for (decltype (m_name_to_value_set)::const_iterator it
- = m_name_to_value_set.cbegin ();
- it != m_name_to_value_set.cend ();
- ++it)
- {
- const char *const name = it->first.c_str ();
- const uint32_t hash = dwarf5_djb_hash (name);
- hash_it_pair hashitpair;
- hashitpair.hash = hash;
- hashitpair.it = it;
- auto &slot = bucket_hash[hash % bucket_hash.size()];
- slot.push_front (std::move (hashitpair));
- }
- for (size_t bucket_ix = 0; bucket_ix < bucket_hash.size (); ++bucket_ix)
- {
- const std::forward_list<hash_it_pair> &hashitlist
- = bucket_hash[bucket_ix];
- if (hashitlist.empty ())
- continue;
- uint32_t &bucket_slot = m_bucket_table[bucket_ix];
- /* The hashes array is indexed starting at 1. */
- store_unsigned_integer (reinterpret_cast<gdb_byte *> (&bucket_slot),
- sizeof (bucket_slot), m_dwarf5_byte_order,
- m_hash_table.size () + 1);
- for (const hash_it_pair &hashitpair : hashitlist)
- {
- m_hash_table.push_back (0);
- store_unsigned_integer (reinterpret_cast<gdb_byte *>
- (&m_hash_table.back ()),
- sizeof (m_hash_table.back ()),
- m_dwarf5_byte_order, hashitpair.hash);
- const c_str_view &name = hashitpair.it->first;
- const std::set<symbol_value> &value_set = hashitpair.it->second;
- m_name_table_string_offs.push_back_reorder
- (m_debugstrlookup.lookup (name.c_str ()));
- m_name_table_entry_offs.push_back_reorder (m_entry_pool.size ());
- gdb_assert (!value_set.empty ());
- for (const symbol_value &value : value_set)
- {
- int &idx = m_indexkey_to_idx[index_key (value.dwarf_tag,
- value.is_static,
- value.kind)];
- if (idx == 0)
- {
- idx = m_idx_next++;
- m_abbrev_table.append_unsigned_leb128 (idx);
- m_abbrev_table.append_unsigned_leb128 (value.dwarf_tag);
- m_abbrev_table.append_unsigned_leb128
- (value.kind == unit_kind::cu ? DW_IDX_compile_unit
- : DW_IDX_type_unit);
- m_abbrev_table.append_unsigned_leb128 (DW_FORM_udata);
- m_abbrev_table.append_unsigned_leb128 (value.is_static
- ? DW_IDX_GNU_internal
- : DW_IDX_GNU_external);
- m_abbrev_table.append_unsigned_leb128 (DW_FORM_flag_present);
-
- /* Terminate attributes list. */
- m_abbrev_table.append_unsigned_leb128 (0);
- m_abbrev_table.append_unsigned_leb128 (0);
- }
-
- m_entry_pool.append_unsigned_leb128 (idx);
- m_entry_pool.append_unsigned_leb128 (value.cu_index);
- }
-
- /* Terminate the list of CUs. */
- m_entry_pool.append_unsigned_leb128 (0);
- }
- }
- gdb_assert (m_hash_table.size () == name_count);
-
- /* Terminate tags list. */
- m_abbrev_table.append_unsigned_leb128 (0);
- }
-
- /* Return .debug_names bucket count. This must be called only after
- calling the build method. */
- uint32_t bucket_count () const
- {
- /* Verify the build method has been already called. */
- gdb_assert (!m_abbrev_table.empty ());
- const uint32_t retval = m_bucket_table.size ();
-
- /* Check for overflow. */
- gdb_assert (retval == m_bucket_table.size ());
- return retval;
- }
-
- /* Return .debug_names names count. This must be called only after
- calling the build method. */
- uint32_t name_count () const
- {
- /* Verify the build method has been already called. */
- gdb_assert (!m_abbrev_table.empty ());
- const uint32_t retval = m_hash_table.size ();
-
- /* Check for overflow. */
- gdb_assert (retval == m_hash_table.size ());
- return retval;
- }
-
- /* Return number of bytes of .debug_names abbreviation table. This
- must be called only after calling the build method. */
- uint32_t abbrev_table_bytes () const
- {
- gdb_assert (!m_abbrev_table.empty ());
- return m_abbrev_table.size ();
- }
-
- /* Recurse into all "included" dependencies and store their symbols
- as if they appeared in this psymtab. */
- void recursively_write_psymbols
- (struct objfile *objfile,
- struct partial_symtab *psymtab,
- std::unordered_set<partial_symbol *> &psyms_seen,
- int cu_index)
- {
- for (int i = 0; i < psymtab->number_of_dependencies; ++i)
- if (psymtab->dependencies[i]->user != NULL)
- recursively_write_psymbols (objfile, psymtab->dependencies[i],
- psyms_seen, cu_index);
-
- write_psymbols (psyms_seen,
- &objfile->global_psymbols[psymtab->globals_offset],
- psymtab->n_global_syms, cu_index, false, unit_kind::cu);
- write_psymbols (psyms_seen,
- &objfile->static_psymbols[psymtab->statics_offset],
- psymtab->n_static_syms, cu_index, true, unit_kind::cu);
- }
-
- /* Return number of bytes the .debug_names section will have. This
- must be called only after calling the build method. */
- size_t bytes () const
- {
- /* Verify the build method has been already called. */
- gdb_assert (!m_abbrev_table.empty ());
- size_t expected_bytes = 0;
- expected_bytes += m_bucket_table.size () * sizeof (m_bucket_table[0]);
- expected_bytes += m_hash_table.size () * sizeof (m_hash_table[0]);
- expected_bytes += m_name_table_string_offs.bytes ();
- expected_bytes += m_name_table_entry_offs.bytes ();
- expected_bytes += m_abbrev_table.size ();
- expected_bytes += m_entry_pool.size ();
- return expected_bytes;
- }
-
- /* Write .debug_names to FILE_NAMES and .debug_str addition to
- FILE_STR. This must be called only after calling the build
- method. */
- void file_write (FILE *file_names, FILE *file_str) const
- {
- /* Verify the build method has been already called. */
- gdb_assert (!m_abbrev_table.empty ());
- ::file_write (file_names, m_bucket_table);
- ::file_write (file_names, m_hash_table);
- m_name_table_string_offs.file_write (file_names);
- m_name_table_entry_offs.file_write (file_names);
- m_abbrev_table.file_write (file_names);
- m_entry_pool.file_write (file_names);
- m_debugstrlookup.file_write (file_str);
- }
-
- /* A helper user data for write_one_signatured_type. */
- class write_one_signatured_type_data
- {
- public:
- write_one_signatured_type_data (debug_names &nametable_,
- signatured_type_index_data &&info_)
- : nametable (nametable_), info (std::move (info_))
- {}
- debug_names &nametable;
- struct signatured_type_index_data info;
- };
-
- /* A helper function to pass write_one_signatured_type to
- htab_traverse_noresize. */
- static int
- write_one_signatured_type (void **slot, void *d)
- {
- write_one_signatured_type_data *data = (write_one_signatured_type_data *) d;
- struct signatured_type_index_data *info = &data->info;
- struct signatured_type *entry = (struct signatured_type *) *slot;
-
- data->nametable.write_one_signatured_type (entry, info);
-
- return 1;
- }
-
-private:
-
- /* Storage for symbol names mapping them to their .debug_str section
- offsets. */
- class debug_str_lookup
- {
- public:
-
- /* Object costructor to be called for current DWARF2_PER_OBJFILE.
- All .debug_str section strings are automatically stored. */
- debug_str_lookup (struct dwarf2_per_objfile *dwarf2_per_objfile)
- : m_abfd (dwarf2_per_objfile->objfile->obfd),
- m_dwarf2_per_objfile (dwarf2_per_objfile)
- {
- dwarf2_read_section (dwarf2_per_objfile->objfile,
- &dwarf2_per_objfile->str);
- if (dwarf2_per_objfile->str.buffer == NULL)
- return;
- for (const gdb_byte *data = dwarf2_per_objfile->str.buffer;
- data < (dwarf2_per_objfile->str.buffer
- + dwarf2_per_objfile->str.size);)
- {
- const char *const s = reinterpret_cast<const char *> (data);
- const auto insertpair
- = m_str_table.emplace (c_str_view (s),
- data - dwarf2_per_objfile->str.buffer);
- if (!insertpair.second)
- complaint (&symfile_complaints,
- _("Duplicate string \"%s\" in "
- ".debug_str section [in module %s]"),
- s, bfd_get_filename (m_abfd));
- data += strlen (s) + 1;
- }
- }
-
- /* Return offset of symbol name S in the .debug_str section. Add
- such symbol to the section's end if it does not exist there
- yet. */
- size_t lookup (const char *s)
- {
- const auto it = m_str_table.find (c_str_view (s));
- if (it != m_str_table.end ())
- return it->second;
- const size_t offset = (m_dwarf2_per_objfile->str.size
- + m_str_add_buf.size ());
- m_str_table.emplace (c_str_view (s), offset);
- m_str_add_buf.append_cstr0 (s);
- return offset;
- }
-
- /* Append the end of the .debug_str section to FILE. */
- void file_write (FILE *file) const
- {
- m_str_add_buf.file_write (file);
- }
-
- private:
- std::unordered_map<c_str_view, size_t, c_str_view_hasher> m_str_table;
- bfd *const m_abfd;
- struct dwarf2_per_objfile *m_dwarf2_per_objfile;
-
- /* Data to add at the end of .debug_str for new needed symbol names. */
- data_buf m_str_add_buf;
- };
-
- /* Container to map used DWARF tags to their .debug_names abbreviation
- tags. */
- class index_key
- {
- public:
- index_key (int dwarf_tag_, bool is_static_, unit_kind kind_)
- : dwarf_tag (dwarf_tag_), is_static (is_static_), kind (kind_)
- {
- }
-
- bool
- operator== (const index_key &other) const
- {
- return (dwarf_tag == other.dwarf_tag && is_static == other.is_static
- && kind == other.kind);
- }
-
- const int dwarf_tag;
- const bool is_static;
- const unit_kind kind;
- };
-
- /* Provide std::unordered_map::hasher for index_key. */
- class index_key_hasher
- {
- public:
- size_t
- operator () (const index_key &key) const
- {
- return (std::hash<int>() (key.dwarf_tag) << 1) | key.is_static;
- }
- };
-
- /* Parameters of one symbol entry. */
- class symbol_value
- {
- public:
- const int dwarf_tag, cu_index;
- const bool is_static;
- const unit_kind kind;
-
- symbol_value (int dwarf_tag_, int cu_index_, bool is_static_,
- unit_kind kind_)
- : dwarf_tag (dwarf_tag_), cu_index (cu_index_), is_static (is_static_),
- kind (kind_)
- {}
-
- bool
- operator< (const symbol_value &other) const
- {
-#define X(n) \
- do \
- { \
- if (n < other.n) \
- return true; \
- if (n > other.n) \
- return false; \
- } \
- while (0)
- X (dwarf_tag);
- X (is_static);
- X (kind);
- X (cu_index);
-#undef X
- return false;
- }
- };
-
- /* Abstract base class to unify DWARF-32 and DWARF-64 name table
- output. */
- class offset_vec
- {
- protected:
- const bfd_endian dwarf5_byte_order;
- public:
- explicit offset_vec (bfd_endian dwarf5_byte_order_)
- : dwarf5_byte_order (dwarf5_byte_order_)
- {}
-
- /* Call std::vector::reserve for NELEM elements. */
- virtual void reserve (size_t nelem) = 0;
-
- /* Call std::vector::push_back with store_unsigned_integer byte
- reordering for ELEM. */
- virtual void push_back_reorder (size_t elem) = 0;
-
- /* Return expected output size in bytes. */
- virtual size_t bytes () const = 0;
-
- /* Write name table to FILE. */
- virtual void file_write (FILE *file) const = 0;
- };
-
- /* Template to unify DWARF-32 and DWARF-64 output. */
- template<typename OffsetSize>
- class offset_vec_tmpl : public offset_vec
- {
- public:
- explicit offset_vec_tmpl (bfd_endian dwarf5_byte_order_)
- : offset_vec (dwarf5_byte_order_)
- {}
-
- /* Implement offset_vec::reserve. */
- void reserve (size_t nelem) override
- {
- m_vec.reserve (nelem);
- }
-
- /* Implement offset_vec::push_back_reorder. */
- void push_back_reorder (size_t elem) override
- {
- m_vec.push_back (elem);
- /* Check for overflow. */
- gdb_assert (m_vec.back () == elem);
- store_unsigned_integer (reinterpret_cast<gdb_byte *> (&m_vec.back ()),
- sizeof (m_vec.back ()), dwarf5_byte_order, elem);
- }
-
- /* Implement offset_vec::bytes. */
- size_t bytes () const override
- {
- return m_vec.size () * sizeof (m_vec[0]);
- }
-
- /* Implement offset_vec::file_write. */
- void file_write (FILE *file) const override
- {
- ::file_write (file, m_vec);
- }
-
- private:
- std::vector<OffsetSize> m_vec;
- };
-
- /* Base class to unify DWARF-32 and DWARF-64 .debug_names output
- respecting name table width. */
- class dwarf
- {
- public:
- offset_vec &name_table_string_offs, &name_table_entry_offs;
-
- dwarf (offset_vec &name_table_string_offs_,
- offset_vec &name_table_entry_offs_)
- : name_table_string_offs (name_table_string_offs_),
- name_table_entry_offs (name_table_entry_offs_)
- {
- }
- };
-
- /* Template to unify DWARF-32 and DWARF-64 .debug_names output
- respecting name table width. */
- template<typename OffsetSize>
- class dwarf_tmpl : public dwarf
- {
- public:
- explicit dwarf_tmpl (bfd_endian dwarf5_byte_order_)
- : dwarf (m_name_table_string_offs, m_name_table_entry_offs),
- m_name_table_string_offs (dwarf5_byte_order_),
- m_name_table_entry_offs (dwarf5_byte_order_)
- {}
-
- private:
- offset_vec_tmpl<OffsetSize> m_name_table_string_offs;
- offset_vec_tmpl<OffsetSize> m_name_table_entry_offs;
- };
-
- /* Try to reconstruct original DWARF tag for given partial_symbol.
- This function is not DWARF-5 compliant but it is sufficient for
- GDB as a DWARF-5 index consumer. */
- static int psymbol_tag (const struct partial_symbol *psym)
- {
- domain_enum domain = PSYMBOL_DOMAIN (psym);
- enum address_class aclass = PSYMBOL_CLASS (psym);
-
- switch (domain)
- {
- case VAR_DOMAIN:
- switch (aclass)
- {
- case LOC_BLOCK:
- return DW_TAG_subprogram;
- case LOC_TYPEDEF:
- return DW_TAG_typedef;
- case LOC_COMPUTED:
- case LOC_CONST_BYTES:
- case LOC_OPTIMIZED_OUT:
- case LOC_STATIC:
- return DW_TAG_variable;
- case LOC_CONST:
- /* Note: It's currently impossible to recognize psyms as enum values
- short of reading the type info. For now punt. */
- return DW_TAG_variable;
- default:
- /* There are other LOC_FOO values that one might want to classify
- as variables, but dwarf2read.c doesn't currently use them. */
- return DW_TAG_variable;
- }
- case STRUCT_DOMAIN:
- return DW_TAG_structure_type;
- default:
- return 0;
- }
- }
-
- /* Call insert for all partial symbols and mark them in PSYMS_SEEN. */
- void write_psymbols (std::unordered_set<partial_symbol *> &psyms_seen,
- struct partial_symbol **psymp, int count, int cu_index,
- bool is_static, unit_kind kind)
- {
- for (; count-- > 0; ++psymp)
- {
- struct partial_symbol *psym = *psymp;
-
- if (SYMBOL_LANGUAGE (psym) == language_ada)
- error (_("Ada is not currently supported by the index"));
-
- /* Only add a given psymbol once. */
- if (psyms_seen.insert (psym).second)
- insert (psym, cu_index, is_static, kind);
- }
- }
-
- /* A helper function that writes a single signatured_type
- to a debug_names. */
- void
- write_one_signatured_type (struct signatured_type *entry,
- struct signatured_type_index_data *info)
- {
- struct partial_symtab *psymtab = entry->per_cu.v.psymtab;
-
- write_psymbols (info->psyms_seen,
- &info->objfile->global_psymbols[psymtab->globals_offset],
- psymtab->n_global_syms, info->cu_index, false,
- unit_kind::tu);
- write_psymbols (info->psyms_seen,
- &info->objfile->static_psymbols[psymtab->statics_offset],
- psymtab->n_static_syms, info->cu_index, true,
- unit_kind::tu);
-
- info->types_list.append_uint (dwarf5_offset_size (), m_dwarf5_byte_order,
- to_underlying (entry->per_cu.sect_off));
-
- ++info->cu_index;
- }
-
- /* Store value of each symbol. */
- std::unordered_map<c_str_view, std::set<symbol_value>, c_str_view_hasher>
- m_name_to_value_set;
-
- /* Tables of DWARF-5 .debug_names. They are in object file byte
- order. */
- std::vector<uint32_t> m_bucket_table;
- std::vector<uint32_t> m_hash_table;
-
- const bfd_endian m_dwarf5_byte_order;
- dwarf_tmpl<uint32_t> m_dwarf32;
- dwarf_tmpl<uint64_t> m_dwarf64;
- dwarf &m_dwarf;
- offset_vec &m_name_table_string_offs, &m_name_table_entry_offs;
- debug_str_lookup m_debugstrlookup;
-
- /* Map each used .debug_names abbreviation tag parameter to its
- index value. */
- std::unordered_map<index_key, int, index_key_hasher> m_indexkey_to_idx;
-
- /* Next unused .debug_names abbreviation tag for
- m_indexkey_to_idx. */
- int m_idx_next = 1;
-
- /* .debug_names abbreviation table. */
- data_buf m_abbrev_table;
-
- /* .debug_names entry pool. */
- data_buf m_entry_pool;
-};
-
-/* Return iff any of the needed offsets does not fit into 32-bit
- .debug_names section. */
-
-static bool
-check_dwarf64_offsets (struct dwarf2_per_objfile *dwarf2_per_objfile)
-{
- for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
- {
- const dwarf2_per_cu_data &per_cu = *dwarf2_per_objfile->all_comp_units[i];
-
- if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
- return true;
- }
- for (int i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- const signatured_type &sigtype = *dwarf2_per_objfile->all_type_units[i];
- const dwarf2_per_cu_data &per_cu = sigtype.per_cu;
-
- if (to_underlying (per_cu.sect_off) >= (static_cast<uint64_t> (1) << 32))
- return true;
- }
- return false;
-}
-
-/* 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. */
-
-static size_t
-psyms_seen_size (struct dwarf2_per_objfile *dwarf2_per_objfile)
-{
- 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. */
- return psyms_count / 4;
-}
-
-/* Write new .gdb_index section for OBJFILE into OUT_FILE.
- Return how many bytes were expected to be written into OUT_FILE. */
-
-static size_t
-write_gdbindex (struct dwarf2_per_objfile *dwarf2_per_objfile, FILE *out_file)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- 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. */
- 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. */
-
- std::unordered_set<partial_symbol *> psyms_seen
- (psyms_seen_size (dwarf2_per_objfile));
- 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;
-
- /* CU of a shared file from 'dwz -m' may be unused by this main file.
- It may be referenced from a local scope but in such case it does not
- need to be present in .gdb_index. */
- if (psymtab == NULL)
- continue;
-
- if (psymtab->user == NULL)
- recursively_write_psymbols (objfile, psymtab, &symtab,
- psyms_seen, i);
-
- const auto insertpair = cu_index_htab.emplace (psymtab, i);
- gdb_assert (insertpair.second);
-
- 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. */
- 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)
- {
- signatured_type_index_data sig_data (types_cu_list,
- psyms_seen);
-
- sig_data.objfile = objfile;
- 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);
- }
-
- /* Now that we've processed all symbols we can shrink their cu_indices
- lists. */
- uniquify_cu_indices (&symtab);
-
- data_buf symtab_vec, constant_pool;
- write_hash_table (&symtab, symtab_vec, constant_pool);
-
- data_buf contents;
- const offset_type size_of_contents = 6 * sizeof (offset_type);
- offset_type total_len = size_of_contents;
-
- /* The version number. */
- contents.append_data (MAYBE_SWAP (8));
-
- /* The offset of the CU list from the start of the file. */
- 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. */
- 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. */
- contents.append_data (MAYBE_SWAP (total_len));
- total_len += addr_vec.size ();
-
- /* The offset of the symbol table from the start of the file. */
- contents.append_data (MAYBE_SWAP (total_len));
- total_len += symtab_vec.size ();
-
- /* The offset of the constant pool from the start of the file. */
- contents.append_data (MAYBE_SWAP (total_len));
- total_len += constant_pool.size ();
-
- gdb_assert (contents.size () == size_of_contents);
-
- 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);
-
- return total_len;
-}
-
-/* DWARF-5 augmentation string for GDB's DW_IDX_GNU_* extension. */
-static const gdb_byte dwarf5_gdb_augmentation[] = { 'G', 'D', 'B', 0 };
-
-/* Write a new .debug_names section for OBJFILE into OUT_FILE, write
- needed addition to .debug_str section to OUT_FILE_STR. Return how
- many bytes were expected to be written into OUT_FILE. */
-
-static size_t
-write_debug_names (struct dwarf2_per_objfile *dwarf2_per_objfile,
- FILE *out_file, FILE *out_file_str)
-{
- const bool dwarf5_is_dwarf64 = check_dwarf64_offsets (dwarf2_per_objfile);
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- const enum bfd_endian dwarf5_byte_order
- = gdbarch_byte_order (get_objfile_arch (objfile));
-
- /* 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. */
- data_buf cu_list;
- debug_names nametable (dwarf2_per_objfile, dwarf5_is_dwarf64,
- dwarf5_byte_order);
- std::unordered_set<partial_symbol *>
- psyms_seen (psyms_seen_size (dwarf2_per_objfile));
- for (int i = 0; i < dwarf2_per_objfile->n_comp_units; ++i)
- {
- const dwarf2_per_cu_data *per_cu = dwarf2_per_objfile->all_comp_units[i];
- partial_symtab *psymtab = per_cu->v.psymtab;
-
- /* CU of a shared file from 'dwz -m' may be unused by this main
- file. It may be referenced from a local scope but in such
- case it does not need to be present in .debug_names. */
- if (psymtab == NULL)
- continue;
-
- if (psymtab->user == NULL)
- nametable.recursively_write_psymbols (objfile, psymtab, psyms_seen, i);
-
- cu_list.append_uint (nametable.dwarf5_offset_size (), dwarf5_byte_order,
- to_underlying (per_cu->sect_off));
- }
-
- /* Write out the .debug_type entries, if any. */
- data_buf types_cu_list;
- if (dwarf2_per_objfile->signatured_types)
- {
- debug_names::write_one_signatured_type_data sig_data (nametable,
- signatured_type_index_data (types_cu_list, psyms_seen));
-
- sig_data.info.objfile = objfile;
- /* It is used only for gdb_index. */
- sig_data.info.symtab = nullptr;
- sig_data.info.cu_index = 0;
- htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
- debug_names::write_one_signatured_type,
- &sig_data);
- }
-
- nametable.build ();
-
- /* No addr_vec - DWARF-5 uses .debug_aranges generated by GCC. */
-
- const offset_type bytes_of_header
- = ((dwarf5_is_dwarf64 ? 12 : 4)
- + 2 + 2 + 7 * 4
- + sizeof (dwarf5_gdb_augmentation));
- size_t expected_bytes = 0;
- expected_bytes += bytes_of_header;
- expected_bytes += cu_list.size ();
- expected_bytes += types_cu_list.size ();
- expected_bytes += nametable.bytes ();
- data_buf header;
-
- if (!dwarf5_is_dwarf64)
- {
- const uint64_t size64 = expected_bytes - 4;
- gdb_assert (size64 < 0xfffffff0);
- header.append_uint (4, dwarf5_byte_order, size64);
- }
- else
- {
- header.append_uint (4, dwarf5_byte_order, 0xffffffff);
- header.append_uint (8, dwarf5_byte_order, expected_bytes - 12);
- }
-
- /* The version number. */
- header.append_uint (2, dwarf5_byte_order, 5);
-
- /* Padding. */
- header.append_uint (2, dwarf5_byte_order, 0);
-
- /* comp_unit_count - The number of CUs in the CU list. */
- header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_comp_units);
-
- /* local_type_unit_count - The number of TUs in the local TU
- list. */
- header.append_uint (4, dwarf5_byte_order, dwarf2_per_objfile->n_type_units);
-
- /* foreign_type_unit_count - The number of TUs in the foreign TU
- list. */
- header.append_uint (4, dwarf5_byte_order, 0);
-
- /* bucket_count - The number of hash buckets in the hash lookup
- table. */
- header.append_uint (4, dwarf5_byte_order, nametable.bucket_count ());
-
- /* name_count - The number of unique names in the index. */
- header.append_uint (4, dwarf5_byte_order, nametable.name_count ());
-
- /* abbrev_table_size - The size in bytes of the abbreviations
- table. */
- header.append_uint (4, dwarf5_byte_order, nametable.abbrev_table_bytes ());
-
- /* augmentation_string_size - The size in bytes of the augmentation
- string. This value is rounded up to a multiple of 4. */
- static_assert (sizeof (dwarf5_gdb_augmentation) % 4 == 0, "");
- header.append_uint (4, dwarf5_byte_order, sizeof (dwarf5_gdb_augmentation));
- header.append_data (dwarf5_gdb_augmentation);
-
- gdb_assert (header.size () == bytes_of_header);
-
- header.file_write (out_file);
- cu_list.file_write (out_file);
- types_cu_list.file_write (out_file);
- nametable.file_write (out_file, out_file_str);
-
- return expected_bytes;
-}
-
-/* Assert that FILE's size is EXPECTED_SIZE. Assumes file's seek
- position is at the end of the file. */
-
-static void
-assert_file_size (FILE *file, const char *filename, size_t expected_size)
-{
- const auto file_size = ftell (file);
- if (file_size == -1)
- error (_("Can't get `%s' size"), filename);
- gdb_assert (file_size == expected_size);
-}
-
-/* Create an index file for OBJFILE in the directory DIR. */
-
-static void
-write_psymtabs_to_index (struct dwarf2_per_objfile *dwarf2_per_objfile,
- const char *dir,
- dw_index_kind index_kind)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
-
- if (dwarf2_per_objfile->using_index)
- error (_("Cannot use an index to create the index"));
-
- if (VEC_length (dwarf2_section_info_def, dwarf2_per_objfile->types) > 1)
- error (_("Cannot make an index when the file has multiple .debug_types sections"));
-
- if (!objfile->psymtabs || !objfile->psymtabs_addrmap)
- return;
-
- struct stat st;
- if (stat (objfile_name (objfile), &st) < 0)
- perror_with_name (objfile_name (objfile));
-
- std::string filename (std::string (dir) + SLASH_STRING
- + lbasename (objfile_name (objfile))
- + (index_kind == dw_index_kind::DEBUG_NAMES
- ? INDEX5_SUFFIX : INDEX4_SUFFIX));
-
- FILE *out_file = gdb_fopen_cloexec (filename.c_str (), "wb").release ();
- if (!out_file)
- error (_("Can't open `%s' for writing"), filename.c_str ());
-
- /* 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);
-
- if (index_kind == dw_index_kind::DEBUG_NAMES)
- {
- std::string filename_str (std::string (dir) + SLASH_STRING
- + lbasename (objfile_name (objfile))
- + DEBUG_STR_SUFFIX);
- FILE *out_file_str
- = gdb_fopen_cloexec (filename_str.c_str (), "wb").release ();
- if (!out_file_str)
- error (_("Can't open `%s' for writing"), filename_str.c_str ());
- gdb::unlinker unlink_file_str (filename_str.c_str ());
- gdb_file_up close_out_file_str (out_file_str);
-
- const size_t total_len
- = write_debug_names (dwarf2_per_objfile, out_file, out_file_str);
- assert_file_size (out_file, filename.c_str (), total_len);
-
- /* We want to keep the file .debug_str file too. */
- unlink_file_str.keep ();
- }
- else
- {
- const size_t total_len
- = write_gdbindex (dwarf2_per_objfile, out_file);
- assert_file_size (out_file, filename.c_str (), total_len);
- }
-
- /* We want to keep the file. */
- unlink_file.keep ();
-}
-
-/* Implementation of the `save gdb-index' command.
-
- Note that the .gdb_index file format used by this command is
- documented in the GDB manual. Any changes here must be documented
- there. */
-
-static void
-save_gdb_index_command (const char *arg, int from_tty)
-{
- struct objfile *objfile;
- const char dwarf5space[] = "-dwarf-5 ";
- dw_index_kind index_kind = dw_index_kind::GDB_INDEX;
-
- if (!arg)
- arg = "";
-
- arg = skip_spaces (arg);
- if (strncmp (arg, dwarf5space, strlen (dwarf5space)) == 0)
- {
- index_kind = dw_index_kind::DEBUG_NAMES;
- arg += strlen (dwarf5space);
- arg = skip_spaces (arg);
- }
-
- if (!*arg)
- error (_("usage: save gdb-index [-dwarf-5] DIRECTORY"));
-
- ALL_OBJFILES (objfile)
- {
- struct stat st;
-
- /* If the objfile does not correspond to an actual file, skip it. */
- if (stat (objfile_name (objfile), &st) < 0)
- continue;
-
- struct dwarf2_per_objfile *dwarf2_per_objfile
- = get_dwarf2_per_objfile (objfile);
-
- if (dwarf2_per_objfile != NULL)
- {
- TRY
- {
- write_psymtabs_to_index (dwarf2_per_objfile, arg, index_kind);
- }
- CATCH (except, RETURN_MASK_ERROR)
- {
- exception_fprintf (gdb_stderr, except,
- _("Error while writing index for `%s': "),
- objfile_name (objfile));
- }
- END_CATCH
- }
-
- }
-}
-
-\f
-
-int dwarf_always_disassemble;
-
-static void
-show_dwarf_always_disassemble (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
-{
- fprintf_filtered (file,
- _("Whether to always disassemble "
- "DWARF expressions is %s.\n"),
- value);
-}
-
-static void
-show_check_physname (struct ui_file *file, int from_tty,
- struct cmd_list_element *c, const char *value)
-{
- fprintf_filtered (file,
- _("Whether to check \"physname\" is %s.\n"),
- value);
-}
-
-void
-_initialize_dwarf2_read (void)
-{
- struct cmd_list_element *c;
-
- dwarf2_objfile_data_key
- = register_objfile_data_with_cleanup (NULL, dwarf2_per_objfile_free);
-
- add_prefix_cmd ("dwarf", class_maintenance, set_dwarf_cmd, _("\
-Set DWARF specific variables.\n\
-Configure DWARF variables such as the cache size"),
- &set_dwarf_cmdlist, "maintenance set dwarf ",
- 0/*allow-unknown*/, &maintenance_set_cmdlist);
-
- add_prefix_cmd ("dwarf", class_maintenance, show_dwarf_cmd, _("\
-Show DWARF specific variables\n\
-Show DWARF variables such as the cache size"),
- &show_dwarf_cmdlist, "maintenance show dwarf ",
- 0/*allow-unknown*/, &maintenance_show_cmdlist);
-
- add_setshow_zinteger_cmd ("max-cache-age", class_obscure,
- &dwarf_max_cache_age, _("\
-Set the upper bound on the age of cached DWARF compilation units."), _("\
-Show the upper bound on the age of cached DWARF compilation units."), _("\
-A higher limit means that cached compilation units will be stored\n\
-in memory longer, and more total memory will be used. Zero disables\n\
-caching, which can slow down startup."),
- NULL,
- show_dwarf_max_cache_age,
- &set_dwarf_cmdlist,
- &show_dwarf_cmdlist);
-
- add_setshow_boolean_cmd ("always-disassemble", class_obscure,
- &dwarf_always_disassemble, _("\
-Set whether `info address' always disassembles DWARF expressions."), _("\
-Show whether `info address' always disassembles DWARF expressions."), _("\
-When enabled, DWARF expressions are always printed in an assembly-like\n\
-syntax. When disabled, expressions will be printed in a more\n\
-conversational style, when possible."),
- NULL,
- show_dwarf_always_disassemble,
- &set_dwarf_cmdlist,
- &show_dwarf_cmdlist);
-
- add_setshow_zuinteger_cmd ("dwarf-read", no_class, &dwarf_read_debug, _("\
-Set debugging of the DWARF reader."), _("\
-Show debugging of the DWARF reader."), _("\
-When enabled (non-zero), debugging messages are printed during DWARF\n\
-reading and symtab expansion. A value of 1 (one) provides basic\n\
-information. A value greater than 1 provides more verbose information."),
- NULL,
- NULL,
- &setdebuglist, &showdebuglist);
-
- add_setshow_zuinteger_cmd ("dwarf-die", no_class, &dwarf_die_debug, _("\
-Set debugging of the DWARF DIE reader."), _("\
-Show debugging of the DWARF DIE reader."), _("\
-When enabled (non-zero), DIEs are dumped after they are read in.\n\
-The value is the maximum depth to print."),
- NULL,
- NULL,
- &setdebuglist, &showdebuglist);
+ add_setshow_zuinteger_cmd ("dwarf-die", no_class, &dwarf_die_debug, _("\
+Set debugging of the DWARF DIE reader."), _("\
+Show debugging of the DWARF DIE reader."), _("\
+When enabled (non-zero), DIEs are dumped after they are read in.\n\
+The value is the maximum depth to print."),
+ NULL,
+ NULL,
+ &setdebuglist, &showdebuglist);
add_setshow_zuinteger_cmd ("dwarf-line", no_class, &dwarf_line_debug, _("\
Set debugging of the dwarf line reader."), _("\
NULL,
&setlist, &showlist);
- c = add_cmd ("gdb-index", class_files, save_gdb_index_command,
- _("\
-Save a gdb-index file.\n\
-Usage: save gdb-index [-dwarf-5] DIRECTORY\n\
-\n\
-No options create one file with .gdb-index extension for pre-DWARF-5\n\
-compatible .gdb_index section. With -dwarf-5 creates two files with\n\
-extension .debug_names and .debug_str for DWARF-5 .debug_names section."),
- &save_cmdlist);
- set_cmd_completer (c, filename_completer);
-
dwarf2_locexpr_index = register_symbol_computed_impl (LOC_COMPUTED,
&dwarf2_locexpr_funcs);
dwarf2_loclist_index = register_symbol_computed_impl (LOC_COMPUTED,