#include "source.h"
#include "filestuff.h"
#include "build-id.h"
+#include "namespace.h"
#include <fcntl.h>
#include <sys/types.h>
/* When non-zero, dump DIEs after they are read in. */
static unsigned int dwarf_die_debug = 0;
+/* When non-zero, dump line number entries as they are read in. */
+static unsigned int dwarf_line_debug = 0;
+
/* When non-zero, cross-check physname against demangler. */
static int check_physname = 0;
struct dwarf2_section_info *section;
/* Set to non-NULL iff this CU is currently loaded. When it gets freed out
- of the CU cache it gets reset to NULL again. */
+ of the CU cache it gets reset to NULL again. This is left as NULL for
+ dummy CUs (a CU header, but nothing else). */
struct dwarf2_cu *cu;
/* The corresponding objfile.
static void read_module (struct die_info *die, struct dwarf2_cu *cu);
+static struct using_direct **using_directives (enum language);
+
static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
dwarf2_per_objfile->gdb_index.size = bfd_get_section_size (sectp);
}
- if ((bfd_get_section_flags (abfd, sectp) & SEC_LOAD)
+ if ((bfd_get_section_flags (abfd, sectp) & (SEC_LOAD | SEC_ALLOC))
&& bfd_section_vma (abfd, sectp) == 0)
dwarf2_per_objfile->has_section_at_zero = 1;
}
else
load_full_comp_unit (per_cu, language_minimal);
- gdb_assert (per_cu->cu != NULL);
+ if (per_cu->cu == NULL)
+ return; /* Dummy CU. */
dwarf2_find_base_address (per_cu->cu->dies, per_cu->cu);
}
that may badly handle TUs, load all the TUs in that DWO as well.
http://sourceware.org/bugzilla/show_bug.cgi?id=15021 */
if (!per_cu->is_debug_types
+ && per_cu->cu != NULL
&& per_cu->cu->dwo_unit != NULL
&& dwarf2_per_objfile->index_table != NULL
&& dwarf2_per_objfile->index_table->version <= 7
if (current_language->la_language == language_cplus
|| current_language->la_language == language_java
- || current_language->la_language == language_fortran)
+ || current_language->la_language == language_fortran
+ || current_language->la_language == language_d)
{
/* NAME is already canonical. Drop any qualifiers as .gdb_index does
not contain any. */
while ((per_cu = dw2_symtab_iter_next (&iter)) != NULL)
{
- struct symbol *sym = NULL;
+ struct symbol *sym, *with_opaque = NULL;
struct compunit_symtab *stab = dw2_instantiate_symtab (per_cu);
const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (stab);
struct block *block = BLOCKVECTOR_BLOCK (bv, block_index);
+ sym = block_find_symbol (block, name, domain,
+ block_find_non_opaque_type_preferred,
+ &with_opaque);
+
/* Some caution must be observed with overloaded functions
and methods, since the index will not contain any overload
information (but NAME might contain it). */
- sym = block_lookup_symbol (block, name, domain);
- if (sym && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
- {
- if (!TYPE_IS_OPAQUE (SYMBOL_TYPE (sym)))
- return stab;
-
- stab_best = stab;
- }
+ if (sym != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (sym), name) == 0)
+ return stab;
+ if (with_opaque != NULL
+ && strcmp_iw (SYMBOL_SEARCH_NAME (with_opaque), name) == 0)
+ stab_best = stab;
/* Keep looking through other CUs. */
}
subpst->dirname = pst->dirname;
}
- subpst->section_offsets = pst->section_offsets;
subpst->textlow = 0;
subpst->texthigh = 0;
struct objfile *objfile = per_cu->objfile;
struct partial_symtab *pst;
- pst = start_psymtab_common (objfile, objfile->section_offsets,
- name, 0,
+ pst = start_psymtab_common (objfile, name, 0,
objfile->global_psymbols.next,
objfile->static_psymbols.next);
pst->textlow = gdbarch_adjust_dwarf2_addr (gdbarch, best_lowpc + baseaddr);
pst->texthigh = gdbarch_adjust_dwarf2_addr (gdbarch, best_highpc + baseaddr);
- pst->n_global_syms = objfile->global_psymbols.next -
- (objfile->global_psymbols.list + pst->globals_offset);
- pst->n_static_syms = objfile->static_psymbols.next -
- (objfile->static_psymbols.list + pst->statics_offset);
- sort_pst_symbols (objfile, pst);
+ end_psymtab_common (objfile, pst);
if (!VEC_empty (dwarf2_per_cu_ptr, cu->per_cu->imported_symtabs))
{
highpc = (CORE_ADDR) 0;
scan_partial_symbols (first_die, &lowpc, &highpc, 0, cu);
- pst->n_global_syms = objfile->global_psymbols.next -
- (objfile->global_psymbols.list + pst->globals_offset);
- pst->n_static_syms = objfile->static_psymbols.next -
- (objfile->static_psymbols.list + pst->statics_offset);
- sort_pst_symbols (objfile, pst);
+ end_psymtab_common (objfile, pst);
}
/* Struct used to sort TUs by their abbreviation table offset. */
built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->global_psymbols,
- 0, addr, cu->language, objfile);
+ addr, cu->language, objfile);
}
else
{
built_actual_name != NULL,
VAR_DOMAIN, LOC_BLOCK,
&objfile->static_psymbols,
- 0, addr, cu->language, objfile);
+ addr, cu->language, objfile);
}
break;
case DW_TAG_constant:
list = &objfile->static_psymbols;
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL, VAR_DOMAIN, LOC_STATIC,
- list, 0, 0, cu->language, objfile);
+ list, 0, cu->language, objfile);
}
break;
case DW_TAG_variable:
built_actual_name != NULL,
VAR_DOMAIN, LOC_STATIC,
&objfile->global_psymbols,
- 0, addr + baseaddr,
+ addr + baseaddr,
cu->language, objfile);
}
else
built_actual_name != NULL,
VAR_DOMAIN, LOC_STATIC,
&objfile->static_psymbols,
- 0,
has_loc ? addr + baseaddr : (CORE_ADDR) 0,
cu->language, objfile);
}
built_actual_name != NULL,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
break;
case DW_TAG_imported_declaration:
case DW_TAG_namespace:
built_actual_name != NULL,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
break;
case DW_TAG_module:
add_psymbol_to_list (actual_name, strlen (actual_name),
built_actual_name != NULL,
MODULE_DOMAIN, LOC_TYPEDEF,
&objfile->global_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
break;
case DW_TAG_class_type:
case DW_TAG_interface_type:
|| cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
break;
case DW_TAG_enumerator:
|| cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
break;
default:
break;
may load a new CU, adding it to the end of the queue. */
for (item = dwarf2_queue; item != NULL; dwarf2_queue = item = next_item)
{
- if (dwarf2_per_objfile->using_index
- ? !item->per_cu->v.quick->compunit_symtab
- : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
+ if ((dwarf2_per_objfile->using_index
+ ? !item->per_cu->v.quick->compunit_symtab
+ : (item->per_cu->v.psymtab && !item->per_cu->v.psymtab->readin))
+ /* Skip dummy CUs. */
+ && item->per_cu->cu != NULL)
{
struct dwarf2_per_cu_data *per_cu = item->per_cu;
unsigned int debug_print_threshold;
len = VEC_length (compunit_symtab_ptr, result_symtabs);
cust->includes
= obstack_alloc (&dwarf2_per_objfile->objfile->objfile_obstack,
- (len + 1) * sizeof (struct symtab *));
+ (len + 1) * sizeof (struct compunit_symtab *));
for (ix = 0;
VEC_iterate (compunit_symtab_ptr, result_symtabs, ix,
compunit_symtab_iter);
/* These are the only languages we know how to qualify names in. */
if (name != NULL
&& (cu->language == language_cplus || cu->language == language_java
- || cu->language == language_fortran))
+ || cu->language == language_fortran || cu->language == language_d))
{
if (die_needs_namespace (die, cu))
{
return 0;
}
+/* Return the using directives repository (global or local?) to use in the
+ current context for LANGUAGE.
+
+ For Ada, imported declarations can materialize renamings, which *may* be
+ global. However it is impossible (for now?) in DWARF to distinguish
+ "external" imported declarations and "static" ones. As all imported
+ declarations seem to be static in all other languages, make them all CU-wide
+ global only in Ada. */
+
+static struct using_direct **
+using_directives (enum language language)
+{
+ if (language == language_ada && context_stack_depth == 0)
+ return &global_using_directives;
+ else
+ return &local_using_directives;
+}
+
/* Read the import statement specified by the given die and record it. */
static void
}
else if (strlen (imported_name_prefix) > 0)
canonical_name = obconcat (&objfile->objfile_obstack,
- imported_name_prefix, "::", imported_name,
- (char *) NULL);
+ imported_name_prefix,
+ (cu->language == language_d ? "." : "::"),
+ imported_name, (char *) NULL);
else
canonical_name = imported_name;
process_die (child_die, cu);
}
- cp_add_using_directive (import_prefix,
- canonical_name,
- import_alias,
- imported_declaration,
- excludes,
- 0,
- &objfile->objfile_obstack);
+ add_using_directive (using_directives (cu->language),
+ import_prefix,
+ canonical_name,
+ import_alias,
+ imported_declaration,
+ excludes,
+ 0,
+ &objfile->objfile_obstack);
do_cleanups (cleanups);
}
lowpc, highpc);
/* For C++, set the block's scope. */
- if ((cu->language == language_cplus || cu->language == language_fortran)
+ if ((cu->language == language_cplus
+ || cu->language == language_fortran
+ || cu->language == language_d)
&& cu->processing_has_namespace_info)
block_set_scope (block, determine_prefix (die, cu),
&objfile->objfile_obstack);
when we finish processing a function scope, we may need to go
back to building a containing block's symbol lists. */
local_symbols = newobj->locals;
- using_directives = newobj->using_directives;
+ local_using_directives = newobj->local_using_directives;
/* If we've finished processing a top-level function, subsequent
symbols go in the file symbol list. */
inherit_abstract_dies (die, cu);
newobj = pop_context ();
- if (local_symbols != NULL || using_directives != NULL)
+ if (local_symbols != NULL || local_using_directives != NULL)
{
struct block *block
= finish_block (0, &local_symbols, newobj->old_blocks,
dwarf2_record_block_ranges (die, block, baseaddr, cu);
}
local_symbols = newobj->locals;
- using_directives = newobj->using_directives;
+ local_using_directives = newobj->local_using_directives;
}
/* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab. */
/* Get accessibility. */
attr = dwarf2_attr (die, DW_AT_accessibility, cu);
if (attr)
- accessibility = DW_UNSND (attr);
+ accessibility = (enum dwarf_access_attribute) DW_UNSND (attr);
else
accessibility = dwarf2_default_access_attribute (die, cu);
switch (accessibility)
if (name != NULL)
{
if (cu->language == language_cplus
- || cu->language == language_java)
+ || cu->language == language_java
+ || cu->language == language_d)
{
const char *full_name = dwarf2_full_name (name, die, cu);
attr = dwarf2_attr (die, DW_AT_ordering, cu);
- if (attr) return DW_SND (attr);
+ if (attr)
+ return (enum dwarf_array_dim_ordering) DW_SND (attr);
/* GNU F77 is a special case, as at 08/2004 array type info is the
opposite order to the dwarf2 specification, but data is still
return set_die_type (die, type, cu);
}
-/* Read a C++ namespace. */
+/* Read a namespace scope. */
static void
read_namespace (struct die_info *die, struct dwarf2_cu *cu)
{
const char *previous_prefix = determine_prefix (die, cu);
- cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL,
- NULL, NULL, 0, &objfile->objfile_obstack);
+ add_using_directive (using_directives (cu->language),
+ previous_prefix, TYPE_NAME (type), NULL,
+ NULL, NULL, 0, &objfile->objfile_obstack);
}
}
/* read in abbrev header */
cur_abbrev->number = abbrev_number;
- cur_abbrev->tag = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
+ cur_abbrev->tag
+ = (enum dwarf_tag) read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
cur_abbrev->has_children = read_1_byte (abfd, abbrev_ptr);
abbrev_ptr += 1;
* sizeof (struct attr_abbrev)));
}
- cur_attrs[cur_abbrev->num_attrs].name = abbrev_name;
- cur_attrs[cur_abbrev->num_attrs++].form = abbrev_form;
+ cur_attrs[cur_abbrev->num_attrs].name
+ = (enum dwarf_attribute) abbrev_name;
+ cur_attrs[cur_abbrev->num_attrs++].form
+ = (enum dwarf_form) abbrev_form;
abbrev_name = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
abbrev_ptr += bytes_read;
abbrev_form = read_unsigned_leb128 (abfd, abbrev_ptr, &bytes_read);
add_psymbol_to_list (part_die->name, strlen (part_die->name), 0,
VAR_DOMAIN, LOC_TYPEDEF,
&objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
continue;
}
|| cu->language == language_java)
? &objfile->global_psymbols
: &objfile->static_psymbols,
- 0, (CORE_ADDR) 0, cu->language, objfile);
+ 0, cu->language, objfile);
info_ptr = locate_pdi_sibling (reader, part_die, info_ptr);
continue;
unsigned int bytes_read;
struct dwarf_block *blk;
- attr->form = form;
+ attr->form = (enum dwarf_form) form;
switch (form)
{
case DW_FORM_ref_addr:
static void
add_include_dir (struct line_header *lh, const char *include_dir)
{
+ if (dwarf_line_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "Adding dir %u: %s\n",
+ lh->num_include_dirs + 1, include_dir);
+
/* Grow the array if necessary. */
if (lh->include_dirs_size == 0)
{
{
struct file_entry *fe;
+ if (dwarf_line_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "Adding file %u: %s\n",
+ lh->num_file_names + 1, name);
+
/* Grow the array if necessary. */
if (lh->file_names_size == 0)
{
return include_name;
}
+/* State machine to track the state of the line number program. */
+
+typedef struct
+{
+ /* These are part of the standard DWARF line number state machine. */
+
+ unsigned char op_index;
+ unsigned int file;
+ unsigned int line;
+ CORE_ADDR address;
+ int is_stmt;
+ unsigned int discriminator;
+
+ /* Additional bits of state we need to track. */
+
+ /* The last file that we called dwarf2_start_subfile for.
+ This is only used for TLLs. */
+ unsigned int last_file;
+ /* The last file a line number was recorded for. */
+ struct subfile *last_subfile;
+
+ /* The function to call to record a line. */
+ record_line_ftype *record_line;
+
+ /* 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;
+ int line_has_non_zero_discriminator;
+} lnp_state_machine;
+
+/* There's a lot of static state to pass to dwarf_record_line.
+ This keeps it all together. */
+
+typedef struct
+{
+ /* The gdbarch. */
+ struct gdbarch *gdbarch;
+
+ /* The line number header. */
+ struct line_header *line_header;
+
+ /* Non-zero if we're recording lines.
+ Otherwise we're building partial symtabs and are just interested in
+ finding include files mentioned by the line number program. */
+ int record_lines_p;
+} lnp_reader_state;
+
/* Ignore this record_line request. */
static void
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)
+dwarf_record_line_1 (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);
+ if (dwarf_line_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Recording line %u, file %s, address %s\n",
+ line, lbasename (subfile->name),
+ paddress (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.
+ The arguments are the same as for dwarf_record_line_1.
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);
+ if (subfile == NULL)
+ return;
+
+ if (dwarf_line_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Finishing current line, file %s, address %s\n",
+ lbasename (subfile->name),
+ paddress (gdbarch, address));
+ }
+
+ dwarf_record_line_1 (gdbarch, subfile, 0, address, p_record_line);
+}
+
+/* Record the line in STATE.
+ END_SEQUENCE is non-zero if we're processing the end of a sequence. */
+
+static void
+dwarf_record_line (lnp_reader_state *reader, lnp_state_machine *state,
+ int end_sequence)
+{
+ const struct line_header *lh = reader->line_header;
+ unsigned int file, line, discriminator;
+ int is_stmt;
+
+ file = state->file;
+ line = state->line;
+ is_stmt = state->is_stmt;
+ discriminator = state->discriminator;
+
+ if (dwarf_line_debug)
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "Processing actual line %u: file %u,"
+ " address %s, is_stmt %u, discrim %u\n",
+ line, file,
+ paddress (reader->gdbarch, state->address),
+ is_stmt, discriminator);
+ }
+
+ if (file == 0 || file - 1 >= lh->num_file_names)
+ dwarf2_debug_line_missing_file_complaint ();
+ /* For now we ignore lines not starting on an instruction boundary.
+ But not when processing end_sequence for compatibility with the
+ previous version of the code. */
+ else if (state->op_index == 0 || end_sequence)
+ {
+ lh->file_names[file - 1].included_p = 1;
+ if (reader->record_lines_p && is_stmt)
+ {
+ if (state->last_subfile != current_subfile || end_sequence)
+ {
+ dwarf_finish_line (reader->gdbarch, state->last_subfile,
+ state->address, state->record_line);
+ }
+
+ if (!end_sequence)
+ {
+ if (dwarf_record_line_p (line, state->last_line,
+ state->line_has_non_zero_discriminator,
+ state->last_subfile))
+ {
+ dwarf_record_line_1 (reader->gdbarch, current_subfile,
+ line, state->address,
+ state->record_line);
+ }
+ state->last_subfile = current_subfile;
+ state->last_line = line;
+ }
+ }
+ }
+}
+
+/* Initialize STATE for the start of a line number program. */
+
+static void
+init_lnp_state_machine (lnp_state_machine *state,
+ const lnp_reader_state *reader)
+{
+ memset (state, 0, sizeof (*state));
+
+ /* Just starting, there is no "last file". */
+ state->last_file = 0;
+ state->last_subfile = NULL;
+
+ state->record_line = record_line;
+
+ state->last_line = 0;
+ state->line_has_non_zero_discriminator = 0;
+
+ /* Initialize these according to the DWARF spec. */
+ state->op_index = 0;
+ state->file = 1;
+ state->line = 1;
+ /* Call `gdbarch_adjust_dwarf2_line' on the initial 0 address as if there
+ was a line entry for it so that the backend has a chance to adjust it
+ and also record it in case it needs it. This is currently used by MIPS
+ code, cf. `mips_adjust_dwarf2_line'. */
+ state->address = gdbarch_adjust_dwarf2_line (reader->gdbarch, 0, 0);
+ state->is_stmt = reader->line_header->default_is_stmt;
+ state->discriminator = 0;
+}
+
+/* Check address and if invalid nop-out the rest of the lines in this
+ sequence. */
+
+static void
+check_line_address (struct dwarf2_cu *cu, lnp_state_machine *state,
+ const gdb_byte *line_ptr,
+ CORE_ADDR lowpc, CORE_ADDR address)
+{
+ /* 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 */
+
+ struct objfile *objfile = cu->objfile;
+ long line_offset = line_ptr - get_debug_line_section (cu)->buffer;
+
+ complaint (&symfile_complaints,
+ _(".debug_line address at offset 0x%lx is 0 [in module %s]"),
+ line_offset, objfile_name (objfile));
+ state->record_line = noop_record_line;
+ /* Note: sm.record_line is left as noop_record_line
+ until we see DW_LNE_end_sequence. */
+ }
}
/* Subroutine of dwarf_decode_lines to simplify it.
- Process the line number information in LH. */
+ Process the line number information in LH.
+ If DECODE_FOR_PST_P is non-zero, all we do is process the line number
+ program in order to set included_p for every referenced header. */
static void
dwarf_decode_lines_1 (struct line_header *lh, struct dwarf2_cu *cu,
struct objfile *objfile = cu->objfile;
bfd *abfd = objfile->obfd;
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- struct subfile *last_subfile = NULL;
- void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc)
- = record_line;
+ /* Non-zero if we're recording line info (as opposed to building partial
+ symtabs). */
+ int record_lines_p = !decode_for_pst_p;
+ /* A collection of things we need to pass to dwarf_record_line. */
+ lnp_reader_state reader_state;
baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
line_ptr = lh->statement_program_start;
line_end = lh->statement_program_end;
+ reader_state.gdbarch = gdbarch;
+ reader_state.line_header = lh;
+ reader_state.record_lines_p = record_lines_p;
+
/* Read the statement sequences until there's nothing left. */
while (line_ptr < line_end)
{
- /* State machine registers. Call `gdbarch_adjust_dwarf2_line'
- on the initial 0 address as if there was a line entry for it
- so that the backend has a chance to adjust it and also record
- it in case it needs it. This is currently used by MIPS code,
- cf. `mips_adjust_dwarf2_line'. */
- CORE_ADDR address = gdbarch_adjust_dwarf2_line (gdbarch, 0, 0);
- unsigned int file = 1;
- unsigned int line = 1;
- int is_stmt = lh->default_is_stmt;
+ /* The DWARF line number program state machine. */
+ lnp_state_machine state_machine;
int end_sequence = 0;
- 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)
+
+ /* Reset the state machine at the start of each sequence. */
+ init_lnp_state_machine (&state_machine, &reader_state);
+
+ if (record_lines_p && lh->num_file_names >= state_machine.file)
{
/* Start a subfile for the current file of the state machine. */
/* lh->include_dirs and lh->file_names are 0-based, but the
directory and file name numbers in the statement program
are 1-based. */
- struct file_entry *fe = &lh->file_names[file - 1];
+ struct file_entry *fe = &lh->file_names[state_machine.file - 1];
const char *dir = NULL;
if (fe->dir_index && lh->include_dirs != NULL)
}
/* Decode the table. */
- while (!end_sequence)
+ while (line_ptr < line_end && !end_sequence)
{
op_code = read_1_byte (abfd, line_ptr);
line_ptr += 1;
- if (line_ptr > line_end)
- {
- dwarf2_debug_line_missing_end_sequence_complaint ();
- break;
- }
if (op_code >= lh->opcode_base)
{
int line_delta;
adj_opcode = op_code - lh->opcode_base;
- addr_adj = (((op_index + (adj_opcode / lh->line_range))
+ addr_adj = (((state_machine.op_index
+ + (adj_opcode / lh->line_range))
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
- address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
- op_index = ((op_index + (adj_opcode / lh->line_range))
- % lh->maximum_ops_per_instruction);
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = ((state_machine.op_index
+ + (adj_opcode / lh->line_range))
+ % lh->maximum_ops_per_instruction);
line_delta = lh->line_base + (adj_opcode % lh->line_range);
- line += line_delta;
+ state_machine.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
- instruction boundary. */
- else if (op_index == 0)
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p && is_stmt)
- {
- if (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);
- }
- last_subfile = current_subfile;
- last_line = line;
- }
- }
- discriminator = 0;
+ state_machine.line_has_non_zero_discriminator
+ = state_machine.discriminator != 0;
+
+ dwarf_record_line (&reader_state, &state_machine, 0);
+ state_machine.discriminator = 0;
}
else switch (op_code)
{
switch (extended_op)
{
case DW_LNE_end_sequence:
- p_record_line = record_line;
+ state_machine.record_line = record_line;
end_sequence = 1;
break;
case DW_LNE_set_address:
- address = read_address (abfd, line_ptr, cu, &bytes_read);
-
- /* 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 */
-
- long line_offset
- = line_ptr - get_debug_line_section (cu)->buffer;
-
- complaint (&symfile_complaints,
- _(".debug_line address at offset 0x%lx is 0 "
- "[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. */
- }
+ {
+ CORE_ADDR address
+ = read_address (abfd, line_ptr, cu, &bytes_read);
- op_index = 0;
- line_ptr += bytes_read;
- address += baseaddr;
- address = gdbarch_adjust_dwarf2_line (gdbarch, address, 0);
+ line_ptr += bytes_read;
+ check_line_address (cu, &state_machine, line_ptr,
+ lowpc, address);
+ state_machine.op_index = 0;
+ address += baseaddr;
+ state_machine.address
+ = gdbarch_adjust_dwarf2_line (gdbarch, address, 0);
+ }
break;
case DW_LNE_define_file:
{
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;
+ state_machine.discriminator
+ = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
+ state_machine.line_has_non_zero_discriminator
+ |= state_machine.discriminator != 0;
line_ptr += bytes_read;
break;
default:
}
break;
case DW_LNS_copy:
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p && is_stmt)
- {
- if (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);
- }
- last_subfile = current_subfile;
- last_line = line;
- }
- }
- discriminator = 0;
+ dwarf_record_line (&reader_state, &state_machine, 0);
+ state_machine.discriminator = 0;
break;
case DW_LNS_advance_pc:
{
= read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
CORE_ADDR addr_adj;
- addr_adj = (((op_index + adjust)
+ addr_adj = (((state_machine.op_index + adjust)
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
- address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
- op_index = ((op_index + adjust)
- % lh->maximum_ops_per_instruction);
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = ((state_machine.op_index + adjust)
+ % lh->maximum_ops_per_instruction);
line_ptr += bytes_read;
}
break;
int line_delta
= read_signed_leb128 (abfd, line_ptr, &bytes_read);
- line += line_delta;
+ state_machine.line += line_delta;
if (line_delta != 0)
- line_has_non_zero_discriminator = discriminator != 0;
+ state_machine.line_has_non_zero_discriminator
+ = state_machine.discriminator != 0;
line_ptr += bytes_read;
}
break;
case DW_LNS_set_file:
- {
- /* The arrays lh->include_dirs and lh->file_names are
- 0-based, but the directory and file name numbers in
- the statement program are 1-based. */
- struct file_entry *fe;
- const char *dir = NULL;
-
- file = read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
- line_ptr += bytes_read;
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- fe = &lh->file_names[file - 1];
- if (fe->dir_index && lh->include_dirs != NULL)
- dir = lh->include_dirs[fe->dir_index - 1];
- if (!decode_for_pst_p)
- {
- last_subfile = current_subfile;
- line_has_non_zero_discriminator = discriminator != 0;
- dwarf2_start_subfile (fe->name, dir);
- }
- }
- }
+ {
+ /* The arrays lh->include_dirs and lh->file_names are
+ 0-based, but the directory and file name numbers in
+ the statement program are 1-based. */
+ struct file_entry *fe;
+ const char *dir = NULL;
+
+ state_machine.file = read_unsigned_leb128 (abfd, line_ptr,
+ &bytes_read);
+ line_ptr += bytes_read;
+ if (state_machine.file == 0
+ || state_machine.file - 1 >= lh->num_file_names)
+ dwarf2_debug_line_missing_file_complaint ();
+ else
+ {
+ fe = &lh->file_names[state_machine.file - 1];
+ if (fe->dir_index && lh->include_dirs != NULL)
+ dir = lh->include_dirs[fe->dir_index - 1];
+ if (record_lines_p)
+ {
+ state_machine.last_subfile = current_subfile;
+ state_machine.line_has_non_zero_discriminator
+ = state_machine.discriminator != 0;
+ dwarf2_start_subfile (fe->name, dir);
+ }
+ }
+ }
break;
case DW_LNS_set_column:
(void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
line_ptr += bytes_read;
break;
case DW_LNS_negate_stmt:
- is_stmt = (!is_stmt);
+ state_machine.is_stmt = (!state_machine.is_stmt);
break;
case DW_LNS_set_basic_block:
break;
CORE_ADDR adjust = (255 - lh->opcode_base) / lh->line_range;
CORE_ADDR addr_adj;
- addr_adj = (((op_index + adjust)
+ addr_adj = (((state_machine.op_index + adjust)
/ lh->maximum_ops_per_instruction)
* lh->minimum_instruction_length);
- address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
- op_index = ((op_index + adjust)
- % lh->maximum_ops_per_instruction);
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = ((state_machine.op_index + adjust)
+ % lh->maximum_ops_per_instruction);
}
break;
case DW_LNS_fixed_advance_pc:
CORE_ADDR addr_adj;
addr_adj = read_2_bytes (abfd, line_ptr);
- address += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
- op_index = 0;
+ state_machine.address
+ += gdbarch_adjust_dwarf2_line (gdbarch, addr_adj, 1);
+ state_machine.op_index = 0;
line_ptr += 2;
}
break;
}
}
}
- if (lh->num_file_names < file || file == 0)
- dwarf2_debug_line_missing_file_complaint ();
- else
- {
- lh->file_names[file - 1].included_p = 1;
- if (!decode_for_pst_p)
- {
- dwarf_finish_line (gdbarch, current_subfile, address,
- p_record_line);
- }
- }
+
+ if (!end_sequence)
+ dwarf2_debug_line_missing_end_sequence_complaint ();
+
+ /* We got a DW_LNE_end_sequence (or we ran off the end of the buffer,
+ in which case we still finish recording the last line). */
+ dwarf_record_line (&reader_state, &state_machine, 1);
}
}
class. */
if (cu->language == language_cplus
|| cu->language == language_java
- || cu->language == language_ada)
+ || cu->language == language_ada
+ || cu->language == language_d)
{
/* The symbol's name is already allocated along
with this objfile, so we don't need to
char *retval;
if (cu->language != language_cplus && cu->language != language_java
- && cu->language != language_fortran)
+ && cu->language != language_fortran && cu->language != language_d)
return "";
retval = anonymous_struct_prefix (die, cu);
sep = "";
else if (cu->language == language_java)
sep = ".";
+ else if (cu->language == language_d)
+ {
+ /* For D, the 'main' function could be defined in any module, but it
+ should never be prefixed. */
+ if (strcmp (suffix, "D main") == 0)
+ {
+ prefix = "";
+ sep = "";
+ }
+ else
+ sep = ".";
+ }
else if (cu->language == language_fortran && physname)
{
/* This is gfortran specific mangling. Normally DW_AT_linkage_name or
if (per_cu->cu == NULL)
load_cu (per_cu);
cu = per_cu->cu;
+ if (cu == NULL)
+ {
+ /* We shouldn't get here for a dummy CU, but don't crash on the user.
+ Instead just throw an error, not much else we can do. */
+ error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
+ offset.sect_off, objfile_name (per_cu->objfile));
+ }
die = follow_die_offset (offset, per_cu->is_dwz, &cu);
if (!die)
if (per_cu->cu == NULL)
load_cu (per_cu);
cu = per_cu->cu;
+ if (cu == NULL)
+ {
+ /* We shouldn't get here for a dummy CU, but don't crash on the user.
+ Instead just throw an error, not much else we can do. */
+ error (_("Dwarf Error: Dummy CU at 0x%x referenced in module %s"),
+ offset.sect_off, objfile_name (per_cu->objfile));
+ }
die = follow_die_offset (offset, per_cu->is_dwz, &cu);
if (!die)
for (i = 0; i < arg; ++i)
{
- mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end, defn[i], offset_size,
+ mac_ptr = skip_form_bytes (abfd, mac_ptr, mac_end,
+ (enum dwarf_form) defn[i], offset_size,
section);
if (mac_ptr == NULL)
{
break;
}
- macinfo_type = read_1_byte (abfd, mac_ptr);
+ macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
mac_ptr++;
/* Note that we rely on the fact that the corresponding GNU and
/* We don't increment mac_ptr here, so this is just
a look-ahead. */
- next_type = read_1_byte (abfd, mac_ptr);
+ next_type
+ = (enum dwarf_macro_record_type) read_1_byte (abfd,
+ mac_ptr);
if (next_type != 0)
complaint (&symfile_complaints,
_("no terminating 0-type entry for "
break;
}
- macinfo_type = read_1_byte (abfd, mac_ptr);
+ macinfo_type = (enum dwarf_macro_record_type) read_1_byte (abfd, mac_ptr);
mac_ptr++;
/* Note that we rely on the fact that the corresponding GNU and
NULL,
&setdebuglist, &showdebuglist);
+ add_setshow_zuinteger_cmd ("dwarf-line", no_class, &dwarf_line_debug, _("\
+Set debugging of the dwarf line reader."), _("\
+Show debugging of the dwarf line reader."), _("\
+When enabled (non-zero), line number entries are dumped as they are read in.\n\
+A value of 1 (one) provides basic information.\n\
+A value greater than 1 provides more verbose information."),
+ NULL,
+ NULL,
+ &setdebuglist, &showdebuglist);
+
add_setshow_boolean_cmd ("check-physname", no_class, &check_physname, _("\
Set cross-checking of \"physname\" code against demangler."), _("\
Show cross-checking of \"physname\" code against demangler."), _("\