* 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.
This commit is contained in:
Alan Modra
2004-03-18 12:50:20 +00:00
parent 3e4caed2b1
commit 4a43e768f1
14 changed files with 251 additions and 171 deletions

View File

@ -1,5 +1,23 @@
2004-03-18 Alan Modra <amodra@bigpond.net.au> 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. * elflink.c (_bfd_elf_merge_symbol): Rewrite weak symbol handling.
(_bfd_elf_add_default_symbol): Remove indirect BFD_ASSERTs. (_bfd_elf_add_default_symbol): Remove indirect BFD_ASSERTs.
* elflink.h (elf_link_add_object_symbols): Don't clear dt_needed in * elflink.h (elf_link_add_object_symbols): Don't clear dt_needed in

View File

@ -599,6 +599,12 @@ struct bfd_link_needed_list
const char *name; 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 extern bfd_boolean bfd_elf_record_link_assignment
(bfd *, struct bfd_link_info *, const char *, bfd_boolean); (bfd *, struct bfd_link_info *, const char *, bfd_boolean);
extern struct bfd_link_needed_list *bfd_elf_get_needed_list 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 *); struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
extern void bfd_elf_set_dt_needed_name extern void bfd_elf_set_dt_needed_name
(bfd *, const char *); (bfd *, const char *);
extern void bfd_elf_set_dt_needed_soname
(bfd *, const char *);
extern const char *bfd_elf_get_dt_soname extern const char *bfd_elf_get_dt_soname
(bfd *); (bfd *);
extern void bfd_elf_set_dyn_lib_class
(bfd *, int);
extern struct bfd_link_needed_list *bfd_elf_get_runpath_list extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);
extern bfd_boolean bfd_elf32_discard_info extern bfd_boolean bfd_elf32_discard_info

View File

@ -606,6 +606,12 @@ struct bfd_link_needed_list
const char *name; 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 extern bfd_boolean bfd_elf_record_link_assignment
(bfd *, struct bfd_link_info *, const char *, bfd_boolean); (bfd *, struct bfd_link_info *, const char *, bfd_boolean);
extern struct bfd_link_needed_list *bfd_elf_get_needed_list 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 *); struct bfd_link_info *, struct bfd_section **, struct bfd_elf_version_tree *);
extern void bfd_elf_set_dt_needed_name extern void bfd_elf_set_dt_needed_name
(bfd *, const char *); (bfd *, const char *);
extern void bfd_elf_set_dt_needed_soname
(bfd *, const char *);
extern const char *bfd_elf_get_dt_soname extern const char *bfd_elf_get_dt_soname
(bfd *); (bfd *);
extern void bfd_elf_set_dyn_lib_class
(bfd *, int);
extern struct bfd_link_needed_list *bfd_elf_get_runpath_list extern struct bfd_link_needed_list *bfd_elf_get_runpath_list
(bfd *, struct bfd_link_info *); (bfd *, struct bfd_link_info *);
extern bfd_boolean bfd_elf32_discard_info extern bfd_boolean bfd_elf32_discard_info

View File

@ -1,6 +1,6 @@
/* BFD back-end data structures for ELF files. /* BFD back-end data structures for ELF files.
Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 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. Written by Cygnus Support.
This file is part of BFD, the Binary File Descriptor library. 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 */ bfd_vma gp; /* The gp value */
unsigned int gp_size; /* The gp size */ unsigned int gp_size; /* The gp size */
Elf_Internal_Shdr **group_sect_ptr;
int num_group;
/* Information grabbed from an elf core file. */ /* Information grabbed from an elf core file. */
int core_signal; int core_signal;
int core_pid; int core_pid;
@ -1142,10 +1139,6 @@ struct elf_obj_tdata
char* core_program; char* core_program;
char* core_command; 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 /* A mapping from external symbols to entries in the linker hash
table, used when linking. This is indexed by the symbol index table, used when linking. This is indexed by the symbol index
minus the sh_info field of the symbol table header. */ minus the sh_info field of the symbol table header. */
@ -1171,21 +1164,6 @@ struct elf_obj_tdata
one. */ one. */
const char *dt_name; 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'. */ /* Records the result of `get_program_header_size'. */
bfd_size_type program_header_size; bfd_size_type program_header_size;
@ -1213,8 +1191,8 @@ struct elf_obj_tdata
created. */ created. */
asection *eh_frame_hdr; asection *eh_frame_hdr;
/* Used to determine if the e_flags field has been initialized */ Elf_Internal_Shdr **group_sect_ptr;
bfd_boolean flags_init; int num_group;
/* Number of symbol version definitions we are about to emit. */ /* Number of symbol version definitions we are about to emit. */
unsigned int cverdefs; unsigned int cverdefs;
@ -1237,6 +1215,25 @@ struct elf_obj_tdata
asymbol *elf_text_symbol; asymbol *elf_text_symbol;
asection *elf_data_section; asection *elf_data_section;
asection *elf_text_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) #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_offsets(bfd) (elf_tdata(bfd) -> local_got.offsets)
#define elf_local_got_ents(bfd) (elf_tdata(bfd) -> local_got.ents) #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_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_bad_symtab(bfd) (elf_tdata(bfd) -> bad_symtab)
#define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init) #define elf_flags_init(bfd) (elf_tdata(bfd) -> flags_init)

