Add Linux style directory searching.
authorIan Lance Taylor <ian@airs.com>
Fri, 8 Sep 1995 23:37:45 +0000 (23:37 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 8 Sep 1995 23:37:45 +0000 (23:37 +0000)
* 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
ld/Makefile.in
ld/configure.tgt
ld/emulparams/.Sanitize
ld/emulparams/i386lelf.sh [new file with mode: 0644]
ld/emultempl/elf32.em

index abc8d03..8d85e4c 100644 (file)
@@ -1,5 +1,20 @@
 Fri Sep  8 16:32:43 1995  Ian Lance Taylor  <ian@cygnus.com>
 
+       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.
index 0543547..07842ce 100644 (file)
@@ -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.
index 6d82a08..13e6bff 100644 (file)
@@ -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 ;;
index dc0ec29..5b129e2 100644 (file)
@@ -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 (file)
index 0000000..b841d9c
--- /dev/null
@@ -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
index b3cb74d..0be8009 100644 (file)
@@ -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 <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+#  include <sys/ndir.h>
+# endif
+# ifdef HAVE_SYS_DIR_H
+#  include <sys/dir.h>
+# endif
+# ifdef HAVE_NDIR_H
+#  include <ndir.h>
+# 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;