testsuite, fortran: fix info-types for intel compilers
[binutils-gdb.git] / gas / write.c
index 62b39428bb5acc3ab10625071c8d7e06f394440c..20f5ce24d5fb17e25b487ee887e567432ed0bf4f 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986-2018 Free Software Foundation, Inc.
+   Copyright (C) 1986-2022 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
 #endif
 
 #ifndef TC_VALIDATE_FIX_SUB
-#ifdef UNDEFINED_DIFFERENCE_OK
-/* The PA needs this for PIC code generation.  */
-#define TC_VALIDATE_FIX_SUB(FIX, SEG)                  \
-  (md_register_arithmetic || (SEG) != reg_section)
-#else
-#define TC_VALIDATE_FIX_SUB(FIX, SEG)                  \
-  ((md_register_arithmetic || (SEG) != reg_section)    \
-   && ((FIX)->fx_r_type == BFD_RELOC_GPREL32           \
-       || (FIX)->fx_r_type == BFD_RELOC_GPREL16))
-#endif
+#define TC_VALIDATE_FIX_SUB(FIX, SEG) 0
 #endif
 
 #ifndef TC_LINKRELAX_FIXUP
@@ -143,8 +134,8 @@ static int n_fixups;
 
 static fixS *
 fix_new_internal (fragS *frag,         /* Which frag?  */
-                 int where,            /* Where in that frag?  */
-                 int size,             /* 1, 2, or 4 usually.  */
+                 unsigned long where,  /* Where in that frag?  */
+                 unsigned long size,   /* 1, 2, or 4 usually.  */
                  symbolS *add_symbol,  /* X_add_symbol.  */
                  symbolS *sub_symbol,  /* X_op_symbol.  */
                  offsetT offset,       /* X_add_number.  */
@@ -164,7 +155,7 @@ fix_new_internal (fragS *frag,              /* Which frag?  */
   /* We've made fx_size a narrow field; check that it's wide enough.  */
   if (fixP->fx_size != size)
     {
-      as_bad (_("field fx_size too small to hold %d"), size);
+      as_bad (_("field fx_size too small to hold %lu"), size);
       abort ();
     }
   fixP->fx_addsy = add_symbol;
@@ -174,9 +165,7 @@ fix_new_internal (fragS *frag,              /* Which frag?  */
   fixP->fx_dot_frag = dot_frag;
   fixP->fx_pcrel = pcrel;
   fixP->fx_r_type = r_type;
-  fixP->fx_im_disp = 0;
   fixP->fx_pcrel_adjust = 0;
-  fixP->fx_bit_fixP = 0;
   fixP->fx_addnumber = 0;
   fixP->fx_tcbit = 0;
   fixP->fx_tcbit2 = 0;
@@ -228,16 +217,16 @@ fix_new_internal (fragS *frag,            /* Which frag?  */
 /* Create a fixup relative to a symbol (plus a constant).  */
 
 fixS *
-fix_new (fragS *frag,          /* Which frag?  */
-        int where,                     /* Where in that frag?  */
-        int size,                      /* 1, 2, or 4 usually.  */
-        symbolS *add_symbol,   /* X_add_symbol.  */
+fix_new (fragS *frag,                  /* Which frag?  */
+        unsigned long where,           /* Where in that frag?  */
+        unsigned long size,            /* 1, 2, or 4 usually.  */
+        symbolS *add_symbol,           /* X_add_symbol.  */
         offsetT offset,                /* X_add_number.  */
         int pcrel,                     /* TRUE if PC-relative relocation.  */
         RELOC_ENUM r_type              /* Relocation type.  */)
 {
   return fix_new_internal (frag, where, size, add_symbol,
-                          (symbolS *) NULL, offset, pcrel, r_type, FALSE);
+                          (symbolS *) NULL, offset, pcrel, r_type, false);
 }
 
 /* Create a fixup for an expression.  Currently we only support fixups
@@ -246,8 +235,8 @@ fix_new (fragS *frag,               /* Which frag?  */
 
 fixS *
 fix_new_exp (fragS *frag,              /* Which frag?  */
-            int where,                 /* Where in that frag?  */
-            int size,                  /* 1, 2, or 4 usually.  */
+            unsigned long where,       /* Where in that frag?  */
+            unsigned long size,        /* 1, 2, or 4 usually.  */
             expressionS *exp,          /* Expression.  */
             int pcrel,                 /* TRUE if PC-relative relocation.  */
             RELOC_ENUM r_type          /* Relocation type.  */)
@@ -306,18 +295,18 @@ fix_new_exp (fragS *frag,         /* Which frag?  */
     }
 
   return fix_new_internal (frag, where, size, add, sub, off, pcrel,
-                          r_type, FALSE);
+                          r_type, false);
 }
 
 /* Create a fixup at the beginning of FRAG.  The arguments are the same
    as for fix_new, except that WHERE is implicitly 0.  */
 
 fixS *
-fix_at_start (fragS *frag, int size, symbolS *add_symbol,
+fix_at_start (fragS *frag, unsigned long size, symbolS *add_symbol,
              offsetT offset, int pcrel, RELOC_ENUM r_type)
 {
   return fix_new_internal (frag, 0, size, add_symbol,
-                          (symbolS *) NULL, offset, pcrel, r_type, TRUE);
+                          (symbolS *) NULL, offset, pcrel, r_type, true);
 }
 
 /* Generic function to determine whether a fixup requires a relocation.  */
@@ -361,8 +350,8 @@ record_alignment (/* Segment to which alignment pertains.  */
   if (seg == absolute_section)
     return;
 
-  if (align > bfd_get_section_alignment (stdoutput, seg))
-    bfd_set_section_alignment (stdoutput, seg, align);
+  if (align > bfd_section_alignment (seg))
+    bfd_set_section_alignment (seg, align);
 }
 
 int
@@ -371,7 +360,7 @@ get_recorded_alignment (segT seg)
   if (seg == absolute_section)
     return 0;
 
-  return bfd_get_section_alignment (stdoutput, seg);
+  return bfd_section_alignment (seg);
 }
 
 /* Reset the section indices after removing the gas created sections.  */
@@ -445,7 +434,7 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
 #ifdef HANDLE_ALIGN
       HANDLE_ALIGN (fragP);
 #endif
-skip_align:
+    skip_align:
       know (fragP->fr_next != NULL);
       fragP->fr_offset = (fragP->fr_next->fr_address
                          - fragP->fr_address
@@ -502,8 +491,8 @@ skip_align:
       md_convert_frag (stdoutput, sec, fragP);
 
       gas_assert (fragP->fr_next == NULL
-             || ((offsetT) (fragP->fr_next->fr_address - fragP->fr_address)
-                 == fragP->fr_fix));
+                 || (fragP->fr_next->fr_address - fragP->fr_address
+                     == fragP->fr_fix));
 
       /* After md_convert_frag, we make the frag into a ".space 0".
         md_convert_frag() should set up any fixSs and constants
@@ -557,7 +546,7 @@ relax_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx)
 }
 
 static void
-size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
+size_seg (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *xxx ATTRIBUTE_UNUSED)
 {
   flagword flags;
   fragS *fragp;
@@ -582,8 +571,8 @@ size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   else
     size = 0;
 
-  flags = bfd_get_section_flags (abfd, sec);
-  if (size == 0 && bfd_get_section_size (sec) != 0 &&
+  flags = bfd_section_flags (sec);
+  if (size == 0 && bfd_section_size (sec) != 0 &&
     (flags & SEC_HAS_CONTENTS) != 0)
     return;
 
@@ -591,7 +580,7 @@ size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
     flags |= SEC_HAS_CONTENTS;
 
   flags &= ~SEC_RELOC;
-  x = bfd_set_section_flags (abfd, sec, flags);
+  x = bfd_set_section_flags (sec, flags);
   gas_assert (x);
 
   /* If permitted, allow the backend to pad out the section
@@ -600,7 +589,7 @@ size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
     newsize = size;
   else
     newsize = md_section_align (sec, size);
-  x = bfd_set_section_size (abfd, sec, newsize);
+  x = bfd_set_section_size (sec, newsize);
   gas_assert (x);
 
   /* If the size had to be rounded up, add some padding in the last
@@ -739,7 +728,9 @@ resolve_reloc_expr_symbols (void)
                 prevent the offset from overflowing the relocated field,
                 unless it has enough bits to cover the whole address
                 space.  */
-             if (S_IS_LOCAL (sym) && !symbol_section_p (sym)
+             if (S_IS_LOCAL (sym)
+                 && S_IS_DEFINED (sym)
+                 && !symbol_section_p (sym)
                  && (sec->use_rela_p
                      || (howto->partial_inplace
                          && (!howto->pc_relative
@@ -850,7 +841,12 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
        /* Since we're reducing to section symbols, don't attempt to reduce
           anything that's already using one.  */
        if (symbol_section_p (sym))
-         continue;
+         {
+           /* Mark the section symbol used in relocation so that it will
+              be included in the symbol table.  */
+           symbol_mark_used_in_reloc (sym);
+           continue;
+         }
 
        symsec = S_GET_SEGMENT (sym);
        if (symsec == NULL)
@@ -875,8 +871,7 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
                    /* The GNU toolchain uses an extension for ELF: a
                       section beginning with the magic string
                       .gnu.linkonce is a linkonce section.  */
-                   && strncmp (segment_name (symsec), ".gnu.linkonce",
-                               sizeof ".gnu.linkonce" - 1) == 0))
+                   && startswith (segment_name (symsec), ".gnu.linkonce")))
              continue;
          }
 
@@ -904,6 +899,15 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
   dump_section_relocs (abfd, sec, stderr);
 }
 
