/* DWARF 2 debugging format support for GDB.
- Copyright (C) 1994-2016 Free Software Foundation, Inc.
+ Copyright (C) 1994-2017 Free Software Foundation, Inc.
Adapted by Gary Funck (gary@intrepid.com), Intrepid Technology,
Inc. with support from Florida State University (under contract
#include "filestuff.h"
#include "build-id.h"
#include "namespace.h"
+#include "common/gdb_unlinker.h"
+#include "common/function-view.h"
#include <fcntl.h>
#include <sys/types.h>
struct dwarf2_section_info abbrev;
struct dwarf2_section_info line;
struct dwarf2_section_info loc;
+ struct dwarf2_section_info loclists;
struct dwarf2_section_info macinfo;
struct dwarf2_section_info macro;
struct dwarf2_section_info str;
+ struct dwarf2_section_info line_str;
struct dwarf2_section_info ranges;
+ struct dwarf2_section_info rnglists;
struct dwarf2_section_info addr;
struct dwarf2_section_info frame;
struct dwarf2_section_info eh_frame;
{ ".debug_abbrev", ".zdebug_abbrev" },
{ ".debug_line", ".zdebug_line" },
{ ".debug_loc", ".zdebug_loc" },
+ { ".debug_loclists", ".zdebug_loclists" },
{ ".debug_macinfo", ".zdebug_macinfo" },
{ ".debug_macro", ".zdebug_macro" },
{ ".debug_str", ".zdebug_str" },
+ { ".debug_line_str", ".zdebug_line_str" },
{ ".debug_ranges", ".zdebug_ranges" },
+ { ".debug_rnglists", ".zdebug_rnglists" },
{ ".debug_types", ".zdebug_types" },
{ ".debug_addr", ".zdebug_addr" },
{ ".debug_frame", ".zdebug_frame" },
struct dwarf2_section_names info_dwo;
struct dwarf2_section_names line_dwo;
struct dwarf2_section_names loc_dwo;
+ struct dwarf2_section_names loclists_dwo;
struct dwarf2_section_names macinfo_dwo;
struct dwarf2_section_names macro_dwo;
struct dwarf2_section_names str_dwo;
{ ".debug_info.dwo", ".zdebug_info.dwo" },
{ ".debug_line.dwo", ".zdebug_line.dwo" },
{ ".debug_loc.dwo", ".zdebug_loc.dwo" },
+ { ".debug_loclists.dwo", ".zdebug_loclists.dwo" },
{ ".debug_macinfo.dwo", ".zdebug_macinfo.dwo" },
{ ".debug_macro.dwo", ".zdebug_macro.dwo" },
{ ".debug_str.dwo", ".zdebug_str.dwo" },
/* Size of the length field; either 4 or 12. */
unsigned int initial_length_size;
+ enum dwarf_unit_type unit_type;
+
/* Offset to the first byte of this compilation unit header in the
.debug_info section, for resolving relative reference dies. */
sect_offset offset;
/* Offset to first die in this cu from the start of the cu.
This will be the first byte following the compilation unit header. */
cu_offset first_die_offset;
+
+ /* 64-bit signature of this type unit - it is valid only for
+ UNIT_TYPE DW_UT_type. */
+ ULONGEST signature;
+
+ /* For types, offset in the type's DIE of the type defined by this TU. */
+ cu_offset type_offset_in_tu;
};
/* Type used for delaying computation of method physnames.
sect_offset offset;
unsigned int length;
+ /* DWARF standard version this data has been read from (such as 4 or 5). */
+ short dwarf_version;
+
/* Flag indicating this compilation unit will be read in before
any of the current compilation units are processed. */
unsigned int queued : 1;
struct dwarf2_section_info abbrev;
struct dwarf2_section_info line;
struct dwarf2_section_info loc;
+ struct dwarf2_section_info loclists;
struct dwarf2_section_info macinfo;
struct dwarf2_section_info macro;
struct dwarf2_section_info str;
unsigned int has_pc_info : 1;
unsigned int may_be_inlined : 1;
+ /* This DIE has been marked DW_AT_main_subprogram. */
+ unsigned int main_subprogram : 1;
+
/* Flag set if the SCOPE field of this structure has been
computed. */
unsigned int scope_set : 1;
{
ENUM_BITFIELD(dwarf_attribute) name : 16;
ENUM_BITFIELD(dwarf_form) form : 16;
+
+ /* It is valid only if FORM is DW_FORM_implicit_const. */
+ LONGEST implicit_const;
};
/* Size of abbrev_table.abbrev_hash_table. */
const struct comp_unit_head *,
unsigned int *);
-static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
+static const char *read_indirect_line_string (bfd *, const gdb_byte *,
+ const struct comp_unit_head *,
+ unsigned int *);
-static ULONGEST read_unsigned_leb128 (bfd *, const gdb_byte *, unsigned int *);
+static const char *read_indirect_string_from_dwz (struct dwz_file *, LONGEST);
static LONGEST read_signed_leb128 (bfd *, const gdb_byte *, unsigned int *);
static char *file_full_name (int file, struct line_header *lh,
const char *comp_dir);
+/* Expected enum dwarf_unit_type for read_comp_unit_head. */
+enum class rcuh_kind { COMPILE, TYPE };
+
static const gdb_byte *read_and_check_comp_unit_head
(struct comp_unit_head *header,
struct dwarf2_section_info *section,
struct dwarf2_section_info *abbrev_section, const gdb_byte *info_ptr,
- int is_debug_types_section);
+ rcuh_kind section_kind);
static void init_cutu_and_read_dies
(struct dwarf2_per_cu_data *this_cu, struct abbrev_table *abbrev_table,
dwarf2_per_objfile->loc.s.section = sectp;
dwarf2_per_objfile->loc.size = bfd_get_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->loclists))
+ {
+ dwarf2_per_objfile->loclists.s.section = sectp;
+ dwarf2_per_objfile->loclists.size = bfd_get_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->macinfo))
{
dwarf2_per_objfile->macinfo.s.section = sectp;
dwarf2_per_objfile->str.s.section = sectp;
dwarf2_per_objfile->str.size = bfd_get_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->line_str))
+ {
+ dwarf2_per_objfile->line_str.s.section = sectp;
+ dwarf2_per_objfile->line_str.size = bfd_get_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->addr))
{
dwarf2_per_objfile->addr.s.section = sectp;
dwarf2_per_objfile->ranges.s.section = sectp;
dwarf2_per_objfile->ranges.size = bfd_get_section_size (sectp);
}
+ else if (section_is_p (sectp->name, &names->rnglists))
+ {
+ dwarf2_per_objfile->rnglists.s.section = sectp;
+ dwarf2_per_objfile->rnglists.size = bfd_get_section_size (sectp);
+ }
else if (section_is_p (sectp->name, &names->types))
{
struct dwarf2_section_info type_section;
static struct dwz_file *
dwarf2_get_dwz_file (void)
{
- bfd *dwz_bfd;
char *data;
struct cleanup *cleanup;
const char *filename;
/* First try the file name given in the section. If that doesn't
work, try to use the build-id instead. */
- dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
+ gdb_bfd_ref_ptr dwz_bfd (gdb_bfd_open (filename, gnutarget, -1));
if (dwz_bfd != NULL)
{
- if (!build_id_verify (dwz_bfd, buildid_len, buildid))
- {
- gdb_bfd_unref (dwz_bfd);
- dwz_bfd = NULL;
- }
+ if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+ dwz_bfd.release ();
}
if (dwz_bfd == NULL)
result = OBSTACK_ZALLOC (&dwarf2_per_objfile->objfile->objfile_obstack,
struct dwz_file);
- result->dwz_bfd = dwz_bfd;
+ result->dwz_bfd = dwz_bfd.release ();
- bfd_map_over_sections (dwz_bfd, locate_dwz_sections, result);
+ bfd_map_over_sections (result->dwz_bfd, locate_dwz_sections, result);
do_cleanups (cleanup);
- gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, result->dwz_bfd);
dwarf2_per_objfile->dwz_file = result;
return result;
}
dw2_map_expand_apply (struct objfile *objfile,
struct dwarf2_per_cu_data *per_cu,
const char *name, const char *real_path,
- int (*callback) (struct symtab *, void *),
- void *data)
+ gdb::function_view<bool (symtab *)> callback)
{
struct compunit_symtab *last_made = objfile->compunit_symtabs;
all of them. */
dw2_instantiate_symtab (per_cu);
- return iterate_over_some_symtabs (name, real_path, callback, data,
- objfile->compunit_symtabs, last_made);
+ return iterate_over_some_symtabs (name, real_path, objfile->compunit_symtabs,
+ last_made, callback);
}
/* Implementation of the map_symtabs_matching_filename method. */
-static int
-dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
- const char *real_path,
- int (*callback) (struct symtab *, void *),
- void *data)
+static bool
+dw2_map_symtabs_matching_filename
+ (struct objfile *objfile, const char *name, const char *real_path,
+ gdb::function_view<bool (symtab *)> callback)
{
int i;
const char *name_basename = lbasename (name);
if (compare_filenames_for_search (this_name, name))
{
if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
- callback, data))
- return 1;
+ callback))
+ return true;
continue;
}
if (compare_filenames_for_search (this_real_name, name))
{
if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
- callback, data))
- return 1;
+ callback))
+ return true;
continue;
}
&& FILENAME_CMP (real_path, this_real_name) == 0)
{
if (dw2_map_expand_apply (objfile, per_cu, name, real_path,
- callback, data))
- return 1;
+ callback))
+ return true;
continue;
}
}
}
}
- return 0;
+ return false;
}
/* Struct used to manage iterating over all CUs looking for a symbol. */
static void
dw2_expand_symtabs_matching
(struct objfile *objfile,
- expand_symtabs_file_matcher_ftype *file_matcher,
- expand_symtabs_symbol_matcher_ftype *symbol_matcher,
- expand_symtabs_exp_notify_ftype *expansion_notify,
- enum search_domain kind,
- void *data)
+ gdb::function_view<expand_symtabs_file_matcher_ftype> file_matcher,
+ gdb::function_view<expand_symtabs_symbol_matcher_ftype> symbol_matcher,
+ gdb::function_view<expand_symtabs_exp_notify_ftype> expansion_notify,
+ enum search_domain kind)
{
int i;
offset_type iter;
if (file_matcher != NULL)
{
- struct cleanup *cleanup;
- htab_t visited_found, visited_not_found;
-
- visited_found = htab_create_alloc (10,
- htab_hash_pointer, htab_eq_pointer,
- NULL, xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (visited_found);
- visited_not_found = htab_create_alloc (10,
- htab_hash_pointer, htab_eq_pointer,
- NULL, xcalloc, xfree);
- make_cleanup_htab_delete (visited_not_found);
+ htab_up visited_found (htab_create_alloc (10, htab_hash_pointer,
+ htab_eq_pointer,
+ NULL, xcalloc, xfree));
+ htab_up visited_not_found (htab_create_alloc (10, htab_hash_pointer,
+ htab_eq_pointer,
+ NULL, xcalloc, xfree));
/* The rule is CUs specify all the files, including those used by
any TU, so there's no need to scan TUs here. */
if (file_data == NULL)
continue;
- if (htab_find (visited_not_found, file_data) != NULL)
+ if (htab_find (visited_not_found.get (), file_data) != NULL)
continue;
- else if (htab_find (visited_found, file_data) != NULL)
+ else if (htab_find (visited_found.get (), file_data) != NULL)
{
per_cu->v.quick->mark = 1;
continue;
{
const char *this_real_name;
- if (file_matcher (file_data->file_names[j], data, 0))
+ if (file_matcher (file_data->file_names[j], false))
{
per_cu->v.quick->mark = 1;
break;
files are involved, do a quick comparison of the basenames. */
if (!basenames_may_differ
&& !file_matcher (lbasename (file_data->file_names[j]),
- data, 1))
+ true))
continue;
this_real_name = dw2_get_real_path (objfile, file_data, j);
- if (file_matcher (this_real_name, data, 0))
+ if (file_matcher (this_real_name, false))
{
per_cu->v.quick->mark = 1;
break;
}
slot = htab_find_slot (per_cu->v.quick->mark
- ? visited_found
- : visited_not_found,
+ ? visited_found.get ()
+ : visited_not_found.get (),
file_data, INSERT);
*slot = file_data;
}
-
- do_cleanups (cleanup);
}
for (iter = 0; iter < index->symbol_table_slots; ++iter)
name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
- if (! (*symbol_matcher) (name, data))
+ if (!symbol_matcher (name))
continue;
/* The name was matched, now expand corresponding CUs that were
&& symtab_was_null
&& per_cu->v.quick->compunit_symtab != NULL)
{
- expansion_notify (per_cu->v.quick->compunit_symtab,
- data);
+ expansion_notify (per_cu->v.quick->compunit_symtab);
}
}
}
void *data, int need_fullname)
{
int i;
- struct cleanup *cleanup;
- htab_t visited = htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
- NULL, xcalloc, xfree);
+ htab_up visited (htab_create_alloc (10, htab_hash_pointer, htab_eq_pointer,
+ NULL, xcalloc, xfree));
- cleanup = make_cleanup_htab_delete (visited);
dw2_setup (objfile);
/* The rule is CUs specify all the files, including those used by
if (per_cu->v.quick->compunit_symtab)
{
- void **slot = htab_find_slot (visited, per_cu->v.quick->file_names,
+ void **slot = htab_find_slot (visited.get (),
+ per_cu->v.quick->file_names,
INSERT);
*slot = per_cu->v.quick->file_names;
if (file_data == NULL)
continue;
- slot = htab_find_slot (visited, file_data, INSERT);
+ slot = htab_find_slot (visited.get (), file_data, INSERT);
if (*slot)
{
/* Already visited. */
(*fun) (file_data->file_names[j], this_real_name, data);
}
}
-
- do_cleanups (cleanup);
}
static int
/* This isn't really ideal: all the data we allocate on the
objfile's obstack is still uselessly kept around. However,
freeing it seems unsafe. */
- struct cleanup *cleanups = make_cleanup_discard_psymtabs (objfile);
-
+ psymtab_discarder psymtabs (objfile);
dwarf2_build_psymtabs_hard (objfile);
- discard_cleanups (cleanups);
+ psymtabs.keep ();
}
CATCH (except, RETURN_MASK_ERROR)
{
}
/* Read in the comp unit header information from the debug_info at info_ptr.
+ Use rcuh_kind::COMPILE as the default type if not known by the caller.
NOTE: This leaves members offset, first_die_offset to be filled in
by the caller. */
static const gdb_byte *
read_comp_unit_head (struct comp_unit_head *cu_header,
- const gdb_byte *info_ptr, bfd *abfd)
+ const gdb_byte *info_ptr,
+ struct dwarf2_section_info *section,
+ rcuh_kind section_kind)
{
int signed_addr;
unsigned int bytes_read;
+ const char *filename = get_section_file_name (section);
+ bfd *abfd = get_section_bfd_owner (section);
cu_header->length = read_initial_length (abfd, info_ptr, &bytes_read);
cu_header->initial_length_size = bytes_read;
info_ptr += bytes_read;
cu_header->version = read_2_bytes (abfd, info_ptr);
info_ptr += 2;
+ if (cu_header->version < 5)
+ switch (section_kind)
+ {
+ case rcuh_kind::COMPILE:
+ cu_header->unit_type = DW_UT_compile;
+ break;
+ case rcuh_kind::TYPE:
+ cu_header->unit_type = DW_UT_type;
+ break;
+ default:
+ internal_error (__FILE__, __LINE__,
+ _("read_comp_unit_head: invalid section_kind"));
+ }
+ else
+ {
+ cu_header->unit_type = static_cast<enum dwarf_unit_type>
+ (read_1_byte (abfd, info_ptr));
+ info_ptr += 1;
+ switch (cu_header->unit_type)
+ {
+ case DW_UT_compile:
+ if (section_kind != rcuh_kind::COMPILE)
+ error (_("Dwarf Error: wrong unit_type in compilation unit header "
+ "(is DW_UT_compile, should be DW_UT_type) [in module %s]"),
+ filename);
+ break;
+ case DW_UT_type:
+ section_kind = rcuh_kind::TYPE;
+ break;
+ default:
+ error (_("Dwarf Error: wrong unit_type in compilation unit header "
+ "(is %d, should be %d or %d) [in module %s]"),
+ cu_header->unit_type, DW_UT_compile, DW_UT_type, filename);
+ }
+
+ cu_header->addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ }
cu_header->abbrev_offset.sect_off = read_offset (abfd, info_ptr, cu_header,
&bytes_read);
info_ptr += bytes_read;
- cu_header->addr_size = read_1_byte (abfd, info_ptr);
- info_ptr += 1;
+ if (cu_header->version < 5)
+ {
+ cu_header->addr_size = read_1_byte (abfd, info_ptr);
+ info_ptr += 1;
+ }
signed_addr = bfd_get_sign_extend_vma (abfd);
if (signed_addr < 0)
internal_error (__FILE__, __LINE__,
_("read_comp_unit_head: dwarf from non elf file"));
cu_header->signed_addr_p = signed_addr;
+ if (section_kind == rcuh_kind::TYPE)
+ {
+ LONGEST type_offset;
+
+ cu_header->signature = read_8_bytes (abfd, info_ptr);
+ info_ptr += 8;
+
+ type_offset = read_offset (abfd, info_ptr, cu_header, &bytes_read);
+ info_ptr += bytes_read;
+ cu_header->type_offset_in_tu.cu_off = type_offset;
+ if (cu_header->type_offset_in_tu.cu_off != type_offset)
+ error (_("Dwarf Error: Too big type_offset in compilation unit "
+ "header (is %s) [in module %s]"), plongest (type_offset),
+ filename);
+ }
+
return info_ptr;
}
{
const char *filename = get_section_file_name (section);
- if (header->version != 2 && header->version != 3 && header->version != 4)
+ if (header->version < 2 || header->version > 5)
error (_("Dwarf Error: wrong version in compilation unit header "
- "(is %d, should be 2, 3, or 4) [in module %s]"), header->version,
+ "(is %d, should be 2, 3, 4 or 5) [in module %s]"), header->version,
filename);
if (header->abbrev_offset.sect_off
struct dwarf2_section_info *section,
struct dwarf2_section_info *abbrev_section,
const gdb_byte *info_ptr,
- int is_debug_types_section)
-{
- const gdb_byte *beg_of_comp_unit = info_ptr;
- bfd *abfd = get_section_bfd_owner (section);
-
- header->offset.sect_off = beg_of_comp_unit - section->buffer;
-
- info_ptr = read_comp_unit_head (header, info_ptr, abfd);
-
- /* If we're reading a type unit, skip over the signature and
- type_offset fields. */
- if (is_debug_types_section)
- info_ptr += 8 /*signature*/ + header->offset_size;
-
- header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
-
- error_check_comp_unit_head (header, section, abbrev_section);
-
- return info_ptr;
-}
-
-/* Read in the types comp unit header information from .debug_types entry at
- types_ptr. The result is a pointer to one past the end of the header. */
-
-static const gdb_byte *
-read_and_check_type_unit_head (struct comp_unit_head *header,
- struct dwarf2_section_info *section,
- struct dwarf2_section_info *abbrev_section,
- const gdb_byte *info_ptr,
- ULONGEST *signature,
- cu_offset *type_offset_in_tu)
+ rcuh_kind section_kind)
{
const gdb_byte *beg_of_comp_unit = info_ptr;
bfd *abfd = get_section_bfd_owner (section);
header->offset.sect_off = beg_of_comp_unit - section->buffer;
- info_ptr = read_comp_unit_head (header, info_ptr, abfd);
-
- /* If we're reading a type unit, skip over the signature and
- type_offset fields. */
- if (signature != NULL)
- *signature = read_8_bytes (abfd, info_ptr);
- info_ptr += 8;
- if (type_offset_in_tu != NULL)
- type_offset_in_tu->cu_off = read_offset_1 (abfd, info_ptr,
- header->offset_size);
- info_ptr += header->offset_size;
+ info_ptr = read_comp_unit_head (header, info_ptr, section, section_kind);
header->first_die_offset.cu_off = info_ptr - beg_of_comp_unit;
const gdb_byte *info_ptr;
unsigned int initial_length_size, offset_size;
sect_offset abbrev_offset;
+ uint16_t version;
dwarf2_read_section (dwarf2_per_objfile->objfile, section);
info_ptr = section->buffer + offset.sect_off;
read_initial_length (abfd, info_ptr, &initial_length_size);
offset_size = initial_length_size == 4 ? 4 : 8;
- info_ptr += initial_length_size + 2 /*version*/;
+ info_ptr += initial_length_size;
+
+ version = read_2_bytes (abfd, info_ptr);
+ info_ptr += 2;
+ if (version >= 5)
+ {
+ /* Skip unit type and address size. */
+ info_ptr += 2;
+ }
+
abbrev_offset.sect_off = read_offset_1 (abfd, info_ptr, offset_size);
return abbrev_offset;
}
return 1;
}
-/* Create the hash table of all entries in the .debug_types
- (or .debug_types.dwo) section(s).
- If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
- otherwise it is NULL.
-
- The result is a pointer to the hash table or NULL if there are no types.
-
- Note: This function processes DWO files only, not DWP files. */
+/* A helper for create_debug_types_hash_table. Read types from SECTION
+ and fill them into TYPES_HTAB. It will process only type units,
+ therefore DW_UT_type. */
-static htab_t
-create_debug_types_hash_table (struct dwo_file *dwo_file,
- VEC (dwarf2_section_info_def) *types)
+static void
+create_debug_type_hash_table (struct dwo_file *dwo_file,
+ dwarf2_section_info *section, htab_t &types_htab,
+ rcuh_kind section_kind)
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
- htab_t types_htab = NULL;
- int ix;
- struct dwarf2_section_info *section;
struct dwarf2_section_info *abbrev_section;
-
- if (VEC_empty (dwarf2_section_info_def, types))
- return NULL;
+ bfd *abfd;
+ const gdb_byte *info_ptr, *end_ptr;
abbrev_section = (dwo_file != NULL
? &dwo_file->sections.abbrev
: &dwarf2_per_objfile->abbrev);
if (dwarf_read_debug)
- fprintf_unfiltered (gdb_stdlog, "Reading .debug_types%s for %s:\n",
- dwo_file ? ".dwo" : "",
+ fprintf_unfiltered (gdb_stdlog, "Reading %s for %s:\n",
+ get_section_name (section),
get_section_file_name (abbrev_section));
- for (ix = 0;
- VEC_iterate (dwarf2_section_info_def, types, ix, section);
- ++ix)
- {
- bfd *abfd;
- const gdb_byte *info_ptr, *end_ptr;
+ dwarf2_read_section (objfile, section);
+ info_ptr = section->buffer;
- dwarf2_read_section (objfile, section);
- info_ptr = section->buffer;
+ if (info_ptr == NULL)
+ return;
- if (info_ptr == NULL)
- continue;
+ /* We can't set abfd until now because the section may be empty or
+ not present, in which case the bfd is unknown. */
+ abfd = get_section_bfd_owner (section);
- /* We can't set abfd until now because the section may be empty or
- not present, in which case the bfd is unknown. */
- abfd = get_section_bfd_owner (section);
+ /* We don't use init_cutu_and_read_dies_simple, or some such, here
+ because we don't need to read any dies: the signature is in the
+ header. */
- /* We don't use init_cutu_and_read_dies_simple, or some such, here
- because we don't need to read any dies: the signature is in the
- header. */
+ end_ptr = info_ptr + section->size;
+ while (info_ptr < end_ptr)
+ {
+ sect_offset offset;
+ struct signatured_type *sig_type;
+ struct dwo_unit *dwo_tu;
+ void **slot;
+ const gdb_byte *ptr = info_ptr;
+ struct comp_unit_head header;
+ unsigned int length;
- end_ptr = info_ptr + section->size;
- while (info_ptr < end_ptr)
- {
- sect_offset offset;
- cu_offset type_offset_in_tu;
- ULONGEST signature;
- struct signatured_type *sig_type;
- struct dwo_unit *dwo_tu;
- void **slot;
- const gdb_byte *ptr = info_ptr;
- struct comp_unit_head header;
- unsigned int length;
+ offset.sect_off = ptr - section->buffer;
- offset.sect_off = ptr - section->buffer;
+ /* Initialize it due to a false compiler warning. */
+ header.signature = -1;
+ header.type_offset_in_tu.cu_off = -1;
- /* We need to read the type's signature in order to build the hash
- table, but we don't need anything else just yet. */
+ /* We need to read the type's signature in order to build the hash
+ table, but we don't need anything else just yet. */
- ptr = read_and_check_type_unit_head (&header, section,
- abbrev_section, ptr,
- &signature, &type_offset_in_tu);
+ ptr = read_and_check_comp_unit_head (&header, section,
+ abbrev_section, ptr, section_kind);
- length = get_cu_length (&header);
+ length = get_cu_length (&header);
- /* Skip dummy type units. */
- if (ptr >= info_ptr + length
- || peek_abbrev_code (abfd, ptr) == 0)
- {
- info_ptr += length;
- continue;
- }
+ /* Skip dummy type units. */
+ if (ptr >= info_ptr + length
+ || peek_abbrev_code (abfd, ptr) == 0
+ || header.unit_type != DW_UT_type)
+ {
+ info_ptr += length;
+ continue;
+ }
- if (types_htab == NULL)
- {
- if (dwo_file)
- types_htab = allocate_dwo_unit_table (objfile);
- else
- types_htab = allocate_signatured_type_table (objfile);
- }
+ if (types_htab == NULL)
+ {
+ if (dwo_file)
+ types_htab = allocate_dwo_unit_table (objfile);
+ else
+ types_htab = allocate_signatured_type_table (objfile);
+ }
+
+ 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 = header.signature;
+ dwo_tu->type_offset_in_tu = header.type_offset_in_tu;
+ dwo_tu->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 = header.signature;
+ sig_type->type_offset_in_tu = header.type_offset_in_tu;
+ sig_type->per_cu.objfile = objfile;
+ sig_type->per_cu.is_debug_types = 1;
+ sig_type->per_cu.section = section;
+ sig_type->per_cu.offset = offset;
+ sig_type->per_cu.length = length;
+ }
+
+ slot = htab_find_slot (types_htab,
+ dwo_file ? (void*) dwo_tu : (void *) sig_type,
+ INSERT);
+ gdb_assert (slot != NULL);
+ if (*slot != NULL)
+ {
+ sect_offset dup_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->section = section;
- dwo_tu->offset = offset;
- dwo_tu->length = length;
+ const struct dwo_unit *dup_tu
+ = (const struct dwo_unit *) *slot;
+
+ dup_offset = dup_tu->offset;
}
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.section = section;
- sig_type->per_cu.offset = offset;
- sig_type->per_cu.length = length;
+ const struct signatured_type *dup_tu
+ = (const struct signatured_type *) *slot;
+
+ dup_offset = dup_tu->per_cu.offset;
}
- slot = htab_find_slot (types_htab,
- dwo_file ? (void*) dwo_tu : (void *) sig_type,
- INSERT);
- gdb_assert (slot != NULL);
- if (*slot != NULL)
- {
- sect_offset dup_offset;
+ complaint (&symfile_complaints,
+ _("debug type entry at offset 0x%x is duplicate to"
+ " the entry at offset 0x%x, signature %s"),
+ offset.sect_off, dup_offset.sect_off,
+ hex_string (header.signature));
+ }
+ *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
- if (dwo_file)
- {
- const struct dwo_unit *dup_tu
- = (const struct dwo_unit *) *slot;
+ if (dwarf_read_debug > 1)
+ fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
+ offset.sect_off,
+ hex_string (header.signature));
- dup_offset = dup_tu->offset;
- }
- else
- {
- const struct signatured_type *dup_tu
- = (const struct signatured_type *) *slot;
+ info_ptr += length;
+ }
+}
- dup_offset = dup_tu->per_cu.offset;
- }
+/* Create the hash table of all entries in the .debug_types
+ (or .debug_types.dwo) section(s).
+ If reading a DWO file, then DWO_FILE is a pointer to the DWO file object,
+ otherwise it is NULL.
- complaint (&symfile_complaints,
- _("debug type entry at offset 0x%x is duplicate to"
- " the entry at offset 0x%x, signature %s"),
- offset.sect_off, dup_offset.sect_off,
- hex_string (signature));
- }
- *slot = dwo_file ? (void *) dwo_tu : (void *) sig_type;
+ The result is a pointer to the hash table or NULL if there are no types.
- if (dwarf_read_debug > 1)
- fprintf_unfiltered (gdb_stdlog, " offset 0x%x, signature %s\n",
- offset.sect_off,
- hex_string (signature));
+ Note: This function processes DWO files only, not DWP files. */
- info_ptr += length;
- }
- }
+static void
+create_debug_types_hash_table (struct dwo_file *dwo_file,
+ VEC (dwarf2_section_info_def) *types,
+ htab_t &types_htab)
+{
+ int ix;
+ struct dwarf2_section_info *section;
- return types_htab;
+ if (VEC_empty (dwarf2_section_info_def, types))
+ return;
+
+ for (ix = 0;
+ VEC_iterate (dwarf2_section_info_def, types, ix, section);
+ ++ix)
+ create_debug_type_hash_table (dwo_file, section, types_htab,
+ rcuh_kind::TYPE);
}
/* Create the hash table of all entries in the .debug_types section,
static int
create_all_type_units (struct objfile *objfile)
{
- htab_t types_htab;
+ htab_t types_htab = NULL;
struct signatured_type **iter;
- types_htab = create_debug_types_hash_table (NULL, dwarf2_per_objfile->types);
+ create_debug_type_hash_table (NULL, &dwarf2_per_objfile->info, types_htab,
+ rcuh_kind::COMPILE);
+ create_debug_types_hash_table (NULL, dwarf2_per_objfile->types, types_htab);
if (types_htab == NULL)
{
dwarf2_per_objfile->signatured_types = NULL;
if (this_cu->is_debug_types)
{
- ULONGEST header_signature;
- cu_offset type_offset_in_tu;
struct signatured_type *sig_type = (struct signatured_type *) this_cu;
- info_ptr = read_and_check_type_unit_head (&cu->header, section,
+ info_ptr = read_and_check_comp_unit_head (&cu->header, section,
dwo_abbrev_section,
- info_ptr,
- &header_signature,
- &type_offset_in_tu);
+ info_ptr, rcuh_kind::TYPE);
/* This is not an assert because it can be caused by bad debug info. */
- if (sig_type->signature != header_signature)
+ if (sig_type->signature != cu->header.signature)
{
error (_("Dwarf Error: signature mismatch %s vs %s while reading"
" TU at offset 0x%x [in module %s]"),
hex_string (sig_type->signature),
- hex_string (header_signature),
+ hex_string (cu->header.signature),
dwo_unit->offset.sect_off,
bfd_get_filename (abfd));
}
/* For DWOs coming from DWP files, we don't know the CU length
nor the type's offset in the TU until now. */
dwo_unit->length = get_cu_length (&cu->header);
- dwo_unit->type_offset_in_tu = type_offset_in_tu;
+ dwo_unit->type_offset_in_tu = cu->header.type_offset_in_tu;
/* Establish the type offset that can be used to lookup the type.
For DWO files, we don't know it until now. */
{
info_ptr = read_and_check_comp_unit_head (&cu->header, section,
dwo_abbrev_section,
- info_ptr, 0);
+ info_ptr, rcuh_kind::COMPILE);
gdb_assert (dwo_unit->offset.sect_off == cu->header.offset.sect_off);
/* For DWOs coming from DWP files, we don't know the CU length
until now. */
{
if (this_cu->is_debug_types)
{
- ULONGEST signature;
- cu_offset type_offset_in_tu;
-
- info_ptr = read_and_check_type_unit_head (&cu->header, section,
+ info_ptr = read_and_check_comp_unit_head (&cu->header, section,
abbrev_section, info_ptr,
- &signature,
- &type_offset_in_tu);
+ rcuh_kind::TYPE);
/* Since per_cu is the first member of struct signatured_type,
we can go from a pointer to one to a pointer to the other. */
sig_type = (struct signatured_type *) this_cu;
- gdb_assert (sig_type->signature == signature);
+ gdb_assert (sig_type->signature == cu->header.signature);
gdb_assert (sig_type->type_offset_in_tu.cu_off
- == type_offset_in_tu.cu_off);
+ == cu->header.type_offset_in_tu.cu_off);
gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
/* LENGTH has not been set yet for type units if we're
/* 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;
+
+ this_cu->dwarf_version = cu->header.version;
}
else
{
info_ptr = read_and_check_comp_unit_head (&cu->header, section,
abbrev_section,
- info_ptr, 0);
+ info_ptr,
+ rcuh_kind::COMPILE);
gdb_assert (this_cu->offset.sect_off == cu->header.offset.sect_off);
gdb_assert (this_cu->length == get_cu_length (&cu->header));
+ this_cu->dwarf_version = cu->header.version;
}
}
begin_info_ptr = info_ptr = section->buffer + this_cu->offset.sect_off;
info_ptr = read_and_check_comp_unit_head (&cu.header, section,
abbrev_section, info_ptr,
- this_cu->is_debug_types);
+ (this_cu->is_debug_types
+ ? rcuh_kind::TYPE
+ : rcuh_kind::COMPILE));
this_cu->length = get_cu_length (&cu.header);
&objfile->static_psymbols,
addr, cu->language, objfile);
}
+
+ if (pdi->main_subprogram && actual_name != NULL)
+ set_objfile_main_name (objfile, actual_name, cu->language);
break;
case DW_TAG_constant:
{
info_ptr += 1;
break;
case DW_FORM_flag_present:
+ case DW_FORM_implicit_const:
break;
case DW_FORM_data2:
case DW_FORM_ref2:
case DW_FORM_ref_sig8:
info_ptr += 8;
break;
+ case DW_FORM_data16:
+ info_ptr += 16;
+ break;
case DW_FORM_string:
read_direct_string (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
case DW_TAG_catch_block:
read_lexical_block_scope (die, cu);
break;
+ case DW_TAG_call_site:
case DW_TAG_GNU_call_site:
read_call_site_scope (die, cu);
break;
}
}
-/* Retrieve the last character from a mem_file. */
-
-static void
-do_ui_file_peek_last (void *object, const char *buffer, long length)
-{
- char *last_char_p = (char *) object;
-
- if (length > 0)
- *last_char_p = buffer[length - 1];
-}
-
/* Compute the fully qualified name of DIE in CU. If PHYSNAME is nonzero,
compute the physname for the object, which include a method's:
- formal parameters (C++),
{
long length;
const char *prefix;
- struct ui_file *buf;
- char *intermediate_name;
const char *canonical_name = NULL;
+ string_file buf;
+
prefix = determine_prefix (die, cu);
- buf = mem_fileopen ();
if (*prefix != '\0')
{
char *prefixed_name = typename_concat (NULL, prefix, name,
physname, cu);
- fputs_unfiltered (prefixed_name, buf);
+ buf.puts (prefixed_name);
xfree (prefixed_name);
}
else
- fputs_unfiltered (name, buf);
+ buf.puts (name);
/* Template parameters may be specified in the DIE's DW_AT_name, or
as children with DW_TAG_template_type_param or
if (first)
{
- fputs_unfiltered ("<", buf);
+ buf.puts ("<");
first = 0;
}
else
- fputs_unfiltered (", ", buf);
+ buf.puts (", ");
attr = dwarf2_attr (child, DW_AT_type, cu);
if (attr == NULL)
{
complaint (&symfile_complaints,
_("template parameter missing DW_AT_type"));
- fputs_unfiltered ("UNKNOWN_TYPE", buf);
+ buf.puts ("UNKNOWN_TYPE");
continue;
}
type = die_type (child, cu);
if (child->tag == DW_TAG_template_type_param)
{
- c_print_type (type, "", buf, -1, 0, &type_print_raw_options);
+ c_print_type (type, "", &buf, -1, 0, &type_print_raw_options);
continue;
}
complaint (&symfile_complaints,
_("template parameter missing "
"DW_AT_const_value"));
- fputs_unfiltered ("UNKNOWN_VALUE", buf);
+ buf.puts ("UNKNOWN_VALUE");
continue;
}
if (TYPE_NOSIGN (type))
/* GDB prints characters as NUMBER 'CHAR'. If that's
changed, this can use value_print instead. */
- c_printchar (value, type, buf);
+ c_printchar (value, type, &buf);
else
{
struct value_print_options opts;
the radix. */
get_formatted_print_options (&opts, 'd');
opts.raw = 1;
- value_print (v, buf, &opts);
+ value_print (v, &buf, &opts);
release_value (v);
value_free (v);
}
{
/* Close the argument list, with a space if necessary
(nested templates). */
- char last_char = '\0';
- ui_file_put (buf, do_ui_file_peek_last, &last_char);
- if (last_char == '>')
- fputs_unfiltered (" >", buf);
+ if (!buf.empty () && buf.string ().back () == '>')
+ buf.puts (" >");
else
- fputs_unfiltered (">", buf);
+ buf.puts (">");
}
}
{
struct type *type = read_type_die (die, cu);
- c_type_print_args (type, buf, 1, cu->language,
+ c_type_print_args (type, &buf, 1, cu->language,
&type_print_raw_options);
if (cu->language == language_cplus)
&& TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) == TYPE_CODE_PTR
&& TYPE_CONST (TYPE_TARGET_TYPE (TYPE_FIELD_TYPE (type,
0))))
- fputs_unfiltered (" const", buf);
+ buf.puts (" const");
}
}
- intermediate_name = ui_file_xstrdup (buf, &length);
- ui_file_delete (buf);
+ const std::string &intermediate_name = buf.string ();
if (cu->language == language_cplus)
canonical_name
- = dwarf2_canonicalize_name (intermediate_name, cu,
+ = dwarf2_canonicalize_name (intermediate_name.c_str (), cu,
&objfile->per_bfd->storage_obstack);
/* If we only computed INTERMEDIATE_NAME, or if
INTERMEDIATE_NAME is already canonical, then we need to
copy it to the appropriate obstack. */
- if (canonical_name == NULL || canonical_name == intermediate_name)
+ if (canonical_name == NULL || canonical_name == intermediate_name.c_str ())
name = ((const char *)
obstack_copy0 (&objfile->per_bfd->storage_obstack,
- intermediate_name,
- strlen (intermediate_name)));
+ intermediate_name.c_str (),
+ intermediate_name.length ()));
else
name = canonical_name;
-
- xfree (intermediate_name);
}
}
refers to information in the line number info statement program
header, so we can only read it if we've read the header
successfully. */
- attr = dwarf2_attr (die, DW_AT_GNU_macros, cu);
+ attr = dwarf2_attr (die, DW_AT_macros, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (die, DW_AT_GNU_macros, cu);
if (attr && cu->line_header)
{
if (dwarf2_attr (die, DW_AT_macro_info, cu))
complaint (&symfile_complaints,
- _("CU refers to both DW_AT_GNU_macros and DW_AT_macro_info"));
+ _("CU refers to both DW_AT_macros and DW_AT_macro_info"));
dwarf_decode_macros (cu, DW_UNSND (attr), 1);
}
If unable to find/open the file, return NULL.
NOTE: This function is derived from symfile_bfd_open. */
-static bfd *
+static gdb_bfd_ref_ptr
try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
{
- bfd *sym_bfd;
int desc, flags;
char *absolute_name;
/* Blech. OPF_TRY_CWD_FIRST also disables searching the path list if
if (desc < 0)
return NULL;
- sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
+ gdb_bfd_ref_ptr sym_bfd (gdb_bfd_open (absolute_name, gnutarget, desc));
xfree (absolute_name);
if (sym_bfd == NULL)
return NULL;
- bfd_set_cacheable (sym_bfd, 1);
+ bfd_set_cacheable (sym_bfd.get (), 1);
- if (!bfd_check_format (sym_bfd, bfd_object))
- {
- gdb_bfd_unref (sym_bfd); /* This also closes desc. */
- return NULL;
- }
+ if (!bfd_check_format (sym_bfd.get (), bfd_object))
+ return NULL;
/* Success. Record the bfd as having been included by the objfile's bfd.
This is important because things like demangled_names_hash lives in the
objfile's per_bfd space and may have references to things like symbol
names that live in the DWO/DWP file's per_bfd space. PR 16426. */
- gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+ gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd.get ());
return sym_bfd;
}
Upon success, the canonicalized path of the file is stored in the bfd,
same as symfile_bfd_open. */
-static bfd *
+static gdb_bfd_ref_ptr
open_dwo_file (const char *file_name, const char *comp_dir)
{
- bfd *abfd;
-
if (IS_ABSOLUTE_PATH (file_name))
return try_open_dwop_file (file_name, 0 /*is_dwp*/, 0 /*search_cwd*/);
/* NOTE: If comp_dir is a relative path, this will also try the
search path, which seems useful. */
- abfd = try_open_dwop_file (path_to_try, 0 /*is_dwp*/, 1 /*search_cwd*/);
+ gdb_bfd_ref_ptr abfd (try_open_dwop_file (path_to_try, 0 /*is_dwp*/,
+ 1 /*search_cwd*/));
xfree (path_to_try);
if (abfd != NULL)
return abfd;
{
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwo_file *dwo_file;
- bfd *dbfd;
struct cleanup *cleanups;
- dbfd = open_dwo_file (dwo_name, comp_dir);
+ gdb_bfd_ref_ptr dbfd (open_dwo_file (dwo_name, comp_dir));
if (dbfd == NULL)
{
if (dwarf_read_debug)
dwo_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_file);
dwo_file->dwo_name = dwo_name;
dwo_file->comp_dir = comp_dir;
- dwo_file->dbfd = dbfd;
+ dwo_file->dbfd = dbfd.release ();
cleanups = make_cleanup (free_dwo_file_cleanup, dwo_file);
- bfd_map_over_sections (dbfd, dwarf2_locate_dwo_sections, &dwo_file->sections);
+ bfd_map_over_sections (dwo_file->dbfd, dwarf2_locate_dwo_sections,
+ &dwo_file->sections);
dwo_file->cu = create_dwo_cu (dwo_file);
- dwo_file->tus = create_debug_types_hash_table (dwo_file,
- dwo_file->sections.types);
+ create_debug_types_hash_table (dwo_file, dwo_file->sections.types,
+ dwo_file->tus);
discard_cleanups (cleanups);
Upon success, the canonicalized path of the file is stored in the bfd,
same as symfile_bfd_open. */
-static bfd *
+static gdb_bfd_ref_ptr
open_dwp_file (const char *file_name)
{
- bfd *abfd;
-
- abfd = try_open_dwop_file (file_name, 1 /*is_dwp*/, 1 /*search_cwd*/);
+ gdb_bfd_ref_ptr abfd (try_open_dwop_file (file_name, 1 /*is_dwp*/,
+ 1 /*search_cwd*/));
if (abfd != NULL)
return abfd;
struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwp_file *dwp_file;
char *dwp_name;
- bfd *dbfd;
struct cleanup *cleanups = make_cleanup (null_cleanup, 0);
/* Try to find first .dwp for the binary file before any symbolic links
dwp_name = xstrprintf ("%s.dwp", objfile->original_name);
make_cleanup (xfree, dwp_name);
- dbfd = open_dwp_file (dwp_name);
+ gdb_bfd_ref_ptr dbfd (open_dwp_file (dwp_name));
if (dbfd == NULL
&& strcmp (objfile->original_name, objfile_name (objfile)) != 0)
{
return NULL;
}
dwp_file = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwp_file);
- dwp_file->name = bfd_get_filename (dbfd);
- dwp_file->dbfd = dbfd;
+ dwp_file->name = bfd_get_filename (dbfd.get ());
+ dwp_file->dbfd = dbfd.release ();
do_cleanups (cleanups);
/* +1: section 0 is unused */
- dwp_file->num_sections = bfd_count_sections (dbfd) + 1;
+ dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1;
dwp_file->elf_sections =
OBSTACK_CALLOC (&objfile->objfile_obstack,
dwp_file->num_sections, asection *);
- bfd_map_over_sections (dbfd, dwarf2_locate_common_dwp_sections, dwp_file);
+ bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_common_dwp_sections,
+ dwp_file);
dwp_file->cus = create_dwp_hash_table (dwp_file, 0);
dwp_file->version = dwp_file->cus->version;
if (dwp_file->version == 2)
- bfd_map_over_sections (dbfd, dwarf2_locate_v2_dwp_sections, dwp_file);
+ bfd_map_over_sections (dwp_file->dbfd, dwarf2_locate_v2_dwp_sections,
+ dwp_file);
dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
struct dwarf2_cu *child_origin_cu;
/* We are trying to process concrete instance entries:
- DW_TAG_GNU_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
+ DW_TAG_call_site DIEs indeed have a DW_AT_abstract_origin tag, but
it's not relevant to our analysis here. i.e. detecting DIEs that are
present in the abstract instance but not referenced in the concrete
one. */
- if (child_die->tag == DW_TAG_GNU_call_site)
+ if (child_die->tag == DW_TAG_call_site
+ || child_die->tag == DW_TAG_GNU_call_site)
continue;
/* For each CHILD_DIE, find the corresponding child of
local_using_directives = newobj->local_using_directives;
}
-/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab. */
+/* Read in DW_TAG_call_site and insert it to CU->call_site_htab. */
static void
read_call_site_scope (struct die_info *die, struct dwarf2_cu *cu)
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
- attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+ attr = dwarf2_attr (die, DW_AT_call_return_pc, cu);
+ if (attr == NULL)
+ {
+ /* This was a pre-DWARF-5 GNU extension alias
+ for DW_AT_call_return_pc. */
+ attr = dwarf2_attr (die, DW_AT_low_pc, cu);
+ }
if (!attr)
{
complaint (&symfile_complaints,
- _("missing DW_AT_low_pc for DW_TAG_GNU_call_site "
+ _("missing DW_AT_call_return_pc for DW_TAG_call_site "
"DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
return;
if (*slot != NULL)
{
complaint (&symfile_complaints,
- _("Duplicate PC %s for DW_TAG_GNU_call_site "
+ _("Duplicate PC %s for DW_TAG_call_site "
"DIE 0x%x [in module %s]"),
paddress (gdbarch, pc), die->offset.sect_off,
objfile_name (objfile));
for (child_die = die->child; child_die && child_die->tag;
child_die = sibling_die (child_die))
{
- if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+ if (child_die->tag != DW_TAG_call_site_parameter
+ && child_die->tag != DW_TAG_GNU_call_site_parameter)
{
complaint (&symfile_complaints,
- _("Tag %d is not DW_TAG_GNU_call_site_parameter in "
- "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ _("Tag %d is not DW_TAG_call_site_parameter in "
+ "DW_TAG_call_site child DIE 0x%x [in module %s]"),
child_die->tag, child_die->offset.sect_off,
objfile_name (objfile));
continue;
memset (call_site, 0, sizeof (*call_site) - sizeof (*call_site->parameter));
call_site->pc = pc;
- if (dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
+ if (dwarf2_flag_true_p (die, DW_AT_call_tail_call, cu)
+ || dwarf2_flag_true_p (die, DW_AT_GNU_tail_call, cu))
{
struct die_info *func_die;
&& func_die->tag != DW_TAG_subroutine_type;
func_die = func_die->parent);
- /* DW_AT_GNU_all_call_sites is a superset
- of DW_AT_GNU_all_tail_call_sites. */
+ /* DW_AT_call_all_calls is a superset
+ of DW_AT_call_all_tail_calls. */
if (func_die
+ && !dwarf2_flag_true_p (func_die, DW_AT_call_all_calls, cu)
&& !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_call_sites, cu)
+ && !dwarf2_flag_true_p (func_die, DW_AT_call_all_tail_calls, cu)
&& !dwarf2_flag_true_p (func_die, DW_AT_GNU_all_tail_call_sites, cu))
{
/* TYPE_TAIL_CALL_LIST is not interesting in functions where it is
}
else
complaint (&symfile_complaints,
- _("Cannot find function owning DW_TAG_GNU_call_site "
+ _("Cannot find function owning DW_TAG_call_site "
"DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
}
}
- attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
+ attr = dwarf2_attr (die, DW_AT_call_target, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (die, DW_AT_GNU_call_site_target, cu);
if (attr == NULL)
- attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+ attr = dwarf2_attr (die, DW_AT_call_origin, cu);
+ if (attr == NULL)
+ {
+ /* This was a pre-DWARF-5 GNU extension alias for DW_AT_call_origin. */
+ attr = dwarf2_attr (die, DW_AT_abstract_origin, cu);
+ }
SET_FIELD_DWARF_BLOCK (call_site->target, NULL);
if (!attr || (attr_form_is_block (attr) && DW_BLOCK (attr)->size == 0))
/* Keep NULL DWARF_BLOCK. */;
target_physname = dwarf2_physname (NULL, target_die, target_cu);
if (target_physname == NULL)
complaint (&symfile_complaints,
- _("DW_AT_GNU_call_site_target target DIE has invalid "
+ _("DW_AT_call_target target DIE has invalid "
"physname, for referencing DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
else
if (dwarf2_get_pc_bounds (target_die, &lowpc, NULL, target_cu, NULL)
<= PC_BOUNDS_INVALID)
complaint (&symfile_complaints,
- _("DW_AT_GNU_call_site_target target DIE has invalid "
+ _("DW_AT_call_target target DIE has invalid "
"low pc, for referencing DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
else
}
else
complaint (&symfile_complaints,
- _("DW_TAG_GNU_call_site DW_AT_GNU_call_site_target is neither "
+ _("DW_TAG_call_site DW_AT_call_target is neither "
"block nor reference, for DIE 0x%x [in module %s]"),
die->offset.sect_off, objfile_name (objfile));
struct call_site_parameter *parameter;
struct attribute *loc, *origin;
- if (child_die->tag != DW_TAG_GNU_call_site_parameter)
+ if (child_die->tag != DW_TAG_call_site_parameter
+ && child_die->tag != DW_TAG_GNU_call_site_parameter)
{
/* Already printed the complaint above. */
continue;
/* DW_AT_location specifies the register number or DW_AT_abstract_origin
specifies DW_TAG_formal_parameter. Value of the data assumed for the
- register is contained in DW_AT_GNU_call_site_value. */
+ register is contained in DW_AT_call_value. */
loc = dwarf2_attr (child_die, DW_AT_location, cu);
- origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+ origin = dwarf2_attr (child_die, DW_AT_call_parameter, cu);
+ if (origin == NULL)
+ {
+ /* This was a pre-DWARF-5 GNU extension alias
+ for DW_AT_call_parameter. */
+ origin = dwarf2_attr (child_die, DW_AT_abstract_origin, cu);
+ }
if (loc == NULL && origin != NULL && attr_form_is_ref (origin))
{
sect_offset offset;
binding can be done only inside one CU. Such referenced DIE
therefore cannot be even moved to DW_TAG_partial_unit. */
complaint (&symfile_complaints,
- _("DW_AT_abstract_origin offset is not in CU for "
- "DW_TAG_GNU_call_site child DIE 0x%x "
- "[in module %s]"),
+ _("DW_AT_call_parameter offset is not in CU for "
+ "DW_TAG_call_site child DIE 0x%x [in module %s]"),
child_die->offset.sect_off, objfile_name (objfile));
continue;
}
{
complaint (&symfile_complaints,
_("No DW_FORM_block* DW_AT_location for "
- "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
+ "DW_TAG_call_site child DIE 0x%x [in module %s]"),
child_die->offset.sect_off, objfile_name (objfile));
continue;
}
complaint (&symfile_complaints,
_("Only single DW_OP_reg or DW_OP_fbreg is supported "
"for DW_FORM_block* DW_AT_location is supported for "
- "DW_TAG_GNU_call_site child DIE 0x%x "
+ "DW_TAG_call_site child DIE 0x%x "
"[in module %s]"),
child_die->offset.sect_off, objfile_name (objfile));
continue;
}
}
- attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
- if (!attr_form_is_block (attr))
+ attr = dwarf2_attr (child_die, DW_AT_call_value, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_value, cu);
+ if (!attr_form_is_block (attr))
+ {
+ complaint (&symfile_complaints,
+ _("No DW_FORM_block* DW_AT_call_value for "
+ "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+ child_die->offset.sect_off, objfile_name (objfile));
+ continue;
+ }
+ parameter->value = DW_BLOCK (attr)->data;
+ parameter->value_size = DW_BLOCK (attr)->size;
+
+ /* Parameters are not pre-cleared by memset above. */
+ parameter->data_value = NULL;
+ parameter->data_value_size = 0;
+ call_site->parameter_count++;
+
+ attr = dwarf2_attr (child_die, DW_AT_call_data_value, cu);
+ if (attr == NULL)
+ attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
+ if (attr)
+ {
+ if (!attr_form_is_block (attr))
+ complaint (&symfile_complaints,
+ _("No DW_FORM_block* DW_AT_call_data_value for "
+ "DW_TAG_call_site child DIE 0x%x [in module %s]"),
+ child_die->offset.sect_off, objfile_name (objfile));
+ else
+ {
+ parameter->data_value = DW_BLOCK (attr)->data;
+ parameter->data_value_size = DW_BLOCK (attr)->size;
+ }
+ }
+ }
+}
+
+/* Call CALLBACK from DW_AT_ranges attribute value OFFSET
+ reading .debug_rnglists.
+ Callback's type should be:
+ void (CORE_ADDR range_beginning, CORE_ADDR range_end)
+ Return true if the attributes are present and valid, otherwise,
+ return false. */
+
+template <typename Callback>
+static bool
+dwarf2_rnglists_process (unsigned offset, struct dwarf2_cu *cu,
+ Callback &&callback)
+{
+ struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ struct comp_unit_head *cu_header = &cu->header;
+ bfd *obfd = objfile->obfd;
+ unsigned int addr_size = cu_header->addr_size;
+ CORE_ADDR mask = ~(~(CORE_ADDR)1 << (addr_size * 8 - 1));
+ /* Base address selection entry. */
+ CORE_ADDR base;
+ int found_base;
+ unsigned int dummy;
+ const gdb_byte *buffer;
+ CORE_ADDR low = 0;
+ CORE_ADDR high = 0;
+ CORE_ADDR baseaddr;
+ bool overflow = false;
+
+ found_base = cu->base_known;
+ base = cu->base_address;
+
+ dwarf2_read_section (objfile, &dwarf2_per_objfile->rnglists);
+ if (offset >= dwarf2_per_objfile->rnglists.size)
+ {
+ complaint (&symfile_complaints,
+ _("Offset %d out of bounds for DW_AT_ranges attribute"),
+ offset);
+ return false;
+ }
+ buffer = dwarf2_per_objfile->rnglists.buffer + offset;
+
+ baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
+
+ while (1)
+ {
+ /* Initialize it due to a false compiler warning. */
+ CORE_ADDR range_beginning = 0, range_end = 0;
+ const gdb_byte *buf_end = (dwarf2_per_objfile->rnglists.buffer
+ + dwarf2_per_objfile->rnglists.size);
+ unsigned int bytes_read;
+
+ if (buffer == buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ const auto rlet = static_cast<enum dwarf_range_list_entry>(*buffer++);
+ switch (rlet)
+ {
+ case DW_RLE_end_of_list:
+ break;
+ case DW_RLE_base_address:
+ if (buffer + cu->header.addr_size > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ base = read_address (obfd, buffer, cu, &bytes_read);
+ found_base = 1;
+ buffer += bytes_read;
+ break;
+ case DW_RLE_start_length:
+ if (buffer + cu->header.addr_size > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+ buffer += bytes_read;
+ range_end = (range_beginning
+ + read_unsigned_leb128 (obfd, buffer, &bytes_read));
+ buffer += bytes_read;
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ break;
+ case DW_RLE_offset_pair:
+ range_beginning = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ range_end = read_unsigned_leb128 (obfd, buffer, &bytes_read);
+ buffer += bytes_read;
+ if (buffer > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ break;
+ case DW_RLE_start_end:
+ if (buffer + 2 * cu->header.addr_size > buf_end)
+ {
+ overflow = true;
+ break;
+ }
+ range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+ buffer += bytes_read;
+ range_end = read_address (obfd, buffer, cu, &bytes_read);
+ buffer += bytes_read;
+ break;
+ default:
+ complaint (&symfile_complaints,
+ _("Invalid .debug_rnglists data (no base address)"));
+ return false;
+ }
+ if (rlet == DW_RLE_end_of_list || overflow)
+ break;
+ if (rlet == DW_RLE_base_address)
+ continue;
+
+ if (!found_base)
+ {
+ /* We have no valid base address for the ranges
+ data. */
+ complaint (&symfile_complaints,
+ _("Invalid .debug_rnglists data (no base address)"));
+ return false;
+ }
+
+ if (range_beginning > range_end)
+ {
+ /* Inverted range entries are invalid. */
+ complaint (&symfile_complaints,
+ _("Invalid .debug_rnglists data (inverted range)"));
+ return false;
+ }
+
+ /* Empty range entries have no effect. */
+ if (range_beginning == range_end)
+ continue;
+
+ range_beginning += base;
+ range_end += base;
+
+ /* A not-uncommon case of bad debug info.
+ Don't pollute the addrmap with bad data. */
+ if (range_beginning + baseaddr == 0
+ && !dwarf2_per_objfile->has_section_at_zero)
{
complaint (&symfile_complaints,
- _("No DW_FORM_block* DW_AT_GNU_call_site_value for "
- "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile_name (objfile));
+ _(".debug_rnglists entry has start address of zero"
+ " [in module %s]"), objfile_name (objfile));
continue;
}
- parameter->value = DW_BLOCK (attr)->data;
- parameter->value_size = DW_BLOCK (attr)->size;
- /* Parameters are not pre-cleared by memset above. */
- parameter->data_value = NULL;
- parameter->data_value_size = 0;
- call_site->parameter_count++;
+ callback (range_beginning, range_end);
+ }
- attr = dwarf2_attr (child_die, DW_AT_GNU_call_site_data_value, cu);
- if (attr)
- {
- if (!attr_form_is_block (attr))
- complaint (&symfile_complaints,
- _("No DW_FORM_block* DW_AT_GNU_call_site_data_value for "
- "DW_TAG_GNU_call_site child DIE 0x%x [in module %s]"),
- child_die->offset.sect_off, objfile_name (objfile));
- else
- {
- parameter->data_value = DW_BLOCK (attr)->data;
- parameter->data_value_size = DW_BLOCK (attr)->size;
- }
- }
+ if (overflow)
+ {
+ complaint (&symfile_complaints,
+ _("Offset %d is not terminated "
+ "for DW_AT_ranges attribute"),
+ offset);
+ return false;
}
+
+ return true;
}
-/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
- Return 1 if the attributes are present and valid, otherwise, return 0.
- If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */
+/* Call CALLBACK from DW_AT_ranges attribute value OFFSET reading .debug_ranges.
+ Callback's type should be:
+ void (CORE_ADDR range_beginning, CORE_ADDR range_end)
+ Return 1 if the attributes are present and valid, otherwise, return 0. */
+template <typename Callback>
static int
-dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
- CORE_ADDR *high_return, struct dwarf2_cu *cu,
- struct partial_symtab *ranges_pst)
+dwarf2_ranges_process (unsigned offset, struct dwarf2_cu *cu,
+ Callback &&callback)
{
struct objfile *objfile = cu->objfile;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
int found_base;
unsigned int dummy;
const gdb_byte *buffer;
- int low_set;
- CORE_ADDR low = 0;
- CORE_ADDR high = 0;
CORE_ADDR baseaddr;
+ if (cu_header->version >= 5)
+ return dwarf2_rnglists_process (offset, cu, callback);
+
found_base = cu->base_known;
base = cu->base_address;
}
buffer = dwarf2_per_objfile->ranges.buffer + offset;
- low_set = 0;
-
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
while (1)
continue;
}
+ callback (range_beginning, range_end);
+ }
+
+ return 1;
+}
+
+/* Get low and high pc attributes from DW_AT_ranges attribute value OFFSET.
+ Return 1 if the attributes are present and valid, otherwise, return 0.
+ If RANGES_PST is not NULL we should setup `objfile->psymtabs_addrmap'. */
+
+static int
+dwarf2_ranges_read (unsigned offset, CORE_ADDR *low_return,
+ CORE_ADDR *high_return, struct dwarf2_cu *cu,
+ struct partial_symtab *ranges_pst)
+{
+ struct objfile *objfile = cu->objfile;
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ const CORE_ADDR baseaddr = ANOFFSET (objfile->section_offsets,
+ SECT_OFF_TEXT (objfile));
+ int low_set = 0;
+ CORE_ADDR low = 0;
+ CORE_ADDR high = 0;
+ int retval;
+
+ retval = dwarf2_ranges_process (offset, cu,
+ [&] (CORE_ADDR range_beginning, CORE_ADDR range_end)
+ {
if (ranges_pst != NULL)
{
CORE_ADDR lowpc;
if (range_end > high)
high = range_end;
}
- }
+ });
+ if (!retval)
+ return 0;
if (! low_set)
/* If the first entry is an end-of-list marker, the range
CORE_ADDR base = cu->base_address;
int base_known = cu->base_known;
- dwarf2_read_section (objfile, &dwarf2_per_objfile->ranges);
- if (offset >= dwarf2_per_objfile->ranges.size)
- {
- complaint (&symfile_complaints,
- _("Offset %lu out of bounds for DW_AT_ranges attribute"),
- offset);
- return;
- }
- buffer = dwarf2_per_objfile->ranges.buffer + offset;
-
- for (;;)
- {
- unsigned int bytes_read;
- CORE_ADDR start, end;
-
- start = read_address (obfd, buffer, cu, &bytes_read);
- buffer += bytes_read;
- end = read_address (obfd, buffer, cu, &bytes_read);
- buffer += bytes_read;
-
- /* Did we find the end of the range list? */
- if (start == 0 && end == 0)
- break;
-
- /* Did we find a base address selection entry? */
- else if ((start & base_select_mask) == base_select_mask)
- {
- base = end;
- base_known = 1;
- }
-
- /* We found an ordinary address range. */
- else
- {
- if (!base_known)
- {
- complaint (&symfile_complaints,
- _("Invalid .debug_ranges data "
- "(no base address)"));
- return;
- }
-
- if (start > end)
- {
- /* Inverted range entries are invalid. */
- complaint (&symfile_complaints,
- _("Invalid .debug_ranges data "
- "(inverted range)"));
- return;
- }
-
- /* Empty range entries have no effect. */
- if (start == end)
- continue;
-
- start += base + baseaddr;
- end += base + baseaddr;
-
- /* A not-uncommon case of bad debug info.
- Don't pollute the addrmap with bad data. */
- if (start == 0 && !dwarf2_per_objfile->has_section_at_zero)
- {
- complaint (&symfile_complaints,
- _(".debug_ranges entry has start address of zero"
- " [in module %s]"), objfile_name (objfile));
- continue;
- }
-
- start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
- end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
- record_block_range (block, start, end - 1);
- }
- }
+ dwarf2_ranges_process (offset, cu,
+ [&] (CORE_ADDR start, CORE_ADDR end)
+ {
+ start += baseaddr;
+ end += baseaddr;
+ start = gdbarch_adjust_dwarf2_addr (gdbarch, start);
+ end = gdbarch_adjust_dwarf2_addr (gdbarch, end);
+ record_block_range (block, start, end - 1);
+ });
}
}
- bit_offset - FIELD_BITSIZE (*fp)));
}
}
+ attr = dwarf2_attr (die, DW_AT_data_bit_offset, cu);
+ if (attr != NULL)
+ SET_FIELD_BITPOS (*fp, (FIELD_BITPOS (*fp)
+ + dwarf2_get_attr_constant_value (attr, 0)));
/* Get name of field. */
fieldname = dwarf2_name (die, cu);
abbrev_ptr += 1;
/* now read in declarations */
- abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
- abbrev_ptr += bytes_read;
- abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
- abbrev_ptr += bytes_read;
- while (abbrev_name)
+ for (;;)
{
+ LONGEST implicit_const;
+
+ abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ abbrev_ptr += bytes_read;
+ if (abbrev_form == DW_FORM_implicit_const)
+ {
+ implicit_const = read_signed_leb128 (abfd, abbrev_ptr,
+ &bytes_read);
+ abbrev_ptr += bytes_read;
+ }
+ else
+ {
+ /* Initialize it due to a false compiler warning. */
+ implicit_const = -1;
+ }
+
+ if (abbrev_name == 0)
+ break;
+
if (cur_abbrev->num_attrs == allocated_attrs)
{
allocated_attrs += ATTR_ALLOC_CHUNK;
cur_attrs[cur_abbrev->num_attrs].name
= (enum dwarf_attribute) abbrev_name;
- cur_attrs[cur_abbrev->num_attrs++].form
+ cur_attrs[cur_abbrev->num_attrs].form
= (enum dwarf_form) abbrev_form;
- abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
- abbrev_ptr += bytes_read;
- abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
- abbrev_ptr += bytes_read;
+ cur_attrs[cur_abbrev->num_attrs].implicit_const = implicit_const;
+ ++cur_abbrev->num_attrs;
}
cur_abbrev->attrs =
to describe functions' calling conventions.
However, because it's a necessary piece of information in
- Fortran, and because DW_CC_program is the only piece of debugging
- information whose definition refers to a 'main program' at all,
- several compilers have begun marking Fortran main programs with
- DW_CC_program --- even when those functions use the standard
- calling conventions.
-
- So until DWARF specifies a way to provide this information and
- compilers pick up the new representation, we'll support this
- practice. */
+ Fortran, and before DWARF 4 DW_CC_program was the only
+ piece of debugging information whose definition refers to
+ a 'main program' at all, several compilers marked Fortran
+ main programs with DW_CC_program --- even when those
+ functions use the standard calling conventions.
+
+ Although DWARF now specifies a way to provide this
+ information, we support this practice for backward
+ compatibility. */
if (DW_UNSND (&attr) == DW_CC_program
- && cu->language == language_fortran
- && part_die->name != NULL)
- set_objfile_main_name (objfile, part_die->name, language_fortran);
+ && cu->language == language_fortran)
+ part_die->main_subprogram = 1;
break;
case DW_AT_inline:
if (DW_UNSND (&attr) == DW_INL_inlined
}
break;
+ case DW_AT_main_subprogram:
+ part_die->main_subprogram = DW_UNSND (&attr);
+ break;
+
default:
break;
}
static const gdb_byte *
read_attribute_value (const struct die_reader_specs *reader,
struct attribute *attr, unsigned form,
- const gdb_byte *info_ptr)
+ LONGEST implicit_const, const gdb_byte *info_ptr)
{
struct dwarf2_cu *cu = reader->cu;
struct objfile *objfile = cu->objfile;
DW_UNSND (attr) = read_8_bytes (abfd, info_ptr);
info_ptr += 8;
break;
+ case DW_FORM_data16:
+ blk = dwarf_alloc_block (cu);
+ blk->size = 16;
+ blk->data = read_n_bytes (abfd, info_ptr, 16);
+ info_ptr += 16;
+ DW_BLOCK (attr) = blk;
+ break;
case DW_FORM_sec_offset:
DW_UNSND (attr) = read_offset (abfd, info_ptr, &cu->header, &bytes_read);
info_ptr += bytes_read;
break;
}
/* FALLTHROUGH */
+ case DW_FORM_line_strp:
+ if (!cu->per_cu->is_dwz)
+ {
+ DW_STRING (attr) = read_indirect_line_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 ();
case DW_FORM_indirect:
form = read_unsigned_leb128 (abfd, info_ptr, &bytes_read);
info_ptr += bytes_read;
- info_ptr = read_attribute_value (reader, attr, form, info_ptr);
+ if (form == DW_FORM_implicit_const)
+ {
+ implicit_const = read_signed_leb128 (abfd, info_ptr, &bytes_read);
+ info_ptr += bytes_read;
+ }
+ info_ptr = read_attribute_value (reader, attr, form, implicit_const,
+ info_ptr);
+ break;
+ case DW_FORM_implicit_const:
+ DW_SND (attr) = implicit_const;
break;
case DW_FORM_GNU_addr_index:
if (reader->dwo_file == NULL)
const gdb_byte *info_ptr)
{
attr->name = abbrev->name;
- return read_attribute_value (reader, attr, abbrev->form, info_ptr);
+ return read_attribute_value (reader, attr, abbrev->form,
+ abbrev->implicit_const, info_ptr);
}
/* Read dwarf information from a buffer. */
return (const char *) buf;
}
+/* Return pointer to string at section SECT offset STR_OFFSET with error
+ reporting strings FORM_NAME and SECT_NAME. */
+
static const char *
-read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
-{
- dwarf2_read_section (dwarf2_per_objfile->objfile, &dwarf2_per_objfile->str);
- if (dwarf2_per_objfile->str.buffer == NULL)
- error (_("DW_FORM_strp used without .debug_str section [in module %s]"),
- bfd_get_filename (abfd));
- if (str_offset >= dwarf2_per_objfile->str.size)
- error (_("DW_FORM_strp pointing outside of "
- ".debug_str section [in module %s]"),
- bfd_get_filename (abfd));
+read_indirect_string_at_offset_from (bfd *abfd, LONGEST str_offset,
+ struct dwarf2_section_info *sect,
+ const char *form_name,
+ const char *sect_name)
+{
+ dwarf2_read_section (dwarf2_per_objfile->objfile, sect);
+ if (sect->buffer == NULL)
+ error (_("%s used without %s section [in module %s]"),
+ form_name, sect_name, bfd_get_filename (abfd));
+ if (str_offset >= sect->size)
+ error (_("%s pointing outside of %s section [in module %s]"),
+ form_name, sect_name, bfd_get_filename (abfd));
gdb_assert (HOST_CHAR_BIT == 8);
- if (dwarf2_per_objfile->str.buffer[str_offset] == '\0')
+ if (sect->buffer[str_offset] == '\0')
return NULL;
- return (const char *) (dwarf2_per_objfile->str.buffer + str_offset);
+ return (const char *) (sect->buffer + str_offset);
+}
+
+/* Return pointer to string at .debug_str offset STR_OFFSET. */
+
+static const char *
+read_indirect_string_at_offset (bfd *abfd, LONGEST str_offset)
+{
+ return read_indirect_string_at_offset_from (abfd, str_offset,
+ &dwarf2_per_objfile->str,
+ "DW_FORM_strp", ".debug_str");
+}
+
+/* Return pointer to string at .debug_line_str offset STR_OFFSET. */
+
+static const char *
+read_indirect_line_string_at_offset (bfd *abfd, LONGEST str_offset)
+{
+ return read_indirect_string_at_offset_from (abfd, str_offset,
+ &dwarf2_per_objfile->line_str,
+ "DW_FORM_line_strp",
+ ".debug_line_str");
}
/* Read a string at offset STR_OFFSET in the .debug_str section from
return (const char *) (dwz->str.buffer + str_offset);
}
+/* Return pointer to string at .debug_str offset as read from BUF.
+ BUF is assumed to be in a compilation unit described by CU_HEADER.
+ Return *BYTES_READ_PTR count of bytes read from BUF. */
+
static const char *
read_indirect_string (bfd *abfd, const gdb_byte *buf,
const struct comp_unit_head *cu_header,
return read_indirect_string_at_offset (abfd, str_offset);
}
-static ULONGEST
+/* Return pointer to string at .debug_line_str offset as read from BUF.
+ BUF is assumed to be in a compilation unit described by CU_HEADER.
+ Return *BYTES_READ_PTR count of bytes read from BUF. */
+
+static const char *
+read_indirect_line_string (bfd *abfd, const gdb_byte *buf,
+ const struct comp_unit_head *cu_header,
+ unsigned int *bytes_read_ptr)
+{
+ LONGEST str_offset = read_offset (abfd, buf, cu_header, bytes_read_ptr);
+
+ return read_indirect_line_string_at_offset (abfd, str_offset);
+}
+
+ULONGEST
read_unsigned_leb128 (bfd *abfd, const gdb_byte *buf,
- unsigned int *bytes_read_ptr)
+ unsigned int *bytes_read_ptr)
{
ULONGEST result;
unsigned int num_read;
if (attr != NULL)
{
- if (attr->form == DW_FORM_strp || attr->form == DW_FORM_string
- || attr->form == DW_FORM_GNU_strp_alt)
+ if (attr->form == DW_FORM_strp || attr->form == DW_FORM_line_strp
+ || attr->form == DW_FORM_string || attr->form == DW_FORM_GNU_strp_alt)
str = DW_STRING (attr);
else
complaint (&symfile_complaints,
return section;
}
+/* Forwarding function for read_formatted_entries. */
+
+static void
+add_include_dir_stub (struct line_header *lh, const char *name,
+ unsigned int dir_index, unsigned int mod_time,
+ unsigned int length)
+{
+ add_include_dir (lh, name);
+}
+
+/* Read directory or file name entry format, starting with byte of
+ format count entries, ULEB128 pairs of entry formats, ULEB128 of
+ entries count and the entries themselves in the described entry
+ format. */
+
+static void
+read_formatted_entries (bfd *abfd, const gdb_byte **bufp,
+ struct line_header *lh,
+ const struct comp_unit_head *cu_header,
+ void (*callback) (struct line_header *lh,
+ const char *name,
+ unsigned int dir_index,
+ unsigned int mod_time,
+ unsigned int length))
+{
+ gdb_byte format_count, formati;
+ ULONGEST data_count, datai;
+ const gdb_byte *buf = *bufp;
+ const gdb_byte *format_header_data;
+ int i;
+ unsigned int bytes_read;
+
+ format_count = read_1_byte (abfd, buf);
+ buf += 1;
+ format_header_data = buf;
+ for (formati = 0; formati < format_count; formati++)
+ {
+ read_unsigned_leb128 (abfd, buf, &bytes_read);
+ buf += bytes_read;
+ read_unsigned_leb128 (abfd, buf, &bytes_read);
+ buf += bytes_read;
+ }
+
+ data_count = read_unsigned_leb128 (abfd, buf, &bytes_read);
+ buf += bytes_read;
+ for (datai = 0; datai < data_count; datai++)
+ {
+ const gdb_byte *format = format_header_data;
+ struct file_entry fe;
+
+ memset (&fe, 0, sizeof (fe));
+
+ for (formati = 0; formati < format_count; formati++)
+ {
+ ULONGEST content_type, form;
+ const char *string_trash;
+ const char **stringp = &string_trash;
+ unsigned int uint_trash, *uintp = &uint_trash;
+
+ content_type = read_unsigned_leb128 (abfd, format, &bytes_read);
+ format += bytes_read;
+ switch (content_type)
+ {
+ case DW_LNCT_path:
+ stringp = &fe.name;
+ break;
+ case DW_LNCT_directory_index:
+ uintp = &fe.dir_index;
+ break;
+ case DW_LNCT_timestamp:
+ uintp = &fe.mod_time;
+ break;
+ case DW_LNCT_size:
+ uintp = &fe.length;
+ break;
+ case DW_LNCT_MD5:
+ break;
+ default:
+ complaint (&symfile_complaints,
+ _("Unknown format content type %s"),
+ pulongest (content_type));
+ }
+
+ form = read_unsigned_leb128 (abfd, format, &bytes_read);
+ format += bytes_read;
+ switch (form)
+ {
+ case DW_FORM_string:
+ *stringp = read_direct_string (abfd, buf, &bytes_read);
+ buf += bytes_read;
+ break;
+
+ case DW_FORM_line_strp:
+ *stringp = read_indirect_line_string (abfd, buf, cu_header, &bytes_read);
+ buf += bytes_read;
+ break;
+
+ case DW_FORM_data1:
+ *uintp = read_1_byte (abfd, buf);
+ buf += 1;
+ break;
+
+ case DW_FORM_data2:
+ *uintp = read_2_bytes (abfd, buf);
+ buf += 2;
+ break;
+
+ case DW_FORM_data4:
+ *uintp = read_4_bytes (abfd, buf);
+ buf += 4;
+ break;
+
+ case DW_FORM_data8:
+ *uintp = read_8_bytes (abfd, buf);
+ buf += 8;
+ break;
+
+ case DW_FORM_udata:
+ *uintp = read_unsigned_leb128 (abfd, buf, &bytes_read);
+ buf += bytes_read;
+ break;
+
+ case DW_FORM_block:
+ /* It is valid only for DW_LNCT_timestamp which is ignored by
+ current GDB. */
+ break;
+ }
+ }
+
+ callback (lh, fe.name, fe.dir_index, fe.mod_time, fe.length);
+ }
+
+ *bufp = buf;
+}
+
/* 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.
lh->statement_program_end = line_ptr + lh->total_length;
lh->version = read_2_bytes (abfd, line_ptr);
line_ptr += 2;
- if (lh->version > 4)
+ if (lh->version > 5)
{
/* This is a version we don't understand. The format could have
changed in ways we don't handle properly so just punt. */
_("unsupported version in .debug_line section"));
return NULL;
}
+ if (lh->version >= 5)
+ {
+ gdb_byte segment_selector_size;
+
+ /* Skip address size. */
+ read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+
+ segment_selector_size = read_1_byte (abfd, line_ptr);
+ line_ptr += 1;
+ if (segment_selector_size != 0)
+ {
+ complaint (&symfile_complaints,
+ _("unsupported segment selector size %u "
+ "in .debug_line section"),
+ segment_selector_size);
+ return NULL;
+ }
+ }
lh->header_length = read_offset_1 (abfd, line_ptr, offset_size);
line_ptr += offset_size;
lh->minimum_instruction_length = read_1_byte (abfd, line_ptr);
line_ptr += 1;
}
- /* Read directory table. */
- while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+ if (lh->version >= 5)
{
- line_ptr += bytes_read;
- add_include_dir (lh, cur_dir);
- }
- line_ptr += bytes_read;
+ /* Read directory table. */
+ read_formatted_entries (abfd, &line_ptr, lh, &cu->header,
+ add_include_dir_stub);
- /* Read file name table. */
- while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+ /* Read file name table. */
+ read_formatted_entries (abfd, &line_ptr, lh, &cu->header, add_file_name);
+ }
+ else
{
- unsigned int dir_index, mod_time, length;
-
- line_ptr += bytes_read;
- dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ /* Read directory table. */
+ while ((cur_dir = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+ {
+ line_ptr += bytes_read;
+ add_include_dir (lh, cur_dir);
+ }
line_ptr += bytes_read;
- add_file_name (lh, cur_file, dir_index, mod_time, length);
+ /* Read file name table. */
+ while ((cur_file = read_direct_string (abfd, line_ptr, &bytes_read)) != NULL)
+ {
+ unsigned int dir_index, mod_time, length;
+
+ line_ptr += bytes_read;
+ dir_index = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ mod_time = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+ length = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ line_ptr += bytes_read;
+
+ add_file_name (lh, cur_file, dir_index, mod_time, length);
+ }
+ line_ptr += bytes_read;
}
- line_ptr += bytes_read;
lh->statement_program_start = line_ptr;
if (line_ptr > (section->buffer + section->size))
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_exprloc:
+ case DW_FORM_data16:
blk = DW_BLOCK (attr);
if (TYPE_LENGTH (type) != blk->size)
dwarf2_const_value_length_mismatch_complaint (name, blk->size,
{
if (name && cu->language == language_cplus)
{
- char *canon_name = cp_canonicalize_string (name);
+ std::string canon_name = cp_canonicalize_string (name);
- if (canon_name != NULL)
+ if (!canon_name.empty ())
{
- if (strcmp (canon_name, name) != 0)
- name = (const char *) obstack_copy0 (obstack, canon_name,
- strlen (canon_name));
- xfree (canon_name);
+ if (canon_name != name)
+ name = (const char *) obstack_copy0 (obstack,
+ canon_name.c_str (),
+ canon_name.length ());
}
}
fprintf_unfiltered (f, "expression: size %s",
pulongest (DW_BLOCK (&die->attrs[i])->size));
break;
+ case DW_FORM_data16:
+ fprintf_unfiltered (f, "constant of 16 bytes");
+ break;
case DW_FORM_ref_addr:
fprintf_unfiltered (f, "ref address: ");
fputs_filtered (hex_string (DW_UNSND (&die->attrs[i])), f);
break;
case DW_FORM_string:
case DW_FORM_strp:
+ case DW_FORM_line_strp:
case DW_FORM_GNU_str_index:
case DW_FORM_GNU_strp_alt:
fprintf_unfiltered (f, "string: \"%s\" (%s canonicalized)",
return DW_UNSND (attr);
else
{
+ /* For DW_FORM_data16 see attr_form_is_constant. */
complaint (&symfile_complaints,
_("Attribute value is not a constant (%s)"),
dwarf_form_name (attr->form));
case DW_FORM_block4:
case DW_FORM_block:
case DW_FORM_exprloc:
+ case DW_FORM_data16:
result = DW_BLOCK (attr)->data;
*len = DW_BLOCK (attr)->size;
break;
bytes += 8;
break;
+ case DW_FORM_data16:
+ bytes += 16;
+ break;
+
case DW_FORM_string:
read_direct_string (abfd, bytes, &bytes_read);
bytes += bytes_read;
unsigned int version, flags;
version = read_2_bytes (abfd, mac_ptr);
- if (version != 4)
+ if (version != 4 && version != 5)
{
complaint (&symfile_complaints,
_("unrecognized version `%d' in .debug_macro section"),
}
/* A helper for dwarf_decode_macros that handles the GNU extensions,
- including DW_MACRO_GNU_transparent_include. */
+ including DW_MACRO_import. */
static void
dwarf_decode_macro_bytes (bfd *abfd,
case 0:
break;
- case DW_MACRO_GNU_define:
- 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:
+ case DW_MACRO_define:
+ case DW_MACRO_undef:
+ case DW_MACRO_define_strp:
+ case DW_MACRO_undef_strp:
+ case DW_MACRO_define_sup:
+ case DW_MACRO_undef_sup:
{
unsigned int bytes_read;
int line;
line = read_unsigned_leb128 (abfd, mac_ptr, &bytes_read);
mac_ptr += bytes_read;
- if (macinfo_type == DW_MACRO_GNU_define
- || macinfo_type == DW_MACRO_GNU_undef)
+ if (macinfo_type == DW_MACRO_define
+ || macinfo_type == DW_MACRO_undef)
{
body = read_direct_string (abfd, mac_ptr, &bytes_read);
mac_ptr += bytes_read;
str_offset = read_offset_1 (abfd, mac_ptr, offset_size);
mac_ptr += offset_size;
- if (macinfo_type == DW_MACRO_GNU_define_indirect_alt
- || macinfo_type == DW_MACRO_GNU_undef_indirect_alt
+ if (macinfo_type == DW_MACRO_define_sup
+ || macinfo_type == DW_MACRO_undef_sup
|| section_is_dwz)
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
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_alt);
+ is_define = (macinfo_type == DW_MACRO_define
+ || macinfo_type == DW_MACRO_define_strp
+ || macinfo_type == DW_MACRO_define_sup);
if (! current_file)
{
/* DWARF violation as no main source is present. */
parse_macro_definition (current_file, line, body);
else
{
- gdb_assert (macinfo_type == DW_MACRO_GNU_undef
- || macinfo_type == DW_MACRO_GNU_undef_indirect
- || macinfo_type == DW_MACRO_GNU_undef_indirect_alt);
+ gdb_assert (macinfo_type == DW_MACRO_undef
+ || macinfo_type == DW_MACRO_undef_strp
+ || macinfo_type == DW_MACRO_undef_sup);
macro_undef (current_file, line, body);
}
}
break;
- case DW_MACRO_GNU_start_file:
+ case DW_MACRO_start_file:
{
unsigned int bytes_read;
int line, file;
if (at_commandline)
{
- /* This DW_MACRO_GNU_start_file was executed in the
+ /* This DW_MACRO_start_file was executed in the
pass one. */
at_commandline = 0;
}
}
break;
- case DW_MACRO_GNU_end_file:
+ case DW_MACRO_end_file:
if (! current_file)
complaint (&symfile_complaints,
_("macro debug info has an unmatched "
}
break;
- case DW_MACRO_GNU_transparent_include:
- case DW_MACRO_GNU_transparent_include_alt:
+ case DW_MACRO_import:
+ case DW_MACRO_import_sup:
{
LONGEST offset;
void **slot;
offset = read_offset_1 (abfd, mac_ptr, offset_size);
mac_ptr += offset_size;
- if (macinfo_type == DW_MACRO_GNU_transparent_include_alt)
+ if (macinfo_type == DW_MACRO_import_sup)
{
struct dwz_file *dwz = dwarf2_get_dwz_file ();
/* This has actually happened; see
http://sourceware.org/bugzilla/show_bug.cgi?id=13568. */
complaint (&symfile_complaints,
- _("recursive DW_MACRO_GNU_transparent_include in "
+ _("recursive DW_MACRO_import in "
".debug_macro section"));
}
else
unsigned int offset_size = cu->header.offset_size;
const gdb_byte *opcode_definitions[256];
struct cleanup *cleanup;
- htab_t include_hash;
void **slot;
struct dwarf2_section_info *section;
const char *section_name;
case 0:
break;
- case DW_MACRO_GNU_define:
- case DW_MACRO_GNU_undef:
+ case DW_MACRO_define:
+ case DW_MACRO_undef:
/* Only skip the data by MAC_PTR. */
{
unsigned int bytes_read;
}
break;
- case DW_MACRO_GNU_start_file:
+ case DW_MACRO_start_file:
{
unsigned int bytes_read;
int line, file;
}
break;
- case DW_MACRO_GNU_end_file:
+ case DW_MACRO_end_file:
/* No data to skip by MAC_PTR. */
break;
- 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:
+ case DW_MACRO_define_strp:
+ case DW_MACRO_undef_strp:
+ case DW_MACRO_define_sup:
+ case DW_MACRO_undef_sup:
{
unsigned int bytes_read;
}
break;
- case DW_MACRO_GNU_transparent_include:
- case DW_MACRO_GNU_transparent_include_alt:
+ case DW_MACRO_import:
+ case DW_MACRO_import_sup:
/* Note that, according to the spec, a transparent include
- chain cannot call DW_MACRO_GNU_start_file. So, we can just
+ chain cannot call DW_MACRO_start_file. So, we can just
skip this opcode. */
mac_ptr += offset_size;
break;
command-line macro definitions/undefinitions. This flag is unset when we
reach the first DW_MACINFO_start_file entry. */
- include_hash = htab_create_alloc (1, htab_hash_pointer, htab_eq_pointer,
- NULL, xcalloc, xfree);
- cleanup = make_cleanup_htab_delete (include_hash);
+ htab_up include_hash (htab_create_alloc (1, htab_hash_pointer,
+ htab_eq_pointer,
+ NULL, xcalloc, xfree));
mac_ptr = section->buffer + offset;
- slot = htab_find_slot (include_hash, mac_ptr, INSERT);
+ slot = htab_find_slot (include_hash.get (), mac_ptr, INSERT);
*slot = (void *) mac_ptr;
dwarf_decode_macro_bytes (abfd, mac_ptr, mac_end,
current_file, lh, section,
- section_is_gnu, 0, offset_size, include_hash);
- do_cleanups (cleanup);
+ section_is_gnu, 0, offset_size,
+ include_hash.get ());
}
/* Check if the attribute's form is a DW_FORM_block*
(lineptr, loclistptr, macptr or rangelistptr). The DWARF spec says
that, if an attribute's can be either a constant or one of the
section offset classes, DW_FORM_data4 and DW_FORM_data8 should be
- taken as section offsets, not constants. */
+ taken as section offsets, not constants.
+
+ DW_FORM_data16 is not considered as dwarf2_get_attr_constant_value
+ cannot handle that. */
static int
attr_form_is_constant (const struct attribute *attr)
cu_debug_loc_section (struct dwarf2_cu *cu)
{
if (cu->dwo_unit)
- return &cu->dwo_unit->dwo_file->sections.loc;
- return &dwarf2_per_objfile->loc;
+ {
+ struct dwo_sections *sections = &cu->dwo_unit->dwo_file->sections;
+
+ return cu->header.version >= 5 ? §ions->loclists : §ions->loc;
+ }
+ return (cu->header.version >= 5 ? &dwarf2_per_objfile->loclists
+ : &dwarf2_per_objfile->loc);
}
/* A helper function that fills in a dwarf2_loclist_baton. */
info_ptr = per_cu->section->buffer + per_cu->offset.sect_off;
memset (cu_headerp, 0, sizeof (*cu_headerp));
- read_comp_unit_head (cu_headerp, info_ptr, per_cu->objfile->obfd);
+ read_comp_unit_head (cu_headerp, info_ptr, per_cu->section,
+ rcuh_kind::COMPILE);
return cu_headerp;
}
return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
}
+/* Return DWARF version number of PER_CU. */
+
+short
+dwarf2_version (struct dwarf2_per_cu_data *per_cu)
+{
+ return per_cu->dwarf_version;
+}
+
/* Locate the .debug_info compilation unit from CU's objfile which contains
the DIE at OFFSET. Raises an error on failure. */
error (_("couldn't data write to file"));
}
-/* Unlink a file if the argument is not NULL. */
-
-static void
-unlink_if_set (void *p)
-{
- char **filename = (char **) p;
- if (*filename)
- unlink (*filename);
-}
-
/* A helper struct used when iterating over debug_types. */
struct signatured_type_index_data
{
write_psymtabs_to_index (struct objfile *objfile, const char *dir)
{
struct cleanup *cleanup;
- char *filename, *cleanup_filename;
+ char *filename;
struct obstack contents, addr_obstack, constant_pool, symtab_obstack;
struct obstack cu_list, types_cu_list;
int i;
struct mapped_symtab *symtab;
offset_type val, size_of_contents, total_len;
struct stat st;
- htab_t psyms_seen;
- htab_t cu_index_htab;
struct psymtab_cu_index_map *psymtab_cu_index_map;
if (dwarf2_per_objfile->using_index)
if (!out_file)
error (_("Can't open `%s' for writing"), filename);
- cleanup_filename = filename;
- make_cleanup (unlink_if_set, &cleanup_filename);
+ gdb::unlinker unlink_file (filename);
symtab = create_mapped_symtab ();
make_cleanup (cleanup_mapped_symtab, symtab);
obstack_init (&types_cu_list);
make_cleanup_obstack_free (&types_cu_list);
- psyms_seen = htab_create_alloc (100, htab_hash_pointer, htab_eq_pointer,
- NULL, xcalloc, xfree);
- make_cleanup_htab_delete (psyms_seen);
+ htab_up psyms_seen (htab_create_alloc (100, htab_hash_pointer,
+ htab_eq_pointer,
+ NULL, xcalloc, xfree));
/* While we're scanning CU's create a table that maps a psymtab pointer
(which is what addrmap records) to its index (which is what is recorded
in the index file). This will later be needed to write the address
table. */
- cu_index_htab = htab_create_alloc (100,
- hash_psymtab_cu_index,
- eq_psymtab_cu_index,
- NULL, xcalloc, xfree);
- make_cleanup_htab_delete (cu_index_htab);
+ htab_up cu_index_htab (htab_create_alloc (100,
+ hash_psymtab_cu_index,
+ eq_psymtab_cu_index,
+ NULL, xcalloc, xfree));
psymtab_cu_index_map = XNEWVEC (struct psymtab_cu_index_map,
dwarf2_per_objfile->n_comp_units);
make_cleanup (xfree, psymtab_cu_index_map);
continue;
if (psymtab->user == NULL)
- recursively_write_psymbols (objfile, psymtab, symtab, psyms_seen, i);
+ recursively_write_psymbols (objfile, psymtab, symtab,
+ psyms_seen.get (), i);
map = &psymtab_cu_index_map[i];
map->psymtab = psymtab;
map->cu_index = i;
- slot = htab_find_slot (cu_index_htab, map, INSERT);
+ slot = htab_find_slot (cu_index_htab.get (), map, INSERT);
gdb_assert (slot != NULL);
gdb_assert (*slot == NULL);
*slot = map;
}
/* Dump the address map. */
- write_address_map (objfile, &addr_obstack, cu_index_htab);
+ write_address_map (objfile, &addr_obstack, cu_index_htab.get ());
/* Write out the .debug_type entries, if any. */
if (dwarf2_per_objfile->signatured_types)
sig_data.objfile = objfile;
sig_data.symtab = symtab;
sig_data.types_list = &types_cu_list;
- sig_data.psyms_seen = psyms_seen;
+ sig_data.psyms_seen = psyms_seen.get ();
sig_data.cu_index = dwarf2_per_objfile->n_comp_units;
htab_traverse_noresize (dwarf2_per_objfile->signatured_types,
write_one_signatured_type, &sig_data);
fclose (out_file);
- /* We want to keep the file, so we set cleanup_filename to NULL
- here. See unlink_if_set. */
- cleanup_filename = NULL;
+ /* We want to keep the file. */
+ unlink_file.keep ();
do_cleanups (cleanup);
}