x86: properly force / avoid forcing EVEX encoding
[deliverable/binutils-gdb.git] / gas / write.c
index 9a99a0f5ae740a330fdaa6ca455759e31ae75907..2d0bbe4601d3599339d6fee5c0ebad1cd79a5193 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986-2017 Free Software Foundation, Inc.
+   Copyright (C) 1986-2018 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
   (TC_FORCE_RELOCATION (FIX))
 #endif
 
-#ifndef TC_FORCE_RELOCATION_LOCAL
-#define TC_FORCE_RELOCATION_LOCAL(FIX)         \
+#define GENERIC_FORCE_RELOCATION_LOCAL(FIX)    \
   (!(FIX)->fx_pcrel                            \
    || TC_FORCE_RELOCATION (FIX))
+#ifndef TC_FORCE_RELOCATION_LOCAL
+#define TC_FORCE_RELOCATION_LOCAL GENERIC_FORCE_RELOCATION_LOCAL
 #endif
 
+#define GENERIC_FORCE_RELOCATION_SUB_SAME(FIX, SEG)    \
+  (!SEG_NORMAL (SEG))
 #ifndef TC_FORCE_RELOCATION_SUB_SAME
-#define TC_FORCE_RELOCATION_SUB_SAME(FIX, SEG) \
-  (! SEG_NORMAL (SEG))
+#define TC_FORCE_RELOCATION_SUB_SAME GENERIC_FORCE_RELOCATION_SUB_SAME
 #endif
 
 #ifndef md_register_arithmetic
@@ -433,6 +435,8 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
 {
   switch (fragP->fr_type)
     {
+    case rs_space_nop:
+      goto skip_align;
     case rs_align:
     case rs_align_code:
     case rs_align_test:
@@ -441,6 +445,7 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
 #ifdef HANDLE_ALIGN
       HANDLE_ALIGN (fragP);
 #endif
+skip_align:
       know (fragP->fr_next != NULL);
       fragP->fr_offset = (fragP->fr_next->fr_address
                          - fragP->fr_address
@@ -448,14 +453,18 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
       if (fragP->fr_offset < 0)
        {
          as_bad_where (fragP->fr_file, fragP->fr_line,
-                       _("attempt to .org/.space backwards? (%ld)"),
+                       _("attempt to .org/.space/.nops backwards? (%ld)"),
                        (long) fragP->fr_offset);
          fragP->fr_offset = 0;
        }
-      fragP->fr_type = rs_fill;
+      if (fragP->fr_type == rs_space_nop)
+       fragP->fr_type = rs_fill_nop;
+      else
+       fragP->fr_type = rs_fill;
       break;
 
     case rs_fill:
+    case rs_fill_nop:
       break;
 
     case rs_leb128:
@@ -463,6 +472,13 @@ cvt_frag_to_fill (segT sec ATTRIBUTE_UNUSED, fragS *fragP)
        valueT value = S_GET_VALUE (fragP->fr_symbol);
        int size;
 
+       if (!S_IS_DEFINED (fragP->fr_symbol))
+         {
+           as_bad_where (fragP->fr_file, fragP->fr_line,
+                         _("leb128 operand is an undefined symbol: %s"),
+                         S_GET_NAME (fragP->fr_symbol));
+         }
+
        size = output_leb128 (fragP->fr_literal + fragP->fr_fix, value,
                              fragP->fr_subtype);
 
@@ -715,7 +731,7 @@ resolve_reloc_expr_symbols (void)
              as_bad_where (r->file, r->line, _("invalid reloc expression"));
              sec = NULL;
            }
-         else if (sym != NULL)
+         else if (sym != NULL && sec != NULL)
            {
              /* Convert relocs against local symbols to refer to the
                 corresponding section symbol plus offset instead.  Keep
@@ -910,9 +926,7 @@ fixup_segment (fixS *fixP, segT this_segment)
   /* If the linker is doing the relaxing, we must not do any fixups.
 
      Well, strictly speaking that's not true -- we could do any that
-     are PC-relative and don't cross regions that could change size.
-     And for the i960 we might be able to turn callx/callj into bal
-     anyways in cases where we know the maximum displacement.  */
+     are PC-relative and don't cross regions that could change size.  */
   if (linkrelax && TC_LINKRELAX_FIXUP (this_segment))
     {
       for (; fixP; fixP = fixP->fx_next)
@@ -1097,7 +1111,11 @@ fixup_segment (fixS *fixP, segT this_segment)
                  else
                    sprintf (buf2, "%ld", (long) add_number);
                  as_bad_where (fixP->fx_file, fixP->fx_line,
-                               _("value of %s too large for field of %d bytes at %s"),
+                               ngettext ("value of %s too large for field "
+                                         "of %d byte at %s",
+                                         "value of %s too large for field "
+                                         "of %d bytes at %s",
+                                         fixP->fx_size),
                                buf2, fixP->fx_size, buf);
                } /* Generic error checking.  */
            }
@@ -1449,7 +1467,10 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   if (obstack_room (ob) < header_size)
     first_newf = frag_alloc (ob);
   if (obstack_room (ob) < header_size)
-    as_fatal (_("can't extend frag %u chars"), header_size);
+    as_fatal (ngettext ("can't extend frag %lu char",
+                       "can't extend frag %lu chars",
+                       (unsigned long) header_size),
+             (unsigned long) header_size);
   last_newf = first_newf;
   obstack_blank_fast (ob, header_size);
   last_newf->fr_type = rs_fill;
@@ -1554,6 +1575,20 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
     }
 }
 
