import gdb-1999-06-21 snapshot
[external/binutils.git] / gas / write.c
index 80616d6..d0a9ac6 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 1998
+   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 96, 97, 98, 1999
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -186,6 +186,11 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
   fixP->fx_no_overflow = 0;
   fixP->fx_signed = 0;
 
+#ifdef USING_CGEN
+  fixP->fx_cgen.insn = NULL;
+  fixP->fx_cgen.opinfo = 0;
+#endif
+
 #ifdef TC_FIX_TYPE
   TC_INIT_FIX_DATA(fixP);
 #endif
@@ -714,39 +719,43 @@ adjust_reloc_syms (abfd, sec, xxx)
           point.  It is possible to see unresolved expression
           symbols, though, since they are not in the regular symbol
           table.  */
-       if (sym != NULL && ! sym->sy_resolved)
+       if (sym != NULL)
          resolve_symbol_value (sym, 1);
-       if (fixp->fx_subsy != NULL && ! fixp->fx_subsy->sy_resolved)
+       
+       if (fixp->fx_subsy != NULL)
          resolve_symbol_value (fixp->fx_subsy, 1);
 
        /* If this symbol is equated to an undefined symbol, convert
            the fixup to being against that symbol.  */
-       if (sym->sy_value.X_op == O_symbol
+       if (sym != NULL && symbol_equated_p (sym)
            && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
          {
-           fixp->fx_offset += sym->sy_value.X_add_number;
-           sym = sym->sy_value.X_add_symbol;
+           fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
+           sym = symbol_get_value_expression (sym)->X_add_symbol;
            fixp->fx_addsy = sym;
          }
 
-       symsec = S_GET_SEGMENT (sym);
-
-       if (sym != NULL && sym->sy_mri_common)
+       if (sym != NULL && symbol_mri_common_p (sym))
          {
            /* These symbols are handled specially in fixup_segment.  */
            goto done;
          }
 
+       symsec = S_GET_SEGMENT (sym);
+
+       if (symsec == NULL)
+         abort ();
+       
        if (bfd_is_abs_section (symsec))
          {
            /* The fixup_segment routine will not use this symbol in a
                relocation unless TC_FORCE_RELOCATION returns 1.  */
            if (TC_FORCE_RELOCATION (fixp))
              {
-               fixp->fx_addsy->sy_used_in_reloc = 1;
+               symbol_mark_used_in_reloc (fixp->fx_addsy);
 #ifdef UNDEFINED_DIFFERENCE_OK
                if (fixp->fx_subsy != NULL)
-                 fixp->fx_subsy->sy_used_in_reloc = 1;
+                 symbol_mark_used_in_reloc (fixp->fx_subsy);
 #endif
              }
            goto done;
@@ -760,22 +769,22 @@ adjust_reloc_syms (abfd, sec, xxx)
        if (bfd_is_und_section (symsec)
            || bfd_is_com_section (symsec))
          {
-           fixp->fx_addsy->sy_used_in_reloc = 1;
+           symbol_mark_used_in_reloc (fixp->fx_addsy);
 #ifdef UNDEFINED_DIFFERENCE_OK
            /* We have the difference of an undefined symbol and some
               other symbol.  Make sure to mark the other symbol as used
               in a relocation so that it will always be output.  */
            if (fixp->fx_subsy)
-             fixp->fx_subsy->sy_used_in_reloc = 1;
+             symbol_mark_used_in_reloc (fixp->fx_subsy);
 #endif
            goto done;
          }
 
-       /* Don't try to reduce relocs which refer to .linkonce
-           sections.  It can lead to confusion when a debugging
-           section refers to a .linkonce section.  I hope this will
-           always be correct.  */
-       if (symsec != sec)
+       /* Don't try to reduce relocs which refer to non-local symbols
+           in .linkonce sections.  It can lead to confusion when a
+           debugging section refers to a .linkonce section.  I hope
+           this will always be correct.  */
+       if (symsec != sec && ! S_IS_LOCAL (sym))
          {
            boolean linkonce;
 
@@ -796,10 +805,10 @@ adjust_reloc_syms (abfd, sec, xxx)
 
            if (linkonce)
              {
-               fixp->fx_addsy->sy_used_in_reloc = 1;
+               symbol_mark_used_in_reloc (fixp->fx_addsy);
 #ifdef UNDEFINED_DIFFERENCE_OK
                if (fixp->fx_subsy != NULL)
-                 fixp->fx_subsy->sy_used_in_reloc = 1;
+                 symbol_mark_used_in_reloc (fixp->fx_subsy);
 #endif
                goto done;
              }
@@ -807,18 +816,30 @@ adjust_reloc_syms (abfd, sec, xxx)
 
        /* Since we're reducing to section symbols, don't attempt to reduce
           anything that's already using one.  */
-       if (sym->bsym->flags & BSF_SECTION_SYM)
+       if (symbol_section_p (sym))
          {
-           fixp->fx_addsy->sy_used_in_reloc = 1;
+           symbol_mark_used_in_reloc (fixp->fx_addsy);
            goto done;
          }
 
+#ifdef BFD_ASSEMBLER
+       /* We can never adjust a reloc against a weak symbol.  If we
+           did, and the weak symbol was overridden by a real symbol
+           somewhere else, then our relocation would be pointing at
+           the wrong area of memory.  */
+       if (S_IS_WEAK (sym))
+         {
+           symbol_mark_used_in_reloc (fixp->fx_addsy);
+           goto done;
+         }
+#endif
+
        /* Is there some other reason we can't adjust this one?  (E.g.,
           call/bal links in i960-bout symbols.)  */
 #ifdef obj_fix_adjustable
        if (! obj_fix_adjustable (fixp))
          {
-           fixp->fx_addsy->sy_used_in_reloc = 1;
+           symbol_mark_used_in_reloc (fixp->fx_addsy);
            goto done;
          }
 #endif
@@ -829,7 +850,7 @@ adjust_reloc_syms (abfd, sec, xxx)
 #ifdef tc_fix_adjustable
        if (! tc_fix_adjustable (fixp))
          {
-           fixp->fx_addsy->sy_used_in_reloc = 1;
+           symbol_mark_used_in_reloc (fixp->fx_addsy);
            goto done;
          }
 #endif
@@ -843,7 +864,7 @@ adjust_reloc_syms (abfd, sec, xxx)
           the section when it calls resolve_symbol_value. */
        fixp->fx_offset += S_GET_VALUE (sym);
        fixp->fx_addsy = section_symbol (S_GET_SEGMENT (sym));
-       fixp->fx_addsy->sy_used_in_reloc = 1;
+       symbol_mark_used_in_reloc (fixp->fx_addsy);
 
       done:
        ;
@@ -910,17 +931,17 @@ write_relocs (abfd, sec, xxx)
          symbol, then use generate the reloc against the latter symbol
          rather than the former.  */
       sym = fixp->fx_addsy;
-      while (sym->sy_value.X_op == O_symbol
+      while (symbol_equated_p (sym)
             && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
        {
          symbolS *n;
 
          /* We must avoid looping, as that can occur with a badly
             written program.  */
-         n = sym->sy_value.X_add_symbol;
+         n = symbol_get_value_expression (sym)->X_add_symbol;
          if (n == sym)
            break;
-         fixp->fx_offset += sym->sy_value.X_add_number;
+         fixp->fx_offset += symbol_get_value_expression (sym)->X_add_number;
          sym = n;
        }
       fixp->fx_addsy = sym;
@@ -950,9 +971,12 @@ write_relocs (abfd, sec, xxx)
        case bfd_reloc_overflow:
          as_bad_where (fixp->fx_file, fixp->fx_line, _("relocation overflow"));
          break;
+       case bfd_reloc_outofrange:
+         as_bad_where (fixp->fx_file, fixp->fx_line, _("relocation out of range"));
+         break;
        default:
-         as_fatal (_("%s:%u: bad return from bfd_install_relocation"),
-                   fixp->fx_file, fixp->fx_line);
+         as_fatal (_("%s:%u: bad return from bfd_install_relocation: %x"),
+                   fixp->fx_file, fixp->fx_line, s);
        }
       relocs[i++] = reloc;
     }
@@ -980,9 +1004,9 @@ write_relocs (abfd, sec, xxx)
          symbol, then use generate the reloc against the latter symbol
          rather than the former.  */
       sym = fixp->fx_addsy;
-      while (sym->sy_value.X_op == O_symbol
+      while (symbol_equated_p (sym)
             && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
-       sym = sym->sy_value.X_add_symbol;
+       sym = symbol_get_value_expression (sym)->X_add_symbol;
       fixp->fx_addsy = sym;
 
       reloc = tc_gen_reloc (sec, fixp);
@@ -1309,8 +1333,8 @@ set_symtab ()
       symp = symbol_rootP;
       for (i = 0; i < nsyms; i++, symp = symbol_next (symp))
        {
-         asympp[i] = symp->bsym;
-         symp->written = 1;
+         asympp[i] = symbol_get_bfdsym (symp);
+         symbol_mark_written (symp);
        }
     }
   else
@@ -1343,7 +1367,13 @@ subsegs_finish ()
   for (frchainP = frchain_root; frchainP; frchainP = frchainP->frch_next)
     {
       subseg_set (frchainP->frch_seg, frchainP->frch_subseg);
-      frag_align (SUB_SEGMENT_ALIGN (now_seg), NOP_OPCODE, 0);
+
+      /* 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.  */
+      frag_align (had_errors () ? 0 : SUB_SEGMENT_ALIGN (now_seg),
+                 subseg_text_p (now_seg) ? NOP_OPCODE : 0,
+                 0);
 
       /* frag_align will have left a new frag.
         Use this last frag for an empty ".fill".
@@ -1522,6 +1552,7 @@ write_object_file ()
        {
          expressionS exp;
 
+         subseg_change (lie->seg, lie->subseg);
          exp.X_op = O_subtract;
          exp.X_add_symbol = lie->add;
          exp.X_op_symbol = lie->sub;
@@ -1566,6 +1597,7 @@ write_object_file ()
        addressT from_addr, to_addr;
        int n, m;
 
+       subseg_change (lie->seg, lie->subseg);
        fragP = lie->dispfrag;
 
        /* Find out how many broken_words go here.  */
@@ -1592,7 +1624,7 @@ write_object_file ()
            /* This is the offset from ??? to table_ptr+0 */
            to_addr = table_addr - S_GET_VALUE (lie->sub);
 #ifdef BFD_ASSEMBLER
-           to_addr -= lie->sub->sy_frag->fr_address;
+           to_addr -= symbol_get_frag (lie->sub)->fr_address;
 #endif
            md_number_to_chars (lie->word_goes_here, to_addr, 2);
            for (untruth = lie->next_broken_word; untruth && untruth->dispfrag == fragP; untruth = untruth->next_broken_word)
@@ -1606,7 +1638,7 @@ write_object_file ()
            from_addr = table_addr;
            to_addr = S_GET_VALUE (lie->add) + lie->addnum;
 #ifdef BFD_ASSEMBLER
-           to_addr += lie->add->sy_frag->fr_address;
+           to_addr += symbol_get_frag (lie->add)->fr_address;
 #endif
            md_create_long_jump (table_ptr, from_addr, to_addr, lie->dispfrag, lie->add);
            table_ptr += md_long_jump_size;
@@ -1739,9 +1771,9 @@ write_object_file ()
       symbolS *symp;
 
       for (symp = symbol_rootP; symp; symp = symbol_next (symp))
-       if (!symp->sy_resolved)
-         resolve_symbol_value (symp, 1);
+       resolve_symbol_value (symp, 1);
     }
+  resolve_local_symbol_values ();
 
   PROGRESS (1);
 
@@ -1764,7 +1796,7 @@ write_object_file ()
          int punt = 0;
          const char *name;
 
-         if (symp->sy_mri_common)
+         if (symbol_mri_common_p (symp))
            {
              if (S_IS_EXTERNAL (symp))
                as_bad (_("%s: global symbols not supported in common sections"),
@@ -1786,23 +1818,11 @@ write_object_file ()
          /* Do it again, because adjust_reloc_syms might introduce
             more symbols.  They'll probably only be section symbols,
             but they'll still need to have the values computed.  */
-         if (! symp->sy_resolved)
-           {
-             if (symp->sy_value.X_op == O_constant)
-               {
-                 /* This is the normal case; skip the call.  */
-                 S_SET_VALUE (symp,
-                              (S_GET_VALUE (symp)
-                               + symp->sy_frag->fr_address));
-                 symp->sy_resolved = 1;
-               }
-             else
-               resolve_symbol_value (symp, 1);
-           }
+         resolve_symbol_value (symp, 1);
 
          /* Skip symbols which were equated to undefined or common
              symbols.  */
-         if (symp->sy_value.X_op == O_symbol
+         if (symbol_equated_p (symp)
              && (! S_IS_DEFINED (symp) || S_IS_COMMON (symp)))
            {
              symbol_remove (symp, &symbol_rootP, &symbol_lastP);
@@ -1818,15 +1838,15 @@ write_object_file ()
          printf ("symbol `%s'\n\t@%x: value=%d flags=%x seg=%s\n",
                  S_GET_NAME (symp), symp,
                  S_GET_VALUE (symp),
-                 symp->bsym->flags,
-                 segment_name (symp->bsym->section));
+                 symbol_get_bfdsym (symp)->flags,
+                 segment_name (S_GET_SEGMENT (symp)));
 #endif
 
 #ifdef obj_frob_symbol
          obj_frob_symbol (symp, punt);
 #endif
 #ifdef tc_frob_symbol
-         if (! punt || symp->sy_used_in_reloc)
+         if (! punt || symbol_used_in_reloc_p (symp))
            tc_frob_symbol (symp, punt);
 #endif
 
@@ -1836,13 +1856,13 @@ write_object_file ()
             and symbols that the frob_symbol macros told us to punt,
             but we keep such symbols if they are used in relocs.  */
          if ((! EMIT_SECTION_SYMBOLS
-              && (symp->bsym->flags & BSF_SECTION_SYM) != 0)
+              && symbol_section_p (symp))
              /* Note that S_IS_EXTERN 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_LOCAL (symp) || punt)
-                 && ! symp->sy_used_in_reloc))
+                 && ! symbol_used_in_reloc_p (symp)))
            {
              symbol_remove (symp, &symbol_rootP, &symbol_lastP);
              /* After symbol_remove, symbol_next(symp) still returns
@@ -1853,16 +1873,16 @@ write_object_file ()
            }
 
          /* Make sure we really got a value for the symbol.  */
-         if (! symp->sy_resolved)
+         if (! symbol_resolved_p (symp))
            {
              as_bad (_("can't resolve value for symbol \"%s\""),
                      S_GET_NAME (symp));
-             symp->sy_resolved = 1;
+             symbol_mark_resolved (symp);
            }
 
          /* Set the value into the BFD symbol.  Up til now the value
             has only been kept in the gas symbolS struct.  */
-         symp->bsym->value = S_GET_VALUE (symp);
+         symbol_get_bfdsym (symp)->value = S_GET_VALUE (symp);
        }
     }
 
@@ -1971,9 +1991,7 @@ relax_frag (fragP, stretch)
 #endif
       know (!(S_GET_SEGMENT (symbolP) == absolute_section)
            || symbolP->sy_frag == &zero_address_frag);
-      target +=
-       S_GET_VALUE (symbolP)
-         + symbolP->sy_frag->fr_address;
+      target +=        S_GET_VALUE (symbolP) + symbol_get_frag (symbolP)->fr_address;
 
       /* If frag has yet to be reached on this pass,
         assume it will move by STRETCH just as we did.
@@ -1984,8 +2002,8 @@ relax_frag (fragP, stretch)
 
         There should be a faster way to do this.  */
 
-      if (symbolP->sy_frag->fr_address >= was_address
-         && is_dnrange (fragP, symbolP->sy_frag))
+      if (symbol_get_frag (symbolP)->fr_address >= was_address
+         && is_dnrange (fragP, symbol_get_frag (symbolP)))
        {
          target += stretch;
        }
@@ -2194,10 +2212,10 @@ relax_segment (segment_frag_root, segment)
                      if (lie->added)
                        continue;
 
-                     offset = (lie->add->sy_frag->fr_address
+                     offset = (symbol_get_frag (lie->add)->fr_address
                                + S_GET_VALUE (lie->add)
                                + lie->addnum
-                               - (lie->sub->sy_frag->fr_address
+                               - (symbol_get_frag (lie->sub)->fr_address
                                   + S_GET_VALUE (lie->sub)));
                      if (offset <= -32768 || offset >= 32767)
                        {
@@ -2219,8 +2237,10 @@ relax_segment (segment_frag_root, segment)
                          for (untruth = lie->next_broken_word;
                               untruth && untruth->dispfrag == lie->dispfrag;
                               untruth = untruth->next_broken_word)
-                           if ((untruth->add->sy_frag == lie->add->sy_frag)
-                               && S_GET_VALUE (untruth->add) == S_GET_VALUE (lie->add))
+                           if ((symbol_get_frag (untruth->add)
+                                == symbol_get_frag (lie->add))
+                               && (S_GET_VALUE (untruth->add)
+                                   == S_GET_VALUE (lie->add)))
                              {
                                untruth->added = 2;
                                untruth->use_jump = lie;
@@ -2270,8 +2290,8 @@ relax_segment (segment_frag_root, segment)
                      know (!(S_GET_SEGMENT (symbolP) == SEG_ABSOLUTE)
                            || (symbolP->sy_frag == &zero_address_frag));
 #endif
-                     target += S_GET_VALUE (symbolP)
-                       + symbolP->sy_frag->fr_address;
+                     target += (S_GET_VALUE (symbolP)
+                                + symbol_get_frag (symbolP)->fr_address);
                    }           /* if we have a symbol */
 
                  know (fragP->fr_next);
@@ -2294,7 +2314,7 @@ relax_segment (segment_frag_root, segment)
                if (symbolP)
                  {
                    growth = S_GET_VALUE (symbolP);
-                   if (symbolP->sy_frag != &zero_address_frag
+                   if (symbol_get_frag (symbolP) != &zero_address_frag
                        || S_IS_COMMON (symbolP)
                        || ! S_IS_DEFINED (symbolP))
                      as_bad_where (fragP->fr_file, fragP->fr_line,
@@ -2412,11 +2432,13 @@ fixup_segment (fixP, this_segment_type)
 
   for (; fixP; fixP = fixP->fx_next)
     {
+
 #ifdef DEBUG5
       fprintf (stderr, "\nprocessing fixup:\n");
       print_fixup (fixP);
 #endif
 
+
       fragP = fixP->fx_frag;
       know (fragP);
       where = fixP->fx_where;
@@ -2432,12 +2454,13 @@ fixup_segment (fixP, this_segment_type)
       plt = fixP->fx_plt;
 
       if (add_symbolP != NULL
-         && add_symbolP->sy_mri_common)
+         && symbol_mri_common_p (add_symbolP))
        {
          know (add_symbolP->sy_value.X_op == O_symbol);
          add_number += S_GET_VALUE (add_symbolP);
          fixP->fx_offset = add_number;
-         add_symbolP = fixP->fx_addsy = add_symbolP->sy_value.X_add_symbol;
+         add_symbolP = fixP->fx_addsy =
+           symbol_get_value_expression (add_symbolP)->X_add_symbol;
        }
 
       if (add_symbolP)
@@ -2550,7 +2573,7 @@ fixup_segment (fixP, this_segment_type)
                  char buf[50];
                  sprint_value (buf, fragP->fr_address + where);
                  as_bad_where (fixP->fx_file, fixP->fx_line,
-                               _("Subtraction of two symbols in different segments \"%s\" {%s segment} - \"%s\" {%s segment} at file address %s."),
+                               _("Subtraction of two symbols in different sections \"%s\" {%s section} - \"%s\" {%s section} at file address %s."),
                                S_GET_NAME (add_symbolP),
                                segment_name (S_GET_SEGMENT (add_symbolP)),
                                S_GET_NAME (sub_symbolP),
@@ -2648,11 +2671,15 @@ fixup_segment (fixP, this_segment_type)
                  seg_reloc_count++;
 #if !(defined (TC_V850) && defined (OBJ_ELF))
 #if !(defined (TC_M68K) && defined (OBJ_ELF))
+#if !(defined (TC_ARM)  && defined (OBJ_ELF))
+#if !(defined (TC_I960) && defined (OBJ_ELF))
 #if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF)) || defined (TE_PE)
                  add_number += S_GET_VALUE (add_symbolP);
 #endif
 #endif
 #endif
+#endif
+#endif
                }
            }
        }
@@ -2667,11 +2694,32 @@ fixup_segment (fixP, this_segment_type)
 #else
              fixP->fx_addsy = section_symbol (absolute_section);
 #endif
-             fixP->fx_addsy->sy_used_in_reloc = 1;
+             symbol_mark_used_in_reloc (fixP->fx_addsy);
              ++seg_reloc_count;
            }
        }
 
+      if (!fixP->fx_done)
+       {
+#ifdef MD_APPLY_FIX3
+         md_apply_fix3 (fixP, &add_number, this_segment_type);
+#else
+#ifdef BFD_ASSEMBLER
+         md_apply_fix (fixP, &add_number);
+#else
+         md_apply_fix (fixP, add_number);
+#endif
+#endif
+
+#ifndef TC_HANDLES_FX_DONE
+         /* If the tc-* files haven't been converted, assume it's handling
+            it the old way, where a null fx_addsy means that the fix has
+            been applied completely, and no further work is needed.  */
+         if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
+           fixP->fx_done = 1;
+#endif
+       }
+
       if (!fixP->fx_bit_fixP && !fixP->fx_no_overflow && size > 0)
        {
          if ((size_t) size < sizeof (valueT))
@@ -2720,26 +2768,6 @@ fixup_segment (fixP, this_segment_type)
 #endif
        }                       /* not a bit fix */
 
-      if (!fixP->fx_done)
-       {
-#ifdef MD_APPLY_FIX3
-         md_apply_fix3 (fixP, &add_number, this_segment_type);
-#else
-#ifdef BFD_ASSEMBLER
-         md_apply_fix (fixP, &add_number);
-#else
-         md_apply_fix (fixP, add_number);
-#endif
-#endif
-
-#ifndef TC_HANDLES_FX_DONE
-         /* If the tc-* files haven't been converted, assume it's handling
-            it the old way, where a null fx_addsy means that the fix has
-            been applied completely, and no further work is needed.  */
-         if (fixP->fx_addsy == 0 && fixP->fx_pcrel == 0)
-           fixP->fx_done = 1;
-#endif
-       }
 #ifdef TC_VALIDATE_FIX
     skip: ;
 #endif
@@ -2789,7 +2817,7 @@ void
 write_print_statistics (file)
      FILE *file;
 {
-  fprintf (stderr, "fixups: %d\n", n_fixups);
+  fprintf (file, "fixups: %d\n", n_fixups);
 }
 
 /* for debugging */