diff options
author | Ian Lance Taylor <ian@airs.com> | 1995-09-08 23:37:45 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1995-09-08 23:37:45 +0000 |
commit | ed753c20492aad05a0bd210970412c6e333dd09c (patch) | |
tree | 0381d7a2c296fd4d5591c4cbbcee45fa22fe1276 /ld/emultempl/elf32.em | |
parent | 2b71e1e4d790289e6c62d67104cdfa968ba1d94e (diff) | |
download | gdb-ed753c20492aad05a0bd210970412c6e333dd09c.zip gdb-ed753c20492aad05a0bd210970412c6e333dd09c.tar.gz gdb-ed753c20492aad05a0bd210970412c6e333dd09c.tar.bz2 |
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.
Diffstat (limited to 'ld/emultempl/elf32.em')
-rw-r--r-- | ld/emultempl/elf32.em | 185 |
1 files changed, 179 insertions, 6 deletions
diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index b3cb74d..0be8009 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 <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; |