diff options
author | Tom Tromey <tom@tromey.com> | 2021-05-17 14:16:06 -0600 |
---|---|---|
committer | Tom Tromey <tom@tromey.com> | 2021-05-17 14:16:06 -0600 |
commit | 8ae78a440e4e2ea7ecda9b33a6b3ec63bbcd3c65 (patch) | |
tree | a3e6f97b5ac11a1aef94a6177d67338e9a9bc945 | |
parent | c1c0a7e1f39fda9f95bb94ecc5f39b189d69a76c (diff) | |
download | gdb-8ae78a440e4e2ea7ecda9b33a6b3ec63bbcd3c65.zip gdb-8ae78a440e4e2ea7ecda9b33a6b3ec63bbcd3c65.tar.gz gdb-8ae78a440e4e2ea7ecda9b33a6b3ec63bbcd3c65.tar.bz2 |
Move dwarf2_cu to new header file
This moves dwarf2_cu and one supporting data structure to a new header
file. The main goal, as always with this kind of change, is to make
the DWARF reader a bit more understandable.
gdb/ChangeLog
2021-05-17 Tom Tromey <tom@tromey.com>
* Makefile.in (HFILES_NO_SRCDIR): Add dwarf2/cu.h.
* dwarf2/read.c (struct delayed_method_info, struct dwarf2_cu):
Move to cu.h.
* dwarf2/cu.h: New file.
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/Makefile.in | 1 | ||||
-rw-r--r-- | gdb/dwarf2/cu.h | 270 | ||||
-rw-r--r-- | gdb/dwarf2/read.c | 245 |
4 files changed, 279 insertions, 244 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7759707..3f44f21 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2021-05-17 Tom Tromey <tom@tromey.com> + + * Makefile.in (HFILES_NO_SRCDIR): Add dwarf2/cu.h. + * dwarf2/read.c (struct delayed_method_info, struct dwarf2_cu): + Move to cu.h. + * dwarf2/cu.h: New file. + 2021-05-17 Andrew Burgess <andrew.burgess@embecosm.com> * .dir-locals.el: Set sentence-end-double-space for all modes, and diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ba0cabb..4737cc9 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1272,6 +1272,7 @@ HFILES_NO_SRCDIR = \ dictionary.h \ disasm.h \ dummy-frame.h \ + dwarf2/cu.h \ dwarf2/frame-tailcall.h \ dwarf2/frame.h \ dwarf2/expr.h \ diff --git a/gdb/dwarf2/cu.h b/gdb/dwarf2/cu.h new file mode 100644 index 0000000..9fb2d61 --- /dev/null +++ b/gdb/dwarf2/cu.h @@ -0,0 +1,270 @@ +/* DWARF CU data structure + + Copyright (C) 2021 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef GDB_DWARF2_CU_H +#define GDB_DWARF2_CU_H + +#include "buildsym.h" +#include "dwarf2/comp-unit.h" +#include "gdbsupport/gdb_optional.h" + +/* Type used for delaying computation of method physnames. + See comments for compute_delayed_physnames. */ +struct delayed_method_info +{ + /* The type to which the method is attached, i.e., its parent class. */ + struct type *type; + + /* The index of the method in the type's function fieldlists. */ + int fnfield_index; + + /* The index of the method in the fieldlist. */ + int index; + + /* The name of the DIE. */ + const char *name; + + /* The DIE associated with this method. */ + struct die_info *die; +}; + +/* Internal state when decoding a particular compilation unit. */ +struct dwarf2_cu +{ + explicit dwarf2_cu (dwarf2_per_cu_data *per_cu, + dwarf2_per_objfile *per_objfile); + + DISABLE_COPY_AND_ASSIGN (dwarf2_cu); + + /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope. + Create the set of symtabs used by this TU, or if this TU is sharing + symtabs with another TU and the symtabs have already been created + then restore those symtabs in the line header. + We don't need the pc/line-number mapping for type units. */ + void setup_type_unit_groups (struct die_info *die); + + /* Start a symtab for DWARF. NAME, COMP_DIR, LOW_PC are passed to the + buildsym_compunit constructor. */ + struct compunit_symtab *start_symtab (const char *name, + const char *comp_dir, + CORE_ADDR low_pc); + + /* Reset the builder. */ + void reset_builder () { m_builder.reset (); } + + /* Return a type that is a generic pointer type, the size of which + matches the address size given in the compilation unit header for + this CU. */ + struct type *addr_type () const; + + /* Find an integer type the same size as the address size given in + the compilation unit header for this CU. UNSIGNED_P controls if + the integer is unsigned or not. */ + struct type *addr_sized_int_type (bool unsigned_p) const; + + /* The header of the compilation unit. */ + struct comp_unit_head header {}; + + /* Base address of this compilation unit. */ + gdb::optional<CORE_ADDR> base_address; + + /* The language we are debugging. */ + enum language language = language_unknown; + const struct language_defn *language_defn = nullptr; + + const char *producer = nullptr; + +private: + /* The symtab builder for this CU. This is only non-NULL when full + symbols are being read. */ + std::unique_ptr<buildsym_compunit> m_builder; + +public: + /* The generic symbol table building routines have separate lists for + file scope symbols and all all other scopes (local scopes). So + we need to select the right one to pass to add_symbol_to_list(). + We do it by keeping a pointer to the correct list in list_in_scope. + + FIXME: The original dwarf code just treated the file scope as the + first local scope, and all other local scopes as nested local + scopes, and worked fine. Check to see if we really need to + distinguish these in buildsym.c. */ + struct pending **list_in_scope = nullptr; + + /* Hash table holding all the loaded partial DIEs + with partial_die->offset.SECT_OFF as hash. */ + htab_t partial_dies = nullptr; + + /* Storage for things with the same lifetime as this read-in compilation + unit, including partial DIEs. */ + auto_obstack comp_unit_obstack; + + /* Backlink to our per_cu entry. */ + struct dwarf2_per_cu_data *per_cu; + + /* The dwarf2_per_objfile that owns this. */ + dwarf2_per_objfile *per_objfile; + + /* How many compilation units ago was this CU last referenced? */ + int last_used = 0; + + /* A hash table of DIE cu_offset for following references with + die_info->offset.sect_off as hash. */ + htab_t die_hash = nullptr; + + /* Full DIEs if read in. */ + struct die_info *dies = nullptr; + + /* A set of pointers to dwarf2_per_cu_data objects for compilation + units referenced by this one. Only set during full symbol processing; + partial symbol tables do not have dependencies. */ + htab_t dependencies = nullptr; + + /* Header data from the line table, during full symbol processing. */ + struct line_header *line_header = nullptr; + /* Non-NULL if LINE_HEADER is owned by this DWARF_CU. Otherwise, + it's owned by dwarf2_per_bfd::line_header_hash. If non-NULL, + this is the DW_TAG_compile_unit die for this CU. We'll hold on + to the line header as long as this DIE is being processed. See + process_die_scope. */ + die_info *line_header_die_owner = nullptr; + + /* A list of methods which need to have physnames computed + after all type information has been read. */ + std::vector<delayed_method_info> method_list; + + /* To be copied to symtab->call_site_htab. */ + htab_t call_site_htab = nullptr; + + /* Non-NULL if this CU came from a DWO file. + There is an invariant here that is important to remember: + Except for attributes copied from the top level DIE in the "main" + (or "stub") file in preparation for reading the DWO file + (e.g., DW_AT_addr_base), we KISS: there is only *one* CU. + Either there isn't a DWO file (in which case this is NULL and the point + is moot), or there is and either we're not going to read it (in which + case this is NULL) or there is and we are reading it (in which case this + is non-NULL). */ + struct dwo_unit *dwo_unit = nullptr; + + /* The DW_AT_addr_base (DW_AT_GNU_addr_base) attribute if present. + Note this value comes from the Fission stub CU/TU's DIE. */ + gdb::optional<ULONGEST> addr_base; + + /* The DW_AT_GNU_ranges_base attribute, if present. + + This is only relevant in the context of pre-DWARF 5 split units. In this + context, there is a .debug_ranges section in the linked executable, + containing all the ranges data for all the compilation units. Each + skeleton/stub unit has (if needed) a DW_AT_GNU_ranges_base attribute that + indicates the base of its contribution to that section. The DW_AT_ranges + attributes in the split-unit are of the form DW_FORM_sec_offset and point + into the .debug_ranges section of the linked file. However, they are not + "true" DW_FORM_sec_offset, because they are relative to the base of their + compilation unit's contribution, rather than relative to the beginning of + the section. The DW_AT_GNU_ranges_base value must be added to it to make + it relative to the beginning of the section. + + Note that the value is zero when we are not in a pre-DWARF 5 split-unit + case, so this value can be added without needing to know whether we are in + this case or not. + + N.B. If a DW_AT_ranges attribute is found on the DW_TAG_compile_unit in the + skeleton/stub, it must not have the base added, as it already points to the + right place. And since the DW_TAG_compile_unit DIE in the split-unit can't + have a DW_AT_ranges attribute, we can use the + + die->tag != DW_AT_compile_unit + + to determine whether the base should be added or not. */ + ULONGEST gnu_ranges_base = 0; + + /* The DW_AT_rnglists_base attribute, if present. + + This is used when processing attributes of form DW_FORM_rnglistx in + non-split units. Attributes of this form found in a split unit don't + use it, as split-unit files have their own non-shared .debug_rnglists.dwo + section. */ + ULONGEST rnglists_base = 0; + + /* The DW_AT_loclists_base attribute if present. */ + ULONGEST loclist_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; + + /* The DW_AT_str_offsets_base attribute if present. For DWARF 4 version DWO + files, the value is implicitly zero. For DWARF 5 version DWO files, the + value is often implicit and is the size of the header of + .debug_str_offsets section (8 or 4, depending on the address size). */ + gdb::optional<ULONGEST> str_offsets_base; + + /* Mark used when releasing cached dies. */ + bool mark : 1; + + /* This CU references .debug_loc. See the symtab->locations_valid field. + This test is imperfect as there may exist optimized debug code not using + any location list and still facing inlining issues if handled as + unoptimized code. For a future better test see GCC PR other/32998. */ + bool has_loclist : 1; + + /* These cache the results for producer_is_* fields. CHECKED_PRODUCER is true + if all the producer_is_* fields are valid. This information is cached + because profiling CU expansion showed excessive time spent in + producer_is_gxx_lt_4_6. */ + bool checked_producer : 1; + bool producer_is_gxx_lt_4_6 : 1; + bool producer_is_gcc_lt_4_3 : 1; + bool producer_is_icc : 1; + bool producer_is_icc_lt_14 : 1; + bool producer_is_codewarrior : 1; + + /* When true, the file that we're processing is known to have + debugging info for C++ namespaces. GCC 3.3.x did not produce + this information, but later versions do. */ + + bool processing_has_namespace_info : 1; + + struct partial_die_info *find_partial_die (sect_offset sect_off); + + /* If this CU was inherited by another CU (via specification, + abstract_origin, etc), this is the ancestor CU. */ + dwarf2_cu *ancestor; + + /* Get the buildsym_compunit for this CU. */ + buildsym_compunit *get_builder () + { + /* If this CU has a builder associated with it, use that. */ + if (m_builder != nullptr) + return m_builder.get (); + + /* Otherwise, search ancestors for a valid builder. */ + if (ancestor != nullptr) + return ancestor->get_builder (); + + return nullptr; + } +}; + +#endif /* GDB_DWARF2_CU_H */ diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index b3b8f1b..d0c6bc3 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -33,6 +33,7 @@ #include "dwarf2/abbrev.h" #include "dwarf2/attribute.h" #include "dwarf2/comp-unit.h" +#include "dwarf2/cu.h" #include "dwarf2/index-cache.h" #include "dwarf2/index-common.h" #include "dwarf2/leb.h" @@ -49,7 +50,6 @@ #include "gdbtypes.h" #include "objfiles.h" #include "dwarf2.h" -#include "buildsym.h" #include "demangle.h" #include "gdb-demangle.h" #include "filenames.h" /* for DOSish file names */ @@ -460,249 +460,6 @@ struct loclists_rnglists_header unsigned int offset_entry_count; }; -/* Type used for delaying computation of method physnames. - See comments for compute_delayed_physnames. */ -struct delayed_method_info -{ - /* The type to which the method is attached, i.e., its parent class. */ - struct type *type; - - /* The index of the method in the type's function fieldlists. */ - int fnfield_index; - - /* The index of the method in the fieldlist. */ - int index; - - /* The name of the DIE. */ - const char *name; - - /* The DIE associated with this method. */ - struct die_info *die; -}; - -/* Internal state when decoding a particular compilation unit. */ -struct dwarf2_cu -{ - explicit dwarf2_cu (dwarf2_per_cu_data *per_cu, - dwarf2_per_objfile *per_objfile); - - DISABLE_COPY_AND_ASSIGN (dwarf2_cu); - - /* TU version of handle_DW_AT_stmt_list for read_type_unit_scope. - Create the set of symtabs used by this TU, or if this TU is sharing - symtabs with another TU and the symtabs have already been created - then restore those symtabs in the line header. - We don't need the pc/line-number mapping for type units. */ - void setup_type_unit_groups (struct die_info *die); - - /* Start a symtab for DWARF. NAME, COMP_DIR, LOW_PC are passed to the - buildsym_compunit constructor. */ - struct compunit_symtab *start_symtab (const char *name, - const char *comp_dir, - CORE_ADDR low_pc); - - /* Reset the builder. */ - void reset_builder () { m_builder.reset (); } - - /* Return a type that is a generic pointer type, the size of which - matches the address size given in the compilation unit header for - this CU. */ - struct type *addr_type () const; - - /* Find an integer type the same size as the address size given in - the compilation unit header for this CU. UNSIGNED_P controls if - the integer is unsigned or not. */ - struct type *addr_sized_int_type (bool unsigned_p) const; - - /* The header of the compilation unit. */ - struct comp_unit_head header {}; - - /* Base address of this compilation unit. */ - gdb::optional<CORE_ADDR> base_address; - - /* The language we are debugging. */ - enum language language = language_unknown; - const struct language_defn *language_defn = nullptr; - - const char *producer = nullptr; - -private: - /* The symtab builder for this CU. This is only non-NULL when full - symbols are being read. */ - std::unique_ptr<buildsym_compunit> m_builder; - -public: - /* The generic symbol table building routines have separate lists for - file scope symbols and all all other scopes (local scopes). So - we need to select the right one to pass to add_symbol_to_list(). - We do it by keeping a pointer to the correct list in list_in_scope. - - FIXME: The original dwarf code just treated the file scope as the - first local scope, and all other local scopes as nested local - scopes, and worked fine. Check to see if we really need to - distinguish these in buildsym.c. */ - struct pending **list_in_scope = nullptr; - - /* Hash table holding all the loaded partial DIEs - with partial_die->offset.SECT_OFF as hash. */ - htab_t partial_dies = nullptr; - - /* Storage for things with the same lifetime as this read-in compilation - unit, including partial DIEs. */ - auto_obstack comp_unit_obstack; - - /* Backlink to our per_cu entry. */ - struct dwarf2_per_cu_data *per_cu; - - /* The dwarf2_per_objfile that owns this. */ - dwarf2_per_objfile *per_objfile; - - /* How many compilation units ago was this CU last referenced? */ - int last_used = 0; - - /* A hash table of DIE cu_offset for following references with - die_info->offset.sect_off as hash. */ - htab_t die_hash = nullptr; - - /* Full DIEs if read in. */ - struct die_info *dies = nullptr; - - /* A set of pointers to dwarf2_per_cu_data objects for compilation - units referenced by this one. Only set during full symbol processing; - partial symbol tables do not have dependencies. */ - htab_t dependencies = nullptr; - - /* Header data from the line table, during full symbol processing. */ - struct line_header *line_header = nullptr; - /* Non-NULL if LINE_HEADER is owned by this DWARF_CU. Otherwise, - it's owned by dwarf2_per_bfd::line_header_hash. If non-NULL, - this is the DW_TAG_compile_unit die for this CU. We'll hold on - to the line header as long as this DIE is being processed. See - process_die_scope. */ - die_info *line_header_die_owner = nullptr; - - /* A list of methods which need to have physnames computed - after all type information has been read. */ - std::vector<delayed_method_info> method_list; - - /* To be copied to symtab->call_site_htab. */ - htab_t call_site_htab = nullptr; - - /* Non-NULL if this CU came from a DWO file. - There is an invariant here that is important to remember: - Except for attributes copied from the top level DIE in the "main" - (or "stub") file in preparation for reading the DWO file - (e.g., DW_AT_addr_base), we KISS: there is only *one* CU. - Either there isn't a DWO file (in which case this is NULL and the point - is moot), or there is and either we're not going to read it (in which - case this is NULL) or there is and we are reading it (in which case this - is non-NULL). */ - struct dwo_unit *dwo_unit = nullptr; - - /* The DW_AT_addr_base (DW_AT_GNU_addr_base) attribute if present. - Note this value comes from the Fission stub CU/TU's DIE. */ - gdb::optional<ULONGEST> addr_base; - - /* The DW_AT_GNU_ranges_base attribute, if present. - - This is only relevant in the context of pre-DWARF 5 split units. In this - context, there is a .debug_ranges section in the linked executable, - containing all the ranges data for all the compilation units. Each - skeleton/stub unit has (if needed) a DW_AT_GNU_ranges_base attribute that - indicates the base of its contribution to that section. The DW_AT_ranges - attributes in the split-unit are of the form DW_FORM_sec_offset and point - into the .debug_ranges section of the linked file. However, they are not - "true" DW_FORM_sec_offset, because they are relative to the base of their - compilation unit's contribution, rather than relative to the beginning of - the section. The DW_AT_GNU_ranges_base value must be added to it to make - it relative to the beginning of the section. - - Note that the value is zero when we are not in a pre-DWARF 5 split-unit - case, so this value can be added without needing to know whether we are in - this case or not. - - N.B. If a DW_AT_ranges attribute is found on the DW_TAG_compile_unit in the - skeleton/stub, it must not have the base added, as it already points to the - right place. And since the DW_TAG_compile_unit DIE in the split-unit can't - have a DW_AT_ranges attribute, we can use the - - die->tag != DW_AT_compile_unit - - to determine whether the base should be added or not. */ - ULONGEST gnu_ranges_base = 0; - - /* The DW_AT_rnglists_base attribute, if present. - - This is used when processing attributes of form DW_FORM_rnglistx in - non-split units. Attributes of this form found in a split unit don't - use it, as split-unit files have their own non-shared .debug_rnglists.dwo - section. */ - ULONGEST rnglists_base = 0; - - /* The DW_AT_loclists_base attribute if present. */ - ULONGEST loclist_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; - - /* The DW_AT_str_offsets_base attribute if present. For DWARF 4 version DWO - files, the value is implicitly zero. For DWARF 5 version DWO files, the - value is often implicit and is the size of the header of - .debug_str_offsets section (8 or 4, depending on the address size). */ - gdb::optional<ULONGEST> str_offsets_base; - - /* Mark used when releasing cached dies. */ - bool mark : 1; - - /* This CU references .debug_loc. See the symtab->locations_valid field. - This test is imperfect as there may exist optimized debug code not using - any location list and still facing inlining issues if handled as - unoptimized code. For a future better test see GCC PR other/32998. */ - bool has_loclist : 1; - - /* These cache the results for producer_is_* fields. CHECKED_PRODUCER is true - if all the producer_is_* fields are valid. This information is cached - because profiling CU expansion showed excessive time spent in - producer_is_gxx_lt_4_6. */ - bool checked_producer : 1; - bool producer_is_gxx_lt_4_6 : 1; - bool producer_is_gcc_lt_4_3 : 1; - bool producer_is_icc : 1; - bool producer_is_icc_lt_14 : 1; - bool producer_is_codewarrior : 1; - - /* When true, the file that we're processing is known to have - debugging info for C++ namespaces. GCC 3.3.x did not produce - this information, but later versions do. */ - - bool processing_has_namespace_info : 1; - - struct partial_die_info *find_partial_die (sect_offset sect_off); - - /* If this CU was inherited by another CU (via specification, - abstract_origin, etc), this is the ancestor CU. */ - dwarf2_cu *ancestor; - - /* Get the buildsym_compunit for this CU. */ - buildsym_compunit *get_builder () - { - /* If this CU has a builder associated with it, use that. */ - if (m_builder != nullptr) - return m_builder.get (); - - /* Otherwise, search ancestors for a valid builder. */ - if (ancestor != nullptr) - return ancestor->get_builder (); - - return nullptr; - } -}; - /* 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. */ |