#include "typeprint.h"
#include "jv-lang.h"
#include "psympriv.h"
-#include "exceptions.h"
#include <sys/stat.h>
#include "completer.h"
#include "vec.h"
#include "build-id.h"
#include <fcntl.h>
-#include <string.h>
-#include "gdb_assert.h"
#include <sys/types.h>
typedef struct symbol *symbolp;
/* The number of .debug_types-related CUs. */
int n_type_units;
+ /* The number of elements allocated in all_type_units.
+ If there are skeleton-less TUs, we add them to all_type_units lazily. */
+ int n_allocated_type_units;
+
/* The .debug_types-related CUs (TUs).
This is stored in malloc space because we may realloc it. */
struct signatured_type **all_type_units;
int nr_symtabs;
int nr_symtab_sharers;
int nr_stmt_less_type_units;
+ int nr_all_type_units_reallocs;
} tu_stats;
/* A chain of compilation units that are currently read in, so that
However we can enter this file with just a "per_cu" handle. */
struct objfile *objfile;
- /* When using partial symbol tables, the 'psymtab' field is active.
- Otherwise the 'quick' field is active. */
+ /* When dwarf2_per_objfile->using_index is true, the 'quick' field
+ is active. Otherwise, the 'psymtab' field is active. */
union
{
/* The partial symbol table associated with this compilation unit,
static void add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu);
+ int set_addrmap, struct dwarf2_cu *cu);
static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc,
+ CORE_ADDR *highpc, int set_addrmap,
struct dwarf2_cu *cu);
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
static void dwarf_decode_lines (struct line_header *, const char *,
struct dwarf2_cu *, struct partial_symtab *,
- int);
+ CORE_ADDR);
static void dwarf2_start_subfile (const char *, const char *, const char *);
offset_type i;
htab_t sig_types_hash;
- dwarf2_per_objfile->n_type_units = elements / 3;
+ dwarf2_per_objfile->n_type_units
+ = dwarf2_per_objfile->n_allocated_type_units
+ = elements / 3;
dwarf2_per_objfile->all_type_units
= xmalloc (dwarf2_per_objfile->n_type_units
* sizeof (struct signatured_type *));
{
if (qfn->real_names == NULL)
qfn->real_names = OBSTACK_CALLOC (&objfile->objfile_obstack,
- qfn->num_file_names, char *);
+ qfn->num_file_names, const char *);
if (qfn->real_names[index] == NULL)
qfn->real_names[index] = gdb_realpath (qfn->file_names[index]);
information (but NAME might contain it). */
if (stab->primary)
{
- struct blockvector *bv = BLOCKVECTOR (stab);
+ const struct blockvector *bv = BLOCKVECTOR (stab);
struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
sym = lookup_block_symbol (block, name, domain);
return; /* No linetable, so no includes. */
/* NOTE: pst->dirname is DW_AT_comp_dir (if present). */
- dwarf_decode_lines (lh, pst->dirname, cu, pst, 1);
+ dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow);
free_line_header (lh);
}
dwarf2_per_objfile->signatured_types = types_htab;
- dwarf2_per_objfile->n_type_units = htab_elements (types_htab);
+ dwarf2_per_objfile->n_type_units
+ = dwarf2_per_objfile->n_allocated_type_units
+ = htab_elements (types_htab);
dwarf2_per_objfile->all_type_units
= xmalloc (dwarf2_per_objfile->n_type_units
* sizeof (struct signatured_type *));
return 1;
}
+/* Add an entry for signature SIG to dwarf2_per_objfile->signatured_types.
+ If SLOT is non-NULL, it is the entry to use in the hash table.
+ Otherwise we find one. */
+
+static struct signatured_type *
+add_type_unit (ULONGEST sig, void **slot)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ int n_type_units = dwarf2_per_objfile->n_type_units;
+ struct signatured_type *sig_type;
+
+ gdb_assert (n_type_units <= dwarf2_per_objfile->n_allocated_type_units);
+ ++n_type_units;
+ if (n_type_units > dwarf2_per_objfile->n_allocated_type_units)
+ {
+ if (dwarf2_per_objfile->n_allocated_type_units == 0)
+ dwarf2_per_objfile->n_allocated_type_units = 1;
+ dwarf2_per_objfile->n_allocated_type_units *= 2;
+ dwarf2_per_objfile->all_type_units
+ = xrealloc (dwarf2_per_objfile->all_type_units,
+ dwarf2_per_objfile->n_allocated_type_units
+ * sizeof (struct signatured_type *));
+ ++dwarf2_per_objfile->tu_stats.nr_all_type_units_reallocs;
+ }
+ dwarf2_per_objfile->n_type_units = n_type_units;
+
+ sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct signatured_type);
+ dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
+ sig_type->signature = sig;
+ sig_type->per_cu.is_debug_types = 1;
+ if (dwarf2_per_objfile->using_index)
+ {
+ sig_type->per_cu.v.quick =
+ OBSTACK_ZALLOC (&objfile->objfile_obstack,
+ struct dwarf2_per_cu_quick_data);
+ }
+
+ if (slot == NULL)
+ {
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ sig_type, INSERT);
+ }
+ gdb_assert (*slot == NULL);
+ *slot = sig_type;
+ /* The rest of sig_type must be filled in by the caller. */
+ return sig_type;
+}
+
/* Subroutine of lookup_dwo_signatured_type and lookup_dwp_signatured_type.
Fill in SIG_ENTRY with DWO_ENTRY. */
/* Make sure we're not clobbering something we don't expect to. */
gdb_assert (! sig_entry->per_cu.queued);
gdb_assert (sig_entry->per_cu.cu == NULL);
- gdb_assert (sig_entry->per_cu.v.quick != NULL);
- gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
+ if (dwarf2_per_objfile->using_index)
+ {
+ gdb_assert (sig_entry->per_cu.v.quick != NULL);
+ gdb_assert (sig_entry->per_cu.v.quick->symtab == NULL);
+ }
+ else
+ gdb_assert (sig_entry->per_cu.v.psymtab == NULL);
gdb_assert (sig_entry->signature == dwo_entry->signature);
gdb_assert (sig_entry->type_offset_in_section.sect_off == 0);
gdb_assert (sig_entry->type_unit_group == NULL);
struct dwo_file *dwo_file;
struct dwo_unit find_dwo_entry, *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
+ void **slot;
gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
- /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
- dwo_unit of the TU itself. */
- dwo_file = cu->dwo_unit->dwo_file;
+ /* 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);
+ }
/* We only ever need to read in one copy of a signatured type.
- Just use the global signatured_types array. If this is the first time
- we're reading this type, replace the recorded data from .gdb_index with
- this TU. */
+ Use the global signatured_types array to do our own comdat-folding
+ of types. If this is the first time we're reading this TU, and
+ the TU has an entry in .gdb_index, replace the recorded data from
+ .gdb_index with this TU. */
- if (dwarf2_per_objfile->signatured_types == NULL)
- return NULL;
find_sig_entry.signature = sig;
- sig_entry = htab_find (dwarf2_per_objfile->signatured_types, &find_sig_entry);
- if (sig_entry == NULL)
- return NULL;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry, INSERT);
+ sig_entry = *slot;
/* We can get here with the TU already read, *or* in the process of being
- read. Don't reassign it if that's the case. Also note that if the TU is
- already being read, it may not have come from a DWO, the program may be
- a mix of Fission-compiled code and non-Fission-compiled code. */
- /* Have we already tried to read this TU? */
- if (sig_entry->per_cu.tu_read)
+ read. Don't reassign the global entry to point to this DWO if that's
+ the case. Also note that if the TU is already being read, it may not
+ have come from a DWO, the program may be a mix of Fission-compiled
+ code and non-Fission-compiled code. */
+
+ /* Have we already tried to read this TU?
+ Note: sig_entry can be NULL if the skeleton TU was removed (thus it
+ needn't exist in the global table yet). */
+ if (sig_entry != NULL && sig_entry->per_cu.tu_read)
return sig_entry;
+ /* Note: cu->dwo_unit is the dwo_unit that references this TU, not the
+ dwo_unit of the TU itself. */
+ dwo_file = cu->dwo_unit->dwo_file;
+
/* Ok, this is the first time we're reading this TU. */
if (dwo_file->tus == NULL)
return NULL;
if (dwo_entry == NULL)
return NULL;
+ /* If the global table doesn't have an entry for this TU, add one. */
+ if (sig_entry == NULL)
+ sig_entry = add_type_unit (sig, slot);
+
fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
sig_entry->per_cu.tu_read = 1;
return sig_entry;
}
-/* Subroutine of lookup_dwp_signatured_type.
- Add an entry for signature SIG to dwarf2_per_objfile->signatured_types. */
-
-static struct signatured_type *
-add_type_unit (ULONGEST sig)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- int n_type_units = dwarf2_per_objfile->n_type_units;
- struct signatured_type *sig_type;
- void **slot;
-
- ++n_type_units;
- dwarf2_per_objfile->all_type_units =
- xrealloc (dwarf2_per_objfile->all_type_units,
- n_type_units * sizeof (struct signatured_type *));
- dwarf2_per_objfile->n_type_units = n_type_units;
- sig_type = OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct signatured_type);
- dwarf2_per_objfile->all_type_units[n_type_units - 1] = sig_type;
- sig_type->signature = sig;
- sig_type->per_cu.is_debug_types = 1;
- sig_type->per_cu.v.quick =
- OBSTACK_ZALLOC (&objfile->objfile_obstack,
- struct dwarf2_per_cu_quick_data);
- slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
- sig_type, INSERT);
- gdb_assert (*slot == NULL);
- *slot = sig_type;
- /* The rest of sig_type must be filled in by the caller. */
- return sig_type;
-}
-
/* Subroutine of lookup_signatured_type.
Look up the type for signature SIG, and if we can't find SIG in .gdb_index
- then try the DWP file.
- Normally this "can't happen", but if there's a bug in signature
- generation and/or the DWP file is built incorrectly, it can happen.
- Using the type directly from the DWP file means we don't have the stub
- which has some useful attributes (e.g., DW_AT_comp_dir), but they're
- not critical. [Eventually the stub may go away for type units anyway.] */
+ then try the DWP file. If the TU stub (skeleton) has been removed then
+ it won't be in .gdb_index. */
static struct signatured_type *
lookup_dwp_signatured_type (struct dwarf2_cu *cu, ULONGEST sig)
struct dwp_file *dwp_file = get_dwp_file ();
struct dwo_unit *dwo_entry;
struct signatured_type find_sig_entry, *sig_entry;
+ void **slot;
gdb_assert (cu->dwo_unit && dwarf2_per_objfile->using_index);
gdb_assert (dwp_file != NULL);
- if (dwarf2_per_objfile->signatured_types != NULL)
+ /* If TU skeletons have been removed then we may not have read in any
+ TUs yet. */
+ if (dwarf2_per_objfile->signatured_types == NULL)
{
- find_sig_entry.signature = sig;
- sig_entry = htab_find (dwarf2_per_objfile->signatured_types,
- &find_sig_entry);
- if (sig_entry != NULL)
- return sig_entry;
+ dwarf2_per_objfile->signatured_types
+ = allocate_signatured_type_table (objfile);
}
- /* This is the "shouldn't happen" case.
- Try the DWP file and hope for the best. */
+ find_sig_entry.signature = sig;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types,
+ &find_sig_entry, INSERT);
+ sig_entry = *slot;
+
+ /* Have we already tried to read this TU?
+ Note: sig_entry can be NULL if the skeleton TU was removed (thus it
+ needn't exist in the global table yet). */
+ if (sig_entry != NULL)
+ return sig_entry;
+
if (dwp_file->tus == NULL)
return NULL;
dwo_entry = lookup_dwo_unit_in_dwp (dwp_file, NULL,
if (dwo_entry == NULL)
return NULL;
- sig_entry = add_type_unit (sig);
+ sig_entry = add_type_unit (sig, slot);
fill_in_sig_entry_from_dwo_entry (objfile, sig_entry, dwo_entry);
- /* The caller will signal a complaint if we return NULL.
- Here we don't return NULL but we still want to complain. */
- complaint (&symfile_complaints,
- _("Bad type signature %s referenced by %s at 0x%x,"
- " coping by using copy in DWP [in module %s]"),
- hex_string (sig),
- cu->per_cu->is_debug_types ? "TU" : "CU",
- cu->per_cu->offset.sect_off,
- objfile_name (objfile));
-
return sig_entry;
}
}
/* Subroutine of init_cutu_and_read_dies to simplify it.
- Read a TU directly from a DWO file, bypassing the stub. */
+ See it for a description of the parameters.
+ Read a TU directly from a DWO file, bypassing the stub.
+
+ Note: This function could be a little bit simpler if we shared cleanups
+ with our caller, init_cutu_and_read_dies. That's generally a fragile thing
+ to do, so we keep this function self-contained. Or we could move this
+ into our caller, but it's complex enough already. */
static void
-init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu, int keep,
+init_tu_and_read_dwo_dies (struct dwarf2_per_cu_data *this_cu,
+ int use_existing_cu, int keep,
die_reader_func_ftype *die_reader_func,
void *data)
{
struct dwarf2_cu *cu;
struct signatured_type *sig_type;
- struct cleanup *cleanups, *free_cu_cleanup;
+ struct cleanup *cleanups, *free_cu_cleanup = NULL;
struct die_reader_specs reader;
const gdb_byte *info_ptr;
struct die_info *comp_unit_die;
cleanups = make_cleanup (null_cleanup, NULL);
- gdb_assert (this_cu->cu == NULL);
- cu = xmalloc (sizeof (*cu));
- init_one_comp_unit (cu, this_cu);
- /* If an error occurs while loading, release our storage. */
- free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+ if (use_existing_cu && this_cu->cu != NULL)
+ {
+ gdb_assert (this_cu->cu->dwo_unit == sig_type->dwo_unit);
+ cu = this_cu->cu;
+ /* There's no need to do the rereading_dwo_cu handling that
+ init_cutu_and_read_dies does since we don't read the stub. */
+ }
+ else
+ {
+ /* If !use_existing_cu, this_cu->cu must be NULL. */
+ gdb_assert (this_cu->cu == NULL);
+ cu = xmalloc (sizeof (*cu));
+ init_one_comp_unit (cu, this_cu);
+ /* If an error occurs while loading, release our storage. */
+ free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
+ }
+
+ /* A future optimization, if needed, would be to use an existing
+ abbrev table. When reading DWOs with skeletonless TUs, all the TUs
+ could share abbrev tables. */
if (read_cutu_die_from_dwo (this_cu, sig_type->dwo_unit,
0 /* abbrev_table_provided */,
/* All the "real" work is done here. */
die_reader_func (&reader, info_ptr, comp_unit_die, has_children, data);
- /* This duplicates some code in init_cutu_and_read_dies,
+ /* This duplicates the code in init_cutu_and_read_dies,
but the alternative is making the latter more complex.
This function is only for the special case of using DWO files directly:
no point in overly complicating the general case just to handle this. */
- if (keep)
+ if (free_cu_cleanup != NULL)
{
- /* We've successfully allocated this compilation unit. Let our
- caller clean it up when finished with it. */
- discard_cleanups (free_cu_cleanup);
+ if (keep)
+ {
+ /* We've successfully allocated this compilation unit. Let our
+ caller clean it up when finished with it. */
+ discard_cleanups (free_cu_cleanup);
- /* We can only discard free_cu_cleanup and all subsequent cleanups.
- So we have to manually free the abbrev table. */
- dwarf2_free_abbrev_table (cu);
+ /* We can only discard free_cu_cleanup and all subsequent cleanups.
+ So we have to manually free the abbrev table. */
+ dwarf2_free_abbrev_table (cu);
- /* Link this CU into read_in_chain. */
- this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
- dwarf2_per_objfile->read_in_chain = this_cu;
+ /* Link this CU into read_in_chain. */
+ this_cu->cu->read_in_chain = dwarf2_per_objfile->read_in_chain;
+ dwarf2_per_objfile->read_in_chain = this_cu;
+ }
+ else
+ do_cleanups (free_cu_cleanup);
}
- else
- do_cleanups (free_cu_cleanup);
do_cleanups (cleanups);
}
/* Narrow down the scope of possibilities to have to understand. */
gdb_assert (this_cu->is_debug_types);
gdb_assert (abbrev_table == NULL);
- gdb_assert (!use_existing_cu);
- init_tu_and_read_dwo_dies (this_cu, keep, die_reader_func, data);
+ init_tu_and_read_dwo_dies (this_cu, use_existing_cu, keep,
+ die_reader_func, data);
return;
}
if (use_existing_cu && this_cu->cu != NULL)
{
cu = this_cu->cu;
-
/* If this CU is from a DWO file we need to start over, we need to
refetch the attributes from the skeleton CU.
This could be optimized by retrieving those attributes from when we
{
/* If !use_existing_cu, this_cu->cu must be NULL. */
gdb_assert (this_cu->cu == NULL);
-
cu = xmalloc (sizeof (*cu));
init_one_comp_unit (cu, this_cu);
-
/* If an error occurs while loading, release our storage. */
free_cu_cleanup = make_cleanup (free_heap_comp_unit, cu);
}
return tu_group;
}
-
-/* Struct used to sort TUs by their abbreviation table offset. */
-
-struct tu_abbrev_offset
-{
- struct signatured_type *sig_type;
- sect_offset abbrev_offset;
-};
-
-/* Helper routine for build_type_unit_groups, passed to qsort. */
-
-static int
-sort_tu_by_abbrev_offset (const void *ap, const void *bp)
-{
- const struct tu_abbrev_offset * const *a = ap;
- const struct tu_abbrev_offset * const *b = bp;
- unsigned int aoff = (*a)->abbrev_offset.sect_off;
- unsigned int boff = (*b)->abbrev_offset.sect_off;
-
- return (aoff > boff) - (aoff < boff);
-}
-
-/* Efficiently read all the type units, calling init_cutu_and_read_dies on
- each one passing FUNC,DATA.
-
- The efficiency is because we sort TUs by the abbrev table they use and
- only read each abbrev table once. In one program there are 200K TUs
- sharing 8K abbrev tables.
-
- The main purpose of this function is to support building the
- dwarf2_per_objfile->type_unit_groups table.
- TUs typically share the DW_AT_stmt_list of the CU they came from, so we
- can collapse the search space by grouping them by stmt_list.
- The savings can be significant, in the same program from above the 200K TUs
- share 8K stmt_list tables.
-
- FUNC is expected to call get_type_unit_group, which will create the
- struct type_unit_group if necessary and add it to
- dwarf2_per_objfile->type_unit_groups. */
-
-static void
-build_type_unit_groups (die_reader_func_ftype *func, void *data)
-{
- struct objfile *objfile = dwarf2_per_objfile->objfile;
- struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
- struct cleanup *cleanups;
- struct abbrev_table *abbrev_table;
- sect_offset abbrev_offset;
- struct tu_abbrev_offset *sorted_by_abbrev;
- struct type_unit_group **iter;
- int i;
-
- /* It's up to the caller to not call us multiple times. */
- gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
-
- if (dwarf2_per_objfile->n_type_units == 0)
- return;
-
- /* TUs typically share abbrev tables, and there can be way more TUs than
- abbrev tables. Sort by abbrev table to reduce the number of times we
- read each abbrev table in.
- Alternatives are to punt or to maintain a cache of abbrev tables.
- This is simpler and efficient enough for now.
-
- Later we group TUs by their DW_AT_stmt_list value (as this defines the
- symtab to use). Typically TUs with the same abbrev offset have the same
- stmt_list value too so in practice this should work well.
-
- The basic algorithm here is:
-
- sort TUs by abbrev table
- for each TU with same abbrev table:
- read abbrev table if first user
- read TU top level DIE
- [IWBN if DWO skeletons had DW_AT_stmt_list]
- call FUNC */
-
- if (dwarf2_read_debug)
- fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
-
- /* Sort in a separate table to maintain the order of all_type_units
- for .gdb_index: TU indices directly index all_type_units. */
- sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
- dwarf2_per_objfile->n_type_units);
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
-
- sorted_by_abbrev[i].sig_type = sig_type;
- sorted_by_abbrev[i].abbrev_offset =
- read_abbrev_offset (sig_type->per_cu.section,
- sig_type->per_cu.offset);
- }
- cleanups = make_cleanup (xfree, sorted_by_abbrev);
- qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
- sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
-
- /* Note: In the .gdb_index case, get_type_unit_group may have already been
- called any number of times, so we don't reset tu_stats here. */
-
- abbrev_offset.sect_off = ~(unsigned) 0;
- abbrev_table = NULL;
- make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
-
- for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
- {
- const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
-
- /* Switch to the next abbrev table if necessary. */
- if (abbrev_table == NULL
- || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
- {
- if (abbrev_table != NULL)
- {
- abbrev_table_free (abbrev_table);
- /* Reset to NULL in case abbrev_table_read_table throws
- an error: abbrev_table_free_cleanup will get called. */
- abbrev_table = NULL;
- }
- abbrev_offset = tu->abbrev_offset;
- abbrev_table =
- abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
- abbrev_offset);
- ++tu_stats->nr_uniq_abbrev_tables;
- }
-
- init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
- func, data);
- }
-
- /* type_unit_groups can be NULL if there is an error in the debug info.
- Just create an empty table so the rest of gdb doesn't have to watch
- for this error case. */
- if (dwarf2_per_objfile->type_unit_groups == NULL)
- {
- dwarf2_per_objfile->type_unit_groups =
- allocate_type_unit_groups_table ();
- }
-
- do_cleanups (cleanups);
-
- if (dwarf2_read_debug)
- {
- fprintf_unfiltered (gdb_stdlog, "Done building type unit groups:\n");
- fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
- dwarf2_per_objfile->n_type_units);
- fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
- tu_stats->nr_uniq_abbrev_tables);
- fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
- tu_stats->nr_symtabs);
- fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
- tu_stats->nr_symtab_sharers);
- fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
- tu_stats->nr_stmt_less_type_units);
- }
-}
\f
/* Partial symbol tables. */
sort_pst_symbols (objfile, pst);
}
+/* Struct used to sort TUs by their abbreviation table offset. */
+
+struct tu_abbrev_offset
+{
+ struct signatured_type *sig_type;
+ sect_offset abbrev_offset;
+};
+
+/* Helper routine for build_type_psymtabs_1, passed to qsort. */
+
+static int
+sort_tu_by_abbrev_offset (const void *ap, const void *bp)
+{
+ const struct tu_abbrev_offset * const *a = ap;
+ const struct tu_abbrev_offset * const *b = bp;
+ unsigned int aoff = (*a)->abbrev_offset.sect_off;
+ unsigned int boff = (*b)->abbrev_offset.sect_off;
+
+ return (aoff > boff) - (aoff < boff);
+}
+
+/* Efficiently read all the type units.
+ This does the bulk of the work for build_type_psymtabs.
+
+ The efficiency is because we sort TUs by the abbrev table they use and
+ only read each abbrev table once. In one program there are 200K TUs
+ sharing 8K abbrev tables.
+
+ The main purpose of this function is to support building the
+ dwarf2_per_objfile->type_unit_groups table.
+ TUs typically share the DW_AT_stmt_list of the CU they came from, so we
+ can collapse the search space by grouping them by stmt_list.
+ The savings can be significant, in the same program from above the 200K TUs
+ share 8K stmt_list tables.
+
+ FUNC is expected to call get_type_unit_group, which will create the
+ struct type_unit_group if necessary and add it to
+ dwarf2_per_objfile->type_unit_groups. */
+
+static void
+build_type_psymtabs_1 (void)
+{
+ struct objfile *objfile = dwarf2_per_objfile->objfile;
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
+ struct cleanup *cleanups;
+ struct abbrev_table *abbrev_table;
+ sect_offset abbrev_offset;
+ struct tu_abbrev_offset *sorted_by_abbrev;
+ struct type_unit_group **iter;
+ int i;
+
+ /* It's up to the caller to not call us multiple times. */
+ gdb_assert (dwarf2_per_objfile->type_unit_groups == NULL);
+
+ if (dwarf2_per_objfile->n_type_units == 0)
+ return;
+
+ /* TUs typically share abbrev tables, and there can be way more TUs than
+ abbrev tables. Sort by abbrev table to reduce the number of times we
+ read each abbrev table in.
+ Alternatives are to punt or to maintain a cache of abbrev tables.
+ This is simpler and efficient enough for now.
+
+ Later we group TUs by their DW_AT_stmt_list value (as this defines the
+ symtab to use). Typically TUs with the same abbrev offset have the same
+ stmt_list value too so in practice this should work well.
+
+ The basic algorithm here is:
+
+ sort TUs by abbrev table
+ for each TU with same abbrev table:
+ read abbrev table if first user
+ read TU top level DIE
+ [IWBN if DWO skeletons had DW_AT_stmt_list]
+ call FUNC */
+
+ if (dwarf2_read_debug)
+ fprintf_unfiltered (gdb_stdlog, "Building type unit groups ...\n");
+
+ /* Sort in a separate table to maintain the order of all_type_units
+ for .gdb_index: TU indices directly index all_type_units. */
+ sorted_by_abbrev = XNEWVEC (struct tu_abbrev_offset,
+ dwarf2_per_objfile->n_type_units);
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ struct signatured_type *sig_type = dwarf2_per_objfile->all_type_units[i];
+
+ sorted_by_abbrev[i].sig_type = sig_type;
+ sorted_by_abbrev[i].abbrev_offset =
+ read_abbrev_offset (sig_type->per_cu.section,
+ sig_type->per_cu.offset);
+ }
+ cleanups = make_cleanup (xfree, sorted_by_abbrev);
+ qsort (sorted_by_abbrev, dwarf2_per_objfile->n_type_units,
+ sizeof (struct tu_abbrev_offset), sort_tu_by_abbrev_offset);
+
+ abbrev_offset.sect_off = ~(unsigned) 0;
+ abbrev_table = NULL;
+ make_cleanup (abbrev_table_free_cleanup, &abbrev_table);
+
+ for (i = 0; i < dwarf2_per_objfile->n_type_units; ++i)
+ {
+ const struct tu_abbrev_offset *tu = &sorted_by_abbrev[i];
+
+ /* Switch to the next abbrev table if necessary. */
+ if (abbrev_table == NULL
+ || tu->abbrev_offset.sect_off != abbrev_offset.sect_off)
+ {
+ if (abbrev_table != NULL)
+ {
+ abbrev_table_free (abbrev_table);
+ /* Reset to NULL in case abbrev_table_read_table throws
+ an error: abbrev_table_free_cleanup will get called. */
+ abbrev_table = NULL;
+ }
+ abbrev_offset = tu->abbrev_offset;
+ abbrev_table =
+ abbrev_table_read_table (&dwarf2_per_objfile->abbrev,
+ abbrev_offset);
+ ++tu_stats->nr_uniq_abbrev_tables;
+ }
+
+ init_cutu_and_read_dies (&tu->sig_type->per_cu, abbrev_table, 0, 0,
+ build_type_psymtabs_reader, NULL);
+ }
+
+ do_cleanups (cleanups);
+}
+
+/* Print collected type unit statistics. */
+
+static void
+print_tu_stats (void)
+{
+ struct tu_stats *tu_stats = &dwarf2_per_objfile->tu_stats;
+
+ fprintf_unfiltered (gdb_stdlog, "Type unit statistics:\n");
+ fprintf_unfiltered (gdb_stdlog, " %d TUs\n",
+ dwarf2_per_objfile->n_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d uniq abbrev tables\n",
+ tu_stats->nr_uniq_abbrev_tables);
+ fprintf_unfiltered (gdb_stdlog, " %d symtabs from stmt_list entries\n",
+ tu_stats->nr_symtabs);
+ fprintf_unfiltered (gdb_stdlog, " %d symtab sharers\n",
+ tu_stats->nr_symtab_sharers);
+ fprintf_unfiltered (gdb_stdlog, " %d type units without a stmt_list\n",
+ tu_stats->nr_stmt_less_type_units);
+ fprintf_unfiltered (gdb_stdlog, " %d all_type_units reallocs\n",
+ tu_stats->nr_all_type_units_reallocs);
+}
+
/* Traversal function for build_type_psymtabs. */
static int
if (! create_all_type_units (objfile))
return;
- build_type_unit_groups (build_type_psymtabs_reader, NULL);
+ build_type_psymtabs_1 ();
+}
+
+/* Traversal function for process_skeletonless_type_unit.
+ Read a TU in a DWO file and build partial symbols for it. */
- /* Now that all TUs have been processed we can fill in the dependencies. */
- htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
- build_type_psymtab_dependencies, NULL);
+static int
+process_skeletonless_type_unit (void **slot, void *info)
+{
+ struct dwo_unit *dwo_unit = (struct dwo_unit *) *slot;
+ struct objfile *objfile = info;
+ struct signatured_type find_entry, *entry;
+
+ /* 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 (objfile);
+ }
+
+ find_entry.signature = dwo_unit->signature;
+ slot = htab_find_slot (dwarf2_per_objfile->signatured_types, &find_entry,
+ INSERT);
+ /* If we've already seen this type there's nothing to do. What's happening
+ is we're doing our own version of comdat-folding here. */
+ if (*slot != NULL)
+ return 1;
+
+ /* This does the job that create_all_type_units would have done for
+ this TU. */
+ entry = add_type_unit (dwo_unit->signature, slot);
+ fill_in_sig_entry_from_dwo_entry (objfile, entry, dwo_unit);
+ *slot = entry;
+
+ /* This does the job that build_type_psymtabs_1 would have done. */
+ init_cutu_and_read_dies (&entry->per_cu, NULL, 0, 0,
+ build_type_psymtabs_reader, NULL);
+
+ return 1;
+}
+
+/* Traversal function for process_skeletonless_type_units. */
+
+static int
+process_dwo_file_for_skeletonless_type_units (void **slot, void *info)
+{
+ struct dwo_file *dwo_file = (struct dwo_file *) *slot;
+
+ if (dwo_file->tus != NULL)
+ {
+ htab_traverse_noresize (dwo_file->tus,
+ process_skeletonless_type_unit, info);
+ }
+
+ return 1;
+}
+
+/* Scan all TUs of DWO files, verifying we've processed them.
+ This is needed in case a TU was emitted without its skeleton.
+ Note: This can't be done until we know what all the DWO files are. */
+
+static void
+process_skeletonless_type_units (struct objfile *objfile)
+{
+ /* Skeletonless TUs in DWP files without .gdb_index is not supported yet. */
+ if (get_dwp_file () == NULL
+ && dwarf2_per_objfile->dwo_files != NULL)
+ {
+ htab_traverse_noresize (dwarf2_per_objfile->dwo_files,
+ process_dwo_file_for_skeletonless_type_units,
+ objfile);
+ }
}
/* A cleanup function that clears objfile's psymtabs_addrmap field. */
process_psymtab_comp_unit (per_cu, 0, language_minimal);
}
+ /* This has to wait until we read the CUs, we need the list of DWOs. */
+ process_skeletonless_type_units (objfile);
+
+ /* Now that all TUs have been processed we can fill in the dependencies. */
+ if (dwarf2_per_objfile->type_unit_groups != NULL)
+ {
+ htab_traverse_noresize (dwarf2_per_objfile->type_unit_groups,
+ build_type_psymtab_dependencies, NULL);
+ }
+
+ if (dwarf2_read_debug)
+ print_tu_stats ();
+
set_partial_user (objfile);
objfile->psymtabs_addrmap = addrmap_create_fixed (objfile->psymtabs_addrmap,
}
/* Process all loaded DIEs for compilation unit CU, starting at
- FIRST_DIE. The caller should pass NEED_PC == 1 if the compilation
+ FIRST_DIE. The caller should pass SET_ADDRMAP == 1 if the compilation
unit DIE did not have PC info (DW_AT_low_pc and DW_AT_high_pc, or
- DW_AT_ranges). If NEED_PC is set, then this function will set
- *LOWPC and *HIGHPC to the lowest and highest PC values found in CU
- and record the covered ranges in the addrmap. */
+ DW_AT_ranges). See the comments of add_partial_subprogram on how
+ SET_ADDRMAP is used and how *LOWPC and *HIGHPC are updated. */
static void
scan_partial_symbols (struct partial_die_info *first_die, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int set_addrmap,
+ struct dwarf2_cu *cu)
{
struct partial_die_info *pdi;
switch (pdi->tag)
{
case DW_TAG_subprogram:
- add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_constant:
case DW_TAG_variable:
add_partial_symbol (pdi, cu);
break;
case DW_TAG_namespace:
- add_partial_namespace (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_namespace (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_module:
- add_partial_module (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_module (pdi, lowpc, highpc, set_addrmap, cu);
break;
case DW_TAG_imported_unit:
{
static void
add_partial_namespace (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu)
+ int set_addrmap, struct dwarf2_cu *cu)
{
/* Add a symbol for the namespace. */
/* Now scan partial symbols in that namespace. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
/* Read a partial die corresponding to a Fortran module. */
static void
add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
- CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
+ CORE_ADDR *highpc, int set_addrmap, struct dwarf2_cu *cu)
{
/* Add a symbol for the namespace. */
/* Now scan partial symbols in that module. */
if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
}
/* Read a partial die corresponding to a subprogram and create a partial
symbol for that subprogram. When the CU language allows it, this
routine also defines a partial symbol for each nested subprogram
- that this subprogram contains.
+ that this subprogram contains. If SET_ADDRMAP is true, record the
+ covered ranges in the addrmap. Set *LOWPC and *HIGHPC to the lowest
+ and highest PC values found in PDI.
- DIE my also be a lexical block, in which case we simply search
- recursively for suprograms defined inside that lexical block.
+ PDI may also be a lexical block, in which case we simply search
+ recursively for subprograms defined inside that lexical block.
Again, this is only performed when the CU language allows this
type of definitions. */
static void
add_partial_subprogram (struct partial_die_info *pdi,
CORE_ADDR *lowpc, CORE_ADDR *highpc,
- int need_pc, struct dwarf2_cu *cu)
+ int set_addrmap, struct dwarf2_cu *cu)
{
if (pdi->tag == DW_TAG_subprogram)
{
*lowpc = pdi->lowpc;
if (pdi->highpc > *highpc)
*highpc = pdi->highpc;
- if (need_pc)
+ if (set_addrmap)
{
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
fixup_partial_die (pdi, cu);
if (pdi->tag == DW_TAG_subprogram
|| pdi->tag == DW_TAG_lexical_block)
- add_partial_subprogram (pdi, lowpc, highpc, need_pc, cu);
+ add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
pdi = pdi->die_sibling;
}
}
if (package_name != NULL)
{
struct objfile *objfile = cu->objfile;
- const char *saved_package_name = obstack_copy0 (&objfile->objfile_obstack,
- package_name,
- strlen (package_name));
+ const char *saved_package_name
+ = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ package_name,
+ strlen (package_name));
struct type *type = init_type (TYPE_CODE_MODULE, 0, 0,
saved_package_name, objfile);
struct symbol *sym;
long length;
const char *prefix;
struct ui_file *buf;
+ char *intermediate_name;
+ const char *canonical_name = NULL;
prefix = determine_prefix (die, cu);
buf = mem_fileopen ();
}
}
- name = ui_file_obsavestring (buf, &objfile->objfile_obstack,
- &length);
+ intermediate_name = ui_file_xstrdup (buf, &length);
ui_file_delete (buf);
if (cu->language == language_cplus)
- {
- const char *cname
- = dwarf2_canonicalize_name (name, cu,
- &objfile->objfile_obstack);
+ canonical_name
+ = dwarf2_canonicalize_name (intermediate_name, 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)
+ name = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ intermediate_name,
+ strlen (intermediate_name));
+ else
+ name = canonical_name;
- if (cname != NULL)
- name = cname;
- }
+ xfree (intermediate_name);
}
}
/* Return the fully qualified name of DIE, based on its DW_AT_name.
If scope qualifiers are appropriate they will be added. The result
- will be allocated on the objfile_obstack, or NULL if the DIE does
+ will be allocated on the storage_obstack, or NULL if the DIE does
not have a name. NAME may either be from a previous call to
dwarf2_name or NULL.
retval = canon;
if (need_copy)
- retval = obstack_copy0 (&objfile->objfile_obstack, retval, strlen (retval));
+ retval = obstack_copy0 (&objfile->per_bfd->storage_obstack,
+ retval, strlen (retval));
do_cleanups (back_to);
return retval;
/* Handle DW_AT_stmt_list for a compilation unit.
DIE is the DW_TAG_compile_unit die for CU.
- COMP_DIR is the compilation directory.
- WANT_LINE_INFO is non-zero if the pc/line-number mapping is needed. */
+ COMP_DIR is the compilation directory. LOWPC is passed to
+ dwarf_decode_lines. See dwarf_decode_lines comments about it. */
static void
handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
- const char *comp_dir) /* ARI: editCase function */
+ const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */
{
struct attribute *attr;
{
cu->line_header = line_header;
make_cleanup (free_cu_line_header, cu);
- dwarf_decode_lines (line_header, comp_dir, cu, NULL, 1);
+ dwarf_decode_lines (line_header, comp_dir, cu, NULL, lowpc);
}
}
}
/* Decode line number information if present. We do this before
processing child DIEs, so that the line header table is available
for DW_AT_decl_file. */
- handle_DW_AT_stmt_list (die, cu, comp_dir);
+ handle_DW_AT_stmt_list (die, cu, comp_dir, lowpc);
/* Process all dies in compilation unit. */
if (die->child != NULL)
TYPE_LENGTH (type) = 0;
}
- if (producer_is_icc (cu))
+ if (producer_is_icc (cu) && (TYPE_LENGTH (type) == 0))
{
/* ICC does not output the required DW_AT_declaration
on incomplete types, but gives them a size of zero. */
+ TYPE_STUB (type) = 1;
}
else
TYPE_STUB_SUPPORTED (type) = 1;
return set_die_type (die, type, cu);
}
+/* Add the given cv-qualifiers to the element type of the array. GCC
+ outputs DWARF type qualifiers that apply to an array, not the
+ element type. But GDB relies on the array element type to carry
+ the cv-qualifiers. This mimics section 6.7.3 of the C99
+ specification. */
+
+static struct type *
+add_array_cv_type (struct die_info *die, struct dwarf2_cu *cu,
+ struct type *base_type, int cnst, int voltl)
+{
+ struct type *el_type, *inner_array;
+
+ base_type = copy_type (base_type);
+ inner_array = base_type;
+
+ while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
+ {
+ TYPE_TARGET_TYPE (inner_array) =
+ copy_type (TYPE_TARGET_TYPE (inner_array));
+ inner_array = TYPE_TARGET_TYPE (inner_array);
+ }
+
+ el_type = TYPE_TARGET_TYPE (inner_array);
+ cnst |= TYPE_CONST (el_type);
+ voltl |= TYPE_VOLATILE (el_type);
+ TYPE_TARGET_TYPE (inner_array) = make_cv_type (cnst, voltl, el_type, NULL);
+
+ return set_die_type (die, base_type, cu);
+}
+
static struct type *
read_tag_const_type (struct die_info *die, struct dwarf2_cu *cu)
{
/* In case the const qualifier is applied to an array type, the element type
is so qualified, not the array type (section 6.7.3 of C99). */
if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
- {
- struct type *el_type, *inner_array;
-
- base_type = copy_type (base_type);
- inner_array = base_type;
-
- while (TYPE_CODE (TYPE_TARGET_TYPE (inner_array)) == TYPE_CODE_ARRAY)
- {
- TYPE_TARGET_TYPE (inner_array) =
- copy_type (TYPE_TARGET_TYPE (inner_array));
- inner_array = TYPE_TARGET_TYPE (inner_array);
- }
-
- el_type = TYPE_TARGET_TYPE (inner_array);
- TYPE_TARGET_TYPE (inner_array) =
- make_cv_type (1, TYPE_VOLATILE (el_type), el_type, NULL);
-
- return set_die_type (die, base_type, cu);
- }
+ return add_array_cv_type (die, cu, base_type, 1, 0);
cv_type = make_cv_type (1, TYPE_VOLATILE (base_type), base_type, 0);
return set_die_type (die, cv_type, cu);
if (cv_type)
return cv_type;
+ /* In case the volatile qualifier is applied to an array type, the
+ element type is so qualified, not the array type (section 6.7.3
+ of C99). */
+ if (TYPE_CODE (base_type) == TYPE_CODE_ARRAY)
+ return add_array_cv_type (die, cu, base_type, 0, 1);
+
cv_type = make_cv_type (TYPE_CONST (base_type), 1, base_type, 0);
return set_die_type (die, cv_type, cu);
}
/* Same as abbrev_table_free but as a cleanup.
We pass in a pointer to the pointer to the table so that we can
set the pointer to NULL when we're done. It also simplifies
- build_type_unit_groups. */
+ build_type_psymtabs_1. */
static void
abbrev_table_free_cleanup (void *table_ptr)
default:
part_die->name
= dwarf2_canonicalize_name (DW_STRING (&attr), cu,
- &objfile->objfile_obstack);
+ &objfile->per_bfd->storage_obstack);
break;
}
break;
if (actual_class_name != NULL)
{
struct_pdi->name
- = obstack_copy0 (&cu->objfile->objfile_obstack,
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
actual_class_name,
strlen (actual_class_name));
xfree (actual_class_name);
else
base = demangled;
- part_die->name = obstack_copy0 (&cu->objfile->objfile_obstack,
- base, strlen (base));
+ part_die->name
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
+ base, strlen (base));
xfree (demangled);
}
}
include_name = "hello.c"
dir_name = "."
DW_AT_comp_dir = comp_dir = "/tmp"
- DW_AT_name = "./hello.c" */
+ DW_AT_name = "./hello.c"
+
+ */
if (dir_name != NULL)
{
return;
}
+/* Return non-zero if we should add LINE to the line number table.
+ LINE is the line to add, LAST_LINE is the last line that was added,
+ LAST_SUBFILE is the subfile for LAST_LINE.
+ LINE_HAS_NON_ZERO_DISCRIMINATOR is non-zero if LINE has ever
+ had a non-zero discriminator.
+
+ We have to be careful in the presence of discriminators.
+ E.g., for this line:
+
+ for (i = 0; i < 100000; i++);
+
+ clang can emit four line number entries for that one line,
+ each with a different discriminator.
+ See gdb.dwarf2/dw2-single-line-discriminators.exp for an example.
+
+ However, we want gdb to coalesce all four entries into one.
+ Otherwise the user could stepi into the middle of the line and
+ gdb would get confused about whether the pc really was in the
+ middle of the line.
+
+ Things are further complicated by the fact that two consecutive
+ line number entries for the same line is a heuristic used by gcc
+ to denote the end of the prologue. So we can't just discard duplicate
+ entries, we have to be selective about it. The heuristic we use is
+ that we only collapse consecutive entries for the same line if at least
+ one of those entries has a non-zero discriminator. PR 17276.
+
+ Note: Addresses in the line number state machine can never go backwards
+ within one sequence, thus this coalescing is ok. */
+
+static int
+dwarf_record_line_p (unsigned int line, unsigned int last_line,
+ int line_has_non_zero_discriminator,
+ struct subfile *last_subfile)
+{
+ if (current_subfile != last_subfile)
+ return 1;
+ if (line != last_line)
+ return 1;
+ /* Same line for the same file that we've seen already.
+ As a last check, for pr 17276, only record the line if the line
+ has never had a non-zero discriminator. */
+ if (!line_has_non_zero_discriminator)
+ return 1;
+ return 0;
+}
+
+/* Use P_RECORD_LINE to record line number LINE beginning at address ADDRESS
+ in the line table of subfile SUBFILE. */
+
+static void
+dwarf_record_line (struct gdbarch *gdbarch, struct subfile *subfile,
+ unsigned int line, CORE_ADDR address,
+ record_line_ftype p_record_line)
+{
+ CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
+
+ (*p_record_line) (subfile, line, addr);
+}
+
+/* Subroutine of dwarf_decode_lines_1 to simplify it.
+ Mark the end of a set of line number records.
+ The arguments are the same as for dwarf_record_line.
+ If SUBFILE is NULL the request is ignored. */
+
+static void
+dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
+ CORE_ADDR address, record_line_ftype p_record_line)
+{
+ if (subfile != NULL)
+ dwarf_record_line (gdbarch, subfile, 0, address, p_record_line);
+}
+
/* Subroutine of dwarf_decode_lines to simplify it.
Process the line number information in LH. */
static void
dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
- struct dwarf2_cu *cu, struct partial_symtab *pst)
+ struct dwarf2_cu *cu, const int decode_for_pst_p,
+ CORE_ADDR lowpc)
{
const gdb_byte *line_ptr, *extended_end;
const gdb_byte *line_end;
unsigned int bytes_read, extended_len;
- unsigned char op_code, extended_op, adj_opcode;
+ unsigned char op_code, extended_op;
CORE_ADDR baseaddr;
struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- const int decode_for_pst_p = (pst != NULL);
struct subfile *last_subfile = NULL;
void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc)
= record_line;
CORE_ADDR address = 0;
unsigned int file = 1;
unsigned int line = 1;
- unsigned int column = 0;
int is_stmt = lh->default_is_stmt;
- int basic_block = 0;
int end_sequence = 0;
- CORE_ADDR addr;
unsigned char op_index = 0;
+ unsigned int discriminator = 0;
+ /* The last line number that was recorded, used to coalesce
+ consecutive entries for the same line. This can happen, for
+ example, when discriminators are present. PR 17276. */
+ unsigned int last_line = 0;
+ int line_has_non_zero_discriminator = 0;
if (!decode_for_pst_p && lh->num_file_names >= file)
{
if (op_code >= lh->opcode_base)
{
- /* Special operand. */
+ /* Special opcode. */
+ unsigned char adj_opcode;
+ int line_delta;
+
adj_opcode = op_code - lh->opcode_base;
address += (((op_index + (adj_opcode / lh->line_range))
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
op_index = ((op_index + (adj_opcode / lh->line_range))
% lh->maximum_ops_per_instruction);
- line += lh->line_base + (adj_opcode % lh->line_range);
+ line_delta = lh->line_base + (adj_opcode % lh->line_range);
+ line += line_delta;
+ if (line_delta != 0)
+ line_has_non_zero_discriminator = discriminator != 0;
if (lh->num_file_names < file || file == 0)
dwarf2_debug_line_missing_file_complaint ();
/* For now we ignore lines not starting on an
{
if (last_subfile != current_subfile)
{
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- if (last_subfile)
- (*p_record_line) (last_subfile, 0, addr);
- last_subfile = current_subfile;
+ dwarf_finish_line (gdbarch, last_subfile,
+ address, p_record_line);
}
- /* Append row to matrix using current values. */
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, line, addr);
+ if (dwarf_record_line_p (line, last_line,
+ line_has_non_zero_discriminator,
+ last_subfile))
+ {
+ dwarf_record_line (gdbarch, current_subfile,
+ line, address, p_record_line);
+ }
+ last_subfile = current_subfile;
+ last_line = line;
}
}
- basic_block = 0;
+ discriminator = 0;
}
else switch (op_code)
{
case DW_LNE_set_address:
address = read_address (abfd, line_ptr, cu, &bytes_read);
- if (address == 0 && !dwarf2_per_objfile->has_section_at_zero)
+ /* If address < lowpc then it's not a usable value, it's
+ outside the pc range of the CU. However, we restrict
+ the test to only address values of zero to preserve
+ GDB's previous behaviour which is to handle the specific
+ case of a function being GC'd by the linker. */
+ if (address == 0 && address < lowpc)
{
/* This line table is for a function which has been
GCd by the linker. Ignore it. PR gdb/12528 */
"[in module %s]"),
line_offset, objfile_name (objfile));
p_record_line = noop_record_line;
+ /* Note: p_record_line is left as noop_record_line
+ until we see DW_LNE_end_sequence. */
}
op_index = 0;
break;
case DW_LNE_set_discriminator:
/* The discriminator is not interesting to the debugger;
- just ignore it. */
- line_ptr = extended_end;
+ just ignore it. We still need to check its value though:
+ if there are consecutive entries for the same
+ (non-prologue) line we want to coalesce them.
+ PR 17276. */
+ discriminator = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ line_has_non_zero_discriminator |= discriminator != 0;
+ line_ptr += bytes_read;
break;
default:
complaint (&symfile_complaints,
{
if (last_subfile != current_subfile)
{
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- if (last_subfile)
- (*p_record_line) (last_subfile, 0, addr);
- last_subfile = current_subfile;
+ dwarf_finish_line (gdbarch, last_subfile,
+ address, p_record_line);
+ }
+ if (dwarf_record_line_p (line, last_line,
+ line_has_non_zero_discriminator,
+ last_subfile))
+ {
+ dwarf_record_line (gdbarch, current_subfile,
+ line, address, p_record_line);
}
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, line, addr);
+ last_subfile = current_subfile;
+ last_line = line;
}
}
- basic_block = 0;
+ discriminator = 0;
break;
case DW_LNS_advance_pc:
{
}
break;
case DW_LNS_advance_line:
- line += read_signed_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
+ {
+ int line_delta
+ = read_signed_leb128 (abfd, line_ptr, &bytes_read);
+
+ line += line_delta;
+ if (line_delta != 0)
+ line_has_non_zero_discriminator = discriminator != 0;
+ line_ptr += bytes_read;
+ }
break;
case DW_LNS_set_file:
{
if (!decode_for_pst_p)
{
last_subfile = current_subfile;
+ line_has_non_zero_discriminator = discriminator != 0;
dwarf2_start_subfile (fe->name, dir, comp_dir);
}
}
}
break;
case DW_LNS_set_column:
- column = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_negate_stmt:
is_stmt = (!is_stmt);
break;
case DW_LNS_set_basic_block:
- basic_block = 1;
break;
/* Add to the address register of the state machine the
address increment value corresponding to special opcode
lh->file_names[file - 1].included_p = 1;
if (!decode_for_pst_p)
{
- addr = gdbarch_addr_bits_remove (gdbarch, address);
- (*p_record_line) (current_subfile, 0, addr);
+ dwarf_finish_line (gdbarch, current_subfile, address,
+ p_record_line);
}
}
}
as the corresponding symtab. Since COMP_DIR is not used in the name of the
symtab we don't use it in the name of the psymtabs we create.
E.g. expand_line_sal requires this when finding psymtabs to expand.
- A good testcase for this is mb-inline.exp. */
+ A good testcase for this is mb-inline.exp.
+
+ LOWPC is the lowest address in CU (or 0 if not known). */
static void
dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
struct dwarf2_cu *cu, struct partial_symtab *pst,
- int want_line_info)
+ CORE_ADDR lowpc)
{
struct objfile *objfile = cu->objfile;
const int decode_for_pst_p = (pst != NULL);
struct subfile *first_subfile = current_subfile;
- if (want_line_info)
- dwarf_decode_lines_1 (lh, comp_dir, cu, pst);
+ dwarf_decode_lines_1 (lh, comp_dir, cu, decode_for_pst_p, lowpc);
if (decode_for_pst_p)
{
&& actual_name[actual_name_len
- die_name_len - 1] == ':')
name =
- obstack_copy0 (&cu->objfile->objfile_obstack,
+ obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
actual_name,
actual_name_len - die_name_len - 2);
}
if (base == NULL || base == DW_STRING (attr) || base[-1] != ':')
return "";
- return obstack_copy0 (&cu->objfile->objfile_obstack,
+ return obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
DW_STRING (attr), &base[-1] - DW_STRING (attr));
}
/* GCJ will output '<init>' for Java constructor names.
For this special case, return the name of the parent class. */
- /* GCJ may output suprogram DIEs with AT_specification set.
+ /* GCJ may output subprogram DIEs with AT_specification set.
If so, use the name of the specified DIE. */
spec_die = die_specification (die, &spec_cu);
if (spec_die != NULL)
char *base;
/* FIXME: we already did this for the partial symbol... */
- DW_STRING (attr) = obstack_copy0 (&cu->objfile->objfile_obstack,
- demangled, strlen (demangled));
+ DW_STRING (attr)
+ = obstack_copy0 (&cu->objfile->per_bfd->storage_obstack,
+ demangled, strlen (demangled));
DW_STRING_IS_CANONICAL (attr) = 1;
xfree (demangled);
{
DW_STRING (attr)
= dwarf2_canonicalize_name (DW_STRING (attr), cu,
- &cu->objfile->objfile_obstack);
+ &cu->objfile->per_bfd->storage_obstack);
DW_STRING_IS_CANONICAL (attr) = 1;
}
return DW_STRING (attr);
{
struct dwarf2_per_cu_offset_and_type **slot, ofs;
struct objfile *objfile = cu->objfile;
+ struct attribute *attr;
+ struct dynamic_prop prop;
/* For Ada types, make sure that the gnat-specific data is always
initialized (if not already set). There are a few types where
&& !HAVE_GNAT_AUX_INFO (type))
INIT_GNAT_SPECIFIC (type);
+ /* Read DW_AT_data_location and set in type. */
+ attr = dwarf2_attr (die, DW_AT_data_location, cu);
+ if (attr_to_dynamic_prop (attr, die, cu, &prop))
+ {
+ TYPE_DATA_LOCATION (type)
+ = obstack_alloc (&objfile->objfile_obstack, sizeof (prop));
+ *TYPE_DATA_LOCATION (type) = prop;
+ }
+
if (dwarf2_per_objfile->die_type_hash == NULL)
{
dwarf2_per_objfile->die_type_hash =
static void
set_dwarf2_cmd (char *args, int from_tty)
{
- help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", -1, gdb_stdout);
+ help_list (set_dwarf2_cmdlist, "maintenance set dwarf2 ", all_commands,
+ gdb_stdout);
}
static void