From ed753c20492aad05a0bd210970412c6e333dd09c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 8 Sep 1995 23:37:45 +0000 Subject: [PATCH] Add Linux style directory searching. * configure.tgt: Add i386lelf to targ_extra_emuls for i[345]86-*-linuxaout* and i[345]86-*-linuxoldld. For i[345]86-*-linux*, set targ_emul to i386lelf, and add elf_i386 to targ_extra_emuls. * emulparams/i386lelf.sh: New file, a copy of elf_i386.sh. * emultempl/elf32.em: If TARGET_IS_i386lelf, use autoconf recommended mechanism to define DIR and struct dirent. (libcmp): New static function use only when TARGET_IS_i386lelf. (gld${EMULATION_NAME}_open_dynamic_archive): Likewise. * Makefile.in (ALL_EMULATIONS): Add ei386lelf.o (ei386lelf.c): New target. --- ld/ChangeLog | 15 ++++ ld/Makefile.in | 8 +- ld/configure.tgt | 12 ++- ld/emulparams/.Sanitize | 1 + ld/emulparams/i386lelf.sh | 9 ++ ld/emultempl/elf32.em | 185 ++++++++++++++++++++++++++++++++++++-- 6 files changed, 219 insertions(+), 11 deletions(-) create mode 100644 ld/emulparams/i386lelf.sh diff --git a/ld/ChangeLog b/ld/ChangeLog index abc8d033f01..8d85e4c7409 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,20 @@ Fri Sep 8 16:32:43 1995 Ian Lance Taylor + Add Linux style directory searching. + * configure.tgt: Add i386lelf to targ_extra_emuls for + i[345]86-*-linuxaout* and i[345]86-*-linuxoldld. For + i[345]86-*-linux*, set targ_emul to i386lelf, and add elf_i386 to + targ_extra_emuls. + * emulparams/i386lelf.sh: New file, a copy of elf_i386.sh. + * emultempl/elf32.em: If TARGET_IS_i386lelf, use autoconf + recommended mechanism to define DIR and struct dirent. + (libcmp): New static function use only when TARGET_IS_i386lelf. + (gld${EMULATION_NAME}_open_dynamic_archive): Likewise. + * Makefile.in (ALL_EMULATIONS): Add ei386lelf.o + (ei386lelf.c): New target. + + * Makefile.in (config.status): Depend upon configure.tgt. + * ldemul.h (ldemul_set_symbols): Declare. (ldemul_parse_args): Declare. * ldemul.c (ldemul_parse_args): Fix indentation. diff --git a/ld/Makefile.in b/ld/Makefile.in index 05435473736..07842cecd0f 100644 --- a/ld/Makefile.in +++ b/ld/Makefile.in @@ -202,7 +202,8 @@ ALL_EMULATIONS = ea29k.o ealpha.o earmaoutl.o earmaoutb.o \ emipsidt.o emipsidtl.o emipslit.o enews.o ens32knbsd.o eppcnw.o \ eriscix.o esa29200.o eshl.o esh.o esparclynx.o esparcnbsd.o \ est2000.o esun3.o esun4.o evanilla.o evax.o evsta.o \ - ez8001.o ez8002.o ei386pe.o earmpe.o eelf32vr4300.o eelf32vr4300el.o + ez8001.o ez8002.o ei386pe.o earmpe.o eelf32vr4300.o \ + eelf32vr4300el.o ei386lelf.o CFILES = ldctor.c ldemul.c ldexp.c ldfile.c ldlang.c \ ldmain.c ldmisc.c ldver.c ldwrite.c lexsup.c \ @@ -441,6 +442,9 @@ em68kaout.c: $(srcdir)/emulparams/m68kaout.sh \ ei386linux.c: $(srcdir)/emulparams/i386linux.sh \ $(srcdir)/emultempl/linux.em $(srcdir)/scripttempl/aout.sc ${GEN_DEPENDS} ${GENSCRIPTS} i386linux +ei386lelf.c: $(srcdir)/emulparams/i386lelf.sh \ + $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} + ${GENSCRIPTS} i386lelf eelf32_sparc.c: $(srcdir)/emulparams/elf32_sparc.sh \ $(srcdir)/emultempl/elf32.em $(srcdir)/scripttempl/elf.sc ${GEN_DEPENDS} ${GENSCRIPTS} elf32_sparc @@ -859,7 +863,7 @@ config.h: stamp-h ; @true stamp-h: config.in config.status CONFIG_FILES= CONFIG_HEADERS=config.h:config.in $(SHELL) ./config.status -config.status: configure configure.host +config.status: configure configure.host configure.tgt $(SHELL) ./config.status --recheck # What appears below is generated by a hacked mkdep using gcc -MM. diff --git a/ld/configure.tgt b/ld/configure.tgt index 6d82a0883c2..13e6bffec4e 100644 --- a/ld/configure.tgt +++ b/ld/configure.tgt @@ -46,9 +46,15 @@ i[345]86-*-bsd) targ_emul=i386bsd ;; i[345]86-*-bsd386) targ_emul=i386bsd ;; i[345]86-*-bsdi*) targ_emul=i386bsd ;; i[345]86-*-aout) targ_emul=i386aout ;; -i[345]86-*-linuxaout*) targ_emul=i386linux; targ_extra_emuls=elf_i386 ;; -i[345]86-*-linuxoldld) targ_emul=i386linux; targ_extra_emuls=elf_i386 ;; -i[345]86-*-linux*) targ_emul=elf_i386; targ_extra_emuls=i386linux ;; +i[345]86-*-linuxaout*) targ_emul=i386linux + targ_extra_emuls="i386lelf elf_i386" + ;; +i[345]86-*-linuxoldld) targ_emul=i386linux + targ_extra_emuls="i386lelf elf_i386" + ;; +i[345]86-*-linux*) targ_emul=i386lelf + targ_extra_emuls="elf_i386 i386linux" + ;; i[345]86-*-sysv4*) targ_emul=elf_i386 ;; i[345]86-*-unixware) targ_emul=elf_i386 ;; i[345]86-*-netbsd*) targ_emul=i386nbsd ;; diff --git a/ld/emulparams/.Sanitize b/ld/emulparams/.Sanitize index dc0ec298c3c..5b129e2060b 100644 --- a/ld/emulparams/.Sanitize +++ b/ld/emulparams/.Sanitize @@ -74,6 +74,7 @@ i386bsd.sh i386coff.sh i386go32.sh i386linux.sh +i386lelf.sh i386lynx.sh i386mach.sh i386moss.sh diff --git a/ld/emulparams/i386lelf.sh b/ld/emulparams/i386lelf.sh new file mode 100644 index 00000000000..b841d9cd189 --- /dev/null +++ b/ld/emulparams/i386lelf.sh @@ -0,0 +1,9 @@ +SCRIPT_NAME=elf +OUTPUT_FORMAT="elf32-i386" +TEXT_START_ADDR=0x08000000 +MAXPAGESIZE=0x1000 +NONPAGED_TEXT_START_ADDR=0x08000000 +ARCH=i386 +NOP=0x9090 +TEMPLATE_NAME=elf32 +GENERATE_SHLIB_SCRIPT=yes diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index b3cb74d63a7..0be80093750 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -34,7 +34,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfdlink.h" #include "ld.h" -#include "config.h" #include "ldmain.h" #include "ldemul.h" #include "ldfile.h" @@ -43,9 +42,26 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "ldlang.h" #include "ldgram.h" +#ifdef TARGET_IS_i386lelf +#ifdef HAVE_DIRENT_H +# include +#else +# define dirent direct +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif +#endif + static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static boolean gld${EMULATION_NAME}_open_dynamic_archive - PARAMS ((const char *, lang_input_statement_type *)); + PARAMS ((const char *, search_dirs_type *, lang_input_statement_type *)); static void gld${EMULATION_NAME}_after_open PARAMS ((void)); static void gld${EMULATION_NAME}_check_needed PARAMS ((lang_input_statement_type *)); @@ -69,20 +85,39 @@ gld${EMULATION_NAME}_before_parse() config.dynamic_link = ${DYNAMIC_LINK-true}; } +#ifndef TARGET_IS_i386lelf + /* Try to open a dynamic archive. This is where we know that ELF dynamic libraries have an extension of .so. */ static boolean -gld${EMULATION_NAME}_open_dynamic_archive (arch, entry) +gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) const char *arch; + search_dirs_type *search; lang_input_statement_type *entry; { const char *filename; + char *string; + + if (! entry->is_archive) + return false; filename = entry->filename; - if (! ldfile_open_file_search (arch, entry, "lib", ".so")) - return false; + string = (char *) xmalloc (strlen (search->name) + + strlen (filename) + + strlen (arch) + + sizeof "/lib.so"); + + sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); + + if (! ldfile_try_open_bfd (string, entry)) + { + free (string); + return false; + } + + entry->filename = string; /* We have found a dynamic object to include in the link. The ELF backend linker will create a DT_NEEDED entry in the .dynamic @@ -113,6 +148,121 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, entry) return true; } +#else /* TARGET_IS_i386lelf */ + +/* Linux deviates from the SVR4 standard in that its archives use + version numbers in the file name. I think this is bogus, but + H.J. Lu insists that it be done this way. */ + +static int libcmp PARAMS ((const char *, const char *)); + +/* Choose between two library names. This is like a string + comparison, except that numbers are compared by value. */ + +static int +libcmp (p1, p2) + const char *p1; + const char *p2; +{ + while (*p1 != '\0') + { + if (isdigit (*p1) && isdigit (*p2)) + { + unsigned long v1, v2; + + v1 = strtoul (p1, (char **) &p1, 10); + v2 = strtoul (p2, (char **) &p2, 10); + if (v1 < v2) + return -1; + else if (v1 > v2) + return 1; + } + else if (*p1 < *p2) + return -1; + else if (*p1 > *p2) + return 1; + else + { + ++p1; + ++p2; + } + } + + if (*p2 != '\0') + return -1; + + return 0; +} + +/* Search for the library to open. */ + +/*ARGSUSED*/ +static boolean +gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) + const char *arch; + search_dirs_type *search; + lang_input_statement_type *entry; +{ + size_t len; + char *found; + DIR *dir; + struct dirent *ent; + char *string; + + len = strlen (entry->filename); + + found = NULL; + + dir = opendir (search->name); + if (dir == NULL) + return false; + + while ((ent = readdir (dir)) != NULL) + { + if (strncmp (ent->d_name, "lib", 3) != 0 + || strncmp (ent->d_name + 3, entry->filename, len) != 0 + || strncmp (ent->d_name + len + 3, ".so", 3) != 0) + continue; + + if (found != NULL) + { + if (libcmp (ent->d_name + len + 6, found + len + 6) < 0) + continue; + free (found); + } + + found = (char *) xmalloc (strlen (ent->d_name) + 1); + strcpy (found, ent->d_name); + } + + closedir (dir); + + if (found == NULL) + return false; + + string = (char *) xmalloc (strlen (search->name) + strlen (found) + 2); + sprintf (string, "%s/%s", search->name, found); + if (! ldfile_try_open_bfd (string, entry)) + { + free (found); + return false; + } + + entry->filename = string; + + if (bfd_check_format (entry->the_bfd, bfd_object) + && (entry->the_bfd->flags & DYNAMIC) != 0) + { + ASSERT (entry->is_archive && entry->search_dirs_flag); + bfd_elf_set_dt_needed_name (entry->the_bfd, found); + } + + return true; + +} + +#endif /* TARGET_IS_i386lelf */ + /* These variables are required to pass information back and forth between after_open and check_needed. */ @@ -279,6 +429,17 @@ gld${EMULATION_NAME}_check_needed (s) if (s->filename != NULL && strcmp (s->filename, global_needed->name) == 0) global_found = true; + else if (s->search_dirs_flag + && s->filename != NULL + && strchr (global_needed->name, '/') == NULL) + { + const char *f; + + f = strrchr (s->filename, '/'); + if (f != NULL + && strcmp (f + 1, global_needed->name) == 0) + global_found = true; + } } /* This is called after the sections have been attached to output @@ -338,7 +499,8 @@ gld${EMULATION_NAME}_before_allocation () einfo ("%F%B: Can't read contents of section .gnu.warning: %E\n", is->the_bfd); msg[sz] = '\0'; - ret = link_info.callbacks->warning (&link_info, msg); + ret = link_info.callbacks->warning (&link_info, msg, is->the_bfd, + (asection *) NULL, (bfd_vma) 0); ASSERT (ret); free (msg); @@ -491,6 +653,17 @@ gld${EMULATION_NAME}_place_orphan (file, s) secname = bfd_get_section_name (s->owner, s); + /* If this is a final link, then always put .gnu.warning.SYMBOL + sections into the .text section to get them out of the way. */ + if (! link_info.shared + && ! link_info.relocateable + && strncmp (secname, ".gnu.warning.", sizeof ".gnu.warning." - 1) == 0 + && hold_text != NULL) + { + wild_doit (&hold_text->children, s, hold_text, file); + return true; + } + /* Decide which segment the section should go in based on the section name and section flags. */ place = NULL; -- 2.30.2