Mon Feb 12 15:16:29 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de>
authorIan Lance Taylor <ian@airs.com>
Mon, 12 Feb 1996 20:33:06 +0000 (20:33 +0000)
committerIan Lance Taylor <ian@airs.com>
Mon, 12 Feb 1996 20:33:06 +0000 (20:33 +0000)
Support for OBJ_ELF on m68k, mostly inside #ifdef OBJ_ELF:
* config/m68k-parse.h (enum pic_relocation): Define.
(struct m68k_exp): Add pic_reloc field.
* config/tc-m68k.h (TC_RELOC_RTSYM_LOC_FIXUP): Define.
(tc_fix_adjustable): Define to call tc_m68k_fix_adjustable.
(NO_RELOC): Define to BFD_RELOC_NONE if BFD_ASSEMBLER, to zero
otherwise.
* config/tc-m68k.c: Delete definition of NO_RELOC.
  (struct m68k_it): Add pic_reloc field.
(add_fix): Copy over pic_reloc field.
(md_pseudo_table): Interpret .align parameter as byte count.
(mote_pseudo_table): Likewise.
(tc_m68k_fix_adjustable): New function.
(get_reloc_code): New function.
(md_assemble): Use it as last argument to fix_new_exp.
(md_apply_fix_2): For a relocation against a symbol don't put the
addend into the data.
(tc_gen_reloc): Different addend computation for OBJ_ELF.
(m68k_ip): Don't relax an operand that requires pic relocation.
(md_begin): Align .text, .data and .bss on 4 byte boundary by
default.
* write.c (fixup_segment): Don't add symbol value to addend if
  TC_M68K and OBJ_ELF.
* config/m68k-parse.y (yylex): Handle @PLTPC, etc.
(motorola_operand): Add rule for `(zapc, EXPR)'.

gas/ChangeLog
gas/config/tc-m68k.c
gas/config/tc-m68k.h
gas/write.c

index 4452b4b083f27d124c094c7e5c79045a3f15fe71..cd321d55ed44b6e5701e2adc1966bf8eaeb61bbe 100644 (file)
@@ -1,3 +1,31 @@
+Mon Feb 12 15:16:29 1996  Andreas Schwab  <schwab@issan.informatik.uni-dortmund.de>
+
+       Support for OBJ_ELF on m68k, mostly inside #ifdef OBJ_ELF:
+       * config/m68k-parse.h (enum pic_relocation): Define.
+       (struct m68k_exp): Add pic_reloc field.
+       * config/tc-m68k.h (TC_RELOC_RTSYM_LOC_FIXUP): Define.
+       (tc_fix_adjustable): Define to call tc_m68k_fix_adjustable.
+       (NO_RELOC): Define to BFD_RELOC_NONE if BFD_ASSEMBLER, to zero
+       otherwise.
+       * config/tc-m68k.c: Delete definition of NO_RELOC.
+       (struct m68k_it): Add pic_reloc field.
+       (add_fix): Copy over pic_reloc field.
+       (md_pseudo_table): Interpret .align parameter as byte count.
+       (mote_pseudo_table): Likewise.
+       (tc_m68k_fix_adjustable): New function.
+       (get_reloc_code): New function.
+       (md_assemble): Use it as last argument to fix_new_exp.
+       (md_apply_fix_2): For a relocation against a symbol don't put the
+       addend into the data.
+       (tc_gen_reloc): Different addend computation for OBJ_ELF.
+       (m68k_ip): Don't relax an operand that requires pic relocation.
+       (md_begin): Align .text, .data and .bss on 4 byte boundary by
+       default.
+       * write.c (fixup_segment): Don't add symbol value to addend if
+       TC_M68K and OBJ_ELF.
+       * config/m68k-parse.y (yylex): Handle @PLTPC, etc.
+       (motorola_operand): Add rule for `(zapc, EXPR)'.
+
 Mon Feb 12 10:07:33 1996  David Mosberger-Tang  <davidm@azstarnet.com>
 
        * ecoff.c (ecoff_directive_weakext): Fixed so that whitespace
