From mboxrd@z Thu Jan 1 00:00:00 1970 From: hjl@nynexst.com (H.J. Lu) To: raeburn@cygnus.com (Ken Raeburn) Cc: gas2@cygnus.com Subject: A new ld patch Date: Tue, 02 May 1995 21:23:00 -0000 Message-id: <9505030420.AA12567@titanic.nynexst.com> X-SW-Source: 1995/msg00086.html This patch added the support fo -Bstatic -lfoo -Bdynamic -lbar. It also fixed the -Lxxxxx bug. H.J. ------ Tue May 2 00:22:54 1995 H.J. Lu (hjl@nynexst.com) * Makefile.in: fix a typo in comments. (NO_DEFAULT_WRITABLE_TEXT_SEGMENT): unset. (GENSCRIPTS): add "${NO_DEFAULT_WRITABLE_TEXT_SEGMENT}" and "${LIB_PATH}". * genscripts.sh (LIB_PATH): set to $7. (NO_DEFAULT_WRITABLE_TEXT_SEGMENT): set to $8. (EMULATION_NAME): set to $9. don't include the native ${LIB_PATH} for non-native emulation. * ldfile.c (try_open_bfd): make it global. (ldfile_open_file): check entry->dynamic_link instead of config.dynamic_link. * ldlang.h (lang_input_statement_type): add boolean dynamic_link; * lexsup.c (parse_args): add boolean last_is_dynamic_link = config.dynamic_link; (OPTION_CALL_SHARED): set last_is_dynamic_link = true; (OPTION_NON_SHARED): set last_is_dynamic_link = false; ('l'): set the dynamic_link field of the library entry to last_is_dynamic_link. Those changes add the -Bstaic -lfoo -Bdynamic -lbar support to ld. * config/i386-linux.mt (NO_DEFAULT_WRITABLE_TEXT_SEGMENT): set to y. * emultempl/elf32.em: add #include . (libcmp): new function, compare two shared libraries and return the order. (gld${EMULATION_NAME}_find_so): new, static. search for open the .so file specified by ENTRY until a match .so or .a file is found. (gld${EMULATION_NAME}_open_dynamic_archive): call gld${EMULATION_NAME}_find_so () to find the shared library. use entry->filename for needed_name. * scripttempl/elf.sc (DATA_ALIGN): if NO_DEFAULT_WRITABLE_TEXT_SEGMENT is 'y' or 'Y', set to ${DATA_ADDR-ALIGN(${MAXPAGESIZE}) + \ ((ALIGN(8) + ${MAXPAGESIZE} - \ ALIGN(${MAXPAGESIZE})) & (${MAXPAGESIZE} - 1))} or set to ${DATA_ADDR- ALIGN(8) + ${MAXPAGESIZE}} =================================================================== RCS file: /home/cvs/gnu/binutils/ld/Makefile.in,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 Makefile.in *** 1.1.1.3 1995/04/17 23:41:03 --- Makefile.in 1995/05/03 02:50:15 *************** *** 66,74 **** BISON = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L../bison/bison ; else echo bison -y ; fi` LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi` # Seach path to override the default search path for -lfoo libraries. # If LIB_PATH is empty, the ones in the script (if any) are left alone. ! # (The default is usually /lib:usr/lib:/usr/local/lib, unless building # a cross-linker, in which case the default is empty. See genscripts.sh.) # Otherwise, they are replaced with the ones given in LIB_PATH, # which may have the form: LIB_PATH=/lib:/usr/local/lib --- 66,77 ---- BISON = `if [ -f ../bison/bison ] ; then echo ../bison/bison -y -L../bison/bison ; else echo bison -y ; fi` LEX = `if [ -f ../flex/flex ] ; then echo ../flex/flex ; else echo flex ; fi` + # This is for the ELF emulation scripts. + NO_DEFAULT_WRITABLE_TEXT_SEGMENT= + # Seach path to override the default search path for -lfoo libraries. # If LIB_PATH is empty, the ones in the script (if any) are left alone. ! # (The default is usually /lib:/usr/lib:/usr/local/lib, unless building # a cross-linker, in which case the default is empty. See genscripts.sh.) # Otherwise, they are replaced with the ones given in LIB_PATH, # which may have the form: LIB_PATH=/lib:/usr/local/lib *************** *** 273,279 **** # These all start with e so 'make clean' can find them. ! GENSCRIPTS = $(SHELL) $(srcdir)/genscripts.sh ${srcdir} ${libdir} ${host_alias} ${target_alias} ${EMUL} "$(NATIVE_LIB_DIRS)" GEN_DEPENDS = $(srcdir)/genscripts.sh $(srcdir)/emultempl/stringify.sed esun4.c: $(srcdir)/emulparams/sun4.sh \ --- 276,282 ---- # These all start with e so 'make clean' can find them. ! GENSCRIPTS = $(SHELL) $(srcdir)/genscripts.sh ${srcdir} ${libdir} ${host_alias} ${target_alias} ${EMUL} "$(NATIVE_LIB_DIRS)" "${LIB_PATH}" "${NO_DEFAULT_WRITABLE_TEXT_SEGMENT}" GEN_DEPENDS = $(srcdir)/genscripts.sh $(srcdir)/emultempl/stringify.sed esun4.c: $(srcdir)/emulparams/sun4.sh \ =================================================================== RCS file: /home/cvs/gnu/binutils/ld/genscripts.sh,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 genscripts.sh *** 1.1.1.3 1995/03/24 02:20:37 --- genscripts.sh 1995/05/03 02:50:15 *************** *** 15,21 **** target_alias=$4 DEFAULT_EMULATION=$5 NATIVE_LIB_DIRS=$6 ! EMULATION_NAME=$7 # Include the emulation-specific parameters: . ${srcdir}/emulparams/${EMULATION_NAME}.sh --- 15,23 ---- target_alias=$4 DEFAULT_EMULATION=$5 NATIVE_LIB_DIRS=$6 ! LIB_PATH=$7 ! NO_DEFAULT_WRITABLE_TEXT_SEGMENT=$8 ! EMULATION_NAME=$9 # Include the emulation-specific parameters: . ${srcdir}/emulparams/${EMULATION_NAME}.sh *************** *** 52,58 **** fi # Always search $(tooldir)/lib, aka /usr/local/TARGET/lib. ! LIB_PATH=${LIB_PATH}:`echo ${libdir} | sed -e s'|/lib$||'`/${target_alias}/lib LIB_SEARCH_DIRS=`echo ${LIB_PATH} | tr ':' ' ' | sed -e 's/\([^ ][^ ]*\)/SEARCH_DIR(\1);/g'` --- 54,65 ---- fi # Always search $(tooldir)/lib, aka /usr/local/TARGET/lib. ! if [ $DEFAULT_EMULATION = $EMULATION_NAME ]; then ! LIB_PATH=${LIB_PATH}:`echo ${libdir} | sed -e s'|/lib$||'`/${target_alias}/lib ! else ! # This is not correct one since this is for a different target. ! LIB_PATH=`echo ${libdir} | sed -e s'|/lib$||'`/${target_alias}/lib ! fi LIB_SEARCH_DIRS=`echo ${LIB_PATH} | tr ':' ' ' | sed -e 's/\([^ ][^ ]*\)/SEARCH_DIR(\1);/g'` =================================================================== RCS file: /home/cvs/gnu/binutils/ld/ldfile.c,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 ldfile.c *** 1.1.1.3 1995/04/15 00:06:18 --- ldfile.c 1995/05/03 00:46:00 *************** *** 68,74 **** static search_arch_type *search_arch_head; static search_arch_type **search_arch_tail_ptr = &search_arch_head; ! static boolean try_open_bfd PARAMS ((const char *attempt, lang_input_statement_type *entry)); static FILE *try_open PARAMS ((const char *name, const char *exten)); --- 68,74 ---- static search_arch_type *search_arch_head; static search_arch_type **search_arch_tail_ptr = &search_arch_head; ! boolean try_open_bfd PARAMS ((const char *attempt, lang_input_statement_type *entry)); static FILE *try_open PARAMS ((const char *name, const char *exten)); *************** *** 89,95 **** /* Try to open a BFD for a lang_input_statement. */ ! static boolean try_open_bfd (attempt, entry) const char *attempt; lang_input_statement_type *entry; --- 89,95 ---- /* Try to open a BFD for a lang_input_statement. */ ! boolean try_open_bfd (attempt, entry) const char *attempt; lang_input_statement_type *entry; *************** *** 183,189 **** arch != (search_arch_type *) NULL; arch = arch->next) { ! if (config.dynamic_link) { if (ldemul_open_dynamic_archive (arch->name, entry)) return; --- 183,189 ---- arch != (search_arch_type *) NULL; arch = arch->next) { ! if (entry->dynamic_link) { if (ldemul_open_dynamic_archive (arch->name, entry)) return; =================================================================== RCS file: /home/cvs/gnu/binutils/ld/ldlang.h,v retrieving revision 1.1.1.2 diff -c -r1.1.1.2 ldlang.h *** 1.1.1.2 1995/02/22 02:02:31 --- ldlang.h 1995/05/03 00:46:01 *************** *** 229,234 **** --- 229,237 ---- asection *common_section; asection *common_output_section; boolean complained; + + /* This is used to overwrite the global one. */ + boolean dynamic_link; } lang_input_statement_type; typedef struct =================================================================== RCS file: /home/cvs/gnu/binutils/ld/lexsup.c,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 lexsup.c *** 1.1.1.3 1995/03/24 02:20:43 --- lexsup.c 1995/05/03 03:43:14 *************** *** 53,58 **** --- 53,60 ---- { int ingroup = 0; + boolean last_is_dynamic_link = config.dynamic_link; + /* Starting the short option string with '-' is for programs that expect options and other ARGV-elements in any order and that care about the ordering of the two. We describe each non-option ARGV-element *************** *** 193,201 **** --- 195,205 ---- break; case OPTION_CALL_SHARED: config.dynamic_link = true; + last_is_dynamic_link = true; break; case OPTION_NON_SHARED: config.dynamic_link = false; + last_is_dynamic_link = false; break; case 'd': command_line.force_common_definition = true; *************** *** 246,252 **** break; case 'l': lang_add_input_file (optarg, lang_input_file_is_l_enum, ! (char *) NULL); break; case 'M': config.map_filename = "-"; --- 250,257 ---- break; case 'l': lang_add_input_file (optarg, lang_input_file_is_l_enum, ! (char *) NULL)->dynamic_link ! = last_is_dynamic_link; break; case 'M': config.map_filename = "-"; =================================================================== RCS file: /home/cvs/gnu/binutils/ld/config/i386-linux.mt,v retrieving revision 1.1.1.2 diff -c -r1.1.1.2 i386-linux.mt *** 1.1.1.2 1995/04/01 00:53:35 --- i386-linux.mt 1995/05/03 02:50:16 *************** *** 1,2 **** --- 1,3 ---- EMUL=elf_i386 EMUL_EXTRA1=i386linux + NO_DEFAULT_WRITABLE_TEXT_SEGMENT=y =================================================================== RCS file: /home/cvs/gnu/binutils/ld/emultempl/elf32.em,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 elf32.em *** 1.1.1.3 1995/03/04 19:23:54 --- elf32.em 1995/05/03 00:46:03 *************** *** 43,48 **** --- 43,55 ---- #include "ldlang.h" #include "ldgram.h" + + /* FIXME: On some hosts we will need to include a different file. + This is correct for ELF/SVR4, which is the only place this file will + typically be compiled. However, if somebody configures the linker + for all targets, they will run into trouble here. */ + #include + static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static boolean gld${EMULATION_NAME}_open_dynamic_archive PARAMS ((const char *, lang_input_statement_type *)); *************** *** 55,60 **** --- 62,71 ---- static void gld${EMULATION_NAME}_place_section PARAMS ((lang_statement_union_type *)); static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); + static boolean gld${EMULATION_NAME}_find_so PARAMS ((lang_input_statement_type *entry)); + + extern boolean try_open_bfd PARAMS ((const char *attempt, + lang_input_statement_type *entry)); static void gld${EMULATION_NAME}_before_parse() *************** *** 63,68 **** --- 74,200 ---- config.dynamic_link = ${DYNAMIC_LINK-true}; } + /* figure out which library is greater */ + static int libcmp(p1, p2) + char *p1, *p2; + { + while (*p1) + { + if (isdigit(*p1) && isdigit(*p2)) + { + /* must compare this numerically */ + int v1, v2; + v1 = strtoul(p1, &p1, 10); + v2 = strtoul(p2, &p2, 10); + if (v1 != v2) + return v1 - v2; + } + else if (*p1 != *p2) + return *p1 - *p2; + else + p1++, p2++; + } + + return *p1 - *p2; + } + + /* Search for and open the .so file specified by ENTRY until + a match .so or .a file is found. H.J. */ + static boolean + gld${EMULATION_NAME}_find_so (entry) + lang_input_statement_type *entry; + { + search_dirs_type *search; + char *filename; + unsigned int len; + char *found; + boolean found_static; + + found_static = false; + found = NULL; + filename = (char *) entry->filename; + len = strlen (filename); + for (search = search_head; + search != (search_dirs_type *)NULL; + search = search->next) + { + DIR *dir; + struct dirent *ent; + + /* We try this directory. */ + dir = opendir (search->name); + if (dir == NULL) + continue; + + while ((ent = readdir (dir)) != NULL) + { + /* We are looking for libxxxx.*. */ + if (ent->d_name [len + 3] != '.' + || strncmp (ent->d_name, "lib", 3) != 0 + || strncmp (ent->d_name + 3, filename, len) != 0) + continue; + + if (strncmp (ent->d_name + 3 + len, ".a", 2) == 0) + { + found_static = true; + continue; + } + + if (strncmp (ent->d_name + 3 + len, ".so", 3) != 0) + continue; + + /* We've found a lib*.so.x.x.x file. We compare it with the + one we have found if there is one. */ + if (found == NULL) + { + found = (char *) xmalloc (strlen (ent->d_name) + 1); + strcpy (found, ent->d_name); + } + else + { + if (libcmp (&ent->d_name [len + 6], &found [len + 6]) > 0) + { + free (found); + found = (char *) xmalloc (strlen (ent->d_name) + 1); + strcpy (found, ent->d_name); + } + } + } + + closedir (dir); + + /* We find a shared or static library. */ + if (found != NULL || found_static == true) + break; + } + + if (found == NULL) + { + /* We did not find a matching .so file. This isn't an error, + since there might still be a matching .a file, which will be + found by the usual search. */ + return false; + } + + filename = (char *) xmalloc (strlen (search->name) + + strlen (found) + 2); + sprintf (filename, "%s/%s", search->name, found); + + free (found); + + /* Give it a try */ + if (try_open_bfd (filename, entry)) + { + entry->filename = filename; + return true; + } + else + { + free (filename); + return false; + } + } + /* Try to open a dynamic archive. This is where we know that ELF dynamic libraries have an extension of .so. */ *************** *** 71,81 **** const char *arch; lang_input_statement_type *entry; { ! const char *filename; ! ! filename = entry->filename; ! ! if (! ldfile_open_file_search (arch, entry, "lib", ".so")) return false; /* We have found a dynamic object to include in the link. The ELF --- 203,209 ---- const char *arch; lang_input_statement_type *entry; { ! if (gld${EMULATION_NAME}_find_so (entry) == false) return false; /* We have found a dynamic object to include in the link. The ELF *************** *** 95,106 **** && (entry->the_bfd->flags & DYNAMIC) != 0) { char *needed_name; ASSERT (entry->is_archive && entry->search_dirs_flag); ! needed_name = (char *) xmalloc (strlen (filename) ! + strlen (arch) ! + sizeof "lib.so"); ! sprintf (needed_name, "lib%s%s.so", filename, arch); bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); } --- 223,236 ---- && (entry->the_bfd->flags & DYNAMIC) != 0) { char *needed_name; + char *shlib; ASSERT (entry->is_archive && entry->search_dirs_flag); ! ! /* We may have /xxxxx/libxxxx.so.x.x.x. We only want the ! * libxxx.so.x.x.x part. */ ! shlib = strrchr (entry->filename, '/'); ! needed_name = strdup (shlib ? shlib + 1 : entry->filename); bfd_elf_set_dt_needed_name (entry->the_bfd, needed_name); } =================================================================== RCS file: /home/cvs/gnu/binutils/ld/scripttempl/elf.sc,v retrieving revision 1.1.1.3 diff -c -r1.1.1.3 elf.sc *** 1.1.1.3 1995/03/04 19:23:56 --- elf.sc 1995/05/03 02:50:17 *************** *** 26,31 **** --- 26,36 ---- test "$LD_FLAG" = "N" && DATA_ADDR=. INTERP=".interp ${RELOCATING-0} : { *(.interp) }" PLT=".plt ${RELOCATING-0} : { *(.plt) }" + if [ x"${NO_DEFAULT_WRITABLE_TEXT_SEGMENT}" = "xy" -o x"${NO_DEFAULT_WRITABLE_TEXT_SEGMENT}" = "xY" ]; then + DATA_ALIGN="${DATA_ADDR-ALIGN(${MAXPAGESIZE}) + ((ALIGN(8) + ${MAXPAGESIZE} - ALIGN(${MAXPAGESIZE})) & (${MAXPAGESIZE} - 1))}" + else + DATA_ALIGN="${DATA_ADDR- ALIGN(8) + ${MAXPAGESIZE}}" + fi cat <