View File

@ -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 /* 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 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 entry for a dynamic object. */
empty string to indicate that no DT_NEEDED entry should be made. */
void void
bfd_elf_set_dt_needed_name (bfd *abfd, const char *name) 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 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 if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
&& bfd_get_format (abfd) == bfd_object) && 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 /* Get the list of DT_NEEDED entries for a link. This is a hook for

View File

@ -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. */ /* Add symbols from an ELF object file to the linker hash table. */
static bfd_boolean static bfd_boolean
@ -202,7 +255,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
} }
dt_needed = FALSE; dt_needed = FALSE;
add_needed = FALSE; add_needed = TRUE;
if (! dynamic) if (! dynamic)
{ {
/* If we are creating a shared library, create all the 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 else
{ {
asection *s; asection *s;
const char *name; const char *soname = NULL;
bfd_size_type oldsize;
bfd_size_type strindex;
struct bfd_link_needed_list *rpath = NULL, *runpath = NULL; struct bfd_link_needed_list *rpath = NULL, *runpath = NULL;
int ret;
/* ld --just-symbols and dynamic objects don't mix very well. /* ld --just-symbols and dynamic objects don't mix very well.
Test for --just-symbols by looking at info set up by 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) && s->sec_info_type == ELF_INFO_TYPE_JUST_SYMS)
goto error_return; goto error_return;
/* Find the name to use in a DT_NEEDED entry that refers to this /* If this dynamic lib was specified on the command line with
object. If the object has a DT_SONAME entry, we use it. --as-needed in effect, then we don't want to add a DT_NEEDED
Otherwise, if the generic linker stuck something in tag unless the lib is actually used.
elf_dt_name, we use that. Otherwise, we just use the file For libs brought in by another lib's DT_NEEDED we do the same,
name. If the generic linker put a null string into and also modify handling of weak syms. */
elf_dt_name, we don't make a DT_NEEDED entry at all, even if switch elf_dyn_lib_class (abfd)
there is a DT_SONAME entry. */
add_needed = TRUE;
name = bfd_get_filename (abfd);
if (elf_dt_name (abfd) != NULL)
{ {
name = elf_dt_name (abfd); case DYN_NORMAL:
if (*name == '\0') break;
{ case DYN_DT_NEEDED:
if (elf_dt_soname (abfd) != NULL) dt_needed = TRUE;
dt_needed = TRUE; /* Fall thru */
case DYN_AS_NEEDED:
add_needed = FALSE; add_needed = FALSE;
}
} }
s = bfd_get_section_by_name (abfd, ".dynamic"); s = bfd_get_section_by_name (abfd, ".dynamic");
if (s != NULL) 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) if (dyn.d_tag == DT_SONAME)
{ {
unsigned int tagv = dyn.d_un.d_val; unsigned int tagv = dyn.d_un.d_val;
name = bfd_elf_string_from_elf_section (abfd, shlink, tagv); soname = bfd_elf_string_from_elf_section (abfd, shlink, tagv);
if (name == NULL) if (soname == NULL)
goto error_free_dyn; goto error_free_dyn;
} }
if (dyn.d_tag == DT_NEEDED) 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)) if (! _bfd_elf_link_create_dynamic_sections (abfd, info))
goto error_return; 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. */ soname = elf_dt_name (abfd);
oldsize = _bfd_elf_strtab_size (hash_table->dynstr); if (soname == NULL || *soname == '\0')
strindex = _bfd_elf_strtab_add (hash_table->dynstr, name, FALSE); soname = bfd_get_filename (abfd);
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;
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;
}
}
}
if (! elf_add_dynamic_entry (info, DT_NEEDED, strindex))
goto error_return;
} }
/* Save the SONAME, if there is one, because sometimes the /* Save the SONAME because sometimes the linker emulation code
linker emulation code will need to know it. */ will need to know it. */
if (*name == '\0') elf_dt_name (abfd) = soname;
name = basename (bfd_get_filename (abfd));
elf_dt_name (abfd) = name; ret = add_dt_needed_tag (info, soname, add_needed);
if (ret < 0)
goto error_return;
/* 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 /* 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; break;
} }
if (dt_needed && !add_needed && definition if (!add_needed && definition
&& (h->elf_link_hash_flags && (h->elf_link_hash_flags
& ELF_LINK_HASH_REF_REGULAR) != 0) & ELF_LINK_HASH_REF_REGULAR) != 0)
{ {
bfd_size_type oldsize; int ret;
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. */
/* 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; add_needed = TRUE;
oldsize = _bfd_elf_strtab_size (hash_table->dynstr); ret = add_dt_needed_tag (info, elf_dt_name (abfd), add_needed);
strindex = _bfd_elf_strtab_add (hash_table->dynstr, if (ret < 0)
elf_dt_soname (abfd), FALSE);
if (strindex == (bfd_size_type) -1)
goto error_free_vers; goto error_free_vers;
if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr)) BFD_ASSERT (ret == 0);
{
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;
} }
} }
} }
@ -3950,7 +3948,8 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
case bfd_link_hash_undefined: case bfd_link_hash_undefined:
case bfd_link_hash_undefweak: case bfd_link_hash_undefweak:
abfd = h->root.u.undef.abfd; 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; return FALSE;
break; break;

View File

@ -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> 2004-03-17 Ralf Corsepius <corsepiu@faw.uni-ulm.de>
* configure.tgt: Switch sh-*-rtems* to ELF. Add sh-*-rtemscoff*. * configure.tgt: Switch sh-*-rtems* to ELF. Add sh-*-rtemscoff*.

View File

@ -89,6 +89,28 @@ gld${EMULATION_NAME}_before_parse (void)
EOF EOF
fi 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 cat >>e${EMULATION_NAME}.c <<EOF
/* These variables are required to pass information back and forth /* These variables are required to pass information back and forth
@ -336,14 +358,13 @@ cat >>e${EMULATION_NAME}.c <<EOF
return TRUE; return TRUE;
} }
/* Tell the ELF backend that we don't want the output file to have a /* Specify the soname to use. */
DT_NEEDED entry for this file. */ bfd_elf_set_dt_needed_name (abfd, soname);
bfd_elf_set_dt_needed_name (abfd, "");
/* Tell the ELF backend that the output file needs a DT_NEEDED /* Tell the ELF linker that we don't want the output file to have a
entry for this file if it is used to resolve the reference in DT_NEEDED entry for this file, unless it is used to resolve
a regular object. */ references in a regular object. */
bfd_elf_set_dt_needed_soname (abfd, soname); bfd_elf_set_dyn_lib_class (abfd, DYN_DT_NEEDED);
/* Add this file into the symbol table. */ /* Add this file into the symbol table. */
if (! bfd_link_add_symbols (abfd, &link_info)) 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, gld${EMULATION_NAME}_handle_option,
${LDEMUL_UNRECOGNIZED_FILE-NULL}, ${LDEMUL_UNRECOGNIZED_FILE-NULL},
${LDEMUL_LIST_OPTIONS-gld${EMULATION_NAME}_list_options}, ${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_FIND_POTENTIAL_LIBRARIES-NULL},
${LDEMUL_NEW_VERS_PATTERN-NULL} ${LDEMUL_NEW_VERS_PATTERN-NULL}
}; };

