* configure.tgt (powerpc-*-macos*): New target.

* emulparams/ppcmacos.sh: New file, PowerMac emulation.
	* Makefile.in (ALL_EMULATIONS): Add eppcmacos.o.
	(eppcmacos.c): New target.
	* mpw-eppcmacos.c: Update.
	* mpw-make.sed: Edit out attempts to use {GENSCRIPTS}.
This commit is contained in:
Stan Shebs 1995-11-18 00:50:06 +00:00
parent 7bb5e83191
commit 5ac7a6e96e
3 changed files with 373 additions and 35 deletions

View file

@ -0,0 +1,4 @@
TEMPLATE_NAME=aix
SCRIPT_NAME=aix
OUTPUT_FORMAT="xcoff-powermac"
ARCH=powerpc

View file

@ -38,12 +38,18 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "ldmisc.h"
#include "ldexp.h"
#include "ldlang.h"
#include "ldctor.h"
#include "ldgram.h"
static void gldppcmacos_before_parse PARAMS ((void));
static int gldppcmacos_parse_args PARAMS ((int, char **));
static void gldppcmacos_after_open PARAMS ((void));
static void gldppcmacos_before_allocation PARAMS ((void));
static void gldppcmacos_read_file PARAMS ((const char *, boolean));
static void gldppcmacos_free PARAMS ((PTR));
static void gldppcmacos_find_relocs
PARAMS ((lang_statement_union_type *));
static void gldppcmacos_find_exp_assignment PARAMS ((etree_type *));
static char *gldppcmacos_get_script PARAMS ((int *isfile));
/* The file alignment required for each section. */
@ -66,7 +72,7 @@ static unsigned short modtype = ('1' << 8) | 'L';
permitted). */
static int textro;
/* Structure used to hold import or export file list. */
/* Structure used to hold import file list. */
struct filelist
{
@ -75,10 +81,20 @@ struct filelist
};
/* List of import files. */
struct filelist *import_files;
static struct filelist *import_files;
/* List of export files. */
struct filelist *export_files;
/* List of export symbols read from the export files. */
struct export_symbol_list
{
struct export_symbol_list *next;
const char *name;
boolean syscall;
};
static struct export_symbol_list *export_symbols;
/* This routine is called before anything else is done. */
static void
gldppcmacos_before_parse()
@ -97,6 +113,7 @@ gldppcmacos_parse_args (argc, argv)
{
int prevoptind = optind;
int prevopterr = opterr;
int indx;
int longind;
int optc;
long val;
@ -108,12 +125,15 @@ gldppcmacos_parse_args (argc, argv)
#define OPTION_EROK (OPTION_ERNOTOK + 1)
#define OPTION_EXPORT (OPTION_EROK + 1)
#define OPTION_IMPORT (OPTION_EXPORT + 1)
#define OPTION_MAXDATA (OPTION_IMPORT + 1)
#define OPTION_LOADMAP (OPTION_IMPORT + 1)
#define OPTION_MAXDATA (OPTION_LOADMAP + 1)
#define OPTION_MAXSTACK (OPTION_MAXDATA + 1)
#define OPTION_MODTYPE (OPTION_MAXSTACK + 1)
#define OPTION_NOAUTOIMP (OPTION_MODTYPE + 1)
#define OPTION_NOSTRCMPCT (OPTION_NOAUTOIMP + 1)
#define OPTION_STRCMPCT (OPTION_NOSTRCMPCT + 1)
#define OPTION_PD (OPTION_NOSTRCMPCT + 1)
#define OPTION_PT (OPTION_PD + 1)
#define OPTION_STRCMPCT (OPTION_PT + 1)
static struct option longopts[] = {
{"basis", no_argument, NULL, OPTION_IGNORE},
@ -133,6 +153,8 @@ gldppcmacos_parse_args (argc, argv)
{"bhalt", required_argument, NULL, OPTION_IGNORE},
{"bI", required_argument, NULL, OPTION_IMPORT},
{"bimport", required_argument, NULL, OPTION_IMPORT},
{"bl", required_argument, NULL, OPTION_LOADMAP},
{"bloadmap", required_argument, NULL, OPTION_LOADMAP},
{"bmaxdata", required_argument, NULL, OPTION_MAXDATA},
{"bmaxstack", required_argument, NULL, OPTION_MAXSTACK},
{"bM", required_argument, NULL, OPTION_MODTYPE},
@ -144,11 +166,14 @@ gldppcmacos_parse_args (argc, argv)
{"bnostrcmpct", no_argument, NULL, OPTION_NOSTRCMPCT},
{"bnotextro", no_argument, &textro, 0},
{"bnro", no_argument, &textro, 0},
{"bpD", required_argument, NULL, OPTION_PD},
{"bpT", required_argument, NULL, OPTION_PT},
{"bro", no_argument, &textro, 1},
{"bS", required_argument, NULL, OPTION_MAXSTACK},
{"bso", no_argument, NULL, OPTION_AUTOIMP},
{"bstrcmpct", no_argument, NULL, OPTION_STRCMPCT},
{"btextro", no_argument, &textro, 1},
{"static", no_argument, NULL, OPTION_NOAUTOIMP},
{NULL, no_argument, NULL, 0}
};
@ -161,14 +186,17 @@ gldppcmacos_parse_args (argc, argv)
-bnotypchk, -bnox, -bquiet, -bR, -brename, -breorder, -btypchk,
-bx, -bX, -bxref. */
/* If the first option starts with -b, change the first : to an =.
/* If the current option starts with -b, change the first : to an =.
The AIX linker uses : to separate the option from the argument;
changing it to = lets us treat it as a getopt option. */
if (optind < argc && strncmp (argv[optind], "-b", 2) == 0)
indx = optind;
if (indx == 0)
indx = 1;
if (indx < argc && strncmp (argv[indx], "-b", 2) == 0)
{
char *s;
for (s = argv[optind]; *s != '\0'; s++)
for (s = argv[indx]; *s != '\0'; s++)
{
if (*s == ':')
{
@ -245,6 +273,9 @@ gldppcmacos_parse_args (argc, argv)
break;
case OPTION_EXPORT:
gldppcmacos_read_file (optarg, false);
break;
case OPTION_IMPORT:
{
struct filelist *n;
@ -253,16 +284,17 @@ gldppcmacos_parse_args (argc, argv)
n = (struct filelist *) xmalloc (sizeof (struct filelist));
n->next = NULL;
n->name = optarg;
if (optc == OPTION_EXPORT)
flpp = &export_files;
else
flpp = &import_files;
flpp = &import_files;
while (*flpp != NULL)
flpp = &(*flpp)->next;
*flpp = n;
}
break;
case OPTION_LOADMAP:
config.map_filename = optarg;
break;
case OPTION_MAXDATA:
val = strtoul (optarg, &end, 0);
if (*end != '\0')
@ -301,6 +333,51 @@ gldppcmacos_parse_args (argc, argv)
config.traditional_format = true;
break;
case OPTION_PD:
/* This sets the page that the .data section is supposed to
start on. The offset within the page should still be the
offset within the file, so we need to build an appropriate
expression. */
val = strtoul (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -pD number %s\n", optarg);
else
{
etree_type *t;
t = exp_binop ('+',
exp_intop (val),
exp_binop ('&',
exp_nameop (NAME, "."),
exp_intop (0xfff)));
t = exp_binop ('&',
exp_binop ('+', t, exp_intop (7)),
exp_intop (~ (bfd_vma) 7));
lang_section_start (".data", t);
}
break;
case OPTION_PT:
/* This set the page that the .text section is supposed to start
on. The offset within the page should still be the offset
within the file. */
val = strtoul (optarg, &end, 0);
if (*end != '\0')
einfo ("%P: warning: ignoring invalid -pT number %s\n", optarg);
else
{
etree_type *t;
t = exp_binop ('+',
exp_intop (val),
exp_nameop (SIZEOF_HEADERS, NULL));
t = exp_binop ('&',
exp_binop ('+', t, exp_intop (7)),
exp_intop (~ (bfd_vma) 7));
lang_section_start (".text", t);
}
break;
case OPTION_STRCMPCT:
config.traditional_format = false;
break;
@ -309,6 +386,48 @@ gldppcmacos_parse_args (argc, argv)
return 1;
}
/* This is called after the input files have been opened. */
static void
gldppcmacos_after_open ()
{
boolean r;
struct set_info *p;
/* Call ldctor_build_sets, after pretending that this is a
relocateable link. We do this because AIX requires relocation
entries for all references to symbols, even in a final
executable. */
r = link_info.relocateable;
link_info.relocateable = true;
ldctor_build_sets ();
link_info.relocateable = r;
/* For each set, record the size, so that the XCOFF backend can
output the correct csect length. */
for (p = sets; p != (struct set_info *) NULL; p = p->next)
{
bfd_size_type size;
/* If the symbol is defined, we may have been invoked from
collect, and the sets may already have been built, so we do
not do anything. */
if (p->h->type == bfd_link_hash_defined
|| p->h->type == bfd_link_hash_defweak)
continue;
if (p->reloc != BFD_RELOC_CTOR)
{
/* Handle this if we need to. */
abort ();
}
size = (p->count + 2) * 4;
if (! bfd_xcoff_link_record_set (output_bfd, &link_info, p->h, size))
einfo ("%F%P: bfd_xcoff_link_record_set failed: %E\n");
}
}
/* This is called after the sections have been attached to output
sections, but before any sizes or addresses have been set. */
@ -316,13 +435,30 @@ static void
gldppcmacos_before_allocation ()
{
struct filelist *fl;
struct export_symbol_list *el;
char *libpath;
asection *special_sections[6];
int i;
/* Handle the import and export files, if any. */
for (fl = import_files; fl != NULL; fl = fl->next)
gldppcmacos_read_file (fl->name, true);
for (fl = export_files; fl != NULL; fl = fl->next)
gldppcmacos_read_file (fl->name, false);
for (el = export_symbols; el != NULL; el = el->next)
{
struct bfd_link_hash_entry *h;
h = bfd_link_hash_lookup (link_info.hash, el->name, false, false, false);
if (h == NULL)
einfo ("%P%F: bfd_link_hash_lookup of export symbol failed: %E\n");
if (! bfd_xcoff_export_symbol (output_bfd, &link_info, h, el->syscall))
einfo ("%P%F: bfd_xcoff_export_symbol failed: %E\n");
}
/* Track down all relocations called for by the linker script (these
are typically constructor/destructor entries created by
CONSTRUCTORS) and let the backend know it will need to create
.loader relocs for them. */
lang_for_each_statement (gldppcmacos_find_relocs);
/* We need to build LIBPATH from the -L arguments. If any -rpath
arguments were used, though, we use -rpath instead, as a GNU
@ -357,11 +493,118 @@ gldppcmacos_before_allocation ()
maxstack, maxdata,
gc ? true : false,
modtype,
textro ? true : false))
textro ? true : false,
special_sections))
einfo ("%P%F: failed to set dynamic section sizes: %E\n");
/* Look through the special sections, and put them in the right
place in the link ordering. This is especially magic. */
for (i = 0; i < 6; i++)
{
asection *sec;
lang_output_section_statement_type *os;
lang_statement_union_type **pls;
lang_input_section_type *is;
const char *oname;
boolean start;
sec = special_sections[i];
if (sec == NULL)
continue;
/* Remove this section from the list of the output section.
This assumes we know what the script looks like. */
is = NULL;
os = lang_output_section_find (sec->output_section->name);
if (os == NULL)
einfo ("%P%F: can't find output section %s\n",
sec->output_section->name);
for (pls = &os->children.head; *pls != NULL; pls = &(*pls)->next)
{
if ((*pls)->header.type == lang_input_section_enum
&& (*pls)->input_section.section == sec)
{
is = (lang_input_section_type *) *pls;
*pls = (*pls)->next;
break;
}
if ((*pls)->header.type == lang_wild_statement_enum)
{
lang_statement_union_type **pwls;
for (pwls = &(*pls)->wild_statement.children.head;
*pwls != NULL;
pwls = &(*pwls)->next)
{
if ((*pwls)->header.type == lang_input_section_enum
&& (*pwls)->input_section.section == sec)
{
is = (lang_input_section_type *) *pwls;
*pwls = (*pwls)->next;
break;
}
}
if (is != NULL)
break;
}
}
if (is == NULL)
einfo ("%P%F: can't find %s in output section\n",
bfd_get_section_name (sec->owner, sec));
/* Now figure out where the section should go. */
switch (i)
{
default: /* to avoid warnings */
case 0:
/* _text */
oname = ".text";
start = true;
break;
case 1:
/* _etext */
oname = ".text";
start = false;
break;
case 2:
/* _data */
oname = ".data";
start = true;
break;
case 3:
/* _edata */
oname = ".data";
start = false;
break;
case 4:
case 5:
/* _end and end */
oname = ".bss";
start = false;
break;
}
os = lang_output_section_find (oname);
if (start)
{
is->header.next = os->children.head;
os->children.head = (lang_statement_union_type *) is;
}
else
{
is->header.next = NULL;
lang_statement_append (&os->children,
(lang_statement_union_type *) is,
&is->header.next);
}
}
}
/* Read an import or export file. */
/* Read an import or export file. For an import file, this is called
by the before_allocation emulation routine. For an export file,
this is called by the parse_args emulation routine. */
static void
gldppcmacos_read_file (filename, import)
@ -539,27 +782,35 @@ gldppcmacos_read_file (filename, import)
}
}
h = bfd_link_hash_lookup (link_info.hash, symname, false, false, true);
if (h == NULL || h->type == bfd_link_hash_new)
if (! import)
{
/* We can just ignore attempts to import an unreferenced
symbol. */
if (! import)
einfo ("%X%s:%d: attempt to export undefined symbol %s\n",
filename, lineno, symname);
}
else if (import)
{
if (! bfd_xcoff_import_symbol (output_bfd, &link_info, h, address,
imppath, impfile, impmember))
einfo ("%X%s:%d: failed to import symbol %s: %E\n",
filename, lineno, symname);
struct export_symbol_list *n;
ldlang_add_undef (symname);
n = ((struct export_symbol_list *)
xmalloc (sizeof (struct export_symbol_list)));
n->next = export_symbols;
n->name = buystring (symname);
n->syscall = syscall;
export_symbols = n;
}
else
{
if (! bfd_xcoff_export_symbol (output_bfd, &link_info, h, syscall))
einfo ("%X%s:%d: failed to export symbol %s: %E\n",
filename, lineno, symname);
h = bfd_link_hash_lookup (link_info.hash, symname, false, false,
true);
if (h == NULL || h->type == bfd_link_hash_new)
{
/* We can just ignore attempts to import an unreferenced
symbol. */
}
else
{
if (! bfd_xcoff_import_symbol (output_bfd, &link_info, h,
address, imppath, impfile,
impmember))
einfo ("%X%s:%d: failed to import symbol %s: %E\n",
filename, lineno, symname);
}
}
obstack_free (o, obstack_base (o));
@ -588,6 +839,76 @@ gldppcmacos_free (p)
free (p);
}
/* This is called by the before_allocation routine via
lang_for_each_statement. It looks for relocations and assignments
to symbols. */
static void
gldppcmacos_find_relocs (s)
lang_statement_union_type *s;
{
if (s->header.type == lang_reloc_statement_enum)
{
lang_reloc_statement_type *rs;
rs = &s->reloc_statement;
if (rs->name == NULL)
einfo ("%F%P: only relocations against symbols are permitted\n");
if (! bfd_xcoff_link_count_reloc (output_bfd, &link_info, rs->name))
einfo ("%F%P: bfd_xcoff_link_count_reloc failed: %E\n");
}
if (s->header.type == lang_assignment_statement_enum)
gldppcmacos_find_exp_assignment (s->assignment_statement.exp);
}
/* Look through an expression for an assignment statement. */
static void
gldppcmacos_find_exp_assignment (exp)
etree_type *exp;
{
struct bfd_link_hash_entry *h;
switch (exp->type.node_class)
{
case etree_provide:
h = bfd_link_hash_lookup (link_info.hash, exp->assign.dst,
false, false, false);
if (h == NULL)
break;
/* Fall through. */
case etree_assign:
if (strcmp (exp->assign.dst, ".") != 0)
{
if (! bfd_xcoff_record_link_assignment (output_bfd, &link_info,
exp->assign.dst))
einfo ("%P%F: failed to record assignment to %s: %E\n",
exp->assign.dst);
}
gldppcmacos_find_exp_assignment (exp->assign.src);
break;
case etree_binary:
gldppcmacos_find_exp_assignment (exp->binary.lhs);
gldppcmacos_find_exp_assignment (exp->binary.rhs);
break;
case etree_trinary:
gldppcmacos_find_exp_assignment (exp->trinary.cond);
gldppcmacos_find_exp_assignment (exp->trinary.lhs);
gldppcmacos_find_exp_assignment (exp->trinary.rhs);
break;
case etree_unary:
gldppcmacos_find_exp_assignment (exp->unary.child);
break;
default:
break;
}
}
static char *
gldppcmacos_get_script(isfile)
int *isfile;
@ -617,6 +938,8 @@ SECTIONS\n\
*(.rw)\n\
*(.sv)\n\
*(.ua)\n\
. = ALIGN(4);\n\
CONSTRUCTORS\n\
*(.ds)\n\
*(.tc0)\n\
*(.tc)\n\
@ -657,6 +980,7 @@ SECTIONS\n\
*(.rw)\n\
*(.sv)\n\
*(.ua)\n\
. = ALIGN(4);\n\
*(.ds)\n\
*(.tc0)\n\
*(.tc)\n\
@ -701,6 +1025,8 @@ SECTIONS\n\
*(.rw)\n\
*(.sv)\n\
*(.ua)\n\
. = ALIGN(4);\n\
CONSTRUCTORS\n\
*(.ds)\n\
*(.tc0)\n\
*(.tc)\n\
@ -748,6 +1074,8 @@ SECTIONS\n\
*(.rw)\n\
*(.sv)\n\
*(.ua)\n\
. = ALIGN(4);\n\
CONSTRUCTORS\n\
*(.ds)\n\
*(.tc0)\n\
*(.tc)\n\
@ -795,6 +1123,8 @@ SECTIONS\n\
*(.rw)\n\
*(.sv)\n\
*(.ua)\n\
. = ALIGN(4);\n\
CONSTRUCTORS\n\
*(.ds)\n\
*(.tc0)\n\
*(.tc)\n\
@ -824,7 +1154,7 @@ struct ld_emulation_xfer_struct ld_ppcmacos_emulation =
syslib_default,
hll_default,
after_parse_default,
after_open_default,
gldppcmacos_after_open,
after_allocation_default,
set_output_arch_default,
ldemul_default_target,

View file

@ -54,9 +54,13 @@
/ldemul-list.h/s/"{s}"ldemul-list\.h/"{o}"ldemul-list.h/g
/ldemul-list.h/s/^ldemul-list\.h/"{o}"ldemul-list.h/
# Edit pathnames to emulation files.
/"{s}"e.*\.c/s/"{s}"e\([-_a-z0-9]*\)\.c/"{o}"e\1.c/g
/^e.*\.c/s/^e\([-_a-z0-9]*\)\.c/"{o}"e\1.c/
# We can't run genscripts, so don't try.
/{GENSCRIPTS}/s/{GENSCRIPTS}/null-command/
#/sed.*free/,/> "{o}"ldlex.c.new/c\
# \ Catenate "{o}"lex.yy.c >"{o}"ldlex.c.new