* ppc.h (R_PPC_RELAX32, R_PPC_RELAX32PC, R_PPC_RELAX32_PLT,
[deliverable/binutils-gdb.git] / gas / write.c
index 320e359fb9a9df8f25aa5cb599c95bda1c781229..7f4e2d57c782cea7637a376596dc476abf3a26d6 100644 (file)
@@ -1,6 +1,6 @@
 /* write.c - emit .o file
    Copyright 1986, 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997,
-   1998, 1999, 2000, 2001, 2002, 2003, 2004
+   1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 /* This thing should be set up to do byteordering correctly.  But...  */
 
 #define MD_PCREL_FROM_SECTION(FIX, SEC) md_pcrel_from (FIX)
 #endif
 
+#ifndef TC_FAKE_LABEL
+#define TC_FAKE_LABEL(NAME) (strcmp ((NAME), FAKE_LABEL_NAME) == 0)
+#endif
+
 /* Used to control final evaluation of expressions.  */
 int finalize_syms = 0;
 
@@ -787,12 +791,20 @@ adjust_reloc_syms (bfd *abfd ATTRIBUTE_UNUSED,
        if (fixp->fx_subsy != NULL)
          resolve_symbol_value (fixp->fx_subsy);
 
-       /* If this symbol is equated to an undefined symbol, convert
-           the fixup to being against that symbol.  */
+       /* If this symbol is equated to an undefined or common symbol,
+          convert the fixup to being against that symbol.  */
        if (symbol_equated_reloc_p (sym))
          {
+           symbolS *new_sym
+             = symbol_get_value_expression (sym)->X_add_symbol;
+           const char *name = S_GET_NAME (sym);
+           if (!S_IS_COMMON (new_sym)
+               && !TC_FAKE_LABEL (name)
+               && (!S_IS_EXTERNAL (sym) || S_IS_LOCAL (sym)))
+             as_bad (_("Local symbol `%s' can't be equated to undefined symbol `%s'"),
+                     name, S_GET_NAME (new_sym));
            fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
-           sym = symbol_get_value_expression (sym)->X_add_symbol;
+           sym = new_sym;
            fixp->fx_addsy = sym;
          }
 
@@ -1463,20 +1475,11 @@ write_object_file (void)
 #ifdef BFD_ASSEMBLER
   /* Remove the sections created by gas for its own purposes.  */
   {
-    asection **seclist;
     int i;
 
-    seclist = &stdoutput->sections;
-    while (*seclist)
-      {
-       if (*seclist == reg_section || *seclist == expr_section)
-         {
-           bfd_section_list_remove (stdoutput, seclist);
-           stdoutput->section_count--;
-         }
-       else
-         seclist = &(*seclist)->next;
-      }
+    bfd_section_list_remove (stdoutput, reg_section);
+    bfd_section_list_remove (stdoutput, expr_section);
+    stdoutput->section_count -= 2;
     i = 0;
     bfd_map_over_sections (stdoutput, renumber_sections, &i);
   }
@@ -1569,11 +1572,11 @@ write_object_file (void)
      Count the number of string-table chars we will emit.
      Put this info into the headers as appropriate.  */
   know (zero_address_frag.fr_address == 0);
-  string_byte_count = sizeof (string_byte_count);
+  string_byte_count = 4;
 
   obj_crawl_symbol_chain (&headers);
 
-  if (string_byte_count == sizeof (string_byte_count))
+  if (string_byte_count == 4)
     string_byte_count = 0;
 
   H_SET_STRING_SIZE (&headers, string_byte_count);
@@ -1882,12 +1885,22 @@ write_object_file (void)
   if (symbol_rootP)
     {
       symbolS *symp;
+      bfd_boolean skip_next_symbol = FALSE;
 
       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
        {
          int punt = 0;
          const char *name;
 
+         if (skip_next_symbol)
+           {
+             /* 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;
+             continue;
+           }
+
          if (symbol_mri_common_p (symp))
            {
              if (S_IS_EXTERNAL (symp))
@@ -1917,9 +1930,15 @@ write_object_file (void)
              symbols.  */
          if (symbol_equated_reloc_p (symp))
            {
-             if (S_IS_COMMON (symp))
-               as_bad (_("`%s' can't be equated to common symbol"),
-                       S_GET_NAME (symp));
+             const char *name = S_GET_NAME (symp);
+             if (S_IS_COMMON (symp)
+                 && !TC_FAKE_LABEL (name)
+                 && (!S_IS_EXTERNAL (symp) || S_IS_LOCAL (symp)))
+               {
+                 expressionS *e = symbol_get_value_expression (symp);
+                 as_bad (_("Local symbol `%s' can't be equated to common symbol `%s'"),
+                         name, S_GET_NAME (e->X_add_symbol));
+               }
              symbol_remove (symp, &symbol_rootP, &symbol_lastP);
              continue;
            }
@@ -1946,10 +1965,10 @@ write_object_file (void)
          if (symp == abs_section_sym
              || (! EMIT_SECTION_SYMBOLS
                  && symbol_section_p (symp))
-             /* Note that S_IS_EXTERN and S_IS_LOCAL are not always
+             /* Note that S_IS_EXTERNAL and S_IS_LOCAL are not always
                 opposites.  Sometimes the former checks flags and the
                 latter examines the name...  */
-             || (!S_IS_EXTERN (symp)
+             || (!S_IS_EXTERNAL (symp)
                  && (punt || S_IS_LOCAL (symp))
                  && ! symbol_used_in_reloc_p (symp)))
            {
@@ -1972,6 +1991,12 @@ write_object_file (void)
          /* Set the value into the BFD symbol.  Up til now the value
             has only been kept in the gas symbolS struct.  */
          symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
+
+         /* A warning construct is a warning symbol followed by the
+            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;
        }
     }
 
@@ -2379,7 +2404,9 @@ relax_segment (struct frag *segment_frag_root, segT segment)
                          into the section.  Here it is assumed that the
                          section's VMA is zero, and can omit subtracting it
                          from the symbol's value to get the address offset.  */
-                      know (S_GET_SECTION (symbolP)->vma == 0);
+#ifdef BFD_ASSEMBLER
+                      know (S_GET_SEGMENT (symbolP)->vma == 0);
+#endif
                      target += S_GET_VALUE (symbolP) * OCTETS_PER_BYTE;
                    }
 
@@ -2567,7 +2594,6 @@ fixup_segment (fixS *fixP, segT this_segment)
       if (fixP->fx_addsy != NULL
          && symbol_mri_common_p (fixP->fx_addsy))
        {
-         know (fixP->fx_addsy->sy_value.X_op == O_symbol);
          add_number += S_GET_VALUE (fixP->fx_addsy);
          fixP->fx_offset = add_number;
          fixP->fx_addsy
This page took 0.027476 seconds and 4 git commands to generate.