+void
+as_bad_subtract (fixS *fixp)
+{
+  as_bad_where (fixp->fx_file, fixp->fx_line,
+               _("can't resolve %s - %s"),
+               fixp->fx_addsy ? S_GET_NAME (fixp->fx_addsy) : "0",
+               S_GET_NAME (fixp->fx_subsy));
+}
+
 /* fixup_segment()
 
    Go through all the fixS's in a segment and see which ones can be
@@ -918,7 +922,6 @@ fixup_segment (fixS *fixP, segT this_segment)
 {
   valueT add_number;
   fragS *fragP;
-  segT add_symbol_segment = absolute_section;
 
   if (fixP != NULL && abs_section_sym == NULL)
     abs_section_sym = section_symbol (absolute_section);
@@ -949,6 +952,8 @@ fixup_segment (fixS *fixP, segT this_segment)
 
   for (; fixP; fixP = fixP->fx_next)
     {
+      segT add_symbol_segment = absolute_section;
+
 #ifdef DEBUG5
       fprintf (stderr, "\nprocessing fixup:\n");
       print_fixup (fixP);
@@ -1025,12 +1030,7 @@ fixup_segment (fixS *fixP, segT this_segment)
                as_bad_where (fixP->fx_file, fixP->fx_line,
                              _("register value used as expression"));
              else
-               as_bad_where (fixP->fx_file, fixP->fx_line,
-                             _("can't resolve `%s' {%s section} - `%s' {%s section}"),
-                             fixP->fx_addsy ? S_GET_NAME (fixP->fx_addsy) : "0",
-                             segment_name (add_symbol_segment),
-                             S_GET_NAME (fixP->fx_subsy),
-                             segment_name (sub_symbol_segment));
+               as_bad_subtract (fixP);
            }
          else if (sub_symbol_segment != undefined_section
                   && ! bfd_is_com_section (sub_symbol_segment)
@@ -1093,7 +1093,7 @@ fixup_segment (fixS *fixP, segT this_segment)
            symbol_mark_used_in_reloc (fixP->fx_subsy);
        }
 
-      if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && fixP->fx_size != 0)
+      if (!fixP->fx_no_overflow && fixP->fx_size != 0)
        {
          if (fixP->fx_size < sizeof (valueT))
            {
@@ -1102,12 +1102,15 @@ fixup_segment (fixS *fixP, segT this_segment)
              mask = 0;
              mask--;           /* Set all bits to one.  */
              mask <<= fixP->fx_size * 8 - (fixP->fx_signed ? 1 : 0);
