aarch64: [SME] Add SME instructions
[binutils-gdb.git] / gas / dwarf2dbg.c
index 25ebc94a8d2b4c51279290770f188bf0ae60be19..256412f9c79197a91918ec99ba4b9fbb7658b647 100644 (file)
@@ -1,5 +1,5 @@
 /* dwarf2dbg.c - DWARF2 debug support
-   Copyright (C) 1999-2020 Free Software Foundation, Inc.
+   Copyright (C) 1999-2021 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
    This file is part of GAS, the GNU Assembler.
 
 #include "as.h"
 #include "safe-ctype.h"
-
-#ifdef HAVE_LIMITS_H
 #include <limits.h>
-#else
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#ifndef INT_MAX
-#define INT_MAX (int) (((unsigned) (-1)) >> 1)
-#endif
-#endif
-
 #include "dwarf2dbg.h"
 #include <filenames.h>
 
@@ -218,7 +207,6 @@ struct file_entry
 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;
@@ -228,23 +216,23 @@ static unsigned int  dirs_allocated = 0;
 /* TRUE when we've seen a .loc directive recently.  Used to avoid
    doing work when there's nothing to do.  Will be reset by
    dwarf2_consume_line_info.  */
-bfd_boolean dwarf2_loc_directive_seen;
+bool dwarf2_loc_directive_seen;
 
 /* TRUE when we've seen any .loc directive at any time during parsing.
    Indicates the user wants us to generate a .debug_line section.
    Used in dwarf2_finish as sanity check.  */
-static bfd_boolean dwarf2_any_loc_directive_seen;
+static bool dwarf2_any_loc_directive_seen;
 
 /* TRUE when we're supposed to set the basic block mark whenever a
    label is seen.  */
-bfd_boolean dwarf2_loc_mark_labels;
+bool dwarf2_loc_mark_labels;
 
 /* Current location as indicated by the most recent .loc directive.  */
 static struct dwarf2_line_info current =
 {
   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
@@ -279,7 +267,7 @@ generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
 /* Find or create (if CREATE_P) an entry for SEG+SUBSEG in ALL_SEGS.  */
 
 static struct line_subseg *
-get_line_subseg (segT seg, subsegT subseg, bfd_boolean create_p)
+get_line_subseg (segT seg, subsegT subseg, bool create_p)
 {
   struct line_seg *s = seg_info (seg)->dwarf2_line_seg;
   struct line_subseg **pss, *lss;
@@ -353,7 +341,7 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
   /* 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;
@@ -378,9 +366,9 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
        }
     }
 
-  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.  */
@@ -415,16 +403,16 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
     {
       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)
@@ -441,16 +429,16 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
        }
     }
 
-  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
@@ -470,7 +458,9 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
            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.  */
@@ -486,14 +476,14 @@ set_or_check_view (struct line_entry *e, struct line_entry *p,
             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));
     }
 }
 
