From 5ac7a6e96e12d8e8d44d4fbfe6304f2219c603be Mon Sep 17 00:00:00 2001 From: Stan Shebs Date: Sat, 18 Nov 1995 00:50:06 +0000 Subject: [PATCH] * 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}. --- ld/emulparams/ppcmacos.sh | 4 + ld/mpw-eppcmacos.c | 400 ++++++++++++++++++++++++++++++++++---- ld/mpw-make.sed | 4 + 3 files changed, 373 insertions(+), 35 deletions(-) create mode 100644 ld/emulparams/ppcmacos.sh diff --git a/ld/emulparams/ppcmacos.sh b/ld/emulparams/ppcmacos.sh new file mode 100644 index 00000000000..b6b800c2c6c --- /dev/null +++ b/ld/emulparams/ppcmacos.sh @@ -0,0 +1,4 @@ +TEMPLATE_NAME=aix +SCRIPT_NAME=aix +OUTPUT_FORMAT="xcoff-powermac" +ARCH=powerpc diff --git a/ld/mpw-eppcmacos.c b/ld/mpw-eppcmacos.c index 9bc98127368..0febbe33db7 100644 --- a/ld/mpw-eppcmacos.c +++ b/ld/mpw-eppcmacos.c @@ -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) - { - /* 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 (! 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, diff --git a/ld/mpw-make.sed b/ld/mpw-make.sed index f672da09870..d26fdced3e0 100644 --- a/ld/mpw-make.sed +++ b/ld/mpw-make.sed @@ -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 -- 2.30.2