diff options
Diffstat (limited to 'gnu/usr.bin/binutils/ld/emultempl/elf32.em')
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/elf32.em | 469 |
1 files changed, 341 insertions, 128 deletions
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 |