PR22374 testcase, function pointer references in .data
[deliverable/binutils-gdb.git] / gas / write.c
index c965e6878562815dc2eddf0b2a789301b5898e94..df88905013b9d12ab82000a5d20b137dd7cc4362 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986-2016 Free Software Foundation, Inc.
+   Copyright (C) 1986-2017 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
    02110-1301, USA.  */
 
-/* This thing should be set up to do byteordering correctly.  But...  */
+/* This thing should be set up to do byte ordering correctly.  But...  */
 
 #include "as.h"
 #include "subsegs.h"
 #include "obstack.h"
 #include "output-file.h"
 #include "dwarf2dbg.h"
-#include "libbfd.h"
 #include "compress-debug.h"
 
 #ifndef TC_FORCE_RELOCATION
   (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
@@ -464,6 +465,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);
 
@@ -579,7 +587,12 @@ size_seg (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   x = bfd_set_section_flags (abfd, sec, flags);
   gas_assert (x);
 
-  newsize = md_section_align (sec, size);
+  /* If permitted, allow the backend to pad out the section
+     to some alignment boundary.  */
+  if (do_not_pad_sections_to_alignment)
+    newsize = size;
+  else
+    newsize = md_section_align (sec, size);
   x = bfd_set_section_size (abfd, sec, newsize);
   gas_assert (x);
 
@@ -711,7 +724,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
@@ -1234,7 +1247,7 @@ write_relocs (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
        rp = &r->next;
     }
 
-  relocs = (arelent **) xcalloc (n, sizeof (arelent *));
+  relocs = XCNEWVEC (arelent *, n);
 
   n = 0;
   r = my_reloc_list;
@@ -1454,7 +1467,7 @@ compress_debug (bfd *abfd, asection *sec, void *xxx ATTRIBUTE_UNUSED)
   compressed_size = header_size;
 
   /* Stream the frags through the compression engine, adding new frags
-     as necessary to accomodate the compressed output.  */
+     as necessary to accommodate the compressed output.  */
   for (f = seginfo->frchainP->frch_root;
        f;
        f = f->fr_next)
@@ -1696,7 +1709,7 @@ set_symtab (void)
 }
 
 /* Finish the subsegments.  After every sub-segment, we fake an
-   ".align ...".  This conforms to BSD4.2 brane-damage.  We then fake
+   ".align ...".  This conforms to BSD4.2 brain-damage.  We then fake
    ".fill 0" because that is the kind of frag that requires least
    thought.  ".align" frags like to have a following frag since that
    makes calculating their intended length trivial.  */
@@ -1708,6 +1721,7 @@ set_symtab (void)
    code-bearing sections.  */
 #define SUB_SEGMENT_ALIGN(SEG, FRCHAIN)                                        \
   (!(FRCHAIN)->frch_next && subseg_text_p (SEG)                                \
+   && !do_not_pad_sections_to_alignment                                        \
    ? get_recorded_alignment (SEG)                                      \
    : 0)
 #else
@@ -1727,31 +1741,31 @@ subsegs_finish_section (asection *s)
        frchainP != NULL;
        frchainP = frchainP->frch_next)
     {
-      int alignment = 0;
+      int alignment;
 
       subseg_set (s, frchainP->frch_subseg);
 
       /* This now gets called even if we had errors.  In that case,
         any alignment is meaningless, and, moreover, will look weird
         if we are generating a listing.  */
-      if (!had_errors ())
-       {
-         alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
-         if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
-             && now_seg->entsize)
-           {
-             unsigned int entsize = now_seg->entsize;
-             int entalign = 0;
+      if (had_errors ())
+       do_not_pad_sections_to_alignment = 1;
 
-             while ((entsize & 1) == 0)
-               {
-                 ++entalign;
-                 entsize >>= 1;
-               }
+      alignment = SUB_SEGMENT_ALIGN (now_seg, frchainP);
+      if ((bfd_get_section_flags (now_seg->owner, now_seg) & SEC_MERGE)
+         && now_seg->entsize)
+       {
+         unsigned int entsize = now_seg->entsize;
+         int entalign = 0;
 
-             if (entalign > alignment)
-               alignment = entalign;
+         while ((entsize & 1) == 0)
+           {
+             ++entalign;
+             entsize >>= 1;
            }
+
+         if (entalign > alignment)
+           alignment = entalign;
        }
 
       if (subseg_text_p (now_seg))
@@ -1830,7 +1844,7 @@ write_object_file (void)
 #endif
 
   /* From now on, we don't care about sub-segments.  Build one frag chain
-     for each segment. Linked thru fr_next.  */
+     for each segment. Linked through fr_next.  */
 
   /* Remove the sections created by gas for its own purposes.  */
   {
@@ -1897,6 +1911,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
@@ -2091,12 +2107,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)
@@ -2687,7 +2702,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;
 
@@ -2709,9 +2728,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"));
 
This page took 0.02757 seconds and 4 git commands to generate.