-             if ((add_number & mask) != 0 && (add_number & mask) != mask)
+             if ((add_number & mask) != 0
+                 && (fixP->fx_signed
+                     ? (add_number & mask) != mask
+                     : (-add_number & mask) != 0))
                {
                  char buf[50], buf2[50];
-                 sprint_value (buf, fragP->fr_address + fixP->fx_where);
+                 bfd_sprintf_vma (stdoutput, buf, fragP->fr_address + fixP->fx_where);
                  if (add_number > 1000)
-                   sprint_value (buf2, add_number);
+                   bfd_sprintf_vma (stdoutput, buf2, add_number);
                  else
                    sprintf (buf2, "%ld", (long) add_number);
                  as_bad_where (fixP->fx_file, fixP->fx_line,
@@ -1131,7 +1134,7 @@ fixup_segment (fixS *fixP, segT this_segment)
                          (long) add_number,
                          (long) (fragP->fr_address + fixP->fx_where));
 #endif
-       }                       /* Not a bit fix.  */
+       }
 
 #ifdef TC_VALIDATE_FIX
     skip:  ATTRIBUTE_UNUSED_LABEL
@@ -1217,7 +1220,8 @@ get_frag_for_reloc (fragS *last_frag,
 }
 
 static void
-write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
+write_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
+             void *xxx ATTRIBUTE_UNUSED)
 {
   segment_info_type *seginfo = seg_info (sec);
   unsigned int n;
@@ -1242,6 +1246,7 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
 
   /* Extract relocs for this section from reloc_list.  */
   rp = &reloc_list;
+
   my_reloc_list = NULL;
   while ((r = *rp) != NULL)
     {
@@ -1264,7 +1269,7 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   for (fixp = seginfo->fix_root; fixp != (fixS *) NULL; fixp = fixp->fx_next)
     {
       int fx_size, slack;
-      offsetT loc;
+      valueT loc;
       arelent **reloc;
 #ifndef RELOC_EXPANSION_POSSIBLE
       arelent *rel;
@@ -1284,6 +1289,13 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
        as_bad_where (fixp->fx_file, fixp->fx_line,
                      _("internal error: fixup not contained within frag"));
 
+#ifdef obj_fixup_removed_symbol
+      if (fixp->fx_addsy && symbol_removed_p (fixp->fx_addsy))
+       obj_fixup_removed_symbol (&fixp->fx_addsy);
+      if (fixp->fx_subsy && symbol_removed_p (fixp->fx_subsy))
+       obj_fixup_removed_symbol (&fixp->fx_subsy);
+#endif
+
 #ifndef RELOC_EXPANSION_POSSIBLE
       *reloc = tc_gen_reloc (sec, fixp);
 #else
@@ -1303,7 +1315,34 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
                }
              r = r->next;
            }
-         relocs[n++] = *reloc;
+#ifdef GAS_SORT_RELOCS
+         if (n != 0 && (*reloc)->address < relocs[n - 1]->address)
+           {
+             size_t lo = 0;
+             size_t hi = n - 1;
+             bfd_vma look = (*reloc)->address;
+             while (lo < hi)
+               {
+                 size_t mid = (lo + hi) / 2;
+                 if (relocs[mid]->address > look)
+                   hi = mid;
+                 else
+                   {
+                     lo = mid + 1;
+                     if (relocs[mid]->address == look)
+                       break;
+                   }
+               }
+             while (lo < hi && relocs[lo]->address == look)
+               lo++;
+             memmove (relocs + lo + 1, relocs + lo,
+                      (n - lo) * sizeof (*relocs));
+             n++;
+             relocs[lo] = *reloc;
+           }
+         else
+#endif
+           relocs[n++] = *reloc;
          install_reloc (sec, *reloc, fixp->fx_frag,
                         fixp->fx_file, fixp->fx_line);
 #ifndef RELOC_EXPANSION_POSSIBLE
@@ -1346,9 +1385,9 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
 
   if (n)
     {
-      flagword flags = bfd_get_section_flags (abfd, sec);
+      flagword flags = bfd_section_flags (sec);
       flags |= SEC_RELOC;
-      bfd_set_section_flags (abfd, sec, flags);
+      bfd_set_section_flags (sec, flags);
       bfd_set_reloc (stdoutput, sec, relocs, n);
     }
 
@@ -1434,7 +1473,7 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   char *header;
   struct z_stream_s *strm;
   int x;
-  flagword flags = bfd_get_section_flags (abfd, sec);
+  flagword flags = bfd_section_flags (sec);
   unsigned int header_size, compression_header_size;
 
   if (seginfo == NULL
@@ -1442,8 +1481,8 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
       || (flags & (SEC_ALLOC | SEC_HAS_CONTENTS)) == SEC_ALLOC)
     return;
 
-  section_name = bfd_get_section_name (stdoutput, sec);
-  if (strncmp (section_name, ".debug_", 7) != 0)
+  section_name = bfd_section_name (sec);
+  if (!startswith (section_name, ".debug_"))
     return;
 
   strm = compress_init ();
@@ -1566,12 +1605,12 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
 
   /* Update the section size and its name.  */
   bfd_update_compression_header (abfd, (bfd_byte *) header, sec);
-  x = bfd_set_section_size (abfd, sec, compressed_size);
+  x = bfd_set_section_size (sec, compressed_size);
   gas_assert (x);
   if (!compression_header_size)
     {
       compressed_name = concat (".z", section_name + 1, (char *) NULL);
-      bfd_section_name (stdoutput, sec) = compressed_name;
+      bfd_rename_section (sec, compressed_name);
     }
 }
 
