diff options
author | Alan Modra <amodra@gmail.com> | 2004-03-18 12:50:20 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2004-03-18 12:50:20 +0000 |
commit | 4a43e768f18f325a0e52de37fe69d4a6a764d668 (patch) | |
tree | 5fed3b135f3382db0391e56136eefc09e32929a0 | |
parent | 3e4caed2b120cd3930d19c96fc5761f9254946c5 (diff) | |
download | gdb-4a43e768f18f325a0e52de37fe69d4a6a764d668.zip gdb-4a43e768f18f325a0e52de37fe69d4a6a764d668.tar.gz gdb-4a43e768f18f325a0e52de37fe69d4a6a764d668.tar.bz2 |
bfd/
* elf-bfd.h (struct elf_obj_tdata): Delete dt_soname field. Add
dyn_lib_class field. Rearrange for better packing.
(elf_dt_soname): Delete.
(elf_dyn_lib_class): Define.
* elf.c (bfd_elf_set_dt_needed_name): Update comment.
(bfd_elf_set_dt_needed_soname): Delete.
(bfd_elf_set_dyn_lib_class): New function.
* elflink.h (add_dt_needed_tag): New function. Split out from..
(elf_link_add_object_symbols): ..here. Rename "name" to "soname".
Use elf_dyn_lib_class to set dt_needed and add_needed. Move fallback
initialization of soname.
(elf_link_check_versioned_symbol): Test elf_dyn_lib_class instead of
elf_dt_soname.
* bfd-in.h (enum dynamic_lib_link_class): New.
(bfd_elf_set_dt_needed_soname): Delete.
(bfd_elf_set_dyn_lib_class): Declare.
* bfd-in2.h: Regenerate.
ld/
* ld.texinfo: Add --as-needed doco.
* ldmain.c (as_needed): New global var.
* ldmain.h (as_needed): Declare.
* lexsup.c (option_values): Add OPTION_AS_NEEDED and
OPTION_NO_AS_NEEDED.
(ld_options): Likewise.
(parse_args): Handle them.
* ldlang.h (lang_input_statement_type): Add as_needed field.
* ldlang.c (new_afile): Set p->as_needed.
* emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): New function.
(gld${EMULATION_NAME}_try_needed): Use bfd_elf_set_dyn_lib_class.
(ld_${EMULATION_NAME}_emulation): Set LDEMUL_RECOGNIZED_FILE entry.
* ldlang.c (open_input_bfds): Remove useless cast.
(lang_do_assignments_1): Likewise.
(lang_for_each_input_section): Delete.
-rw-r--r-- | bfd/ChangeLog | 18 | ||||
-rw-r--r-- | bfd/bfd-in.h | 10 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 10 | ||||
-rw-r--r-- | bfd/elf-bfd.h | 49 | ||||
-rw-r--r-- | bfd/elf.c | 7 | ||||
-rw-r--r-- | bfd/elflink.h | 207 | ||||
-rw-r--r-- | ld/ChangeLog | 19 | ||||
-rw-r--r-- | ld/emultempl/elf32.em | 37 | ||||
-rw-r--r-- | ld/ld.texinfo | 12 | ||||
-rw-r--r-- | ld/ldlang.c | 24 | ||||
-rw-r--r-- | ld/ldlang.h | 4 | ||||
-rw-r--r-- | ld/ldmain.c | 6 | ||||
-rw-r--r-- | ld/ldmain.h | 3 | ||||
-rw-r--r-- | ld/lexsup.c | 14 |
14 files changed, 250 insertions, 170 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 2d41bb8..eb91f6e 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,23 @@ 2004-03-18 Alan Modra <amodra@bigpond.net.au> + * elf-bfd.h (struct elf_obj_tdata): Delete dt_soname field. Add + dyn_lib_class field. Rearrange for better packing. + (elf_dt_soname): Delete. + (elf_dyn_lib_class): Define. + * elf.c (bfd_elf_set_dt_needed_name): Update comment. + (bfd_elf_set_dt_needed_soname): Delete. + (bfd_elf_set_dyn_lib_class): New function. + * elflink.h (add_dt_needed_tag): New function. Split out from.. + (elf_link_add_object_symbols): ..here. Rename "name" to "soname". + Use elf_dyn_lib_class to set dt_needed and add_needed. Move fallback + initialization of soname. + (elf_link_check_versioned_symbol): Test elf_dyn_lib_class instead of + elf_dt_soname. + * bfd-in.h (enum dynamic_lib_link_class): New. + (bfd_elf_set_dt_needed_soname): Delete. + (bfd_elf_set_dyn_lib_class): Declare. + * bfd-in2.h: Regenerate. + * elflink.c (_bfd_elf_merge_symbol): Rewrite weak symbol handling. (_bfd_elf_add_default_symbol): Remove indirect BFD_ASSERTs. * elflink.h (elf_link_add_object_symbols): Don't clear dt_needed in diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 37df5f2..fedcb37 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -599,6 +599,12 @@ struct bfd_link_needed_list const char *name; }; +enum dynamic_lib_link_class { + DYN_NORMAL = 0, + DYN_AS_NEEDED = 1, + DYN_DT_NEEDED = 2 +}; + extern bfd_boolean bfd_elf_record_link_assignment (bfd *, struct bfd_link_info *, const char *, bfd_boolean); extern struct bfd_link_needed_list *bfd_elf_get_needed_list @@ -613,10 +619,10 @@ extern bfd_boolean bfd_elf64_size_dynamic_sections struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *); extern void bfd_elf_set_dt_needed_name (bfd *, const char *); -extern void bfd_elf_set_dt_needed_soname - (bfd *, const char *); extern const char *bfd_elf_get_dt_soname (bfd *); +extern void bfd_elf_set_dyn_lib_class + (bfd *, int); extern struct bfd_link_needed_list *bfd_elf_get_runpath_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf32_discard_info diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index c723731..5e53956 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -606,6 +606,12 @@ struct bfd_link_needed_list const char *name; }; +enum dynamic_lib_link_class { + DYN_NORMAL = 0, + DYN_AS_NEEDED = 1, + DYN_DT_NEEDED = 2 +}; + extern bfd_boolean bfd_elf_record_link_assignment (bfd *, struct bfd_link_info *, const char *, bfd_boolean); extern struct bfd_link_needed_list *bfd_elf_get_needed_list @@ -620,10 +626,10 @@ extern bfd_boolean bfd_elf64_size_dynamic_sections struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *); extern void bfd_elf_set_dt_needed_name (bfd *, const char *); -extern void bfd_elf_set_dt_needed_soname - (bfd *, const char *); extern const char *bfd_elf_get_dt_soname (bfd *); +extern void bfd_elf_set_dyn_lib_class + (bfd *, int); extern struct bfd_link_needed_list *bfd_elf_get_runpath_list (bfd *, struct bfd_link_info *); extern bfd_boolean bfd_elf32_discard_info diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 5f4bcd8..a90024f 100644 --- a/bfd/elf-bfd.h +++ b/bfd/elf-bfd.h @@ -1,6 +1,6 @@ /* BFD back-end data structures for ELF files. Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003 Free Software Foundation, Inc. + 2002, 2003, 2004 Free Software Foundation, Inc. Written by Cygnus Support. This file is part of BFD, the Binary File Descriptor library. @@ -1132,9 +1132,6 @@ struct elf_obj_tdata bfd_vma gp; /* The gp value */ unsigned int gp_size; /* The gp size */ - Elf_Internal_Shdr **group_sect_ptr; - int num_group; - /* Information grabbed from an elf core file. */ int core_signal; int core_pid; @@ -1142,10 +1139,6 @@ struct elf_obj_tdata char* core_program; char* core_command; - /* This is set to TRUE if the object was created by the backend - linker. */ - bfd_boolean linker; - /* A mapping from external symbols to entries in the linker hash table, used when linking. This is indexed by the symbol index minus the sh_info field of the symbol table header. */ @@ -1171,21 +1164,6 @@ struct elf_obj_tdata one. */ const char *dt_name; - /* When a reference in a regular object is resolved by a shared - object is loaded into via the DT_NEEDED entries by the linker - ELF emulation code, we need to add the shared object to the - DT_NEEDED list of the resulting binary to indicate the dependency - as if the -l option is passed to the linker. This field holds the - name of the loaded shared object. */ - const char *dt_soname; - - /* Irix 5 often screws up the symbol table, sorting local symbols - after global symbols. This flag is set if the symbol table in - this BFD appears to be screwed up. If it is, we ignore the - sh_info field in the symbol table header, and always read all the - symbols. */ - bfd_boolean bad_symtab; - /* Records the result of `get_program_header_size'. */ bfd_size_type program_header_size; @@ -1213,8 +1191,8 @@ struct elf_obj_tdata created. */ asection *eh_frame_hdr; - /* Used to determine if the e_flags field has been initialized */ - bfd_boolean flags_init; + Elf_Internal_Shdr **group_sect_ptr; + int num_group; /* Number of symbol version definitions we are about to emit. */ unsigned int cverdefs; @@ -1237,6 +1215,25 @@ struct elf_obj_tdata asymbol *elf_text_symbol; asection *elf_data_section; asection *elf_text_section; + + /* Whether a dyanmic object was specified normally on the linker + command line, or was specified when --as-needed was in effect, + or was found via a DT_NEEDED entry. */ + enum dynamic_lib_link_class dyn_lib_class; + + /* This is set to TRUE if the object was created by the backend + linker. */ + bfd_boolean linker; + + /* Irix 5 often screws up the symbol table, sorting local symbols + after global symbols. This flag is set if the symbol table in + this BFD appears to be screwed up. If it is, we ignore the + sh_info field in the symbol table header, and always read all the + symbols. */ + bfd_boolean bad_symtab; + + /* Used to determine if the e_flags field has been initialized */ + bfd_boolean flags_init; }; #define elf_tdata(bfd) ((bfd) -> tdata.elf_obj_data) @@ -1263,7 +1260,7 @@ struct elf_obj_tdata #define elf_local_got_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets) #define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents) #define elf_dt_name(bfd) (elf_tdata(bfd) -> dt_name) -#define elf_dt_soname(bfd) (elf_tdata(bfd) -> dt_soname) +#define elf_dyn_lib_class(bfd) (elf_tdata(bfd) -> dyn_lib_class) #define elf_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab) #define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init) @@ -1479,8 +1479,7 @@ _bfd_elf_link_hash_table_create (bfd *abfd) /* This is a hook for the ELF emulation code in the generic linker to tell the backend linker what file name to use for the DT_NEEDED - entry for a dynamic object. The generic linker passes name as an - empty string to indicate that no DT_NEEDED entry should be made. */ + entry for a dynamic object. */ void bfd_elf_set_dt_needed_name (bfd *abfd, const char *name) @@ -1491,11 +1490,11 @@ bfd_elf_set_dt_needed_name (bfd *abfd, const char *name) } void -bfd_elf_set_dt_needed_soname (bfd *abfd, const char *name) +bfd_elf_set_dyn_lib_class (bfd *abfd, int lib_class) { if (bfd_get_flavour (abfd) == bfd_target_elf_flavour && bfd_get_format (abfd) == bfd_object) - elf_dt_soname (abfd) = name; + elf_dyn_lib_class (abfd) = lib_class; } /* Get the list of DT_NEEDED entries for a link. This is a hook for diff --git a/bfd/elflink.h b/bfd/elflink.h index ec20e75..82a2b3b 100644 --- a/bfd/elflink.h +++ b/bfd/elflink.h @@ -68,6 +68,59 @@ sort_symbol (const void *arg1, const void *arg2) } } +/* Add a DT_NEEDED entry for this dynamic object. Returns -1 on error, + 1 if a DT_NEEDED tag already exists, and 0 on success. */ + +static int +add_dt_needed_tag (struct bfd_link_info *info, const char *soname, + bfd_boolean do_it) +{ + struct elf_link_hash_table *hash_table; + bfd_size_type oldsize; + bfd_size_type strindex; + + hash_table = elf_hash_table (info); + oldsize = _bfd_elf_strtab_size (hash_table->dynstr); + strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, FALSE); + if (strindex == (bfd_size_type) -1) + return -1; + + if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) + { + asection *sdyn; + Elf_External_Dyn *dyncon, *dynconend; + + sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); + BFD_ASSERT (sdyn != NULL); + + dyncon = (Elf_External_Dyn *) sdyn->contents; + dynconend = (Elf_External_Dyn *) (sdyn->contents + sdyn->_raw_size); + for (; dyncon < dynconend; dyncon++) + { + Elf_Internal_Dyn dyn; + + elf_swap_dyn_in (hash_table->dynobj, dyncon, & dyn); + if (dyn.d_tag == DT_NEEDED + && dyn.d_un.d_val == strindex) + { + _bfd_elf_strtab_delref (hash_table->dynstr, strindex); + return 1; + } + } + } + + if (do_it) + { + if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex)) + return -1; + } + else + /* We were just checking for existence of the tag. */ + _bfd_elf_strtab_delref (hash_table->dynstr, strindex); + + return 0; +} + /* Add symbols from an ELF object file to the linker hash table. */ static bfd_boolean @@ -202,7 +255,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) } dt_needed = FALSE; - add_needed = FALSE; + add_needed = TRUE; if (! dynamic) { /* If we are creating a shared library, create all the dynamic @@ -224,10 +277,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) else { asection *s; - const char *name; - bfd_size_type oldsize; - bfd_size_type strindex; + const char *soname = NULL; struct bfd_link_needed_list *rpath = NULL, *runpath = NULL; + int ret; /* ld --just-symbols and dynamic objects don't mix very well. Test for --just-symbols by looking at info set up by @@ -236,26 +288,22 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS) goto error_return; - /* Find the name to use in a DT_NEEDED entry that refers to this - object. If the object has a DT_SONAME entry, we use it. - Otherwise, if the generic linker stuck something in - elf_dt_name, we use that. Otherwise, we just use the file - name. If the generic linker put a null string into - elf_dt_name, we don't make a DT_NEEDED entry at all, even if - there is a DT_SONAME entry. */ - add_needed = TRUE; - name = bfd_get_filename (abfd); - if (elf_dt_name (abfd) != NULL) + /* If this dynamic lib was specified on the command line with + --as-needed in effect, then we don't want to add a DT_NEEDED + tag unless the lib is actually used. + For libs brought in by another lib's DT_NEEDED we do the same, + and also modify handling of weak syms. */ + switch elf_dyn_lib_class (abfd) { - name = elf_dt_name (abfd); - if (*name == '\0') - { - if (elf_dt_soname (abfd) != NULL) - dt_needed = TRUE; - - add_needed = FALSE; - } + case DYN_NORMAL: + break; + case DYN_DT_NEEDED: + dt_needed = TRUE; + /* Fall thru */ + case DYN_AS_NEEDED: + add_needed = FALSE; } + s = bfd_get_section_by_name (abfd, ".dynamic"); if (s != NULL) { @@ -287,8 +335,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (dyn.d_tag == DT_SONAME) { unsigned int tagv = dyn.d_un.d_val; - name = bfd_elf_string_from_elf_section (abfd, shlink, tagv); - if (name == NULL) + soname = bfd_elf_string_from_elf_section (abfd, shlink, tagv); + if (soname == NULL) goto error_free_dyn; } if (dyn.d_tag == DT_NEEDED) @@ -405,53 +453,31 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) if (! _bfd_elf_link_create_dynamic_sections (abfd, info)) goto error_return; - if (add_needed) + /* Find the name to use in a DT_NEEDED entry that refers to this + object. If the object has a DT_SONAME entry, we use it. + Otherwise, if the generic linker stuck something in + elf_dt_name, we use that. Otherwise, we just use the file + name. */ + if (soname == NULL || *soname == '\0') { - /* Add a DT_NEEDED entry for this dynamic object. */ - oldsize = _bfd_elf_strtab_size (hash_table->dynstr); - strindex = _bfd_elf_strtab_add (hash_table->dynstr, name, FALSE); - if (strindex == (bfd_size_type) -1) - goto error_return; - - if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) - { - asection *sdyn; - Elf_External_Dyn *dyncon, *dynconend; - - /* The hash table size did not change, which means that - the dynamic object name was already entered. If we - have already included this dynamic object in the - link, just ignore it. There is no reason to include - a particular dynamic object more than once. */ - sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic"); - BFD_ASSERT (sdyn != NULL); - - dyncon = (Elf_External_Dyn *) sdyn->contents; - dynconend = (Elf_External_Dyn *) (sdyn->contents + - sdyn->_raw_size); - for (; dyncon < dynconend; dyncon++) - { - Elf_Internal_Dyn dyn; + soname = elf_dt_name (abfd); + if (soname == NULL || *soname == '\0') + soname = bfd_get_filename (abfd); + } - elf_swap_dyn_in (hash_table->dynobj, dyncon, & dyn); - if (dyn.d_tag == DT_NEEDED - && dyn.d_un.d_val == strindex) - { - _bfd_elf_strtab_delref (hash_table->dynstr, strindex); - return TRUE; - } - } - } + /* Save the SONAME because sometimes the linker emulation code + will need to know it. */ + elf_dt_name (abfd) = soname; - if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex)) - goto error_return; - } + ret = add_dt_needed_tag (info, soname, add_needed); + if (ret < 0) + goto error_return; - /* Save the SONAME, if there is one, because sometimes the - linker emulation code will need to know it. */ - if (*name == '\0') - name = basename (bfd_get_filename (abfd)); - elf_dt_name (abfd) = name; + /* If we have already included this dynamic object in the + link, just ignore it. There is no reason to include a + particular dynamic object more than once. */ + if (ret > 0) + return TRUE; } /* If this is a dynamic object, we always link against the .dynsym @@ -1051,49 +1077,21 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) break; } - if (dt_needed && !add_needed && definition + if (!add_needed && definition && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0) { - bfd_size_type oldsize; - bfd_size_type strindex; - - /* The symbol from a DT_NEEDED object is referenced from - the regular object to create a dynamic executable. We - have to make sure there is a DT_NEEDED entry for it. */ + int ret; + /* A symbol from a library loaded via DT_NEEDED of some + other library is referenced by a regular object. + Add a DT_NEEDED entry for it. */ add_needed = TRUE; - oldsize = _bfd_elf_strtab_size (hash_table->dynstr); - strindex = _bfd_elf_strtab_add (hash_table->dynstr, - elf_dt_soname (abfd), FALSE); - if (strindex == (bfd_size_type) -1) + ret = add_dt_needed_tag (info, elf_dt_name (abfd), add_needed); + if (ret < 0) goto error_free_vers; - if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) - { - asection *sdyn; - Elf_External_Dyn *dyncon, *dynconend; - - sdyn = bfd_get_section_by_name (hash_table->dynobj, - ".dynamic"); - BFD_ASSERT (sdyn != NULL); - - dyncon = (Elf_External_Dyn *) sdyn->contents; - dynconend = (Elf_External_Dyn *) (sdyn->contents + - sdyn->_raw_size); - for (; dyncon < dynconend; dyncon++) - { - Elf_Internal_Dyn dyn; - - elf_swap_dyn_in (hash_table->dynobj, - dyncon, &dyn); - BFD_ASSERT (dyn.d_tag != DT_NEEDED || - dyn.d_un.d_val != strindex); - } - } - - if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex)) - goto error_free_vers; + BFD_ASSERT (ret == 0); } } } @@ -3950,7 +3948,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info, case bfd_link_hash_undefined: case bfd_link_hash_undefweak: abfd = h->root.u.undef.abfd; - if ((abfd->flags & DYNAMIC) == 0 || elf_dt_soname (abfd) == NULL) + if ((abfd->flags & DYNAMIC) == 0 + || elf_dyn_lib_class (abfd) != DYN_DT_NEEDED) return FALSE; break; diff --git a/ld/ChangeLog b/ld/ChangeLog index 0b3407f..3c4940c 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,22 @@ +2004-03-18 Alan Modra <amodra@bigpond.net.au> + + * ld.texinfo: Add --as-needed doco. + * ldmain.c (as_needed): New global var. + * ldmain.h (as_needed): Declare. + * lexsup.c (option_values): Add OPTION_AS_NEEDED and + OPTION_NO_AS_NEEDED. + (ld_options): Likewise. + (parse_args): Handle them. + * ldlang.h (lang_input_statement_type): Add as_needed field. + * ldlang.c (new_afile): Set p->as_needed. + * emultempl/elf32.em (gld${EMULATION_NAME}_load_symbols): New function. + (gld${EMULATION_NAME}_try_needed): Use bfd_elf_set_dyn_lib_class. + (ld_${EMULATION_NAME}_emulation): Set LDEMUL_RECOGNIZED_FILE entry. + + * ldlang.c (open_input_bfds): Remove useless cast. + (lang_do_assignments_1): Likewise. + (lang_for_each_input_section): Delete. + 2004-03-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de> * configure.tgt: Switch sh-*-rtems* to ELF. Add sh-*-rtemscoff*. diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 45749e7..e95b3a9 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -89,6 +89,28 @@ gld${EMULATION_NAME}_before_parse (void) EOF fi +if test x"$LDEMUL_RECOGNIZED_FILE" != xgld"${EMULATION_NAME}"_load_symbols; then +cat >>e${EMULATION_NAME}.c <<EOF +/* Handle as_needed DT_NEEDED. */ + +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; + + /* 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); + + /* Continue on with normal load_symbols processing. */ + return FALSE; +} +EOF +fi + cat >>e${EMULATION_NAME}.c <<EOF /* These variables are required to pass information back and forth @@ -336,14 +358,13 @@ cat >>e${EMULATION_NAME}.c <<EOF return TRUE; } - /* Tell the ELF backend that we don't want the output file to have a - DT_NEEDED entry for this file. */ - bfd_elf_set_dt_needed_name (abfd, ""); + /* Specify the soname to use. */ + bfd_elf_set_dt_needed_name (abfd, soname); - /* Tell the ELF backend that the output file needs a DT_NEEDED - entry for this file if it is used to resolve the reference in - a regular object. */ - bfd_elf_set_dt_needed_soname (abfd, soname); + /* 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); /* Add this file into the symbol table. */ if (! bfd_link_add_symbols (abfd, &link_info)) @@ -1752,7 +1773,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation = gld${EMULATION_NAME}_handle_option, ${LDEMUL_UNRECOGNIZED_FILE-NULL}, ${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options}, - ${LDEMUL_RECOGNIZED_FILE-NULL}, + ${LDEMUL_RECOGNIZED_FILE-gld${EMULATION_NAME}_load_symbols}, ${LDEMUL_FIND_POTENTIAL_LIBRARIES-NULL}, ${LDEMUL_NEW_VERS_PATTERN-NULL} }; diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 9710f4f..4310c12 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -972,6 +972,18 @@ behaviour from release 2.14 onwards is to reject such input files, and so the @samp{--accept-unknown-input-arch} option has been added to restore the old behaviour. +@kindex --as-needed +@kindex --no-as-needed +@item --as-needed +@itemx --no-as-needed +This option affects ELF DT_NEEDED tags for dynamic libraries mentioned +on the command line after the @option{--as-needed} option. Normally, +the linker will add a DT_NEEDED tag for each dynamic library mentioned +on the command line, regardless of whether the library is actually +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 -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 3855998..0c08601 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -445,6 +445,7 @@ new_afile (const char *name, p->next = NULL; p->symbol_count = 0; p->dynamic = config.dynamic_link; + p->as_needed = as_needed; p->whole_archive = whole_archive; p->loaded = FALSE; lang_statement_append (&input_file_chain, @@ -1842,7 +1843,7 @@ open_input_bfds (lang_statement_union_type *s, bfd_boolean force) /* Maybe we should load the file's symbols. */ if (s->wild_statement.filename && ! wildcardp (s->wild_statement.filename)) - (void) lookup_name (s->wild_statement.filename); + lookup_name (s->wild_statement.filename); open_input_bfds (s->wild_statement.children.head, force); break; case lang_group_statement_enum: @@ -3348,8 +3349,7 @@ lang_do_assignments_1 if (os->bfd_section != NULL) { dot = os->bfd_section->vma; - (void) lang_do_assignments_1 (os->children.head, os, - os->fill, dot); + lang_do_assignments_1 (os->children.head, os, os->fill, dot); dot = (os->bfd_section->vma + TO_ADDR (os->bfd_section->_raw_size)); @@ -3938,24 +3938,6 @@ lang_for_each_file (void (*func) (lang_input_statement_type *)) } } -#if 0 - -/* Not used. */ - -void -lang_for_each_input_section (void (*func) (bfd *ab, asection *as)) -{ - LANG_FOR_EACH_INPUT_STATEMENT (f) - { - asection *s; - - for (s = f->the_bfd->sections; s != NULL; s = s->next) - func (f->the_bfd, s); - } -} - -#endif - void ldlang_add_file (lang_input_statement_type *entry) { diff --git a/ld/ldlang.h b/ld/ldlang.h index d518398..649fea1 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -264,6 +264,10 @@ typedef struct lang_input_statement_struct /* Whether to search for this entry as a dynamic archive. */ bfd_boolean dynamic; + /* Whether this entry should cause a DT_NEEDED tag only when + satisfying references from regular files, or always. */ + bfd_boolean as_needed; + /* Whether to include the entire contents of an archive. */ bfd_boolean whole_archive; diff --git a/ld/ldmain.c b/ld/ldmain.c index 88b5c75..d0e0b12 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -1,6 +1,6 @@ /* Main program of GNU linker. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, - 2002, 2003 + 2002, 2003, 2004 Free Software Foundation, Inc. Written by Steve Chamberlain steve@cygnus.com @@ -93,6 +93,10 @@ bfd_boolean version_printed; /* Nonzero means link in every member of an archive. */ bfd_boolean whole_archive; +/* Nonzero means create DT_NEEDED entries only if a dynamic library + actually satisfies some reference in a regular object. */ +bfd_boolean as_needed; + /* TRUE if we should demangle symbol names. */ bfd_boolean demangling; diff --git a/ld/ldmain.h b/ld/ldmain.h index 10169dd..8cab5fe 100644 --- a/ld/ldmain.h +++ b/ld/ldmain.h @@ -1,5 +1,5 @@ /* ldmain.h - - Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2002, 2003 + Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -32,6 +32,7 @@ extern bfd_boolean trace_files; extern bfd_boolean trace_file_tries; extern bfd_boolean version_printed; extern bfd_boolean whole_archive; +extern bfd_boolean as_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 e43e15e..d3b3d8d 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -1,6 +1,6 @@ /* Parse options for the GNU linker. Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003 + 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. @@ -112,6 +112,8 @@ enum option_values OPTION_SPLIT_BY_RELOC, OPTION_SPLIT_BY_FILE , OPTION_WHOLE_ARCHIVE, + OPTION_AS_NEEDED, + OPTION_NO_AS_NEEDED, OPTION_WRAP, OPTION_FORCE_EXE_SUFFIX, OPTION_GC_SECTIONS, @@ -438,6 +440,10 @@ static const struct ld_option ld_options[] = TWO_DASHES }, { {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE}, '\0', NULL, N_("Include all objects from following archives"), 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 }, + { {"no-as-needed", no_argument, NULL, OPTION_NO_AS_NEEDED}, + '\0', NULL, N_("Always set DT_NEEDED for following dynamic libs"), TWO_DASHES }, { {"wrap", required_argument, NULL, OPTION_WRAP}, '\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES } }; @@ -1156,6 +1162,12 @@ parse_args (unsigned argc, char **argv) case OPTION_WHOLE_ARCHIVE: whole_archive = TRUE; break; + case OPTION_AS_NEEDED: + as_needed = TRUE; + break; + case OPTION_NO_AS_NEEDED: + as_needed = FALSE; + break; case OPTION_WRAP: add_wrap (optarg); break; |