diff options
author | obrien <obrien@FreeBSD.org> | 2002-01-27 12:24:18 +0000 |
---|---|---|
committer | obrien <obrien@FreeBSD.org> | 2002-01-27 12:24:18 +0000 |
commit | 1ec5095d71bc63040c196401124c09f0b035999b (patch) | |
tree | 822c923648653fb7791e878e6b2c084fad98d61f /contrib/binutils/ld/emultempl | |
parent | 9065e980a4f15264a94d9bf01140109a23aa3e6a (diff) | |
download | FreeBSD-src-1ec5095d71bc63040c196401124c09f0b035999b.zip FreeBSD-src-1ec5095d71bc63040c196401124c09f0b035999b.tar.gz |
Merge rev 1.2 (teach `ld' how to access FreeBSD's ld ELF hints)
into Binutils 2.12.0_snap.
Diffstat (limited to 'contrib/binutils/ld/emultempl')
-rw-r--r-- | contrib/binutils/ld/emultempl/elf32.em | 265 |
1 files changed, 197 insertions, 68 deletions
diff --git a/contrib/binutils/ld/emultempl/elf32.em b/contrib/binutils/ld/emultempl/elf32.em index 0044a95..7642337 100644 --- a/contrib/binutils/ld/emultempl/elf32.em +++ b/contrib/binutils/ld/emultempl/elf32.em @@ -6,6 +6,11 @@ # This file is now misnamed, because it supports both 32 bit and 64 bit # ELF emulations. test -z "${ELFSIZE}" && ELFSIZE=32 +if [ -z "$MACHINE" ]; then + OUTPUT_ARCH=${ARCH} +else + OUTPUT_ARCH=${ARCH}:${MACHINE} +fi cat >e${EMULATION_NAME}.c <<EOF /* This file is is generated by a shell script. DO NOT EDIT! */ @@ -36,8 +41,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" #include "sysdep.h" #include "libiberty.h" - -#include <ctype.h> +#include "safe-ctype.h" #include "bfdlink.h" @@ -51,27 +55,38 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ldgram.h" #include "elf/common.h" -static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); +static void gld${EMULATION_NAME}_before_parse + PARAMS ((void)); static void gld${EMULATION_NAME}_vercheck PARAMS ((lang_input_statement_type *)); static void gld${EMULATION_NAME}_stat_needed PARAMS ((lang_input_statement_type *)); -static boolean gld${EMULATION_NAME}_try_needed PARAMS ((const char *, int)); +static boolean gld${EMULATION_NAME}_try_needed + PARAMS ((const char *, int)); static boolean gld${EMULATION_NAME}_search_needed PARAMS ((const char *, const char *, int)); static void gld${EMULATION_NAME}_check_needed PARAMS ((lang_input_statement_type *)); -static void gld${EMULATION_NAME}_after_open PARAMS ((void)); -static void gld${EMULATION_NAME}_find_exp_assignment PARAMS ((etree_type *)); +static void gld${EMULATION_NAME}_after_open + PARAMS ((void)); +static void gld${EMULATION_NAME}_find_exp_assignment + PARAMS ((etree_type *)); static void gld${EMULATION_NAME}_find_statement_assignment PARAMS ((lang_statement_union_type *)); -static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); +static void gld${EMULATION_NAME}_before_allocation + PARAMS ((void)); static boolean gld${EMULATION_NAME}_open_dynamic_archive PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); -static lang_output_section_statement_type *output_rel_find PARAMS ((void)); +static lang_output_section_statement_type *output_rel_find + PARAMS ((void)); +static asection *output_prev_sec_find + PARAMS ((lang_output_section_statement_type *)); static boolean gld${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); -static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); +static void gld${EMULATION_NAME}_finish + PARAMS ((void)); +static char *gld${EMULATION_NAME}_get_script + PARAMS ((int *isfile)); EOF @@ -93,7 +108,15 @@ cat >>e${EMULATION_NAME}.c <<EOF static void gld${EMULATION_NAME}_before_parse () { - ldfile_output_architecture = bfd_arch_`echo ${ARCH} | sed -e 's/:.*//'`; + const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}"); + if (arch) + { + ldfile_output_architecture = arch->arch; + ldfile_output_machine = arch->mach; + ldfile_output_machine_name = arch->printable_name; + } + else + 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`; } @@ -145,7 +168,7 @@ gld${EMULATION_NAME}_vercheck (s) soname = bfd_elf_get_dt_soname (s->the_bfd); if (soname == NULL) - soname = lbasename (bfd_get_filename (s->the_bfd)); + soname = basename (bfd_get_filename (s->the_bfd)); for (l = global_vercheck_needed; l != NULL; l = l->next) { @@ -227,10 +250,9 @@ gld${EMULATION_NAME}_stat_needed (s) soname = bfd_elf_get_dt_soname (s->the_bfd); if (soname == NULL) - soname = lbasename (s->filename); + soname = basename (s->filename); - if (strncmp (soname, global_needed->name, - suffix - global_needed->name) == 0) + if (strncmp (soname, global_needed->name, suffix - global_needed->name) == 0) einfo ("%P: warning: %s, needed by %B, may conflict with %s\n", global_needed->name, global_needed->by, soname); } @@ -253,12 +275,12 @@ gld${EMULATION_NAME}_try_needed (name, force) return false; if (! bfd_check_format (abfd, bfd_object)) { - (void) bfd_close (abfd); + bfd_close (abfd); return false; } if ((bfd_get_file_flags (abfd) & DYNAMIC) == 0) { - (void) bfd_close (abfd); + bfd_close (abfd); return false; } @@ -281,7 +303,7 @@ gld${EMULATION_NAME}_try_needed (name, force) lang_for_each_input_file (gld${EMULATION_NAME}_vercheck); if (global_vercheck_failed) { - (void) bfd_close (abfd); + bfd_close (abfd); /* Return false to force the caller to move on to try another file on the search path. */ return false; @@ -306,7 +328,7 @@ case ${target} in break; if (l == NULL) { - (void) bfd_close (abfd); + bfd_close (abfd); return false; } } @@ -332,7 +354,7 @@ cat >>e${EMULATION_NAME}.c <<EOF einfo ("%F%P:%B: bfd_stat failed: %E\n", abfd); /* First strip off everything before the last '/'. */ - soname = lbasename (abfd->filename); + soname = basename (abfd->filename); if (trace_file_tries) info_msg (_("found %s at %s\n"), soname, name); @@ -350,6 +372,9 @@ cat >>e${EMULATION_NAME}.c <<EOF DT_NEEDED entry for this file. */ bfd_elf_set_dt_needed_name (abfd, ""); + /* Previos basename call was clobbered in lang_for_each_input_file. */ + soname = basename (abfd->filename); + /* Tell the ELF backend that the output file needs a DT_NEEDED entry for this file if it is used to resolve the reference in a regular object. */ @@ -860,6 +885,18 @@ gld${EMULATION_NAME}_find_statement_assignment (s) EOF if test x"$LDEMUL_BEFORE_ALLOCATION" != xgld"$EMULATION_NAME"_before_allocation; then + if test x"${ELF_INTERPRETER_NAME+set}" = xset; then + ELF_INTERPRETER_SET_DEFAULT=" + if (sinterp != NULL) + { + sinterp->contents = ${ELF_INTERPRETER_NAME}; + sinterp->_raw_size = strlen (sinterp->contents) + 1; + } + +" + else + ELF_INTERPRETER_SET_DEFAULT= + fi cat >>e${EMULATION_NAME}.c <<EOF /* This is called after the sections have been attached to output @@ -883,11 +920,11 @@ gld${EMULATION_NAME}_before_allocation () rpath = (const char *) getenv ("LD_RUN_PATH"); if (! (bfd_elf${ELFSIZE}_size_dynamic_sections (output_bfd, command_line.soname, rpath, - command_line.export_dynamic, command_line.filter_shlib, + 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"); - +${ELF_INTERPRETER_SET_DEFAULT} /* Let the user override the dynamic linker we are using. */ if (command_line.interpreter != NULL && sinterp != NULL) @@ -1019,6 +1056,8 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) EOF fi + +if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then cat >>e${EMULATION_NAME}.c <<EOF /* A variant of lang_output_section_find. Used by place_orphan. */ @@ -1044,10 +1083,31 @@ output_rel_find () return (lang_output_section_statement_type *) NULL; } -EOF +/* Find the last output section before given output statement. + Used by place_orphan. */ -if test x"$LDEMUL_PLACE_ORPHAN" != xgld"$EMULATION_NAME"_place_orphan; then -cat >>e${EMULATION_NAME}.c <<EOF +static asection * +output_prev_sec_find (os) + lang_output_section_statement_type *os; +{ + asection *s = (asection *) NULL; + lang_statement_union_type *u; + lang_output_section_statement_type *lookup; + + for (u = lang_output_section_statement.head; + u != (lang_statement_union_type *) NULL; + u = lookup->next) + { + lookup = &u->output_section_statement; + if (lookup == os) + return s; + + if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL) + s = lookup->bfd_section; + } + + return NULL; +} /* Place an orphan section. We use this to put random SHF_ALLOC sections in the right segment. */ @@ -1088,12 +1148,13 @@ gld${EMULATION_NAME}_place_orphan (file, s) os = lang_output_section_find (secname); if (os != NULL - && os->bfd_section != NULL - && ((s->flags ^ os->bfd_section->flags) - & (SEC_LOAD | SEC_ALLOC)) == 0) + && (os->bfd_section == NULL + || ((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0)) { - /* We have already placed a section with this name. */ - wild_doit (&os->children, s, os, file); + /* We already have an output section statement with this + name, and its bfd section, if any, has compatible flags. */ + lang_add_section (&os->children, s, os, file); return true; } } @@ -1108,7 +1169,7 @@ gld${EMULATION_NAME}_place_orphan (file, s) && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 && hold_text.os != NULL) { - wild_doit (&hold_text.os->children, s, hold_text.os, file); + lang_add_section (&hold_text.os->children, s, hold_text.os, file); return true; } @@ -1121,7 +1182,11 @@ gld${EMULATION_NAME}_place_orphan (file, s) (hold.os != NULL || (hold.os = lang_output_section_find (name)) != NULL) if (s->flags & SEC_EXCLUDE) - return false; + { + if (s->output_section == NULL) + s->output_section = bfd_abs_section_ptr; + return true; + } place = NULL; if ((s->flags & SEC_ALLOC) == 0) @@ -1142,7 +1207,25 @@ gld${EMULATION_NAME}_place_orphan (file, s) else if (strncmp (secname, ".rel", 4) == 0 && (hold_rel.os != NULL || (hold_rel.os = output_rel_find ()) != NULL)) - place = &hold_rel; + { + if (! link_info.relocateable && link_info.combreloc) + { + if (strncmp (secname, ".rela", 5) == 0) + os = lang_output_section_find (".rela.dyn"); + else + os = lang_output_section_find (".rel.dyn"); + + if (os != NULL + && os->bfd_section != NULL + && ((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0) + { + lang_add_section (&os->children, s, os, file); + return true; + } + } + place = &hold_rel; + } else if ((s->flags & (SEC_CODE | SEC_READONLY)) == SEC_READONLY && HAVE_SECTION (hold_rodata, ".rodata")) place = &hold_rodata; @@ -1183,7 +1266,7 @@ 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 = outsecname; *ps != '\0'; ps++) - if (! isalnum ((unsigned char) *ps) && *ps != '_') + if (! ISALNUM (*ps) && *ps != '_') break; if (*ps == '\0') { @@ -1209,7 +1292,7 @@ gld${EMULATION_NAME}_place_orphan (file, s) (etree_type *) NULL, (etree_type *) NULL); - wild_doit (&os->children, s, os, file); + lang_add_section (&os->children, s, os, file); lang_leave_output_section_statement ((bfd_vma) 0, "*default*", @@ -1238,45 +1321,50 @@ gld${EMULATION_NAME}_place_orphan (file, s) asection *snew, **pps; snew = os->bfd_section; - if (place->section != NULL - || (place->os->bfd_section != NULL - && place->os->bfd_section != snew)) + + /* Shuffle the bfd section list to make the output file look + neater. This is really only cosmetic. */ + if (place->section == NULL) { - /* Shuffle the section to make the output file look neater. - This is really only cosmetic. */ - if (place->section == NULL) - { -#if 0 - /* Finding the end of the list is a little tricky. We - make a wild stab at it by comparing section flags. */ - flagword first_flags = place->os->bfd_section->flags; - for (pps = &place->os->bfd_section->next; - *pps != NULL && (*pps)->flags == first_flags; - pps = &(*pps)->next) - ; - place->section = pps; -#else - /* Put orphans after the first section on the list. */ - place->section = &place->os->bfd_section->next; -#endif - } + asection *bfd_section = place->os->bfd_section; - /* Unlink the section. */ + /* If the output statement hasn't been used to place + any input sections (and thus doesn't have an output + bfd_section), look for the closest prior output statement + having an output section. */ + if (bfd_section == NULL) + bfd_section = output_prev_sec_find (place->os); + + if (bfd_section != NULL && bfd_section != snew) + place->section = &bfd_section->next; + } + + if (place->section != NULL) + { + /* Unlink the section. */ for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) ; - *pps = snew->next; + bfd_section_list_remove (output_bfd, pps); /* Now tack it on to the "place->os" section list. */ - snew->next = *place->section; - *place->section = snew; + bfd_section_list_insert (output_bfd, place->section, snew); } - place->section = &snew->next; /* Save the end of this list. */ + /* Save the end of this list. Further ophans of this type will + follow the one we've just added. */ + place->section = &snew->next; + + /* The following is non-cosmetic. We try to put the output + statements in some sort of reasonable order here, because + they determine the final load addresses of the orphan + sections. In addition, placing output statements in the + wrong order may require extra segments. For instance, + given a typical situation of all read-only sections placed + in one segment and following that a segment containing all + the read-write sections, we wouldn't want to place an orphan + read/write section before or amongst the read-only ones. */ if (add.head != NULL) { - /* We try to put the output statements in some sort of - reasonable order here, because they determine the final - load addresses of the orphan sections. */ if (place->stmt == NULL) { /* Put the new statement list right at the head. */ @@ -1302,7 +1390,29 @@ gld${EMULATION_NAME}_place_orphan (file, s) return true; } +EOF +fi + +if test x"$LDEMUL_FINISH" != xgld"$EMULATION_NAME"_finish; then +cat >>e${EMULATION_NAME}.c <<EOF + +static void +gld${EMULATION_NAME}_finish () +{ + if (bfd_elf${ELFSIZE}_discard_info (output_bfd, &link_info)) + { + /* Resize the sections. */ + lang_size_sections (stat_ptr->head, abs_output_section, + &stat_ptr->head, 0, (bfd_vma) 0, NULL); + /* Redo special stuff. */ + ldemul_after_allocation (); + + /* Do the assignments again. */ + lang_do_assignments (stat_ptr->head, abs_output_section, + (fill_type) 0, (bfd_vma) 0); + } +} EOF fi @@ -1333,14 +1443,18 @@ echo ' ; else if (link_info.relocateable == true) return' >> e${EMULATION_NAME} 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 +if cmp -s ldscripts/${EMULATION_NAME}.x ldscripts/${EMULATION_NAME}.xn; then : ; else echo ' ; else if (!config.magic_demand_paged) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xn >> e${EMULATION_NAME}.c - +fi if test -n "$GENERATE_SHLIB_SCRIPT" ; then +echo ' ; else if (link_info.shared && link_info.combreloc) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xsc >> e${EMULATION_NAME}.c echo ' ; else if (link_info.shared) return' >> e${EMULATION_NAME}.c sed $sc ldscripts/${EMULATION_NAME}.xs >> e${EMULATION_NAME}.c fi - +echo ' ; else if (link_info.combreloc) return' >> e${EMULATION_NAME}.c +sed $sc ldscripts/${EMULATION_NAME}.xc >> 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 @@ -1387,6 +1501,7 @@ cat >>e${EMULATION_NAME}.c <<EOF #define OPTION_DISABLE_NEW_DTAGS (400) #define OPTION_ENABLE_NEW_DTAGS (OPTION_DISABLE_NEW_DTAGS + 1) #define OPTION_GROUP (OPTION_ENABLE_NEW_DTAGS + 1) +#define OPTION_EH_FRAME_HDR (OPTION_GROUP + 1) static struct option longopts[] = { @@ -1400,6 +1515,7 @@ cat >>e${EMULATION_NAME}.c <<EOF {"disable-new-dtags", no_argument, NULL, OPTION_DISABLE_NEW_DTAGS}, {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, {"enable-new-dtags", no_argument, NULL, OPTION_ENABLE_NEW_DTAGS}, + {"eh-frame-hdr", no_argument, NULL, OPTION_EH_FRAME_HDR}, {"Bgroup", no_argument, NULL, OPTION_GROUP}, {"Bgroup", no_argument, NULL, OPTION_GROUP}, EOF @@ -1460,6 +1576,10 @@ cat >>e${EMULATION_NAME}.c <<EOF link_info.new_dtags = true; break; + case OPTION_EH_FRAME_HDR: + link_info.eh_frame_hdr = true; + break; + case OPTION_GROUP: link_info.flags_1 |= (bfd_vma) DF_1_GROUP; /* Groups must be self-contained. */ @@ -1493,6 +1613,12 @@ cat >>e${EMULATION_NAME}.c <<EOF } else if (strcmp (optarg, "defs") == 0) link_info.no_undefined = true; + else if (strcmp (optarg, "combreloc") == 0) + link_info.combreloc = true; + else if (strcmp (optarg, "nocombreloc") == 0) + link_info.combreloc = false; + else if (strcmp (optarg, "nocopyreloc") == 0) + link_info.nocopyreloc = true; /* What about the other Solaris -z options? FIXME. */ break; EOF @@ -1529,17 +1655,20 @@ cat >>e${EMULATION_NAME}.c <<EOF fprintf (file, _(" -Bgroup\t\tSelects group name lookup rules for DSO\n")); fprintf (file, _(" --disable-new-dtags\tDisable new dynamic tags\n")); fprintf (file, _(" --enable-new-dtags\tEnable new dynamic tags\n")); + fprintf (file, _(" --eh-frame-hdr\tCreate .eh_frame_hdr section\n")); + fprintf (file, _(" -z combreloc\t\tMerge dynamic relocs into one section and sort\n")); fprintf (file, _(" -z defs\t\tDisallows undefined symbols\n")); fprintf (file, _(" -z initfirst\t\tMark DSO to be initialized first at runtime\n")); fprintf (file, _(" -z interpose\t\tMark object to interpose all DSOs but executable\n")); fprintf (file, _(" -z loadfltr\t\tMark object requiring immediate process\n")); + fprintf (file, _(" -z nocombreloc\tDon't merge dynamic relocs into one section\n")); + fprintf (file, _(" -z nocopyreloc\tDon't create copy relocs\n")); fprintf (file, _(" -z nodefaultlib\tMark object not to use default search paths\n")); fprintf (file, _(" -z nodelete\t\tMark DSO non-deletable at runtime\n")); fprintf (file, _(" -z nodlopen\t\tMark DSO not available to dlopen\n")); fprintf (file, _(" -z nodump\t\tMark DSO not available to dldump\n")); fprintf (file, _(" -z now\t\tMark object non-lazy runtime binding\n")); - fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n")); - fprintf (file, _("\t\t\t at runtime\n")); + fprintf (file, _(" -z origin\t\tMark object requiring immediate \$ORIGIN processing\n\t\t\t at runtime\n")); fprintf (file, _(" -z KEYWORD\t\tIgnored for Solaris compatibility\n")); EOF fi @@ -1589,7 +1718,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = ${LDEMUL_GET_SCRIPT-gld${EMULATION_NAME}_get_script}, "${EMULATION_NAME}", "${OUTPUT_FORMAT}", - ${LDEMUL_FINISH-NULL}, + ${LDEMUL_FINISH-gld${EMULATION_NAME}_finish}, ${LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS-NULL}, ${LDEMUL_OPEN_DYNAMIC_ARCHIVE-gld${EMULATION_NAME}_open_dynamic_archive}, ${LDEMUL_PLACE_ORPHAN-gld${EMULATION_NAME}_place_orphan}, |