@@ -1600,7 +1639,7 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
 
   /* Write out the frags.  */
   if (seginfo == NULL
-      || !(bfd_get_section_flags (abfd, sec) & SEC_HAS_CONTENTS))
+      || !(bfd_section_flags (sec) & SEC_HAS_CONTENTS))
     return;
 
   for (f = seginfo->frchainP->frch_root;
@@ -1625,7 +1664,7 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                                "to section %s of %s: '%s'",
                                (long) f->fr_fix),
                      (long) f->fr_fix,
-                     sec->name, stdoutput->filename,
+                     bfd_section_name (sec), bfd_get_filename (stdoutput),
                      bfd_errmsg (bfd_get_error ()));
          offset += f->fr_fix;
        }
@@ -1649,9 +1688,11 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                                    "in section %s of %s: '%s'",
                                    "can't fill %ld bytes "
                                    "in section %s of %s: '%s'",
-                                   (long) count), (long) count,
-                                   sec->name, stdoutput->filename,
-                                   bfd_errmsg (bfd_get_error ()));
+                                   (long) count),
+                         (long) count,
+                         bfd_section_name (sec),
+                         bfd_get_filename (stdoutput),
+                         bfd_errmsg (bfd_get_error ()));
              offset += count;
              free (buf);
            }
@@ -1678,7 +1719,8 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                                        "in section %s of %s: '%s'",
                                        (long) fill_size),
                              (long) fill_size,
