* configure.in (powerpc-*-elf*): New target; use ppc-elf32.
authorIan Lance Taylor <ian@airs.com>
Fri, 25 Feb 1994 03:32:08 +0000 (03:32 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 25 Feb 1994 03:32:08 +0000 (03:32 +0000)
* config/ppc-elf32.mt: New file.
* emulparams/elf32ppc.sh: New file.
* emultempl/ppc.em: New file.
* Makefile.in (ALL_EMULATIONS): Added em_elf32ppc.o.
(em_elf32ppc.c): New target; uses elf32ppc.sh, ppc.em and elf.sc.
(EMULATION_OFILES): Added dependencies on ldexp.h and ldlang.h.

ld/.Sanitize
ld/ChangeLog
ld/Makefile.in
ld/config/.Sanitize
ld/config/ppc-elf32.mt [new file with mode: 0644]
ld/emulparams/.Sanitize
ld/emulparams/elf32ppc.sh [new file with mode: 0644]
ld/emultempl/.Sanitize
ld/emultempl/ppc.em [new file with mode: 0644]

index 7014772be74ff2173e1daefce90cbc6d6a7adbdb..f797560d0bb8e0de9c0d4c05c4ecfcbcd0ed24e7 100644 (file)
@@ -144,4 +144,26 @@ else
        done
 fi
 
+echo Looking for PowerPC NetWare...
+ppcfiles="configure.in"
+if ( echo $* | grep keep\-powerpc\-netware > /dev/null ) ; then
+       if [ -n "${verbose}" ] ; then
+               echo Keeping PowerPC NetWare stuff in $ppcfiles.
+       fi
+else
+       if [ -n "${verbose}" ]; then
+               echo -n Removing PowerPC NetWare in `pwd`:
+       fi
+       for f in $ppcfiles ; do
+               if [ -n "${verbose}" ] ; then
+                       echo -n " " $f
+               fi
+               sed '/start\-sanitize\-powerpc\-netware/,/end\-sanitize\-powerpc\-netware/d' < $f > new
+               if [ -n "${safe}" ] ; then
+                       mv $f .Recover
+               fi
+               mv new $f
+       done
+fi
+
 # End of file.
index 827c81771d14c7cafe64390856d503d1a5921b57..f0f73a3cb3c56223f359bdd79761418b78df8da6 100644 (file)
@@ -1,3 +1,13 @@
+Thu Feb 24 16:47:33 1994  Ian Lance Taylor  (ian@cygnus.com)
+
+       * configure.in (powerpc-*-elf*): New target; use ppc-elf32.
+       * config/ppc-elf32.mt: New file.
+       * emulparams/elf32ppc.sh: New file.
+       * emultempl/ppc.em: New file.
+       * Makefile.in (ALL_EMULATIONS): Added em_elf32ppc.o.
+       (em_elf32ppc.c): New target; uses elf32ppc.sh, ppc.em and elf.sc.
+       (EMULATION_OFILES): Added dependencies on ldexp.h and ldlang.h.
+
 Thu Feb 24 12:27:07 1994  David J. Mackenzie  (djm@rtl.cygnus.com)
 
        Use getopt instead of lex and yacc to parse the command line.
index d38fe760976ca4b69720be5b52d8495f879c27ea..b6e349ed513e865d0c7570dd1c41f40d0ff26bc2 100644 (file)
@@ -173,7 +173,7 @@ ALL_EMULATIONS = em_lnk960.o em_sun3.o em_i386aout.o em_go32.o em_vsta.o \
        em_h8500b.o em_h8500s.o em_h8500c.o em_h8500m.o \
        em_hppaelf.o em_mipsidtl.o em_sh.o em_elf_i386.o em_alpha.o \
        em_i386lynx.o em_m68klynx.o em_sparclynx.o em_coff_sparc.o \
-       em_delta68.o \
+       em_delta68.o em_elf32ppc.o \
        $(OTHER_EMULATIONS)
 
 # This is now set by configure.in.
@@ -377,13 +377,17 @@ em_alpha.c: $(srcdir)/emulparams/alpha.sh \
 em_coff_sparc.c: $(srcdir)/emulparams/coff_sparc.sh \
   $(srcdir)/emultempl/generic.em $(srcdir)/scripttempl/sparccoff.sc ${GEN_DEPENDS}
        ${GENSCRIPTS} coff_sparc
+em_elf32ppc.c: $(srcdir)/emulparams/elf32ppc.sh \
+  $(srcdir)/emultempl/ppc.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS}
+       ${GENSCRIPTS} elf32ppc
 
 $(LD_PROG): $(OFILES) $(BFDLIB) $(LIBIBERTY)
        $(CC) $(CFLAGS) $(LDFLAGS) -o $(LD_PROG) $(OFILES) $(BFDLIB) $(LIBIBERTY) $(EXTRALIBS)
 
 # The generated emulation files mostly have the same dependencies.
 $(EMULATION_OFILES): ../bfd/bfd.h ../bfd/sysdep.h $(INCDIR)/bfdlink.h \
