static struct file_entry *files;
static unsigned int files_in_use;
static unsigned int files_allocated;
-static unsigned int num_of_auto_assigned;
/* Table of directories used by .debug_line. */
static char ** dirs = NULL;
{
1, 1, 0, 0,
DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0,
- 0, NULL
+ 0, { NULL }
};
/* This symbol is used to recognize view number forced resets in loc
/* First, compute !(E->label > P->label), to tell whether or not
we're to reset the view number. If we can't resolve it to a
constant, keep it symbolic. */
- if (!p || (e->loc.view == force_reset_view && force_reset_view))
+ if (!p || (e->loc.u.view == force_reset_view && force_reset_view))
{
viewx.X_op = O_constant;
viewx.X_add_number = 0;
}
}
- if (S_IS_DEFINED (e->loc.view) && symbol_constant_p (e->loc.view))
+ if (S_IS_DEFINED (e->loc.u.view) && symbol_constant_p (e->loc.u.view))
{
- expressionS *value = symbol_get_value_expression (e->loc.view);
+ expressionS *value = symbol_get_value_expression (e->loc.u.view);
/* We can't compare the view numbers at this point, because in
VIEWX we've only determined whether we're to reset it so
far. */
{
expressionS incv;
- if (!p->loc.view)
+ if (!p->loc.u.view)
{
- p->loc.view = symbol_temp_make ();
- gas_assert (!S_IS_DEFINED (p->loc.view));
+ p->loc.u.view = symbol_temp_make ();
+ gas_assert (!S_IS_DEFINED (p->loc.u.view));
}
memset (&incv, 0, sizeof (incv));
incv.X_unsigned = 1;
incv.X_op = O_symbol;
- incv.X_add_symbol = p->loc.view;
+ incv.X_add_symbol = p->loc.u.view;
incv.X_add_number = 1;
if (viewx.X_op == O_constant)
}
}
- if (!S_IS_DEFINED (e->loc.view))
+ if (!S_IS_DEFINED (e->loc.u.view))
{
- symbol_set_value_expression (e->loc.view, &viewx);
- S_SET_SEGMENT (e->loc.view, expr_section);
- symbol_set_frag (e->loc.view, &zero_address_frag);
+ symbol_set_value_expression (e->loc.u.view, &viewx);
+ S_SET_SEGMENT (e->loc.u.view, expr_section);
+ symbol_set_frag (e->loc.u.view, &zero_address_frag);
}
/* Define and attempt to simplify any earlier views needed to
compute E's. */
- if (h && p && p->loc.view && !S_IS_DEFINED (p->loc.view))
+ if (h && p && p->loc.u.view && !S_IS_DEFINED (p->loc.u.view))
{
struct line_entry *h2;
/* Reverse the list to avoid quadratic behavior going backwards
break;
set_or_check_view (r, r->next, NULL);
}
- while (r->next && r->next->loc.view && !S_IS_DEFINED (r->next->loc.view)
+ while (r->next
+ && r->next->loc.u.view
+ && !S_IS_DEFINED (r->next->loc.u.view)
&& (r = r->next));
/* Unreverse the list, so that we can go forward again. */
view of the previous subsegment. */
if (r == h)
continue;
- gas_assert (S_IS_DEFINED (r->loc.view));
- resolve_expression (symbol_get_value_expression (r->loc.view));
+ gas_assert (S_IS_DEFINED (r->loc.u.view));
+ resolve_expression (symbol_get_value_expression (r->loc.u.view));
}
while (r != p && (r = r->next));
/* Now that we've defined and computed all earlier views that might
be needed to compute E's, attempt to simplify it. */
- resolve_expression (symbol_get_value_expression (e->loc.view));
+ resolve_expression (symbol_get_value_expression (e->loc.u.view));
}
}
/* Subseg heads are chained to previous subsegs in
dwarf2_finish. */
- if (loc->view && lss->head)
- set_or_check_view (e,
- (struct line_entry *)lss->ptail,
- lss->head);
+ if (loc->filenum != -1u && loc->u.view && lss->head)
+ set_or_check_view (e, (struct line_entry *) lss->ptail, lss->head);
*lss->ptail = e;
lss->ptail = &e->next;
void
dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
{
- static unsigned int line = -1;
- static unsigned int filenum = -1;
-
symbolS *sym;
/* Early out for as-yet incomplete location information. */
symbols apply to assembler code. It is necessary to emit
duplicate line symbols when a compiler asks for them, because GDB
uses them to determine the end of the prologue. */
- if (debug_type == DEBUG_DWARF2
- && line == loc->line && filenum == loc->filenum)
- return;
+ if (debug_type == DEBUG_DWARF2)
+ {
+ static unsigned int line = -1;
+ static const char *filename = NULL;
- line = loc->line;
- filenum = loc->filenum;
+ if (line == loc->line)
+ {
+ if (filename == loc->u.filename)
+ return;
+ if (filename_cmp (filename, loc->u.filename) == 0)
+ {
+ filename = loc->u.filename;
+ return;
+ }
+ }
+
+ line = loc->line;
+ filename = loc->u.filename;
+ }
if (linkrelax)
{
- char name[120];
+ static int label_num = 0;
+ char name[32];
/* Use a non-fake name for the line number location,
so that it can be referred to by relocations. */
- sprintf (name, ".Loc.%u.%u", line, filenum);
+ sprintf (name, ".Loc.%u", label_num);
+ label_num++;
sym = symbol_new (name, now_seg, frag_now, ofs);
}
else
static unsigned int
get_directory_table_entry (const char *dirname,
+ const char *file0_dirname,
size_t dirlen,
bool can_use_zero)
{
if (can_use_zero)
{
if (dirs == NULL || dirs[0] == NULL)
- d = 0;
+ {
+ const char * pwd = file0_dirname ? file0_dirname : getpwd ();
+
+ if (dwarf_level >= 5 && filename_cmp (dirname, pwd) != 0)
+ {
+ /* In DWARF-5 the 0 entry in the directory table is
+ expected to be the same as the DW_AT_comp_dir (which
+ is set to the current build directory). Since we are
+ about to create a directory entry that is not the
+ same, allocate the current directory first. */
+ (void) get_directory_table_entry (pwd, file0_dirname,
+ strlen (pwd), true);
+ d = 1;
+ }
+ else
+ d = 0;
+ }
}
else if (d == 0)
d = 1;
if (d >= dirs_allocated)
{
unsigned int old = dirs_allocated;
-
- dirs_allocated = d + 32;
+#define DIR_TABLE_INCREMENT 32
+ dirs_allocated = d + DIR_TABLE_INCREMENT;
dirs = XRESIZEVEC (char *, dirs, dirs_allocated);
memset (dirs + old, 0, (dirs_allocated - old) * sizeof (char *));
}
}
else
{
- if (filename_ncmp (pathname, dirname, last_used_dir_len) == 0
- && IS_DIR_SEPARATOR (pathname [last_used_dir_len])
- && filename_cmp (pathname + last_used_dir_len + 1,
+ if (filename_ncmp (pathname, dirname, last_used_dir_len - 1) == 0
+ && IS_DIR_SEPARATOR (pathname [last_used_dir_len - 1])
+ && filename_cmp (pathname + last_used_dir_len,
files[last_used].filename) == 0)
return last_used;
}
file = get_basename (pathname);
dir_len = file - pathname;
- dir = get_directory_table_entry (pathname, dir_len, false);
+ dir = get_directory_table_entry (pathname, NULL, dir_len, false);
/* Do not use slot-0. That is specifically reserved for use by
the '.file 0 "name"' directive. */
if (!assign_file_to_slot (i, file, dir))
return -1;
- num_of_auto_assigned++;
-
last_used = i;
last_used_dir_len = dir_len;
return i;
}
+/* Run through the list of line entries starting at E, allocating
+ file entries for gas generated debug. */
+
+static void
+do_allocate_filenum (struct line_entry *e)
+{
+ do
+ {
+ if (e->loc.filenum == -1u)
+ {
+ e->loc.filenum = allocate_filenum (e->loc.u.filename);
+ e->loc.u.view = NULL;
+ }
+ e = e->next;
+ }
+ while (e);
+}
+
+/* Remove any generated line entries. These don't live comfortably
+ with compiler generated line info. */
+
+static void
+purge_generated_debug (void)
+{
+ struct line_seg *s;
+
+ for (s = all_segs; s; s = s->next)
+ {
+ struct line_subseg *lss;
+
+ for (lss = s->head; lss; lss = lss->next)
+ {
+ struct line_entry *e, *next;
+
+ for (e = lss->head; e; e = next)
+ {
+ know (e->loc.filenum == -1u);
+ next = e->next;
+ free (e);
+ }
+
+ lss->head = NULL;
+ lss->ptail = &lss->head;
+ lss->pmove_tail = &lss->head;
+ }
+ }
+}
+
/* Allocate slot NUM in the .debug_line file table to FILENAME.
If DIRNAME is not NULL or there is a directory component to FILENAME
then this will be stored in the directory table, if not already present.
const char *file;
size_t dirlen;
unsigned int i, d;
+ const char *file0_dirname;
/* Short circuit the common case of adding the same pathname
as last time. */
{
if (dirs == NULL)
{
- dirs_allocated = files[num].dir + 32;
+ dirs_allocated = files[num].dir + DIR_TABLE_INCREMENT;
dirs = XCNEWVEC (char *, dirs_allocated);
}
{
if (dirs == NULL)
{
- dirs_allocated = files[num].dir + 32;
+ dirs_allocated = files[num].dir + DIR_TABLE_INCREMENT;
dirs = XCNEWVEC (char *, dirs_allocated);
}
return false;
}
- if (dirname == NULL)
+ /* For file .0, the directory name is the current directory and the file
+ may be in another directory contained in the file name. */
+ if (num == 0)
{
- dirname = filename;
+ file0_dirname = dirname;
+
file = get_basename (filename);
- dirlen = file - filename;
+
+ if (dirname && file == filename)
+ dirlen = strlen (dirname);
+ else
+ {
+ dirname = filename;
+ dirlen = file - filename;
+ }
}
else
{
- dirlen = strlen (dirname);
- file = filename;
+ file0_dirname = NULL;
+
+ if (dirname == NULL)
+ {
+ dirname = filename;
+ file = get_basename (filename);
+ dirlen = file - filename;
+ }
+ else
+ {
+ dirlen = strlen (dirname);
+ file = filename;
+ }
}
-
- d = get_directory_table_entry (dirname, dirlen, num == 0);
+
+ d = get_directory_table_entry (dirname, file0_dirname, dirlen, num == 0);
i = num;
if (! assign_file_to_slot (i, file, d))
{
if (debug_type == DEBUG_DWARF2)
{
- const char *filename;
-
- memset (line, 0, sizeof (*line));
- filename = as_where (&line->line);
- line->filenum = allocate_filenum (filename);
- /* FIXME: We should check the return value from allocate_filenum. */
+ line->u.filename = as_where (&line->line);
+ line->filenum = -1u;
line->column = 0;
line->flags = DWARF2_FLAG_IS_STMT;
line->isa = current.isa;
line->discriminator = current.discriminator;
- line->view = NULL;
}
else
*line = current;
| DWARF2_FLAG_PROLOGUE_END
| DWARF2_FLAG_EPILOGUE_BEGIN);
current.discriminator = 0;
- current.view = NULL;
+ current.u.view = NULL;
}
/* Called for each (preferably code) label. If dwarf2_loc_mark_labels
char *filename;
const char * dirname = NULL;
int filename_len;
- unsigned int i;
/* Continue to accept a bare string and pass it off. */
SKIP_WHITESPACE ();
/* A .file directive implies compiler generated debug information is
being supplied. Turn off gas generated debug info. */
+ if (debug_type == DEBUG_DWARF2)
+ purge_generated_debug ();
debug_type = DEBUG_NONE;
if (num != (unsigned int) num
return NULL;
}
- if (num_of_auto_assigned)
- {
- /* Clear slots auto-assigned before the first .file <NUMBER>
- directive was seen. */
- if (files_in_use != (num_of_auto_assigned + 1))
- abort ();
- for (i = 1; i < files_in_use; i++)
- files[i].filename = NULL;
- files_in_use = 0;
- num_of_auto_assigned = 0;
- }
-
if (! allocate_filename_to_slot (dirname, filename, (unsigned int) num,
with_md5))
return NULL;
return;
}
+ /* debug_type will be turned off by dwarf2_directive_filename, and
+ if we don't have a dwarf style .file then files_in_use will be
+ zero and the above error will trigger. */
+ gas_assert (debug_type == DEBUG_NONE);
+
current.filenum = filenum;
current.line = line;
current.discriminator = 0;
S_SET_VALUE (sym, 0);
symbol_set_frag (sym, &zero_address_frag);
}
- current.view = sym;
+ current.u.view = sym;
}
else
{
demand_empty_rest_of_line ();
dwarf2_any_loc_directive_seen = dwarf2_loc_directive_seen = true;
- debug_type = DEBUG_NONE;
/* If we were given a view id, emit the row right away. */
- if (current.view)
+ if (current.u.view)
dwarf2_emit_insn (0);
}
frag_ofs = S_GET_VALUE (lab);
if (last_frag == NULL
- || (e->loc.view == force_reset_view && force_reset_view
+ || (e->loc.u.view == force_reset_view && force_reset_view
/* If we're going to reset the view, but we know we're
advancing the PC, we don't have to force with
set_address. We know we do when we're at the same
Otherwise use pwd as main file directory. */
if (dirs_in_use > 0 && dirs != NULL && dirs[0] != NULL)
dir = remap_debug_filename (dirs[0]);
- else if (dirs_in_use > 1 && dirs != NULL && dirs[1] != NULL)
+ else if (dirs_in_use > 1
+ && dirs != NULL
+ && dirs[1] != NULL
+ /* DWARF-5 directory tables expect dir[0] to be the same as
+ DW_AT_comp_dir, which is the same as pwd. */
+ && dwarf_level < 5)
dir = remap_debug_filename (dirs[1]);
else
dir = remap_debug_filename (getpwd ());
uses slot zero, but that is only set explicitly using a
.file 0 directive. If that isn't used, but file 1 is,
then use that as main file name. */
- if (DWARF2_LINE_VERSION >= 5 && i == 0 && files_in_use >= 1)
- files[0].filename = files[1].filename;
+ if (DWARF2_LINE_VERSION >= 5 && i == 0 && files_in_use >= 1 && files[0].filename == NULL)
+ files[0].filename = files[1].filename;
else
files[i].filename = "";
if (DWARF2_LINE_VERSION < 5 || i != 0)
for (s = all_segs; s; s = s->next)
/* Paranoia - this check should have already have
been handled in dwarf2_gen_line_info_1(). */
- if (SEG_NORMAL (s->seg))
+ if (s->head->head && SEG_NORMAL (s->seg))
process_entries (s->seg, s->head->head);
if (flag_dwarf_sections)
SEC_READONLY | SEC_DEBUGGING | SEC_OCTETS);
}
+ for (s = all_segs; s; s = s->next)
+ {
+ struct line_subseg *lss;
+
+ for (lss = s->head; lss; lss = lss->next)
+ if (lss->head)
+ do_allocate_filenum (lss->head);
+ }
+
/* For each subsection, chain the debug entries together. */
for (s = all_segs; s; s = s->next)
{
/* Reset the initial view of the first subsection of the
section. */
- if (lss->head && lss->head->loc.view)
+ if (lss->head && lss->head->loc.u.view)
set_or_check_view (lss->head, NULL, NULL);
while ((lss = lss->next) != NULL)
{
/* Link the first view of subsequent subsections to the
previous view. */
- if (lss->head && lss->head->loc.view)
+ if (lss->head && lss->head->loc.u.view)
set_or_check_view (lss->head,
!s->head ? NULL : (struct line_entry *)ptail,
s->head ? s->head->head : NULL);