-                             sec->name, stdoutput->filename,
+                             bfd_section_name (sec),
+                             bfd_get_filename (stdoutput),
                              bfd_errmsg (bfd_get_error ()));
                  offset += fill_size;
                }
@@ -1714,7 +1756,8 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                                        "in section %s of %s: '%s'",
                                        (long) (n_per_buf * fill_size)),
                              (long) (n_per_buf * fill_size),
-                             sec->name, stdoutput->filename,
+                             bfd_section_name (sec),
+                             bfd_get_filename (stdoutput),
                              bfd_errmsg (bfd_get_error ()));
                  offset += n_per_buf * fill_size;
                }
@@ -1739,14 +1782,18 @@ set_symtab (void)
   int nsyms;
   asymbol **asympp;
   symbolS *symp;
-  bfd_boolean result;
+  bool result;
 
   /* Count symbols.  We can't rely on a count made by the loop in
      write_object_file, because *_frob_file may add a new symbol or
-     two.  */
+     two.  Generate unused section symbols only if needed.  */
   nsyms = 0;
   for (symp = symbol_rootP; symp; symp = symbol_next (symp))
-    nsyms++;
+    if (!symbol_removed_p (symp)
+       && (bfd_keep_unused_section_symbols (stdoutput)
+           || !symbol_section_p (symp)
+           || symbol_used_in_reloc_p (symp)))
+      nsyms++;
 
   if (nsyms)
     {
@@ -1755,15 +1802,23 @@ set_symtab (void)
 
       asympp = (asymbol **) bfd_alloc (stdoutput, amt);
       symp = symbol_rootP;
-      for (i = 0; i < nsyms; i++, symp = symbol_next (symp))
-       {
-         asympp[i] = symbol_get_bfdsym (symp);
-         if (asympp[i]->flags != BSF_SECTION_SYM
-             || !(bfd_is_const_section (asympp[i]->section)
-                  && asympp[i]->section->symbol == asympp[i]))
-           asympp[i]->flags |= BSF_KEEP;
-         symbol_mark_written (symp);
-       }
+      for (i = 0; i < nsyms; symp = symbol_next (symp))
+       if (!symbol_removed_p (symp)
+           && (bfd_keep_unused_section_symbols (stdoutput)
+               || !symbol_section_p (symp)
+               || symbol_used_in_reloc_p (symp)))
+         {
+           asympp[i] = symbol_get_bfdsym (symp);
+           if (asympp[i]->flags != BSF_SECTION_SYM
+               || !(bfd_is_const_section (asympp[i]->section)
+                    && asympp[i]->section->symbol == asympp[i]))
+             asympp[i]->flags |= BSF_KEEP;
+           symbol_mark_written (symp);
+           /* Include this section symbol in the symbol table.  */
+           if (symbol_section_p (symp))
+             asympp[i]->flags |= BSF_SECTION_SYM_USED;
+           i++;
+         }
     }
   else
     asympp = 0;
