testsuite, fortran: fix info-types for intel compilers
[binutils-gdb.git] / gas / write.c
index 054f27987d51f1732afdc81bbc9e19a95160c53f..20f5ce24d5fb17e25b487ee887e567432ed0bf4f 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986-2020 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
@@ -235,7 +226,7 @@ fix_new (fragS *frag,                       /* Which frag?  */
         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
@@ -304,7 +295,7 @@ 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
@@ -315,7 +306,7 @@ 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.  */
@@ -737,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
@@ -848,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)
@@ -873,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;
          }
 
@@ -902,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
@@ -916,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);
@@ -947,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);
@@ -1023,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)
@@ -1100,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,
@@ -1284,6 +1289,13 @@ write_relocs (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
        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 ATTRIBUTE_UNUSED, asection *sec,
                }
              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
@@ -1443,7 +1482,7 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
     return;
 
   section_name = bfd_section_name (sec);
-  if (strncmp (section_name, ".debug_", 7) != 0)
+  if (!startswith (section_name, ".debug_"))
     return;
 
   strm = compress_init ();
@@ -1743,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)
     {
@@ -1759,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;
@@ -1969,7 +2020,7 @@ 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 (sec, (SEC_READONLY | SEC_HAS_CONTENTS | SEC_DATA
                               | SEC_OCTETS));
@@ -2022,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 ();
@@ -2058,6 +2109,10 @@ maybe_generate_build_notes (void)
                           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 ?  */
       }
@@ -2310,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))
        {
@@ -2322,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;
            }
 
@@ -2426,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;
        }
     }
 
@@ -2845,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),
@@ -3155,7 +3212,7 @@ 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");
@@ -3166,7 +3223,7 @@ print_fixup (fixS *fixp)
   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,