View File

@ -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 so the @samp{--accept-unknown-input-arch} option has been added to
restore the old behaviour. 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} @kindex -assert @var{keyword}
@item -assert @var{keyword} @item -assert @var{keyword}
This option is ignored for SunOS compatibility. This option is ignored for SunOS compatibility.

View File

@ -445,6 +445,7 @@ new_afile (const char *name,
p->next = NULL; p->next = NULL;
p->symbol_count = 0; p->symbol_count = 0;
p->dynamic = config.dynamic_link; p->dynamic = config.dynamic_link;
p->as_needed = as_needed;
p->whole_archive = whole_archive; p->whole_archive = whole_archive;
p->loaded = FALSE; p->loaded = FALSE;
lang_statement_append (&input_file_chain, 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. */ /* Maybe we should load the file's symbols. */
if (s->wild_statement.filename if (s->wild_statement.filename
&& ! wildcardp (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); open_input_bfds (s->wild_statement.children.head, force);
break; break;
case lang_group_statement_enum: case lang_group_statement_enum:
@ -3348,8 +3349,7 @@ lang_do_assignments_1
if (os->bfd_section != NULL) if (os->bfd_section != NULL)
{ {
dot = os->bfd_section->vma; dot = os->bfd_section->vma;
(void) lang_do_assignments_1 (os->children.head, os, lang_do_assignments_1 (os->children.head, os, os->fill, dot);
os->fill, dot);
dot = (os->bfd_section->vma dot = (os->bfd_section->vma
+ TO_ADDR (os->bfd_section->_raw_size)); + 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 void
ldlang_add_file (lang_input_statement_type *entry) ldlang_add_file (lang_input_statement_type *entry)
{ {

View File

@ -264,6 +264,10 @@ typedef struct lang_input_statement_struct
/* Whether to search for this entry as a dynamic archive. */ /* Whether to search for this entry as a dynamic archive. */
bfd_boolean dynamic; 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. */ /* Whether to include the entire contents of an archive. */
bfd_boolean whole_archive; bfd_boolean whole_archive;

View File

@ -1,6 +1,6 @@
/* Main program of GNU linker. /* Main program of GNU linker.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003 2002, 2003, 2004
Free Software Foundation, Inc. Free Software Foundation, Inc.
Written by Steve Chamberlain steve@cygnus.com Written by Steve Chamberlain steve@cygnus.com
@ -93,6 +93,10 @@ bfd_boolean version_printed;
/* Nonzero means link in every member of an archive. */ /* Nonzero means link in every member of an archive. */
bfd_boolean whole_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. */ /* TRUE if we should demangle symbol names. */
bfd_boolean demangling; bfd_boolean demangling;

View File

@ -1,5 +1,5 @@
/* ldmain.h - /* 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. Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker. 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 trace_file_tries;
extern bfd_boolean version_printed; extern bfd_boolean version_printed;
extern bfd_boolean whole_archive; extern bfd_boolean whole_archive;
extern bfd_boolean as_needed;
extern bfd_boolean demangling; extern bfd_boolean demangling;
extern int g_switch_value; extern int g_switch_value;
extern const char *output_filename; extern const char *output_filename;

View File

@ -1,6 +1,6 @@
/* Parse options for the GNU linker. /* Parse options for the GNU linker.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003 2001, 2002, 2003, 2004
Free Software Foundation, Inc. Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker. This file is part of GLD, the Gnu Linker.
@ -112,6 +112,8 @@ enum option_values
OPTION_SPLIT_BY_RELOC, OPTION_SPLIT_BY_RELOC,
OPTION_SPLIT_BY_FILE , OPTION_SPLIT_BY_FILE ,
OPTION_WHOLE_ARCHIVE, OPTION_WHOLE_ARCHIVE,
OPTION_AS_NEEDED,
OPTION_NO_AS_NEEDED,
OPTION_WRAP, OPTION_WRAP,
OPTION_FORCE_EXE_SUFFIX, OPTION_FORCE_EXE_SUFFIX,
OPTION_GC_SECTIONS, OPTION_GC_SECTIONS,
@ -438,6 +440,10 @@ static const struct ld_option ld_options[] =
TWO_DASHES }, TWO_DASHES },
{ {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE}, { {"whole-archive", no_argument, NULL, OPTION_WHOLE_ARCHIVE},
'\0', NULL, N_("Include all objects from following archives"), TWO_DASHES }, '\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}, { {"wrap", required_argument, NULL, OPTION_WRAP},
'\0', N_("SYMBOL"), N_("Use wrapper functions for SYMBOL"), TWO_DASHES } '\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: case OPTION_WHOLE_ARCHIVE:
whole_archive = TRUE; whole_archive = TRUE;
break; break;
case OPTION_AS_NEEDED:
as_needed = TRUE;
break;
case OPTION_NO_AS_NEEDED:
as_needed = FALSE;
break;
case OPTION_WRAP: case OPTION_WRAP:
add_wrap (optarg); add_wrap (optarg);
break; break;