diff options
author | Marc Espie <espie@cvs.openbsd.org> | 2000-10-20 12:25:21 +0000 |
---|---|---|
committer | Marc Espie <espie@cvs.openbsd.org> | 2000-10-20 12:25:21 +0000 |
commit | 805ccd92b3b85dddd509fc07950b118368d38e0c (patch) | |
tree | 378944978c64aedc717de91cf4b7dad7d3eabc1a /gnu/usr.bin | |
parent | f932f29c05da31be7462b924a875114c1889eb30 (diff) |
Add support for major/minor version numbers.
Testing by Dale.
Ok'd deraadt@
Diffstat (limited to 'gnu/usr.bin')
-rw-r--r-- | gnu/usr.bin/binutils/ld/emultempl/elf32.em | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/gnu/usr.bin/binutils/ld/emultempl/elf32.em b/gnu/usr.bin/binutils/ld/emultempl/elf32.em index 2913ecf1bcb..d629d9a245b 100644 --- a/gnu/usr.bin/binutils/ld/emultempl/elf32.em +++ b/gnu/usr.bin/binutils/ld/emultempl/elf32.em @@ -69,6 +69,155 @@ static void gld${EMULATION_NAME}_place_section PARAMS ((lang_statement_union_type *)); static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); +EOF +case ${target} in + *-*-openbsd*) + cat >>e${EMULATION_NAME}.c <<EOF +#include <sys/types.h> +#include <dirent.h> + +/* Search a directory for a .so file. */ + +static char * +gld${EMULATION_NAME}_search_dir (dirname, filename) + const char *dirname; + const char *filename; +{ + int force_maj, force_min; + const char *dot; + unsigned int len; + char *alc; + char *found; + int max_maj, max_min; + DIR *dir; + struct dirent *entry; + unsigned int dirnamelen; + char *full_path; + int statval; + struct stat st; + + force_maj = -1; + force_min = -1; + dot = strchr (filename, '.'); + if (dot == NULL) + { + len = strlen (filename); + alc = NULL; + } + else + { + force_maj = atoi (dot + 1); + + len = dot - filename; + alc = (char *) xmalloc (len + 1); + strncpy (alc, filename, len); + alc[len] = '\0'; + filename = alc; + + dot = strchr (dot + 1, '.'); + if (dot != NULL) + force_min = atoi (dot + 1); + } + + found = NULL; + max_maj = max_min = 0; + + dir = opendir (dirname); + if (dir == NULL) + return NULL; + dirnamelen = strlen (dirname); + + while ((entry = readdir (dir)) != NULL) + { + const char *s; + char *eptr, *eptr1; + int found_maj, found_min; + + if (strncmp (entry->d_name, "lib", 3) != 0 + || strncmp (entry->d_name + 3, filename, len) != 0) + continue; + + /* We accept libfoo.so without a version number, even though the + native linker does not. This is more convenient for packages + which just generate .so files for shared libraries, as on ELF + systems. */ + if (strncmp (entry->d_name + 3 + len, ".so", 3) != 0) + continue; + + if (entry->d_name[6 + len] == '\0') + ; + else if (entry->d_name[6 + len] == '.' + && isdigit ((unsigned char) entry->d_name[7 + len])) + ; + else + continue; + + for (s = entry->d_name + 6 + len; *s != '\0'; s++) + if (*s != '.' && ! isdigit ((unsigned char) *s)) + break; + if (*s != '\0') + continue; + + /* We've found a .so file. Work out the major and minor + version numbers. */ + found_maj = -1; + found_min = -1; + + /* do allow libN.so */ + if (entry->d_name[6 + len] == '.') { + found_maj = strtoul (entry->d_name + 7 + len, &eptr, 10); + + /* do not support libN.so. or libN.so.X */ + if (*eptr != '.' || ((entry->d_name + 3 + len) == eptr)) + continue; + + found_min = strtoul (eptr+1, &eptr1, 10); + + /* do not support libN.so.X. or libN.so.X.Y.[anything] */ + if (*eptr1 != '\0' || (eptr+1 == eptr1)) + continue; + } + + if ((force_maj != -1 && force_maj != found_maj) + || (force_min != -1 && force_min != found_min)) + continue; + + /* Make sure the file really exists (ignore broken symlinks). */ + full_path = xmalloc (dirnamelen + 1 + strlen (entry->d_name) + 1); + sprintf (full_path, "%s/%s", dirname, entry->d_name); + statval = stat (full_path, &st); + free (full_path); + if (statval != 0) + continue; + + /* We've found a match for the name we are searching for. See + if this is the version we should use. */ + if (found == NULL + || (found_maj > max_maj) + || (found_maj == max_maj + && (found_min > max_min))) + { + if (found != NULL) + free (found); + found = (char *) xmalloc (dirnamelen + strlen (entry->d_name) + 2); + sprintf (found, "%s/%s", dirname, entry->d_name); + max_maj = found_maj; + max_min = found_min; + } + } + + closedir (dir); + + if (alc != NULL) + free (alc); + + return found; +} + +EOF + ;; +esac +cat >>e${EMULATION_NAME}.c <<EOF static void gld${EMULATION_NAME}_before_parse() { @@ -95,6 +244,15 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) filename = entry->filename; +EOF +case ${target} in + *-*-openbsd*) + cat >>e${EMULATION_NAME}.c <<EOF + string = gld${EMULATION_NAME}_search_dir(search->name, filename); +EOF + ;; + *) + cat >>e${EMULATION_NAME}.c <<EOF /* 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. */ @@ -108,6 +266,10 @@ gld${EMULATION_NAME}_open_dynamic_archive (arch, search, entry) sprintf (string, "%s/lib%s%s.so", search->name, filename, arch); +EOF + ;; +esac +cat >>e${EMULATION_NAME}.c <<EOF #ifdef EXTRA_SHLIB_EXTENSION /* Try the .so extension first. If that fails build a new filename using EXTRA_SHLIB_EXTENSION. */ |