@@ -1816,7 +1871,7 @@ subsegs_finish_section (asection *s)
        do_not_pad_sections_to_alignment = 1;
 
       alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
-      if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
+      if ((bfd_section_flags (now_seg) & SEC_MERGE)
          && now_seg->entsize)
        {
          unsigned int entsize = now_seg->entsize;
@@ -1876,7 +1931,7 @@ create_obj_attrs_section (void)
   s = subseg_new (name, 0);
   elf_section_type (s)
     = get_elf_backend_data (stdoutput)->obj_attrs_section_type;
-  bfd_set_section_flags (stdoutput, s, SEC_READONLY | SEC_DATA);
+  bfd_set_section_flags (s, SEC_READONLY | SEC_DATA);
   frag_now_fix ();
   p = frag_more (size);
   bfd_elf_set_obj_attr_contents (stdoutput, (bfd_byte *)p, size);
@@ -1891,7 +1946,9 @@ create_obj_attrs_section (void)
 static void
 create_note_reloc (segT           sec,
                   symbolS *      sym,
-                  bfd_size_type  offset,
+                  bfd_size_type  note_offset,
+                  bfd_size_type  desc2_offset,
+                  offsetT        desc2_size,
                   int            reloc_type,
                   bfd_vma        addend,
                   char *         note)
@@ -1901,10 +1958,10 @@ create_note_reloc (segT           sec,
   reloc = XNEW (struct reloc_list);
 
   /* We create a .b type reloc as resolve_reloc_expr_symbols() has already been called.  */
-  reloc->u.b.sec   = sec;
-  reloc->u.b.s     = symbol_get_bfdsym (sym);
+  reloc->u.b.sec           = sec;
+  reloc->u.b.s             = symbol_get_bfdsym (sym);
   reloc->u.b.r.sym_ptr_ptr = & reloc->u.b.s;
-  reloc->u.b.r.address     = offset;
+  reloc->u.b.r.address     = note_offset + desc2_offset;
   reloc->u.b.r.addend      = addend;
   reloc->u.b.r.howto       = bfd_reloc_type_lookup (stdoutput, reloc_type);
 
@@ -1926,15 +1983,21 @@ create_note_reloc (segT           sec,
         but still stores the addend in the word being relocated.  */
       || strstr (bfd_get_target (stdoutput), "-sh") != NULL)
     {
+      offsetT i;
+
+      /* Zero out the addend, since it is now stored in the note.  */
+      reloc->u.b.r.addend = 0;
+
       if (target_big_endian)
        {
-         if (bfd_arch_bits_per_address (stdoutput) <= 32)
-           note[offset + 3] = addend;
-         else
-           note[offset + 7] = addend;
+         for (i = desc2_size; addend != 0 && i > 0; addend >>= 8, i--)
+           note[desc2_offset + i - 1] = (addend & 0xff);
        }
       else
-       note[offset] = addend;
+       {
+         for (i = 0; addend != 0 && i < desc2_size; addend >>= 8, i++)
+           note[desc2_offset + i] = (addend & 0xff);
+       }
     }
 }
 
@@ -1957,11 +2020,11 @@ maybe_generate_build_notes (void)
     return;
 
   /* Create a GNU Build Attribute section.  */
-  sec = subseg_new (GNU_BUILD_ATTRS_SECTION_NAME, FALSE);
+  sec = subseg_new (GNU_BUILD_ATTRS_SECTION_NAME, false);
   elf_section_type (sec) = SHT_NOTE;
-  bfd_set_section_flags (stdoutput, sec,
-                        SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA);
-  bfd_set_section_alignment (stdoutput, sec, 2);
+  bfd_set_section_flags (sec, (SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA
+                              | SEC_OCTETS));
+  bfd_set_section_alignment (sec, 2);
 
   /* Work out the size of the notes that we will create,
      and the relocation we should use.  */
@@ -2010,7 +2073,7 @@ maybe_generate_build_notes (void)
        /* Skip linkonce sections - we cannot use these section symbols as they may disappear.  */
        && (bsym->section->flags & (SEC_CODE | SEC_LINK_ONCE)) == SEC_CODE
        /* Not all linkonce sections are flagged...  */
-       && strncmp (S_GET_NAME (sym), ".gnu.linkonce", sizeof ".gnu.linkonce" - 1) != 0)
+       && !startswith (S_GET_NAME (sym), ".gnu.linkonce"))
       {
        /* Create a version note.  */
        frag_now_fix ();
@@ -2020,14 +2083,14 @@ maybe_generate_build_notes (void)
        if (target_big_endian)
          {
            note[3] = 8; /* strlen (name) + 1.  */
-           note[7] = desc_size; /* Two 8-byte offsets.  */
+           note[7] = desc_size; /* Two N-byte offsets.  */
            note[10] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
            note[11] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
          }
        else
          {
            note[0] = 8; /* strlen (name) + 1.  */
-           note[4] = desc_size; /* Two 8-byte offsets.  */
+           note[4] = desc_size; /* Two N-byte offsets.  */
            note[8] = NT_GNU_BUILD_ATTRIBUTE_OPEN & 0xff;
            note[9] = NT_GNU_BUILD_ATTRIBUTE_OPEN >> 8;
          }
@@ -2037,13 +2100,19 @@ maybe_generate_build_notes (void)
        memcpy (note + 12, "GA$\ 13a1", 8);
 
        /* Create a relocation to install the start address of the note...  */
-       create_note_reloc (sec, sym, total_size + 20, desc_reloc, 0, note);
+       create_note_reloc (sec, sym, total_size, 20, desc_size / 2, desc_reloc, 0, note);
 
        /* ...and another one to install the end address.  */
-       create_note_reloc (sec, sym, total_size + desc2_offset, desc_reloc,
-                          bfd_get_section_size (bsym->section),
+       create_note_reloc (sec, sym, total_size, desc2_offset,
+                          desc_size / 2,
+                          desc_reloc,
+                          bfd_section_size (bsym->section),
                           note);
 
+       /* Mark the section symbol used in relocation so that it will be
+          included in the symbol table.  */
+       symbol_mark_used_in_reloc (sym);
+
        total_size += note_size;
        /* FIXME: Maybe add a note recording the assembler command line and version ?  */
       }
@@ -2271,7 +2340,7 @@ write_object_file (void)
   if (IS_ELF)
     maybe_generate_build_notes ();
 #endif
-  
+
   PROGRESS (1);
 
 #ifdef tc_frob_file_before_adjust
@@ -2296,7 +2365,7 @@ write_object_file (void)
   if (symbol_rootP)
     {
       symbolS *symp;
-      bfd_boolean skip_next_symbol = FALSE;
+      bool skip_next_symbol = false;
 
       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
        {
@@ -2308,7 +2377,7 @@ write_object_file (void)
              /* Don't do anything besides moving the value of the
                 symbol from the GAS value-field to the BFD value-field.  */
              symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
-             skip_next_symbol = FALSE;
+             skip_next_symbol = false;
              continue;
            }
 
@@ -2412,7 +2481,7 @@ write_object_file (void)
             symbol warned about.  Don't let anything object-format or
             target-specific muck with it; it's ready for output.  */
          if (symbol_get_bfdsym (symp)->flags & BSF_WARNING)
-           skip_next_symbol = TRUE;
+           skip_next_symbol = true;
        }
     }
 