index fe6c9bd0c7dc0e2bd2a43c65eb2791cf258006ff..8b3128363e1358ff17a4d9ff788893e5acc8e987 100644 (file)
@@ -19,7 +19,6 @@
    02111-1307, USA.  */
 
 #include <ctype.h>
-#define  NO_RELOC 0
 #include "as.h"
 #include "obstack.h"
 #include "subsegs.h"
@@ -62,7 +61,8 @@ const int md_reloc_size = 8;  /* Size of relocation record */
 
 /* Are we trying to generate PIC code?  If so, absolute references
    ought to be made into linkage table references or pc-relative
-   references.  */
+   references.  Not implemented.  For ELF there are other means 
+   to denote pic relocations.  */
 int flag_want_pic;
 
 static int flag_short_refs;    /* -l option */
@@ -199,6 +199,11 @@ struct m68k_it
         significance of some values (in the branch instruction, for
         example).  */
       int pcrel_fix;
+#ifdef OBJ_ELF
+      /* Whether this expression needs special pic relocation, and if
+        so, which.  */
+      enum pic_relocation pic_reloc;
+#endif
     }
   reloc[5];                    /* Five is enough??? */
 };
@@ -252,6 +257,9 @@ add_fix (width, exp, pc_rel, pc_fix)
   the_ins.reloc[the_ins.nrel].exp = exp->exp;
   the_ins.reloc[the_ins.nrel].wid = width;
   the_ins.reloc[the_ins.nrel].pcrel_fix = pc_fix;
+#ifdef OBJ_ELF
+  the_ins.reloc[the_ins.nrel].pic_reloc = exp->pic_reloc;
+#endif
   the_ins.reloc[the_ins.nrel++].pcrel = pc_rel;
 }
 
@@ -428,7 +436,7 @@ const pseudo_typeS md_pseudo_table[] =
   {"even", s_even, 0},
   {"skip", s_space, 0},
   {"proc", s_proc, 0},
-#ifdef TE_SUN3
+#if defined (TE_SUN3) || defined (OBJ_ELF)
   {"align", s_align_bytes, 0},
 #endif
 #ifdef OBJ_ELF
@@ -500,7 +508,11 @@ CONST pseudo_typeS mote_pseudo_table[] =
   {"dsb", s_space, 1},
 
   {"xdef", s_globl, 0},
+#ifdef OBJ_ELF
+  {"align", s_align_bytes, 0},
+#else
   {"align", s_align_ptwo, 0},
+#endif
 #ifdef M68KCOFF
   {"sect", obj_coff_section, 0},
   {"section", obj_coff_section, 0},
@@ -585,6 +597,145 @@ tc_coff_fix2rtype (fixP)
 
 #endif
 
