This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
Re: RFC: linker enhancements
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: binutils at sources dot redhat dot com
- Date: Thu, 18 Mar 2004 23:16:11 +1030
- Subject: Re: RFC: linker enhancements
- References: <20031212112448.GI12344@sunsite.ms.mff.cuni.cz> <87wu92xan5.fsf@egil.codesourcery.com> <20031212142914.GK12344@sunsite.ms.mff.cuni.cz> <20040317042418.GZ15900@bubble.modra.org>
I've renamed the option from --only-if-needed to --as-needed, and done
some surgery to elf_link_add_object_symbols. Some changes were
necessary to have the right behaviour for weak syms in shared libs, and
to handle multiple inclusion of the same shared lib. I've also removed
bfd_elf_set_dt_needed_soname and the hack that set an empty soname in
elf_dt_name for DT_NEEDED shared libs. Instead, we call a new function,
bfd_elf_set_dyn_lib_class, to specify any special linker behaviour.
Applying mainline.
bfd/ChangeLog
* 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/ChangeLog
* 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.
Index: bfd/bfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/bfd-in.h,v
retrieving revision 1.74
diff -u -p -r1.74 bfd-in.h
--- bfd/bfd-in.h 15 Mar 2004 14:21:42 -0000 1.74
+++ bfd/bfd-in.h 18 Mar 2004 12:15:00 -0000
@@ -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_dynami
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
Index: bfd/elf-bfd.h
===================================================================
RCS file: /cvs/src/src/bfd/elf-bfd.h,v
retrieving revision 1.127
diff -u -p -r1.127 elf-bfd.h
--- bfd/elf-bfd.h 29 Feb 2004 06:11:52 -0000 1.127
+++ bfd/elf-bfd.h 18 Mar 2004 12:15:05 -0000
@@ -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)
Index: bfd/elf.c
===================================================================
RCS file: /cvs/src/src/bfd/elf.c,v
retrieving revision 1.218
diff -u -p -r1.218 elf.c
--- bfd/elf.c 5 Mar 2004 11:26:04 -0000 1.218
+++ bfd/elf.c 18 Mar 2004 12:15:08 -0000
@@ -1479,8 +1479,7 @@ _bfd_elf_link_hash_table_create (bfd *ab
/* 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, c
}
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
Index: bfd/elflink.h
===================================================================
RCS file: /cvs/src/src/bfd/elflink.h,v
retrieving revision 1.255
diff -u -p -r1.255 elflink.h
--- bfd/elflink.h 18 Mar 2004 04:32:17 -0000 1.255
+++ bfd/elflink.h 18 Mar 2004 12:15:11 -0000
@@ -68,6 +68,59 @@ sort_symbol (const void *arg1, const voi
}
}
+/* 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,
}
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,
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,
&& 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,
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,
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;
+ soname = elf_dt_name (abfd);
+ if (soname == NULL || *soname == '\0')
+ soname = bfd_get_filename (abfd);
+ }
- /* 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;
- }
- }
- }
+ /* 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,
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
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;
Index: ld/ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.106
diff -u -p -r1.106 ld.texinfo
--- ld/ld.texinfo 1 Mar 2004 17:33:36 -0000 1.106
+++ ld/ld.texinfo 18 Mar 2004 12:15:41 -0000
@@ -972,6 +972,18 @@ behaviour from release 2.14 onwards is t
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.
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.140
diff -u -p -r1.140 ldlang.c
--- ld/ldlang.c 5 Mar 2004 11:26:04 -0000 1.140
+++ ld/ldlang.c 18 Mar 2004 12:15:43 -0000
@@ -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_ty
/* 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));
@@ -3937,24 +3937,6 @@ lang_for_each_file (void (*func) (lang_i
func (f);
}
}
-
-#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)
Index: ld/ldlang.h
===================================================================
RCS file: /cvs/src/src/ld/ldlang.h,v
retrieving revision 1.35
diff -u -p -r1.35 ldlang.h
--- ld/ldlang.h 23 Feb 2004 10:10:01 -0000 1.35
+++ ld/ldlang.h 18 Mar 2004 12:15:44 -0000
@@ -264,6 +264,10 @@ typedef struct lang_input_statement_stru
/* 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;
Index: ld/ldmain.c
===================================================================
RCS file: /cvs/src/src/ld/ldmain.c,v
retrieving revision 1.78
diff -u -p -r1.78 ldmain.c
--- ld/ldmain.c 15 Feb 2004 02:24:53 -0000 1.78
+++ ld/ldmain.c 18 Mar 2004 12:15:45 -0000
@@ -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;
Index: ld/ldmain.h
===================================================================
RCS file: /cvs/src/src/ld/ldmain.h,v
retrieving revision 1.7
diff -u -p -r1.7 ldmain.h
--- ld/ldmain.h 28 Jun 2003 05:28:54 -0000 1.7
+++ ld/ldmain.h 18 Mar 2004 12:15:45 -0000
@@ -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;
Index: ld/lexsup.c
===================================================================
RCS file: /cvs/src/src/ld/lexsup.c,v
retrieving revision 1.70
diff -u -p -r1.70 lexsup.c
--- ld/lexsup.c 7 Dec 2003 00:08:41 -0000 1.70
+++ ld/lexsup.c 18 Mar 2004 12:15:45 -0000
@@ -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 }
};
@@ -1155,6 +1161,12 @@ parse_args (unsigned argc, char **argv)
break;
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);
Index: ld/emultempl/elf32.em
===================================================================
RCS file: /cvs/src/src/ld/emultempl/elf32.em,v
retrieving revision 1.108
diff -u -p -r1.108 elf32.em
--- ld/emultempl/elf32.em 3 Jan 2004 12:39:07 -0000 1.108
+++ ld/emultempl/elf32.em 18 Mar 2004 12:15:47 -0000
@@ -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, "");
-
- /* 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);
+ /* Specify the soname to use. */
+ bfd_elf_set_dt_needed_name (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_${EMU
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}
};
--
Alan Modra
IBM OzLabs - Linux Technology Centre