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