+#ifndef md_generate_nops
+/* Genenerate COUNT bytes of no-op instructions to WHERE.  A target
+   backend must override this with proper no-op instructions.   */
+
+static void
+md_generate_nops (fragS *f ATTRIBUTE_UNUSED,
+                 char *where ATTRIBUTE_UNUSED,
+                 offsetT count ATTRIBUTE_UNUSED,
+                 int control ATTRIBUTE_UNUSED)
+{
+  as_bad (_("unimplemented .nops directive"));
+}
+#endif
+
 static void
 write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                asection *sec,
@@ -1577,22 +1612,52 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
       char *fill_literal;
       offsetT count;
 
-      gas_assert (f->fr_type == rs_fill);
+      gas_assert (f->fr_type == rs_fill || f->fr_type == rs_fill_nop);
       if (f->fr_fix)
        {
          x = bfd_set_section_contents (stdoutput, sec,
                                        f->fr_literal, (file_ptr) offset,
                                        (bfd_size_type) f->fr_fix);
          if (!x)
-           as_fatal (_("can't write %ld bytes to section %s of %s because: '%s'"),
-                     (long) f->fr_fix, sec->name,
-                     stdoutput->filename,
+           as_fatal (ngettext ("can't write %ld byte "
+                               "to section %s of %s: '%s'",
+                               "can't write %ld bytes "
+                               "to section %s of %s: '%s'",
+                               (long) f->fr_fix),
+                     (long) f->fr_fix,
+                     sec->name, stdoutput->filename,
                      bfd_errmsg (bfd_get_error ()));
          offset += f->fr_fix;
        }
-      fill_literal = f->fr_literal + f->fr_fix;
+
       fill_size = f->fr_var;
       count = f->fr_offset;
+      fill_literal = f->fr_literal + f->fr_fix;
+
+      if (f->fr_type == rs_fill_nop)
+       {
+         gas_assert (count >= 0 && fill_size == 1);
+         if (count > 0)
+           {
+             char *buf = xmalloc (count);
+             md_generate_nops (f, buf, count, *fill_literal);
+             x = bfd_set_section_contents
+               (stdoutput, sec, buf, (file_ptr) offset,
+                (bfd_size_type) count);
+             if (!x)
+               as_fatal (ngettext ("can't fill %ld byte "
+                                   "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 ()));
+             offset += count;
+             free (buf);
+           }
+         continue;
+       }
+
       gas_assert (count >= 0);
       if (fill_size && count)
        {
@@ -1607,9 +1672,13 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                                                (file_ptr) offset,
                                                (bfd_size_type) fill_size);
                  if (!x)
-                   as_fatal (_("can't fill %ld bytes in section %s of %s because '%s'"),
-                             (long) fill_size, sec->name,
-                             stdoutput->filename,
+                   as_fatal (ngettext ("can't fill %ld byte "
+                                       "in section %s of %s: '%s'",
+                                       "can't fill %ld bytes "
+                                       "in section %s of %s: '%s'",
+                                       (long) fill_size),
+                             (long) fill_size,
+                             sec->name, stdoutput->filename,
                              bfd_errmsg (bfd_get_error ()));
                  offset += fill_size;
                }
@@ -1639,9 +1708,13 @@ write_contents (bfd *abfd ATTRIBUTE_UNUSED,
                    (stdoutput, sec, buf, (file_ptr) offset,
                     (bfd_size_type) n_per_buf * fill_size);
                  if (!x)
-                   as_fatal (_("cannot fill %ld bytes in section %s of %s because: '%s'"),
-                             (long)(n_per_buf * fill_size), sec->name,
-                             stdoutput->filename,
+                   as_fatal (ngettext ("can't fill %ld byte "
+                                       "in section %s of %s: '%s'",
+                                       "can't fill %ld bytes "
+                                       "in section %s of %s: '%s'",
+                                       (long) (n_per_buf * fill_size)),
+                             (long) (n_per_buf * fill_size),
+                             sec->name, stdoutput->filename,
                              bfd_errmsg (bfd_get_error ()));
                  offset += n_per_buf * fill_size;
                }
@@ -1902,6 +1975,8 @@ write_object_file (void)
   /* Relaxation has completed.  Freeze all syms.  */
   finalize_syms = 1;
 
+  dwarf2dbg_final_check ();
+
 #ifdef md_post_relax_hook
   md_post_relax_hook;
 #endif
@@ -2096,12 +2171,11 @@ write_object_file (void)
 
              if (S_IS_COMMON (symp)
                  && !TC_FAKE_LABEL (sname)
-                 && !S_IS_WEAKREFR (symp)
-                 && (!S_IS_EXTERNAL (symp) || S_IS_LOCAL (symp)))
+                 && !S_IS_WEAKREFR (symp))
                {
                  expressionS *e = symbol_get_value_expression (symp);
 
-                 as_bad (_("Local symbol `%s' can't be equated to common symbol `%s'"),
+                 as_bad (_("`%s' can't be equated to common symbol `%s'"),
                          sname, S_GET_NAME (e->X_add_symbol));
                }
              if (S_GET_SEGMENT (symp) == reg_section)
@@ -2412,7 +2486,11 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
            if (offset % fragP->fr_var != 0)
              {
                as_bad_where (fragP->fr_file, fragP->fr_line,
-                             _("alignment padding (%lu bytes) not a multiple of %ld"),
+                             ngettext ("alignment padding (%lu byte) "
+                                       "not a multiple of %ld",
+                                       "alignment padding (%lu bytes) "
+                                       "not a multiple of %ld",
+                                       (unsigned long) offset),
                              (unsigned long) offset, (long) fragP->fr_var);
                offset -= (offset % fragP->fr_var);
              }
@@ -2428,6 +2506,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
          break;
 
        case rs_space:
+       case rs_space_nop:
          break;
 
        case rs_machine_dependent:
@@ -2692,7 +2771,11 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                  know (fragP->fr_next);
                  after = fragP->fr_next->fr_address + stretch;
                  growth = target - after;
-                 if (growth < 0)
+
+                 /* 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)
                    {
                      growth = 0;
 
@@ -2714,9 +2797,6 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                          break;
                        }
 
-                     /* Growth may be negative, but variable part of frag
-                        cannot have fewer than 0 chars.  That is, we can't
-                        .org backwards.  */
                      as_bad_where (fragP->fr_file, fragP->fr_line,
                                    _("attempt to move .org backwards"));
 
@@ -2731,6 +2811,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                break;
 
              case rs_space:
+             case rs_space_nop:
                growth = 0;
                if (symbolP)
                  {
@@ -2757,7 +2838,7 @@ relax_segment (struct frag *segment_frag_root, segT segment, int pass)
                          }
 
                        as_warn_where (fragP->fr_file, fragP->fr_line,
-                                      _(".space or .fill with negative value, ignored"));
+                                      _(".space, .nops or .fill with negative value, ignored"));
                        fragP->fr_symbol = 0;
                      }
                    else
This page took 0.027049 seconds and 4 git commands to generate.