PATCH: Slow linker with shared C++ libraries
H. J. Lu
hjl@lucon.org
Thu Feb 26 21:11:00 GMT 2004
On Thu, Feb 26, 2004 at 11:58:05AM +0100, Lars Knoll wrote:
> On Thursday 26 February 2004 07:19, H. J. Lu wrote:
> > If a shared C++ library has many weak data definitions and many
> > symbols, linking against such libraries can be very slow since
> > elf_link_add_object_symbols has to go through all symbols for
> > each referenced weak data definition to search for its aliases,
> > although in most cases there is no alias. What is the best way
> > to speed it up? Can we introduce a linker command not to check
> > aliase for a DSO?
>
> Michael Matz and myself made a patch to speed up weak symbol handling in the
> linker, see:
>
> http://sources.redhat.com/ml/binutils/2003-09/msg00175.html
>
> As far as I know the patch is still not in binutils, but it sounds very much
> like a solution to your problem.
That is the same problem. You may want to add h->type != STT_FUNC
when you create the hash table. In my testcase, there is no visible
speed difference between sorted array and hash table. Either way
should work for me.
I am enclosing the modified hash table patch here. Could someone
please take a look at both?
Thanks.
H.J.
-------------- next part --------------
2003-09-10 Lars Knoll <lars@trolltech.com>
Michael Matz <matz@suse.de>
Andreas Jaeger <aj@suse.de>
* elflink.h: Include hashtab.h.
(sym_tab_hash, sym_hash_equal): New.
(elf_link_add_object_symbols): Avoid quadratic algorithm by using
a hash of all symbols.
--- bfd/elflink.h.weak 2004-02-24 09:32:07.000000000 -0800
+++ bfd/elflink.h 2004-02-26 12:55:20.000000000 -0800
@@ -18,6 +18,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include <hashtab.h>
+
/* ELF linker code. */
#include "safe-ctype.h"
@@ -392,6 +394,28 @@ elf_link_add_archive_symbols (bfd *abfd,
return FALSE;
}
+static hashval_t
+sym_tab_hash (const void *ptr)
+{
+ const struct elf_link_hash_entry *h;
+ h = (const struct elf_link_hash_entry *) ptr;
+
+ return (hashval_t)(h->root.u.def.value >> 3)
+ ^ (h->root.u.def.section->target_index << 10);
+}
+
+
+static int
+sym_hash_equal (const void *p1, const void *p2)
+{
+ const struct elf_link_hash_entry *h1, *h2;
+ h1 = (const struct elf_link_hash_entry *) p1;
+ h2 = (const struct elf_link_hash_entry *) p2;
+
+ return ((h1->root.u.def.section == h2->root.u.def.section)
+ && (h1->root.u.def.value == h2->root.u.def.value));
+}
+
/* Add symbols from an ELF object file to the linker hash table. */
static bfd_boolean
@@ -1493,36 +1517,54 @@ elf_link_add_object_symbols (bfd *abfd,
assembler code, handling it correctly would be very time
consuming, and other ELF linkers don't handle general aliasing
either. */
- while (weaks != NULL)
+ if (weaks != NULL)
{
- struct elf_link_hash_entry *hlook;
- asection *slook;
- bfd_vma vlook;
+ htab_t sym_tab;
struct elf_link_hash_entry **hpp;
struct elf_link_hash_entry **hppend;
- hlook = weaks;
- weaks = hlook->weakdef;
- hlook->weakdef = NULL;
-
- BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
- || hlook->root.type == bfd_link_hash_defweak
- || hlook->root.type == bfd_link_hash_common
- || hlook->root.type == bfd_link_hash_indirect);
- slook = hlook->root.u.def.section;
- vlook = hlook->root.u.def.value;
+ sym_tab = htab_create_alloc ((size_t) extsymcount * 3, sym_tab_hash,
+ sym_hash_equal, NULL, calloc, free);
+ if (sym_tab == NULL)
+ goto error_return;
+
+ /* Fill symbol hashtable. */
hpp = elf_sym_hashes (abfd);
hppend = hpp + extsymcount;
for (; hpp < hppend; hpp++)
{
+ struct elf_link_hash_entry *h = *hpp;
+ if (h
+ && h->root.type == bfd_link_hash_defined
+ && h->type != STT_FUNC)
+ {
+ void **p = htab_find_slot (sym_tab, h, INSERT);
+ if (p == NULL)
+ goto error_return;
+ if (*p == NULL)
+ /* Add element to hashtable. */
+ *p = h;
+ }
+ }
+
+ while (weaks != NULL)
+ {
+ struct elf_link_hash_entry *hlook;
struct elf_link_hash_entry *h;
- h = *hpp;
- if (h != NULL && h != hlook
- && h->root.type == bfd_link_hash_defined
- && h->root.u.def.section == slook
- && h->root.u.def.value == vlook)
+ hlook = weaks;
+ weaks = hlook->weakdef;
+ hlook->weakdef = NULL;
+
+ BFD_ASSERT (hlook->root.type == bfd_link_hash_defined
+ || hlook->root.type == bfd_link_hash_defweak
+ || hlook->root.type == bfd_link_hash_common
+ || hlook->root.type == bfd_link_hash_indirect);
+
+ h = (struct elf_link_hash_entry *)htab_find (sym_tab, hlook);
+
+ if (h && h != hlook)
{
hlook->weakdef = h;
@@ -1547,9 +1589,9 @@ elf_link_add_object_symbols (bfd *abfd,
if (! _bfd_elf_link_record_dynamic_symbol (info, hlook))
goto error_return;
}
- break;
}
}
+ htab_delete (sym_tab);
}
/* If this object is the same format as the output object, and it is
More information about the Binutils
mailing list