-  ld.h ldmain.h ldemul.h ldfile.h ldmisc.h ldexp.h ldlang.h config.h ldctor.h
+  ld.h ldmain.h ldemul.h ldfile.h ldmisc.h ldexp.h ldlang.h config.h \
+  ldctor.h ldexp.h ldlang.h
 
 # These targets are for the dejagnu testsuites. The file site.exp 
 # contains global variables that all the testsuites will use.
index daadb16934537de701433c0ad15c4898e53e1afd..767c7ce897c74d2882889f833a7d2cf96b5a7f27 100644 (file)
@@ -68,6 +68,7 @@ mips-lit.mt
 mipsb-elf32.mt
 news.mt
 ose68.mt
+ppc-elf32.mt
 rtbsd.mh
 sa29200.mt
 solaris2.mh
diff --git a/ld/config/ppc-elf32.mt b/ld/config/ppc-elf32.mt
new file mode 100644 (file)
index 0000000..f0d2056
--- /dev/null
@@ -0,0 +1 @@
+EMUL=elf32ppc
index 0237707589aca710763b2bfe53dc83d4efdf1f37..aef97accaabc3716392e3431abc15b5c59d94cb8 100644 (file)
@@ -32,6 +32,7 @@ ebmon29k.sh
 elf32_sparc.sh
 elf64_sparc.sh
 elf32mipb.sh
+elf32ppc.sh
 elf_i386.sh
 gld960.sh
 go32.sh
diff --git a/ld/emulparams/elf32ppc.sh b/ld/emulparams/elf32ppc.sh
new file mode 100644 (file)
index 0000000..792265b
--- /dev/null
@@ -0,0 +1,11 @@
+TEMPLATE_NAME=ppc
+SCRIPT_NAME=elf
+OUTPUT_FORMAT="elf32-powerpc"
+TEXT_START_ADDR=0x0400000
+DATA_ADDR=0x10000000
+MAXPAGESIZE=0x40000
+NONPAGED_TEXT_START_ADDR=0x0400000
+OTHER_READWRITE_SECTIONS='
+  .toc . : { *(.toc) }
+'
+ARCH=powerpc
index 97309802cfe5a3ffa78d4458b7a2bcebd334622b..d8f482141b3621d28192f896929632f1ed883ec6 100644 (file)
@@ -30,6 +30,7 @@ gld960.em
 hppaelf.em
 lnk960.em
 m88kbcs.em
+ppc.em
 vanilla.em
 
 Things-to-lose:
