#include "gdbsupport/selftest.h"
#include "rust-lang.h"
#include "gdbsupport/pathstuff.h"
+#include "count-one-bits.h"
+#include "debuginfod-support.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
/* dwarf2read.c's main "handle" on a TU symtab.
To simplify things we create an artificial CU that "includes" all the
type units using this stmt_list so that the rest of the code still has
- a "per_cu" handle on the symtab.
- This PER_CU is recognized by having no section. */
-#define IS_TYPE_UNIT_GROUP(per_cu) ((per_cu)->section == NULL)
+ a "per_cu" handle on the symtab. */
struct dwarf2_per_cu_data per_cu;
/* The TUs that share this DW_AT_stmt_list entry.
/* The data used to construct the hash key. */
struct stmt_list_hash hash;
- /* The number of symtabs from the line header.
- The value here must match line_header.num_file_names. */
- unsigned int num_symtabs;
-
/* The symbol tables for this TU (obtained from the files listed in
DW_AT_stmt_list).
WARNING: The order of entries here must match the order of entries
cutu_reader (struct dwarf2_per_cu_data *this_cu,
struct abbrev_table *abbrev_table,
- int use_existing_cu, int keep,
+ int use_existing_cu,
bool skip_partial);
explicit cutu_reader (struct dwarf2_per_cu_data *this_cu,
struct dwarf2_cu *parent_cu = nullptr,
struct dwo_file *dwo_file = nullptr);
- ~cutu_reader ();
-
DISABLE_COPY_AND_ASSIGN (cutu_reader);
const gdb_byte *info_ptr = nullptr;
struct die_info *comp_unit_die = nullptr;
bool dummy_p = false;
+ /* Release the new CU, putting it on the chain. This cannot be done
+ for dummy CUs. */
+ void keep ();
+
private:
void init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
- int use_existing_cu, int keep);
+ int use_existing_cu);
struct dwarf2_per_cu_data *m_this_cu;
- int m_keep = 0;
std::unique_ptr<dwarf2_cu> m_new_cu;
/* The ordinary abbreviation table. */
std::vector<struct nextfield> fields;
std::vector<struct nextfield> baseclasses;
- /* Number of fields (including baseclasses). */
- int nfields = 0;
-
/* Set if the accessibility of one of the fields is not public. */
int non_public_fields = 0;
/* Nested types defined by this class and the number of elements in this
list. */
std::vector<struct decl_field> nested_types_list;
+
+ /* Return the total number of fields (including baseclasses). */
+ int nfields () const
+ {
+ return fields.size () + baseclasses.size ();
+ }
};
/* Loaded secondary compilation units are kept in memory until they
static CORE_ADDR read_addr_index (struct dwarf2_cu *cu, unsigned int addr_index);
-static CORE_ADDR read_address (bfd *, const gdb_byte *ptr, struct dwarf2_cu *,
- unsigned int *);
-
static LONGEST read_checked_initial_length_and_offset
(bfd *, const gdb_byte *, const struct comp_unit_head *,
unsigned int *, unsigned int *);
(struct dwarf2_per_objfile *dwarf2_per_objfile,
struct dwarf2_section_info *, sect_offset);
-static const gdb_byte *read_n_bytes (bfd *, const gdb_byte *, unsigned int);
-
-static const char *read_direct_string (bfd *, const gdb_byte *, unsigned int *);
-
static const char *read_indirect_string
(struct dwarf2_per_objfile *dwarf2_per_objfile, bfd *, const gdb_byte *,
const struct comp_unit_head *, unsigned int *);
static void process_die (struct die_info *, struct dwarf2_cu *);
static const char *dwarf2_canonicalize_name (const char *, struct dwarf2_cu *,
- struct obstack *);
+ struct objfile *);
static const char *dwarf2_name (struct die_info *die, struct dwarf2_cu *);
static file_and_directory find_file_and_directory (struct die_info *die,
struct dwarf2_cu *cu);
-static htab_up allocate_signatured_type_table (struct objfile *objfile);
+static htab_up allocate_signatured_type_table ();
-static htab_up allocate_dwo_unit_table (struct objfile *objfile);
+static htab_up allocate_dwo_unit_table ();
static struct dwo_unit *lookup_dwo_unit_in_dwp
(struct dwarf2_per_objfile *dwarf2_per_objfile,
if (dwz_bfd == NULL)
dwz_bfd = build_id_to_debug_bfd (buildid_len, buildid);
+ if (dwz_bfd == nullptr)
+ {
+ gdb::unique_xmalloc_ptr<char> alt_filename;
+ const char *origname = dwarf2_per_objfile->objfile->original_name;
+
+ scoped_fd fd (debuginfod_debuginfo_query (buildid,
+ buildid_len,
+ origname,
+ &alt_filename));
+
+ if (fd.get () >= 0)
+ {
+ /* File successfully retrieved from server. */
+ dwz_bfd = gdb_bfd_open (alt_filename.get (), gnutarget, -1);
+
+ if (dwz_bfd == nullptr)
+ warning (_("File \"%s\" from debuginfod cannot be opened as bfd"),
+ alt_filename.get ());
+ else if (!build_id_verify (dwz_bfd.get (), buildid_len, buildid))
+ dwz_bfd.reset (nullptr);
+ }
+ }
+
if (dwz_bfd == NULL)
error (_("could not find '.gnu_debugaltlink' file for %s"),
objfile_name (dwarf2_per_objfile->objfile));
/* Skip type_unit_groups, reading the type units they contain
is handled elsewhere. */
- if (IS_TYPE_UNIT_GROUP (per_cu))
+ if (per_cu->type_unit_group_p ())
return;
/* The destructor of dwarf2_queue_guard frees any entries left on
gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
dwarf2_per_objfile->all_type_units.reserve (elements / 3);
- htab_up sig_types_hash = allocate_signatured_type_table (objfile);
+ htab_up sig_types_hash = allocate_signatured_type_table ();
for (offset_type i = 0; i < elements; i += 3)
{
gdb_assert (dwarf2_per_objfile->all_type_units.empty ());
dwarf2_per_objfile->all_type_units.reserve (map.tu_count);
- htab_up sig_types_hash = allocate_signatured_type_table (objfile);
+ htab_up sig_types_hash = allocate_signatured_type_table ();
for (uint32_t i = 0; i < map.tu_count; ++i)
{
/* This should never be called for TUs. */
gdb_assert (! this_cu->is_debug_types);
/* Nor type unit groups. */
- gdb_assert (! IS_TYPE_UNIT_GROUP (this_cu));
+ gdb_assert (! this_cu->type_unit_group_p ());
if (this_cu->v.quick->file_names != NULL)
return this_cu->v.quick->file_names;
return (sect_offset) read_offset (abfd, info_ptr, offset_size);
}
+/* A partial symtab that is used only for include files. */
+struct dwarf2_include_psymtab : public partial_symtab
+{
+ dwarf2_include_psymtab (const char *filename, struct objfile *objfile)
+ : partial_symtab (filename, objfile)
+ {
+ }
+
+ void read_symtab (struct objfile *objfile) override
+ {
+ expand_psymtab (objfile);
+ }
+
+ void expand_psymtab (struct objfile *objfile) override
+ {
+ if (m_readin)
+ return;
+ /* It's an include file, no symbols to read for it.
+ Everything is in the parent symtab. */
+ read_dependencies (objfile);
+ m_readin = true;
+ }
+
+ bool readin_p () const override
+ {
+ return m_readin;
+ }
+
+ struct compunit_symtab *get_compunit_symtab () const override
+ {
+ return nullptr;
+ }
+
+private:
+
+ bool m_readin = false;
+};
+
/* Allocate a new partial symtab for file named NAME and mark this new
partial symtab as being an include of PST. */
dwarf2_create_include_psymtab (const char *name, dwarf2_psymtab *pst,
struct objfile *objfile)
{
- dwarf2_psymtab *subpst = new dwarf2_psymtab (name, objfile);
+ dwarf2_include_psymtab *subpst = new dwarf2_include_psymtab (name, objfile);
if (!IS_ABSOLUTE_PATH (subpst->filename))
{
subpst->dependencies = objfile->partial_symtabs->allocate_dependencies (1);
subpst->dependencies[0] = pst;
subpst->number_of_dependencies = 1;
-
- /* No private part is necessary for include psymtabs. This property
- can be used to differentiate between such include psymtabs and
- the regular ones. */
- subpst->per_cu_data = nullptr;
}
/* Read the Line Number Program data and extract the list of files
/* Allocate a hash table for signatured types. */
static htab_up
-allocate_signatured_type_table (struct objfile *objfile)
+allocate_signatured_type_table ()
{
return htab_up (htab_create_alloc (41,
hash_signatured_type,
if (types_htab == NULL)
{
if (dwo_file)
- types_htab = allocate_dwo_unit_table (objfile);
+ types_htab = allocate_dwo_unit_table ();
else
- types_htab = allocate_signatured_type_table (objfile);
+ types_htab = allocate_signatured_type_table ();
}
if (dwo_file)
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwo_file *dwo_file;
struct dwo_unit find_dwo_entry, *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
/* If TU skeletons have been removed then we may not have read in any
TUs yet. */
if (dwarf2_per_objfile->signatured_types == NULL)
- {
- dwarf2_per_objfile->signatured_types
- = allocate_signatured_type_table (objfile);
- }
+ dwarf2_per_objfile->signatured_types = allocate_signatured_type_table ();
/* We only ever need to read in one copy of a signatured type.
Use the global signatured_types array to do our own comdat-folding
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= cu->per_cu->dwarf2_per_objfile;
- struct objfile *objfile = dwarf2_per_objfile->objfile;
struct dwp_file *dwp_file = get_dwp_file (dwarf2_per_objfile);
struct dwo_unit *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
/* If TU skeletons have been removed then we may not have read in any
TUs yet. */
if (dwarf2_per_objfile->signatured_types == NULL)
- {
- dwarf2_per_objfile->signatured_types
- = allocate_signatured_type_table (objfile);
- }
+ dwarf2_per_objfile->signatured_types = allocate_signatured_type_table ();
find_sig_entry.signature = sig;
slot = htab_find_slot (dwarf2_per_objfile->signatured_types.get (),
void
cutu_reader::init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
- int use_existing_cu, int keep)
+ int use_existing_cu)
{
struct signatured_type *sig_type;
- struct die_reader_specs reader;
/* Verify we can do the following downcast, and that we have the
data we need. */
if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
NULL /* stub_comp_unit_die */,
sig_type->dwo_unit->dwo_file->comp_dir,
- &reader, &info_ptr,
+ this, &info_ptr,
&comp_unit_die,
&m_dwo_abbrev_table) == 0)
{
This is an optimization for when we already have the abbrev table.
If USE_EXISTING_CU is non-zero, and THIS_CU->cu is non-NULL, then use it.
- Otherwise, a new CU is allocated with xmalloc.
-
- If KEEP is non-zero, then if we allocated a dwarf2_cu we add it to
- read_in_chain. Otherwise the dwarf2_cu data is freed at the
- end. */
+ Otherwise, a new CU is allocated with xmalloc. */
cutu_reader::cutu_reader (struct dwarf2_per_cu_data *this_cu,
struct abbrev_table *abbrev_table,
- int use_existing_cu, int keep,
+ int use_existing_cu,
bool skip_partial)
: die_reader_specs {},
- m_this_cu (this_cu),
- m_keep (keep)
+ m_this_cu (this_cu)
{
struct dwarf2_per_objfile *dwarf2_per_objfile = this_cu->dwarf2_per_objfile;
struct objfile *objfile = dwarf2_per_objfile->objfile;
this_cu->is_debug_types ? "type" : "comp",
sect_offset_str (this_cu->sect_off));
- if (use_existing_cu)
- gdb_assert (keep);
-
/* If we're reading a TU directly from a DWO file, including a virtual DWO
file (instead of going through the stub), short-circuit all of this. */
if (this_cu->reading_dwo_directly)
/* Narrow down the scope of possibilities to have to understand. */
gdb_assert (this_cu->is_debug_types);
gdb_assert (abbrev_table == NULL);
- init_tu_and_read_dwo_dies (this_cu, use_existing_cu, keep);
+ init_tu_and_read_dwo_dies (this_cu, use_existing_cu);
return;
}
}
}
-cutu_reader::~cutu_reader ()
+void
+cutu_reader::keep ()
{
/* Done, clean up. */
- if (m_new_cu != NULL && m_keep && !dummy_p)
+ gdb_assert (!dummy_p);
+ if (m_new_cu != NULL)
{
struct dwarf2_per_objfile *dwarf2_per_objfile
= m_this_cu->dwarf2_per_objfile;
/* Allocate a hash table for type unit groups. */
static htab_up
-allocate_type_unit_groups_table (struct objfile *objfile)
+allocate_type_unit_groups_table ()
{
return htab_up (htab_create_alloc (3,
hash_type_unit_group,
struct type_unit_group type_unit_group_for_lookup;
if (dwarf2_per_objfile->type_unit_groups == NULL)
- {
- dwarf2_per_objfile->type_unit_groups =
- allocate_type_unit_groups_table (dwarf2_per_objfile->objfile);
- }
+ dwarf2_per_objfile->type_unit_groups = allocate_type_unit_groups_table ();
/* Do we need to create a new group, or can we use an existing one? */
process_psymtab_comp_unit_reader (const struct die_reader_specs *reader,
const gdb_byte *info_ptr,
struct die_info *comp_unit_die,
- int want_partial_unit,
enum language pretend_language)
{
struct dwarf2_cu *cu = reader->cu;
enum pc_bounds_kind cu_bounds_kind;
const char *filename;
- if (comp_unit_die->tag == DW_TAG_partial_unit && !want_partial_unit)
- return;
-
gdb_assert (! per_cu->is_debug_types);
prepare_one_comp_unit (cu, comp_unit_die, pretend_language);
/* Allocate a new partial symbol table structure. */
+ gdb::unique_xmalloc_ptr<char> debug_filename;
+ static const char artificial[] = "<artificial>";
filename = dwarf2_string_attr (comp_unit_die, DW_AT_name, cu);
if (filename == NULL)
filename = "";
+ else if (strcmp (filename, artificial) == 0)
+ {
+ debug_filename.reset (concat (artificial, "@",
+ sect_offset_str (per_cu->sect_off),
+ (char *) NULL));
+ filename = debug_filename.get ();
+ }
pst = create_partial_symtab (per_cu, filename);
static void
process_psymtab_comp_unit (struct dwarf2_per_cu_data *this_cu,
- int want_partial_unit,
+ bool want_partial_unit,
enum language pretend_language)
{
/* If this compilation unit was already read in, free the
if (this_cu->cu != NULL)
free_one_cached_comp_unit (this_cu);
- cutu_reader reader (this_cu, NULL, 0, 0, false);
+ cutu_reader reader (this_cu, NULL, 0, false);
+
+ switch (reader.comp_unit_die->tag)
+ {
+ case DW_TAG_compile_unit:
+ this_cu->unit_type = DW_UT_compile;
+ break;
+ case DW_TAG_partial_unit:
+ this_cu->unit_type = DW_UT_partial;
+ break;
+ default:
+ abort ();
+ }
if (reader.dummy_p)
{
else if (this_cu->is_debug_types)
build_type_psymtabs_reader (&reader, reader.info_ptr,
reader.comp_unit_die);
- else
+ else if (want_partial_unit
+ || reader.comp_unit_die->tag != DW_TAG_partial_unit)
process_psymtab_comp_unit_reader (&reader, reader.info_ptr,
reader.comp_unit_die,
- want_partial_unit,
pretend_language);
+ this_cu->lang = this_cu->cu->language;
+
/* Age out any secondary CUs. */
age_cached_comp_units (this_cu->dwarf2_per_objfile);
}
}
cutu_reader reader (&tu.sig_type->per_cu, abbrev_table.get (),
- 0, 0, false);
+ 0, false);
if (!reader.dummy_p)
build_type_psymtabs_reader (&reader, reader.info_ptr,
reader.comp_unit_die);
int i;
gdb_assert (len > 0);
- gdb_assert (IS_TYPE_UNIT_GROUP (per_cu));
+ gdb_assert (per_cu->type_unit_group_p ());
pst->number_of_dependencies = len;
pst->dependencies = objfile->partial_symtabs->allocate_dependencies (len);
/* If this TU doesn't exist in the global table, add it and read it in. */
if (dwarf2_per_objfile->signatured_types == NULL)
- {
- dwarf2_per_objfile->signatured_types
- = allocate_signatured_type_table (dwarf2_per_objfile->objfile);
- }
+ dwarf2_per_objfile->signatured_types = allocate_signatured_type_table ();
find_entry.signature = dwo_unit->signature;
slot = htab_find_slot (dwarf2_per_objfile->signatured_types.get (),
*slot = entry;
/* This does the job that build_type_psymtabs_1 would have done. */
- cutu_reader reader (&entry->per_cu, NULL, 0, 0, false);
+ cutu_reader reader (&entry->per_cu, NULL, 0, false);
if (!reader.dummy_p)
build_type_psymtabs_reader (&reader, reader.info_ptr,
reader.comp_unit_die);
objfile_name (objfile));
}
- dwarf2_per_objfile->reading_partial_symbols = 1;
+ scoped_restore restore_reading_psyms
+ = make_scoped_restore (&dwarf2_per_objfile->reading_partial_symbols,
+ true);
dwarf2_per_objfile->info.read (objfile);
addrmap_create_mutable (&temp_obstack));
for (dwarf2_per_cu_data *per_cu : dwarf2_per_objfile->all_comp_units)
- process_psymtab_comp_unit (per_cu, 0, language_minimal);
+ process_psymtab_comp_unit (per_cu, false, language_minimal);
/* This has to wait until we read the CUs, we need the list of DWOs. */
process_skeletonless_type_units (dwarf2_per_objfile);
static void
load_partial_comp_unit (struct dwarf2_per_cu_data *this_cu)
{
- cutu_reader reader (this_cu, NULL, 1, 1, false);
+ cutu_reader reader (this_cu, NULL, 1, false);
if (!reader.dummy_p)
{
If not, there's no more debug_info for this comp unit. */
if (reader.comp_unit_die->has_children)
load_partial_dies (&reader, reader.info_ptr, 0);
+
+ reader.keep ();
}
}
/* Go read the partial unit, if needed. */
if (per_cu->v.psymtab == NULL)
- process_psymtab_comp_unit (per_cu, 1, cu->language);
+ process_psymtab_comp_unit (per_cu, true, cu->language);
cu->per_cu->imported_symtabs_push (per_cu);
}
= dpo_backlink->has_section_at_zero;
}
- dwarf2_per_objfile->reading_partial_symbols = 0;
-
expand_psymtab (objfile);
process_cu_includes (dwarf2_per_objfile);
void
dwarf2_psymtab::expand_psymtab (struct objfile *objfile)
{
- struct dwarf2_per_cu_data *per_cu;
-
if (readin)
return;
read_dependencies (objfile);
- per_cu = per_cu_data;
-
- if (per_cu == NULL)
- {
- /* It's an include file, no symbols to read for it.
- Everything is in the parent symtab. */
- readin = true;
- return;
- }
-
- dw2_do_instantiate_symtab (per_cu, false);
+ dw2_do_instantiate_symtab (per_cu_data, false);
+ gdb_assert (get_compunit_symtab () != nullptr);
}
/* Trivial hash function for die_info: the hash value of a DIE
{
gdb_assert (! this_cu->is_debug_types);
- cutu_reader reader (this_cu, NULL, 1, 1, skip_partial);
+ cutu_reader reader (this_cu, NULL, 1, skip_partial);
if (reader.dummy_p)
return;
Similarly, if we do not read the producer, we can not apply
producer-specific interpretation. */
prepare_one_comp_unit (cu, cu->dies, pretend_language);
+
+ reader.keep ();
}
/* Add a DIE to the delayed physname list. */
if (package_name != NULL)
{
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- const char *saved_package_name
- = obstack_strdup (&objfile->per_bfd->storage_obstack, package_name.get ());
+ const char *saved_package_name = objfile->intern (package_name.get ());
struct type *type = init_type (objfile, TYPE_CODE_MODULE, 0,
saved_package_name);
struct symbol *sym;
= dwarf2_find_containing_comp_unit (sect_off, is_dwz,
cu->per_cu->dwarf2_per_objfile);
+ /* We're importing a C++ compilation unit with tag DW_TAG_compile_unit
+ into another compilation unit, at root level. Regard this as a hint,
+ and ignore it. */
+ if (die->parent && die->parent->parent == NULL
+ && per_cu->unit_type == DW_UT_compile
+ && per_cu->lang == language_cplus)
+ return;
+
/* If necessary, add it to the queue and load its DIEs. */
if (maybe_queue_comp_unit (cu, per_cu, cu->language))
load_full_comp_unit (per_cu, false, cu->language);
if (cu->language == language_cplus)
canonical_name
= dwarf2_canonicalize_name (intermediate_name.c_str (), cu,
- &objfile->per_bfd->storage_obstack);
+ objfile);
/* If we only computed INTERMEDIATE_NAME, or if
INTERMEDIATE_NAME is already canonical, then we need to
- copy it to the appropriate obstack. */
+ intern it. */
if (canonical_name == NULL || canonical_name == intermediate_name.c_str ())
- name = obstack_strdup (&objfile->per_bfd->storage_obstack,
- intermediate_name);
+ name = objfile->intern (intermediate_name);
else
name = canonical_name;
}
retval = canon;
if (need_copy)
- retval = obstack_strdup (&objfile->per_bfd->storage_obstack, retval);
+ retval = objfile->intern (retval);
return retval;
}
process_full_type_unit still needs to know if this is the first
time. */
- tu_group->num_symtabs = line_header->file_names_size ();
- tu_group->symtabs = XNEWVEC (struct symtab *,
- line_header->file_names_size ());
+ tu_group->symtabs
+ = XOBNEWVEC (&COMPUNIT_OBJFILE (cust)->objfile_obstack,
+ struct symtab *, line_header->file_names_size ());
auto &file_names = line_header->file_names ();
for (i = 0; i < file_names.size (); ++i)
/* Allocate a hash table for DWO files. */
static htab_up
-allocate_dwo_file_hash_table (struct objfile *objfile)
+allocate_dwo_file_hash_table ()
{
auto delete_dwo_file = [] (void *item)
{
void **slot;
if (dwarf2_per_objfile->dwo_files == NULL)
- dwarf2_per_objfile->dwo_files
- = allocate_dwo_file_hash_table (dwarf2_per_objfile->objfile);
+ dwarf2_per_objfile->dwo_files = allocate_dwo_file_hash_table ();
find_entry.dwo_name = dwo_name;
find_entry.comp_dir = comp_dir;
There is one of these tables for each of CUs,TUs for each DWO file. */
static htab_up
-allocate_dwo_unit_table (struct objfile *objfile)
+allocate_dwo_unit_table ()
{
/* Start out with a pretty small number.
Generally DWO files contain only one CU and maybe some TUs. */
continue;
if (cus_htab == NULL)
- cus_htab = allocate_dwo_unit_table (objfile);
+ cus_htab = allocate_dwo_unit_table ();
dwo_unit = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct dwo_unit);
*dwo_unit = read_unit;
virtual_dwo_name.c_str ());
}
dwo_file = new struct dwo_file;
- dwo_file->dwo_name = obstack_strdup (&objfile->objfile_obstack,
- virtual_dwo_name);
+ dwo_file->dwo_name = objfile->intern (virtual_dwo_name);
dwo_file->comp_dir = comp_dir;
dwo_file->sections.abbrev = sections.abbrev;
dwo_file->sections.line = sections.line;
virtual_dwo_name.c_str ());
}
dwo_file = new struct dwo_file;
- dwo_file->dwo_name = obstack_strdup (&objfile->objfile_obstack,
- virtual_dwo_name);
+ dwo_file->dwo_name = objfile->intern (virtual_dwo_name);
dwo_file->comp_dir = comp_dir;
dwo_file->sections.abbrev =
create_dwp_v2_section (dwarf2_per_objfile, &dwp_file->sections.abbrev,
/* Allocate a hash table for dwp_file loaded CUs/TUs. */
static htab_up
-allocate_dwp_loaded_cutus_table (struct objfile *objfile)
+allocate_dwp_loaded_cutus_table ()
{
return htab_up (htab_create_alloc (3,
hash_dwp_loaded_cutus,
dwarf2_locate_v2_dwp_sections,
dwp_file.get ());
- dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table (objfile);
- dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table (objfile);
+ dwp_file->loaded_cus = allocate_dwp_loaded_cutus_table ();
+ dwp_file->loaded_tus = allocate_dwp_loaded_cutus_table ();
if (dwarf_read_debug)
{
overflow = true;
break;
}
- base = read_address (obfd, buffer, cu, &bytes_read);
+ base = cu->header.read_address (obfd, buffer, &bytes_read);
found_base = 1;
buffer += bytes_read;
break;
overflow = true;
break;
}
- range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+ range_beginning = cu->header.read_address (obfd, buffer,
+ &bytes_read);
buffer += bytes_read;
range_end = (range_beginning
+ read_unsigned_leb128 (obfd, buffer, &bytes_read));
overflow = true;
break;
}
- range_beginning = read_address (obfd, buffer, cu, &bytes_read);
+ range_beginning = cu->header.read_address (obfd, buffer,
+ &bytes_read);
buffer += bytes_read;
- range_end = read_address (obfd, buffer, cu, &bytes_read);
+ range_end = cu->header.read_address (obfd, buffer, &bytes_read);
buffer += bytes_read;
break;
default:
{
CORE_ADDR range_beginning, range_end;
- range_beginning = read_address (obfd, buffer, cu, &dummy);
+ range_beginning = cu->header.read_address (obfd, buffer, &dummy);
buffer += addr_size;
- range_end = read_address (obfd, buffer, cu, &dummy);
+ range_end = cu->header.read_address (obfd, buffer, &dummy);
buffer += addr_size;
offset += 2 * addr_size;
new_field = &fip->fields.back ();
}
- fip->nfields++;
-
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr != nullptr)
new_field->accessibility = DW_UNSND (attr);
dwarf2_attach_fields_to_type (struct field_info *fip, struct type *type,
struct dwarf2_cu *cu)
{
- int nfields = fip->nfields;
+ int nfields = fip->nfields ();
/* Record the field count, allocate space for the array of fields,
and create blank accessibility bitfields if necessary. */
}
/* Attach fields and member functions to the type. */
- if (fi.nfields)
+ if (fi.nfields () > 0)
dwarf2_attach_fields_to_type (&fi, type, cu);
if (!fi.fnfieldlists.empty ())
{
struct die_info *child_die;
int unsigned_enum = 1;
int flag_enum = 1;
- ULONGEST mask = 0;
auto_obstack obstack;
unsigned_enum = 0;
flag_enum = 0;
}
- else if ((mask & value) != 0)
- flag_enum = 0;
else
- mask |= value;
+ {
+ if (count_one_bits_ll (value) >= 2)
+ flag_enum = 0;
+ }
/* If we already know that the enum type is neither unsigned, nor
a flag type, no need to look at the rest of the enumerates. */
sect_offset_str (die->sect_off), objfile_name (objfile));
TYPE_TARGET_TYPE (this_type) = NULL;
}
+ if (name == NULL)
+ {
+ /* Gcc-7 and before supports -feliminate-dwarf2-dups, which generates
+ anonymous typedefs, which is, strictly speaking, invalid DWARF.
+ Handle these by just returning the target type, rather than
+ constructing an anonymous typedef type and trying to handle this
+ elsewhere. */
+ set_die_type (die, target_type, cu);
+ return target_type;
+ }
return this_type;
}
struct objfile *objfile = dwarf2_per_objfile->objfile;
name
- = dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->per_bfd->storage_obstack);
+ = dwarf2_canonicalize_name (DW_STRING (&attr), cu, objfile);
}
break;
}
if (actual_class_name != NULL)
{
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- struct_pdi->name
- = obstack_strdup (&objfile->per_bfd->storage_obstack,
- actual_class_name.get ());
+ struct_pdi->name = objfile->intern (actual_class_name.get ());
}
break;
}
base = demangled.get ();
struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile;
- name = obstack_strdup (&objfile->per_bfd->storage_obstack, base);
+ name = objfile->intern (base);
}
}
{
case DW_FORM_ref_addr:
if (cu->header.version == 2)
- DW_UNSND (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+ DW_UNSND (attr) = cu->header.read_address (abfd, info_ptr,
+ &bytes_read);
else
DW_UNSND (attr) = cu->header.read_offset (abfd, info_ptr,
&bytes_read);
info_ptr += bytes_read;
break;
case DW_FORM_addr:
- DW_ADDR (attr) = read_address (abfd, info_ptr, cu, &bytes_read);
+ DW_ADDR (attr) = cu->header.read_address (abfd, info_ptr, &bytes_read);
DW_ADDR (attr) = gdbarch_adjust_dwarf2_addr (gdbarch, DW_ADDR (attr));
info_ptr += bytes_read;
break;
need_reprocess);
}
-static CORE_ADDR
-read_address (bfd *abfd, const gdb_byte *buf, struct dwarf2_cu *cu,
- unsigned int *bytes_read)
-{
- struct comp_unit_head *cu_header = &cu->header;
- CORE_ADDR retval = 0;
-
- if (cu_header->signed_addr_p)
- {
- switch (cu_header->addr_size)
- {
- case 2:
- retval = bfd_get_signed_16 (abfd, buf);
- break;
- case 4:
- retval = bfd_get_signed_32 (abfd, buf);
- break;
- case 8:
- retval = bfd_get_signed_64 (abfd, buf);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("read_address: bad switch, signed [in module %s]"),
- bfd_get_filename (abfd));
- }
- }
- else
- {
- switch (cu_header->addr_size)
- {
- case 2:
- retval = bfd_get_16 (abfd, buf);
- break;
- case 4:
- retval = bfd_get_32 (abfd, buf);
- break;
- case 8:
- retval = bfd_get_64 (abfd, buf);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("read_address: bad switch, "
- "unsigned [in module %s]"),
- bfd_get_filename (abfd));
- }
- }
-
- *bytes_read = cu_header->addr_size;
- return retval;
-}
-
/* Cover function for read_initial_length.
Returns the length of the object at BUF, and stores the size of the
initial length in *BYTES_READ and stores the size that offsets will be in
return length;
}
-static const gdb_byte *
-read_n_bytes (bfd *abfd, const gdb_byte *buf, unsigned int size)
-{
- /* If the size of a host char is 8 bits, we can return a pointer
- to the buffer, otherwise we have to copy the data to a buffer
- allocated on the temporary obstack. */
- gdb_assert (HOST_CHAR_BIT == 8);
- return buf;
-}
-
-static const char *
-read_direct_string (bfd *abfd, const gdb_byte *buf,
- unsigned int *bytes_read_ptr)
-{
- /* If the size of a host char is 8 bits, we can return a pointer
- to the string, otherwise we have to copy the string to a buffer
- allocated on the temporary obstack. */
- gdb_assert (HOST_CHAR_BIT == 8);
- if (*buf == '\0')
- {
- *bytes_read_ptr = 1;
- return NULL;
- }
- *bytes_read_ptr = strlen ((const char *) buf) + 1;
- return (const char *) buf;
-}
-
/* Return pointer to string at section SECT offset STR_OFFSET with error
reporting strings FORM_NAME and SECT_NAME. */
return read_addr_index (cu, addr_index);
}
-/* Given an index in .debug_addr, fetch the value.
- NOTE: This can be called during dwarf expression evaluation,
- long after the debug information has been read, and thus per_cu->cu
- may no longer exist. */
+/* See read.h. */
CORE_ADDR
-dwarf2_read_addr_index (struct dwarf2_per_cu_data *per_cu,
- unsigned int addr_index)
+dwarf2_read_addr_index (dwarf2_per_cu_data *per_cu, unsigned int addr_index)
{
struct dwarf2_per_objfile *dwarf2_per_objfile = per_cu->dwarf2_per_objfile;
struct dwarf2_cu *cu = per_cu->cu;
}
else
{
- cutu_reader reader (per_cu, NULL, 0, 0, false);
+ cutu_reader reader (per_cu, NULL, 0, false);
addr_base = reader.cu->addr_base;
addr_size = reader.cu->header.addr_size;
}
lnp_state_machine::handle_special_opcode (unsigned char op_code)
{
unsigned char adj_opcode = op_code - m_line_header->opcode_base;
- CORE_ADDR addr_adj = (((m_op_index
- + (adj_opcode / m_line_header->line_range))
+ unsigned char adj_opcode_d = adj_opcode / m_line_header->line_range;
+ unsigned char adj_opcode_r = adj_opcode % m_line_header->line_range;
+ CORE_ADDR addr_adj = (((m_op_index + adj_opcode_d)
/ m_line_header->maximum_ops_per_instruction)
* m_line_header->minimum_instruction_length);
m_address += gdbarch_adjust_dwarf2_line (m_gdbarch, addr_adj, true);
- m_op_index = ((m_op_index + (adj_opcode / m_line_header->line_range))
+ m_op_index = ((m_op_index + adj_opcode_d)
% m_line_header->maximum_ops_per_instruction);
- int line_delta = (m_line_header->line_base
- + (adj_opcode % m_line_header->line_range));
+ int line_delta = m_line_header->line_base + adj_opcode_r;
advance_line (line_delta);
record_line (false);
m_discriminator = 0;
static void
dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
- unsigned int line, CORE_ADDR address,
+ unsigned int line, CORE_ADDR address, bool is_stmt,
struct dwarf2_cu *cu)
{
CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
}
if (cu != nullptr)
- cu->get_builder ()->record_line (subfile, line, addr);
+ cu->get_builder ()->record_line (subfile, line, addr, is_stmt);
}
/* Subroutine of dwarf_decode_lines_1 to simplify it.
paddress (gdbarch, address));
}
- dwarf_record_line_1 (gdbarch, subfile, 0, address, cu);
+ dwarf_record_line_1 (gdbarch, subfile, 0, address, true, cu);
}
void
else if (m_op_index == 0 || end_sequence)
{
fe->included_p = 1;
- if (m_record_lines_p
- && (producer_is_codewarrior (m_cu) || m_is_stmt || end_sequence))
+ if (m_record_lines_p)
{
if (m_last_subfile != m_cu->get_builder ()->get_current_subfile ()
|| end_sequence)
if (!end_sequence)
{
+ bool is_stmt = producer_is_codewarrior (m_cu) || m_is_stmt;
+
if (dwarf_record_line_p (m_cu, m_line, m_last_line,
m_line_has_non_zero_discriminator,
m_last_subfile))
buildsym_compunit *builder = m_cu->get_builder ();
dwarf_record_line_1 (m_gdbarch,
builder->get_current_subfile (),
- m_line, m_address,
+ m_line, m_address, is_stmt,
m_currently_recording_lines ? m_cu : nullptr);
}
m_last_subfile = m_cu->get_builder ()->get_current_subfile ();
case DW_LNE_set_address:
{
CORE_ADDR address
- = read_address (abfd, line_ptr, cu, &bytes_read);
+ = cu->header.read_address (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
state_machine.check_line_address (cu, line_ptr,
unsigned int dummy;
if (DW_BLOCK (attr)->data[0] == DW_OP_addr)
- SET_SYMBOL_VALUE_ADDRESS (sym,
- read_address (objfile->obfd,
- DW_BLOCK (attr)->data + 1,
- cu, &dummy));
+ SET_SYMBOL_VALUE_ADDRESS
+ (sym, cu->header.read_address (objfile->obfd,
+ DW_BLOCK (attr)->data + 1,
+ &dummy));
else
SET_SYMBOL_VALUE_ADDRESS
(sym, read_addr_index_from_leb128 (cu, DW_BLOCK (attr)->data + 1,
static const char *
dwarf2_canonicalize_name (const char *name, struct dwarf2_cu *cu,
- struct obstack *obstack)
+ struct objfile *objfile)
{
if (name && cu->language == language_cplus)
{
if (!canon_name.empty ())
{
if (canon_name != name)
- name = obstack_strdup (obstack, canon_name);
+ name = objfile->intern (canon_name);
}
}
{
gdb::unique_xmalloc_ptr<char> demangled
(gdb_demangle (DW_STRING (attr), DMGL_TYPES));
+ if (demangled == nullptr)
+ return nullptr;
- const char *base;
-
- /* FIXME: we already did this for the partial symbol... */
- DW_STRING (attr)
- = obstack_strdup (&objfile->per_bfd->storage_obstack,
- demangled.get ());
+ DW_STRING (attr) = objfile->intern (demangled.get ());
DW_STRING_IS_CANONICAL (attr) = 1;
-
- /* Strip any leading namespaces/classes, keep only the base name.
- DW_AT_name for named DIEs does not contain the prefixes. */
- base = strrchr (DW_STRING (attr), ':');
- if (base && base > DW_STRING (attr) && base[-1] == ':')
- return &base[1];
- else
- return DW_STRING (attr);
}
+
+ /* Strip any leading namespaces/classes, keep only the base name.
+ DW_AT_name for named DIEs does not contain the prefixes. */
+ const char *base = strrchr (DW_STRING (attr), ':');
+ if (base && base > DW_STRING (attr) && base[-1] == ':')
+ return &base[1];
+ else
+ return DW_STRING (attr);
}
break;
if (!DW_STRING_IS_CANONICAL (attr))
{
- DW_STRING (attr)
- = dwarf2_canonicalize_name (DW_STRING (attr), cu,
- &objfile->per_bfd->storage_obstack);
+ DW_STRING (attr) = dwarf2_canonicalize_name (DW_STRING (attr), cu,
+ objfile);
DW_STRING_IS_CANONICAL (attr) = 1;
}
return DW_STRING (attr);
return die;
}
-/* Return DWARF block referenced by DW_AT_location of DIE at SECT_OFF at PER_CU.
- Returned value is intended for DW_OP_call*. Returned
- dwarf2_locexpr_baton->data has lifetime of
- PER_CU->DWARF2_PER_OBJFILE->OBJFILE. */
+/* See read.h. */
struct dwarf2_locexpr_baton
dwarf2_fetch_die_loc_sect_off (sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu,
+ dwarf2_per_cu_data *per_cu,
CORE_ADDR (*get_frame_pc) (void *baton),
void *baton, bool resolve_abstract_p)
{
return retval;
}
-/* Like dwarf2_fetch_die_loc_sect_off, but take a CU
- offset. */
+/* See read.h. */
struct dwarf2_locexpr_baton
dwarf2_fetch_die_loc_cu_off (cu_offset offset_in_cu,
- struct dwarf2_per_cu_data *per_cu,
+ dwarf2_per_cu_data *per_cu,
CORE_ADDR (*get_frame_pc) (void *baton),
void *baton)
{
return result;
}
-/* If the DIE at OFFSET in PER_CU has a DW_AT_const_value, return a
- pointer to the constant bytes and set LEN to the length of the
- data. If memory is needed, allocate it on OBSTACK. If the DIE
- does not have a DW_AT_const_value, return NULL. */
+/* See read.h. */
const gdb_byte *
dwarf2_fetch_constant_bytes (sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu,
- struct obstack *obstack,
+ dwarf2_per_cu_data *per_cu,
+ obstack *obstack,
LONGEST *len)
{
struct dwarf2_cu *cu;
return result;
}
-/* Return the type of the die at OFFSET in PER_CU. Return NULL if no
- valid type for this die is found. */
+/* See read.h. */
struct type *
dwarf2_fetch_die_type_sect_off (sect_offset sect_off,
- struct dwarf2_per_cu_data *per_cu)
+ dwarf2_per_cu_data *per_cu)
{
struct dwarf2_cu *cu;
struct die_info *die;
return die_type (die, cu);
}
-/* Return the type of the DIE at DIE_OFFSET in the CU named by
- PER_CU. */
+/* See read.h. */
struct type *
dwarf2_get_die_type (cu_offset die_offset,
struct signatured_type *sig_type;
/* Caller is responsible for ensuring type_unit_groups don't get here. */
- gdb_assert (! IS_TYPE_UNIT_GROUP (per_cu));
+ gdb_assert (! per_cu->type_unit_group_p ());
/* We have the per_cu, but we need the signatured_type.
Fortunately this is an easy translation. */
gdb_assert (per_cu->is_debug_types);
gdb_assert (per_cu->cu == NULL);
- cutu_reader reader (per_cu, NULL, 0, 1, false);
+ cutu_reader reader (per_cu, NULL, 0, false);
if (!reader.dummy_p)
{
correctly. Similarly, if we do not read the producer, we can
not apply producer-specific interpretation. */
prepare_one_comp_unit (cu, cu->dies, language_minimal);
+
+ reader.keep ();
}
sig_type->per_cu.tu_read = 1;
break;
case DW_OP_addr:
- stack[++stacki] = read_address (objfile->obfd, &data[i],
- cu, &bytes_read);
+ stack[++stacki] = cu->header.read_address (objfile->obfd, &data[i],
+ &bytes_read);
i += bytes_read;
break;
return addr_type;
}
-/* Locate the .debug_info compilation unit from CU's objfile which contains
- the DIE at OFFSET. Raises an error on failure. */
+/* A helper function for dwarf2_find_containing_comp_unit that returns
+ the index of the result, and that searches a vector. It will
+ return a result even if the offset in question does not actually
+ occur in any CU. This is separate so that it can be unit
+ tested. */
-static struct dwarf2_per_cu_data *
-dwarf2_find_containing_comp_unit (sect_offset sect_off,
- unsigned int offset_in_dwz,
- struct dwarf2_per_objfile *dwarf2_per_objfile)
+static int
+dwarf2_find_containing_comp_unit
+ (sect_offset sect_off,
+ unsigned int offset_in_dwz,
+ const std::vector<dwarf2_per_cu_data *> &all_comp_units)
{
- struct dwarf2_per_cu_data *this_cu;
int low, high;
low = 0;
- high = dwarf2_per_objfile->all_comp_units.size () - 1;
+ high = all_comp_units.size () - 1;
while (high > low)
{
struct dwarf2_per_cu_data *mid_cu;
int mid = low + (high - low) / 2;
- mid_cu = dwarf2_per_objfile->all_comp_units[mid];
+ mid_cu = all_comp_units[mid];
if (mid_cu->is_dwz > offset_in_dwz
|| (mid_cu->is_dwz == offset_in_dwz
- && mid_cu->sect_off + mid_cu->length >= sect_off))
+ && mid_cu->sect_off + mid_cu->length > sect_off))
high = mid;
else
low = mid + 1;
}
gdb_assert (low == high);
- this_cu = dwarf2_per_objfile->all_comp_units[low];
+ return low;
+}
+
+/* Locate the .debug_info compilation unit from CU's objfile which contains
+ the DIE at OFFSET. Raises an error on failure. */
+
+static struct dwarf2_per_cu_data *
+dwarf2_find_containing_comp_unit (sect_offset sect_off,
+ unsigned int offset_in_dwz,
+ struct dwarf2_per_objfile *dwarf2_per_objfile)
+{
+ int low
+ = dwarf2_find_containing_comp_unit (sect_off, offset_in_dwz,
+ dwarf2_per_objfile->all_comp_units);
+ struct dwarf2_per_cu_data *this_cu
+ = dwarf2_per_objfile->all_comp_units[low];
+
if (this_cu->is_dwz != offset_in_dwz || this_cu->sect_off > sect_off)
{
if (low == 0 || this_cu->is_dwz != offset_in_dwz)
}
}
+#if GDB_SELF_TEST
+
+namespace selftests {
+namespace find_containing_comp_unit {
+
+static void
+run_test ()
+{
+ struct dwarf2_per_cu_data one {};
+ struct dwarf2_per_cu_data two {};
+ struct dwarf2_per_cu_data three {};
+ struct dwarf2_per_cu_data four {};
+
+ one.length = 5;
+ two.sect_off = sect_offset (one.length);
+ two.length = 7;
+
+ three.length = 5;
+ three.is_dwz = 1;
+ four.sect_off = sect_offset (three.length);
+ four.length = 7;
+ four.is_dwz = 1;
+
+ std::vector<dwarf2_per_cu_data *> units;
+ units.push_back (&one);
+ units.push_back (&two);
+ units.push_back (&three);
+ units.push_back (&four);
+
+ int result;
+
+ result = dwarf2_find_containing_comp_unit (sect_offset (0), 0, units);
+ SELF_CHECK (units[result] == &one);
+ result = dwarf2_find_containing_comp_unit (sect_offset (3), 0, units);
+ SELF_CHECK (units[result] == &one);
+ result = dwarf2_find_containing_comp_unit (sect_offset (5), 0, units);
+ SELF_CHECK (units[result] == &two);
+
+ result = dwarf2_find_containing_comp_unit (sect_offset (0), 1, units);
+ SELF_CHECK (units[result] == &three);
+ result = dwarf2_find_containing_comp_unit (sect_offset (3), 1, units);
+ SELF_CHECK (units[result] == &three);
+ result = dwarf2_find_containing_comp_unit (sect_offset (5), 1, units);
+ SELF_CHECK (units[result] == &four);
+}
+
+}
+}
+
+#endif /* GDB_SELF_TEST */
+
/* Initialize dwarf2_cu CU, owned by PER_CU. */
dwarf2_cu::dwarf2_cu (struct dwarf2_per_cu_data *per_cu_)
#if GDB_SELF_TEST
selftests::register_test ("dw2_expand_symtabs_matching",
selftests::dw2_expand_symtabs_matching::run_test);
+ selftests::register_test ("dwarf2_find_containing_comp_unit",
+ selftests::find_containing_comp_unit::run_test);
#endif
}