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 /bfd | |
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.
Diffstat (limited to 'bfd')
-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 |
6 files changed, 163 insertions, 138 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; |