This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
OO.o / ld / -Bsymbolic patch ...
- From: michael meeks <michael dot meeks at novell dot com>
- To: binutils <binutils at sources dot redhat dot com>
- Cc: Matthias Huetsch <matthias dot huetsch at sun dot com>
- Date: Tue, 05 Jul 2005 15:17:29 +0100
- Subject: OO.o / ld / -Bsymbolic patch ...
- Reply-to: michael dot meeks at novell dot com
Hi guys,
This is my 1st post here; please be patient with me - no doubt I'm
horribly ill-informed; furthermore my patch is for discussion purposes &
is clearly not suitable for merging in it's current form.
So - my problem is; OO.o startup is dog slow - everyone likes to blame
OO.o for this, but arguably it's a pure infrastructural problem; it
starts faster under Wine on the same system eg.
Everything was better in the olden-times when one could use -Bsymbolic
on C++ [correct me if I'm wrong], but then the C++ ABI changed pwrt.
exception handling such that we had to honour weak symbols globally. We
stopped using -Bsymbolic.
OO.o startup performance then sucked so, so badly that we spent ages
marking everything up with visiblity attributes. This improved matters
somewhat. However - we still have a huge number of relocations.
To give some idea - on warm start, we take ~4secs on my machine, and
~25% of that is processing relocations ;-) this is not good.
So - part of the problem is that we do lots of unnecessary work wrt.
internal relocations; the attached patch reduces the total OO.o rel.plt
relocations by ~20% and the total relocation count by nearly 1/2
(rel.dyn + rel.plt[1]).
The patch does 2 things:
a) honours the man pages' promise to bind only -global-
symbols, and not weak ones.
+ a simple objdump -R shows the current
mis-behavior
b) doesn't set DT_SYMBOLIC.
So - a) is (hopefully) quite obvious, b) is perhaps less so. After a) I
was rather perplexed to find my simple C++ throw/catch across libraries
was still not working correctly. [ test for convenience at
http://go-oo.org/~michael/symbolic-test.tar.gz ('make test') ].
The problem with DT_SYMBOLIC (which makes me think that perhaps the
current behavior is feature-not-bug) is to ignore symbol-weakness and
just do the lookup in the scope of the current library - which of course
breaks C++ weak symbols / exceptions really badly :-)
So - the patch turns off that flag. Of course - ideally I'd love a
DT_SYMBOLIC (or sim.) that honoured weak symbols, and yet did a far
shorter search in the library dependants to resolve global symbols - is
such a thing possible ? [I guess this isn't the right list to ask (?)].
Rather a separate issue I suppose.
So - question 1: is this a sensible idea ? or am I smoking crack &
following some common mis-conception ? Q.2 - if not should we add a
-Bsymbolic-foo type option to do this but not set DT_SYMBOLIC (perhaps
that exists already) ?
Anyhow - advice much appreciated, for reference here is the
before/after LD_DEBUG=statistics output for an oowriter run:
before:
14491: runtime linker statistics:
14491: final number of relocations: 61001
14491: final number of relocations from cache: 119292
after:
13540: runtime linker statistics:
13540: final number of relocations: 42107
13540: final number of relocations from cache: 95858
Thanks,
Michael.
[1] - I once understood the difference & my tooling counts only rel.plt
for reasons I've subsequently forgotten.
--- binutils-2.16/bfd/elf32-i386.c
+++ binutils-2.16/bfd/elf32-i386.c
@@ -2395,7 +2429,8 @@
&& (r_type == R_386_PC32
|| !info->shared
|| !info->symbolic
+ || h->root.type == bfd_link_hash_defweak
|| !h->def_regular))
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
else
{
--- binutils-2.16/bfd/elflink.c
+++ binutils-2.16/bfd/elflink.c
@@ -2582,9 +2616,19 @@
/* 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)
return TRUE;
+ if (info->symbolic) {
+ if (h->root.type != bfd_link_hash_defweak)
+ {
+ if (getenv ("BSYMBOLIC_DEBUG"))
+ fprintf (stderr, "-Bsymbolic binding '%s' internally\n",
+ h->root.root.string);
+ return TRUE;
+ }
+ }
+
/* Now deal with defined dynamic symbols in shared libraries. Ones
with default visibility might not resolve locally. */
if (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
@@ -5021,12 +5065,15 @@
return FALSE;
}
+ fprintf (stderr, "Not setting DT_SYMBOLIC\n");
+#if 0
if (info->symbolic)
{
if (!_bfd_elf_add_dynamic_entry (info, DT_SYMBOLIC, 0))
return FALSE;
info->flags |= DF_SYMBOLIC;
}
+#endif
if (rpath != NULL)
{
--
michael.meeks@novell.com <><, Pseudo Engineer, itinerant idiot