* dwarf2read.c (struct dwarf2_per_objfile) <dwz_file>: New field.

(struct dwarf2_per_cu_data) <length>: No longer bitfield.
	<is_dwz>: New field.
	(struct dwz_file): New.
	(struct partial_die_info) <is_dwz, spec_is_dwz>: New fields.
	(locate_dwz_sections, dwarf2_get_dwz_file)
	(get_abbrev_section_for_cu): New functions.
	(error_check_comp_unit_head, read_and_check_comp_unit_head)
	(read_and_check_type_unit_head): Add abbrev_section argument.
	(create_debug_types_hash_table): Update.
	(init_cutu_and_read_dies): Use proper abbrev section.
	(init_cutu_and_read_dies_no_follow): Likewise.
	(set_partial_user): Do nothing if PST==NULL.
	(read_comp_units_from_section): New function.
	(create_all_comp_units): Use it.
	(scan_partial_symbols, partial_die_parent_scope): Update.
	(skip_one_die): Handle DW_FORM_GNU_ref_alt, DW_FORM_GNU_strp_alt.
	(process_imported_unit_die, read_partial_die): Handle .dwz files.
	(find_partial_die): Add offset_in_dwz argument.  Update.
	(guess_partial_die_structure_name, fixup_partial_die): Update.
	(read_attribute_value): Handle DW_FORM_GNU_ref_alt,
	DW_FORM_GNU_strp_alt.
	(read_indirect_string_from_dwz): New function.
	(dwarf2_const_value_attr): Handle DW_FORM_GNU_strp_alt.
	(dump_die_shallow): Handle DW_FORM_GNU_ref_alt, DW_FORM_GNU_strp_alt.
	(is_ref_attr): Handle DW_FORM_GNU_ref_alt.
	(follow_die_offset): Add offset_in_dwz argument.
	(follow_die_ref, dwarf2_fetch_die_location_block): Update.
	(skip_form_bytes): Handle DW_FORM_GNU_strp_alt.
	(dwarf_decode_macro_bytes): Add section_is_dwz argument.
	Handle new macro forms.
	(dwarf_decode_macros): Update.
	(dwarf2_find_containing_comp_unit): Add offset_in_dwz argument.
	(dwarf2_per_objfile_free): Unref dwz_bfd, if it exists
	(lookup_die_type): Handle DW_FORM_GNU_ref_alt.
	(create_debug_types_hash_table): Use correct abbrev section.
	(get_debug_line_section): New function.
	(dwarf_decode_line_header, dwarf_decode_lines_1): Use it.
	(process_full_comp_unit): Pass 'required' argument to
	end_symtab_get_static_block.
	* buildsym.h (end_symtab_get_static_block): Update.
	* buildsym.c (end_symtab_get_static_block): Add 'required'
	argument.
	(end_symtab, end_expandable_symtab): Update.
This commit is contained in:
Tom Tromey 2012-07-18 19:59:35 +00:00
parent 4bf44c1cf1
commit 3658672899
4 changed files with 477 additions and 92 deletions

View File

@ -1,3 +1,50 @@
2012-07-18 Tom Tromey <tromey@redhat.com>
* dwarf2read.c (struct dwarf2_per_objfile) <dwz_file>: New field.
(struct dwarf2_per_cu_data) <length>: No longer bitfield.
<is_dwz>: New field.
(struct dwz_file): New.
(struct partial_die_info) <is_dwz, spec_is_dwz>: New fields.
(locate_dwz_sections, dwarf2_get_dwz_file)
(get_abbrev_section_for_cu): New functions.
(error_check_comp_unit_head, read_and_check_comp_unit_head)
(read_and_check_type_unit_head): Add abbrev_section argument.
(create_debug_types_hash_table): Update.
(init_cutu_and_read_dies): Use proper abbrev section.
(init_cutu_and_read_dies_no_follow): Likewise.
(set_partial_user): Do nothing if PST==NULL.
(read_comp_units_from_section): New function.
(create_all_comp_units): Use it.
(scan_partial_symbols, partial_die_parent_scope): Update.
(skip_one_die): Handle DW_FORM_GNU_ref_alt, DW_FORM_GNU_strp_alt.
(process_imported_unit_die, read_partial_die): Handle .dwz files.
(find_partial_die): Add offset_in_dwz argument. Update.
(guess_partial_die_structure_name, fixup_partial_die): Update.
(read_attribute_value): Handle DW_FORM_GNU_ref_alt,
DW_FORM_GNU_strp_alt.
(read_indirect_string_from_dwz): New function.
(dwarf2_const_value_attr): Handle DW_FORM_GNU_strp_alt.
(dump_die_shallow): Handle DW_FORM_GNU_ref_alt, DW_FORM_GNU_strp_alt.
(is_ref_attr): Handle DW_FORM_GNU_ref_alt.
(follow_die_offset): Add offset_in_dwz argument.
(follow_die_ref, dwarf2_fetch_die_location_block): Update.
(skip_form_bytes): Handle DW_FORM_GNU_strp_alt.
(dwarf_decode_macro_bytes): Add section_is_dwz argument.
Handle new macro forms.
(dwarf_decode_macros): Update.
(dwarf2_find_containing_comp_unit): Add offset_in_dwz argument.
(dwarf2_per_objfile_free): Unref dwz_bfd, if it exists
(lookup_die_type): Handle DW_FORM_GNU_ref_alt.
(create_debug_types_hash_table): Use correct abbrev section.
(get_debug_line_section): New function.
(dwarf_decode_line_header, dwarf_decode_lines_1): Use it.
(process_full_comp_unit): Pass 'required' argument to
end_symtab_get_static_block.
* buildsym.h (end_symtab_get_static_block): Update.
* buildsym.c (end_symtab_get_static_block): Add 'required'
argument.
(end_symtab, end_expandable_symtab): Update.
2012-07-18 Tom Tromey <tromey@redhat.com>
* dwarf2read.c: Don't include zlib.h or sys/mman.h.

