Applied Michael's Sokolov's patch to implement --embedded-relocs for m68k coff.
authorNick Clifton <nickc@redhat.com>
Fri, 21 Jul 2000 23:31:53 +0000 (23:31 +0000)
committerNick Clifton <nickc@redhat.com>
Fri, 21 Jul 2000 23:31:53 +0000 (23:31 +0000)
bfd/ChangeLog
bfd/coff-m68k.c
ld/ChangeLog
ld/Makefile.am
ld/Makefile.in
ld/emulparams/m68kcoff.sh
ld/emultempl/m68kcoff.em [new file with mode: 0644]

index eee5f1ac75d0abf6d468977afa292cccc486685a..52b30aeaafba00e0b13bc23b465b2058085f8a55 100644 (file)
@@ -1,3 +1,9 @@
+2000-07-27  Michael Sokolov  <msokolov@ivan.Harhan.ORG>
+
+        * coff-m68k.c (bfd_m68k_coff_create_embedded_relocs): New function.
+        * bfd-in.h (bfd_m68k_coff_create_embedded_relocs): Add declaration.
+        * bfd-in2.h: Regenerate.
+
 2000-07-21  Nick Clifton  <nickc@cygnus.com>
 
        * elf32-mips.c (_bfd_mips_elf_check_relocs): Detect out of
index d7138c082e0b4e6298eca3e57267344e6132b8bd..3ae98dbd12cc5a6abf95f7f087da51e0d1ce1fa5 100644 (file)
@@ -1,5 +1,5 @@
 /* BFD back-end for Motorola 68000 COFF binaries.
-   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 1999
+   Copyright 1990, 91, 92, 93, 94, 95, 96, 97, 99, 2000
    Free Software Foundation, Inc.
    Written by Cygnus Support.
 
@@ -419,6 +419,97 @@ m68kcoff_common_addend_rtype_to_howto (abfd, sec, rel, h, sym, addendp)
 #endif /* ! defined (coff_rtype_to_howto) */
 
 #endif /* COFF_COMMON_ADDEND */
+
+#if !defined ONLY_DECLARE_RELOCS && ! defined STATIC_RELOCS
+/* Given a .data section and a .emreloc in-memory section, store
+   relocation information into the .emreloc section which can be
+   used at runtime to relocate the section.  This is called by the
+   linker when the --embedded-relocs switch is used.  This is called
+   after the add_symbols entry point has been called for all the
+   objects, and before the final_link entry point is called.  */
+
+boolean
+bfd_m68k_coff_create_embedded_relocs (abfd, info, datasec, relsec, errmsg)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     asection *datasec;
+     asection *relsec;
+     char **errmsg;
+{
+  char *extsyms;
+  bfd_size_type symesz;
+  struct internal_reloc *irel, *irelend;
+  bfd_byte *p;
+
+  BFD_ASSERT (! info->relocateable);
+
+  *errmsg = NULL;
+
+  if (datasec->reloc_count == 0)
+    return true;
+
+  extsyms = obj_coff_external_syms (abfd);
+  symesz = bfd_coff_symesz (abfd);
+
+  irel = _bfd_coff_read_internal_relocs (abfd, datasec, true, NULL, false,
+                                        NULL);
+  irelend = irel + datasec->reloc_count;
+
+  relsec->contents = (bfd_byte *) bfd_alloc (abfd, datasec->reloc_count * 12);
+  if (relsec->contents == NULL)
+    return false;
+
+  p = relsec->contents;
+
+  for (; irel < irelend; irel++, p += 12)
+    {
+      asection *targetsec;
+
+      /* We are going to write a four byte longword into the runtime
+       reloc section.  The longword will be the address in the data
+       section which must be relocated.  It is followed by the name
+       of the target section NUL-padded or truncated to 8
+       characters.  */
+
+      /* We can only relocate absolute longword relocs at run time.  */
+      if (irel->r_type != R_RELLONG)
+       {
+         *errmsg = _("unsupported reloc type");
+         bfd_set_error (bfd_error_bad_value);
+         return false;
+       }
+
+      if (irel->r_symndx == -1)
+       targetsec = bfd_abs_section_ptr;
+      else
+       {
+         struct coff_link_hash_entry *h;
+         
+         h = obj_coff_sym_hashes (abfd)[irel->r_symndx];
+         if (h == NULL)
+           {
+             struct internal_syment isym;
+             
+             bfd_coff_swap_sym_in (abfd, extsyms + symesz * irel->r_symndx,
+                                   &isym);
+             targetsec = coff_section_from_bfd_index (abfd, isym.n_scnum);
+           }
+         else if (h->root.type == bfd_link_hash_defined
+                  || h->root.type == bfd_link_hash_defweak)
+           targetsec = h->root.u.def.section;
+         else
+           targetsec = NULL;
+       }
+      
+      bfd_put_32 (abfd,
+                 (irel->r_vaddr - datasec->vma + datasec->output_offset), p);
+      memset (p + 4, 0, 8);
+      strncpy (p + 4, targetsec->output_section->name, 8);
+    }
+  
+  return true;
+}
+#endif /* neither ONLY_DECLARE_RELOCS not STATIC_RELOCS  */
 \f
 #define coff_bfd_is_local_label_name m68k_coff_is_local_label_name
 