+#ifdef OBJ_ELF
+
+/* Compute the relocation code for a fixup of SIZE bytes, using pc
+   relative relocation if PCREL is non-zero.  PIC says whether a special
+   pic relocation was requested.  */
+
+static bfd_reloc_code_real_type get_reloc_code
+  PARAMS ((int, int, enum pic_relocation));
+
+static bfd_reloc_code_real_type
+get_reloc_code (size, pcrel, pic)
+     int size;
+     int pcrel;
+     enum pic_relocation pic;
+{
+  switch (pic)
+    {
+    case pic_got_pcrel:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_GOT_PCREL;
+       case 2:
+         return BFD_RELOC_16_GOT_PCREL;
+       case 4:
+         return BFD_RELOC_32_GOT_PCREL;
+       }
+      break;
+
+    case pic_got_off:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_GOTOFF;
+       case 2:
+         return BFD_RELOC_16_GOTOFF;
+       case 4:
+         return BFD_RELOC_32_GOTOFF;
+       }
+      break;
+
+    case pic_plt_pcrel:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_PLT_PCREL;
+       case 2:
+         return BFD_RELOC_16_PLT_PCREL;
+       case 4:
+         return BFD_RELOC_32_PLT_PCREL;
+       }
+      break;
+
+    case pic_plt_off:
+      switch (size)
+       {
+       case 1:
+         return BFD_RELOC_8_PLTOFF;
+       case 2:
+         return BFD_RELOC_16_PLTOFF;
+       case 4:
+         return BFD_RELOC_32_PLTOFF;
+       }
+      break;
+
+    case pic_none:
+      if (pcrel)
+       {
+         switch (size)
+           {
+           case 1:
+             return BFD_RELOC_8_PCREL;
+           case 2:
+             return BFD_RELOC_16_PCREL;
+           case 4:
+             return BFD_RELOC_32_PCREL;
+           }
+       }
+      else
+       {
+         switch (size)
+           {
+           case 1:
+             return BFD_RELOC_8;
+           case 2:
+             return BFD_RELOC_16;
+           case 4:
+             return BFD_RELOC_32;
+           }
+       }
+    }
+
+  as_bad ("Can not do %d byte %s%srelocation", size,
+         pcrel ? "pc-relative " : "",
+         pic == pic_none ? "" : "pic ");
+  return BFD_RELOC_NONE;
+}
+
+/* Here we decide which fixups can be adjusted to make them relative
+   to the beginning of the section instead of the symbol.  Basically
+   we need to make sure that the dynamic relocations are done
+   correctly, so in some cases we force the original symbol to be
+   used.  */
+int
+tc_m68k_fix_adjustable (fixP)
+     fixS *fixP;
+{
+  /* Prevent all adjustments to global symbols. */
+  if (S_IS_EXTERNAL (fixP->fx_addsy))
+    return 0;
+
+  /* adjust_reloc_syms doesn't know about the GOT */
+  switch (fixP->fx_r_type)
+    {
+    case BFD_RELOC_8_GOT_PCREL:
+    case BFD_RELOC_16_GOT_PCREL:
+    case BFD_RELOC_32_GOT_PCREL:
+    case BFD_RELOC_8_GOTOFF:
+    case BFD_RELOC_16_GOTOFF:
+    case BFD_RELOC_32_GOTOFF:
+    case BFD_RELOC_8_PLT_PCREL:
+    case BFD_RELOC_16_PLT_PCREL:
+    case BFD_RELOC_32_PLT_PCREL:
+    case BFD_RELOC_8_PLTOFF:
+    case BFD_RELOC_16_PLTOFF:
+    case BFD_RELOC_32_PLTOFF:
+      return 0;
+
+    default:
+      return 1;
+    }
+}
+
+#else /* !OBJ_ELF */
+
+#define get_reloc_code(SIZE,PCREL,OTHER) NO_RELOC
+
+#endif /* OBJ_ELF */
+
 #ifdef BFD_ASSEMBLER
 
 arelent *
@@ -598,28 +749,50 @@ tc_gen_reloc (section, fixp)
   if (fixp->fx_tcbit)
     abort ();
 
-#define F(SZ,PCREL)            (((SZ) << 1) + (PCREL))
-  switch (F (fixp->fx_size, fixp->fx_pcrel))
+  if (fixp->fx_r_type != BFD_RELOC_NONE)
+    code = fixp->fx_r_type;
+  else
     {
+#define F(SZ,PCREL)            (((SZ) << 1) + (PCREL))
+      switch (F (fixp->fx_size, fixp->fx_pcrel))
+       {
 #define MAP(SZ,PCREL,TYPE)     case F(SZ,PCREL): code = (TYPE); break
-      MAP (1, 0, BFD_RELOC_8);
-      MAP (2, 0, BFD_RELOC_16);
-      MAP (4, 0, BFD_RELOC_32);
-      MAP (1, 1, BFD_RELOC_8_PCREL);
-      MAP (2, 1, BFD_RELOC_16_PCREL);
-      MAP (4, 1, BFD_RELOC_32_PCREL);
-    default:
-      abort ();
+         MAP (1, 0, BFD_RELOC_8);
+         MAP (2, 0, BFD_RELOC_16);
+         MAP (4, 0, BFD_RELOC_32);
+         MAP (1, 1, BFD_RELOC_8_PCREL);
+         MAP (2, 1, BFD_RELOC_16_PCREL);
+         MAP (4, 1, BFD_RELOC_32_PCREL);
+       default:
+         abort ();
+       }
     }