@@ -504,14 +494,17 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
 {
   struct line_subseg *lss;
   struct line_entry *e;
-  flagword need_flags = SEC_ALLOC | SEC_LOAD | SEC_CODE;
+  flagword need_flags = SEC_LOAD | SEC_CODE;
 
-  /* PR 26850: Do not record LOCs in non-executable, non-allocated,
-     or non-loaded sections.  */
+  /* PR 26850: Do not record LOCs in non-executable or non-loaded
+     sections.  SEC_ALLOC isn't tested for non-ELF because obj-coff.c
+     obj_coff_section is careless in setting SEC_ALLOC.  */
+  if (IS_ELF)
+    need_flags |= SEC_ALLOC;
   if ((now_seg->flags & need_flags) != need_flags)
     {
-      if (! SEG_NORMAL (now_seg))
-       /* FIXME: Add code to suppress multiple warnings ?  */
+      /* FIXME: Add code to suppress multiple warnings ?  */
+      if (debug_type != DEBUG_DWARF2)
        as_warn ("dwarf line number information for %s ignored",
                 segment_name (now_seg));
       return;
@@ -522,14 +515,12 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
   e->label = label;
   e->loc = *loc;
 
-  lss = get_line_subseg (now_seg, now_subseg, TRUE);
+  lss = get_line_subseg (now_seg, now_subseg, true);
 
   /* 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;
@@ -540,35 +531,52 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
 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.  */
   if (loc->line == 0)
     return;
-  if (loc->filenum == 0 && DWARF2_LINE_VERSION < 5)
-    return;
+  if (loc->filenum == 0)
+    {
+      if (dwarf_level < 5)
+       dwarf_level = 5;
+      if (DWARF2_LINE_VERSION < 5)
+       return;
+    }
 
   /* Don't emit sequences of line symbols for the same line when the
      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
@@ -594,9 +602,10 @@ get_basename (const char * pathname)
 }
 
 static unsigned int
-get_directory_table_entry (const char *  dirname,
-                          size_t        dirlen,
-                          bfd_boolean   can_use_zero)
+get_directory_table_entry (const char *dirname,
+                          const char *file0_dirname,
+                          size_t dirlen,
+                          bool can_use_zero)
 {
   unsigned int d;
 
@@ -623,7 +632,23 @@ get_directory_table_entry (const char *  dirname,
   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;
@@ -631,8 +656,8 @@ get_directory_table_entry (const char *  dirname,
   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 *));
     }
@@ -644,7 +669,7 @@ get_directory_table_entry (const char *  dirname,
   return d;  
 }
 
-static bfd_boolean
+static bool
 assign_file_to_slot (unsigned long i, const char *file, unsigned int dir)
 {
   if (i >= files_allocated)
@@ -656,7 +681,7 @@ assign_file_to_slot (unsigned long i, const char *file, unsigned int dir)
       if (files_allocated <= old)
        {
          as_bad (_("file number %lu is too big"), (unsigned long) i);
-         return FALSE;
+         return false;
        }
 
       files = XRESIZEVEC (struct file_entry, files, files_allocated);
@@ -670,7 +695,7 @@ assign_file_to_slot (unsigned long i, const char *file, unsigned int dir)
   if (files_in_use < i + 1)
     files_in_use = i + 1;
 
-  return TRUE;
+  return true;
 }
 
 /* Get a .debug_line file number for PATHNAME.  If there is a
@@ -703,9 +728,9 @@ allocate_filenum (const char * pathname)
        }
       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;
        }
@@ -714,7 +739,7 @@ allocate_filenum (const char * pathname)
   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.  */
@@ -731,29 +756,76 @@ allocate_filenum (const char * pathname)
   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.
    if WITH_MD5 is TRUE then there is a md5 value in generic_bignum.
    Returns TRUE if allocation succeeded, FALSE otherwise.  */
 
-static bfd_boolean
-allocate_filename_to_slot (const char *  dirname,
-                          const char *  filename,
-                          unsigned int  num,
-                          bfd_boolean   with_md5)
+static bool
+allocate_filename_to_slot (const char *dirname,
+                          const char *filename,
+                          unsigned int num,
+                          bool with_md5)
 {
   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.  */
@@ -761,7 +833,7 @@ allocate_filename_to_slot (const char *  dirname,
     {
       const char * dir = NULL;
 
-      if (dirs)
+      if (dirs != NULL)
        dir = dirs[files[num].dir];
 
       if (with_md5
@@ -779,9 +851,17 @@ allocate_filename_to_slot (const char *  dirname,
          /* If the filenames match, but the directory table entry was
             empty, then fill it with the provided directory name.  */
          if (dir == NULL)
-           dirs[files[num].dir] = xmemdup0 (dirname, strlen (dirname));
+           {
+             if (dirs == NULL)
+               {
+                 dirs_allocated = files[num].dir + DIR_TABLE_INCREMENT;
+                 dirs = XCNEWVEC (char *, dirs_allocated);
+               }
+             
+             dirs[files[num].dir] = xmemdup0 (dirname, strlen (dirname));
+           }
            
-         return TRUE;
+         return true;
        }
       else if (dir != NULL) 
        {
@@ -789,18 +869,26 @@ allocate_filename_to_slot (const char *  dirname,
          if (filename_ncmp (filename, dir, dirlen) == 0
              && IS_DIR_SEPARATOR (filename [dirlen])
              && filename_cmp (filename + dirlen + 1, files[num].filename) == 0)
-           return TRUE;
+           return true;
        }
       else /* dir == NULL  */
        {
          file = get_basename (filename);
          if (filename_cmp (file, files[num].filename) == 0)
            {
+             /* The filenames match, but the directory table entry is empty.
+                Fill it with the provided directory name.  */
              if (file > filename)
-               /* The filenames match, but the directory table entry is empty.
-                  Fill it with the provided directory name.  */
-               dirs[files[num].dir] = xmemdup0 (filename, file - filename);
-             return TRUE;
+               {
+                 if (dirs == NULL)
+                   {
+                     dirs_allocated = files[num].dir + DIR_TABLE_INCREMENT;
+                     dirs = XCNEWVEC (char *, dirs_allocated);
+                   }
+
+                 dirs[files[num].dir] = xmemdup0 (filename, file - filename);
+               }
+             return true;
            }
        }
 
@@ -813,26 +901,47 @@ allocate_filename_to_slot (const char *  dirname,
              dirname == NULL ? "" : dirname,
              dirname == NULL ? "" : "/",
              filename);
-      return FALSE;
+      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))
-    return FALSE;
+    return false;
 
   if (with_md5)
     {
@@ -884,7 +993,7 @@ allocate_filename_to_slot (const char *  dirname,
   else
     memset (files[i].md5, 0, NUM_MD5_BYTES);
 
-  return TRUE;
+  return true;
 }
 
 /* Returns the current source information.  If .file directives have
@@ -897,17 +1006,12 @@ dwarf2_where (struct dwarf2_line_info *line)
 {
   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;
@@ -957,7 +1061,7 @@ dwarf2_move_insn (int delta)
   if (delta == 0)
     return;
 
-  lss = get_line_subseg (now_seg, now_subseg, FALSE);
+  lss = get_line_subseg (now_seg, now_subseg, false);
   if (!lss)
     return;
 
@@ -980,13 +1084,13 @@ dwarf2_consume_line_info (void)
 {
   /* Unless we generate DWARF2 debugging information for each
      assembler line, we only emit one line symbol for one LOC.  */
-  dwarf2_loc_directive_seen = FALSE;
+  dwarf2_loc_directive_seen = false;
 
   current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
                     | 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
@@ -1023,12 +1127,11 @@ dwarf2_emit_label (symbolS *label)
 char *
 dwarf2_directive_filename (void)
 {
-  bfd_boolean with_md5 = FALSE;
+  bool with_md5 = false;
   valueT num;
   char *filename;
   const char * dirname = NULL;
   int filename_len;
-  unsigned int i;
 
   /* Continue to accept a bare string and pass it off.  */
   SKIP_WHITESPACE ();
@@ -1040,11 +1143,16 @@ dwarf2_directive_filename (void)
 
   num = get_absolute_expression ();
 
-  if ((offsetT) num < 1 && DWARF2_LINE_VERSION < 5)
+  if ((offsetT) num < 1)
     {
-      as_bad (_("file number less than one"));
-      ignore_rest_of_line ();
-      return NULL;
+      if (num == 0 && dwarf_level < 5)
+       dwarf_level = 5;
+      if ((offsetT) num < 0 || DWARF2_LINE_VERSION < 5)
+       {
+         as_bad (_("file number less than one"));
+         ignore_rest_of_line ();
+         return NULL;
+       }
     }
 
   /* FIXME: Should we allow ".file <N>\n" as an expression meaning
@@ -1068,7 +1176,7 @@ dwarf2_directive_filename (void)
          SKIP_WHITESPACE ();
        }
 
-      if (strncmp (input_line_pointer, "md5", 3) == 0)
+      if (startswith (input_line_pointer, "md5"))
        {
          input_line_pointer += 3;
          SKIP_WHITESPACE ();
@@ -1078,7 +1186,7 @@ dwarf2_directive_filename (void)
          if (exp.X_op != O_big)
            as_bad (_("md5 value too small or not a constant"));
          else
-           with_md5 = TRUE;
+           with_md5 = true;
        }
     }
 
@@ -1086,6 +1194,8 @@ dwarf2_directive_filename (void)
 
   /* 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
@@ -1095,18 +1205,6 @@ dwarf2_directive_filename (void)
       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;
@@ -1139,19 +1237,26 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
 
   if (filenum < 1)
     {
-      if (filenum != 0 || DWARF2_LINE_VERSION < 5)
+      if (filenum == 0 && dwarf_level < 5)
+       dwarf_level = 5;
+      if (filenum < 0 || DWARF2_LINE_VERSION < 5)
        {
          as_bad (_("file number less than one"));
          return;
        }
     }
 
-  if (filenum >= (int) files_in_use || files[filenum].filename == NULL)
+  if ((valueT) filenum >= files_in_use || files[filenum].filename == NULL)
     {
       as_bad (_("unassigned file number %ld"), (long) filenum);
       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;
@@ -1255,7 +1360,7 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
          if (ISDIGIT (*input_line_pointer)
              || *input_line_pointer == '-')
            {
-             bfd_boolean force_reset = *input_line_pointer == '-';
+             bool force_reset = *input_line_pointer == '-';
 
              value = get_absolute_expression ();
              if (value != 0)
@@ -1294,7 +1399,7 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
              S_SET_VALUE (sym, 0);
              symbol_set_frag (sym, &zero_address_frag);
            }
-         current.view = sym;
+         current.u.view = sym;
        }
       else
        {
@@ -1307,11 +1412,10 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
     }
 
   demand_empty_rest_of_line ();
-  dwarf2_any_loc_directive_seen = dwarf2_loc_directive_seen = TRUE;
-  debug_type = DEBUG_NONE;
+  dwarf2_any_loc_directive_seen = dwarf2_loc_directive_seen = true;
 
   /* If we were given a view id, emit the row right away.  */
-  if (current.view)
+  if (current.u.view)
     dwarf2_emit_insn (0);
 }
 
@@ -1878,13 +1982,13 @@ process_entries (segT seg, struct line_entry *e)
       if (strcmp (sec_name, ".text") != 0)
        {
          name = concat (".debug_line", sec_name, (char *) NULL);
-         subseg_set (subseg_get (name, FALSE), 0);
+         subseg_set (subseg_get (name, false), 0);
        }
       else
        /* Don't create a .debug_line.text section -
           that is redundant.  Instead just switch back to the
           normal .debug_line section.  */
-       subseg_set (subseg_get (".debug_line", FALSE), 0);
+       subseg_set (subseg_get (".debug_line", false), 0);
     }
 
   do
@@ -1945,7 +2049,7 @@ process_entries (segT seg, struct line_entry *e)
       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
@@ -2020,9 +2124,9 @@ out_dir_and_file_list (segT line_seg, int sizeof_offset)
   const char *dir;
   char *cp;
   unsigned int i;
-  bfd_boolean emit_md5 = FALSE;
-  bfd_boolean emit_timestamps = TRUE;
-  bfd_boolean emit_filesize = TRUE;
+  bool emit_md5 = false;
+  bool emit_timestamps = true;
+  bool emit_filesize = true;
   segT line_str_seg = NULL;
   symbolS *line_strp;
 
@@ -2062,7 +2166,12 @@ out_dir_and_file_list (segT line_seg, int sizeof_offset)
         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 ());
@@ -2099,13 +2208,13 @@ out_dir_and_file_list (segT line_seg, int sizeof_offset)
 
       if (((unsigned long) DWARF2_FILE_TIME_NAME ("", "")) == -1UL)
        {
-         emit_timestamps = FALSE;
+         emit_timestamps = false;
          -- columns;
        }
 
       if (DWARF2_FILE_SIZE_NAME ("", "") == -1)
        {
-         emit_filesize = FALSE;
+         emit_filesize = false;
          -- columns;
        }
 
@@ -2114,7 +2223,7 @@ out_dir_and_file_list (segT line_seg, int sizeof_offset)
          break;
       if (i < files_in_use)
        {
-         emit_md5 = TRUE;
+         emit_md5 = true;
          ++ columns;
        }
       
@@ -2165,8 +2274,8 @@ out_dir_and_file_list (segT line_seg, int sizeof_offset)
             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)
@@ -2355,7 +2464,7 @@ out_debug_line (segT line_seg)
   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)
@@ -2366,7 +2475,7 @@ out_debug_line (segT line_seg)
        This section contains the line_end symbol which is used to
        compute the size of the linked .debug_line section, as seen
        in the DWARF Line Number header.  */
-    subseg_set (subseg_get (".debug_line_end", FALSE), 0);
+    subseg_set (subseg_get (".debug_line_end", false), 0);
 
   symbol_set_value_now (line_end);
 }
@@ -2800,6 +2909,15 @@ dwarf2_finish (void)
                             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)
     {
@@ -2808,14 +2926,14 @@ dwarf2_finish (void)
 
       /* 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);