index 1c6e4760c06d8fee9e568d92f2a62878fb360c82..d082eb86ddfe0258a2782dbd5cf8498f550a7787 100644 (file)
@@ -1,3 +1,11 @@
+2000-07-21  Michael Sokolov  <msokolov@ivan.Harhan.ORG>
+
+       * emultempl/m68kcoff.em: New file.
+       * emulparams/m68kcoff.sh (TEMPLATE_NAME): Use m68kcoff template.
+       * Makefile.am (em68kcoff.c): Depend on m68kcoff.em rather than
+       generic.em.
+       * Makefile.in: Regenerate.
+
 2000-07-20  H.J. Lu  <hjl@gnu.org>
 
        * emultempl/elf32.em (longopts): Duplicate "disable-new-dtags"
index 9ce016ab7f9fe903b88ee56e8512ffe460edbdb5..40ad6bed64d205bb20785b651a24f571bae69958 100644 (file)
@@ -601,7 +601,7 @@ em68kaux.c: $(srcdir)/emulparams/m68kaux.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kaux.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} m68kaux "$(tdir_m68kaux)"
 em68kcoff.c: $(srcdir)/emulparams/m68kcoff.sh \
-  $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
+  $(srcdir)/emultempl/m68kcoff.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} m68kcoff "$(tdir_m68kcoff)"
 em68kelf.c: $(srcdir)/emulparams/m68kelf.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
index dcc185fa49b13cc5b00440d41ec077d19af0a9e1..6b9b637686f459aa788465b94d411065386777a3 100644 (file)
@@ -447,7 +447,7 @@ deffilep.c ldgram.c ldlex.c
 
 DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
 
-TAR = tar
+TAR = gtar
 GZIP_ENV = --best
 SOURCES = $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES)
 OBJECTS = $(ld_new_OBJECTS)
@@ -1302,7 +1302,7 @@ em68kaux.c: $(srcdir)/emulparams/m68kaux.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kaux.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} m68kaux "$(tdir_m68kaux)"
 em68kcoff.c: $(srcdir)/emulparams/m68kcoff.sh \
-  $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
+  $(srcdir)/emultempl/m68kcoff.em $(srcdir)/scripttempl/m68kcoff.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} m68kcoff "$(tdir_m68kcoff)"
 em68kelf.c: $(srcdir)/emulparams/m68kelf.sh \
   $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
index b417c0da45c1e099d72a457fc90785407128ac74..bd884c9f80533844a3df5c1b72cba0207f0f975f 100644 (file)
@@ -3,3 +3,4 @@ OUTPUT_FORMAT="coff-m68k"
 TEXT_START_ADDR=0x1000000
 TARGET_PAGE_SIZE=0x1000000
 ARCH=m68k
