static const gdb_byte *read_attribute (const struct die_reader_specs *,
struct attribute *,
const struct attr_abbrev *,
- const gdb_byte *);
+ const gdb_byte *,
+ bool allow_reprocess = true);
+/* Note that the default for TAG is chosen because it only matters
+ when reading the top-level DIE, and that function is careful to
+ pass the correct tag. */
static void read_attribute_reprocess (const struct die_reader_specs *reader,
- struct attribute *attr, dwarf_tag tag);
+ struct attribute *attr,
+ dwarf_tag tag = DW_TAG_padding);
static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
static const gdb_byte *read_full_die_1 (const struct die_reader_specs *,
struct die_info **, const gdb_byte *,
- int);
+ int, bool);
-static const gdb_byte *read_full_die (const struct die_reader_specs *,
- struct die_info **, const gdb_byte *);
+static const gdb_byte *read_toplevel_die (const struct die_reader_specs *,
+ struct die_info **,
+ const gdb_byte *,
+ gdb::array_view<attribute *> = {});
static void process_die (struct die_info *, struct dwarf2_cu *);
dwarf2_per_bfd::~dwarf2_per_bfd ()
{
+ /* Data from the per-BFD may be needed when finalizing the cooked
+ index table, so wait here while this happens. */
+ if (index_table != nullptr)
+ index_table->wait_completely ();
+
for (auto &per_cu : all_units)
{
per_cu->imported_symtabs_free ();
try
{
dwarf2_build_psymtabs_hard (per_objfile);
-
- /* (maybe) store an index in the cache. */
- global_index_cache.store (per_objfile);
}
catch (const gdb_exception_error &except)
{
struct objfile *objfile = per_objfile->objfile;
bfd *abfd;
const gdb_byte *begin_info_ptr, *info_ptr;
- struct attribute *comp_dir, *stmt_list, *low_pc, *high_pc, *ranges;
- int i,num_extra_attrs;
struct dwarf2_section_info *dwo_abbrev_section;
- struct die_info *comp_unit_die;
/* At most one of these may be provided. */
gdb_assert ((stub_comp_unit_die != NULL) + (stub_comp_dir != NULL) <= 1);
- /* These attributes aren't processed until later:
- DW_AT_stmt_list, DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges.
- DW_AT_comp_dir is used now, to find the DWO file, but it is also
- referenced later. However, these attributes are found in the stub
- which we won't have later. In order to not impose this complication
- on the rest of the code, we read them here and copy them to the
- DWO CU/TU die. */
+ /* These attributes aren't processed until later: DW_AT_stmt_list,
+ DW_AT_low_pc, DW_AT_high_pc, DW_AT_ranges, DW_AT_comp_dir.
+ However, these attributes are found in the stub which we won't
+ have later. In order to not impose this complication on the rest
+ of the code, we read them here and copy them to the DWO CU/TU
+ die. */
- stmt_list = NULL;
- low_pc = NULL;
- high_pc = NULL;
- ranges = NULL;
- comp_dir = NULL;
+ /* We store them all in an array. */
+ struct attribute *attributes[5] {};
+ /* Next available element of the attributes array. */
+ int next_attr_idx = 0;
+
+ /* Push an element into ATTRIBUTES. */
+ auto push_back = [&] (struct attribute *attr)
+ {
+ gdb_assert (next_attr_idx < ARRAY_SIZE (attributes));
+ if (attr != nullptr)
+ attributes[next_attr_idx++] = attr;
+ };
if (stub_comp_unit_die != NULL)
{
/* For TUs in DWO files, the DW_AT_stmt_list attribute lives in the
DWO file. */
if (!per_cu->is_debug_types)
- stmt_list = dwarf2_attr (stub_comp_unit_die, DW_AT_stmt_list, cu);
- low_pc = dwarf2_attr (stub_comp_unit_die, DW_AT_low_pc, cu);
- high_pc = dwarf2_attr (stub_comp_unit_die, DW_AT_high_pc, cu);
- ranges = dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu);
- comp_dir = dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu);
+ push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_stmt_list, cu));
+ push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_low_pc, cu));
+ push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_high_pc, cu));
+ push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_ranges, cu));
+ push_back (dwarf2_attr (stub_comp_unit_die, DW_AT_comp_dir, cu));
cu->addr_base = stub_comp_unit_die->addr_base ();
/* There should be a DW_AT_GNU_ranges_base attribute here (if needed).
- We need the value before we can process DW_AT_ranges values from the
- DWO. */
+ We need the value before we can process DW_AT_ranges values from the
+ DWO. */
cu->gnu_ranges_base = stub_comp_unit_die->gnu_ranges_base ();
/* For DWARF5: record the DW_AT_rnglists_base value from the skeleton. If
- there are attributes of form DW_FORM_rnglistx in the skeleton, they'll
- need the rnglists base. Attributes of form DW_FORM_rnglistx in the
- split unit don't use it, as the DWO has its own .debug_rnglists.dwo
- section. */
+ there are attributes of form DW_FORM_rnglistx in the skeleton, they'll
+ need the rnglists base. Attributes of form DW_FORM_rnglistx in the
+ split unit don't use it, as the DWO has its own .debug_rnglists.dwo
+ section. */
cu->rnglists_base = stub_comp_unit_die->rnglists_base ();
}
else if (stub_comp_dir != NULL)
{
/* Reconstruct the comp_dir attribute to simplify the code below. */
- comp_dir = OBSTACK_ZALLOC (&cu->comp_unit_obstack, struct attribute);
+ struct attribute *comp_dir = OBSTACK_ZALLOC (&cu->comp_unit_obstack,
+ struct attribute);
comp_dir->name = DW_AT_comp_dir;
comp_dir->form = DW_FORM_string;
comp_dir->set_string_noncanonical (stub_comp_dir);
+ push_back (comp_dir);
}
/* Set up for reading the DWO CU/TU. */
init_cu_die_reader (result_reader, cu, section, dwo_unit->dwo_file,
result_dwo_abbrev_table->get ());
- /* Read in the die, but leave space to copy over the attributes
- from the stub. This has the benefit of simplifying the rest of
- the code - all the work to maintain the illusion of a single
+ /* Read in the die, filling in the attributes from the stub. This
+ has the benefit of simplifying the rest of the code - all the
+ work to maintain the illusion of a single
DW_TAG_{compile,type}_unit DIE is done here. */
- num_extra_attrs = ((stmt_list != NULL)
- + (low_pc != NULL)
- + (high_pc != NULL)
- + (ranges != NULL)
- + (comp_dir != NULL));
- info_ptr = read_full_die_1 (result_reader, result_comp_unit_die, info_ptr,
- num_extra_attrs);
-
- /* Copy over the attributes from the stub to the DIE we just read in. */
- comp_unit_die = *result_comp_unit_die;
- i = comp_unit_die->num_attrs;
- if (stmt_list != NULL)
- comp_unit_die->attrs[i++] = *stmt_list;
- if (low_pc != NULL)
- comp_unit_die->attrs[i++] = *low_pc;
- if (high_pc != NULL)
- comp_unit_die->attrs[i++] = *high_pc;
- if (ranges != NULL)
- comp_unit_die->attrs[i++] = *ranges;
- if (comp_dir != NULL)
- comp_unit_die->attrs[i++] = *comp_dir;
- comp_unit_die->num_attrs += num_extra_attrs;
-
- if (dwarf_die_debug)
- {
- gdb_printf (gdb_stdlog,
- "Read die from %s@0x%x of %s:\n",
- section->get_name (),
- (unsigned) (begin_info_ptr - section->buffer),
- bfd_get_filename (abfd));
- comp_unit_die->dump (dwarf_die_debug);
- }
+ info_ptr = read_toplevel_die (result_reader, result_comp_unit_die, info_ptr,
+ gdb::make_array_view (attributes,
+ next_attr_idx));
/* Skip dummy compilation units. */
if (info_ptr >= begin_info_ptr + dwo_unit->length
/* Read the top level CU/TU die. */
init_cu_die_reader (this, cu, section, NULL, abbrev_table);
- info_ptr = read_full_die (this, &comp_unit_die, info_ptr);
+ info_ptr = read_toplevel_die (this, &comp_unit_die, info_ptr);
if (skip_partial && comp_unit_die->tag == DW_TAG_partial_unit)
{
init_cu_die_reader (this, m_new_cu.get (), section, dwo_file,
m_abbrev_table_holder.get ());
- info_ptr = read_full_die (this, &comp_unit_die, info_ptr);
+ info_ptr = read_toplevel_die (this, &comp_unit_die, info_ptr);
}
\f
indexes.push_back (index_storage.release ());
indexes.shrink_to_fit ();
- cooked_index *vec = new cooked_index (std::move (indexes));
+ cooked_index *vec = new cooked_index (std::move (indexes), per_bfd);
per_bfd->index_table.reset (vec);
const cooked_index_entry *main_entry = vec->get_main ();
if (main_entry != nullptr)
- set_objfile_main_name (objfile, main_entry->name,
- main_entry->per_cu->lang ());
+ {
+ /* We only do this for names not requiring canonicalization. At
+ this point in the process names have not been canonicalized.
+ However, currently, languages that require this step also do
+ not use DW_AT_main_subprogram. An assert is appropriate here
+ because this filtering is done in get_main. */
+ enum language lang = main_entry->per_cu->lang ();
+ gdb_assert (!language_requires_canonicalization (lang));
+ const char *full_name = main_entry->full_name (&per_bfd->obstack, true);
+ set_objfile_main_name (objfile, full_name, lang);
+ }
dwarf_read_debug_printf ("Done building psymtabs of %s",
objfile_name (objfile));
/* The only abbrev we care about is DW_AT_sibling. */
if (do_skip_children && abbrev->attrs[i].name == DW_AT_sibling)
{
- read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
+ /* Note there is no need for the extra work of
+ "reprocessing" here, so we pass false for that
+ argument. */
+ read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr, false);
if (attr.form == DW_FORM_ref_addr)
complaint (_("ignoring absolute DW_AT_sibling"));
else
if (cu->has_loclist && gcc_4_minor >= 5)
cust->set_locations_valid (true);
- if (gcc_4_minor >= 5)
+ int major, minor;
+ if (cu->producer != nullptr
+ && producer_is_gcc (cu->producer, &major, &minor)
+ && (major < 4 || (major == 4 && minor < 5)))
+ /* Don't trust gcc < 4.5.x. */
+ cust->set_epilogue_unwind_valid (false);
+ else
cust->set_epilogue_unwind_valid (true);
cust->set_call_site_htab (cu->call_site_htab);
|| cu->lang () == language_d
|| cu->lang () == language_rust)
&& cu->processing_has_namespace_info)
- block_set_scope (block, determine_prefix (die, cu),
- &objfile->objfile_obstack);
+ block->set_scope (determine_prefix (die, cu),
+ &objfile->objfile_obstack);
/* If we have address ranges, record them. */
dwarf2_record_block_ranges (die, block, baseaddr, cu);
&& !die_is_declaration (die, cu))
{
if (die->tag == DW_TAG_namelist_item)
- {
+ {
/* Typically, DW_TAG_namelist_item are references to namelist items.
If so, follow that reference. */
struct attribute *attr1 = dwarf2_attr (die, DW_AT_namelist_item, cu);
struct die_info *item_die = nullptr;
struct dwarf2_cu *item_cu = cu;
- if (attr1->form_is_ref ())
+ if (attr1->form_is_ref ())
item_die = follow_die_ref (die, attr1, &item_cu);
if (item_die != nullptr)
die = item_die;
- }
+ }
/* Data member other than a C++ static data member. */
/* Get type of field. */
memcpy (type->fields (), fields.data (),
sizeof (struct field) * fields.size ());
}
+ else
+ flag_enum = 0;
if (unsigned_enum)
type->set_is_unsigned (true);
&len);
if (ptr - blk->data + len <= blk->size)
{
- mpz_import (value->val, len,
- bfd_big_endian (cu->per_objfile->objfile->obfd.get ())
- ? 1 : -1,
- 1, 0, 0, ptr);
+ value->read (gdb::make_array_view (ptr, len),
+ bfd_big_endian (cu->per_objfile->objfile->obfd.get ())
+ ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE,
+ true);
return;
}
}
else if (attr->form_is_block ())
{
dwarf_block *blk = attr->as_block ();
- mpz_import (value->val, blk->size,
- bfd_big_endian (cu->per_objfile->objfile->obfd.get ())
- ? 1 : -1,
- 1, 0, 0, blk->data);
+ value->read (gdb::make_array_view (blk->data, blk->size),
+ bfd_big_endian (cu->per_objfile->objfile->obfd.get ())
+ ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE,
+ true);
}
else
*value = gdb_mpz (attr->constant_value (1));
gdb_mpz denom (1);
get_dwarf2_rational_constant (die, cu, &num, &denom);
- if (mpz_sgn (num.val) == -1 && mpz_sgn (denom.val) == -1)
+ if (num < 0 && denom < 0)
{
- mpz_neg (num.val, num.val);
- mpz_neg (denom.val, denom.val);
+ num.negate ();
+ denom.negate ();
}
- else if (mpz_sgn (num.val) == -1)
+ else if (num < 0)
{
complaint (_("unexpected negative value for DW_AT_GNU_numerator"
" in DIE at %s"),
sect_offset_str (die->sect_off));
return;
}
- else if (mpz_sgn (denom.val) == -1)
+ else if (denom < 0)
{
complaint (_("unexpected negative value for DW_AT_GNU_denominator"
" in DIE at %s"),
return false;
std::string copy (&encoding[start], k - start);
- if (mpz_set_str (result->val, copy.c_str (), 10) == -1)
- return false;
-
- return true;
+ return result->set (copy.c_str (), 10);
}
/* Scan two numbers from ENCODING at OFFSET, assuming the string is of
else if (attr->name == DW_AT_binary_scale)
{
LONGEST scale_exp = attr->constant_value (0);
- gdb_mpz *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+ gdb_mpz &num_or_denom = scale_exp > 0 ? scale_num : scale_denom;
- mpz_mul_2exp (num_or_denom->val, num_or_denom->val, std::abs (scale_exp));
+ num_or_denom <<= std::abs (scale_exp);
}
else if (attr->name == DW_AT_decimal_scale)
{
LONGEST scale_exp = attr->constant_value (0);
- gdb_mpz *num_or_denom = scale_exp > 0 ? &scale_num : &scale_denom;
+ gdb_mpz &num_or_denom = scale_exp > 0 ? scale_num : scale_denom;
- mpz_ui_pow_ui (num_or_denom->val, 10, std::abs (scale_exp));
+ num_or_denom = gdb_mpz::pow (10, std::abs (scale_exp));
}
else if (attr->name == DW_AT_small)
{
sect_offset_str (die->sect_off));
}
- gdb_mpq &scaling_factor = type->fixed_point_info ().scaling_factor;
- mpz_set (mpq_numref (scaling_factor.val), scale_num.val);
- mpz_set (mpq_denref (scaling_factor.val), scale_denom.val);
- mpq_canonicalize (scaling_factor.val);
+ type->fixed_point_info ().scaling_factor = gdb_mpq (scale_num, scale_denom);
}
/* The gnat-encoding suffix for fixed point. */
gdb_mpz num (1), denom (1);
get_dwarf2_rational_constant (scale_die, cu, &num, &denom);
- return mpz_sgn (num.val) == 0 && mpz_sgn (denom.val) == 0;
+ return num == 0 && denom == 0;
}
/* Initialise and return a floating point type of size BITS suitable for
struct die_info *die;
const gdb_byte *cur_ptr;
- cur_ptr = read_full_die_1 (reader, &die, info_ptr, 0);
+ cur_ptr = read_full_die_1 (reader, &die, info_ptr, 0, true);
if (die == NULL)
{
*new_info_ptr = cur_ptr;
static const gdb_byte *
read_full_die_1 (const struct die_reader_specs *reader,
struct die_info **diep, const gdb_byte *info_ptr,
- int num_extra_attrs)
+ int num_extra_attrs, bool allow_reprocess)
{
unsigned int abbrev_number, bytes_read, i;
const struct abbrev_info *abbrev;
attributes. */
die->num_attrs = abbrev->num_attrs;
- bool any_need_reprocess = false;
for (i = 0; i < abbrev->num_attrs; ++i)
- {
- info_ptr = read_attribute (reader, &die->attrs[i], &abbrev->attrs[i],
- info_ptr);
- if (die->attrs[i].requires_reprocessing_p ())
- any_need_reprocess = true;
- }
+ info_ptr = read_attribute (reader, &die->attrs[i], &abbrev->attrs[i],
+ info_ptr, allow_reprocess);
- struct attribute *attr = die->attr (DW_AT_str_offsets_base);
+ *diep = die;
+ return info_ptr;
+}
+
+/* Read a die and all its attributes.
+ Set DIEP to point to a newly allocated die with its information,
+ except for its child, sibling, and parent fields. */
+
+static const gdb_byte *
+read_toplevel_die (const struct die_reader_specs *reader,
+ struct die_info **diep, const gdb_byte *info_ptr,
+ gdb::array_view<attribute *> extra_attrs)
+{
+ const gdb_byte *result;
+ struct dwarf2_cu *cu = reader->cu;
+
+ result = read_full_die_1 (reader, diep, info_ptr, extra_attrs.size (),
+ false);
+
+ /* Copy in the extra attributes, if any. */
+ attribute *next = &(*diep)->attrs[(*diep)->num_attrs];
+ for (attribute *extra : extra_attrs)
+ *next++ = *extra;
+
+ struct attribute *attr = (*diep)->attr (DW_AT_str_offsets_base);
if (attr != nullptr && attr->form_is_unsigned ())
cu->str_offsets_base = attr->as_unsigned ();
- attr = die->attr (DW_AT_loclists_base);
+ attr = (*diep)->attr (DW_AT_loclists_base);
if (attr != nullptr)
cu->loclist_base = attr->as_unsigned ();
- auto maybe_addr_base = die->addr_base ();
+ auto maybe_addr_base = (*diep)->addr_base ();
if (maybe_addr_base.has_value ())
cu->addr_base = *maybe_addr_base;
- attr = die->attr (DW_AT_rnglists_base);
+ attr = (*diep)->attr (DW_AT_rnglists_base);
if (attr != nullptr)
cu->rnglists_base = attr->as_unsigned ();
- if (any_need_reprocess)
+ for (int i = 0; i < (*diep)->num_attrs; ++i)
{
- for (i = 0; i < abbrev->num_attrs; ++i)
- {
- if (die->attrs[i].requires_reprocessing_p ())
- read_attribute_reprocess (reader, &die->attrs[i], die->tag);
- }
+ if ((*diep)->attrs[i].form_requires_reprocessing ())
+ read_attribute_reprocess (reader, &(*diep)->attrs[i], (*diep)->tag);
}
- *diep = die;
- return info_ptr;
-}
-
-/* Read a die and all its attributes.
- Set DIEP to point to a newly allocated die with its information,
- except for its child, sibling, and parent fields. */
-
-static const gdb_byte *
-read_full_die (const struct die_reader_specs *reader,
- struct die_info **diep, const gdb_byte *info_ptr)
-{
- const gdb_byte *result;
- result = read_full_die_1 (reader, diep, info_ptr, 0);
+ (*diep)->num_attrs += extra_attrs.size ();
if (dwarf_die_debug)
{
{
attribute attr;
info_ptr = read_attribute (reader, &attr, &abbrev->attrs[i], info_ptr);
- if (attr.requires_reprocessing_p ())
- read_attribute_reprocess (reader, &attr, abbrev->tag);
/* Store the data if it is of an attribute we want to keep in a
partial symbol table. */
have linkage name present but name is absent. */
if (name != nullptr
|| (abbrev->tag != DW_TAG_subprogram
- && abbrev->tag != DW_TAG_inlined_subroutine
- && abbrev->tag != DW_TAG_entry_point))
+ && abbrev->tag != DW_TAG_inlined_subroutine
+ && abbrev->tag != DW_TAG_entry_point))
flags = flags | IS_LINKAGE;
m_index_storage->add (this_die, abbrev->tag, flags,
linkage_name, nullptr, m_per_cu);
static const gdb_byte *
read_attribute_value (const struct die_reader_specs *reader,
struct attribute *attr, unsigned form,
- LONGEST implicit_const, const gdb_byte *info_ptr)
+ LONGEST implicit_const, const gdb_byte *info_ptr,
+ bool allow_reprocess)
{
struct dwarf2_cu *cu = reader->cu;
dwarf2_per_objfile *per_objfile = cu->per_objfile;
attr->set_unsigned_reprocess (read_unsigned_leb128 (abfd, info_ptr,
&bytes_read));
info_ptr += bytes_read;
+ if (allow_reprocess)
+ read_attribute_reprocess (reader, attr);
}
break;
case DW_FORM_string:
attr->set_unsigned_reprocess (read_unsigned_leb128 (abfd, info_ptr,
&bytes_read));
info_ptr += bytes_read;
+ if (allow_reprocess)
+ read_attribute_reprocess (reader, attr);
}
break;
case DW_FORM_udata:
info_ptr += bytes_read;
}
info_ptr = read_attribute_value (reader, attr, form, implicit_const,
- info_ptr);
+ info_ptr, allow_reprocess);
break;
case DW_FORM_implicit_const:
attr->set_signed (implicit_const);
attr->set_unsigned_reprocess (read_unsigned_leb128 (abfd, info_ptr,
&bytes_read));
info_ptr += bytes_read;
+ if (allow_reprocess)
+ read_attribute_reprocess (reader, attr);
break;
case DW_FORM_strx:
case DW_FORM_strx1:
info_ptr += bytes_read;
}
attr->set_unsigned_reprocess (str_index);
+ if (allow_reprocess)
+ read_attribute_reprocess (reader, attr);
}
break;
default:
static const gdb_byte *
read_attribute (const struct die_reader_specs *reader,
struct attribute *attr, const struct attr_abbrev *abbrev,
- const gdb_byte *info_ptr)
+ const gdb_byte *info_ptr,
+ bool allow_reprocess)
{
attr->name = abbrev->name;
attr->string_is_canonical = 0;
- attr->requires_reprocessing = 0;
return read_attribute_value (reader, attr, abbrev->form,
- abbrev->implicit_const, info_ptr);
+ abbrev->implicit_const, info_ptr,
+ allow_reprocess);
}
/* See read.h. */
if (reader->cu->header.version >= 5)
{
/* We have a DWARF5 CU with a reference to a .debug_str_offsets section,
- so assume the .debug_str_offsets section is DWARF5 as well, and
+ so assume the .debug_str_offsets section is DWARF5 as well, and
parse the header. FIXME: Parse the header only once. */
unsigned int bytes_read = 0;
bfd *abfd = reader->dwo_file->sections.str_offsets.get_bfd_owner ();
}
/* Handle DW_LNE_set_address. */
- void handle_set_address (CORE_ADDR baseaddr, CORE_ADDR address)
+ void handle_set_address (CORE_ADDR address)
{
m_op_index = 0;
- address += baseaddr;
m_address = gdbarch_adjust_dwarf2_line (m_gdbarch, address, false);
}
state_machine.check_line_address (cu, line_ptr,
lowpc - baseaddr, address);
- state_machine.handle_set_address (baseaddr, address);
+ state_machine.handle_set_address (address);
}
break;
case DW_LNE_define_file:
name = dwarf2_name (die, cu);
if (name == nullptr && (die->tag == DW_TAG_subprogram
- || die->tag == DW_TAG_inlined_subroutine
- || die->tag == DW_TAG_entry_point))
+ || die->tag == DW_TAG_inlined_subroutine
+ || die->tag == DW_TAG_entry_point))
name = dw2_linkage_name (die, cu);
if (name)