diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 23 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 78 | ||||
-rw-r--r-- | ld/ld.texinfo | 12 | ||||
-rw-r--r-- | ld/ldlang.c | 1 | ||||
-rw-r--r-- | ld/ldlang.h | 4 | ||||
-rw-r--r-- | ld/ldmain.c | 4 | ||||
-rw-r--r-- | ld/ldmain.h | 1 | ||||
-rw-r--r-- | ld/lexsup.c | 14 |
8 files changed, 121 insertions, 16 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index a1b679c1d5..e029451e86 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,26 @@ +2004-07-19 H.J. Lu <hongjiu.lu@intel.com> + + * emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): Also + check the add_needed field. + (dt_needed): New struct. + (gld${EMULATION_NAME}_try_needed): Change the first argument + to a pointer to struct dt_needed. Check the DYN_NO_ADD_NEEDED + bit in the file where the DT_NEEDED entry comes from. + (gld${EMULATION_NAME}_search_needed): Change the second + argument to a pointer to struct dt_needed. + (gld${EMULATION_NAME}_check_ld_so_conf): Updated. + (gld${EMULATION_NAME}_after_open): Likewise. + + * ld.texinfo: Add --add-needed document. + * ldlang.c (new_afile): Set p->add_needed. + * ldlang.h (lang_input_statement_type): Add add_needed field. + * ldmain.h (add_needed): Declare. + * ldmain.c (add_needed): New global var. + * lexsup.c (option_values): Add OPTION_ADD_NEEDED and + OPTION_NO_ADD_NEEDED. + (ld_options): Likewise. + (parse_args): Handle them. + 2004-07-13 Christof Petig <christof@petig-baender.de> * emultempl/pe.em (make_import_fixup): Use bfd_get_32 to correct diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 8dbd60a573..469f0540f4 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -96,14 +96,25 @@ cat >>e${EMULATION_NAME}.c <<EOF static bfd_boolean gld${EMULATION_NAME}_load_symbols (lang_input_statement_type *entry) { - if (!entry->as_needed - || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0) - return FALSE; + int class = 0; /* Tell the ELF linker that we don't want the output file to have a DT_NEEDED entry for this file, unless it is used to resolve references in a regular object. */ - bfd_elf_set_dyn_lib_class (entry->the_bfd, DYN_AS_NEEDED); + if (entry->as_needed) + class = DYN_AS_NEEDED; + + /* Tell the ELF linker that we don't want the output file to have a + DT_NEEDED entry for any dynamic library in DT_NEEDED tags from + this file at all. */ + if (!entry->add_needed) + class |= DYN_NO_ADD_NEEDED; + + if (!class + || (bfd_get_file_flags (entry->the_bfd) & DYNAMIC) == 0) + return FALSE; + + bfd_elf_set_dyn_lib_class (entry->the_bfd, class); /* Continue on with normal load_symbols processing. */ return FALSE; @@ -242,16 +253,24 @@ gld${EMULATION_NAME}_stat_needed (lang_input_statement_type *s) global_needed->name, global_needed->by, soname); } +struct dt_needed +{ + bfd *by; + const char *name; +}; /* This function is called for each possible name for a dynamic object named by a DT_NEEDED entry. The FORCE parameter indicates whether to skip the check for a conflicting version. */ static bfd_boolean -gld${EMULATION_NAME}_try_needed (const char *name, int force) +gld${EMULATION_NAME}_try_needed (struct dt_needed *needed, + int force) { bfd *abfd; + const char *name = needed->name; const char *soname; + int class; abfd = bfd_openr (name, bfd_get_target (output_bfd)); if (abfd == NULL) @@ -364,7 +383,17 @@ cat >>e${EMULATION_NAME}.c <<EOF /* Tell the ELF linker that we don't want the output file to have a DT_NEEDED entry for this file, unless it is used to resolve references in a regular object. */ - bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED); + class = DYN_DT_NEEDED; + + /* Tell the ELF linker that we don't want the output file to have a + DT_NEEDED entry for this file at all if the entry is from a file + with DYN_NO_ADD_NEEDED. */ + if (needed->by + && (bfd_elf_get_dyn_lib_class (needed->by) + & DYN_NO_ADD_NEEDED) != 0) + class |= DYN_NO_NEEDED | DYN_NO_ADD_NEEDED; + + bfd_elf_set_dyn_lib_class (abfd, class); /* Add this file into the symbol table. */ if (! bfd_link_add_symbols (abfd, &link_info)) @@ -377,16 +406,23 @@ cat >>e${EMULATION_NAME}.c <<EOF /* Search for a needed file in a path. */ static bfd_boolean -gld${EMULATION_NAME}_search_needed (const char *path, const char *name, int force) +gld${EMULATION_NAME}_search_needed (const char *path, + struct dt_needed *n, int force) { const char *s; + const char *name = n->name; size_t len; + struct dt_needed needed; if (name[0] == '/') - return gld${EMULATION_NAME}_try_needed (name, force); + return gld${EMULATION_NAME}_try_needed (n, force); if (path == NULL || *path == '\0') return FALSE; + + needed.by = n->by; + needed.name = n->name; + len = strlen (name); while (1) { @@ -407,7 +443,8 @@ gld${EMULATION_NAME}_search_needed (const char *path, const char *name, int forc } strcpy (sset, name); - if (gld${EMULATION_NAME}_try_needed (filename, force)) + needed.name = filename; + if (gld${EMULATION_NAME}_try_needed (&needed, force)) return TRUE; free (filename); @@ -474,6 +511,7 @@ gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force) { static bfd_boolean initialized; static char *ld_so_conf; + struct dt_needed needed; if (! initialized) { @@ -548,7 +586,10 @@ gld${EMULATION_NAME}_check_ld_so_conf (const char *name, int force) if (ld_so_conf == NULL) return FALSE; - return gld${EMULATION_NAME}_search_needed (ld_so_conf, name, force); + + needed.by = NULL; + needed.name = name; + return gld${EMULATION_NAME}_search_needed (ld_so_conf, &needed, force); } EOF @@ -631,6 +672,7 @@ gld${EMULATION_NAME}_after_open (void) for (l = needed; l != NULL; l = l->next) { struct bfd_link_needed_list *ll; + struct dt_needed n, nn; int force; /* If we've already seen this file, skip it. */ @@ -647,6 +689,9 @@ gld${EMULATION_NAME}_after_open (void) if (global_found) continue; + n.by = l->by; + n.name = l->name; + nn.by = l->by; if (trace_file_tries) info_msg (_("%s needed by %B\n"), l->name, l->by); @@ -676,13 +721,13 @@ fi cat >>e${EMULATION_NAME}.c <<EOF if (gld${EMULATION_NAME}_search_needed (command_line.rpath_link, - l->name, force)) + &n, force)) break; EOF if [ "x${USE_LIBPATH}" = xyes ] ; then cat >>e${EMULATION_NAME}.c <<EOF if (gld${EMULATION_NAME}_search_needed (command_line.rpath, - l->name, force)) + &n, force)) break; EOF fi @@ -692,12 +737,12 @@ cat >>e${EMULATION_NAME}.c <<EOF && command_line.rpath == NULL) { lib_path = (const char *) getenv ("LD_RUN_PATH"); - if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, + if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force)) break; } lib_path = (const char *) getenv ("LD_LIBRARY_PATH"); - if (gld${EMULATION_NAME}_search_needed (lib_path, l->name, force)) + if (gld${EMULATION_NAME}_search_needed (lib_path, &n, force)) break; EOF fi @@ -710,7 +755,7 @@ cat >>e${EMULATION_NAME}.c <<EOF char *tmpname = gld${EMULATION_NAME}_add_sysroot (rp->name); found = (rp->by == l->by && gld${EMULATION_NAME}_search_needed (tmpname, - l->name, + &n, force)); free (tmpname); } @@ -729,7 +774,8 @@ cat >>e${EMULATION_NAME}.c <<EOF continue; filename = (char *) xmalloc (strlen (search->name) + len + 2); sprintf (filename, "%s/%s", search->name, l->name); - if (gld${EMULATION_NAME}_try_needed (filename, force)) + nn.name = filename; + if (gld${EMULATION_NAME}_try_needed (&nn, force)) break; free (filename); } diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 2b77260b60..8af0223874 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -984,6 +984,18 @@ needed. @option{--as-needed} causes DT_NEEDED tags to only be emitted for libraries that satisfy some reference from regular objects. @option{--no-as-needed} restores the default behaviour. +@kindex --add-needed +@kindex --no-add-needed +@item --add-needed +@itemx --no-add-needed +This option affects the treatment of dynamic libraries from ELF +DT_NEEDED tags in dynamic libraries mentioned on the command line after +the @option{--no-add-needed} option. Normally, the linker will add +a DT_NEEDED tag for each dynamic library from DT_NEEDED tags. +@option{--no-add-needed} causes DT_NEEDED tags will never be emitted +for those libraries from DT_NEEDED tags. @option{--add-needed} restores +the default behaviour. + @kindex -assert @var{keyword} @item -assert @var{keyword} This option is ignored for SunOS compatibility. diff --git a/ld/ldlang.c b/ld/ldlang.c index 8daf9c5337..c5cfd5c45a 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -454,6 +454,7 @@ new_afile (const char *name, p->next = NULL; p->symbol_count = 0; p->dynamic = config.dynamic_link; + p->add_needed = add_needed; p->as_needed = as_needed; p->whole_archive = whole_archive; p->loaded = FALSE; diff --git a/ld/ldlang.h b/ld/ldlang.h index 0b56c276c3..f7e2fa619e 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -266,6 +266,10 @@ typedef struct lang_input_statement_struct /* Whether to search for this entry as a dynamic archive. */ bfd_boolean dynamic; + /* Whether DT_NEEDED tags should be added for dynamic libraries in + DT_NEEDED tags from this entry. */ + bfd_boolean add_needed; + /* Whether this entry should cause a DT_NEEDED tag only when satisfying references from regular files, or always. */ bfd_boolean as_needed; diff --git a/ld/ldmain.c b/ld/ldmain.c index f1804c438a..193fd69b09 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -97,6 +97,10 @@ bfd_boolean whole_archive; actually satisfies some reference in a regular object. */ bfd_boolean as_needed; +/* Nonzero means never create DT_NEEDED entries for dynamic libraries + in DT_NEEDED tags. */ +bfd_boolean add_needed = TRUE; + /* TRUE if we should demangle symbol names. */ bfd_boolean demangling; diff --git a/ld/ldmain.h b/ld/ldmain.h index 8cab5fe1f2..976810ebd1 100644 --- a/ld/ldmain.h +++ b/ld/ldmain.h @@ -33,6 +33,7 @@ extern bfd_boolean trace_file_tries; extern bfd_boolean version_printed; extern bfd_boolean whole_archive; extern bfd_boolean as_needed; +extern bfd_boolean add_needed; extern bfd_boolean demangling; extern int g_switch_value; extern const char *output_filename; diff --git a/ld/lexsup.c b/ld/lexsup.c index 55ab5ee0da..9a599a3d5c 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -112,6 +112,8 @@ enum option_values OPTION_SPLIT_BY_RELOC, OPTION_SPLIT_BY_FILE , OPTION_WHOLE_ARCHIVE, + OPTION_ADD_NEEDED, + OPTION_NO_ADD_NEEDED, OPTION_AS_NEEDED, OPTION_NO_AS_NEEDED, OPTION_WRAP, @@ -482,6 +484,12 @@ static const struct ld_option ld_options[] = { {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE}, '\0', NULL, N_("Include all objects from following archives"), TWO_DASHES }, + { {"add-needed", no_argument, NULL, OPTION_ADD_NEEDED}, + '\0', NULL, N_("Set DT_NEEDED tags for DT_NEEDED entries in\n" + "\t\t\t\tfollowing dynamic libs"), TWO_DASHES }, + { {"no-add-needed", no_argument, NULL, OPTION_NO_ADD_NEEDED}, + '\0', NULL, N_("Do not set DT_NEEDED tags for DT_NEEDED entries\n" + "\t\t\t\tin following dynamic libs"), TWO_DASHES }, { {"as-needed", no_argument, NULL, OPTION_AS_NEEDED}, '\0', NULL, N_("Only set DT_NEEDED for following dynamic libs if used"), TWO_DASHES }, @@ -1196,6 +1204,12 @@ parse_args (unsigned argc, char **argv) case OPTION_WHOLE_ARCHIVE: whole_archive = TRUE; break; + case OPTION_ADD_NEEDED: + add_needed = TRUE; + break; + case OPTION_NO_ADD_NEEDED: + add_needed = FALSE; + break; case OPTION_AS_NEEDED: as_needed = TRUE; break; |