@@ -2428,7 +2497,7 @@ write_object_file (void)
 #endif
 
   /* Stop if there is an error.  */
-  if (had_errors ())
+  if (!flag_always_generate_output && had_errors ())
     return;
 
   /* Now that all the sizes are known, and contents correct, we can
@@ -2480,6 +2549,10 @@ write_object_file (void)
 }
 
 #ifdef TC_GENERIC_RELAX_TABLE
+#ifndef md_generic_table_relax_frag
+#define md_generic_table_relax_frag relax_frag
+#endif
+
 /* Relax a fragment by scanning TC_GENERIC_RELAX_TABLE.  */
 
 long
@@ -2497,7 +2570,7 @@ relax_frag (segT segment, fragS *fragP, long stretch)
   const relax_typeS *table;
 
   target = fragP->fr_offset;
-  address = fragP->fr_address;
+  address = fragP->fr_address + fragP->fr_fix;
   table = TC_GENERIC_RELAX_TABLE;
   this_state = fragP->fr_subtype;
   start_type = this_type = table + this_state;
@@ -2537,13 +2610,13 @@ relax_frag (segT segment, fragS *fragP, long stretch)
             negative.  Don't allow this in case the negative reach is
             large enough to require a larger branch instruction.  */
          else if (target < address)
-           target = fragP->fr_next->fr_address + stretch;
+           return 0;
        }
     }
 
