RFC: Add dynamic list to version script
H. J. Lu
hjl@lucon.org
Fri Jul 28 17:40:00 GMT 2006
On Fri, Jul 28, 2006 at 03:13:49PM +0200, Michael Matz wrote:
> Hi,
>
> On Thu, 27 Jul 2006, H. J. Lu wrote:
>
> > > (no JUMP_SLOT, as expected that's now bound locally). With -Bsymbolic the
> > > _ZTI1A reloc goes away, but the _ZTS1A remains.
> >
> > Can you show me your example?
This updated patch fixes it.
>
>
> > > I find the overloading of semantics a bit confusing. I mean that
> > > using a version script with the "dynamic" tag implicitely has the
> > > effect of -Bsymbolic without actually mentioning that flag. This
> > > means that an empty version script using the "dynamic" tag is the
> > > opposite of using no version script. Perhaps such version script
> > > should only have an effect if the user also specifies -Bsymbolic (i.e.
> > > creating exceptions to the -Bsymbolic symbol set). OTOH it's
> > > documented so it's not that important.
> > >
> >
> > The dynamic verion script doesn't imply -Bsymbolic and shouldn't be used
> > together with -Bsymbolic since -Bsymbolic will set DF_SYMBOLIC and
> > dynamic linker will treat the DSO differently.
>
> Ah yes, I only mean the effect of -Bsymbolic to bind self-defined symbols
> locally. I wonder if DT_SYMBOLIC makes a difference in the end. During
> link editing all references to symbols defined in the DSO are bound
> locally by ld. So there's no reference left for ld.so which could be
> satisfied by the DSO itself, hence it shouldn't matter that it comes first
> in the symbol search order with DT_SYMBOLIC. Hmm.
>
> > What it does is to bind all symbols locally except for which are
> > undefined or on the dynamic list.
>
> With an empty dynamic list, isn't that exactly what -Bsymbolic does,
> ignoring the setting of DT_SYMBOLIC?
The current scheme won't allow empty dynamic list. How useful is empty
dynamic list?
>
> > BTW, I'd like to have a new option name and I am thinking to add an
> > option to make C++ symbols dynamic automatically. Does anyone have any
> > suggestions for new option name?
>
> How do you envision should it work? Would you implement a rule of what
> C++ symbols are in ld (i.e. something like the globs), or would you
> somehow mark the symbols in the compiler? How about -dynamic-only-cpp or
> similar?
>
I am thinking a special section containing a dynamic list and we can
have a builtin dynamic list for C++. How about --dynamic-list and
--dynamic-list-cpp?
H.J.
-----
bfd/
2006-07-24 H.J. Lu <hongjiu.lu@intel.com>
* elf-bfd.h (elf_link_hash_entry): Add a dynamic field.
(bfd_elf_link_mark_dynamic_symbol): New.
* elf32-i386.c (elf_i386_check_relocs): Also check the dynamic
field.
(elf_i386_relocate_section): Likewise.
* elf64-x86-64.c (elf64_x86_64_check_relocs): Likewise.
(elf64_x86_64_relocate_section): Likewise.
* elflink.c (_bfd_elf_merge_symbol): Likewise.
(_bfd_elf_fix_symbol_flags): Likewise.
(_bfd_elf_dynamic_symbol_p): Likewise.
(_bfd_elf_symbol_refs_local_p): Likewise.
* elfxx-ia64.c (elfNN_ia64_check_relocs): Likewise.
* elflink.c (bfd_elf_link_mark_dynamic_symbol): New.
(bfd_elf_record_link_assignment): Call
bfd_elf_link_mark_dynamic_symbol on new entry.
(_bfd_elf_merge_symbol): Likewise.
(_bfd_elf_export_symbol): Return if the symbol isn't exported.
(_bfd_elf_link_assign_sym_version): Don't hide a symbol if it
is marked dynamic.
(bfd_elf_size_dynamic_sections): Updated.
include/
2006-07-24 H.J. Lu <hongjiu.lu@intel.com>
* bfdlink.h (bfd_elf_dynamic_list): New.
(bfd_link_info): Add a dynamic field.
* ld.texinfo: Updated.
* ldgram.y: Support dynamic list.
* ldlex.l: Likewise.
* ldlang.c (lang_register_vers_node): Handle dynamic list.
(lang_new_dynamic_list): New.
* ldlang.h (lang_new_dynamic_list): Likewise.
* ldmain.c (main): Initialize link_info.dynamic.
--- binutils/bfd/elf-bfd.h.dynamic 2006-07-18 13:26:51.000000000 -0700
+++ binutils/bfd/elf-bfd.h 2006-07-24 12:40:19.000000000 -0700
@@ -155,6 +155,8 @@ struct elf_link_hash_entry
unsigned int hidden : 1;
/* Symbol was forced to local scope due to a version script file. */
unsigned int forced_local : 1;
+ /* Symbol was forced to be dynamic due to a version script file. */
+ unsigned int dynamic : 1;
/* Symbol was marked during garbage collection. */
unsigned int mark : 1;
/* Symbol is referenced by a non-GOT/non-PLT relocation. This is
@@ -1833,6 +1835,9 @@ extern bfd_boolean bfd_elf_link_record_d
extern int bfd_elf_link_record_local_dynamic_symbol
(struct bfd_link_info *, bfd *, long);
+extern void bfd_elf_link_mark_dynamic_symbol
+ (struct bfd_link_info *, struct elf_link_hash_entry *);
+
extern bfd_boolean _bfd_elf_close_and_cleanup
(bfd *);
--- binutils/bfd/elf32-i386.c.dynamic 2006-07-11 12:53:42.000000000 -0700
+++ binutils/bfd/elf32-i386.c 2006-07-28 10:09:01.000000000 -0700
@@ -1150,7 +1150,8 @@ elf_i386_check_relocs (bfd *abfd,
&& (sec->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32
|| (h != NULL
- && (! info->symbolic
+ && (! (info->symbolic
+ || (info->dynamic && !h->dynamic))
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
@@ -2629,7 +2630,8 @@ elf_i386_relocate_section (bfd *output_b
&& h->dynindx != -1
&& (r_type == R_386_PC32
|| !info->shared
- || !info->symbolic
+ || !(info->symbolic
+ || (info->dynamic && !h->dynamic))
|| !h->def_regular))
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
else
--- binutils/bfd/elf64-x86-64.c.dynamic 2006-07-11 12:53:42.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c 2006-07-28 10:09:49.000000000 -0700
@@ -997,7 +997,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
&& (r_type != R_X86_64_PC32)
&& (r_type != R_X86_64_PC64))
|| (h != NULL
- && (! info->symbolic
+ && (! (info->symbolic
+ || (info->dynamic && !h->dynamic))
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
@@ -2445,7 +2446,8 @@ elf64_x86_64_relocate_section (bfd *outp
|| r_type == R_X86_64_PC32
|| r_type == R_X86_64_PC64
|| !info->shared
- || !info->symbolic
+ || !(info->symbolic
+ || (info->dynamic && !h->dynamic))
|| !h->def_regular))
{
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
--- binutils/bfd/elflink.c.dynamic 2006-07-18 13:26:51.000000000 -0700
+++ binutils/bfd/elflink.c 2006-07-24 13:52:56.000000000 -0700
@@ -444,6 +444,21 @@ bfd_elf_link_record_dynamic_symbol (stru
return TRUE;
}
+/* Mark a symbol dynamic. */
+
+void
+bfd_elf_link_mark_dynamic_symbol (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ struct bfd_elf_dynamic_list *d = info->dynamic;
+
+ if (d == NULL || info->relocatable)
+ return;
+
+ if ((*d->match) (&d->head, NULL, h->root.root.string))
+ h->dynamic = 1;
+}
+
/* Record an assignment to a symbol made by a linker script. We need
this in case some dynamic object refers to this symbol. */
@@ -477,7 +492,10 @@ bfd_elf_record_link_assignment (bfd *out
}
if (h->root.type == bfd_link_hash_new)
- h->non_elf = 0;
+ {
+ bfd_elf_link_mark_dynamic_symbol (info, h);
+ h->non_elf = 0;
+ }
/* If this symbol is being provided by the linker script, and it is
currently defined by a dynamic object, but not by a regular
@@ -840,6 +858,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
if (h->root.type == bfd_link_hash_new)
{
+ bfd_elf_link_mark_dynamic_symbol (info, h);
h->non_elf = 0;
return TRUE;
}
@@ -914,6 +933,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
if (pold_alignment == NULL
&& !info->shared
&& !info->export_dynamic
+ && !h->dynamic
&& !h->ref_dynamic
&& newdyn
&& newdef
@@ -1626,6 +1646,10 @@ _bfd_elf_export_symbol (struct elf_link_
{
struct elf_info_failed *eif = data;
+ /* Ignore this if we won't export it. */
+ if (!eif->info->export_dynamic && !h->dynamic)
+ return TRUE;
+
/* Ignore indirect symbols. These are added by the versioning code. */
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
@@ -1842,6 +1866,7 @@ _bfd_elf_link_assign_sym_version (struct
d = (*t->match) (&t->locals, NULL, alc);
if (d != NULL
&& h->dynindx != -1
+ && ! h->dynamic
&& ! info->export_dynamic)
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
@@ -1968,6 +1993,7 @@ _bfd_elf_link_assign_sym_version (struct
{
h->verinfo.vertree = local_ver;
if (h->dynindx != -1
+ && ! h->dynamic
&& ! info->export_dynamic)
{
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
@@ -2380,6 +2406,7 @@ _bfd_elf_fix_symbol_flags (struct elf_li
&& eif->info->shared
&& is_elf_hash_table (eif->info->hash)
&& (eif->info->symbolic
+ || (eif->info->dynamic && !h->dynamic)
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
&& h->def_regular)
{
@@ -2608,7 +2635,9 @@ _bfd_elf_dynamic_symbol_p (struct elf_li
/* Identify the cases where name binding rules say that a
visible symbol resolves locally. */
- binding_stays_local_p = info->executable || info->symbolic;
+ binding_stays_local_p = (info->executable
+ || info->symbolic
+ || (info->dynamic && !h->dynamic));
switch (ELF_ST_VISIBILITY (h->other))
{
@@ -2671,7 +2700,9 @@ _bfd_elf_symbol_refs_local_p (struct elf
/* At this point, we know the symbol is defined and dynamic. In an
executable it must resolve locally, likewise when building symbolic
shared libraries. */
- if (info->executable || info->symbolic)
+ if (info->executable
+ || info->symbolic
+ || (info->dynamic && !h->dynamic))
return TRUE;
/* Now deal with defined dynamic symbols in shared libraries. Ones
@@ -5306,7 +5337,7 @@ bfd_elf_size_dynamic_sections (bfd *outp
/* If we are supposed to export all symbols into the dynamic symbol
table (this is not the normal case), then do so. */
- if (info->export_dynamic)
+ if (info->export_dynamic || info->dynamic)
{
elf_link_hash_traverse (elf_hash_table (info),
_bfd_elf_export_symbol,
--- binutils/bfd/elfxx-ia64.c.dynamic 2006-06-20 11:59:14.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c 2006-07-28 10:12:44.000000000 -0700
@@ -2741,7 +2741,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
have yet been processed. Do something with what we know, as
this may help reduce memory usage and processing time later. */
maybe_dynamic = (h && ((!info->executable
- && (!info->symbolic
+ && (!(info->symbolic
+ || (info->dynamic && !h->dynamic))
|| info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| !h->def_regular
|| h->root.type == bfd_link_hash_defweak));
@@ -2913,7 +2914,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
have yet been processed. Do something with what we know, as
this may help reduce memory usage and processing time later. */
maybe_dynamic = (h && ((!info->executable
- && (!info->symbolic
+ && (!(info->symbolic
+ || (info->dynamic && !h->dynamic))
|| info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| !h->def_regular
|| h->root.type == bfd_link_hash_defweak));
--- binutils/include/bfdlink.h.dynamic 2006-07-11 12:53:43.000000000 -0700
+++ binutils/include/bfdlink.h 2006-07-24 11:16:17.000000000 -0700
@@ -221,6 +221,8 @@ enum report_method
RM_GENERATE_ERROR
};
+struct bfd_elf_dynamic_list;
+
/* This structure holds all the information needed to communicate
between BFD and the linker when doing a link. */
@@ -428,6 +430,9 @@ struct bfd_link_info
/* Start and end of RELRO region. */
bfd_vma relro_start, relro_end;
+
+ /* List of symbols should be dynamic. */
+ struct bfd_elf_dynamic_list *dynamic;
};
/* This structures holds a set of callback functions. These are
@@ -721,4 +726,12 @@ struct bfd_elf_version_tree
struct bfd_elf_version_expr *prev, const char *sym);
};
+struct bfd_elf_dynamic_list
+{
+ struct bfd_elf_version_expr_head head;
+ struct bfd_elf_version_expr *(*match)
+ (struct bfd_elf_version_expr_head *head,
+ struct bfd_elf_version_expr *prev, const char *sym);
+};
+
#endif
--- binutils/ld/ld.texinfo.dynamic 2006-07-11 12:53:43.000000000 -0700
+++ binutils/ld/ld.texinfo 2006-07-24 14:16:15.000000000 -0700
@@ -485,11 +485,11 @@ mentioned in the link.
If you use @code{dlopen} to load a dynamic object which needs to refer
back to the symbols defined by the program, rather than some other
dynamic object, then you will probably need to use this option when
-linking the program itself.
-
-You can also use the version script to control what symbols should
-be added to the dynamic symbol table if the output format supports it.
-See the description of @samp{--version-script} in @ref{VERSION}.
+linking the program itself. If the output format supports the version
+script, you can also use it to add the symbols needed by the dynamic
+object to the dynamic symbol table in th executable or keep the dynamic
+relocation in the dynamic object. See the description of
+@samp{--version-script} in @ref{VERSION}.
@ifclear SingleFormat
@cindex big-endian objects
@@ -1128,7 +1128,10 @@ When creating a shared library, bind ref
definition within the shared library, if any. Normally, it is possible
for a program linked against a shared library to override the definition
within the shared library. This option is only meaningful on ELF
-platforms which support shared libraries.
+platforms which support shared libraries. You can use the version
+script to control which symbols shouldn't be bound to the definitions
+within the shared library. See the description of
+@samp{--version-script} in @ref{VERSION}.
@kindex --check-sections
@kindex --no-check-sections
@@ -4464,6 +4467,24 @@ might change in the future, even if the
should check that all of your version directives are behaving as you
expect when you upgrade.
+The nameless version node in the version script can be used to control
+which symbols should be exported in an executable or which symbols
+shouldn't be bound within a shared library.
+
+@smallexample
+@{ dynamic: foo; bar; @};
+@end smallexample
+
+When it is used to export symbols in executables, it is similar to
+@samp{--export-dynamic}, except for that symbols can be exported
+selectively with a version script. When a symbol in a shared library
+is listed as dynamic in a version script, its reference won't be bound
+to the definition within the shared library. If a symbol isn't listed
+as dynamic, its reference will be bound to the definition within
+the shared library. It is similar to @samp{-Bsymbolic}, except for
+that those symbols listed as dynamic won't be bound to their
+definitions.
+
@node Expressions
@section Expressions in Linker Scripts
@cindex expressions
--- binutils/ld/ldgram.y.dynamic 2006-06-08 22:37:07.000000000 -0700
+++ binutils/ld/ldgram.y 2006-07-24 11:37:07.000000000 -0700
@@ -150,6 +150,7 @@ static int error_index;
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
%token <name> VERS_TAG VERS_IDENTIFIER
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
+%token LD_DYNAMIC
%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
%token EXCLUDE_FILE
%token CONSTANT
@@ -1217,6 +1218,10 @@ vers_tag:
{
$$ = lang_new_vers_node ($3, $7);
}
+ | LD_DYNAMIC ':' vers_defns ';'
+ {
+ $$ = lang_new_dynamic_list ($3);
+ }
;
vers_defns:
@@ -1283,6 +1288,14 @@ vers_defns:
{
$$ = lang_new_vers_pattern ($1, "extern", ldgram_vers_current_lang, FALSE);
}
+ | LD_DYNAMIC
+ {
+ $$ = lang_new_vers_pattern (NULL, "dynamic", ldgram_vers_current_lang, FALSE);
+ }
+ | vers_defns ';' LD_DYNAMIC
+ {
+ $$ = lang_new_vers_pattern ($1, "dynamic", ldgram_vers_current_lang, FALSE);
+ }
;
opt_semicolon:
--- binutils/ld/ldlang.c.dynamic 2006-07-18 13:26:51.000000000 -0700
+++ binutils/ld/ldlang.c 2006-07-24 14:49:20.000000000 -0700
@@ -6599,6 +6599,15 @@ lang_register_vers_node (const char *nam
if (name == NULL)
name = "";
+ if (version == NULL)
+ {
+ ASSERT (deps == NULL);
+ if (name[0] != '\0')
+ einfo (_("%F%P: Invalid version tag `%s'. Only anonymous "
+ "version tag is allowed for dynamic list.\n"), name);
+ return;
+ }
+
if ((name[0] == '\0' && lang_elf_version_info != NULL)
|| (lang_elf_version_info && lang_elf_version_info->name[0] == '\0'))
{
@@ -6763,3 +6772,23 @@ lang_add_unique (const char *name)
ent->next = unique_section_list;
unique_section_list = ent;
}
+
+/* Create a list of dynamic symbols. */
+
+struct bfd_elf_version_tree *
+lang_new_dynamic_list (struct bfd_elf_version_expr *dynamic)
+{
+ struct bfd_elf_dynamic_list *d;
+
+ if (link_info.dynamic != NULL)
+ einfo (_("%F%P: Duplicated dynamic lists.\n"));
+
+ d = xcalloc (1, sizeof *d);
+ d->head.list = dynamic;
+ d->match = lang_vers_match;
+ link_info.dynamic = d;
+
+ lang_finalize_version_expr_head (&d->head);
+
+ return NULL;
+}
--- binutils/ld/ldlang.h.dynamic 2006-06-20 11:59:15.000000000 -0700
+++ binutils/ld/ldlang.h 2006-07-24 11:17:44.000000000 -0700
@@ -591,6 +591,8 @@ extern struct bfd_elf_version_deps *lang
(struct bfd_elf_version_deps *, const char *);
extern void lang_register_vers_node
(const char *, struct bfd_elf_version_tree *, struct bfd_elf_version_deps *);
+extern struct bfd_elf_version_tree *lang_new_dynamic_list
+ (struct bfd_elf_version_expr *);
bfd_boolean unique_section_p
(const asection *);
extern void lang_add_unique
--- binutils/ld/ldlex.l.dynamic 2006-05-30 09:45:42.000000000 -0700
+++ binutils/ld/ldlex.l 2006-07-23 15:30:01.000000000 -0700
@@ -405,6 +405,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
<VERS_NODE>local { RTOKEN(LOCAL); }
+<VERS_NODE>dynamic { RTOKEN(LD_DYNAMIC); }
+
<VERS_NODE>extern { RTOKEN(EXTERN); }
<VERS_NODE>{V_IDENTIFIER} { yylval.name = xstrdup (yytext);
--- binutils/ld/ldmain.c.dynamic 2006-07-11 12:53:43.000000000 -0700
+++ binutils/ld/ldmain.c 2006-07-24 11:22:55.000000000 -0700
@@ -318,6 +318,7 @@ main (int argc, char **argv)
link_info.relax_pass = 1;
link_info.warn_shared_textrel = FALSE;
link_info.gc_sections = FALSE;
+ link_info.dynamic = NULL;
config.maxpagesize = 0;
config.commonpagesize = 0;
More information about the Binutils
mailing list