diff --git a/ld/emultempl/ppc.em b/ld/emultempl/ppc.em
new file mode 100644 (file)
index 0000000..d3eb950
--- /dev/null
@@ -0,0 +1,373 @@
+# This shell script emits a C file. -*- C -*-
+# It does some substitutions.
+cat >em_${EMULATION_NAME}.c <<EOF
+/* This file is is generated by a shell script.  DO NOT EDIT! */
+
+/* PowerPC/POWER emulation for the linker.
+   Copyright (C) 1994 Free Software Foundation, Inc.
+   Written by Ian Lance Taylor, Cygnus Support
+
+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., 675 Mass Ave, Cambridge, MA 02139, USA.  */
+
+/* This file is similar to generic.em.  However, we need to build
+   linker stubs to handle calls to different modules.  A PowerPC call
+   is emitted as a two instruction sequence:
+     bl .{function}
+     cror 31,31,31
+
+   When linking, if the function symbol is defined and in the same
+   module, we leave it alone (actually, if it is more than 26 bits
+   away we should treat it as though it were in a different module).
+   If the function symbol is not defined, we must construct a linker
+   stub.  We reroute the call to go to the linker stub instead, and we
+   change the cror instruction to reload the TOC register value.  The
+   linker stub looks like this
+     l     r12,{function}(r2)
+     st    r2,20(r1)
+     l     r0,0(r12)
+     l     r2,4(r12)
+     mtctr r0
+     bcc
+
+   Since we do not yet support dynamic linking, all function symbols
+   are in the same module.  However, we still need to create a stub
+   for an undefined symbol.
+
+   This is actually probably not correct for the PowerPC ABI.
+   However, I do not have that ABI yet.  */
+
+#define TARGET_IS_${EMULATION_NAME}
+
+#include "bfd.h"
+#include "sysdep.h"
+#include "bfdlink.h"
+
+/* FIXME!  */
+#include "genlink.h"
+
+#include "ld.h"
+#include "config.h"
+#include "ldmain.h"
+#include "ldemul.h"
+#include "ldfile.h"
+#include "ldmisc.h"
+#include "ldexp.h"
+#include "ldlang.h"
+
+static void gld${EMULATION_NAME}_before_parse PARAMS ((void));
+static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile));
+static void gld${EMULATION_NAME}_create_output_section_statements
+  PARAMS ((void));
+static void gld${EMULATION_NAME}_before_allocation PARAMS ((void));
+static boolean gld${EMULATION_NAME}_check_symbol
+  PARAMS ((struct bfd_link_hash_entry *, PTR));
+
+static void
+gld${EMULATION_NAME}_before_parse()
+{
+  ldfile_output_architecture = bfd_arch_${ARCH};
+}
+
+/* Section in which we build stubs.  */
+
+static asection *stub_sec;
+
+/* Section in which we build TOC entries for stubs.  */
+
+static asection *stub_toc_sec;
+
+/* This is called before the input files are opened.  We create a new
+   fake input file to hold the stub section.  */
+
+static void
+gld${EMULATION_NAME}_create_output_section_statements ()
+{
+  lang_input_statement_type *stub_file;
+  
+  stub_file = lang_add_input_file ("linker stubs",
+                                  lang_input_file_is_fake_enum,
+                                  (char *) NULL);
+
+  stub_file->the_bfd = bfd_create ("linker stubs", output_bfd);
+  if (stub_file->the_bfd == (bfd *) NULL
+      || ! bfd_set_arch_mach (stub_file->the_bfd,
+                             bfd_get_arch (output_bfd),
+                             bfd_get_mach (output_bfd)))
+    {
+      einfo ("%X%P: can not create BFD: %E");
+      return;
+    }
+
+  stub_sec = bfd_make_section_old_way (stub_file->the_bfd, ".text");
+  stub_toc_sec = bfd_make_section_old_way (stub_file->the_bfd, ".toc");
+  if (stub_sec == (asection *) NULL
+      || stub_toc_sec == (asection *) NULL
+      || ! bfd_set_section_flags (stub_file->the_bfd, stub_sec,
+                                 (SEC_HAS_CONTENTS
+                                  | SEC_ALLOC
+                                  | SEC_LOAD
+                                  | SEC_CODE
+                                  | SEC_RELOC
+                                  | SEC_IN_MEMORY))
+      || ! bfd_set_section_flags (stub_file->the_bfd, stub_toc_sec,
+                                 (SEC_HAS_CONTENTS
+                                  | SEC_ALLOC
+                                  | SEC_LOAD
+                                  | SEC_DATA
+                                  | SEC_RELOC
+                                  | SEC_IN_MEMORY)))
+    {
+      einfo ("%X%P: can not create stub sections: %E");
+      return;
+    }
+
+  ldlang_add_file (stub_file);
+}
+
+/* This is called after the input sections have been attached to the
+   output sections but before the output section sizes have been set.
+   We can identify the required stubs because they are undefined
+   symbols beginning with ".".  For each such symbol, we build a stub
+   in the .text section.  */
+
+static void
+gld${EMULATION_NAME}_before_allocation ()
+{
+  bfd_link_hash_traverse (link_info.hash,
+                         gld${EMULATION_NAME}_check_symbol,
+                         (PTR) NULL);
+}
+
+/* If a particular symbol is undefined and starts with a ".", then we
+   need to make a stub for it.  */
+
+/*ARGSUSED*/
+static boolean
+gld${EMULATION_NAME}_check_symbol (h, info)
+     struct bfd_link_hash_entry *h;
+     PTR info;
+{
+  bfd *stub_bfd;
+  bfd_byte *p;
+  arelent *r;
+  struct bfd_link_hash_entry *hnew;
+  asymbol *sym;
+
+  if (h->type != bfd_link_hash_undefined
+      || h->root.string[0] != '.')
+    return true;
+
+  stub_bfd = stub_sec->owner;
+
+  /* Define this symbol to be the current location in stub_sec.  */
+  h->type = bfd_link_hash_defined;
+  h->u.def.value = bfd_section_size (stub_bfd, stub_sec);
+  h->u.def.section = stub_sec;
+
+  /* We want to add this:
+       LONG (0x81820000)       lwz     r12,{TOC index}(r2)
+       LONG (0x90410014)       stw     r2,20(r1)
+       LONG (0x800c0000)       lwz     r0,0(r12)
+       LONG (0x804c0004)       lwz     r2,4(r12)
+       LONG (0x7c0903a6)       mtctr   r0
+       LONG (0x4e800420)       bctr
+       LONG (0)                        Traceback table
+       LONG (0xc8000)
+       LONG (0)
+     */
+
+  if (! bfd_set_section_size (stub_bfd, stub_sec,
+                             h->u.def.value + 9 * 4))
+    {
+      einfo ("%P%X: can not set section size: %E");
+      return false;
+    }
+
+  stub_sec->contents = ((bfd_byte *)
+                       xrealloc ((PTR) stub_sec->contents,
+                                 bfd_section_size (stub_bfd, stub_sec)));
+  p = stub_sec->contents + h->u.def.value;
+  bfd_put_32 (stub_bfd,
+             (bfd_vma) 0x81820000 + bfd_section_size (stub_bfd, stub_toc_sec),
+             p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0x90410014, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0x800c0000, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0x804c0004, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0x7c0903a6, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0x4e800420, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0xc8000, p);
+  p += 4;
+  bfd_put_32 (stub_bfd, (bfd_vma) 0, p);
+
+  /* Add an undefined symbol for the TOC reference.  This is the name
+     without the leading ".".  */
+  hnew = bfd_link_hash_lookup (link_info.hash, h->root.string + 1, true,
+                              false, true);
+  if (hnew == (struct bfd_link_hash_entry *) NULL)
+    einfo ("%P%F: bfd_link_hash_lookup failed: %E");
+  if (hnew->type == bfd_link_hash_new)
+    {
+      hnew->type = bfd_link_hash_undefined;
+      hnew->u.undef.abfd = stub_bfd;
+      bfd_link_add_undef (link_info.hash, hnew);
+    }
+
+  /* Add a relocation entry for the TOC reference in the first
+     instruction.  */
+  ++stub_sec->reloc_count;
+  stub_sec->relocation = ((arelent *)
+                         xrealloc ((PTR) stub_sec->relocation,
+                                   (stub_sec->reloc_count
+                                    * sizeof (arelent))));
+  r = &stub_sec->relocation[stub_sec->reloc_count - 1];
+  r->sym_ptr_ptr = stub_toc_sec->symbol_ptr_ptr;
+  r->address = h->u.def.value;
+  if (stub_bfd->xvec->byteorder_big_p)
+    r->address += 2;
+  r->addend = 0;
+  r->howto = bfd_reloc_type_lookup (stub_bfd, BFD_RELOC_PPC_TOC16);
+  if (r->howto == (reloc_howto_type *) NULL)
+    einfo ("%P%F: no howto for TOC reference: %E");
+
+  /* Add a relocation entry in the TOC section.  */
+  ++stub_toc_sec->reloc_count;
+  stub_toc_sec->relocation = ((arelent *)
+                             xrealloc ((PTR) stub_toc_sec->relocation,
+                                       (stub_toc_sec->reloc_count
+                                        * sizeof (arelent))));
+  r = &stub_toc_sec->relocation[stub_toc_sec->reloc_count - 1];
+
+  sym = bfd_make_empty_symbol (stub_bfd);
+  sym->name = hnew->root.string;
+  sym->value = 0;
+  sym->flags = BSF_NO_FLAGS;
+  sym->section = &bfd_und_section;
+  sym->udata = NULL;
+  
+  /* FIXME! */
+  ((struct generic_link_hash_entry *) hnew)->sym = sym;
+
+  r->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
+  *r->sym_ptr_ptr = sym;
+  r->address = bfd_section_size (stub_bfd, stub_toc_sec);
+  r->addend = 0;
+  r->howto = bfd_reloc_type_lookup (stub_bfd, BFD_RELOC_32);
+  if (r->howto == (reloc_howto_type *) NULL)
+    einfo ("%P%F: no howto for TOC entry: %E");
+
+  /* Add more space to the .toc section.  */
+  if (! bfd_set_section_size (stub_bfd, stub_toc_sec,
+                             bfd_section_size (stub_bfd, stub_toc_sec) + 4))
+    {
+      einfo ("%P%X: can not set section size: %E");
+      return false;
+    }
+
+  stub_toc_sec->contents = ((bfd_byte *)
+                           xrealloc ((PTR) stub_toc_sec->contents,
+                                     bfd_section_size (stub_bfd,
+                                                       stub_toc_sec)));
+  bfd_put_32 (stub_bfd, (bfd_vma) 0,
+             (stub_toc_sec->contents
+              + bfd_section_size (stub_bfd, stub_toc_sec)
+              - 4));
+
+  return true;
+}
+
+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='s/["\\]/\\&/g
+s/$/\\n\\/
+1s/^/"{/
+$s/$/n}"/
+'
+
+cat >>em_${EMULATION_NAME}.c <<EOF
+{                           
+  *isfile = 0;
+
+  if (link_info.relocateable == true && config.build_constructors == true)
+    return `sed "$sc" ldscripts/${EMULATION_NAME}.xu`;
+  else if (link_info.relocateable == true)
+    return `sed "$sc" ldscripts/${EMULATION_NAME}.xr`;
+  else if (!config.text_read_only)
+    return `sed "$sc" ldscripts/${EMULATION_NAME}.xbn`;
+  else if (!config.magic_demand_paged)
+    return `sed "$sc" ldscripts/${EMULATION_NAME}.xn`;
+  else
+    return `sed "$sc" ldscripts/${EMULATION_NAME}.x`;
+}
+EOF
+
+else
+# Scripts read from the filesystem.
+
+cat >>em_${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 >>em_${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,
+  after_allocation_default,
+  set_output_arch_default,
+  ldemul_default_target,
+  gld${EMULATION_NAME}_before_allocation,
+  gld${EMULATION_NAME}_get_script,
+  "${EMULATION_NAME}",
+  "${OUTPUT_FORMAT}",
+  0,
+  gld${EMULATION_NAME}_create_output_section_statements
+};
+EOF