diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2000-09-12 19:13:03 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2000-09-12 19:13:03 +0000 |
commit | 1b50fce4c0ed748c156af3ac629e50cb5e4d0ef4 (patch) | |
tree | edee61faabd18b4a5d84e8cdb679d7a8d1fe171f /gnu/usr.bin/binutils/ld/emultempl | |
parent | 9f1193e30b5f04af9ea81c644eec79b7b535b890 (diff) |
Help stupid cvs fixing basic conflicts.
Diffstat (limited to 'gnu/usr.bin/binutils/ld/emultempl')
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/aix.em | 25 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/elf32.em | 469 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/generic.em | 16 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/gld960.em | 41 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/gld960c.em | 62 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/hppaelf.em | 40 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/linux.em | 41 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/lnk960.em | 42 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em | 24 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/pe.em | 1225 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/sunos.em | 94 | ||||
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/vanilla.em | 12 |
12 files changed, 1528 insertions, 563 deletions
diff --git a/gnu/usr.bin/binutils/ld/emultempl/aix.em b/gnu/usr.bin/binutils/ld/emultempl/aix.em index 42aa1e162e0..5eff6b59a41 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/aix.em +++ b/gnu/usr.bin/binutils/ld/emultempl/aix.em @@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* AIX emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> AIX support by Ian Lance Taylor <ian@cygnus.com> @@ -108,6 +108,7 @@ gld${EMULATION_NAME}_before_parse() #ifndef TARGET_ /* I.e., if not generic. */ ldfile_output_architecture = bfd_arch_${ARCH}; #endif /* not TARGET_ */ + config.has_shared = true; } /* Handle AIX specific options. */ @@ -215,12 +216,17 @@ gld${EMULATION_NAME}_parse_args (argc, argv) } } + /* We add s and u so to the short options list so that -s and -u on + the command line do not match -static and -unix. */ + opterr = 0; - optc = getopt_long_only (argc, argv, "-D:H:KT:z", longopts, &longind); + optc = getopt_long_only (argc, argv, "-D:H:KT:zsu", longopts, &longind); opterr = prevopterr; switch (optc) { + case 's': + case 'u': default: optind = prevoptind; return 0; @@ -360,8 +366,8 @@ gld${EMULATION_NAME}_parse_args (argc, argv) exp_nameop (NAME, "."), exp_intop (0xfff))); t = exp_binop ('&', - exp_binop ('+', t, exp_intop (7)), - exp_intop (~ (bfd_vma) 7)); + exp_binop ('+', t, exp_intop (31)), + exp_intop (~ (bfd_vma) 31)); lang_section_start (".data", t); } break; @@ -381,8 +387,8 @@ gld${EMULATION_NAME}_parse_args (argc, argv) exp_intop (val), exp_nameop (SIZEOF_HEADERS, NULL)); t = exp_binop ('&', - exp_binop ('+', t, exp_intop (7)), - exp_intop (~ (bfd_vma) 7)); + exp_binop ('+', t, exp_intop (31)), + exp_intop (~ (bfd_vma) 31)); lang_section_start (".text", t); } break; @@ -734,7 +740,7 @@ gld${EMULATION_NAME}_read_file (filename, import) obstack_free (o, obstack_base (o)); } else if (*s == '(') - einfo ("%F%s%d: #! ([member]) is not supported in import files", + einfo ("%F%s%d: #! ([member]) is not supported in import files\n", filename, lineno); else { @@ -974,7 +980,7 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc="-f ${srcdir}/emultempl/stringify.sed" +sc="-f stringify.sed" cat >>e${EMULATION_NAME}.c <<EOF { @@ -1038,6 +1044,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = 0, /* place_orphan */ 0, /* set_symbols */ gld${EMULATION_NAME}_parse_args, - gld${EMULATION_NAME}_unrecognized_file + gld${EMULATION_NAME}_unrecognized_file, + NULL /* find_potential_libraries */ }; EOF diff --git a/gnu/usr.bin/binutils/ld/emultempl/elf32.em b/gnu/usr.bin/binutils/ld/emultempl/elf32.em index 5031dd02283..2913ecf1bcb 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/elf32.em +++ b/gnu/usr.bin/binutils/ld/emultempl/elf32.em @@ -7,7 +7,8 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* ${ELFSIZE} bit ELF emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 93, 94, 95, 1996 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> ELF support by Ian Lance Taylor <ian@cygnus.com> @@ -54,8 +55,10 @@ static void gld${EMULATION_NAME}_check_needed static void gld${EMULATION_NAME}_stat_needed PARAMS ((lang_input_statement_type *)); static boolean gld${EMULATION_NAME}_search_needed - PARAMS ((const char *, const char *)); -static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *)); + PARAMS ((const char *, const char *, int)); +static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int)); +static void gld${EMULATION_NAME}_vercheck + PARAMS ((lang_input_statement_type *)); static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); static void gld${EMULATION_NAME}_find_statement_assignment PARAMS ((lang_statement_union_type *)); @@ -71,10 +74,12 @@ gld${EMULATION_NAME}_before_parse() { ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`; config.dynamic_link = ${DYNAMIC_LINK-true}; + config.has_shared = `if test -n "$GENERATE_SHLIB_SCRIPT" ; then echo true ; else echo false ; fi`; } /* Try to open a dynamic archive. This is where we know that ELF - dynamic libraries have an extension of .so. */ + dynamic libraries have an extension of .so (or .sl on oddball systems + like hpux). */ static boolean gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) @@ -90,13 +95,27 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) filename = entry->filename; + /* This allocates a few bytes too many when EXTRA_SHLIB_EXTENSION + is defined, but it does not seem worth the headache to optimize + away those two bytes of space. */ string = (char *) xmalloc (strlen (search->name) + strlen (filename) + strlen (arch) +#ifdef EXTRA_SHLIB_EXTENSION + + strlen (EXTRA_SHLIB_EXTENSION) +#endif + sizeof "/lib.so"); sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); +#ifdef EXTRA_SHLIB_EXTENSION + /* Try the .so extension first. If that fails build a new filename + using EXTRA_SHLIB_EXTENSION. */ + if (! ldfile_try_open_bfd (string, entry)) + sprintf (string, "%s/lib%s%s%s", search->name, + filename, arch, EXTRA_SHLIB_EXTENSION); +#endif + if (! ldfile_try_open_bfd (string, entry)) { free (string); @@ -124,10 +143,16 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) char *needed_name; ASSERT (entry->is_archive && entry->search_dirs_flag); - needed_name = (char *) xmalloc (strlen (filename) - + strlen (arch) - + sizeof "lib.so"); - sprintf (needed_name, "lib%s%s.so", filename, arch); + + /* Rather than duplicating the logic above. Just use the + filename we recorded earlier. + + First strip off everything before the last '/'. */ + filename = strrchr (entry->filename, '/'); + filename++; + + needed_name = (char *) xmalloc (strlen (filename) + 1); + strcpy (needed_name, filename); bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); } @@ -136,18 +161,21 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) EOF if [ "x${host}" = "x${target}" ] ; then - if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) cat >>e${EMULATION_NAME}.c <<EOF /* For a native linker, check the file /etc/ld.so.conf for directories in which we may find shared libraries. /etc/ld.so.conf is really only meaningful on Linux, but we check it on other systems anyhow. */ -static boolean gld${EMULATION_NAME}_check_ld_so_conf PARAMS ((const char *)); +static boolean gld${EMULATION_NAME}_check_ld_so_conf + PARAMS ((const char *, int)); static boolean -gld${EMULATION_NAME}_check_ld_so_conf (name) +gld${EMULATION_NAME}_check_ld_so_conf (name, force) const char *name; + int force; { static boolean initialized; static char *ld_so_conf; @@ -215,20 +243,23 @@ gld${EMULATION_NAME}_check_ld_so_conf (name) if (ld_so_conf == NULL) return false; - return gld${EMULATION_NAME}_search_needed (ld_so_conf, name); + return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force); } EOF - fi + ;; + esac fi cat >>e${EMULATION_NAME}.c <<EOF /* These variables are required to pass information back and forth - between after_open and check_needed and stat_needed. */ + between after_open and check_needed and stat_needed and vercheck. */ static struct bfd_link_needed_list *global_needed; static struct stat global_stat; static boolean global_found; +static struct bfd_link_needed_list *global_vercheck_needed; +static boolean global_vercheck_failed; /* This is called after all the input files have been opened. */ @@ -254,9 +285,7 @@ gld${EMULATION_NAME}_after_open () for (l = needed; l != NULL; l = l->next) { struct bfd_link_needed_list *ll; - const char *lib_path; - size_t len; - search_dirs_type *search; + int force; /* If we've already seen this file, skip it. */ for (ll = needed; ll != l; ll = ll->next) @@ -277,55 +306,75 @@ gld${EMULATION_NAME}_after_open () linker will search. That means that we want to use rpath_link, rpath, then the environment variable LD_LIBRARY_PATH (native only), then the linker script - LIB_SEARCH_DIRS. We do not search using the -L arguments. */ - if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, - l->name)) - continue; - if (gld${EMULATION_NAME}_search_needed (command_line.rpath, l->name)) - continue; - if (command_line.rpath_link == NULL - && command_line.rpath == NULL) + LIB_SEARCH_DIRS. We do not search using the -L arguments. + + We search twice. The first time, we skip objects which may + introduce version mismatches. The second time, we force + their use. See gld${EMULATION_NAME}_vercheck comment. */ + for (force = 0; force < 2; force++) { - lib_path = (const char *) getenv ("LD_RUN_PATH"); - if (gld${EMULATION_NAME}_search_needed (lib_path, l->name)) - continue; - } + const char *lib_path; + size_t len; + search_dirs_type *search; + + if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, + l->name, force)) + break; + if (gld${EMULATION_NAME}_search_needed (command_line.rpath, + l->name, force)) + break; + if (command_line.rpath_link == NULL + && command_line.rpath == NULL) + { + lib_path = (const char *) getenv ("LD_RUN_PATH"); + if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, + force)) + break; + } EOF if [ "x${host}" = "x${target}" ] ; then - if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) cat >>e${EMULATION_NAME}.c <<EOF - lib_path = (const char *) getenv ("LD_LIBRARY_PATH"); - if (gld${EMULATION_NAME}_search_needed (lib_path, l->name)) - continue; + lib_path = (const char *) getenv ("LD_LIBRARY_PATH"); + if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) + break; EOF - fi + ;; + esac fi cat >>e${EMULATION_NAME}.c <<EOF - len = strlen (l->name); - for (search = search_head; search != NULL; search = search->next) - { - char *filename; - - if (search->cmdline) - continue; - filename = (char *) xmalloc (strlen (search->name) + len + 2); - sprintf (filename, "%s/%s", search->name, l->name); - if (gld${EMULATION_NAME}_try_needed (filename)) + len = strlen (l->name); + for (search = search_head; search != NULL; search = search->next) + { + char *filename; + + if (search->cmdline) + continue; + filename = (char *) xmalloc (strlen (search->name) + len + 2); + sprintf (filename, "%s/%s", search->name, l->name); + if (gld${EMULATION_NAME}_try_needed (filename, force)) + break; + free (filename); + } + if (search != NULL) break; - free (filename); - } - if (search != NULL) - continue; EOF if [ "x${host}" = "x${target}" ] ; then - if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) cat >>e${EMULATION_NAME}.c <<EOF - if (gld${EMULATION_NAME}_check_ld_so_conf (l->name)) - continue; + if (gld${EMULATION_NAME}_check_ld_so_conf (l->name, force)) + break; EOF - fi + ;; + esac fi cat >>e${EMULATION_NAME}.c <<EOF + } + + if (force < 2) + continue; einfo ("%P: warning: %s, needed by %B, not found (try using --rpath)\n", l->name, l->by); @@ -335,9 +384,10 @@ cat >>e${EMULATION_NAME}.c <<EOF /* Search for a needed file in a path. */ static boolean -gld${EMULATION_NAME}_search_needed (path, name) +gld${EMULATION_NAME}_search_needed (path, name, force) const char *path; const char *name; + int force; { const char *s; size_t len; @@ -364,7 +414,7 @@ gld${EMULATION_NAME}_search_needed (path, name) } strcpy (sset, name); - if (gld${EMULATION_NAME}_try_needed (filename)) + if (gld${EMULATION_NAME}_try_needed (filename, force)) return true; free (filename); @@ -378,11 +428,13 @@ gld${EMULATION_NAME}_search_needed (path, name) } /* This function is called for each possible name for a dynamic object - named by a DT_NEEDED entry. */ + named by a DT_NEEDED entry. The FORCE parameter indicates whether + to skip the check for a conflicting version. */ static boolean -gld${EMULATION_NAME}_try_needed (name) +gld${EMULATION_NAME}_try_needed (name, force) const char *name; + int force; { bfd *abfd; @@ -400,6 +452,62 @@ gld${EMULATION_NAME}_try_needed (name) return false; } + /* Check whether this object would include any conflicting library + versions. If FORCE is set, then we skip this check; we use this + the second time around, if we couldn't find any compatible + instance of the shared library. */ + + if (! force) + { + struct bfd_link_needed_list *needed; + + if (! bfd_elf_get_bfd_needed_list (abfd, &needed)) + einfo ("%F%P:%B: bfd_elf_get_bfd_needed_list failed: %E\n", abfd); + + if (needed != NULL) + { + global_vercheck_needed = needed; + global_vercheck_failed = false; + lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); + if (global_vercheck_failed) + { + (void) bfd_close (abfd); + /* Return false to force the caller to move on to try + another file on the search path. */ + return false; + } + + /* But wait! It gets much worse. On Linux, if a shared + library does not use libc at all, we are supposed to skip + it the first time around in case we encounter a shared + library later on with the same name which does use the + version of libc that we want. This is much too horrible + to use on any system other than Linux. */ + +EOF +case ${target} in + *-*-linux-gnu*) + cat >>e${EMULATION_NAME}.c <<EOF + { + struct bfd_link_needed_list *l; + + for (l = needed; l != NULL; l = l->next) + if (strncmp (l->name, "libc.so", 7) == 0) + break; + if (l == NULL) + { + (void) bfd_close (abfd); + return false; + } + } + +EOF + ;; +esac +cat >>e${EMULATION_NAME}.c <<EOF + } + } + /* We've found a dynamic object matching the DT_NEEDED entry. */ /* We have already checked that there is no other input file of the @@ -538,6 +646,78 @@ gld${EMULATION_NAME}_stat_needed (s) global_needed->name, global_needed->by, f); } +/* On Linux, it's possible to have different versions of the same + shared library linked against different versions of libc. The + dynamic linker somehow tags which libc version to use in + /etc/ld.so.cache, and, based on the libc that it sees in the + executable, chooses which version of the shared library to use. + + We try to do a similar check here by checking whether this shared + library needs any other shared libraries which may conflict with + libraries we have already included in the link. If it does, we + skip it, and try to find another shared library farther on down the + link path. + + This is called via lang_for_each_input_file. + GLOBAL_VERCHECK_NEEDED is the list of objects needed by the object + which we ar checking. This sets GLOBAL_VERCHECK_FAILED if we find + a conflicting version. */ + +static void +gld${EMULATION_NAME}_vercheck (s) + lang_input_statement_type *s; +{ + const char *soname, *f; + struct bfd_link_needed_list *l; + + if (global_vercheck_failed) + return; + if (s->the_bfd == NULL + || (bfd_get_file_flags (s->the_bfd) & DYNAMIC) == 0) + return; + + soname = bfd_elf_get_dt_soname (s->the_bfd); + if (soname == NULL) + soname = bfd_get_filename (s->the_bfd); + + f = strrchr (soname, '/'); + if (f != NULL) + ++f; + else + f = soname; + + for (l = global_vercheck_needed; l != NULL; l = l->next) + { + const char *suffix; + + if (strcmp (f, l->name) == 0) + { + /* Probably can't happen, but it's an easy check. */ + continue; + } + + if (strchr (l->name, '/') != NULL) + continue; + + suffix = strstr (l->name, ".so."); + if (suffix == NULL) + continue; + + suffix += sizeof ".so." - 1; + + if (strncmp (f, l->name, suffix - l->name) == 0) + { + /* Here we know that S is a dynamic object FOO.SO.VER1, and + the object we are considering needs a dynamic object + FOO.SO.VER2, and VER1 and VER2 are different. This + appears to be a version mismatch, so we tell the caller + to try a different version of this library. */ + global_vercheck_failed = true; + return; + } + } +} + /* This is called after the sections have been attached to output sections, but before any sizes or addresses have been set. */ @@ -557,12 +737,11 @@ gld${EMULATION_NAME}_before_allocation () rpath = command_line.rpath; if (rpath == NULL) rpath = (const char *) getenv ("LD_RUN_PATH"); - if (! bfd_elf${ELFSIZE}_size_dynamic_sections (output_bfd, - command_line.soname, - rpath, - command_line.export_dynamic, - &link_info, - &sinterp)) + if (! (bfd_elf${ELFSIZE}_size_dynamic_sections + (output_bfd, command_line.soname, rpath, + command_line.export_dynamic, command_line.filter_shlib, + (const char * const *) command_line.auxiliary_filters, + &link_info, &sinterp, lang_elf_version_info))) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); /* Let the user override the dynamic linker we are using. */ @@ -611,37 +790,6 @@ gld${EMULATION_NAME}_before_allocation () s->_raw_size = 0; } } - -#if defined (TARGET_IS_elf32bmip) || defined (TARGET_IS_elf32lmip) - /* For MIPS ELF the .reginfo section requires special handling. - Each input section is 24 bytes, and the final output section must - also be 24 bytes. We handle this by clobbering all but the first - input section size to 0. The .reginfo section is handled - specially by the backend code anyhow. */ - { - boolean found = false; - LANG_FOR_EACH_INPUT_STATEMENT (is) - { - asection *s; - - if (is->just_syms_flag) - continue; - - s = bfd_get_section_by_name (is->the_bfd, ".reginfo"); - if (s == NULL) - continue; - - if (! found) - { - found = true; - continue; - } - - s->_raw_size = 0; - s->_cooked_size = 0; - } - } -#endif } /* This is called by the before_allocation routine via @@ -724,6 +872,7 @@ static lang_output_section_statement_type *hold_rodata; static lang_output_section_statement_type *hold_data; static lang_output_section_statement_type *hold_bss; static lang_output_section_statement_type *hold_rel; +static lang_output_section_statement_type *hold_interp; /*ARGSUSED*/ static boolean @@ -737,6 +886,7 @@ gld${EMULATION_NAME}_place_orphan (file, s) lang_statement_list_type add; etree_type *address; const char *secname, *ps; + const char *outsecname; lang_output_section_statement_type *os; if ((s->flags & SEC_ALLOC) == 0) @@ -768,10 +918,19 @@ gld${EMULATION_NAME}_place_orphan (file, s) } /* Decide which segment the section should go in based on the - section name and section flags. */ + section name and section flags. We put loadable .note sections + right after the .interp section, so that the PT_NOTE segment is + stored right after the program headers where the OS can read it + in the first page. */ place = NULL; - if ((s->flags & SEC_HAS_CONTENTS) == 0 - && hold_bss != NULL) + if (s->flags & SEC_EXCLUDE) + return false; + else if ((s->flags & SEC_LOAD) != 0 + && strncmp (secname, ".note", 4) == 0 + && hold_interp != NULL) + place = hold_interp; + else if ((s->flags & SEC_HAS_CONTENTS) == 0 + && hold_bss != NULL) place = hold_bss; else if ((s->flags & SEC_READONLY) == 0 && hold_data != NULL) @@ -789,12 +948,36 @@ gld${EMULATION_NAME}_place_orphan (file, s) if (place == NULL) return false; + /* Choose a unique name for the section. This will be needed if the + same section name appears in the input file with different + loadable or allocateable characteristics. */ + outsecname = secname; + if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) + { + unsigned int len; + char *newname; + unsigned int i; + + len = strlen (outsecname); + newname = xmalloc (len + 5); + strcpy (newname, outsecname); + i = 0; + do + { + sprintf (newname + len, "%d", i); + ++i; + } + while (bfd_get_section_by_name (output_bfd, newname) != NULL); + + outsecname = newname; + } + /* Create the section in the output file, and put it in the right place. This shuffling is to make the output file look neater. */ - snew = bfd_make_section (output_bfd, secname); + snew = bfd_make_section (output_bfd, outsecname); if (snew == NULL) einfo ("%P%F: output format %s cannot represent section called %s\n", - output_bfd->xvec->name, secname); + output_bfd->xvec->name, outsecname); if (place->bfd_section != NULL) { for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) @@ -811,15 +994,15 @@ gld${EMULATION_NAME}_place_orphan (file, s) /* If the name of the section is representable in C, then create symbols to mark the start and the end of the section. */ - for (ps = secname; *ps != '\0'; ps++) - if (! isalnum (*ps) && *ps != '_') + for (ps = outsecname; *ps != '\0'; ps++) + if (! isalnum ((unsigned char) *ps) && *ps != '_') break; if (*ps == '\0' && config.build_constructors) { char *symname; - symname = (char *) xmalloc (ps - secname + sizeof "__start_"); - sprintf (symname, "__start_%s", secname); + symname = (char *) xmalloc (ps - outsecname + sizeof "__start_"); + sprintf (symname, "__start_%s", outsecname); lang_add_assignment (exp_assop ('=', symname, exp_unop (ALIGN_K, exp_intop ((bfd_vma) 1 @@ -831,25 +1014,26 @@ gld${EMULATION_NAME}_place_orphan (file, s) else address = exp_intop ((bfd_vma) 0); - lang_enter_output_section_statement (secname, address, 0, + lang_enter_output_section_statement (outsecname, address, 0, (bfd_vma) 0, (etree_type *) NULL, (etree_type *) NULL, (etree_type *) NULL); - os = lang_output_section_statement_lookup (secname); + os = lang_output_section_statement_lookup (outsecname); wild_doit (&os->children, s, os, file); lang_leave_output_section_statement - ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL); + ((bfd_vma) 0, "*default*", (struct lang_output_section_phdr_list *) NULL, + "*default*"); stat_ptr = &add; if (*ps == '\0' && config.build_constructors) { char *symname; - symname = (char *) xmalloc (ps - secname + sizeof "__stop_"); - sprintf (symname, "__stop_%s", secname); + symname = (char *) xmalloc (ps - outsecname + sizeof "__stop_"); + sprintf (symname, "__stop_%s", outsecname); lang_add_assignment (exp_assop ('=', symname, exp_nameop (NAME, "."))); } @@ -874,7 +1058,10 @@ gld${EMULATION_NAME}_place_section (s) os = &s->output_section_statement; - if (strcmp (os->name, hold_section->name) == 0) + if (strcmp (os->name, hold_section->name) == 0 + && os->bfd_section != NULL + && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) + == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) hold_use = os; if (strcmp (os->name, ".text") == 0) @@ -887,8 +1074,11 @@ gld${EMULATION_NAME}_place_section (s) hold_bss = os; else if (hold_rel == NULL && os->bfd_section != NULL + && (os->bfd_section->flags & SEC_ALLOC) != 0 && strncmp (os->name, ".rel", 4) == 0) hold_rel = os; + else if (strcmp (os->name, ".interp") == 0) + hold_interp = os; } static char * @@ -901,30 +1091,31 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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 if (link_info.shared) - return `sed "$sc" ldscripts/${EMULATION_NAME}.xs`; - else - return `sed "$sc" ldscripts/${EMULATION_NAME}.x`; -} + 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 + +if test -n "$GENERATE_SHLIB_SCRIPT" ; then +echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c +fi + +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. @@ -950,6 +1141,22 @@ EOF fi +if test -n "$PARSE_AND_LIST_ARGS" ; then +cat >>e${EMULATION_NAME}.c <<EOF +static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **)); +static void gld_${EMULATION_NAME}_list_options PARAMS ((FILE * file)); + + $PARSE_AND_LIST_ARGS +EOF +else + +cat >>e${EMULATION_NAME}.c <<EOF +#define gld_${EMULATION_NAME}_parse_args NULL +#define gld_${EMULATION_NAME}_list_options NULL +EOF + +fi + cat >>e${EMULATION_NAME}.c <<EOF struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = @@ -966,9 +1173,15 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - NULL, - NULL, + NULL, /* finish */ + NULL, /* create output section statements */ gld${EMULATION_NAME}_open_dynamic_archive, - gld${EMULATION_NAME}_place_orphan + gld${EMULATION_NAME}_place_orphan, + NULL, /* set_symbols */ + gld_${EMULATION_NAME}_parse_args, + NULL, /* unrecognized_file */ + gld_${EMULATION_NAME}_list_options, + NULL, /* recognized_file */ + NULL /* find_potential_libraries */ }; EOF diff --git a/gnu/usr.bin/binutils/ld/emultempl/generic.em b/gnu/usr.bin/binutils/ld/emultempl/generic.em index 1c0c8eb214d..6635e09e20a 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/generic.em +++ b/gnu/usr.bin/binutils/ld/emultempl/generic.em @@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* emulate the original gld for the given ${EMULATION_NAME} - Copyright (C) 1991, 1993 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 96, 1999 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of GLD, the Gnu Linker. @@ -56,7 +56,7 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc="-f ${srcdir}/emultempl/stringify.sed" +sc="-f stringify.sed" cat >>e${EMULATION_NAME}.c <<EOF { @@ -113,6 +113,16 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = before_allocation_default, gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", - "${OUTPUT_FORMAT}" + "${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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/gld960.em b/gnu/usr.bin/binutils/ld/emultempl/gld960.em index df998fb74a8..ad8e5bfafa2 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/gld960.em +++ b/gnu/usr.bin/binutils/ld/emultempl/gld960.em @@ -1,7 +1,7 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF -/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +/* Copyright (C) 1991, 93, 94, 95, 1999 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -111,28 +111,25 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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`; -} + 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. @@ -171,6 +168,16 @@ struct ld_emulation_xfer_struct ld_gld960_emulation = before_allocation_default, gld960_get_script, "960", - "" + "", + 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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/gld960c.em b/gnu/usr.bin/binutils/ld/emultempl/gld960c.em index 492d5d3d6ae..c7f162455cb 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/gld960c.em +++ b/gnu/usr.bin/binutils/ld/emultempl/gld960c.em @@ -1,7 +1,7 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF -/* Copyright (C) 1991, 1993 Free Software Foundation, Inc. +/* Copyright (C) 1991, 93, 94, 95, 96, 1999 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -16,14 +16,16 @@ 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 GLD; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +along with GLD; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ /* * emulate the Intels port of gld */ +#include <ctype.h> #include "bfd.h" #include "sysdep.h" #include "libiberty.h" @@ -78,7 +80,20 @@ static void gld960_before_parse() static void gld960_set_output_arch() { - bfd_set_arch_mach(output_bfd, ldfile_output_architecture, bfd_mach_i960_core); + if (ldfile_output_machine_name != NULL + && *ldfile_output_machine_name != '\0') + { + char *s, *s1; + + s = concat ("i960:", ldfile_output_machine_name, (char *) NULL); + for (s1 = s; *s1 != '\0'; s1++) + if (isupper ((unsigned char) *s1)) + *s1 = tolower ((unsigned char) *s1); + ldfile_set_output_arch (s); + free (s); + } + + set_output_arch_default (); } static char * @@ -112,28 +127,25 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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`; -} + 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. @@ -172,6 +184,16 @@ struct ld_emulation_xfer_struct ld_gld960coff_emulation = before_allocation_default, gld960_get_script, "960coff", - "" + "", + 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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em b/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em index 57920174a8a..fde43628005 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em +++ b/gnu/usr.bin/binutils/ld/emultempl/hppaelf.em @@ -2,7 +2,7 @@ # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF /* An emulation for HP PA-RISC ELF linkers. - Copyright (C) 1991, 1993 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 97, 1999 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of GLD, the Gnu Linker. @@ -48,9 +48,6 @@ extern lang_statement_list_type file_chain; static void hppaelf_before_parse () { - link_info.lprefix = "L$"; - link_info.lprefix_len = 2; - ldfile_output_architecture = bfd_arch_hppa; } @@ -219,28 +216,25 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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`; -} + 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. @@ -282,5 +276,13 @@ struct ld_emulation_xfer_struct ld_hppaelf_emulation = "elf32-hppa", hppaelf_finish, hppaelf_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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/linux.em b/gnu/usr.bin/binutils/ld/emultempl/linux.em index 6860c3ffaf2..dfa855edd07 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/linux.em +++ b/gnu/usr.bin/binutils/ld/emultempl/linux.em @@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* Linux a.out emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 1993, 1994, 1995, 1996 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 96, 98, 1999 Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> Linux support by Eric Youngdale <ericy@cais.cais.com> @@ -53,6 +53,7 @@ gld${EMULATION_NAME}_before_parse() { ldfile_output_architecture = bfd_arch_${ARCH}; config.dynamic_link = true; + config.has_shared = true; } /* Try to open a dynamic archive. This is where we know that Linux @@ -139,28 +140,25 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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`; -} + 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. @@ -200,8 +198,15 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - NULL, + NULL, /* finish */ gld${EMULATION_NAME}_create_output_section_statements, - gld${EMULATION_NAME}_open_dynamic_archive + gld${EMULATION_NAME}_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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/lnk960.em b/gnu/usr.bin/binutils/ld/emultempl/lnk960.em index 066d46bb328..a4c32579ee7 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/lnk960.em +++ b/gnu/usr.bin/binutils/ld/emultempl/lnk960.em @@ -2,7 +2,7 @@ # It does some substitutions. cat >e${EMULATION_NAME}.c <<EOF /* intel coff loader emulation specific stuff - Copyright (C) 1991, 1993 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 96, 1999 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com This file is part of GLD, the Gnu Linker. @@ -263,27 +263,25 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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`; -} + 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. @@ -322,6 +320,16 @@ struct ld_emulation_xfer_struct ld_lnk960_emulation = lnk960_before_allocation, lnk960_get_script, "lnk960", - "" + "", + 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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em b/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em index 7ceb6e07b8a..4c932a14fad 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em +++ b/gnu/usr.bin/binutils/ld/emultempl/mipsecoff.em @@ -4,7 +4,7 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* Handle embedded relocs for MIPS. - Copyright 1994 Free Software Foundation, Inc. + Copyright 1994, 95, 97, 1999 Free Software Foundation, Inc. Written by Ian Lance Taylor <ian@cygnus.com> based on generic.em. This file is part of GLD, the Gnu Linker. @@ -92,7 +92,7 @@ gld${EMULATION_NAME}_after_open () || ! bfd_set_section_alignment (abfd, relsec, 2) || ! bfd_set_section_size (abfd, relsec, datasec->reloc_count * 4)) - einfo ("%F%B: can not create .rel.sdata section: %E"); + einfo ("%F%B: can not create .rel.sdata section: %E\n"); } /* Double check that all other data sections are empty, as is @@ -113,7 +113,7 @@ check_sections (abfd, sec, sdatasec) if ((bfd_get_section_flags (abfd, sec) & SEC_CODE) == 0 && sec != (asection *) sdatasec && sec->reloc_count != 0) - einfo ("%P%X: section %s has relocs; can not use --embedded-relocs", + einfo ("%P%X: section %s has relocs; can not use --embedded-relocs\n", abfd, bfd_get_section_name (abfd, sec)); } @@ -148,10 +148,10 @@ gld${EMULATION_NAME}_after_allocation () &errmsg)) { if (errmsg == NULL) - einfo ("%B%X: can not create runtime reloc information: %E", + einfo ("%B%X: can not create runtime reloc information: %E\n", abfd); else - einfo ("%X%B: can not create runtime reloc information: %s", + einfo ("%X%B: can not create runtime reloc information: %s\n", abfd, errmsg); } } @@ -167,7 +167,7 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc="-f ${srcdir}/emultempl/stringify.sed" +sc="-f stringify.sed" cat >>e${EMULATION_NAME}.c <<EOF { @@ -224,6 +224,16 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = before_allocation_default, gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", - "${OUTPUT_FORMAT}" + "${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 diff --git a/gnu/usr.bin/binutils/ld/emultempl/pe.em b/gnu/usr.bin/binutils/ld/emultempl/pe.em index f0daa5d1092..d13bb40be36 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/pe.em +++ b/gnu/usr.bin/binutils/ld/emultempl/pe.em @@ -1,15 +1,10 @@ # This shell script emits a C file. -*- C -*- # It does some substitutions. -cat >e${EMULATION_NAME}.c <<EOF -/* For WINDOWS_NT */ -/* The original file generated returned different default scripts depending - on whether certain switches were set, but these switches pertain to the - Linux system and that particular version of coff. In the NT case, we - only determine if the subsystem is console or windows in order to select - the correct entry point by default. */ - - +rm -f e${EMULATION_NAME}.c +(echo;echo;echo;echo;echo)>e${EMULATION_NAME}.c # there, now line numbers match ;-) +cat >>e${EMULATION_NAME}.c <<EOF /* This file is part of GLD, the Gnu Linker. + Copyright 1995, 96, 97, 98, 99, 2000 Free Software Foundation, Inc. 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 @@ -25,11 +20,18 @@ 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. */ +/* For WINDOWS_NT */ +/* The original file generated returned different default scripts depending + on whether certain switches were set, but these switches pertain to the + Linux system and that particular version of coff. In the NT case, we + only determine if the subsystem is console or windows in order to select + the correct entry point by default. */ + #include "bfd.h" #include "sysdep.h" #include "bfdlink.h" #include "getopt.h" -#include "ld.h" +#include "libiberty.h" #include "ld.h" #include "ldmain.h" #include "ldgram.h" @@ -41,35 +43,101 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ldctor.h" #include "ldfile.h" #include "coff/internal.h" + +/* FIXME: This is a BFD internal header file, and we should not be + using it here. */ #include "../bfd/libcoff.h" +#include "deffile.h" +#include "pe-dll.h" + #define TARGET_IS_${EMULATION_NAME} +/* Permit the emulation parameters to override the default section + alignment by setting OVERRIDE_SECTION_ALIGNMENT. FIXME: This makes + it seem that include/coff/internal.h should not define + PE_DEF_SECTION_ALIGNMENT. */ +#if PE_DEF_SECTION_ALIGNMENT != ${OVERRIDE_SECTION_ALIGNMENT:-PE_DEF_SECTION_ALIGNMENT} +#undef PE_DEF_SECTION_ALIGNMENT +#define PE_DEF_SECTION_ALIGNMENT ${OVERRIDE_SECTION_ALIGNMENT} +#endif + +#if defined(TARGET_IS_i386pe) +#define DLL_SUPPORT +#endif +#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) || defined(TARGET_IS_armpe) +#define DLL_SUPPORT +#endif + +#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT) +#define PE_DEF_SUBSYSTEM 3 +#else +#undef NT_EXE_IMAGE_BASE +#undef PE_DEF_SECTION_ALIGNMENT +#undef PE_DEF_FILE_ALIGNMENT +#define NT_EXE_IMAGE_BASE 0x00010000 +#ifdef TARGET_IS_armpe +#define PE_DEF_SECTION_ALIGNMENT 0x00001000 +#define PE_DEF_SUBSYSTEM 9 +#else +#define PE_DEF_SECTION_ALIGNMENT 0x00000400 +#define PE_DEF_SUBSYSTEM 2 +#endif +#define PE_DEF_FILE_ALIGNMENT 0x00000200 +#endif + +#ifdef TARGET_IS_arm_epoc_pe +#define bfd_arm_pe_allocate_interworking_sections \ + bfd_arm_epoc_pe_allocate_interworking_sections +#define bfd_arm_pe_get_bfd_for_interworking \ + bfd_arm_epoc_pe_get_bfd_for_interworking +#define bfd_arm_pe_process_before_allocation \ + bfd_arm_epoc_pe_process_before_allocation +#endif + static void gld_${EMULATION_NAME}_set_symbols PARAMS ((void)); static void gld_${EMULATION_NAME}_after_open PARAMS ((void)); static void gld_${EMULATION_NAME}_before_parse PARAMS ((void)); +static void gld_${EMULATION_NAME}_after_parse PARAMS ((void)); static void gld_${EMULATION_NAME}_before_allocation PARAMS ((void)); -static boolean gld${EMULATION_NAME}_place_orphan +static boolean gld_${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); +static void gld${EMULATION_NAME}_place_section + PARAMS ((lang_statement_union_type *)); static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *)); static int gld_${EMULATION_NAME}_parse_args PARAMS ((int, char **)); - -#if 0 /* argument to qsort so don't prototype */ -static int sort_by_file_name PARAMS ((void *, void *)); -static int sort_by_section_name PARAMS ((void *, void *)); -#endif -static lang_statement_union_type **sort_sections_1 - PARAMS ((lang_statement_union_type **, lang_statement_union_type *, int, - int (*)())); -static void sort_sections PARAMS ((lang_statement_union_type *)); +static void gld_${EMULATION_NAME}_finish PARAMS ((void)); static struct internal_extra_pe_aouthdr pe; static int dll; +static int support_old_code = 0; +static char * thumb_entry_symbol = NULL; +static lang_assignment_statement_type *image_base_statement = 0; + +static int pe_enable_stdcall_fixup = -1; /* 0=disable 1=enable */ +#ifdef DLL_SUPPORT +static char *pe_out_def_filename = 0; +static char *pe_implib_filename = 0; +#endif + +extern const char *output_filename; static void gld_${EMULATION_NAME}_before_parse() { + output_filename = "${EXECUTABLE_NAME:-a.exe}"; ldfile_output_architecture = bfd_arch_${ARCH}; +#ifdef DLL_SUPPORT + config.has_shared = 1; + +#if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) +#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe + lang_add_entry ("WinMainCRTStartup", 1); +#else + lang_add_entry ("_WinMainCRTStartup", 1); +#endif +#endif +#endif } /* PE format extra command line options. */ @@ -89,31 +157,62 @@ gld_${EMULATION_NAME}_before_parse() #define OPTION_STACK (OPTION_SECTION_ALIGNMENT + 1) #define OPTION_SUBSYSTEM (OPTION_STACK + 1) #define OPTION_HEAP (OPTION_SUBSYSTEM + 1) - -static struct option longopts[] = { +#define OPTION_SUPPORT_OLD_CODE (OPTION_HEAP + 1) +#define OPTION_OUT_DEF (OPTION_SUPPORT_OLD_CODE + 1) +#define OPTION_EXPORT_ALL (OPTION_OUT_DEF + 1) +#define OPTION_EXCLUDE_SYMBOLS (OPTION_EXPORT_ALL + 1) +#define OPTION_KILL_ATS (OPTION_EXCLUDE_SYMBOLS + 1) +#define OPTION_STDCALL_ALIASES (OPTION_KILL_ATS + 1) +#define OPTION_ENABLE_STDCALL_FIXUP (OPTION_STDCALL_ALIASES + 1) +#define OPTION_DISABLE_STDCALL_FIXUP (OPTION_ENABLE_STDCALL_FIXUP + 1) +#define OPTION_IMPLIB_FILENAME (OPTION_DISABLE_STDCALL_FIXUP + 1) +#define OPTION_THUMB_ENTRY (OPTION_IMPLIB_FILENAME + 1) +#define OPTION_WARN_DUPLICATE_EXPORTS (OPTION_THUMB_ENTRY + 1) +#define OPTION_IMP_COMPAT (OPTION_WARN_DUPLICATE_EXPORTS + 1) + +static struct option longopts[] = +{ /* PE options */ - {"base-file", required_argument, NULL, OPTION_BASE_FILE}, - {"dll", no_argument, NULL, OPTION_DLL}, - {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT}, - {"heap", required_argument, NULL, OPTION_HEAP}, - {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, - {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION}, - {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION}, - {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION}, - {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION}, - {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION}, - {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION}, - {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT}, - {"stack", required_argument, NULL, OPTION_STACK}, - {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM}, - {NULL, no_argument, NULL, 0} - }; + {"base-file", required_argument, NULL, OPTION_BASE_FILE}, + {"dll", no_argument, NULL, OPTION_DLL}, + {"file-alignment", required_argument, NULL, OPTION_FILE_ALIGNMENT}, + {"heap", required_argument, NULL, OPTION_HEAP}, + {"image-base", required_argument, NULL, OPTION_IMAGE_BASE}, + {"major-image-version", required_argument, NULL, OPTION_MAJOR_IMAGE_VERSION}, + {"major-os-version", required_argument, NULL, OPTION_MAJOR_OS_VERSION}, + {"major-subsystem-version", required_argument, NULL, OPTION_MAJOR_SUBSYSTEM_VERSION}, + {"minor-image-version", required_argument, NULL, OPTION_MINOR_IMAGE_VERSION}, + {"minor-os-version", required_argument, NULL, OPTION_MINOR_OS_VERSION}, + {"minor-subsystem-version", required_argument, NULL, OPTION_MINOR_SUBSYSTEM_VERSION}, + {"section-alignment", required_argument, NULL, OPTION_SECTION_ALIGNMENT}, + {"stack", required_argument, NULL, OPTION_STACK}, + {"subsystem", required_argument, NULL, OPTION_SUBSYSTEM}, + {"support-old-code", no_argument, NULL, OPTION_SUPPORT_OLD_CODE}, + {"thumb-entry", required_argument, NULL, OPTION_THUMB_ENTRY}, +#ifdef DLL_SUPPORT + /* getopt allows abbreviations, so we do this to stop it from treating -o + as an abbreviation for this option */ + {"output-def", required_argument, NULL, OPTION_OUT_DEF}, + {"output-def", required_argument, NULL, OPTION_OUT_DEF}, + {"export-all-symbols", no_argument, NULL, OPTION_EXPORT_ALL}, + {"exclude-symbols", required_argument, NULL, OPTION_EXCLUDE_SYMBOLS}, + {"kill-at", no_argument, NULL, OPTION_KILL_ATS}, + {"add-stdcall-alias", no_argument, NULL, OPTION_STDCALL_ALIASES}, + {"enable-stdcall-fixup", no_argument, NULL, OPTION_ENABLE_STDCALL_FIXUP}, + {"disable-stdcall-fixup", no_argument, NULL, OPTION_DISABLE_STDCALL_FIXUP}, + {"out-implib", required_argument, NULL, OPTION_IMPLIB_FILENAME}, + {"warn-duplicate-exports", no_argument, NULL, OPTION_WARN_DUPLICATE_EXPORTS}, + {"compat-implib", no_argument, NULL, OPTION_IMP_COMPAT}, +#endif + {NULL, no_argument, NULL, 0} +}; /* PE/WIN32; added routines to get the subsystem type, heap and/or stack parameters which may be input from the command line */ -typedef struct { +typedef struct +{ void *ptr; int size; int value; @@ -129,24 +228,62 @@ static definfo init[] = #define IMAGEBASEOFF 0 D(ImageBase,"__image_base__", NT_EXE_IMAGE_BASE), #define DLLOFF 1 - {&dll, sizeof(dll), 0, "__dll__"}, + {&dll, sizeof(dll), 0, "__dll__", 0}, D(SectionAlignment,"__section_alignment__", PE_DEF_SECTION_ALIGNMENT), D(FileAlignment,"__file_alignment__", PE_DEF_FILE_ALIGNMENT), D(MajorOperatingSystemVersion,"__major_os_version__", 4), D(MinorOperatingSystemVersion,"__minor_os_version__", 0), D(MajorImageVersion,"__major_image_version__", 1), D(MinorImageVersion,"__minor_image_version__", 0), +#ifdef TARGET_IS_armpe + D(MajorSubsystemVersion,"__major_subsystem_version__", 2), +#else D(MajorSubsystemVersion,"__major_subsystem_version__", 4), +#endif D(MinorSubsystemVersion,"__minor_subsystem_version__", 0), - D(Subsystem,"__subsystem__", 3), + D(Subsystem,"__subsystem__", ${SUBSYSTEM}), D(SizeOfStackReserve,"__size_of_stack_reserve__", 0x2000000), D(SizeOfStackCommit,"__size_of_stack_commit__", 0x1000), D(SizeOfHeapReserve,"__size_of_heap_reserve__", 0x100000), D(SizeOfHeapCommit,"__size_of_heap_commit__", 0x1000), D(LoaderFlags,"__loader_flags__", 0x0), - 0 + { NULL, 0, 0, NULL, 0 } }; +static void +gld_${EMULATION_NAME}_list_options (file) + FILE * file; +{ + fprintf (file, _(" --base_file <basefile> Generate a base file for relocatable DLLs\n")); + fprintf (file, _(" --dll Set image base to the default for DLLs\n")); + fprintf (file, _(" --file-alignment <size> Set file alignment\n")); + fprintf (file, _(" --heap <size> Set initial size of the heap\n")); + fprintf (file, _(" --image-base <address> Set start address of the executable\n")); + fprintf (file, _(" --major-image-version <number> Set version number of the executable\n")); + fprintf (file, _(" --major-os-version <number> Set minimum required OS version\n")); + fprintf (file, _(" --major-subsystem-version <number> Set minimum required OS subsystem version\n")); + fprintf (file, _(" --minor-image-version <number> Set revision number of the executable\n")); + fprintf (file, _(" --minor-os-version <number> Set minimum required OS revision\n")); + fprintf (file, _(" --minor-subsystem-version <number> Set minimum required OS subsystem revision\n")); + fprintf (file, _(" --section-alignment <size> Set section alignment\n")); + fprintf (file, _(" --stack <size> Set size of the initial stack\n")); + fprintf (file, _(" --subsystem <name>[:<version>] Set required OS subsystem [& version]\n")); + fprintf (file, _(" --support-old-code Support interworking with old code\n")); + fprintf (file, _(" --thumb-entry=<symbol> Set the entry point to be Thumb <symbol>\n")); +#ifdef DLL_SUPPORT + fprintf (file, _(" --add-stdcall-alias Export symbols with and without @nn\n")); + fprintf (file, _(" --disable-stdcall-fixup Don't link _sym to _sym@nn\n")); + fprintf (file, _(" --enable-stdcall-fixup Link _sym to _sym@nn without warnings\n")); + fprintf (file, _(" --exclude-symbols sym,sym,... Exclude symbols from automatic export\n")); + fprintf (file, _(" --export-all-symbols Automatically export all globals to DLL\n")); + fprintf (file, _(" --kill-at Remove @nn from exported symbols\n")); + fprintf (file, _(" --out-implib <file> Generate import library\n")); + fprintf (file, _(" --output-def <file> Generate a .DEF file for the built DLL\n")); + fprintf (file, _(" --warn-duplicate-exports Warn about duplicate exports.\n")); + fprintf (file, _(" --compat-implib Create backward compatible import libs;\n")); + fprintf (file, _(" create __imp_<SYMBOL> as well.\n")); +#endif +} static void set_pe_name (name, val) @@ -182,14 +319,19 @@ set_pe_subsystem () } v[] = { - { "native", 1, "_NtProcessStartup" }, - { "windows", 2, "_WinMainCRTStartup" }, - { "console", 3, "_mainCRTStartup" }, + { "native", 1, "NtProcessStartup" }, +#if defined TARGET_IS_mipspe || defined TARGET_IS_armpe + { "windows", 2, "WinMainCRTStartup" }, +#else + { "windows", 2, "WinMainCRTStartup" }, +#endif + { "console", 3, "mainCRTStartup" }, #if 0 /* The Microsoft linker does not recognize this. */ { "os2", 5, "" }, #endif - { "posix", 7, "___PosixProcessStartup"}, + { "posix", 7, "__PosixProcessStartup"}, + { "wince", 9, "_WinMainCRTStartup" }, { 0, 0, 0 } }; @@ -207,7 +349,7 @@ set_pe_subsystem () set_pe_name ("__minor_subsystem_version__", strtoul (end + 1, &end, 0)); if (*end != '\0') - einfo ("%P: warning: bad version number in -subsystem option\n"); + einfo (_("%P: warning: bad version number in -subsystem option\n")); } for (i = 0; v[i].name; i++) @@ -215,31 +357,35 @@ set_pe_subsystem () if (strncmp (optarg, v[i].name, len) == 0 && v[i].name[len] == '\0') { + const char *initial_symbol_char; + const char *entry; + set_pe_name ("__subsystem__", v[i].value); - /* If the subsystem is windows, we use a different entry - point. We also register the entry point as an undefined - symbol. The reason we do this is so that the user - doesn't have to because they would have to use the -u - switch if they were specifying an entry point other than - _mainCRTStartup. Specifically, if creating a windows - application, entry point _WinMainCRTStartup must be - specified. What I have found for non console - applications (entry not _mainCRTStartup) is that the .obj - that contains mainCRTStartup is brought in since it is - the first encountered in libc.lib and it has other - symbols in it which will be pulled in by the link - process. To avoid this, adding -u with the entry point - name specified forces the correct .obj to be used. We - can avoid making the user do this by always adding the - entry point name as an undefined symbol. */ - lang_add_entry (v[i].entry, 1); - ldlang_add_undef (v[i].entry); + initial_symbol_char = ${INITIAL_SYMBOL_CHAR}; + if (*initial_symbol_char == '\0') + entry = v[i].entry; + else + { + char *alc_entry; + + /* lang_add_entry expects its argument to be permanently + allocated, so we don't free this string. */ + alc_entry = xmalloc (strlen (initial_symbol_char) + + strlen (v[i].entry) + + 1); + strcpy (alc_entry, initial_symbol_char); + strcat (alc_entry, v[i].entry); + entry = alc_entry; + } + + lang_add_entry (entry, 1); return; } } - einfo ("%P%F: invalid subsystem type %s\n", optarg); + + einfo (_("%P%F: invalid subsystem type %s\n"), optarg); } @@ -250,11 +396,11 @@ set_pe_value (name) { char *end; + set_pe_name (name, strtoul (optarg, &end, 0)); + if (end == optarg) - { - einfo ("%P%F: invalid hex number for PE parameter '%s'\n", optarg); - } + einfo (_("%P%F: invalid hex number for PE parameter '%s'\n"), optarg); optarg = end; } @@ -264,19 +410,15 @@ set_pe_stack_heap (resname, comname) char *resname; char *comname; { - char *begin_commit; - char *end; - set_pe_value (resname); + if (*optarg == ',') { optarg++; set_pe_value (comname); } else if (*optarg) - { - einfo ("%P%F: strange hex info for PE parameter '%s'\n", optarg); - } + einfo (_("%P%F: strange hex info for PE parameter '%s'\n"), optarg); } @@ -314,7 +456,8 @@ gld_${EMULATION_NAME}_parse_args(argc, argv) link_info.base_file = (PTR) fopen (optarg, FOPEN_WB); if (link_info.base_file == NULL) { - fprintf (stderr, "%s: Can't open base file %s\n", + /* xgettext:c-format */ + fprintf (stderr, _("%s: Can't open base file %s\n"), program_name, optarg); xexit (1); } @@ -360,12 +503,53 @@ gld_${EMULATION_NAME}_parse_args(argc, argv) case OPTION_IMAGE_BASE: set_pe_value ("__image_base__"); break; + case OPTION_SUPPORT_OLD_CODE: + support_old_code = 1; + break; + case OPTION_THUMB_ENTRY: + thumb_entry_symbol = optarg; + break; +#ifdef DLL_SUPPORT + case OPTION_OUT_DEF: + pe_out_def_filename = xstrdup (optarg); + break; + case OPTION_EXPORT_ALL: + pe_dll_export_everything = 1; + break; + case OPTION_EXCLUDE_SYMBOLS: + pe_dll_add_excludes (optarg); + break; + case OPTION_KILL_ATS: + pe_dll_kill_ats = 1; + break; + case OPTION_STDCALL_ALIASES: + pe_dll_stdcall_aliases = 1; + break; + case OPTION_ENABLE_STDCALL_FIXUP: + pe_enable_stdcall_fixup = 1; + break; + case OPTION_DISABLE_STDCALL_FIXUP: + pe_enable_stdcall_fixup = 0; + break; + case OPTION_IMPLIB_FILENAME: + pe_implib_filename = xstrdup (optarg); + break; + case OPTION_WARN_DUPLICATE_EXPORTS: + pe_dll_warn_dup_exports = 1; + break; + case OPTION_IMP_COMPAT: + pe_dll_compat_implib = 1; + break; +#endif } return 1; } +/* Assign values to the special symbols before the linker script is + read. */ + static void -gld_${EMULATION_NAME}_set_symbols() +gld_${EMULATION_NAME}_set_symbols () { /* Run through and invent symbols for all the names and insert the defaults. */ @@ -373,8 +557,18 @@ gld_${EMULATION_NAME}_set_symbols() lang_statement_list_type *save; if (!init[IMAGEBASEOFF].inited) - init[IMAGEBASEOFF].value = init[DLLOFF].value - ? NT_DLL_IMAGE_BASE : NT_EXE_IMAGE_BASE; + { + if (link_info.relocateable) + init[IMAGEBASEOFF].value = 0; + else if (init[DLLOFF].value || link_info.shared) + init[IMAGEBASEOFF].value = NT_DLL_IMAGE_BASE; + else + init[IMAGEBASEOFF].value = NT_EXE_IMAGE_BASE; + } + + /* Don't do any symbol assignments if this is a relocateable link. */ + if (link_info.relocateable) + return; /* Glue the assignments into the abs section */ save = stat_ptr; @@ -384,14 +578,20 @@ gld_${EMULATION_NAME}_set_symbols() for (j = 0; init[j].ptr; j++) { long val = init[j].value; - lang_add_assignment (exp_assop ('=' ,init[j].symbol, exp_intop (val))); + lang_assignment_statement_type *rv; + rv = lang_add_assignment (exp_assop ('=' ,init[j].symbol, exp_intop (val))); if (init[j].size == sizeof(short)) *(short *)init[j].ptr = val; else if (init[j].size == sizeof(int)) *(int *)init[j].ptr = val; else if (init[j].size == sizeof(long)) *(long *)init[j].ptr = val; + /* This might be a long long or other special type. */ + else if (init[j].size == sizeof(bfd_vma)) + *(bfd_vma *)init[j].ptr = val; else abort(); + if (j == IMAGEBASEOFF) + image_base_statement = rv; } /* Restore the pointer. */ stat_ptr = save; @@ -399,285 +599,714 @@ gld_${EMULATION_NAME}_set_symbols() if (pe.FileAlignment > pe.SectionAlignment) { - einfo ("%P: warning, file alignment > section alignment.\n"); - } -} - -static void -gld_${EMULATION_NAME}_after_open() -{ - /* Pass the wacky PE command line options into the output bfd */ - struct internal_extra_pe_aouthdr *i; - if (!coff_data(output_bfd)->pe) - { - einfo ("%F%P: PE operations on non PE file.\n"); + einfo (_("%P: warning, file alignment > section alignment.\n")); } - - pe_data(output_bfd)->pe_opthdr = pe; - pe_data(output_bfd)->dll = init[DLLOFF].value; - } - -/* Callback functions for qsort in sort_sections. */ -static int -sort_by_file_name (a, b) - void *a; - void *b; -{ - lang_statement_union_type **ra = a; - lang_statement_union_type **rb = b; - return strcmp ((*ra)->input_section.ifile->filename, - (*rb)->input_section.ifile->filename); -} +/* This is called after the linker script and the command line options + have been read. */ -static int -sort_by_section_name (a, b) - void *a; - void *b; +static void +gld_${EMULATION_NAME}_after_parse () { - lang_statement_union_type **ra = a; - lang_statement_union_type **rb = b; - return strcmp ((*ra)->input_section.section->name, - (*rb)->input_section.section->name); + /* The Windows libraries are designed for the linker to treat the + entry point as an undefined symbol. Otherwise, the .obj that + defines mainCRTStartup is brought in because it is the first + encountered in libc.lib and it has other symbols in it which will + be pulled in by the link process. To avoid this, we act as + though the user specified -u with the entry point symbol. + + This function is called after the linker script and command line + options have been read, so at this point we know the right entry + point. This function is called before the input files are + opened, so registering the symbol as undefined will make a + difference. */ + + if (! link_info.relocateable && entry_symbol != NULL) + ldlang_add_undef (entry_symbol); } -/* Subroutine of sort_sections to a contiguous subset of a list of sections. - NEXT_AFTER is the element after the last one to sort. - The result is a pointer to the last element's "next" pointer. */ +static struct bfd_link_hash_entry *pe_undef_found_sym; -static lang_statement_union_type ** -sort_sections_1 (startptr, next_after, count, sort_func) - lang_statement_union_type **startptr,*next_after; - int count; - int (*sort_func) (); +static boolean +pe_undef_cdecl_match (h, string) + struct bfd_link_hash_entry *h; + PTR string; { - lang_statement_union_type **vec; - lang_statement_union_type *p; - int i; - - if (count == 0) - return startptr; - - vec = (lang_statement_union_type **) - alloca (count * sizeof (lang_statement_union_type *)); - - for (p = *startptr, i = 0; i < count; i++, p = p->next) - vec[i] = p; - - qsort (vec, count, sizeof (vec[0]), sort_func); - - /* Fill in the next pointers again. */ - *startptr = vec[0]; - for (i = 0; i < count - 1; i++) - vec[i]->header.next = vec[i + 1]; - vec[i]->header.next = next_after; - return &(vec[i]->header.next); + int sl = strlen (string); + if (h->type == bfd_link_hash_defined + && strncmp (h->root.string, string, sl) == 0 + && h->root.string[sl] == '@') + { + pe_undef_found_sym = h; + return false; + } + return true; } -/* Sort the .idata\$foo input sections of archives into filename order. - The reason is so dlltool can arrange to have the pe dll import information - generated correctly - the head of the list goes into dh.o, the tail into - dt.o, and the guts into ds[nnnn].o. Note that this is only needed for the - .idata section. - FIXME: This may no longer be necessary with grouped sections. Instead of - sorting on dh.o, ds[nnnn].o, dt.o, one could, for example, have dh.o use - .idata\$4h, have ds[nnnn].o use .idata\$4s[nnnn], and have dt.o use .idata\$4t. - This would have to be elaborated upon to handle multiple dll's - [assuming such an eloboration is possible of course]. - - We also sort sections in '\$' wild statements. These are created by the - place_orphans routine to implement grouped sections. */ - +#ifdef DLL_SUPPORT static void -sort_sections (s) - lang_statement_union_type *s; +pe_fixup_stdcalls () { - for (; s ; s = s->next) - switch (s->header.type) + static int gave_warning_message = 0; + struct bfd_link_hash_entry *undef, *sym; + char *at; + for (undef = link_info.hash->undefs; undef; undef=undef->next) + if (undef->type == bfd_link_hash_undefined) + { + at = strchr (undef->root.string, '@'); + if (at) { - case lang_output_section_statement_enum: - sort_sections (s->output_section_statement.children.head); - break; - case lang_wild_statement_enum: + /* The symbol is a stdcall symbol, so let's look for a cdecl + symbol with the same name and resolve to that */ + char *cname = xstrdup (undef->root.string); + at = strchr (cname, '@'); + *at = 0; + sym = bfd_link_hash_lookup (link_info.hash, cname, 0, 0, 1); + if (sym && sym->type == bfd_link_hash_defined) { - lang_statement_union_type **p = &s->wild_statement.children.head; - - /* Is this the .idata section? */ - if (s->wild_statement.section_name != NULL - && strncmp (s->wild_statement.section_name, ".idata", 6) == 0) + undef->type = bfd_link_hash_defined; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; + if (pe_enable_stdcall_fixup == -1) { - /* Sort any children in the same archive. Run through all - the children of this wild statement, when an - input_section in an archive is found, scan forward to - find all input_sections which are in the same archive. - Sort them by their filename and then re-thread the - pointer chain. */ - - while (*p) + einfo (_("Warning: resolving %s by linking to %s\n"), + undef->root.string, cname); + if (! gave_warning_message) { - lang_statement_union_type *start = *p; - if (start->header.type != lang_input_section_enum - || !start->input_section.ifile->the_bfd->my_archive) - p = &(start->header.next); - else - { - lang_statement_union_type *end; - int count; - - for (end = start, count = 0; - end && end->header.type == lang_input_section_enum - && (end->input_section.ifile->the_bfd->my_archive - == start->input_section.ifile->the_bfd->my_archive); - end = end->next) - count++; - - p = sort_sections_1 (p, end, count, sort_by_file_name); - } + gave_warning_message = 1; + einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); } - break; } - - /* If this is a collection of grouped sections, sort them. - The linker script must explicitly mention "*(.foo\$)". - Don't sort them if \$ is not the last character (not sure if - this is really useful, but it allows explicitly mentioning - some \$ sections and letting the linker handle the rest). */ - if (s->wild_statement.section_name != NULL) + } + } + else + { + /* The symbol is a cdecl symbol, so we look for stdcall + symbols - which means scanning the whole symbol table */ + pe_undef_found_sym = 0; + bfd_link_hash_traverse (link_info.hash, pe_undef_cdecl_match, + (PTR) undef->root.string); + sym = pe_undef_found_sym; + if (sym) + { + undef->type = bfd_link_hash_defined; + undef->u.def.value = sym->u.def.value; + undef->u.def.section = sym->u.def.section; + if (pe_enable_stdcall_fixup == -1) { - char *q = strchr (s->wild_statement.section_name, '\$'); - - if (q && q[1] == 0) + einfo (_("Warning: resolving %s by linking to %s\n"), + undef->root.string, sym->root.string); + if (! gave_warning_message) { - lang_statement_union_type *end; - int count; - - for (end = *p, count = 0; end; end = end->next) - { - if (end->header.type != lang_input_section_enum) - abort (); - count++; - } - (void) sort_sections_1 (p, end, count, sort_by_section_name); + gave_warning_message = 1; + einfo(_("Use --enable-stdcall-fixup to disable these warnings\n")); + einfo(_("Use --disable-stdcall-fixup to disable these fixups\n")); } - break; } } - break; - default: - break; } + } } +#endif /* DLL_SUPPORT */ + +static void +gld_${EMULATION_NAME}_after_open () +{ + /* Pass the wacky PE command line options into the output bfd. + FIXME: This should be done via a function, rather than by + including an internal BFD header. */ + + if (!coff_data (output_bfd)->pe) + einfo (_("%F%P: PE operations on non PE file.\n")); + + pe_data (output_bfd)->pe_opthdr = pe; + pe_data (output_bfd)->dll = init[DLLOFF].value; + +#ifdef DLL_SUPPORT + if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */ + pe_fixup_stdcalls (); + pe_process_import_defs(output_bfd, &link_info); + if (link_info.shared) + pe_dll_build_sections (output_bfd, &link_info); + +#ifndef TARGET_IS_i386pe +#ifndef TARGET_IS_armpe + else + pe_exe_build_sections (output_bfd, &link_info); +#endif +#endif +#endif + +#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) + if (strstr (bfd_get_target (output_bfd), "arm") == NULL) + { + /* The arm backend needs special fields in the output hash structure. + These will only be created if the output format is an arm format, + hence we do not support linking and changing output formats at the + same time. Use a link followed by objcopy to change output formats. */ + einfo ("%F%X%P: error: cannot change output format whilst linking ARM binaries\n"); + return; + } + { + /* Find a BFD that can hold the interworking stubs. */ + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + if (bfd_arm_pe_get_bfd_for_interworking (is->the_bfd, & link_info)) + break; + } + } +#endif + + { + int is_ms_arch = 0; + bfd *cur_arch = 0; + lang_input_statement_type *is2; + + /* Careful - this is a shell script. Watch those dollar signs! */ + /* Microsoft import libraries have every member named the same, + and not in the right order for us to link them correctly. We + must detect these and rename the members so that they'll link + correctly. There are three types of objects: the head, the + thunks, and the sentinel(s). The head is easy; it's the one + with idata2. We assume that the sentinels won't have relocs, + and the thunks will. It's easier than checking the symbol + table for external references. */ + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + if (is->the_bfd->my_archive) + { + bfd *arch = is->the_bfd->my_archive; + if (cur_arch != arch) + { + cur_arch = arch; + is_ms_arch = 1; + for (is2 = is; + is2 && is2->the_bfd->my_archive == arch; + is2 = (lang_input_statement_type *)is2->next) + { + if (strcmp (is->the_bfd->filename, is2->the_bfd->filename)) + is_ms_arch = 0; + } + } + + if (is_ms_arch) + { + int idata2 = 0, reloc_count=0; + asection *sec; + char *new_name, seq; + + for (sec = is->the_bfd->sections; sec; sec = sec->next) + { + if (strcmp (sec->name, ".idata\$2") == 0) + idata2 = 1; + reloc_count += sec->reloc_count; + } + + if (idata2) /* .idata2 is the TOC */ + seq = 'a'; + else if (reloc_count > 0) /* thunks */ + seq = 'b'; + else /* sentinel */ + seq = 'c'; + + new_name = xmalloc (strlen (is->the_bfd->filename) + 3); + sprintf (new_name, "%s.%c", is->the_bfd->filename, seq); + is->the_bfd->filename = new_name; + + new_name = xmalloc (strlen(is->filename) + 3); + sprintf (new_name, "%s.%c", is->filename, seq); + is->filename = new_name; + } + } + } + } +} + static void gld_${EMULATION_NAME}_before_allocation() { - extern lang_statement_list_type *stat_ptr; - #ifdef TARGET_IS_ppcpe /* Here we rummage through the found bfds to collect toc information */ { LANG_FOR_EACH_INPUT_STATEMENT (is) { - if (!ppc_process_before_allocation(is->the_bfd, &link_info)) + if (!ppc_process_before_allocation (is->the_bfd, &link_info)) { - einfo("Errors encountered processing file %s", is->filename); + /* xgettext:c-format */ + einfo (_("Errors encountered processing file %s\n"), is->filename); } } } /* We have seen it all. Allocate it, and carry on */ ppc_allocate_toc_section (&link_info); +#endif /* TARGET_IS_ppcpe */ + +#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) + /* FIXME: we should be able to set the size of the interworking stub + section. + + Here we rummage through the found bfds to collect glue + information. FIXME: should this be based on a command line + option? krk@cygnus.com */ + { + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + if (! bfd_arm_pe_process_before_allocation + (is->the_bfd, & link_info, support_old_code)) + { + /* xgettext:c-format */ + einfo (_("Errors encountered processing file %s for interworking"), + is->filename); + } + } + } + + /* We have seen it all. Allocate it, and carry on */ + bfd_arm_pe_allocate_interworking_sections (& link_info); +#endif /* TARGET_IS_armpe */ +} + + +/* This is called when an input file isn't recognized as a BFD. We + check here for .DEF files and pull them in automatically. */ +#ifdef DLL_SUPPORT +static int +saw_option(char *option) +{ + int i; + for (i=0; init[i].ptr; i++) + if (strcmp (init[i].symbol, option) == 0) + return init[i].inited; + return 0; +} +#endif + +static boolean +gld_${EMULATION_NAME}_unrecognized_file(entry) + lang_input_statement_type *entry ATTRIBUTE_UNUSED; +{ +#ifdef DLL_SUPPORT + const char *ext = entry->filename + strlen (entry->filename) - 4; + + if (strcmp (ext, ".def") == 0 || strcmp (ext, ".DEF") == 0) + { + if (pe_def_file == 0) + pe_def_file = def_file_empty (); + def_file_parse (entry->filename, pe_def_file); + if (pe_def_file) + { + int i, buflen=0, len; + char *buf; + for (i=0; i<pe_def_file->num_exports; i++) + { + len = strlen(pe_def_file->exports[i].internal_name); + if (buflen < len+2) + buflen = len+2; + } + buf = (char *) xmalloc (buflen); + for (i=0; i<pe_def_file->num_exports; i++) + { + struct bfd_link_hash_entry *h; + sprintf(buf, "_%s", pe_def_file->exports[i].internal_name); + + h = bfd_link_hash_lookup (link_info.hash, buf, true, true, true); + if (h == (struct bfd_link_hash_entry *) NULL) + einfo (_("%P%F: bfd_link_hash_lookup failed: %E\n")); + if (h->type == bfd_link_hash_new) + { + h->type = bfd_link_hash_undefined; + h->u.undef.abfd = NULL; + bfd_link_add_undef (link_info.hash, h); + } + } + free (buf); + + /* def_file_print (stdout, pe_def_file); */ + if (pe_def_file->is_dll == 1) + link_info.shared = 1; + + if (pe_def_file->base_address != (bfd_vma)(-1)) + { + pe.ImageBase = + pe_data (output_bfd)->pe_opthdr.ImageBase = + init[IMAGEBASEOFF].value = pe_def_file->base_address; + init[IMAGEBASEOFF].inited = 1; + if (image_base_statement) + image_base_statement->exp = + exp_assop ('=', "__image_base__", exp_intop (pe.ImageBase)); + } + +#if 0 + /* Not sure if these *should* be set */ + if (pe_def_file->version_major != -1) + { + pe.MajorImageVersion = pe_def_file->version_major; + pe.MinorImageVersion = pe_def_file->version_minor; + } +#endif + if (pe_def_file->stack_reserve != -1 + && ! saw_option ("__size_of_stack_reserve__")) + { + pe.SizeOfStackReserve = pe_def_file->stack_reserve; + if (pe_def_file->stack_commit != -1) + pe.SizeOfStackCommit = pe_def_file->stack_commit; + } + if (pe_def_file->heap_reserve != -1 + && ! saw_option ("__size_of_heap_reserve__")) + { + pe.SizeOfHeapReserve = pe_def_file->heap_reserve; + if (pe_def_file->heap_commit != -1) + pe.SizeOfHeapCommit = pe_def_file->heap_commit; + } + return true; + } + } #endif + return false; + +} - sort_sections (stat_ptr->head); +static boolean +gld_${EMULATION_NAME}_recognized_file(entry) + lang_input_statement_type *entry ATTRIBUTE_UNUSED; +{ +#ifdef DLL_SUPPORT +#ifdef TARGET_IS_i386pe + pe_dll_id_target ("pei-i386"); +#endif +#ifdef TARGET_IS_shpe + pe_dll_id_target ("pei-shl"); +#endif +#ifdef TARGET_IS_mipspe + pe_dll_id_target ("pei-mips"); +#endif +#ifdef TARGET_IS_armpe + pe_dll_id_target ("pei-arm-little"); +#endif + if (bfd_get_format (entry->the_bfd) == bfd_object) + { + const char *ext = entry->filename + strlen (entry->filename) - 4; + if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0) + return pe_implied_import_dll (entry->filename); + } +#endif + return false; } + +static void +gld_${EMULATION_NAME}_finish () +{ +#if defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) + struct bfd_link_hash_entry * h; + + if (thumb_entry_symbol != NULL) + { + h = bfd_link_hash_lookup (link_info.hash, thumb_entry_symbol, false, false, true); + + if (h != (struct bfd_link_hash_entry *) NULL + && (h->type == bfd_link_hash_defined + || h->type == bfd_link_hash_defweak) + && h->u.def.section->output_section != NULL) + { + static char buffer[32]; + bfd_vma val; + + /* Special procesing is required for a Thumb entry symbol. The + bottom bit of its address must be set. */ + val = (h->u.def.value + + bfd_get_section_vma (output_bfd, + h->u.def.section->output_section) + + h->u.def.section->output_offset); + + val |= 1; + + /* Now convert this value into a string and store it in entry_symbol + where the lang_finish() function will pick it up. */ + buffer[0] = '0'; + buffer[1] = 'x'; + + sprintf_vma (buffer + 2, val); + + if (entry_symbol != NULL && entry_from_cmdline) + einfo (_("%P: warning: '--thumb-entry %s' is overriding '-e %s'\n"), + thumb_entry_symbol, entry_symbol); + entry_symbol = buffer; + } + else + einfo (_("%P: warning: connot find thumb start symbol %s\n"), thumb_entry_symbol); + } +#endif /* defined(TARGET_IS_armpe) || defined(TARGET_IS_arm_epoc_pe) */ + +#ifdef DLL_SUPPORT + if (link_info.shared) + { + pe_dll_fill_sections (output_bfd, &link_info); + if (pe_implib_filename) + pe_dll_generate_implib (pe_def_file, pe_implib_filename); + } +#if defined(TARGET_IS_shpe) || defined(TARGET_IS_mipspe) + else + { + pe_exe_fill_sections (output_bfd, &link_info); + } +#endif + + if (pe_out_def_filename) + pe_dll_generate_def_file (pe_out_def_filename); +#endif +} + -/* Place an orphan section. We use this to put sections with a '\$' in them - into the right place. Any section with a '\$' in them (e.g. .text\$foo) - gets mapped to the output section with everything from the '\$' on stripped - (e.g. .text). - See the Microsoft Portable Executable and Common Object File Format - Specification 4.1, section 4.2, Grouped Sections. */ +/* Place an orphan section. + + We use this to put sections in a reasonable place in the file, and + to ensure that they are aligned as required. + + We handle grouped sections here as well. A section named .foo$nn + goes into the output section .foo. All grouped sections are sorted + by name. + + Grouped sections for the default sections are handled by the + default linker script using wildcards, and are sorted by + sort_sections. */ + +static asection *hold_section; +static char *hold_section_name; +static lang_output_section_statement_type *hold_use; +static lang_output_section_statement_type *hold_text; +static lang_output_section_statement_type *hold_rdata; +static lang_output_section_statement_type *hold_data; +static lang_output_section_statement_type *hold_bss; + +/* Place an orphan section. We use this to put random SHF_ALLOC + sections in the right segment. */ /*ARGSUSED*/ static boolean -gld${EMULATION_NAME}_place_orphan (file, s) +gld_${EMULATION_NAME}_place_orphan (file, s) lang_input_statement_type *file; asection *s; { const char *secname; - char *output_secname, *ps; - lang_output_section_statement_type *os; - lang_statement_list_type *ptr; - lang_statement_union_type *l; + char *dollar = NULL; if ((s->flags & SEC_ALLOC) == 0) return false; - /* Don't process grouped sections unless doing a final link. - If they're marked as COMDAT sections, we don't want .text\$foo to - end up in .text and then have .text disappear because it's marked - link-once-discard. */ - if (link_info.relocateable) - return false; - secname = bfd_get_section_name (s->owner, s); - /* Everything from the '\$' on gets deleted so don't allow '\$' as the - first character. */ - if (*secname == '\$') - einfo ("%P%F: section %s has '\$' as first character\n", secname); - if (strchr (secname + 1, '\$') == NULL) - return false; + /* Look through the script to see where to place this section. */ + + hold_section = s; - /* Look up the output section. The Microsoft specs say sections names in - image files never contain a '\$'. Fortunately, lang_..._lookup creates - the section if it doesn't exist. */ - output_secname = buystring (secname); - ps = strchr (output_secname + 1, '\$'); - *ps = 0; - os = lang_output_section_statement_lookup (output_secname); - - /* Find the '\$' wild statement for this section. We currently require the - linker script to explicitly mention "*(.foo\$)". - FIXME: ppcpe.sc has .CRT\$foo in the .rdata section. According to the - Microsoft docs this isn't correct so it's not (currently) handled. */ - - ps[0] = '\$'; - ps[1] = 0; - for (l = os->children.head; l; l = l->next) + hold_section_name = xstrdup (secname); + if (!link_info.relocateable) { - if (l->header.type == lang_wild_statement_enum - && strcmp (l->wild_statement.section_name, output_secname) == 0) - break; + dollar = strchr (hold_section_name, '$'); + if (dollar != NULL) + *dollar = '\0'; } - ps[0] = 0; - if (l == NULL) -#if 1 - einfo ("%P%F: *(%s\$) missing from linker script\n", output_secname); -#else /* FIXME: This block is untried. It exists to convey the intent, - should one decide to not require *(.foo\$) to appear in the linker - script. */ + + hold_use = NULL; + lang_for_each_statement (gld${EMULATION_NAME}_place_section); + + if (hold_use == NULL) { - lang_wild_statement_type *new = new_stat (lang_wild_statement, - &os->children); - new->section_name = xmalloc (strlen (output_secname) + 2); - sprintf (new->section_name, "%s\$", output_secname); - new->filename = NULL; - lang_list_init (&new->children); - l = new; + lang_output_section_statement_type *place; + char *outsecname; + asection *snew, **pps; + lang_statement_list_type *old; + lang_statement_list_type add; + etree_type *address; + + /* Try to put the new output section in a reasonable place based + on the section name and section flags. */ + place = NULL; + if ((s->flags & SEC_HAS_CONTENTS) == 0 + && hold_bss != NULL) + place = hold_bss; + else if ((s->flags & SEC_READONLY) == 0 + && hold_data != NULL) + place = hold_data; + else if ((s->flags & SEC_CODE) == 0 + && (s->flags & SEC_READONLY) != 0 + && hold_rdata != NULL) + place = hold_rdata; + else if ((s->flags & SEC_READONLY) != 0 + && hold_text != NULL) + place = hold_text; + + /* Choose a unique name for the section. This will be needed if + the same section name appears in the input file with + different loadable or allocateable characteristics. */ + outsecname = xstrdup (hold_section_name); + if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) + { + unsigned int len; + char *newname; + unsigned int i; + + len = strlen (outsecname); + newname = xmalloc (len + 5); + strcpy (newname, outsecname); + i = 0; + do + { + sprintf (newname + len, "%d", i); + ++i; + } + while (bfd_get_section_by_name (output_bfd, newname) != NULL); + + free (outsecname); + outsecname = newname; + } + + /* We don't want to free OUTSECNAME, as it may get attached to + the output section statement. */ + + /* Create the section in the output file, and put it in the + right place. This shuffling is to make the output file look + neater. */ + snew = bfd_make_section (output_bfd, outsecname); + if (snew == NULL) + einfo ("%P%F: output format %s cannot represent section called %s\n", + output_bfd->xvec->name, outsecname); + if (place != NULL && place->bfd_section != NULL) + { + for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) + ; + *pps = snew->next; + snew->next = place->bfd_section->next; + place->bfd_section->next = snew; + } + + /* Start building a list of statements for this section. */ + old = stat_ptr; + stat_ptr = &add; + lang_list_init (stat_ptr); + + if (link_info.relocateable) + address = NULL; + else + { + /* All sections in an executable must be aligned to a page + boundary. */ + address = exp_unop (ALIGN_K, + exp_nameop (NAME, "__section_alignment__")); + } + + lang_enter_output_section_statement (outsecname, address, 0, + (bfd_vma) 0, + (etree_type *) NULL, + (etree_type *) NULL, + (etree_type *) NULL); + + hold_use = lang_output_section_statement_lookup (outsecname); + + lang_leave_output_section_statement + ((bfd_vma) 0, "*default*", + (struct lang_output_section_phdr_list *) NULL, + "*default*"); + + /* Now stick the new statement list right after PLACE. */ + if (place != NULL) + { + *add.tail = place->header.next; + place->header.next = add.head; + } + + stat_ptr = old; } -#endif - /* Link the input section in and we're done for now. - The sections still have to be sorted, but that has to wait until - all such sections have been processed by us. The sorting is done by - sort_sections. */ - wild_doit (&l->wild_statement.children, s, os, file); + if (dollar == NULL) + wild_doit (&hold_use->children, s, hold_use, file); + else + { + lang_statement_union_type **pl; + boolean found_dollar; + lang_statement_list_type list; + + /* The section name has a '$'. Sort it with the other '$' + sections. */ + + found_dollar = false; + for (pl = &hold_use->children.head; *pl != NULL; pl = &(*pl)->next) + { + lang_input_section_type *ls; + const char *lname; + + if ((*pl)->header.type != lang_input_section_enum) + continue; + + ls = &(*pl)->input_section; + + lname = bfd_get_section_name (ls->ifile->the_bfd, ls->section); + if (strchr (lname, '$') == NULL) + { + if (found_dollar) + break; + } + else + { + found_dollar = true; + if (strcmp (secname, lname) < 0) + break; + } + } + + lang_list_init (&list); + wild_doit (&list, s, hold_use, file); + if (list.head != NULL) + { + ASSERT (list.head->next == NULL); + list.head->next = *pl; + *pl = list.head; + } + } + + free (hold_section_name); return true; } + +static void +gld${EMULATION_NAME}_place_section (s) + lang_statement_union_type *s; +{ + lang_output_section_statement_type *os; + + if (s->header.type != lang_output_section_statement_enum) + return; + + os = &s->output_section_statement; + + if (strcmp (os->name, hold_section_name) == 0 + && os->bfd_section != NULL + && ((hold_section->flags & (SEC_LOAD | SEC_ALLOC)) + == (os->bfd_section->flags & (SEC_LOAD | SEC_ALLOC)))) + hold_use = os; + + if (strcmp (os->name, ".text") == 0) + hold_text = os; + else if (strcmp (os->name, ".rdata") == 0) + hold_rdata = os; + else if (strcmp (os->name, ".data") == 0) + hold_data = os; + else if (strcmp (os->name, ".bss") == 0) + hold_bss = os; +} + +static int +gld_${EMULATION_NAME}_find_potential_libraries (name, entry) + char * name; + lang_input_statement_type * entry; +{ + return ldfile_open_file_search (name, entry, "", ".lib"); +} static char * gld_${EMULATION_NAME}_get_script(isfile) @@ -685,7 +1314,7 @@ gld_${EMULATION_NAME}_get_script(isfile) EOF # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc="-f ${srcdir}/emultempl/stringify.sed" +sc="-f stringify.sed" cat >>e${EMULATION_NAME}.c <<EOF { @@ -713,7 +1342,7 @@ 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_parse, gld_${EMULATION_NAME}_after_open, after_allocation_default, set_output_arch_default, @@ -722,11 +1351,15 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld_${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - NULL, /* finish */ + gld_${EMULATION_NAME}_finish, /* finish */ NULL, /* create output section statements */ NULL, /* open dynamic archive */ - gld${EMULATION_NAME}_place_orphan, + gld_${EMULATION_NAME}_place_orphan, gld_${EMULATION_NAME}_set_symbols, - gld_${EMULATION_NAME}_parse_args + gld_${EMULATION_NAME}_parse_args, + gld_${EMULATION_NAME}_unrecognized_file, + gld_${EMULATION_NAME}_list_options, + gld_${EMULATION_NAME}_recognized_file, + gld_${EMULATION_NAME}_find_potential_libraries }; EOF diff --git a/gnu/usr.bin/binutils/ld/emultempl/sunos.em b/gnu/usr.bin/binutils/ld/emultempl/sunos.em index e20e08c3758..a571b6b3b75 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/sunos.em +++ b/gnu/usr.bin/binutils/ld/emultempl/sunos.em @@ -4,7 +4,8 @@ cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ /* SunOS emulation code for ${EMULATION_NAME} - Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc. + Copyright (C) 1991, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. Written by Steve Chamberlain <sac@cygnus.com> SunOS shared library support by Ian Lance Taylor <ian@cygnus.com> @@ -26,8 +27,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #define TARGET_IS_${EMULATION_NAME} -#include <sys/types.h> -#include <sys/stat.h> +#include <ctype.h> #include "bfd.h" #include "sysdep.h" @@ -87,6 +87,7 @@ gld${EMULATION_NAME}_before_parse() { ldfile_output_architecture = bfd_arch_${ARCH}; config.dynamic_link = true; + config.has_shared = true; } /* This is called after the command line arguments have been parsed, @@ -99,7 +100,8 @@ gld${EMULATION_NAME}_set_symbols () { EOF if [ "x${host}" = "x${target}" ] ; then - if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) cat >>e${EMULATION_NAME}.c <<EOF const char *env; @@ -124,7 +126,8 @@ cat >>e${EMULATION_NAME}.c <<EOF } } EOF - fi + ;; + esac fi cat >>e${EMULATION_NAME}.c <<EOF } @@ -151,7 +154,7 @@ gld${EMULATION_NAME}_find_so (inp) lang_input_statement_type *inp; { search_dirs_type *search; - char *found; + char *found = NULL; char *alc; struct stat st; @@ -195,7 +198,7 @@ gld${EMULATION_NAME}_find_so (inp) found, add it to the list of input files. */ alc = (char *) xmalloc (strlen (inp->filename) + 1); strcpy (alc, inp->filename); - strstr (alc, ".so.")[2] = 'a'; + strstr (alc + strlen (search->name), ".so")[2] = 'a'; if (stat (alc, &st) != 0) free (alc); else @@ -232,6 +235,10 @@ gld${EMULATION_NAME}_search_dir (dirname, filename, found_static) int max_maj, max_min; DIR *dir; struct dirent *entry; + unsigned int dirnamelen; + char *full_path; + int statval; + struct stat st; *found_static = false; @@ -264,9 +271,11 @@ gld${EMULATION_NAME}_search_dir (dirname, filename, found_static) dir = opendir (dirname); if (dir == NULL) return NULL; + dirnamelen = strlen (dirname); while ((entry = readdir (dir)) != NULL) { + const char *s; int found_maj, found_min; if (strncmp (entry->d_name, "lib", 3) != 0 @@ -280,8 +289,25 @@ gld${EMULATION_NAME}_search_dir (dirname, filename, found_static) continue; } + /* We accept libfoo.so without a version number, even though the + native linker does not. This is more convenient for packages + which just generate .so files for shared libraries, as on ELF + systems. */ if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0) continue; + if (entry->d_name[6 + len] == '\0') + ; + else if (entry->d_name[6 + len] == '.' + && isdigit ((unsigned char) entry->d_name[7 + len])) + ; + else + continue; + + for (s = entry->d_name + 6 + len; *s != '\0'; s++) + if (*s != '.' && ! isdigit ((unsigned char) *s)) + break; + if (*s != '\0') + continue; /* We've found a .so file. Work out the major and minor version numbers. */ @@ -294,6 +320,14 @@ gld${EMULATION_NAME}_search_dir (dirname, filename, found_static) || (force_min != -1 && force_min != found_min)) continue; + /* Make sure the file really exists (ignore broken symlinks). */ + full_path = xmalloc (dirnamelen + 1 + strlen (entry->d_name) + 1); + sprintf (full_path, "%s/%s", dirname, entry->d_name); + statval = stat (full_path, &st); + free (full_path); + if (statval != 0) + continue; + /* We've found a match for the name we are searching for. See if this is the version we should use. If the major and minor versions match, we use the last entry in alphabetical order; @@ -432,7 +466,8 @@ gld${EMULATION_NAME}_after_open () } EOF if [ "x${host}" = "x${target}" ] ; then - if [ "x${DEFAULT_EMULATION}" = "x${EMULATION_NAME}" ] ; then + case " ${EMULATION_LIBPATH} " in + *" ${EMULATION_NAME} "*) cat >>e${EMULATION_NAME}.c <<EOF { const char *lib_path; @@ -442,7 +477,8 @@ cat >>e${EMULATION_NAME}.c <<EOF continue; } EOF - fi + ;; + esac fi cat >>e${EMULATION_NAME}.c <<EOF if (command_line.rpath != NULL) @@ -935,28 +971,25 @@ then # Scripts compiled in. # sed commands to quote an ld script as a C string. -sc='s/["\\]/\\&/g -s/$/\\n\\/ -1s/^/"/ -$s/$/n"/ -' +sc="-f stringify.sed" cat >>e${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`; -} + 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. @@ -996,10 +1029,15 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld${EMULATION_NAME}_get_script, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - NULL, /* finish */ + NULL, /* finish */ gld${EMULATION_NAME}_create_output_section_statements, - NULL, /* open_dynamic_library */ - NULL, /* place_orphan */ - gld${EMULATION_NAME}_set_symbols + NULL, /* open dynamic archive */ + NULL, /* place orphan */ + gld${EMULATION_NAME}_set_symbols, + NULL, /* parse args */ + NULL, /* unrecognized file */ + NULL, /* list options */ + NULL, /* recognized file */ + NULL /* find_potential_libraries */ }; EOF diff --git a/gnu/usr.bin/binutils/ld/emultempl/vanilla.em b/gnu/usr.bin/binutils/ld/emultempl/vanilla.em index 04e36fbc947..0a74abd0e08 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/vanilla.em +++ b/gnu/usr.bin/binutils/ld/emultempl/vanilla.em @@ -64,6 +64,16 @@ struct ld_emulation_xfer_struct ld_vanilla_emulation = before_allocation_default, vanilla_get_script, "vanilla", - "a.out-sunos-big" + "a.out-sunos-big", + 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 |