-  aim = target - address - fragP->fr_fix;
+  aim = target - address;
 #ifdef TC_PCREL_ADJUST
-  /* Currently only the ns32k family needs this.  */
+  /* Currently only the ns32k and arc needs this.  */
   aim += TC_PCREL_ADJUST (fragP);
 #endif
 
@@ -2827,7 +2900,9 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                          if (flag_warn_displacement)
                            {
                              char buf[50];
-                             sprint_value (buf, (addressT) lie->addnum);
+
+                             bfd_sprintf_vma (stdoutput, buf,
+                                              (addressT) lie->addnum);
                              as_warn_where (fragP->fr_file, fragP->fr_line,
                                             _(".word %s-%s+%s didn't fit"),
                                             S_GET_NAME (lie->add),
@@ -2931,7 +3006,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
 
              case rs_org:
                {
-                 addressT target = offset;
+                 offsetT target = offset;
                  addressT after;
 
                  if (symbolP)
@@ -2951,7 +3026,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                  /* Growth may be negative, but variable part of frag
                     cannot have fewer than 0 chars.  That is, we can't
                     .org backwards.  */
-                 if (address + fragP->fr_fix > target)
+                 if ((offsetT) (address + fragP->fr_fix) > target)
                    {
                      growth = 0;
 
@@ -2999,7 +3074,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                        || ! S_IS_DEFINED (symbolP))
                      {
                        as_bad_where (fragP->fr_file, fragP->fr_line,
-                                     _(".space specifies non-absolute value"));
+                                     _(".space, .nops or .fill specifies non-absolute value"));
                        /* Prevent repeat of this error message.  */
                        fragP->fr_symbol = 0;
                      }
@@ -3030,7 +3105,8 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
 #ifdef TC_GENERIC_RELAX_TABLE
                /* The default way to relax a frag is to look through
                   TC_GENERIC_RELAX_TABLE.  */
-               growth = relax_frag (segment, fragP, stretch);
+               growth = md_generic_table_relax_frag (segment, fragP,
+                                                     stretch);
 #endif /* TC_GENERIC_RELAX_TABLE  */
 #endif
                break;
@@ -3136,26 +3212,18 @@ print_fixup (fixS *fixp)
 {
   indent_level = 1;
   fprintf (stderr, "fix ");
-  fprintf_vma (stderr, (bfd_vma)((bfd_hostptr_t) fixp));
+  fprintf_vma (stderr, (bfd_vma) (uintptr_t) fixp);
   fprintf (stderr, " %s:%d",fixp->fx_file, fixp->fx_line);
   if (fixp->fx_pcrel)
     fprintf (stderr, " pcrel");
   if (fixp->fx_pcrel_adjust)
     fprintf (stderr, " pcrel_adjust=%d", fixp->fx_pcrel_adjust);
-  if (fixp->fx_im_disp)
-    {
-#ifdef TC_NS32K
-      fprintf (stderr, " im_disp=%d", fixp->fx_im_disp);
-#else
-      fprintf (stderr, " im_disp");
-#endif
-    }
   if (fixp->fx_tcbit)
     fprintf (stderr, " tcbit");
   if (fixp->fx_done)
     fprintf (stderr, " done");
   fprintf (stderr, "\n    size=%d frag=", fixp->fx_size);
-  fprintf_vma (stderr, (bfd_vma) ((bfd_hostptr_t) fixp->fx_frag));
+  fprintf_vma (stderr, (bfd_vma) (uintptr_t) fixp->fx_frag);
   fprintf (stderr, " where=%ld offset=%lx addnumber=%lx",
           (long) fixp->fx_where,
           (unsigned long) fixp->fx_offset,