* 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.
This commit is contained in:
Ian Lance Taylor 1994-02-25 03:32:08 +00:00
parent d4e5e3c330
commit c361ce46c5
9 changed files with 426 additions and 2 deletions

View 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.

View 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.

View 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.

View File

@ -68,6 +68,7 @@ mips-lit.mt
mipsb-elf32.mt
news.mt
ose68.mt
ppc-elf32.mt
rtbsd.mh
sa29200.mt
solaris2.mh

1
ld/config/ppc-elf32.mt Normal file
View File

@ -0,0 +1 @@
EMUL=elf32ppc

View File

@ -32,6 +32,7 @@ ebmon29k.sh
elf32_sparc.sh
elf64_sparc.sh
elf32mipb.sh
elf32ppc.sh
elf_i386.sh
gld960.sh
go32.sh

11
ld/emulparams/elf32ppc.sh Normal file
View File

@ -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

View File

@ -30,6 +30,7 @@ gld960.em
hppaelf.em
lnk960.em
m88kbcs.em
ppc.em
vanilla.em
Things-to-lose:

373
ld/emultempl/ppc.em Normal file
View File

@ -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