* [RFA 3/3] Initial Fission support, the actual Fission stuff
@ 2012-04-18 19:12 Doug Evans
2012-04-19 5:07 ` Doug Evans
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Doug Evans @ 2012-04-18 19:12 UTC (permalink / raw)
To: gdb-patches, tromey; +Cc: ccoutant, saugustine
Hi.
This is the third patch in the Fission series and provides the actual
Fission support.
It requires patches 1/3, 2/3.
Regression tested on amd64-linux, with/without dwarf4 and .gdb_index,
and with the Fission gcc/binutils.
Ok to commit?
2012-04-18 Doug Evans <dje@google.com>
Initial support for Fission. http://gcc.gnu.org/wiki/DebugFission
* symfile.c (default_symfile_relocate): Use sectp->owner instead of
objfile->obfd.
* symfile.h (dwarf2_debug_sections): New members addr, ref.
* dwarf2expr.c (execute_stack_op): New case DW_OP_GNU_addr_index.
(ctx_no_get_addr_index): New function.
* dwarf2expr.h (dwarf_expr_context_funcs): New member get_addr_index.
(ctx_no_get_addr_index): Declare.
* dwarf2-frame.c (dwarf2_frame_ctx_funcs): Update.
* dwarf2loc.c (dwarf_expr_get_addr_index): New function.
(dwarf_expr_ctx_funcs): Update.
(needs_get_addr_index): New function.
(needs_frame_ctx_funcs): Update.
* dwarf2loc.h (dwarf2_read_addr_index): Declare.
* dwarf2read.c: #include "gdbcore.h".
(dwarf2_per_objfile): New members addr, ref, dwo_files.
(dwarf2_elf_names): Add entries for addr, ref.
(struct dwo_section_names): New type.
(dwo_section_names): New static global.
(dwarf2_cu): New members dwo_unit, addr_base, ref_base,
have_addr_base, have_ref_base.
(dwarf2_per_cu_data): New member is_debug_types, all boolean uses of
old debug_types_section member updated to use this.
Rename member debug_types_section to info_or_types_section,
all uses updated.
(signatured_type): Rename member type_offset to type_offset_in_tu,
all uses updated. New member type_offset_in_section.
(struct dwo_sections): New type.
(struct dwo_unit): New type.
(struct dwo_file): New type.
(die_reader_specs): New member dwo_file.
(dwarf2_locate_sections): Watch for .debug_addr, .debug_ref.
(dwarf2_read_section): Get bfd of section from bfd's asection,
instead of objfile.
(create_cus_from_index): Initialize the_cu->info_or_types_section.
(create_signatured_type_table_from_index): Initialize
sig_type->info_or_types_section.
(dw2_get_file_names): Statement lists for type units with DWO files
live in the DWO file.
(create_debug_types_hash_table): New function.
(create_all_type_units): Rewrite.
(lookup_signatured_type): New arg dwo_file, all callers updated.
(init_and_read_dies_worker): Get section from
this_cu->info_or_types_section. Set sig_type->type_offset_in_section.
Watch for DW_AT_GNU_dwo_name and if present lookup the file and
continue reading the CU/TU from there.
(init_cutu_and_read_dies_no_follow): New arg dwo_file, all callers
updated. Get section from this_cu->info_or_types_section.
(create_all_comp_units): Initialize this_cu->info_or_types_section.
(skip_one_die): New cases DW_FORM_GNU_addr_index,
DW_FORM_GNU_ref_index, DW_FORM_GNU_str_index.
(hash_dwo_file, eq_dwo_file): New functions.
(allocate_dwo_file_hash_table): New function.
(hash_dwo_unit, eq_dwo_unit): New functions.
(allocate_dwo_unit_table): New function.
(dwarf2_locate_dwo_sections): New function.
(struct create_dwo_info_table_data): New type.
(create_debug_info_hash_table_reader): New function.
(create_debug_info_hash_table): New function.
(try_open_dwo_file, open_dwo_file, init_dwo_file): New function.
(lookup_dwo_file): New function.
(lookup_dwo_comp_unit, lookup_dwo_type_unit): New functions.
(free_dwo_file, free_dwo_file_cleanup): New functions.
(free_dwo_file_from_slot, free_dwo_files): New functions.
(process_enumeration_scope): Update to use type_offset_in_section.
(read_full_die_1): New function.
(read_full_die): Rewrite.
(read_attribute_value): New cases DW_FORM_GNU_addr_index,
DW_FORM_GNU_ref_index, DW_FORM_GNU_str_index.
(read_addr_index_1, read_addr_index): New functions.
(read_addr_index_from_leb128): New function.
(struct dwarf2_read_addr_index_data): New type.
(dwarf2_read_addr_index_reader): New function.
(dwarf2_read_addr_index): New function.
(read_ref_index, read_ref_index_from_leb128): New functions.
(read_str_index): New function.
(leb128_size): New function.
(dwarf_decode_line_header): Delete arg abfd, all callers updated.
If processing a type unit from a DWO file, get the line section
from the DWO file.
(var_decode_location): Watch for DW_OP_GNU_addr_index.
(dwarf2_const_value_attr): New cases DW_FORM_GNU_addr_index,
DW_FORM_GNU_str_index.
(lookup_die_type): Check whether section offset of type's die is
known before looking it up.
(dwarf_attr_name): Handle Fission attributes.
(dwarf_form_name): Handle Fission forms.
(dump_die_shallow): New cases DW_FORM_GNU_addr_index,
DW_FORM_GNU_ref_index, DW_FORM_GNU_str_index.
(is_ref_attr): New case DW_FORM_GNU_ref_index.
(follow_die_sig): Update to use type_offset_in_section.
(decode_locdesc): New case DW_OP_GNU_addr_index.
(skip_form_bytes): New cases DW_FORM_GNU_addr_index,
DW_FORM_GNU_ref_index, DW_FORM_GNU_str_index.
(attr_form_is_section_offset): Handle DW_FORM_GNU_ref_index.
(dwarf2_per_objfile_free): Unmap .debug_addr, .debug_ref sections.
Free DWO files if present.
Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.330
diff -u -p -r1.330 symfile.c
--- symfile.c 17 Apr 2012 15:47:09 -0000 1.330
+++ symfile.c 18 Apr 2012 17:19:53 -0000
@@ -3625,7 +3625,9 @@ bfd_byte *
default_symfile_relocate (struct objfile *objfile, asection *sectp,
bfd_byte *buf)
{
- bfd *abfd = objfile->obfd;
+ /* Use sectp->owner instead of objfile->obfd. sectp may point to a
+ DWO file. */
+ bfd *abfd = sectp->owner;
/* We're only interested in sections with relocation
information. */
Index: symfile.h
===================================================================
RCS file: /cvs/src/src/gdb/symfile.h,v
retrieving revision 1.106
diff -u -p -r1.106 symfile.h
--- symfile.h 16 Mar 2012 16:47:31 -0000 1.106
+++ symfile.h 18 Apr 2012 17:19:53 -0000
@@ -589,6 +589,8 @@ struct dwarf2_debug_sections {
struct dwarf2_section_names str;
struct dwarf2_section_names ranges;
struct dwarf2_section_names types;
+ struct dwarf2_section_names addr;
+ struct dwarf2_section_names ref;
struct dwarf2_section_names frame;
struct dwarf2_section_names eh_frame;
struct dwarf2_section_names gdb_index;
Index: dwarf2expr.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.c,v
retrieving revision 1.80
diff -u -p -r1.80 dwarf2expr.c
--- dwarf2expr.c 19 Mar 2012 19:59:18 -0000 1.80
+++ dwarf2expr.c 18 Apr 2012 17:19:52 -0000
@@ -732,6 +732,12 @@ execute_stack_op (struct dwarf_expr_cont
result_val = value_from_ulongest (address_type, result);
break;
+ case DW_OP_GNU_addr_index:
+ op_ptr = read_uleb128 (op_ptr, op_end, &uoffset);
+ result = (ctx->funcs->get_addr_index) (ctx->baton, uoffset);
+ result_val = value_from_ulongest (address_type, result);
+ break;
+
case DW_OP_const1u:
result = extract_unsigned_integer (op_ptr, 1, byte_order);
result_val = value_from_ulongest (address_type, result);
@@ -1543,6 +1549,14 @@ ctx_no_push_dwarf_reg_entry_value (struc
_("Support for DW_OP_GNU_entry_value is unimplemented"));
}
+/* Stub dwarf_expr_context_funcs.get_addr_index implementation. */
+
+CORE_ADDR
+ctx_no_get_addr_index (void *baton, unsigned int index)
+{
+ error (_("%s is invalid in this context"), "DW_OP_GNU_addr_index");
+}
+
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_dwarf2expr;
Index: dwarf2expr.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2expr.h,v
retrieving revision 1.44
diff -u -p -r1.44 dwarf2expr.h
--- dwarf2expr.h 19 Mar 2012 19:59:18 -0000 1.44
+++ dwarf2expr.h 18 Apr 2012 17:19:52 -0000
@@ -85,6 +85,10 @@ struct dwarf_expr_context_funcs
int dwarf_reg, CORE_ADDR fb_offset,
int deref_size);
+ /* Return the address indexed by DW_OP_GNU_addr_index.
+ This can throw an exception if the index is out of range. */
+ CORE_ADDR (*get_addr_index) (void *baton, unsigned int index);
+
#if 0
/* Not yet implemented. */
@@ -293,6 +297,7 @@ struct type *ctx_no_get_base_type (struc
void ctx_no_push_dwarf_reg_entry_value (struct dwarf_expr_context *ctx,
int dwarf_reg, CORE_ADDR fb_offset,
int deref_size);
+CORE_ADDR ctx_no_get_addr_index (void *baton, unsigned int index);
int dwarf_block_to_dwarf_reg (const gdb_byte *buf, const gdb_byte *buf_end);
Index: dwarf2-frame.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2-frame.c,v
retrieving revision 1.133
diff -u -p -r1.133 dwarf2-frame.c
--- dwarf2-frame.c 17 Jan 2012 14:03:33 -0000 1.133
+++ dwarf2-frame.c 18 Apr 2012 17:19:52 -0000
@@ -354,7 +354,8 @@ static const struct dwarf_expr_context_f
ctx_no_get_tls_address,
ctx_no_dwarf_call,
ctx_no_get_base_type,
- ctx_no_push_dwarf_reg_entry_value
+ ctx_no_push_dwarf_reg_entry_value,
+ ctx_no_get_addr_index
};
static CORE_ADDR
Index: dwarf2loc.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2loc.c,v
retrieving revision 1.142
diff -u -p -r1.142 dwarf2loc.c
--- dwarf2loc.c 19 Mar 2012 19:59:19 -0000 1.142
+++ dwarf2loc.c 18 Apr 2012 17:19:52 -0000
@@ -1008,6 +1008,17 @@ dwarf_expr_push_dwarf_reg_entry_value (s
ctx->baton = saved_ctx.baton;
}
+/* Callback function for dwarf2_evaluate_loc_desc.
+ Fetch the address indexed by DW_OP_GNU_addr_index. */
+
+static CORE_ADDR
+dwarf_expr_get_addr_index (void *baton, unsigned int index)
+{
+ struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton;
+
+ return dwarf2_read_addr_index (debaton->per_cu, index);
+}
+
/* VALUE must be of type lval_computed with entry_data_value_funcs. Perform
the indirect method on it, that is use its stored target value, the sole
purpose of entry_data_value_funcs.. */
@@ -1942,7 +1953,8 @@ static const struct dwarf_expr_context_f
dwarf_expr_tls_address,
dwarf_expr_dwarf_call,
dwarf_expr_get_base_type,
- dwarf_expr_push_dwarf_reg_entry_value
+ dwarf_expr_push_dwarf_reg_entry_value,
+ dwarf_expr_get_addr_index
};
/* Evaluate a location description, starting at DATA and with length
@@ -2241,6 +2253,15 @@ needs_dwarf_reg_entry_value (struct dwar
nf_baton->needs_frame = 1;
}
+/* DW_OP_GNU_addr_index doesn't require a frame. */
+
+static CORE_ADDR
+needs_get_addr_index (void *baton, unsigned int index)
+{
+ /* Nothing to do. */
+ return 1;
+}
+
/* Virtual method table for dwarf2_loc_desc_needs_frame below. */
static const struct dwarf_expr_context_funcs needs_frame_ctx_funcs =
@@ -2253,7 +2274,8 @@ static const struct dwarf_expr_context_f
needs_frame_tls_address,
needs_frame_dwarf_call,
NULL, /* get_base_type */
- needs_dwarf_reg_entry_value
+ needs_dwarf_reg_entry_value,
+ needs_get_addr_index
};
/* Return non-zero iff the location expression at DATA (length SIZE)
Index: dwarf2loc.h
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2loc.h,v
retrieving revision 1.31
diff -u -p -r1.31 dwarf2loc.h
--- dwarf2loc.h 19 Mar 2012 19:59:19 -0000 1.31
+++ dwarf2loc.h 18 Apr 2012 17:19:52 -0000
@@ -80,6 +80,9 @@ struct value *dwarf2_evaluate_loc_desc (
unsigned short size,
struct dwarf2_per_cu_data *per_cu);
+CORE_ADDR dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
+ unsigned int addr_index);
+
/* The symbol location baton types used by the DWARF-2 reader (i.e.
SYMBOL_LOCATION_BATON for a LOC_COMPUTED symbol). "struct
dwarf2_locexpr_baton" is for a symbol with a single location
diff -u -p -d dwarf2read.c= dwarf2read.c
--- ../../../dwarf-cleanup/src/gdb/dwarf2read.c 2012-04-18 00:26:36.000000000 -0700
+++ ./dwarf2read.c 2012-04-18 11:19:49.000000000 -0700
@@ -60,6 +60,7 @@
#include "vec.h"
#include "c-lang.h"
#include "valprint.h"
+#include "gdbcore.h" /* for gnutarget */
#include <ctype.h>
#include <fcntl.h>
@@ -159,6 +160,8 @@ 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 ref;
struct dwarf2_section_info frame;
struct dwarf2_section_info eh_frame;
struct dwarf2_section_info gdb_index;
@@ -189,6 +192,10 @@ struct dwarf2_per_objfile
This is NULL if the .debug_types section hasn't been read in yet. */
htab_t signatured_types;
+ /* 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;
@@ -234,12 +241,35 @@ static const struct dwarf2_debug_section
{ ".debug_str", ".zdebug_str" },
{ ".debug_ranges", ".zdebug_ranges" },
{ ".debug_types", ".zdebug_types" },
+ { ".debug_addr", ".zdebug_addr" },
+ { ".debug_ref", ".zdebug_ref" },
{ ".debug_frame", ".zdebug_frame" },
{ ".eh_frame", NULL },
{ ".gdb_index", ".zgdb_index" },
23
};
+/* 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 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_str.dwo", ".zdebug_str.dwo" },
+ { ".debug_str_offsets.dwo", ".zdebug_str_offsets.dwo" },
+ { ".debug_types.dwo", ".zdebug_types.dwo" },
+};
+
/* local data types */
/* We hold several abbreviation tables in memory at the same time. */
@@ -375,6 +405,21 @@ 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.
+ At present this exists for debugging purposes, so one can know where
+ the CU originated from. */
+ 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_ref_base attribute if present, zero otherwise
+ (zero is a valid value though).
+ Note this value comes from the stub CU/TU's DIE. */
+ ULONGEST ref_base;
+
/* Mark used when releasing cached dies. */
unsigned int mark : 1;
@@ -390,6 +435,11 @@ struct dwarf2_cu
excessive time spent in producer_is_gxx_lt_4_6. */
unsigned int checked_producer : 1;
unsigned int producer_is_gxx_lt_4_6 : 1;
+
+ /* Flags indicating the respective attributes where found.
+ They are used when processing DWO files. */
+ unsigned int have_addr_base : 1;
+ unsigned int have_ref_base : 1;
};
/* Persistent data held for a compilation unit, even when not
@@ -402,7 +452,9 @@ 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. */
+ 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;
@@ -416,9 +468,13 @@ struct dwarf2_per_cu_data
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. */
@@ -447,15 +503,82 @@ struct dwarf2_per_cu_data
struct signatured_type
{
+ /* The type's signature. */
ULONGEST signature;
- /* Offset in this TU of the type defined by this TU. */
- cu_offset 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;
/* The CU(/TU) of this type. */
struct dwarf2_per_cu_data per_cu;
};
+/* 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 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. */
+ struct 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
@@ -469,8 +592,11 @@ struct die_reader_specs
/* The CU of the DIE we are parsing. */
struct dwarf2_cu *cu;
+ /* 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. */
+ This is either .debug_info or .debug_types, or the .dwo variants. */
struct dwarf2_section_info *die_section;
/* die_section->buffer. */
@@ -959,6 +1085,15 @@ static unsigned long read_unsigned_leb12
static long read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
+static CORE_ADDR read_addr_index_from_leb128 (struct dwarf2_cu *, gdb_byte *,
+ unsigned int *);
+
+static ULONGEST read_ref_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 gdb_byte *skip_leb128 (bfd *, gdb_byte *);
static void set_cu_language (unsigned int, struct dwarf2_cu *);
@@ -983,9 +1118,8 @@ static void free_line_header (struct lin
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 *,
@@ -1107,6 +1241,9 @@ static struct die_info *read_die_and_sib
gdb_byte **new_info_ptr,
struct die_info *parent);
+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 *);
@@ -1273,6 +1410,10 @@ static gdb_byte *read_and_check_comp_uni
struct dwarf2_section_info *section, gdb_byte *info_ptr,
int is_debug_types_section);
+static void init_tu_and_read_dies
+ (struct dwarf2_per_cu_data *this_cu, int keep,
+ die_reader_func_ftype *die_reader_func, void *data);
+
static void init_cutu_and_read_dies_simple
(struct dwarf2_per_cu_data *this_cu,
die_reader_func_ftype *die_reader_func, void *data);
@@ -1281,6 +1422,18 @@ static htab_t allocate_signatured_type_t
static void process_psymtab_comp_unit (struct dwarf2_per_cu_data *);
+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 *);
+
#if WORDS_BIGENDIAN
/* Convert VALUE between big- and little-endian. */
@@ -1401,6 +1554,16 @@ dwarf2_locate_sections (bfd *abfd, asect
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->ref))
+ {
+ dwarf2_per_objfile->ref.asection = sectp;
+ dwarf2_per_objfile->ref.size = bfd_get_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->frame))
{
dwarf2_per_objfile->frame.asection = sectp;
@@ -1530,15 +1693,17 @@ dwarf2_section_empty_p (struct dwarf2_se
return info->asection == NULL || info->size == 0;
}
-/* Read the contents of the section INFO 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];
@@ -1551,6 +1716,9 @@ dwarf2_read_section (struct objfile *obj
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
@@ -1772,7 +1940,7 @@ create_quick_file_names_table (unsigned
static void
load_cu (struct dwarf2_per_cu_data *per_cu)
{
- if (per_cu->debug_types_section)
+ if (per_cu->is_debug_types)
load_full_type_unit (per_cu);
else
load_full_comp_unit (per_cu);
@@ -1888,6 +2056,7 @@ create_cus_from_index (struct objfile *o
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;
@@ -1930,8 +2099,9 @@ create_signatured_type_table_from_index
sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
struct signatured_type);
sig_type->signature = signature;
- sig_type->type_offset.cu_off = type_offset_in_tu;
- sig_type->per_cu.debug_types_section = section;
+ 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
@@ -2237,7 +2407,6 @@ dw2_get_file_names_reader (const struct
struct dwarf2_cu *cu = reader->cu;
struct dwarf2_per_cu_data *this_cu = cu->per_cu;
struct objfile *objfile = dwarf2_per_objfile->objfile;
- bfd *abfd = objfile->obfd;
struct line_header *lh;
struct attribute *attr;
int i;
@@ -2269,7 +2438,7 @@ dw2_get_file_names_reader (const struct
return;
}
- lh = dwarf_decode_line_header (line_offset, abfd, cu);
+ lh = dwarf_decode_line_header (line_offset, cu);
}
if (lh == NULL)
{
@@ -2309,7 +2478,14 @@ dw2_get_file_names (struct objfile *objf
if (this_cu->v.quick->no_file_data)
return NULL;
- init_cutu_and_read_dies_simple (this_cu, dw2_get_file_names_reader, 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)
+ init_tu_and_read_dies (this_cu, 0, dw2_get_file_names_reader, NULL);
+ 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;
@@ -3150,18 +3326,12 @@ dwarf2_build_include_psymtabs (struct dw
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. */
@@ -3217,30 +3387,28 @@ add_signatured_type_cu_to_table (void **
return 1;
}
-/* Create the hash table of all entries in the .debug_types section(s).
- The result is zero if there are no .debug_types sections,
- otherwise non-zero. */
+/* Create the hash table of all entries in the .debug_types section.
+ 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_all_type_units (struct objfile *objfile)
+static htab_t
+create_debug_types_hash_table (struct dwo_file *dwo_file,
+ VEC (dwarf2_section_info_def) *types)
{
- struct bfd *abfd = objfile->obfd;
+ 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;
- 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;
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);
@@ -3249,12 +3417,21 @@ create_all_type_units (struct objfile *o
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, "Reading signatured types for %s:\n",
- bfd_get_filename (abfd));
+ bfd_get_filename (objfile->obfd));
/* 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
@@ -3264,9 +3441,10 @@ create_all_type_units (struct objfile *o
while (info_ptr < end_ptr)
{
sect_offset offset;
- cu_offset type_offset;
+ cu_offset type_offset_in_tu;
ULONGEST signature;
struct signatured_type *sig_type;
+ struct dwo_unit *dwo_tu;
void **slot;
gdb_byte *ptr = info_ptr;
struct comp_unit_head header;
@@ -3278,7 +3456,7 @@ create_all_type_units (struct objfile *o
table, but we don't need anything else just yet. */
ptr = read_and_check_type_unit_head (&header, section, ptr,
- &signature, &type_offset);
+ &signature, &type_offset_in_tu);
length = header.initial_length_size + header.length;
@@ -3290,28 +3468,62 @@ create_all_type_units (struct objfile *o
continue;
}
- sig_type = obstack_alloc (&objfile->objfile_obstack, sizeof (*sig_type));
- memset (sig_type, 0, sizeof (*sig_type));
- sig_type->signature = signature;
- sig_type->type_offset = type_offset;
- sig_type->per_cu.objfile = objfile;
- sig_type->per_cu.debug_types_section = section;
- sig_type->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, sig_type, 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.sect_off, dup_sig->per_cu.offset.sect_off,
+ offset.sect_off, dup_offset.sect_off,
phex (signature, sizeof (signature)));
- gdb_assert (signature == dup_sig->signature);
}
- *slot = sig_type;
+ *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
if (dwarf2_die_debug)
fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature 0x%s\n",
@@ -3322,6 +3534,27 @@ create_all_type_units (struct objfile *o
}
}
+ 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 dwarf2_per_cu_data **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_units = htab_elements (types_htab);
@@ -3362,11 +3595,13 @@ lookup_signatured_type (ULONGEST sig)
static void
init_cu_die_reader (struct die_reader_specs *reader,
struct dwarf2_cu *cu,
- struct dwarf2_section_info *section)
+ struct dwarf2_section_info *section,
+ struct dwo_file *dwo_file)
{
gdb_assert (section->readin);
reader->abfd = section->asection->owner;
reader->cu = cu;
+ reader->dwo_file = dwo_file;
reader->die_section = section;
reader->buffer = section->buffer;
}
@@ -3404,6 +3639,7 @@ dwarf2_find_base_address (struct die_inf
/* Subroutine of init_{cu,tu}_and_read_dies.
Do all the work necessary to initialize THIS_CU->cu and read in its DIE(s).
+ If the CU defers to a DWO file, read the DWO file as well.
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.
@@ -3426,8 +3662,8 @@ init_and_read_dies_worker (struct dwarf2
void *data)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct dwarf2_section_info *section;
- bfd *abfd;
+ 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;
@@ -3439,15 +3675,9 @@ init_and_read_dies_worker (struct dwarf2
if (use_existing_cu)
gdb_assert (keep);
- if (this_cu->debug_types_section)
+ if (this_cu->is_debug_types)
gdb_assert (! use_existing_cu);
- if (this_cu->debug_types_section)
- section = this_cu->debug_types_section;
- else
- section = &dwarf2_per_objfile->info;
- abfd = section->asection->owner;
-
cleanups = make_cleanup (null_cleanup, NULL);
/* This is cheap if the section is already read in. */
@@ -3471,7 +3701,7 @@ init_and_read_dies_worker (struct dwarf2
/* If an error occurs while loading, release our storage. */
free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
- if (this_cu->debug_types_section)
+ if (this_cu->is_debug_types)
{
ULONGEST signature;
@@ -3491,6 +3721,10 @@ init_and_read_dies_worker (struct dwarf2
/* LENGTH has not been set yet for type units. */
this_cu->length = cu->header.length + cu->header.initial_length_size;
+
+ /* 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
{
@@ -3519,9 +3753,167 @@ init_and_read_dies_worker (struct dwarf2
}
/* Read the top level CU/TU die. */
- init_cu_die_reader (&reader, cu, section);
+ 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;
+ struct dwo_unit *dwo_unit;
+ ULONGEST signature; /* Or dwo_id. */
+ struct attribute *stmt_list, *low_pc, *high_pc, *ranges;
+ int i,num_extra_attrs;
+
+ 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. */
+ stmt_list = low_pc = high_pc = ranges = NULL;
+
+ /* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
+ DWO file. */
+ 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_stmt_list, cu);
+
+ /* There should be DW_AT_addr_base,DW_AT_ref_base attributes here
+ (if needed).
+ We need their values before we can process DW_FORM_GNU_addr_index
+ and DW_FORM_GNU_ref_index values. */
+ cu->addr_base = 0;
+ cu->have_addr_base = 0;
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_addr_base, cu);
+ if (attr)
+ {
+ /* FIXME: Why do ref attributes use DW_ADDR instead of DW_UNSND? */
+ cu->addr_base = DW_UNSND (attr);
+ cu->have_addr_base = 1;
+ }
+ cu->ref_base = 0;
+ cu->have_ref_base = 0;
+ attr = dwarf2_attr (comp_unit_die, DW_AT_GNU_ref_base, cu);
+ if (attr)
+ {
+ /* FIXME: Why do ref attributes use DW_ADDR instead of DW_UNSND? */
+ cu->ref_base = DW_UNSND (attr);
+ cu->have_ref_base = 1;
+ }
+
+ if (this_cu->is_debug_types)
+ {
+ 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 = NULL;
+ attr = dwarf2_attr (comp_unit_die, DW_AT_comp_dir, cu);
+ if (attr)
+ comp_dir = DW_STRING (attr);
+
+ if (this_cu->is_debug_types)
+ dwo_unit = lookup_dwo_type_unit (sig_type, dwo_name, comp_dir);
+ else
+ dwo_unit = lookup_dwo_comp_unit (this_cu, dwo_name, comp_dir,
+ 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;
+ 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, 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
+ == cu->header.length + cu->header.initial_length_size);
+
+ /* 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, info_ptr, 0);
+ gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
+ gdb_assert (dwo_unit->length
+ == cu->header.length + cu->header.initial_length_size);
+ }
+
+ /* Discard the original CU's abbrev table, and read the DWO's. */
+ dwarf2_free_abbrev_table (cu);
+ dwarf2_read_abbrevs (cu, &dwo_unit->dwo_file->sections.abbrev);
+
+ /* 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));
+ 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;
+ 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)
@@ -3549,6 +3941,7 @@ init_and_read_dies_worker (struct dwarf2
/* Main entry point for reading a CU.
Do all the work necessary to initialize THIS_CU->cu and read in its DIE(s).
+ If the CU defers to a DWO file, read the DWO file as well.
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.
@@ -3568,6 +3961,7 @@ init_cu_and_read_dies (struct dwarf2_per
/* Main entry point for reading a TU.
Do all the work necessary to initialize THIS_CU->cu and read in its DIE(s).
+ If the TU defers to a DWO file, read the DWO file as well.
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. */
@@ -3578,14 +3972,17 @@ init_tu_and_read_dies (struct dwarf2_per
die_reader_func_ftype *die_reader_func,
void *data)
{
- gdb_assert (this_cu->debug_types_section);
+ gdb_assert (this_cu->is_debug_types);
init_and_read_dies_worker (this_cu, 0, keep, die_reader_func, data);
}
-/* Read the CU/TU at OFFSET in section SECTION.
+/* 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).
The caller is required to fill in THIS_CU->section, THIS_CU->offset, and
- THIS_CU->debug_types_section, but nothing else.
+ THIS_CU->is_debug_types, but nothing else.
We fill in THIS_CU->length.
@@ -3593,17 +3990,19 @@ init_tu_and_read_dies (struct dwarf2_per
linker) then DIE_READER_FUNC will not get called.
THIS_CU->cu is always freed when done.
- [This is done for Fission reasons, to be specified.] */
+ 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)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct dwarf2_section_info *section;
- bfd *abfd;
+ 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;
@@ -3613,12 +4012,6 @@ init_cutu_and_read_dies_no_follow (struc
gdb_assert (this_cu->cu == NULL);
- if (this_cu->debug_types_section)
- section = this_cu->debug_types_section;
- else
- section = &dwarf2_per_objfile->info;
- abfd = section->asection->owner;
-
/* This is cheap if the section is already read in. */
dwarf2_read_section (objfile, section);
@@ -3628,7 +4021,7 @@ init_cutu_and_read_dies_no_follow (struc
begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
info_ptr = read_and_check_comp_unit_head (&cu.header, section, info_ptr,
- this_cu->debug_types_section != NULL);
+ this_cu->is_debug_types);
this_cu->length = cu.header.length + cu.header.initial_length_size;
@@ -3643,7 +4036,7 @@ init_cutu_and_read_dies_no_follow (struc
dwarf2_read_abbrevs (&cu, abbrev_section);
make_cleanup (dwarf2_free_abbrev_table, &cu);
- init_cu_die_reader (&reader, &cu, section);
+ init_cu_die_reader (&reader, &cu, section, dwo_file);
info_ptr = read_full_die (&reader, &comp_unit_die, info_ptr, &has_children);
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
@@ -3651,11 +4044,14 @@ init_cutu_and_read_dies_no_follow (struc
do_cleanups (cleanups);
}
-/* Read a CU/TU.
- [This is a separate routine for Fission, to be specified.]
+/* 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.
THIS_CU->cu is always freed when done.
- [This is done for Fission reasons, to be specified.] */
+ 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. */
static void
init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu,
@@ -3664,6 +4060,7 @@ init_cutu_and_read_dies_simple (struct d
{
init_cutu_and_read_dies_no_follow (this_cu,
&dwarf2_per_objfile->abbrev,
+ NULL,
die_reader_func, data);
}
@@ -3772,7 +4169,7 @@ process_psymtab_comp_unit_reader (const
(objfile->static_psymbols.list + pst->statics_offset);
sort_pst_symbols (pst);
- if (per_cu->debug_types_section)
+ if (per_cu->is_debug_types)
{
/* It's not clear we want to do anything with stmt lists here.
Waiting to see what gcc ultimately does. */
@@ -3799,7 +4196,7 @@ process_psymtab_comp_unit (struct dwarf2
if (this_cu->cu != NULL)
free_one_cached_comp_unit (this_cu);
- gdb_assert (! this_cu->debug_types_section);
+ gdb_assert (! this_cu->is_debug_types);
init_cu_and_read_dies (this_cu, 0, 0, process_psymtab_comp_unit_reader,
NULL);
@@ -3826,7 +4223,7 @@ process_psymtab_type_unit (void **slot,
if (per_cu->cu != NULL)
free_one_cached_comp_unit (per_cu);
- gdb_assert (per_cu->debug_types_section);
+ gdb_assert (per_cu->is_debug_types);
init_tu_and_read_dies (per_cu, 0, process_psymtab_comp_unit_reader, NULL);
/* Age out any secondary CUs. */
@@ -3901,7 +4298,7 @@ dwarf2_build_psymtabs_hard (struct objfi
do_cleanups (back_to);
}
-/* Load the partial DIEs for a secondary CU into memory. */
+/* die_reader_func for load_partial_comp_unit. */
static void
load_partial_comp_unit_reader (const struct die_reader_specs *reader,
@@ -3927,7 +4324,7 @@ load_partial_comp_unit_reader (const str
static void
load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
{
- if (this_cu->debug_types_section)
+ if (this_cu->is_debug_types)
init_tu_and_read_dies (this_cu, 1, load_partial_comp_unit_reader, NULL);
else
init_cu_and_read_dies (this_cu, 0, 1, load_partial_comp_unit_reader, NULL);
@@ -3973,6 +4370,7 @@ create_all_comp_units (struct objfile *o
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)
{
@@ -4655,6 +5053,9 @@ skip_one_die (const struct die_reader_sp
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_ref_index:
+ case DW_FORM_GNU_str_index:
info_ptr = skip_leb128 (abfd, info_ptr);
break;
case DW_FORM_indirect:
@@ -4933,7 +5334,7 @@ load_full_comp_unit_reader (const struct
static void
load_full_comp_unit (struct dwarf2_per_cu_data *this_cu)
{
- gdb_assert (! this_cu->debug_types_section);
+ gdb_assert (! this_cu->is_debug_types);
init_cu_and_read_dies (this_cu, 1, 1, load_full_comp_unit_reader, NULL);
}
@@ -5786,15 +6187,13 @@ handle_DW_AT_stmt_list (struct die_info
const char *comp_dir, int want_line_info)
{
struct attribute *attr;
- struct objfile *objfile = cu->objfile;
- bfd *abfd = objfile->obfd;
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)
{
@@ -5974,6 +6373,529 @@ read_type_unit_scope (struct die_info *d
do_cleanups (back_to);
}
+\f
+/* DWO files. */
+
+static hashval_t
+hash_dwo_file (const void *item)
+{
+ const struct dwo_file *dwo_file = item;
+
+ return htab_hash_string (dwo_file->dwo_name);
+}
+
+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;
+
+ return strcmp (lhs->dwo_name, rhs->dwo_name) == 0;
+}
+
+/* Allocate a hash table for DWO files. */
+
+static htab_t
+allocate_dwo_file_hash_table (void)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+ return htab_create_alloc_ex (41,
+ hash_dwo_file,
+ eq_dwo_file,
+ NULL,
+ &objfile->objfile_obstack,
+ hashtab_obstack_allocate,
+ dummy_obstack_deallocate);
+}
+
+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))
+ {
+ 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->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_die_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_die_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 struct bfd *
+try_open_dwo_file (const char *file_name)
+{
+ bfd *sym_bfd;
+ int desc;
+ char *absolute_name;
+ char *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)
+ {
+ close (desc);
+ 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 struct bfd *
+open_dwo_file (const char *dwo_name, const char *comp_dir)
+{
+ struct bfd *abfd;
+ char *path_to_try, *debug_dir;
+
+ 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);
+ struct bfd *abfd;
+ struct cleanup *cleanups;
+
+ if (dwarf2_die_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 the DWO CU 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 the DWO CU 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;
+ struct dwo_unit find_dwo_tu, *dwo_tu;
+
+ 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 all the DWO file descriptors 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);
+
+ 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.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);
+
+ VEC_free (dwarf2_section_info_def, dwo_file->sections.types);
+}
+
+/* Wrapper for free_dwo_file for use in cleanups. */
+
+static void
+free_dwo_file_cleanup (void *arg)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) arg;
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+
+ free_dwo_file (dwo_file, objfile);
+}
+
+/* Traversal function for free_dwo_files. */
+
+static int
+free_dwo_file_from_slot (void **slot, void *info)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) *slot;
+ struct objfile *objfile = (struct objfile *) info;
+
+ free_dwo_file (dwo_file, objfile);
+
+ return 1;
+}
+
+/* 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);
+}
+\f
+/* Read in various DIEs. */
/* qsort helper for inherit_abstract_dies. */
@@ -8235,17 +9157,17 @@ process_enumeration_scope (struct die_in
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 *sig_type;
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 (sig_type->per_cu.offset.sect_off + sig_type->type_offset.cu_off
- != die->offset.sect_off)
+ 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;
}
@@ -9360,15 +10282,18 @@ read_die_and_siblings (const struct die_
}
}
-/* 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;
sect_offset offset;
@@ -9393,11 +10318,14 @@ read_full_die (const struct die_reader_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)
@@ -9409,6 +10337,19 @@ read_full_die (const struct die_reader_s
return info_ptr;
}
+/* 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);
+}
+
/* 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
@@ -10077,7 +11018,7 @@ find_partial_die (sect_offset offset, st
else
{
/* TUs don't reference other CUs/TUs (except via type signatures). */
- if (cu->per_cu->debug_types_section)
+ 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"),
@@ -10396,6 +11337,48 @@ read_attribute_value (const struct die_r
info_ptr += bytes_read;
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_ref_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_UNSND (attr) = read_ref_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]"),
dwarf_form_name (form),
@@ -10765,6 +11748,209 @@ read_signed_leb128 (bfd *abfd, gdb_byte
return result;
}
+/* 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 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)
+{
+ struct 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 an index in .debug_ref, fetch the value. */
+
+static ULONGEST
+read_ref_index (struct dwarf2_cu *cu, unsigned int ref_index)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ bfd *abfd = objfile->obfd;
+ gdb_byte *info_ptr;
+
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->ref);
+ if (dwarf2_per_objfile->ref.buffer == NULL)
+ error (_("DW_FORM_GNU_ref_index used without .debug_ref section"
+ " [in module %s]"),
+ objfile->name);
+ if (cu->ref_base + ref_index * cu->header.offset_size
+ >= dwarf2_per_objfile->ref.size)
+ error (_("DW_FORM_GNU_ref_index pointing outside of .debug_ref section"
+ " [in module %s]"),
+ objfile->name);
+ info_ptr = (dwarf2_per_objfile->ref.buffer
+ + cu->ref_base
+ + ref_index * cu->header.offset_size);
+ if (cu->header.offset_size == 4)
+ return bfd_get_32 (abfd, info_ptr);
+ else
+ return bfd_get_64 (abfd, info_ptr);
+}
+
+/* Given a pointer to an leb128 value, fetch the value from .debug_ref. */
+
+static ULONGEST
+read_ref_index_from_leb128 (struct dwarf2_cu *cu, gdb_byte *info_ptr,
+ unsigned int *bytes_read)
+{
+ struct bfd *abfd = dwarf2_per_objfile->objfile->obfd;
+ unsigned int ref_index = read_unsigned_leb128 (abfd, info_ptr, bytes_read);
+
+ return read_ref_index (cu, ref_index);
+}
+
+/* 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 a pointer to just past the end of an LEB128 number in BUF. */
static gdb_byte *
@@ -10781,6 +11967,22 @@ skip_leb128 (bfd *abfd, gdb_byte *buf)
}
}
+/* Return the length of an LEB128 number in BUF. */
+
+static int
+leb128_size (const gdb_byte *buf)
+{
+ const gdb_byte *begin = buf;
+ gdb_byte byte;
+
+ while (1)
+ {
+ byte = *buf++;
+ if ((byte & 128) == 0)
+ return buf - begin;
+ }
+}
+
static void
set_cu_language (unsigned int lang, struct dwarf2_cu *cu)
{
@@ -11005,16 +12207,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;
@@ -11022,17 +12223,30 @@ dwarf_decode_line_header (unsigned int o
unsigned int bytes_read, offset_size;
int i;
char *cur_dir, *cur_file;
+ struct dwarf2_section_info *section;
+ bfd *abfd;
- dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->line);
- if (dwarf2_per_objfile->line.buffer == NULL)
+ /* 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;
+ abfd = section->asection->owner;
+
+ 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;
}
/* 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;
@@ -11043,15 +12257,14 @@ dwarf_decode_line_header (unsigned int o
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;
@@ -11123,8 +12336,7 @@ dwarf_decode_line_header (unsigned int o
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"));
@@ -11674,17 +12886,24 @@ var_decode_location (struct attribute *a
/* 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,
@@ -12135,6 +13354,7 @@ dwarf2_const_value_attr (struct attribut
switch (attr->form)
{
case DW_FORM_addr:
+ case DW_FORM_GNU_addr_index:
{
gdb_byte *data;
@@ -12162,6 +13382,7 @@ dwarf2_const_value_attr (struct attribut
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);
@@ -12357,7 +13578,6 @@ lookup_die_type (struct die_info *die, s
else if (attr->form == DW_FORM_ref_sig8)
{
struct signatured_type *sig_type = DW_SIGNATURED_TYPE (attr);
- sect_offset offset;
/* sig_type will be NULL if the signatured type is missing from
the debug info. */
@@ -12366,10 +13586,16 @@ lookup_die_type (struct die_info *die, s
"at 0x%x [in module %s]"),
die->offset.sect_off, objfile->name);
- gdb_assert (sig_type->per_cu.debug_types_section);
- offset.sect_off = (sig_type->per_cu.offset.sect_off
- + sig_type->type_offset.cu_off);
- 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
{
@@ -13334,6 +14560,19 @@ dwarf_attr_name (unsigned attr)
return "DW_AT_signature";
case DW_AT_linkage_name:
return "DW_AT_linkage_name";
+ /* Tentative Fission values. */
+ case DW_AT_GNU_dwo_name:
+ return "DW_AT_GNU_dwo_name";
+ case DW_AT_GNU_dwo_id:
+ return "DW_AT_GNU_dwo_id";
+ case DW_AT_GNU_ref_base:
+ return "DW_AT_GNU_ref_base";
+ case DW_AT_GNU_addr_base:
+ return "DW_AT_GNU_addr_base";
+ case DW_AT_GNU_pubnames:
+ return "DW_AT_GNU_pubnames";
+ case DW_AT_GNU_pubtypes:
+ return "DW_AT_GNU_pubtypes";
/* SGI/MIPS extensions. */
#ifdef MIPS /* collides with DW_AT_HP_block_index */
case DW_AT_MIPS_fde:
@@ -13482,6 +14721,12 @@ dwarf_form_name (unsigned form)
return "DW_FORM_flag_present";
case DW_FORM_ref_sig8:
return "DW_FORM_ref_sig8";
+ case DW_FORM_GNU_addr_index:
+ return "DW_FORM_GNU_addr_index";
+ case DW_FORM_GNU_ref_index:
+ return "DW_FORM_GNU_ref_index";
+ case DW_FORM_GNU_str_index:
+ return "DW_FORM_GNU_str_index";
default:
return "DW_FORM_<unknown>";
}
@@ -14014,6 +15259,7 @@ dump_die_shallow (struct ui_file *f, int
switch (die->attrs[i].form)
{
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;
@@ -14037,6 +15283,7 @@ dump_die_shallow (struct ui_file *f, int
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_ref_index:
fprintf_unfiltered (f, "constant ref: 0x%lx (adjusted)",
(long) (DW_UNSND (&die->attrs[i])));
break;
@@ -14062,6 +15309,7 @@ dump_die_shallow (struct ui_file *f, int
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]) : "",
@@ -14165,6 +15413,7 @@ is_ref_attr (struct attribute *attr)
case DW_FORM_ref4:
case DW_FORM_ref8:
case DW_FORM_ref_udata:
+ case DW_FORM_GNU_ref_index:
return 1;
default:
return 0;
@@ -14292,7 +15541,7 @@ follow_die_offset (sect_offset offset, s
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
@@ -14454,8 +15703,8 @@ follow_die_sig (struct die_info *src_die
gdb_assert (sig_type->per_cu.cu != NULL);
sig_cu = sig_type->per_cu.cu;
- temp_die.offset.sect_off = (sig_type->per_cu.offset.sect_off
- + sig_type->type_offset.cu_off);
+ 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)
@@ -14503,7 +15752,7 @@ static void
load_full_type_unit (struct dwarf2_per_cu_data *per_cu)
{
struct objfile *objfile = per_cu->objfile;
- struct dwarf2_section_info *sect = per_cu->debug_types_section;
+ struct dwarf2_section_info *sect = per_cu->info_or_types_section;
sect_offset offset = per_cu->offset;
struct signatured_type *sig_type;
@@ -14564,14 +15813,16 @@ read_signatured_type_reader (const struc
prepare_one_comp_unit (cu, cu->dies);
}
-/* Read in a signatured type and build its CU and DIEs. */
+/* 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;
- gdb_assert (per_cu->debug_types_section);
+ gdb_assert (per_cu->is_debug_types);
gdb_assert (per_cu->cu == NULL);
init_tu_and_read_dies (per_cu, 1, read_signatured_type_reader, NULL);
@@ -14799,6 +16050,12 @@ decode_locdesc (struct dwarf_block *blk,
case DW_OP_GNU_uninit:
break;
+ case DW_OP_GNU_addr_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);
@@ -15186,6 +16443,9 @@ skip_form_bytes (bfd *abfd, gdb_byte *by
case DW_FORM_sdata:
case DW_FORM_udata:
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_ref_index:
+ case DW_FORM_GNU_str_index:
bytes = skip_leb128 (abfd, bytes);
break;
@@ -15737,7 +16997,9 @@ attr_form_is_section_offset (struct attr
{
return (attr->form == DW_FORM_data4
|| attr->form == DW_FORM_data8
- || attr->form == DW_FORM_sec_offset);
+ || attr->form == DW_FORM_sec_offset
+ /* Fission uses this for DW_AT_location. */
+ || attr->form == DW_FORM_GNU_ref_index);
}
/* Return non-zero if ATTR's value falls in the 'constant' class, or
@@ -16175,11 +17437,12 @@ dwarf2_free_objfile (struct objfile *obj
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.
- 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. */
+ 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_per_cu_offset_and_type
{
@@ -16449,6 +17712,8 @@ dwarf2_per_objfile_free (struct objfile
munmap_section_buffer (&data->macro);
munmap_section_buffer (&data->str);
munmap_section_buffer (&data->ranges);
+ munmap_section_buffer (&data->addr);
+ munmap_section_buffer (&data->ref);
munmap_section_buffer (&data->frame);
munmap_section_buffer (&data->eh_frame);
munmap_section_buffer (&data->gdb_index);
@@ -16459,6 +17724,9 @@ dwarf2_per_objfile_free (struct objfile
munmap_section_buffer (section);
VEC_free (dwarf2_section_info_def, data->types);
+
+ if (data->dwo_files)
+ free_dwo_files (data->dwo_files, objfile);
}
\f
@@ -17004,7 +18272,8 @@ write_one_signatured_type (void **slot,
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.cu_off);
+ 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);
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-18 19:12 [RFA 3/3] Initial Fission support, the actual Fission stuff Doug Evans
@ 2012-04-19 5:07 ` Doug Evans
2012-04-27 18:29 ` Tom Tromey
2012-04-19 10:25 ` Yao Qi
` (2 subsequent siblings)
3 siblings, 1 reply; 12+ messages in thread
From: Doug Evans @ 2012-04-19 5:07 UTC (permalink / raw)
To: gdb-patches, tromey; +Cc: ccoutant, saugustine
On Wed, Apr 18, 2012 at 11:57 AM, Doug Evans <dje@google.com> wrote:
> Hi.
>
> This is the third patch in the Fission series and provides the actual
> Fission support.
Sorry, forgot.
A lot of the error() calls for bad debug info I want to turn into
complaints, but it's been useful during development to have the more
immediate effect of the error.
IWBN to have an option to make complaints errors, but that is
problematic as well. For now, my plan is to turn the errors into
complaints in time.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-18 19:12 [RFA 3/3] Initial Fission support, the actual Fission stuff Doug Evans
2012-04-19 5:07 ` Doug Evans
@ 2012-04-19 10:25 ` Yao Qi
2012-04-19 15:28 ` Doug Evans
2012-04-27 18:20 ` Tom Tromey
2012-04-29 9:05 ` Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff] Jan Kratochvil
3 siblings, 1 reply; 12+ messages in thread
From: Yao Qi @ 2012-04-19 10:25 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches, tromey, ccoutant, saugustine
On 04/19/2012 02:57 AM, Doug Evans wrote:
> Regression tested on amd64-linux, with/without dwarf4 and .gdb_index,
> and with the Fission gcc/binutils.
>
Do we have a test case for this feature?
>
> 2012-04-18 Doug Evans <dje@google.com>
>
> Initial support for Fission. http://gcc.gnu.org/wiki/DebugFission
Need a NEWS entry?
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-19 10:25 ` Yao Qi
@ 2012-04-19 15:28 ` Doug Evans
2012-04-27 18:38 ` Tom Tromey
0 siblings, 1 reply; 12+ messages in thread
From: Doug Evans @ 2012-04-19 15:28 UTC (permalink / raw)
To: Yao Qi; +Cc: gdb-patches, tromey, ccoutant, saugustine
On Thu, Apr 19, 2012 at 12:14 AM, Yao Qi <yao@codesourcery.com> wrote:
> On 04/19/2012 02:57 AM, Doug Evans wrote:
>> Regression tested on amd64-linux, with/without dwarf4 and .gdb_index,
>> and with the Fission gcc/binutils.
>>
>
> Do we have a test case for this feature?
Heh. Touche! :-)
I've been testing with -gfission with/without --Wl,--gdb-index (gold).
It's akin to testing .debug_types and .gdb_index.
If Tom adds a testcase case for gdb_index, I'll add one for Fission.
1/2 :-)
>> 2012-04-18 Doug Evans <dje@google.com>
>>
>> Initial support for Fission. http://gcc.gnu.org/wiki/DebugFission
>
> Need a NEWS entry?
Yep, thanks.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-18 19:12 [RFA 3/3] Initial Fission support, the actual Fission stuff Doug Evans
2012-04-19 5:07 ` Doug Evans
2012-04-19 10:25 ` Yao Qi
@ 2012-04-27 18:20 ` Tom Tromey
2012-04-28 23:59 ` Doug Evans
2012-04-29 9:05 ` Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff] Jan Kratochvil
3 siblings, 1 reply; 12+ messages in thread
From: Tom Tromey @ 2012-04-27 18:20 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches, ccoutant, saugustine
>>>>> "Doug" == Doug Evans <dje@google.com> writes:
Doug> * symfile.h (dwarf2_debug_sections): New members addr, ref.
I think you have to update xcoffread.c as well.
Doug> + struct bfd *dwo_bfd;
I think it is more normal to use the 'bfd' typedef.
I see a few uses of 'struct bfd' in the tree, but 10x more for the
typedef.
Doug> + /* We can't set abfd until now because the section may be empty or
Doug> + not present, in which case section->asection will be NULL. */
Doug> + abfd = section->asection->owner;
Doug> +
Doug> if (types_htab == NULL)
Doug> - types_htab = allocate_signatured_type_table (objfile);
Doug> + {
Doug> + if (dwo_file)
Doug> + types_htab = allocate_dwo_unit_table (objfile);
Doug> + else
Doug> + types_htab = allocate_signatured_type_table (objfile);
Doug> + }
Doug> if (dwarf2_die_debug)
Doug> fprintf_unfiltered (gdb_stdlog, "Reading signatured types for %s:\n",
Doug> - bfd_get_filename (abfd));
Doug> + bfd_get_filename (objfile->obfd));
The code uses abfd, but the debugging print uses objfile->obfd.
If this is intentional, I think it deserves a clarifying comment.
Doug> + /* FIXME: Why do ref attributes use DW_ADDR instead of DW_UNSND? */
Doug> + /* FIXME: Why do ref attributes use DW_ADDR instead of DW_UNSND? */
IIRC you fixed these already.
Doug> +static struct bfd *
Doug> +try_open_dwo_file (const char *file_name)
Doug> +{
Doug> + bfd *sym_bfd;
[...]
I couldn't find any code to close these BFDs.
I think it may be an oversight in free_dwo_file.
Also, I wonder whether this needs special code for the case where the
underlying object file is modified.
Tom
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-19 5:07 ` Doug Evans
@ 2012-04-27 18:29 ` Tom Tromey
0 siblings, 0 replies; 12+ messages in thread
From: Tom Tromey @ 2012-04-27 18:29 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches, ccoutant, saugustine
Doug> IWBN to have an option to make complaints errors, but that is
Doug> problematic as well. For now, my plan is to turn the errors into
Doug> complaints in time.
Radical view follows.
I'm more and more of the opinion that we should just remove all the
complaints.
First, there's evidence that nobody reads them.
There are a few complaints that have been regularly printed for years,
with zero action. (Now, at least one of these is a GCC/GDB/GNU
interpretation of DWARF that is, IMO, baked in and unlikely to change
(the register thing) -- so one may argue that just the bad ones should
be eliminated.)
Second, the complaints are in practice often useless for finding or
reporting any problem. I usually resort to debugging gdb.
Fixable, of course, but seeing as nobody has bothered...
Third, even if the messages were useful, they're still not very good for
ordinary users to understand "why doesn't gdb work". That's because,
unless they are enabled at the moment at which debuginfo is read, they
are just gone.
I think rather than complaints we could get "someone" to fix up
dwarflint instead. This would serve the toolchain development community
better. E.g., we could build the distro with dwarflint checking and fix
the bugs.
Tom
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-19 15:28 ` Doug Evans
@ 2012-04-27 18:38 ` Tom Tromey
0 siblings, 0 replies; 12+ messages in thread
From: Tom Tromey @ 2012-04-27 18:38 UTC (permalink / raw)
To: Doug Evans; +Cc: Yao Qi, gdb-patches, ccoutant, saugustine
>>>>> "Doug" == Doug Evans <dje@google.com> writes:
Doug> If Tom adds a testcase case for gdb_index, I'll add one for Fission.
Doug> 1/2 :-)
It may be a good idea.
I'm a bit concerned that our test configurations are exploding.
Perhaps it would be good to have at least a smoke test of all features
without any special setup.
E.g, just in this area we have:
* Test with or without an index
* Two ways to make the index
* Fission
* dwz; and this can be run after the index is made, as it attempts
to rewrite it in place -- so you could test gdb-index | dwz,
dwz | gdb-index, or gold | dwz
Tom
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFA 3/3] Initial Fission support, the actual Fission stuff
2012-04-27 18:20 ` Tom Tromey
@ 2012-04-28 23:59 ` Doug Evans
0 siblings, 0 replies; 12+ messages in thread
From: Doug Evans @ 2012-04-28 23:59 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches, ccoutant, saugustine
On Fri, Apr 27, 2012 at 11:15 AM, Tom Tromey <tromey@redhat.com> wrote:
>>>>>> "Doug" == Doug Evans <dje@google.com> writes:
>
> Doug> * symfile.h (dwarf2_debug_sections): New members addr, ref.
>
> I think you have to update xcoffread.c as well.
Righto.
> Doug> + struct bfd *dwo_bfd;
>
> I think it is more normal to use the 'bfd' typedef.
> I see a few uses of 'struct bfd' in the tree, but 10x more for the
> typedef.
Yeah, done.
> Doug> + /* We can't set abfd until now because the section may be empty or
> Doug> + not present, in which case section->asection will be NULL. */
> Doug> + abfd = section->asection->owner;
> Doug> +
> Doug> if (types_htab == NULL)
> Doug> - types_htab = allocate_signatured_type_table (objfile);
> Doug> + {
> Doug> + if (dwo_file)
> Doug> + types_htab = allocate_dwo_unit_table (objfile);
> Doug> + else
> Doug> + types_htab = allocate_signatured_type_table (objfile);
> Doug> + }
>
> Doug> if (dwarf2_die_debug)
> Doug> fprintf_unfiltered (gdb_stdlog, "Reading signatured types for %s:\n",
> Doug> - bfd_get_filename (abfd));
> Doug> + bfd_get_filename (objfile->obfd));
>
> The code uses abfd, but the debugging print uses objfile->obfd.
> If this is intentional, I think it deserves a clarifying comment.
Done.
> Doug> + /* FIXME: Why do ref attributes use DW_ADDR instead of DW_UNSND? */
>
> Doug> + /* FIXME: Why do ref attributes use DW_ADDR instead of DW_UNSND? */
>
> IIRC you fixed these already.
Righto, removed.
> Doug> +static struct bfd *
> Doug> +try_open_dwo_file (const char *file_name)
> Doug> +{
> Doug> + bfd *sym_bfd;
> [...]
>
> I couldn't find any code to close these BFDs.
> I think it may be an oversight in free_dwo_file.
Indeed.
> Also, I wonder whether this needs special code for the case where the
> underlying object file is modified.
That will require some API enhancements to the file readers (there
could be an arbitrary number of such files, and I don't want symfile.c
to have to know about them).
I'm going to submit that as a separate patch.
As discussed off list, I've committed the patches to date.
Regression tested without fission. A few failures remain with -gfission.
I still need a NEWS entry as well. That will come with the followup patch.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff]
2012-04-18 19:12 [RFA 3/3] Initial Fission support, the actual Fission stuff Doug Evans
` (2 preceding siblings ...)
2012-04-27 18:20 ` Tom Tromey
@ 2012-04-29 9:05 ` Jan Kratochvil
2012-04-30 0:06 ` Doug Evans
3 siblings, 1 reply; 12+ messages in thread
From: Jan Kratochvil @ 2012-04-29 9:05 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches, tromey, ccoutant, saugustine
On Wed, 18 Apr 2012 20:57:38 +0200, Doug Evans wrote:
> 2012-04-18 Doug Evans <dje@google.com>
>
> Initial support for Fission. http://gcc.gnu.org/wiki/DebugFission
Running gdb/testsuite/gdb.dwarf2/dw2-inheritance.exp ...
-PASS: gdb.dwarf2/dw2-inheritance.exp: ptype inherited
+ERROR: couldn't load /unsafegdb/testsuite.unix.-m32/gdb.dwarf2/dw2-inheritance.x into /unsafegdb/testsuite.unix.-m32/../../gdb/gdb (end of file).
+ERROR: Couldn't send ptype inherited to GDB.
+UNRESOLVED: gdb.dwarf2/dw2-inheritance.exp: ptype inherited
Program terminated with signal 11, Segmentation fault.
#0 0x000000000063037c in dwarf_decode_line_header (offset=0, cu=0x2c4b410) at dwarf2read.c:12320
12320 abfd = section->asection->owner;
(gdb) p section->asection
$2 = (asection *) 0x0
(gdb) bt
#0 0x000000000063037c in dwarf_decode_line_header (offset=0, cu=0x2c4b410) at dwarf2read.c:12320
#1 0x000000000061c354 in dwarf2_build_include_psymtabs (cu=0x2c4b410, die=0x2c4b5d0, pst=0x2c2d810) at dwarf2read.c:3324
#2 0x000000000061e46b in process_psymtab_comp_unit_reader (reader=0x7fff3fa1ac90, info_ptr=0x2c2d777 "\003base", comp_unit_die=0x2c4b5d0, has_children=1,
data=0x0) at dwarf2read.c:4159
#3 0x000000000061dc53 in init_and_read_dies_worker (this_cu=0x2c2d7a0, use_existing_cu=0, keep=0, die_reader_func=
0x61e036 <process_psymtab_comp_unit_reader>, data=0x0) at dwarf2read.c:3895
#4 0x000000000061dd12 in init_cu_and_read_dies (this_cu=0x2c2d7a0, use_existing_cu=0, keep=0, die_reader_func=0x61e036 <process_psymtab_comp_unit_reader>,
data=0x0) at dwarf2read.c:3936
#5 0x000000000061e4f9 in process_psymtab_comp_unit (this_cu=0x2c2d7a0) at dwarf2read.c:4178
#6 0x000000000061e726 in dwarf2_build_psymtabs_hard (objfile=0x2c386d0) at dwarf2read.c:4269
#7 0x000000000061bca2 in dwarf2_build_psymtabs (objfile=0x2c386d0) at dwarf2read.c:3133
#8 0x0000000000508db2 in read_psyms (objfile=0x2c386d0) at elfread.c:1449
#9 0x000000000058f9be in require_partial_symbols (objfile=0x2c386d0, verbose=0) at psymtab.c:92
It happens on RHEL-6 i386/x86_68/x86_64-m32. Feel free to request more info.
Regards,
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff]
2012-04-29 9:05 ` Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff] Jan Kratochvil
@ 2012-04-30 0:06 ` Doug Evans
2012-04-30 2:07 ` Jan Kratochvil
0 siblings, 1 reply; 12+ messages in thread
From: Doug Evans @ 2012-04-30 0:06 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, tromey, ccoutant, saugustine
[-- Attachment #1: Type: text/plain, Size: 2907 bytes --]
On Sun, Apr 29, 2012 at 1:57 AM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
> On Wed, 18 Apr 2012 20:57:38 +0200, Doug Evans wrote:
>> 2012-04-18 Doug Evans <dje@google.com>
>>
>> Initial support for Fission. http://gcc.gnu.org/wiki/DebugFission
>
> Running gdb/testsuite/gdb.dwarf2/dw2-inheritance.exp ...
> -PASS: gdb.dwarf2/dw2-inheritance.exp: ptype inherited
> +ERROR: couldn't load /unsafegdb/testsuite.unix.-m32/gdb.dwarf2/dw2-inheritance.x into /unsafegdb/testsuite.unix.-m32/../../gdb/gdb (end of file).
> +ERROR: Couldn't send ptype inherited to GDB.
> +UNRESOLVED: gdb.dwarf2/dw2-inheritance.exp: ptype inherited
>
> Program terminated with signal 11, Segmentation fault.
> #0 0x000000000063037c in dwarf_decode_line_header (offset=0, cu=0x2c4b410) at dwarf2read.c:12320
> 12320 abfd = section->asection->owner;
> (gdb) p section->asection
> $2 = (asection *) 0x0
> (gdb) bt
> #0 0x000000000063037c in dwarf_decode_line_header (offset=0, cu=0x2c4b410) at dwarf2read.c:12320
> #1 0x000000000061c354 in dwarf2_build_include_psymtabs (cu=0x2c4b410, die=0x2c4b5d0, pst=0x2c2d810) at dwarf2read.c:3324
> #2 0x000000000061e46b in process_psymtab_comp_unit_reader (reader=0x7fff3fa1ac90, info_ptr=0x2c2d777 "\003base", comp_unit_die=0x2c4b5d0, has_children=1,
> data=0x0) at dwarf2read.c:4159
> #3 0x000000000061dc53 in init_and_read_dies_worker (this_cu=0x2c2d7a0, use_existing_cu=0, keep=0, die_reader_func=
> 0x61e036 <process_psymtab_comp_unit_reader>, data=0x0) at dwarf2read.c:3895
> #4 0x000000000061dd12 in init_cu_and_read_dies (this_cu=0x2c2d7a0, use_existing_cu=0, keep=0, die_reader_func=0x61e036 <process_psymtab_comp_unit_reader>,
> data=0x0) at dwarf2read.c:3936
> #5 0x000000000061e4f9 in process_psymtab_comp_unit (this_cu=0x2c2d7a0) at dwarf2read.c:4178
> #6 0x000000000061e726 in dwarf2_build_psymtabs_hard (objfile=0x2c386d0) at dwarf2read.c:4269
> #7 0x000000000061bca2 in dwarf2_build_psymtabs (objfile=0x2c386d0) at dwarf2read.c:3133
> #8 0x0000000000508db2 in read_psyms (objfile=0x2c386d0) at elfread.c:1449
> #9 0x000000000058f9be in require_partial_symbols (objfile=0x2c386d0, verbose=0) at psymtab.c:92
>
> It happens on RHEL-6 i386/x86_68/x86_64-m32. Feel free to request more info.
>
>
> Regards,
> Jan
Hi.
I can't recreate this on my fc16 box (neither i386 nor amd64), but the
it's easy enough to see what the issue is.
Can you test this patch? Regression tested here.
It also fixes a potential segv in dwarf_decode_macros.
2012-04-29 Doug Evans <dje@seba.sebabeach.org>
* dwarf2read.c (dwarf_decode_macros): New arg section_name.
All callers updated.
(init_cu_die_reader): Verify the section is non-empty.
(dwarf_decode_line_header): Don't dereference section->asection
until we know the section is present. Return NULL, not 0.
[-- Attachment #2: gdb-120429-fission-supplement-3-1.patch.txt --]
[-- Type: text/plain, Size: 3582 bytes --]
2012-04-29 Doug Evans <dje@seba.sebabeach.org>
* dwarf2read.c (dwarf_decode_macros): New arg section_name.
All callers updated.
(init_cu_die_reader): Verify the section is non-empty.
(dwarf_decode_line_header): Don't dereference section->asection
until we know the section is present. Return NULL, not 0.
Index: dwarf2read.c
===================================================================
RCS file: /cvs/src/src/gdb/dwarf2read.c,v
retrieving revision 1.644
diff -u -p -r1.644 dwarf2read.c
--- dwarf2read.c 28 Apr 2012 23:22:13 -0000 1.644
+++ dwarf2read.c 29 Apr 2012 22:13:16 -0000
@@ -1317,7 +1317,7 @@ static struct die_info *dwarf_alloc_die
static void dwarf_decode_macros (struct line_header *, unsigned int,
char *, bfd *, struct dwarf2_cu *,
struct dwarf2_section_info *,
- int);
+ int, const char *);
static int attr_form_is_block (struct attribute *);
@@ -1671,7 +1671,8 @@ zlib_decompress_section (struct objfile
#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)
@@ -3588,7 +3589,7 @@ init_cu_die_reader (struct die_reader_sp
struct dwarf2_section_info *section,
struct dwo_file *dwo_file)
{
- gdb_assert (section->readin);
+ gdb_assert (section->readin && section->buffer != NULL);
reader->abfd = section->asection->owner;
reader->cu = cu;
reader->dwo_file = dwo_file;
@@ -6354,7 +6355,8 @@ read_file_scope (struct die_info *die, s
dwarf_decode_macros (cu->line_header, DW_UNSND (attr),
comp_dir, abfd, cu,
- &dwarf2_per_objfile->macro, 1);
+ &dwarf2_per_objfile->macro, 1,
+ ".debug_macro");
}
else
{
@@ -6365,7 +6367,8 @@ read_file_scope (struct die_info *die, s
dwarf_decode_macros (cu->line_header, macro_offset,
comp_dir, abfd, cu,
- &dwarf2_per_objfile->macinfo, 0);
+ &dwarf2_per_objfile->macinfo, 0,
+ ".debug_macinfo");
}
}
@@ -12317,7 +12320,6 @@ dwarf_decode_line_header (unsigned int o
section = &cu->dwo_unit->dwo_file->sections.line;
else
section = &dwarf2_per_objfile->line;
- abfd = section->asection->owner;
dwarf2_read_section (dwarf2_per_objfile->objfile, section);
if (section->buffer == NULL)
@@ -12329,6 +12331,10 @@ dwarf_decode_line_header (unsigned int o
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 >= section->size)
@@ -16894,7 +16900,7 @@ dwarf_decode_macros (struct line_header
char *comp_dir, bfd *abfd,
struct dwarf2_cu *cu,
struct dwarf2_section_info *section,
- int section_is_gnu)
+ int section_is_gnu, const char *section_name)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
gdb_byte *mac_ptr, *mac_end;
@@ -16909,8 +16915,7 @@ dwarf_decode_macros (struct line_header
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;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff]
2012-04-30 0:06 ` Doug Evans
@ 2012-04-30 2:07 ` Jan Kratochvil
2012-04-30 14:30 ` Doug Evans
0 siblings, 1 reply; 12+ messages in thread
From: Jan Kratochvil @ 2012-04-30 2:07 UTC (permalink / raw)
To: Doug Evans; +Cc: gdb-patches, tromey, ccoutant, saugustine
On Mon, 30 Apr 2012 01:21:18 +0200, Doug Evans wrote:
> I can't recreate this on my fc16 box (neither i386 nor amd64),
FYI in fact the regression was on CentOS-6 (and not real RHEL-6).
> Can you test this patch? Regression tested here.
Yes, it fixes the regression for me.
Thanks,
Jan
> 2012-04-29 Doug Evans <dje@seba.sebabeach.org>
FYI
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff]
2012-04-30 2:07 ` Jan Kratochvil
@ 2012-04-30 14:30 ` Doug Evans
0 siblings, 0 replies; 12+ messages in thread
From: Doug Evans @ 2012-04-30 14:30 UTC (permalink / raw)
To: Jan Kratochvil; +Cc: gdb-patches, tromey, ccoutant, saugustine
On Sun, Apr 29, 2012 at 7:05 PM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
>> 2012-04-29 Doug Evans <dje@seba.sebabeach.org>
>
> FYI
Hey, it's my fc16 box. :-)
[I was going to change the email address when committing it, but now
maybe I won't. 1/2 :-)]
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2012-04-30 2:07 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-18 19:12 [RFA 3/3] Initial Fission support, the actual Fission stuff Doug Evans
2012-04-19 5:07 ` Doug Evans
2012-04-27 18:29 ` Tom Tromey
2012-04-19 10:25 ` Yao Qi
2012-04-19 15:28 ` Doug Evans
2012-04-27 18:38 ` Tom Tromey
2012-04-27 18:20 ` Tom Tromey
2012-04-28 23:59 ` Doug Evans
2012-04-29 9:05 ` Crash regression for gdb.dwarf2/dw2-inheritance.exp [Re: [RFA 3/3] Initial Fission support, the actual Fission stuff] Jan Kratochvil
2012-04-30 0:06 ` Doug Evans
2012-04-30 2:07 ` Jan Kratochvil
2012-04-30 14:30 ` Doug Evans
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox