From: "H. J. Lu" <hjl@lucon.org>
To: Michael Matz <matz@suse.de>
Cc: binutils@sources.redhat.com
Subject: RFC: Add dynamic list to version script
Date: Mon, 24 Jul 2006 22:27:00 -0000 [thread overview]
Message-ID: <20060724221020.GA22024@lucon.org> (raw)
On Tue, Jul 18, 2006 at 06:10:18PM +0200, Michael Matz wrote:
> Hi,
>
> On Sun, 16 Jul 2006, H. J. Lu wrote:
>
> > ld -shared -Bsymbolic will reduce number of dynamic relocations in
> > a shared library. Unfortunately, it won't work correctly with C++
> > exception and maybe other language features.
> >
> > However, I think it is possible to make -shared -Bsymbolic to work
> > for C++ by providing a way to specify a list of symbols which must
> > be dynamic. We then can do
> >
> > # g++ -Wl,-Bsymbolic -shared -xxx "list of dynamic symbols" -o libfoo.so ...
> >
> > and libfoo.so written in C++ will work correctly with much fewer dynamic
> > relocations.
>
> Yes, I'd like that too (actually a customer of us). There is some
> precedent set by the HP-UX linker (and I believe the Solaris linker has
> that too). Actually I would make -xxx (whatever the final name would be)
> accept a list of globs, not just a list of symbols. Then you simply can
> say -xxx "_ZTS*,_ZTI*" and have the typeinfo symbols and names exported,
> while all others are bound symbolically.
>
>
Here is a prototype, which added dynamic list to version script. I used
{
dynamic:
extern "C++"
{
*typeinfo*;
};
};
It seems to work correctly with execptions between shared C++ libraries.
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-24 13:42:00.000000000 -0700
@@ -1151,6 +1151,8 @@ elf_i386_check_relocs (bfd *abfd,
&& (r_type != R_386_PC32
|| (h != NULL
&& (! info->symbolic
+ || ! info->dynamic
+ || h->dynamic
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
@@ -2630,6 +2632,8 @@ elf_i386_relocate_section (bfd *output_b
&& (r_type == R_386_PC32
|| !info->shared
|| !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-24 13:42:14.000000000 -0700
@@ -998,6 +998,8 @@ elf64_x86_64_check_relocs (bfd *abfd, st
&& (r_type != R_X86_64_PC64))
|| (h != NULL
&& (! info->symbolic
+ || ! info->dynamic
+ || h->dynamic
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
@@ -2446,6 +2448,8 @@ elf64_x86_64_relocate_section (bfd *outp
|| r_type == R_X86_64_PC64
|| !info->shared
|| !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;
}
\f
+/* 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-24 13:42:31.000000000 -0700
@@ -2742,6 +2742,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
this may help reduce memory usage and processing time later. */
maybe_dynamic = (h && ((!info->executable
&& (!info->symbolic
+ || !info->dynamic
+ || h->dynamic
|| info->unresolved_syms_in_shared_libs == RM_IGNORE))
|| !h->def_regular
|| h->root.type == bfd_link_hash_defweak));
@@ -2914,6 +2916,8 @@ elfNN_ia64_check_relocs (abfd, info, sec
this may help reduce memory usage and processing time later. */
maybe_dynamic = (h && ((!info->executable
&& (!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;
next reply other threads:[~2006-07-24 22:27 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-07-24 22:27 H. J. Lu [this message]
2006-07-25 12:53 ` Ulrich Drepper
2006-07-25 13:49 ` H. J. Lu
2006-07-25 14:04 ` Ulrich Drepper
2006-07-25 14:36 ` H. J. Lu
2006-07-25 14:49 ` Ulrich Drepper
2006-07-26 16:42 ` Michael Matz
2006-07-27 17:11 ` H. J. Lu
2006-07-28 13:14 ` Michael Matz
2006-07-28 17:40 ` H. J. Lu
2006-07-28 17:59 ` Ulrich Drepper
2006-07-28 18:05 ` H. J. Lu
2006-08-08 17:22 ` H. J. Lu
2006-08-08 18:49 ` Michael Matz
2006-08-09 20:36 ` PATCH: Add --dynamic-list to ld H. J. Lu
2006-09-07 15:28 ` Nick Clifton
2006-09-07 19:41 ` H. J. Lu
2006-09-08 8:17 ` Nick Clifton
2006-10-10 15:50 ` [PATCH] Fix --dynamic-list Jakub Jelinek
2006-10-11 15:39 ` Nick Clifton
2006-10-16 22:45 ` H. J. Lu
2006-10-18 18:19 ` Nick Clifton
2006-08-09 2:02 ` RFC: Add dynamic list to version script Alan Modra
2006-08-09 16:05 ` Michael Matz
2006-08-09 16:19 ` Alan Modra
2006-08-09 17:40 ` H. J. Lu
2006-08-09 16:25 ` H. J. Lu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20060724221020.GA22024@lucon.org \
--to=hjl@lucon.org \
--cc=binutils@sources.redhat.com \
--cc=matz@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).