View File

@ -966,11 +966,14 @@ reset_symtab_globals (void)
file's text.
If EXPANDABLE is non-zero the STATIC_BLOCK dictionary is made
expandable. */
expandable.
If REQUIRED is non-zero, then a symtab is created even if it does
not contain any symbols. */
struct block *
end_symtab_get_static_block (CORE_ADDR end_addr, struct objfile *objfile,
int expandable)
int expandable, int required)
{
/* Finish the lexical context of the last function in the file; pop
the context stack. */
@ -1038,7 +1041,8 @@ end_symtab_get_static_block (CORE_ADDR end_addr, struct objfile *objfile,
cleanup_undefined_stabs_types (objfile);
finish_global_stabs (objfile);
if (pending_blocks == NULL
if (!required
&& pending_blocks == NULL
&& file_symbols == NULL
&& global_symbols == NULL
&& have_line_numbers == 0
@ -1296,7 +1300,7 @@ end_symtab (CORE_ADDR end_addr, struct objfile *objfile, int section)
{
struct block *static_block;
static_block = end_symtab_get_static_block (end_addr, objfile, 0);
static_block = end_symtab_get_static_block (end_addr, objfile, 0, 0);
return end_symtab_from_static_block (static_block, objfile, section, 0);
}
@ -1308,7 +1312,7 @@ end_expandable_symtab (CORE_ADDR end_addr, struct objfile *objfile,
{
struct block *static_block;
static_block = end_symtab_get_static_block (end_addr, objfile, 1);
static_block = end_symtab_get_static_block (end_addr, objfile, 1, 0);
return end_symtab_from_static_block (static_block, objfile, section, 1);
}

View File

@ -260,7 +260,8 @@ extern char *pop_subfile (void);
extern struct block *end_symtab_get_static_block (CORE_ADDR end_addr,
struct objfile *objfile,
int expandable);
int expandable,
int required);
extern struct symtab *end_symtab_from_static_block (struct block *static_block,
struct objfile *objfile,

View File

@ -233,6 +233,10 @@ struct dwarf2_per_objfile
This is NULL if the table hasn't been allocated yet. */
htab_t dwo_files;
/* The shared '.dwz' file, if one exists. This is used when the
original data was compressed using 'dwz -m'. */
struct dwz_file *dwz_file;
/* A flag indicating wether this objfile has a section loaded at a
VMA of 0. */
int has_section_at_zero;
@ -491,15 +495,13 @@ struct dwarf2_cu
struct dwarf2_per_cu_data
{
/* The start offset and length of this compilation unit. 2**29-1
bytes should suffice to store the length of any compilation unit
- if it doesn't, GDB will fall over anyway.
/* The start offset and length of this compilation unit.
NOTE: Unlike comp_unit_head.length, this length includes
initial_length_size.
If the DIE refers to a DWO file, this is always of the original die,
not the DWO file. */
sect_offset offset;
unsigned int length : 29;
unsigned int length;
/* Flag indicating this compilation unit will be read in before
any of the current compilation units are processed. */
@ -514,6 +516,9 @@ struct dwarf2_per_cu_data
/* Non-zero if this CU is from .debug_types. */
unsigned int is_debug_types : 1;
/* Non-zero if this CU is from the .dwz file. */
unsigned int is_dwz : 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. */
@ -701,6 +706,21 @@ struct dwo_file
htab_t tus;
};
/* This represents a '.dwz' file. */
struct dwz_file
{
/* A dwz file can only contain a few sections. */
struct dwarf2_section_info abbrev;
struct dwarf2_section_info info;
struct dwarf2_section_info str;
struct dwarf2_section_info line;
struct dwarf2_section_info macro;
/* The dwz's BFD. */
bfd *dwz_bfd;
};
/* 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
@ -814,6 +834,12 @@ struct partial_die_info
/* Flag set if fixup_partial_die has been called on this die. */
unsigned int fixup_called : 1;
/* Flag set if DW_TAG_imported_unit uses DW_FORM_GNU_ref_alt. */
unsigned int is_dwz : 1;
/* Flag set if spec_offset uses DW_FORM_GNU_ref_alt. */
unsigned int spec_is_dwz : 1;
/* The name of this DIE. Normally the value of DW_AT_name, but
sometimes a default name for unnamed DIEs. */
char *name;
@ -1199,7 +1225,7 @@ static gdb_byte *read_partial_die (const struct die_reader_specs *,
unsigned int,
gdb_byte *);
static struct partial_die_info *find_partial_die (sect_offset,
static struct partial_die_info *find_partial_die (sect_offset, int,
struct dwarf2_cu *);
static void fixup_partial_die (struct partial_die_info *,
@ -1244,6 +1270,8 @@ static char *read_indirect_string (bfd *, gdb_byte *,
const struct comp_unit_head *,
unsigned int *);
static char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
static ULONGEST read_unsigned_leb128 (bfd *, gdb_byte *, unsigned int *);
static LONGEST read_signed_leb128 (bfd *, gdb_byte *, unsigned int *);
@ -1510,7 +1538,7 @@ static hashval_t partial_die_hash (const void *item);
static int partial_die_eq (const void *item_lhs, const void *item_rhs);
static struct dwarf2_per_cu_data *dwarf2_find_containing_comp_unit
(sect_offset offset, struct objfile *objfile);
(sect_offset offset, unsigned int offset_in_dwz, struct objfile *objfile);
static void init_one_comp_unit (struct dwarf2_cu *cu,
struct dwarf2_per_cu_data *per_cu);
@ -1573,6 +1601,12 @@ static void find_file_and_directory (struct die_info *die,
static char *file_full_name (int file, struct line_header *lh,
const char *comp_dir);
static gdb_byte *read_and_check_comp_unit_head
(struct comp_unit_head *header,
struct dwarf2_section_info *section,
struct dwarf2_section_info *abbrev_section, gdb_byte *info_ptr,
int is_debug_types_section);
static void init_cutu_and_read_dies
(struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table,
int use_existing_cu, int keep,
@ -1885,6 +1919,106 @@ dwarf2_get_section_info (struct objfile *objfile,
*sizep = info->size;
}
/* A helper function to find the sections for a .dwz file. */
static void
locate_dwz_sections (bfd *abfd, asection *sectp, void *arg)
{
struct dwz_file *dwz_file = arg;
/* Note that we only support the standard ELF names, because .dwz
is ELF-only (at the time of writing). */
if (section_is_p (sectp->name, &dwarf2_elf_names.abbrev))
{
dwz_file->abbrev.asection = sectp;
dwz_file->abbrev.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.info))
{
dwz_file->info.asection = sectp;
dwz_file->info.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.str))
{
dwz_file->str.asection = sectp;
dwz_file->str.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.line))
{
dwz_file->line.asection = sectp;
dwz_file->line.size = bfd_get_section_size (sectp);
}
else if (section_is_p (sectp->name, &dwarf2_elf_names.macro))
{
dwz_file->macro.asection = sectp;
dwz_file->macro.size = bfd_get_section_size (sectp);
}
}
/* Open the separate '.dwz' debug file, if needed. Error if the file
cannot be found. */
static struct dwz_file *
dwarf2_get_dwz_file (void)
{
bfd *abfd, *dwz_bfd;
asection *section;
gdb_byte *data;
struct cleanup *cleanup;
const char *filename;
struct dwz_file *result;
if (dwarf2_per_objfile->dwz_file != NULL)
return dwarf2_per_objfile->dwz_file;
abfd = dwarf2_per_objfile->objfile->obfd;
section = bfd_get_section_by_name (abfd, ".gnu_debugaltlink");
if (section == NULL)
error (_("could not find '.gnu_debugaltlink' section"));
if (!bfd_malloc_and_get_section (abfd, section, &data))
error (_("could not read '.gnu_debugaltlink' section: %s"),
bfd_errmsg (bfd_get_error ()));
cleanup = make_cleanup (xfree, data);
filename = data;
if (!IS_ABSOLUTE_PATH (filename))
{
char *abs = gdb_realpath (dwarf2_per_objfile->objfile->name);
char *rel;
make_cleanup (xfree, abs);
abs = ldirname (abs);
make_cleanup (xfree, abs);
rel = concat (abs, SLASH_STRING, filename, (char *) NULL);
make_cleanup (xfree, rel);
filename = rel;
}
/* The format is just a NUL-terminated file name, followed by the
build-id. For now, though, we ignore the build-id. */
dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
if (dwz_bfd == NULL)
error (_("could not read '%s': %s"), filename,
bfd_errmsg (bfd_get_error ()));
if (!bfd_check_format (dwz_bfd, bfd_object))
{
gdb_bfd_unref (dwz_bfd);
error (_("file '%s' was not usable: %s"), filename,
bfd_errmsg (bfd_get_error ()));
}
result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
struct dwz_file);
result->dwz_bfd = dwz_bfd;
bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result);
do_cleanups (cleanup);
return result;
}
/* DWARF quick_symbols_functions support. */
@ -3560,6 +3694,22 @@ read_comp_unit_head (struct comp_unit_head *cu_header,
return info_ptr;
}
/* Helper function that returns the proper abbrev section for
THIS_CU. */
static struct dwarf2_section_info *
get_abbrev_section_for_cu (struct dwarf2_per_cu_data *this_cu)
{
struct dwarf2_section_info *abbrev;
if (this_cu->is_dwz)
abbrev = &dwarf2_get_dwz_file ()->abbrev;
else
abbrev = &dwarf2_per_objfile->abbrev;
return abbrev;
}
/* Subroutine of read_and_check_comp_unit_head and
read_and_check_type_unit_head to simplify them.
Perform various error checking on the header. */
@ -3578,8 +3728,7 @@ error_check_comp_unit_head (struct comp_unit_head *header,
filename);
if (header->abbrev_offset.sect_off
>= dwarf2_section_size (dwarf2_per_objfile->objfile,
&dwarf2_per_objfile->abbrev))
>= dwarf2_section_size (dwarf2_per_objfile->objfile, abbrev_section))
error (_("Dwarf Error: bad offset (0x%lx) in compilation unit header "
"(offset 0x%lx + 6) [in module %s]"),
(long) header->abbrev_offset.sect_off, (long) header->offset.sect_off,
@ -3816,6 +3965,7 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
{
bfd *abfd;
gdb_byte *info_ptr, *end_ptr;
struct dwarf2_section_info *abbrev_section;
dwarf2_read_section (objfile, section);
info_ptr = section->buffer;
@ -3827,6 +3977,11 @@ create_debug_types_hash_table (struct dwo_file *dwo_file,
not present, in which case section->asection will be NULL. */
abfd = section->asection->owner;
if (dwo_file)
abbrev_section = &dwo_file->sections.abbrev;
else
abbrev_section = &dwarf2_per_objfile->abbrev;
if (types_htab == NULL)
{
if (dwo_file)
@ -4066,7 +4221,8 @@ init_cutu_and_read_dies (struct dwarf2_per_cu_data *this_cu,
dwarf2_read_section (objfile, section);
begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
abbrev_section = &dwarf2_per_objfile->abbrev;
abbrev_section = get_abbrev_section_for_cu (this_cu);
if (use_existing_cu && this_cu->cu != NULL)
{
@ -4448,7 +4604,7 @@ init_cutu_and_read_dies_simple (struct dwarf2_per_cu_data *this_cu,
void *data)
{
init_cutu_and_read_dies_no_follow (this_cu,
&dwarf2_per_objfile->abbrev,
get_abbrev_section_for_cu (this_cu),
NULL,
die_reader_func, data);
}
@ -5076,6 +5232,9 @@ set_partial_user (struct objfile *objfile)
struct partial_symtab *pst = per_cu->v.psymtab;
int j;
if (pst == NULL)
continue;
for (j = 0; j < pst->number_of_dependencies; ++j)
{
/* Set the 'user' field only if it is not already set. */
@ -5170,6 +5329,57 @@ load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
load_partial_comp_unit_reader, NULL);
}
static void
read_comp_units_from_section (struct objfile *objfile,
struct dwarf2_section_info *section,
unsigned int is_dwz,
int *n_allocated,
int *n_comp_units,
struct dwarf2_per_cu_data ***all_comp_units)
{
gdb_byte *info_ptr;
bfd *abfd = section->asection->owner;
dwarf2_read_section (objfile, section);
info_ptr = section->buffer;
while (info_ptr < section->buffer + section->size)
{
unsigned int length, initial_length_size;
struct dwarf2_per_cu_data *this_cu;
sect_offset offset;
offset.sect_off = info_ptr - section->buffer;
/* Read just enough information to find out where the next
compilation unit is. */
length = read_initial_length (abfd, info_ptr, &initial_length_size);
/* Save the compilation unit for later lookup. */
this_cu = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_per_cu_data));
memset (this_cu, 0, sizeof (*this_cu));
this_cu->offset = offset;
this_cu->length = length + initial_length_size;
this_cu->is_dwz = is_dwz;
this_cu->objfile = objfile;
this_cu->info_or_types_section = section;
if (*n_comp_units == *n_allocated)
{
*n_allocated *= 2;
*all_comp_units = xrealloc (*all_comp_units,
*n_allocated
* sizeof (struct dwarf2_per_cu_data *));
}
(*all_comp_units)[*n_comp_units] = this_cu;
++*n_comp_units;
info_ptr = info_ptr + this_cu->length;
}
}
/* Create a list of all compilation units in OBJFILE.
This is only done for -readnow and building partial symtabs. */
@ -5179,49 +5389,22 @@ create_all_comp_units (struct objfile *objfile)
int n_allocated;
int n_comp_units;
struct dwarf2_per_cu_data **all_comp_units;
gdb_byte *info_ptr;
dwarf2_read_section (objfile, &dwarf2_per_objfile->info);
info_ptr = dwarf2_per_objfile->info.buffer;
n_comp_units = 0;
n_allocated = 10;
all_comp_units = xmalloc (n_allocated
* sizeof (struct dwarf2_per_cu_data *));
while (info_ptr < dwarf2_per_objfile->info.buffer
+ dwarf2_per_objfile->info.size)
read_comp_units_from_section (objfile, &dwarf2_per_objfile->info, 0,
&n_allocated, &n_comp_units, &all_comp_units);
if (bfd_get_section_by_name (objfile->obfd, ".gnu_debugaltlink") != NULL)
{
unsigned int length, initial_length_size;
struct dwarf2_per_cu_data *this_cu;
sect_offset offset;
struct dwz_file *dwz = dwarf2_get_dwz_file ();
offset.sect_off = info_ptr - dwarf2_per_objfile->info.buffer;
/* Read just enough information to find out where the next
compilation unit is. */
length = read_initial_length (objfile->obfd, info_ptr,
&initial_length_size);
/* Save the compilation unit for later lookup. */
this_cu = obstack_alloc (&objfile->objfile_obstack,
sizeof (struct dwarf2_per_cu_data));
memset (this_cu, 0, sizeof (*this_cu));
this_cu->offset = offset;
this_cu->length = length + initial_length_size;
this_cu->objfile = objfile;
this_cu->info_or_types_section = &dwarf2_per_objfile->info;
if (n_comp_units == n_allocated)
{
n_allocated *= 2;
all_comp_units = xrealloc (all_comp_units,
n_allocated
* sizeof (struct dwarf2_per_cu_data *));
}
all_comp_units[n_comp_units++] = this_cu;
info_ptr = info_ptr + this_cu->length;
read_comp_units_from_section (objfile, &dwz->info, 1,
&n_allocated, &n_comp_units,
&all_comp_units);
}
dwarf2_per_objfile->all_comp_units
@ -5315,6 +5498,7 @@ scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
}
per_cu = dwarf2_find_containing_comp_unit (pdi->d.offset,
pdi->is_dwz,
cu->objfile);
/* Go read the partial unit, if needed. */
@ -5372,7 +5556,8 @@ partial_die_parent_scope (struct partial_die_info *pdi,
real_pdi = pdi;
while (real_pdi->has_specification)
real_pdi = find_partial_die (real_pdi->spec_offset, cu);
real_pdi = find_partial_die (real_pdi->spec_offset,
real_pdi->spec_is_dwz, cu);
parent = real_pdi->die_parent;
if (parent == NULL)
@ -5872,6 +6057,9 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
else
info_ptr += cu->header.offset_size;
break;
case DW_FORM_GNU_ref_alt:
info_ptr += cu->header.offset_size;
break;
case DW_FORM_addr:
info_ptr += cu->header.addr_size;
break;
@ -5901,6 +6089,7 @@ skip_one_die (const struct die_reader_specs *reader, gdb_byte *info_ptr,
break;
case DW_FORM_sec_offset:
case DW_FORM_strp:
case DW_FORM_GNU_strp_alt:
info_ptr += cu->header.offset_size;
break;
case DW_FORM_exprloc:
@ -6568,7 +6757,9 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu,
it, by scanning the DIE's below the compilation unit. */
get_scope_pc_bounds (cu->dies, &lowpc, &highpc, cu);
static_block = end_symtab_get_static_block (highpc + baseaddr, objfile, 0);
static_block
= end_symtab_get_static_block (highpc + baseaddr, objfile, 0,
per_cu->s.imported_symtabs != NULL);
/* If the comp unit has DW_AT_ranges, it may have discontiguous ranges.
Also, DW_AT_ranges may record ranges not belonging to any child DIEs
@ -6719,9 +6910,11 @@ process_imported_unit_die (struct die_info *die, struct dwarf2_cu *cu)
struct dwarf2_per_cu_data *per_cu;
struct symtab *imported_symtab;
sect_offset offset;
int is_dwz;
offset = dwarf2_get_ref_die_offset (attr);
per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
is_dwz = (attr->form == DW_FORM_GNU_ref_alt || cu->per_cu->is_dwz);
per_cu = dwarf2_find_containing_comp_unit (offset, is_dwz, cu->objfile);
/* Queue the unit, if needed. */
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
@ -12403,6 +12596,8 @@ read_partial_die (const struct die_reader_specs *reader,
case DW_AT_extension:
part_die->has_specification = 1;
part_die->spec_offset = dwarf2_get_ref_die_offset (&attr);
part_die->spec_is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz);
break;
case DW_AT_sibling:
/* Ignore absolute siblings, they might point outside of
@ -12449,7 +12644,11 @@ read_partial_die (const struct die_reader_specs *reader,
case DW_AT_import:
if (part_die->tag == DW_TAG_imported_unit)
part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
{
part_die->d.offset = dwarf2_get_ref_die_offset (&attr);
part_die->is_dwz = (attr.form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz);
}
break;
default:
@ -12520,13 +12719,14 @@ find_partial_die_in_comp_unit (sect_offset offset, struct dwarf2_cu *cu)
DW_FORM_ref_sig8). */
static struct partial_die_info *
find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
find_partial_die (sect_offset offset, int offset_in_dwz, struct dwarf2_cu *cu)
{
struct objfile *objfile = cu->objfile;
struct dwarf2_per_cu_data *per_cu = NULL;
struct partial_die_info *pd = NULL;
if (offset_in_cu_p (&cu->header, offset))
if (offset_in_dwz == cu->per_cu->is_dwz
&& offset_in_cu_p (&cu->header, offset))
{
pd = find_partial_die_in_comp_unit (offset, cu);
if (pd != NULL)
@ -12545,7 +12745,8 @@ find_partial_die (sect_offset offset, struct dwarf2_cu *cu)
(long) cu->header.offset.sect_off, (long) offset.sect_off,
bfd_get_filename (objfile->obfd));
}
per_cu = dwarf2_find_containing_comp_unit (offset, objfile);
per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
objfile);
if (per_cu->cu == NULL || per_cu->cu->partial_dies == NULL)
load_partial_comp_unit (per_cu);
@ -12603,7 +12804,8 @@ guess_partial_die_structure_name (struct partial_die_info *struct_pdi,
real_pdi = struct_pdi;
while (real_pdi->has_specification)
real_pdi = find_partial_die (real_pdi->spec_offset, cu);
real_pdi = find_partial_die (real_pdi->spec_offset,
real_pdi->spec_is_dwz, cu);
if (real_pdi->die_parent != NULL)
return;
@ -12651,7 +12853,8 @@ fixup_partial_die (struct partial_die_info *part_die,
{
struct partial_die_info *spec_die;
spec_die = find_partial_die (part_die->spec_offset, cu);
spec_die = find_partial_die (part_die->spec_offset,
part_die->spec_is_dwz, cu);
fixup_partial_die (spec_die, cu);
@ -12739,6 +12942,10 @@ read_attribute_value (const struct die_reader_specs *reader,
&cu->header, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_GNU_ref_alt:
DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_addr:
DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
info_ptr += bytes_read;
@ -12781,10 +12988,25 @@ read_attribute_value (const struct die_reader_specs *reader,
info_ptr += bytes_read;
break;
case DW_FORM_strp:
DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
&bytes_read);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
if (!cu->per_cu->is_dwz)
{
DW_STRING (attr) = read_indirect_string (abfd, info_ptr, cu_header,
&bytes_read);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
break;
}
/* FALLTHROUGH */
case DW_FORM_GNU_strp_alt:
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
LONGEST str_offset = read_offset (abfd, info_ptr, cu_header,
&bytes_read);
DW_STRING (attr) = read_indirect_string_from_dwz (dwz, str_offset);
DW_STRING_IS_CANONICAL (attr) = 0;
info_ptr += bytes_read;
}
break;
case DW_FORM_exprloc:
case DW_FORM_block:
@ -12896,6 +13118,10 @@ read_attribute_value (const struct die_reader_specs *reader,
bfd_get_filename (abfd));
}
/* Super hack. */
if (cu->per_cu->is_dwz && is_ref_attr (attr))
attr->form = DW_FORM_GNU_ref_alt;
/* We have seen instances where the compiler tried to emit a byte
size attribute of -1 which ended up being encoded as an unsigned
0xffffffff. Although 0xffffffff is technically a valid size value,
@ -13192,6 +13418,30 @@ read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
return (char *) (dwarf2_per_objfile->str.buffer + str_offset);
}
/* Read a string at offset STR_OFFSET in the .debug_str section from
the .dwz file DWZ. Throw an error if the offset is too large. If
the string consists of a single NUL byte, return NULL; otherwise
return a pointer to the string. */
static char *
read_indirect_string_from_dwz (struct dwz_file *dwz, LONGEST str_offset)
{
dwarf2_read_section (dwarf2_per_objfile->objfile, &dwz->str);
if (dwz->str.buffer == NULL)
error (_("DW_FORM_GNU_strp_alt used without .debug_str "
"section [in module %s]"),
bfd_get_filename (dwz->dwz_bfd));
if (str_offset >= dwz->str.size)
error (_("DW_FORM_GNU_strp_alt pointing outside of "
".debug_str section [in module %s]"),
bfd_get_filename (dwz->dwz_bfd));
gdb_assert (HOST_CHAR_BIT == 8);
if (dwz->str.buffer[str_offset] == '\0')
return NULL;
return (char *) (dwz->str.buffer + str_offset);
}
static char *
read_indirect_string (bfd *abfd, gdb_byte *buf,
const struct comp_unit_head *cu_header,
@ -13663,6 +13913,30 @@ add_file_name (struct line_header *lh,
fe->symtab = NULL;
}
/* A convenience function to find the proper .debug_line section for a
CU. */
static struct dwarf2_section_info *
get_debug_line_section (struct dwarf2_cu *cu)
{
struct dwarf2_section_info *section;
/* 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 if (cu->per_cu->is_dwz)
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
section = &dwz->line;
}
else
section = &dwarf2_per_objfile->line;
return section;
}
/* Read the statement program header starting at OFFSET in
.debug_line, or .debug_line.dwo. Return a pointer
to a struct line_header, allocated using xmalloc.
@ -13683,13 +13957,7 @@ dwarf_decode_line_header (unsigned int offset, struct dwarf2_cu *cu)
struct dwarf2_section_info *section;
bfd *abfd;
/* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
DWO file. */
if (cu->dwo_unit && cu->per_cu->is_debug_types)
section = &cu->dwo_unit->dwo_file->sections.line;
else
section = &dwarf2_per_objfile->line;
section = get_debug_line_section (cu);
dwarf2_read_section (dwarf2_per_objfile->objfile, section);
if (section->buffer == NULL)
{
@ -14014,7 +14282,7 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
GCd by the linker. Ignore it. PR gdb/12528 */
long line_offset
= line_ptr - dwarf2_per_objfile->line.buffer;
= line_ptr - get_debug_line_section (cu)->buffer;
complaint (&symfile_complaints,
_(".debug_line address at offset 0x%lx is 0 "
@ -14860,6 +15128,7 @@ dwarf2_const_value_attr (struct attribute *attr, struct type *type,
case DW_FORM_string:
case DW_FORM_strp:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
/* DW_STRING is already allocated on the objfile obstack, point
directly to it. */
*bytes = (gdb_byte *) DW_STRING (attr);
@ -15046,7 +15315,15 @@ lookup_die_type (struct die_info *die, struct attribute *attr,
/* First see if we have it cached. */
if (is_ref_attr (attr))
if (attr->form == DW_FORM_GNU_ref_alt)
{
struct dwarf2_per_cu_data *per_cu;
sect_offset offset = dwarf2_get_ref_die_offset (attr);
per_cu = dwarf2_find_containing_comp_unit (offset, 1, cu->objfile);
this_type = get_die_type_at_offset (offset, per_cu);
}
else if (is_ref_attr (attr))
{
sect_offset offset = dwarf2_get_ref_die_offset (attr);
@ -15819,6 +16096,10 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
fprintf_unfiltered (f, "ref address: ");
fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
break;
case DW_FORM_GNU_ref_alt:
fprintf_unfiltered (f, "alt ref address: ");
fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
break;
case DW_FORM_ref1:
case DW_FORM_ref2:
case DW_FORM_ref4:
@ -15850,6 +16131,7 @@ dump_die_shallow (struct ui_file *f, int indent, struct die_info *die)
case DW_FORM_string:
case DW_FORM_strp:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
DW_STRING (&die->attrs[i])
? DW_STRING (&die->attrs[i]) : "",
@ -15953,6 +16235,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_alt:
return 1;
default:
return 0;
@ -16030,7 +16313,8 @@ follow_die_ref_or_sig (struct die_info *src_die, struct attribute *attr,
Returns NULL if OFFSET is invalid. */
static struct die_info *
follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
follow_die_offset (sect_offset offset, int offset_in_dwz,
struct dwarf2_cu **ref_cu)
{
struct die_info temp_die;
struct dwarf2_cu *target_cu, *cu = *ref_cu;
@ -16047,11 +16331,13 @@ follow_die_offset (sect_offset offset, struct dwarf2_cu **ref_cu)
if (! offset_in_cu_p (&cu->header, offset))
return NULL;
}
else if (! offset_in_cu_p (&cu->header, offset))
else if (offset_in_dwz != cu->per_cu->is_dwz
|| ! offset_in_cu_p (&cu->header, offset))
{
struct dwarf2_per_cu_data *per_cu;
per_cu = dwarf2_find_containing_comp_unit (offset, cu->objfile);
per_cu = dwarf2_find_containing_comp_unit (offset, offset_in_dwz,
cu->objfile);
/* If necessary, add it to the queue and load its DIEs. */
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
@ -16083,7 +16369,10 @@ follow_die_ref (struct die_info *src_die, struct attribute *attr,
struct dwarf2_cu *cu = *ref_cu;
struct die_info *die;
die = follow_die_offset (offset, ref_cu);
die = follow_die_offset (offset,
(attr->form == DW_FORM_GNU_ref_alt
|| cu->per_cu->is_dwz),
ref_cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced from DIE "
"at 0x%x [in module %s]"),
@ -16114,7 +16403,7 @@ dwarf2_fetch_die_location_block (cu_offset offset_in_cu,
load_cu (per_cu);
cu = per_cu->cu;
die = follow_die_offset (offset, &cu);
die = follow_die_offset (offset, per_cu->is_dwz, &cu);
if (!die)
error (_("Dwarf Error: Cannot find DIE at 0x%x referenced in module %s"),
offset.sect_off, per_cu->objfile->name);
@ -16908,6 +17197,7 @@ skip_form_bytes (bfd *abfd, gdb_byte *bytes, gdb_byte *buffer_end,
case DW_FORM_sec_offset:
case DW_FORM_strp:
case DW_FORM_GNU_strp_alt:
bytes += offset_size;
break;
@ -17063,7 +17353,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
struct macro_source_file *current_file,
struct line_header *lh, char *comp_dir,
struct dwarf2_section_info *section,
int section_is_gnu,
int section_is_gnu, int section_is_dwz,
unsigned int offset_size,
struct objfile *objfile,
htab_t include_hash)
@ -17114,6 +17404,8 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
case DW_MACRO_GNU_undef:
case DW_MACRO_GNU_define_indirect:
case DW_MACRO_GNU_undef_indirect:
case DW_MACRO_GNU_define_indirect_alt:
case DW_MACRO_GNU_undef_indirect_alt:
{
unsigned int bytes_read;
int line;
@ -17136,11 +17428,20 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
mac_ptr += offset_size;
body = read_indirect_string_at_offset (abfd, str_offset);
if (macinfo_type == DW_MACRO_GNU_define_indirect_alt
|| macinfo_type == DW_MACRO_GNU_undef_indirect_alt)
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
body = read_indirect_string_from_dwz (dwz, str_offset);
}
else
body = read_indirect_string_at_offset (abfd, str_offset);
}
is_define = (macinfo_type == DW_MACRO_GNU_define
|| macinfo_type == DW_MACRO_GNU_define_indirect);
|| macinfo_type == DW_MACRO_GNU_define_indirect
|| macinfo_type == DW_MACRO_GNU_define_indirect_alt);
if (! current_file)
{
/* DWARF violation as no main source is present. */
@ -17164,7 +17465,8 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
else
{
gdb_assert (macinfo_type == DW_MACRO_GNU_undef
|| macinfo_type == DW_MACRO_GNU_undef_indirect);
|| macinfo_type == DW_MACRO_GNU_undef_indirect
|| macinfo_type == DW_MACRO_GNU_undef_indirect_alt);
macro_undef (current_file, line, body);
}
}
@ -17239,6 +17541,7 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
break;
case DW_MACRO_GNU_transparent_include:
case DW_MACRO_GNU_transparent_include_alt:
{
LONGEST offset;
void **slot;
@ -17257,13 +17560,32 @@ dwarf_decode_macro_bytes (bfd *abfd, gdb_byte *mac_ptr, gdb_byte *mac_end,
}
else
{
bfd *include_bfd = abfd;
struct dwarf2_section_info *include_section = section;
struct dwarf2_section_info alt_section;
gdb_byte *include_mac_end = mac_end;
int is_dwz = section_is_dwz;
*slot = mac_ptr;
dwarf_decode_macro_bytes (abfd,
section->buffer + offset,
mac_end, current_file,
if (macinfo_type == DW_MACRO_GNU_transparent_include_alt)
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
dwarf2_read_section (dwarf2_per_objfile->objfile,
&dwz->macro);
include_bfd = dwz->macro.asection->owner;
include_section = &dwz->macro;
include_mac_end = dwz->macro.buffer + dwz->macro.size;
is_dwz = 1;
}
dwarf_decode_macro_bytes (include_bfd,
include_section->buffer + offset,
include_mac_end, current_file,
lh, comp_dir,
section, section_is_gnu,
section, section_is_gnu, is_dwz,
offset_size, objfile, include_hash);
htab_remove_elt (include_hash, mac_ptr);
@ -17482,7 +17804,8 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
slot = htab_find_slot (include_hash, mac_ptr, INSERT);
*slot = mac_ptr;
dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
current_file, lh, comp_dir, section, section_is_gnu,
current_file, lh, comp_dir, section,
section_is_gnu, 0,
offset_size, objfile, include_hash);
do_cleanups (cleanup);
}
@ -17737,28 +18060,35 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu)
static struct dwarf2_per_cu_data *
dwarf2_find_containing_comp_unit (sect_offset offset,
unsigned int offset_in_dwz,
struct objfile *objfile)
{
struct dwarf2_per_cu_data *this_cu;
int low, high;
const sect_offset *cu_off;
low = 0;
high = dwarf2_per_objfile->n_comp_units - 1;
while (high > low)
{
struct dwarf2_per_cu_data *mid_cu;
int mid = low + (high - low) / 2;
if (dwarf2_per_objfile->all_comp_units[mid]->offset.sect_off
>= offset.sect_off)
mid_cu = dwarf2_per_objfile->all_comp_units[mid];
cu_off = &mid_cu->offset;
if (mid_cu->is_dwz > offset_in_dwz
|| (mid_cu->is_dwz == offset_in_dwz
&& cu_off->sect_off >= offset.sect_off))
high = mid;
else
low = mid + 1;
}
gdb_assert (low == high);
if (dwarf2_per_objfile->all_comp_units[low]->offset.sect_off
> offset.sect_off)
this_cu = dwarf2_per_objfile->all_comp_units[low];
cu_off = &this_cu->offset;
if (this_cu->is_dwz != offset_in_dwz || cu_off->sect_off > offset.sect_off)
{
if (low == 0)
if (low == 0 || this_cu->is_dwz != offset_in_dwz)
error (_("Dwarf Error: could not find partial DIE containing "
"offset 0x%lx [in module %s]"),
(long) offset.sect_off, bfd_get_filename (objfile->obfd));
@ -18216,6 +18546,9 @@ dwarf2_per_objfile_free (struct objfile *objfile, void *d)
if (data->dwo_files)
free_dwo_files (data->dwo_files, objfile);
if (data->dwz_file && data->dwz_file->dwz_bfd)
gdb_bfd_unref (data->dwz_file->dwz_bfd);
}