+#undef F
+#undef MAP
 
   reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
   assert (reloc != 0);
   reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
   reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
+#ifndef OBJ_ELF
   if (fixp->fx_pcrel)
     reloc->addend = fixp->fx_addnumber;
   else
     reloc->addend = 0;
+#else
+  if (!fixp->fx_pcrel)
+    reloc->addend = fixp->fx_addnumber;
+  else if ((fixp->fx_addsy->bsym->flags & BSF_SECTION_SYM) != 0)
+    reloc->addend = (section->vma
+                    + (fixp->fx_pcrel_adjust == 64
+                       ? -1 : fixp->fx_pcrel_adjust)
+                    + fixp->fx_addnumber
+                    + md_pcrel_from (fixp));
+  else
+    reloc->addend = (fixp->fx_offset
+                    + (fixp->fx_pcrel_adjust == 64
+                       ? -1 : fixp->fx_pcrel_adjust));
+#endif
 
   reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
   assert (reloc->howto != 0);
@@ -1575,16 +1748,24 @@ m68k_ip (instring)
                    {
                      if (opP->reg == PC)
                        {
-#if 0
-                         addword (0x0170);
-                         add_fix ('l', &opP->disp, 1, 2);
-                         addword (0), addword (0);
-#else
-                         add_frag (adds (&opP->disp),
-                                   offs (&opP->disp),
-                                   TAB (PCLEA, SZ_UNDEF));
+                         if (opP->disp.size == SIZE_LONG
+#ifdef OBJ_ELF
+                             /* If the displacement needs pic
+                                relocation it cannot be relaxed.  */
+                             || opP->disp.pic_reloc != pic_none
 #endif
-                         break;
+                             )
+                           {
+                             addword (0x0170);
+                             add_fix ('l', &opP->disp, 1, 2);
+                           }
+                         else
+                           {
+                             add_frag (adds (&opP->disp),
+                                       offs (&opP->disp),
+                                       TAB (PCLEA, SZ_UNDEF));
+                             break;
+                           }
                        }
                      else
                        {
@@ -1730,7 +1911,13 @@ m68k_ip (instring)
                      else if (siz1 == SIZE_UNSPEC
                               && opP->reg == PC
                               && isvar (&opP->disp)
-                              && subs (&opP->disp) == NULL)
+                              && subs (&opP->disp) == NULL
+#ifdef OBJ_ELF
+                              /* If the displacement needs pic
+                                 relocation it cannot be relaxed.  */
+                              && opP->disp.pic_reloc == pic_none
+#endif
+                              )
                        {
                          nextword += baseo & 0xff;
                          addword (nextword);
@@ -1866,6 +2053,11 @@ m68k_ip (instring)
                  if (isvar (&opP->disp)
                      && !subs (&opP->disp)
                      && adds (&opP->disp)
+#ifdef OBJ_ELF
+                     /* If the displacement needs pic relocation it
+                        cannot be relaxed.  */
+                     && opP->disp.pic_reloc == pic_none
+#endif
                      && S_GET_SEGMENT (adds (&opP->disp)) == now_seg
                      && cpu_of_arch (current_architecture) >= m68020
                      && !flag_long_jumps
@@ -2005,6 +2197,13 @@ m68k_ip (instring)
              if (subs (&opP->disp))    /* We can't relax it */
                goto long_branch;
 
+#ifdef OBJ_ELF
+             /* If the displacement needs pic relocation it cannot be
+                relaxed.  */
+             if (opP->disp.pic_reloc != pic_none)
+               goto long_branch;
+#endif
+
              /* This could either be a symbol, or an absolute
                 address.  No matter, the frag hacking will finger it
                 out.  Not quite: it can't switch from BRANCH to
@@ -2938,7 +3137,8 @@ md_assemble (str)
                              n,
                              &the_ins.reloc[m].exp,
                              the_ins.reloc[m].pcrel,
-                             NO_RELOC);
+                             get_reloc_code (n, the_ins.reloc[m].pcrel,
+                                             the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
        }
       return;
@@ -2982,7 +3182,8 @@ md_assemble (str)
                              wid,
                              &the_ins.reloc[m].exp,
                              the_ins.reloc[m].pcrel,
-                             NO_RELOC);
+                             get_reloc_code (wid, the_ins.reloc[m].pcrel,
+                                             the_ins.reloc[m].pic_reloc));
          fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
        }
       (void) frag_var (rs_machine_dependent, 10, 0,
@@ -3018,7 +3219,8 @@ md_assemble (str)
                          wid,
                          &the_ins.reloc[m].exp,
                          the_ins.reloc[m].pcrel,
-                         NO_RELOC);
+                         get_reloc_code (wid, the_ins.reloc[m].pcrel,
+                                         the_ins.reloc[m].pic_reloc));
       fixP->fx_pcrel_adjust = the_ins.reloc[m].pcrel_fix;
     }
 }
@@ -3185,6 +3387,12 @@ md_begin ()
 #endif
 
   init_regtable ();
+
+#ifdef OBJ_ELF
+  record_alignment (text_section, 2);
+  record_alignment (data_section, 2);
+  record_alignment (bss_section, 2);
+#endif
 }
 
 void
@@ -3371,6 +3579,15 @@ md_apply_fix_2 (fixP, val)
   else
     val &= 0x7fffffff;
 
+#ifdef OBJ_ELF
+  if (fixP->fx_addsy)
+    {
+      memset (buf, 0, fixP->fx_size);
+      fixP->fx_addnumber = val;        /* Remember value for emit_reloc */
+      return;
+    }
+#endif
+
   switch (fixP->fx_size)
     {
       /* The cast to offsetT below are necessary to make code correct for
@@ -5974,8 +6191,14 @@ md_parse_option (c, arg)
       flag_reg_prefix_optional = 1;
       break;
 
-    case 'Q':
+      /* -V: SVR4 argument to print version ID.  */
     case 'V':
+      print_version_id ();
+      break;
+
+      /* -Qy, -Qn: SVR4 arguments controlling whether a .comment section
+        should be emitted or not.  FIXME: Not implemented.  */
+    case 'Q':
       break;
 
     default:
index 36abd6c2e974061078b681f5a499afe219da0359..3f99de9e69d0894515ac04da45c626dbdd41584e 100644 (file)
@@ -1,6 +1,7 @@
 /* This file is tc-m68k.h
 
-   Copyright (C) 1987-1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 89, 90, 91, 92, 93, 94, 95, 1996
+   Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
 
    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, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #define TC_M68K 1
 
+#define TARGET_BYTES_BIG_ENDIAN 1
+
 #ifdef OBJ_AOUT
+#ifdef TE_SUN3
 #define TARGET_FORMAT "a.out-sunos-big"
+#else
+#ifdef TE_NetBSD
+#define TARGET_FORMAT "a.out-m68k-netbsd"
+#else
+#define TARGET_FORMAT "a.out-zero-big"
+#endif
+#endif
+#endif
+
+#ifdef OBJ_ELF
+#define TARGET_FORMAT "elf32-m68k"
 #endif
 
 #ifdef TE_APOLLO
 #ifdef TE_LYNX
 #define TARGET_FORMAT          "coff-m68k-lynx"
 #endif
+#ifdef TE_AUX
+#define TARGET_FORMAT          "coff-m68k-aux"
+#endif
 
 #ifndef COFF_MAGIC
 #define COFF_MAGIC MC68MAGIC
 #endif
-#define BFD_ARCH bfd_arch_m68k
+#define BFD_ARCH bfd_arch_m68k /* for non-BFD_ASSEMBLER */
+#define TARGET_ARCH bfd_arch_m68k /* BFD_ASSEMBLER */
 #define COFF_FLAGS F_AR32W
 #define TC_COUNT_RELOC(x) ((x)->fx_addsy||(x)->fx_subsy)
 
 #define TC_COFF_FIX2RTYPE(fixP) tc_coff_fix2rtype(fixP)
 #define TC_COFF_SIZEMACHDEP(frag) tc_coff_sizemachdep(frag)
+extern int tc_coff_sizemachdep PARAMS ((struct frag *));
 #ifdef TE_SUN3
 /* This variable contains the value to write out at the beginning of
    the a.out file.  The 2<<16 means that this is a 68020 file instead
@@ -77,7 +97,7 @@ extern int m68k_aout_machtype;
 #endif
 
 #if !defined (REGISTER_PREFIX_OPTIONAL)
-#ifdef M68KCOFF
+#if defined (M68KCOFF) || defined (OBJ_ELF)
 #define LOCAL_LABEL(name) (name[0] == '.' \
                           && (name[1] == 'L' || name[1] == '.'))
 #define FAKE_LABEL_NAME ".L0\001"
@@ -92,11 +112,36 @@ extern int m68k_aout_machtype;
    can't be used as the initial character.  If that's not true, more
    work will be needed to fix this up.  */
 #define LEX_PCT 1
+/* On the Delta, dots are not required before pseudo-ops.  */
+#define NO_PSEUDO_DOT
 #endif
 
 #ifdef BFD_ASSEMBLER
+
 #define tc_frob_symbol(sym,punt) \
     if (S_GET_SEGMENT (sym) == reg_section) punt = 1
+
+#define NO_RELOC BFD_RELOC_NONE
+
+#ifdef OBJ_ELF
+
+/* This expression evaluates to false if the relocation is for a local object
+   for which we still want to do the relocation at runtime.  True if we
+   are willing to perform this relocation while building the .o file.  */
+
+#define TC_RELOC_RTSYM_LOC_FIXUP(FIX)                  \
+       ((FIX)->fx_r_type != BFD_RELOC_8_PLT_PCREL      \
+        && (FIX)->fx_r_type != BFD_RELOC_16_PLT_PCREL  \
+        && (FIX)->fx_r_type != BFD_RELOC_32_PLT_PCREL  \
+        && (FIX)->fx_r_type != BFD_RELOC_8_GOT_PCREL   \
+        && (FIX)->fx_r_type != BFD_RELOC_16_GOT_PCREL  \
+        && (FIX)->fx_r_type != BFD_RELOC_32_GOT_PCREL)
+
+#define tc_fix_adjustable(X) tc_m68k_fix_adjustable(X)
+#endif
+
+#else
+#define NO_RELOC 0
 #endif
 
 #define DIFF_EXPR_OK
@@ -107,4 +152,12 @@ extern void m68k_init_after_args PARAMS ((void));
 extern int m68k_parse_long_option PARAMS ((char *));
 #define md_parse_long_option m68k_parse_long_option
 
+#define md_operand(x)
+
+#define TARGET_WORD_SIZE 32
+#define TARGET_ARCH bfd_arch_m68k
+
+extern struct relax_type md_relax_table[];
+#define TC_GENERIC_RELAX_TABLE md_relax_table
+
 /* end of tc-m68k.h */
index 91871da548ee4ee06766e22e1b8afc4b3eea4e05..97df4fb1553772df00bd733440115aacce34515c 100644 (file)
@@ -1,5 +1,5 @@
 /* write.c - emit .o file
-   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 1995
+   Copyright (C) 1986, 87, 90, 91, 92, 93, 94, 95, 1996
    Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
@@ -94,6 +94,8 @@ int magic_number_for_object_file = DEFAULT_MAGIC_NUMBER_FOR_OBJECT_FILE;
 
 #endif /* BFD_ASSEMBLER */
 
+static int n_fixups;
+
 #ifdef BFD_ASSEMBLER
 static fixS *fix_new_internal PARAMS ((fragS *, int where, int size,
                                       symbolS *add, symbolS *sub,
@@ -133,6 +135,8 @@ fix_new_internal (frag, where, size, add_symbol, sub_symbol, offset, pcrel,
 {
   fixS *fixP;
 
+  n_fixups++;
+
   fixP = (fixS *) obstack_alloc (&notes, sizeof (fixS));
 
   fixP->fx_frag = frag;
@@ -799,12 +803,23 @@ write_relocs (abfd, sec, xxx)
     {
       arelent *reloc;
       bfd_reloc_status_type s;
+      symbolS *sym;
 
       if (fixp->fx_done)
        {
          n--;
          continue;
        }
+
+      /* If this is an undefined symbol which was equated to another
+         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
+            && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+       sym = sym->sy_value.X_add_symbol;
+      fixp->fx_addsy = sym;
+
       reloc = tc_gen_reloc (sec, fixp);
       if (!reloc)
        {
@@ -844,6 +859,7 @@ write_relocs (abfd, sec, xxx)
       arelent **reloc;
       char *data;
       bfd_reloc_status_type s;
+      symbolS *sym;
       int j;
 
       if (fixp->fx_done)
@@ -851,6 +867,16 @@ write_relocs (abfd, sec, xxx)
          n--;
          continue;
        }
+
+      /* If this is an undefined symbol which was equated to another
+         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
+            && (! S_IS_DEFINED (sym) || S_IS_COMMON (sym)))
+       sym = sym->sy_value.X_add_symbol;
+      fixp->fx_addsy = sym;
+
       reloc = tc_gen_reloc (sec, fixp);
 
       for (j = 0; reloc[j]; j++)
@@ -1642,6 +1668,15 @@ write_object_file ()
                resolve_symbol_value (symp);
            }
 
+         /* Skip symbols which were equated to undefined or common
+             symbols.  */
+         if (symp->sy_value.X_op == O_symbol
+             && (! S_IS_DEFINED (symp) || S_IS_COMMON (symp)))
+           {
+             symbol_remove (symp, &symbol_rootP, &symbol_lastP);
+             continue;
+           }
+
          /* So far, common symbols have been treated like undefined symbols.
             Put them in the common section now.  */
          if (S_IS_DEFINED (symp) == 0
@@ -1703,6 +1738,9 @@ write_object_file ()
 
   /* Now do any format-specific adjustments to the symbol table, such
      as adding file symbols.  */
+#ifdef tc_adjust_symtab
+  tc_adjust_symtab ();
+#endif
 #ifdef obj_adjust_symtab
   obj_adjust_symtab ();
 #endif
@@ -2402,8 +2440,10 @@ fixup_segment (fixP, this_segment_type)
              else
                {
                  seg_reloc_count++;
+#if !(defined (TC_M68K) && defined (OBJ_ELF))
 #if !defined (TC_I386) || !(defined (OBJ_ELF) || defined (OBJ_COFF))
                  add_number += S_GET_VALUE (add_symbolP);
+#endif
 #endif
                }
            }
@@ -2531,6 +2571,13 @@ number_to_chars_littleendian (buf, val, n)
     }
 }
 
+void
+write_print_statistics (file)
+     FILE *file;
+{
+  fprintf (stderr, "fixups: %d\n", n_fixups);
+}
+
 /* for debugging */
 extern int indent_level;
 extern void print_symbol_value_1 ();