+TEMPLATE_NAME=m68kcoff
diff --git a/ld/emultempl/m68kcoff.em b/ld/emultempl/m68kcoff.em
new file mode 100644 (file)
index 0000000..06422d3
--- /dev/null
@@ -0,0 +1,245 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >e${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script.  DO NOT EDIT! */
+
+/* Handle embedded relocs for m68k.
+   Copyright (C) 2000 Free Software Foundation, Inc.
+   Written by Michael Sokolov <msokolov@ivan.Harhan.ORG>, based on generic.em
+   by Steve Chamberlain <steve@cygnus.com>, embedded relocs code based on
+   mipsecoff.em by Ian Lance Taylor <ian@cygnus.com>.
+
+This file is part of GLD, the Gnu Linker.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+#include "ld.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static void gld${EMULATION_NAME}_after_open PARAMS ((void));
+static void check_sections PARAMS ((bfd *, asection *, PTR));
+static void gld${EMULATION_NAME}_after_allocation PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+
+static void
+gld${EMULATION_NAME}_before_parse ()
+{
+#ifndef TARGET_                        /* I.e., if not generic.  */
+  ldfile_set_output_arch ("`echo ${ARCH}`");
+#endif /* not TARGET_ */
+}
+
+/* This function is run after all the input files have been opened.
+   We create a .emreloc section for each input file with a non zero
+   .data section.  The BFD backend will fill in these sections with
+   magic numbers which can be used to relocate the data section at run
+   time.  */
+
+static void
+gld${EMULATION_NAME}_after_open ()
+{
+  bfd *abfd;
+
+  if (! command_line.embedded_relocs
+      || link_info.relocateable)
+    return;
+
+  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+    {
+      asection *datasec;
+
+      /* As first-order business, make sure that each input BFD is COFF. It
+         better be, as we are directly calling a COFF backend function.  */
+      if (bfd_get_flavour (abfd) != bfd_target_coff_flavour)
+       einfo ("%F%B: all input objects must be COFF for --embedded-relocs\n");
+
+      datasec = bfd_get_section_by_name (abfd, ".data");
+
+      /* Note that we assume that the reloc_count field has already
+         been set up.  We could call bfd_get_reloc_upper_bound, but
+         that returns the size of a memory buffer rather than a reloc
+         count.  We do not want to call bfd_canonicalize_reloc,
+         because although it would always work it would force us to
+         read in the relocs into BFD canonical form, which would waste
+         a significant amount of time and memory.  */
+      if (datasec != NULL && datasec->reloc_count > 0)
+       {
+         asection *relsec;
+
+         relsec = bfd_make_section (abfd, ".emreloc");
+         if (relsec == NULL
+             || ! bfd_set_section_flags (abfd, relsec,
+                                         (SEC_ALLOC
+                                          | SEC_LOAD
+                                          | SEC_HAS_CONTENTS
+                                          | SEC_IN_MEMORY))
+             || ! bfd_set_section_alignment (abfd, relsec, 2)
+             || ! bfd_set_section_size (abfd, relsec,
+                                        datasec->reloc_count * 12))
+           einfo ("%F%B: can not create .emreloc section: %E\n");
+       }
+
+      /* Double check that all other data sections are empty, as is
+         required for embedded PIC code.  */
+      bfd_map_over_sections (abfd, check_sections, (PTR) datasec);
+    }
+}
+
+/* Check that of the data sections, only the .data section has
+   relocs.  This is called via bfd_map_over_sections.  */
+
+static void
+check_sections (abfd, sec, datasec)
+     bfd *abfd;
+     asection *sec;
+     PTR datasec;
+{
+  if ((bfd_get_section_flags (abfd, sec) & SEC_DATA)
+      && sec != (asection *) datasec
+      && sec->reloc_count != 0)
+    einfo ("%B%X: section %s has relocs; can not use --embedded-relocs\n",
+          abfd, bfd_get_section_name (abfd, sec));
+}
+
+/* This function is called after the section sizes and offsets have
+   been set.  If we are generating embedded relocs, it calls a special
+   BFD backend routine to do the work.  */
+
+static void
+gld${EMULATION_NAME}_after_allocation ()
+{
+  bfd *abfd;
+
+  if (! command_line.embedded_relocs
+      || link_info.relocateable)
+    return;
+
+  for (abfd = link_info.input_bfds; abfd != NULL; abfd = abfd->link_next)
+    {
+      asection *datasec, *relsec;
+      char *errmsg;
+
+      datasec = bfd_get_section_by_name (abfd, ".data");
+
+      if (datasec == NULL || datasec->reloc_count == 0)
+       continue;
+
+      relsec = bfd_get_section_by_name (abfd, ".emreloc");
+      ASSERT (relsec != NULL);
+
+      if (! bfd_m68k_coff_create_embedded_relocs (abfd, &link_info,
+                                                  datasec, relsec,
+                                                  &errmsg))
+       {
+         if (errmsg == NULL)
+           einfo ("%B%X: can not create runtime reloc information: %E\n",
+                  abfd);
+         else
+           einfo ("%X%B: can not create runtime reloc information: %s\n",
+                  abfd, errmsg);
+       }
+    }
+}
+
+static char *
+gld${EMULATION_NAME}_get_script(isfile)
+     int *isfile;
+EOF
+
+if test -n "$COMPILE_IN"
+then
+# Scripts compiled in.
+
+# sed commands to quote an ld script as a C string.
+sc="-f stringify.sed"
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{                           
+  *isfile = 0;
+
+  if (link_info.relocateable == true && config.build_constructors == true)
+    return
+EOF
+sed $sc ldscripts/${EMULATION_NAME}.xu                     >> e${EMULATION_NAME}.c
+echo '  ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xr                     >> e${EMULATION_NAME}.c
+echo '  ; else if (!config.text_read_only) return'         >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xbn                    >> e${EMULATION_NAME}.c
+echo '  ; else if (!config.magic_demand_paged) return'     >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.xn                     >> e${EMULATION_NAME}.c
+echo '  ; else return'                                     >> e${EMULATION_NAME}.c
+sed $sc ldscripts/${EMULATION_NAME}.x                      >> e${EMULATION_NAME}.c
+echo '; }'                                                 >> e${EMULATION_NAME}.c
+
+else
+# Scripts read from the filesystem.
+
+cat >>e${EMULATION_NAME}.c <<EOF
+{                           
+  *isfile = 1;
+
+  if (link_info.relocateable == true && config.build_constructors == true)
+    return "ldscripts/${EMULATION_NAME}.xu";
+  else if (link_info.relocateable == true)
+    return "ldscripts/${EMULATION_NAME}.xr";
+  else if (!config.text_read_only)
+    return "ldscripts/${EMULATION_NAME}.xbn";
+  else if (!config.magic_demand_paged)
+    return "ldscripts/${EMULATION_NAME}.xn";
+  else
+    return "ldscripts/${EMULATION_NAME}.x";
+}
+EOF
+
+fi
+
+cat >>e${EMULATION_NAME}.c <<EOF
+
+struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 
+{
+  gld${EMULATION_NAME}_before_parse,
+  syslib_default,
+  hll_default,
+  after_parse_default,
+  gld${EMULATION_NAME}_after_open,
+  gld${EMULATION_NAME}_after_allocation,
+  set_output_arch_default,
+  ldemul_default_target,
+  before_allocation_default,
+  gld${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  NULL,        /* finish */
+  NULL,        /* create output section statements */
+  NULL,        /* open dynamic archive */
+  NULL,        /* place orphan */
+  NULL,        /* set symbols */
+  NULL,        /* parse args */
+  NULL,        /* unrecognized file */
+  NULL,        /* list options */
+  NULL,        /* recognized file */
+  NULL         /* find_potential_libraries */
+};
+EOF