public inbox for elfutils@sourceware.org
 help / color / mirror / Atom feed
* Re: [PATCH] Remove eu-ld and unused code.
@ 2016-08-03 16:26 Mark Wielaard
  0 siblings, 0 replies; 5+ messages in thread
From: Mark Wielaard @ 2016-08-03 16:26 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 793 bytes --]

On Wed, 2016-07-06 at 23:10 +0200, Mark Wielaard wrote:
> Nobody has hacked on eu-ld in a very long time. It didn't really work.
> And we didn't install it by default in the spec file. Remove sources,
> the build rules and any (now) unused code.

After a small vacation and some positive comments on irc (*) I have now
pushed this to master since it is clear nobody is going to work on this
code in the public repository. If people do want to, then we can of
course resurrect it.

Cheers,

Mark

(*) We do have an irc channel #elfutils on irc.freenode.net where
everybody is welcome to discuss hacking on or using elfutils. Sometimes
irc is easier to have a quick question or discussion. But please do post
any conclusion or comment about code to be committed on the list too.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Remove eu-ld and unused code.
@ 2016-07-08 13:09 Mark Wielaard
  0 siblings, 0 replies; 5+ messages in thread
From: Mark Wielaard @ 2016-07-08 13:09 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1269 bytes --]

On Thu, 2016-07-07 at 07:37 -0400, Ulrich Drepper wrote:
> On Thu, Jul 7, 2016 at 3:55 AM, Mark Wielaard <mjw@redhat.com> wrote:
> > Yes, you did a lot of work on it. And yes, it does have an unique
> > design. Thanks. But your last commit to it was 8 years ago.
> 
> The changes aren't in your repository because I don't trust you one
> bit and don't want to deal with the public repository.  I don't have
> to ask what to check in.  I have the change in my repository and they
> are published once I'm satisfied I'll push them out in one piece.  By
> removing the code you declare that you decide about the future of all
> that code.

I am proposing to remove that code because as far as I know none of the
maintainers is using it or willing to do any work on it in the public
repository. If someone wants to then I am happy to keep it around. But
if not then I do think it is confusing and a bit of a maintenance burden
given that it is incomplete, there are no current users nor any tests
for it. That doesn't mean you cannot keep hacking on your private copy
if you don't want to deal with the public repository. How to work with
and get code into the public repository is described in the CONTRIBUTING
document. It does require a bit of trust.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Remove eu-ld and unused code.
@ 2016-07-07  7:55 Mark Wielaard
  0 siblings, 0 replies; 5+ messages in thread
From: Mark Wielaard @ 2016-07-07  7:55 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 1617 bytes --]

Hi Ulrich,

On Wed, 2016-07-06 at 18:04 -0400, Ulrich Drepper wrote:
> On Wed, Jul 6, 2016 at 5:10 PM, Mark Wielaard <mjw@redhat.com> wrote:
> > Nobody has hacked on eu-ld in a very long time. It didn't really work.
> > And we didn't install it by default in the spec file. Remove sources,
> > the build rules and any (now) unused code.
> 
> Wrong.  I have worked on it and this is my code after all.  You just,
> without asking, claimed ownership anyway.  This is the only linker,
> I'm aware of, which is aimed to be used in library form which was one
> of the design decisions.

Yes, you did a lot of work on it. And yes, it does have an unique
design. Thanks. But your last commit to it was 8 years ago. Since then
people have only patched it up to fix build issues. There are no
testcases for it. And we do get reports from people who do install it
and find it not working. While it does have great potential, if nobody
is working on it or using it, then it is just a drag on maintenance.

The direct reason for removing it now is because various projects found
some use for the string table code which I wanted to rework. This code
is of course used a lot in the linker. But given that nobody actively
uses or works on the linker and we have no tests for it, it seemed
better to remove the (unused) code now than to pretend we keep what is
there working.

The code is of course not really gone. It will be in the git repository
history and can be resurrected once people actively work on it again.
All elfutils development is done openly through this mailinglist.

Cheers,

Mark

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Remove eu-ld and unused code.
@ 2016-07-06 22:04 Ulrich Drepper
  0 siblings, 0 replies; 5+ messages in thread
From: Ulrich Drepper @ 2016-07-06 22:04 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 501 bytes --]

On Wed, Jul 6, 2016 at 5:10 PM, Mark Wielaard <mjw@redhat.com> wrote:
> Nobody has hacked on eu-ld in a very long time. It didn't really work.
> And we didn't install it by default in the spec file. Remove sources,
> the build rules and any (now) unused code.

Wrong.  I have worked on it and this is my code after all.  You just,
without asking, claimed ownership anyway.  This is the only linker,
I'm aware of, which is aimed to be used in library form which was one
of the design decisions.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH] Remove eu-ld and unused code.
@ 2016-07-06 21:10 Mark Wielaard
  0 siblings, 0 replies; 5+ messages in thread
From: Mark Wielaard @ 2016-07-06 21:10 UTC (permalink / raw)
  To: elfutils-devel

[-- Attachment #1: Type: text/plain, Size: 468494 bytes --]

Nobody has hacked on eu-ld in a very long time. It didn't really work.
And we didn't install it by default in the spec file. Remove sources,
the build rules and any (now) unused code.

Signed-off-by: Mark Wielaard <mjw@redhat.com>
---
 .gitignore                 |    4 -
 ChangeLog                  |    5 +
 config/ChangeLog           |    4 +
 config/elfutils.spec.in    |    2 -
 configure.ac               |   30 -
 libebl/ChangeLog           |   18 +
 libebl/Makefile.am         |    6 +-
 libebl/ebl-hooks.h         |    8 +-
 libebl/eblgstrtab.c        |  365 ---
 libebl/eblobjecttypename.c |   59 -
 libebl/eblopenbackend.c    |   21 +-
 libebl/eblshflagscombine.c |   41 -
 libebl/eblwstrtab.c        |  359 ---
 libebl/libebl.h            |   54 +-
 libelf/ChangeLog           |    5 +
 libelf/elf-knowledge.h     |   26 +-
 po/ChangeLog               |    5 +
 po/POTFILES.in             |    5 -
 src/ChangeLog              |   24 +
 src/Makefile.am            |   81 +-
 src/elf32-i386.script      |  229 --
 src/i386_ld.c              | 1102 -------
 src/ld.c                   | 1607 ----------
 src/ld.h                   | 1135 -------
 src/ldgeneric.c            | 7132 --------------------------------------------
 src/ldlex.l                |  353 ---
 src/ldscript.y             |  803 -----
 src/libld_elf_i386.map     |    7 -
 src/none_ld.c              |    1 -
 src/sectionhash.c          |   73 -
 src/sectionhash.h          |   27 -
 src/symbolhash.c           |   33 -
 src/symbolhash.h           |   28 -
 src/unaligned.h            |  102 -
 src/versionhash.c          |   32 -
 src/versionhash.h          |   26 -
 src/xelf.h                 |  391 ---
 37 files changed, 72 insertions(+), 14131 deletions(-)
 delete mode 100644 libebl/eblgstrtab.c
 delete mode 100644 libebl/eblobjecttypename.c
 delete mode 100644 libebl/eblshflagscombine.c
 delete mode 100644 libebl/eblwstrtab.c
 delete mode 100644 src/elf32-i386.script
 delete mode 100644 src/i386_ld.c
 delete mode 100644 src/ld.c
 delete mode 100644 src/ld.h
 delete mode 100644 src/ldgeneric.c
 delete mode 100644 src/ldlex.l
 delete mode 100644 src/ldscript.y
 delete mode 100644 src/libld_elf_i386.map
 delete mode 100644 src/none_ld.c
 delete mode 100644 src/sectionhash.c
 delete mode 100644 src/sectionhash.h
 delete mode 100644 src/symbolhash.c
 delete mode 100644 src/symbolhash.h
 delete mode 100644 src/unaligned.h
 delete mode 100644 src/versionhash.c
 delete mode 100644 src/versionhash.h
 delete mode 100644 src/xelf.h

diff --git a/.gitignore b/.gitignore
index 75043fe..c583347 100644
--- a/.gitignore
+++ b/.gitignore
@@ -60,10 +60,6 @@ Makefile.in
 /src/elfcompress
 /src/elflint
 /src/findtextrel
-/src/ld
-/src/ldlex.c
-/src/ldscript.c
-/src/ldscript.h
 /src/make-debug-archive
 /src/nm
 /src/objdump
diff --git a/ChangeLog b/ChangeLog
index 5be4c5e..6a038a2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* .gitignore: Remove src/ld. ldlex.c, ldscript.c and ldscript.h.
+	* configure.ac (enable generic): Removed.
+
 2016-06-28  Richard Henderson <rth@redhat.com>
 
 	* configure.ac (HAVE_LINUX_BPF_H): New test and conditional.
diff --git a/config/ChangeLog b/config/ChangeLog
index 5357f22..4ca6fa8 100644
--- a/config/ChangeLog
+++ b/config/ChangeLog
@@ -1,3 +1,7 @@
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Remove eu-ld.
+
 2016-03-31  Mark Wielaard  <mjw@redhat.com>
 
 	* elfutils.spec.in: Update for 0.166.
diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
index 9b00c47..b62be26 100644
--- a/config/elfutils.spec.in
+++ b/config/elfutils.spec.in
@@ -134,7 +134,6 @@ chmod +x ${RPM_BUILD_ROOT}%{_prefix}/%{_lib}/elfutils/lib*.so*
 
 # XXX Nuke unpackaged files
 { cd ${RPM_BUILD_ROOT}
-  rm -f .%{_bindir}/eu-ld
   rm -f .%{_includedir}/elfutils/libasm.h
   rm -f .%{_libdir}/libasm.so
   rm -f .%{_libdir}/libasm.a
@@ -176,7 +175,6 @@ rm -rf ${RPM_BUILD_ROOT}
 %{_bindir}/eu-ar
 %{_bindir}/eu-unstrip
 %{_bindir}/eu-make-debug-archive
-#%{_bindir}/eu-ld
 %{_bindir}/eu-elfcompress
 %{_libdir}/libasm-%{version}.so
 %{_libdir}/libdw-%{version}.so
diff --git a/configure.ac b/configure.ac
index 926715c..e753dd9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -144,36 +144,6 @@ dnl tests, because the choice of the file model can (in principle) affect
 dnl whether functions and headers are available, whether they work, etc.
 AC_SYS_LARGEFILE
 
-dnl Enable the linker to be build as a native-only linker.  By default it
-dnl can handle all architectures but this comes at a cost.  A native
-dnl will be slightly faster, small, and has fewer dependencies.
-native_ld=no
-AC_ARG_ENABLE([generic],
-AS_HELP_STRING([--disable-generic], [do not build generic linker]), [dnl
-if test "$enable_generic" = no; then
-  case "$host_cpu" in
-   i?86)
-    AC_DEFINE(NATIVE_ELF, 32)
-    native_ld=yes
-    base_cpu=i386
-    ;;
-   *)
-    AC_MSG_ERROR([no machine-specific linker for this configuration available])
-    ;;
-  esac
-fi])
-AH_TEMPLATE([NATIVE_ELF],
-[Define to 32 or 64 if a specific implementation is wanted.])
-AM_CONDITIONAL(NATIVE_LD, test "$native_ld" = yes)
-dnl The automake generated Makefile cannot deal with macros in the name
-dnl of files if at any time there is no such file, even if the filename
-dnl would not be used.
-AS_IF([test -z "$base_cpu"], [base_cpu=none])
-AC_SUBST(base_cpu)
-dnl Support to work around automake's inflexible dependency generation.
-dnl See src/Makefile.am for more information.
-AM_CONDITIONAL(NEVER, false)
-
 dnl enable debugging of branch prediction.
 AC_ARG_ENABLE([debugpred],
 AS_HELP_STRING([--enable-debugpred],[build binaries with support to debug branch prediction]),
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 8ff4010..fc3cf3b 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,21 @@
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Remove eblobjecttypename.c,
+	eblshflagscombine.c, eblwstrtab.c and eblgstrtab.c.
+	* ebl-hooks.h (object_type_name): Removed.
+	(sh_flags_combine): Likewise.
+	* eblgstrtab.c: Removed.
+	* eblobjecttypename.c: Removed.
+	* eblopenbackend.c (default_object_type_name): Removed.
+	(default_sh_flags_combine): Likewise.
+	(fill_defaults): Removed object_type_name and sh_flags_combine.
+	* eblshflagscombine.c: Removed.
+	* eblwstrtab.c: Removed.
+	* libebl.h (ebl_object_type_name): Removed.
+	(ebl_sh_flags_combine): Likewise.
+	(ebl_wstrtab*): Removed.
+	(ebl_gstrtab*): Likewise.
+
 2016-06-28  Richard Henderson <rth@redhat.com>
 
 	* ebl-hooks.h (EBLHOOK(disasm)): Add ebl parameter.
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 6b41a3e..3bd4abe 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 2000-2010, 2013 Red Hat, Inc.
+## Copyright (C) 2000-2010, 2013, 2016 Red Hat, Inc.
 ## This file is part of elfutils.
 ##
 ## This file is free software; you can redistribute it and/or modify
@@ -41,9 +41,7 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
 	      eblreloctypename.c eblsegmenttypename.c \
 	      eblsectiontypename.c eblmachineflagname.c \
 	      eblsymboltypename.c ebldynamictagname.c eblsectionname.c \
-	      eblobjecttypename.c eblsymbolbindingname.c \
-	      eblbackendname.c eblshflagscombine.c eblwstrtab.c \
-	      eblgstrtab.c eblosabiname.c \
+	      eblsymbolbindingname.c eblbackendname.c eblosabiname.c \
 	      eblmachineflagcheck.c eblmachinesectionflagcheck.c \
 	      eblreloctypecheck.c eblrelocvaliduse.c eblrelocsimpletype.c \
 	      ebldynamictagcheck.c eblcorenotetypename.c eblobjnotetypename.c \
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index a7f4755..b725374 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -1,5 +1,5 @@
 /* Backend hook signatures internal interface for libebl.
-   Copyright (C) 2000-2011, 2013, 2014 Red Hat, Inc.
+   Copyright (C) 2000-2011, 2013, 2014, 2016 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -26,9 +26,6 @@
    the GNU Lesser General Public License along with this program.  If
    not, see <http://www.gnu.org/licenses/>.  */
 
-/* Return symbol representaton of object file type.  */
-const char *EBLHOOK(object_type_name) (int, char *, size_t);
-
 /* Return symbolic representation of relocation type.  */
 const char *EBLHOOK(reloc_type_name) (int, char *, size_t);
 
@@ -80,9 +77,6 @@ const char *EBLHOOK(dynamic_tag_name) (int64_t, char *, size_t);
 /* Check dynamic tag.  */
 bool EBLHOOK(dynamic_tag_check) (int64_t);
 
-/* Combine section header flags values.  */
-GElf_Word EBLHOOK(sh_flags_combine) (GElf_Word, GElf_Word);
-
 /* Return symbolic representation of OS ABI.  */
 const char *EBLHOOK(osabi_name) (int, char *, size_t);
 
diff --git a/libebl/eblgstrtab.c b/libebl/eblgstrtab.c
deleted file mode 100644
index 0d92c00..0000000
--- a/libebl/eblgstrtab.c
+++ /dev/null
@@ -1,365 +0,0 @@
-/* Generic string table handling.
-   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of either
-
-     * the GNU Lesser General Public License as published by the Free
-       Software Foundation; either version 3 of the License, or (at
-       your option) any later version
-
-   or
-
-     * the GNU General Public License as published by the Free
-       Software Foundation; either version 2 of the License, or (at
-       your option) any later version
-
-   or both in parallel, as here.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received copies of the GNU General Public License and
-   the GNU Lesser General Public License along with this program.  If
-   not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <inttypes.h>
-#include <libelf.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-
-#include "libebl.h"
-
-#ifndef MIN
-# define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-
-struct Ebl_GStrent
-{
-  const char *string;
-  size_t len;
-  struct Ebl_GStrent *next;
-  struct Ebl_GStrent *left;
-  struct Ebl_GStrent *right;
-  size_t offset;
-  unsigned int width;
-  char reverse[0];
-};
-
-
-struct memoryblock
-{
-  struct memoryblock *next;
-  char memory[0];
-};
-
-
-struct Ebl_GStrtab
-{
-  struct Ebl_GStrent *root;
-  struct memoryblock *memory;
-  char *backp;
-  size_t left;
-  size_t total;
-  unsigned int width;
-  bool nullstr;
-
-  struct Ebl_GStrent null;
-};
-
-
-/* Cache for the pagesize.  We correct this value a bit so that `malloc'
-   is not allocating more than a page.  */
-static size_t ps;
-
-
-struct Ebl_GStrtab *
-ebl_gstrtabinit (unsigned int width, bool nullstr)
-{
-  struct Ebl_GStrtab *ret;
-
-  if (ps == 0)
-    {
-      ps = sysconf (_SC_PAGESIZE) - 2 * sizeof (void *);
-      assert (sizeof (struct memoryblock) < ps);
-    }
-
-  ret = (struct Ebl_GStrtab *) calloc (1, sizeof (struct Ebl_GStrtab));
-  if (ret != NULL)
-    {
-      ret->width = width;
-      ret->nullstr = nullstr;
-
-      if (nullstr)
-	{
-	  ret->null.len = 1;
-	  ret->null.string = (char *) calloc (1, width);
-	}
-    }
-
-  return ret;
-}
-
-
-static void
-morememory (struct Ebl_GStrtab *st, size_t len)
-{
-  struct memoryblock *newmem;
-
-  if (len < ps)
-    len = ps;
-  newmem = (struct memoryblock *) malloc (len);
-  if (newmem == NULL)
-    abort ();
-
-  newmem->next = st->memory;
-  st->memory = newmem;
-  st->backp = newmem->memory;
-  st->left = len - offsetof (struct memoryblock, memory);
-}
-
-
-void
-ebl_gstrtabfree (struct Ebl_GStrtab *st)
-{
-  struct memoryblock *mb = st->memory;
-
-  while (mb != NULL)
-    {
-      void *old = mb;
-      mb = mb->next;
-      free (old);
-    }
-
-  if (st->null.string != NULL)
-    free ((char *) st->null.string);
-
-  free (st);
-}
-
-
-static struct Ebl_GStrent *
-newstring (struct Ebl_GStrtab *st, const char *str, size_t len)
-{
-  /* Compute the amount of padding needed to make the structure aligned.  */
-  size_t align = ((__alignof__ (struct Ebl_GStrent)
-		   - (((uintptr_t) st->backp)
-		      & (__alignof__ (struct Ebl_GStrent) - 1)))
-		  & (__alignof__ (struct Ebl_GStrent) - 1));
-
-  /* Make sure there is enough room in the memory block.  */
-  if (st->left < align + sizeof (struct Ebl_GStrent) + len * st->width)
-    {
-      morememory (st, sizeof (struct Ebl_GStrent) + len * st->width);
-      align = 0;
-    }
-
-  /* Create the reserved string.  */
-  struct Ebl_GStrent *newstr = (struct Ebl_GStrent *) (st->backp + align);
-  newstr->string = str;
-  newstr->len = len;
-  newstr->width = st->width;
-  newstr->next = NULL;
-  newstr->left = NULL;
-  newstr->right = NULL;
-  newstr->offset = 0;
-  for (int i = len - 2; i >= 0; --i)
-    for (int j = st->width - 1; j >= 0; --j)
-      newstr->reverse[i * st->width + j] = str[(len - 2 - i) * st->width + j];
-  for (size_t j = 0; j < st->width; ++j)
-    newstr->reverse[(len - 1) * st->width + j] = '\0';
-  st->backp += align + sizeof (struct Ebl_GStrent) + len * st->width;
-  st->left -= align + sizeof (struct Ebl_GStrent) + len * st->width;
-
-  return newstr;
-}
-
-
-/* XXX This function should definitely be rewritten to use a balancing
-   tree algorith (AVL, red-black trees).  For now a simple, correct
-   implementation is enough.  */
-static struct Ebl_GStrent **
-searchstring (struct Ebl_GStrent **sep, struct Ebl_GStrent *newstr)
-{
-  int cmpres;
-
-  /* More strings?  */
-  if (*sep == NULL)
-    {
-      *sep = newstr;
-      return sep;
-    }
-
-  /* Compare the strings.  */
-  cmpres = memcmp ((*sep)->reverse, newstr->reverse,
-		   (MIN ((*sep)->len, newstr->len) - 1) * (*sep)->width);
-  if (cmpres == 0)
-    /* We found a matching string.  */
-    return sep;
-  else if (cmpres > 0)
-    return searchstring (&(*sep)->left, newstr);
-  else
-    return searchstring (&(*sep)->right, newstr);
-}
-
-
-/* Add new string.  The actual string is assumed to be permanent.  */
-struct Ebl_GStrent *
-ebl_gstrtabadd (struct Ebl_GStrtab *st, const char *str, size_t len)
-{
-  struct Ebl_GStrent *newstr;
-  struct Ebl_GStrent **sep;
-
-  /* Compute the string length if the caller doesn't know it.  */
-  if (len == 0)
-    {
-      size_t j;
-
-      do
-	for (j = 0; j < st->width; ++j)
-	  if (str[len * st->width + j] != '\0')
-	    break;
-      while (j == st->width && ++len);
-    }
-
-  /* Make sure all "" strings get offset 0 but only if the table was
-     created with a special null entry in mind.  */
-  if (len == 1 && st->null.string != NULL)
-    return &st->null;
-
-  /* Allocate memory for the new string and its associated information.  */
-  newstr = newstring (st, str, len);
-
-  /* Search in the array for the place to insert the string.  If there
-     is no string with matching prefix and no string with matching
-     leading substring, create a new entry.  */
-  sep = searchstring (&st->root, newstr);
-  if (*sep != newstr)
-    {
-      /* This is not the same entry.  This means we have a prefix match.  */
-      if ((*sep)->len > newstr->len)
-	{
-	  struct Ebl_GStrent *subs;
-
-	  /* Check whether we already know this string.  */
-	  for (subs = (*sep)->next; subs != NULL; subs = subs->next)
-	    if (subs->len == newstr->len)
-	      {
-		/* We have an exact match with a substring.  Free the memory
-		   we allocated.  */
-		st->left += (st->backp - (char *) newstr) * st->width;
-		st->backp = (char *) newstr;
-
-		return subs;
-	      }
-
-	  /* We have a new substring.  This means we don't need the reverse
-	     string of this entry anymore.  */
-	  st->backp -= newstr->len;
-	  st->left += newstr->len;
-
-	  newstr->next = (*sep)->next;
-	  (*sep)->next = newstr;
-	}
-      else if ((*sep)->len != newstr->len)
-	{
-	  /* When we get here it means that the string we are about to
-	     add has a common prefix with a string we already have but
-	     it is longer.  In this case we have to put it first.  */
-	  st->total += newstr->len - (*sep)->len;
-	  newstr->next = *sep;
-	  newstr->left = (*sep)->left;
-	  newstr->right = (*sep)->right;
-	  *sep = newstr;
-	}
-      else
-	{
-	  /* We have an exact match.  Free the memory we allocated.  */
-	  st->left += (st->backp - (char *) newstr) * st->width;
-	  st->backp = (char *) newstr;
-
-	  newstr = *sep;
-	}
-    }
-  else
-    st->total += newstr->len;
-
-  return newstr;
-}
-
-
-static void
-copystrings (struct Ebl_GStrent *nodep, char **freep, size_t *offsetp)
-{
-  struct Ebl_GStrent *subs;
-
-  if (nodep->left != NULL)
-    copystrings (nodep->left, freep, offsetp);
-
-  /* Process the current node.  */
-  nodep->offset = *offsetp;
-  *freep = (char *) mempcpy (*freep, nodep->string, nodep->len * nodep->width);
-  *offsetp += nodep->len * nodep->width;
-
-  for (subs = nodep->next; subs != NULL; subs = subs->next)
-    {
-      assert (subs->len < nodep->len);
-      subs->offset = nodep->offset + (nodep->len - subs->len) * nodep->width;
-      assert (subs->offset != 0 || subs->string[0] == '\0');
-    }
-
-  if (nodep->right != NULL)
-    copystrings (nodep->right, freep, offsetp);
-}
-
-
-void
-ebl_gstrtabfinalize (struct Ebl_GStrtab *st, Elf_Data *data)
-{
-  size_t copylen;
-  char *endp;
-  size_t nulllen = st->nullstr ? st->width : 0;
-
-  /* Fill in the information.  */
-  data->d_buf = malloc (st->total + nulllen);
-  if (data->d_buf == NULL)
-    abort ();
-
-  /* The first byte must always be zero if we created the table with a
-     null string.  */
-  if (st->nullstr)
-    memset (data->d_buf, '\0', st->width);
-
-  data->d_type = ELF_T_BYTE;
-  data->d_size = st->total + nulllen;
-  data->d_off = 0;
-  data->d_align = 1;
-  data->d_version = EV_CURRENT;
-
-  /* Now run through the tree and add all the string while also updating
-     the offset members of the elfstrent records.  */
-  endp = (char *) data->d_buf + nulllen;
-  copylen = nulllen;
-  copystrings (st->root, &endp, &copylen);
-  assert (copylen == st->total * st->width + nulllen);
-}
-
-
-size_t
-ebl_gstrtaboffset (struct Ebl_GStrent *se)
-{
-  return se->offset;
-}
diff --git a/libebl/eblobjecttypename.c b/libebl/eblobjecttypename.c
deleted file mode 100644
index b0fd372..0000000
--- a/libebl/eblobjecttypename.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Return object file type name.
-   Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of either
-
-     * the GNU Lesser General Public License as published by the Free
-       Software Foundation; either version 3 of the License, or (at
-       your option) any later version
-
-   or
-
-     * the GNU General Public License as published by the Free
-       Software Foundation; either version 2 of the License, or (at
-       your option) any later version
-
-   or both in parallel, as here.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received copies of the GNU General Public License and
-   the GNU Lesser General Public License along with this program.  If
-   not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <stdio.h>
-#include <libeblP.h>
-
-
-const char *
-ebl_object_type_name (Ebl *ebl, int object, char *buf, size_t len)
-{
-  const char *res;
-
-  res = ebl != NULL ? ebl->object_type_name (object, buf, len) : NULL;
-  if (res == NULL)
-    {
-      /* Handle OS-specific section names.  */
-      if (object >= ET_LOOS && object <= ET_HIOS)
-	snprintf (buf, len, "LOOS+%x", object - ET_LOOS);
-      /* Handle processor-specific section names.  */
-      else if (object >= ET_LOPROC && object <= ET_HIPROC)
-	snprintf (buf, len, "LOPROC+%x", object - ET_LOPROC);
-      else
-	snprintf (buf, len, "%s: %d", gettext ("<unknown>"), object);
-
-      res = buf;
-    }
-
-  return res;
-}
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 16ec1c4..aa75b95 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -1,5 +1,5 @@
 /* Generate ELF backend handle.
-   Copyright (C) 2000-2015 Red Hat, Inc.
+   Copyright (C) 2000-2016 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -140,8 +140,6 @@ static const struct
 #define MAX_PREFIX_LEN 16
 
 /* Default callbacks.  Mostly they just return the error value.  */
-static const char *default_object_type_name (int ignore, char *buf,
-					     size_t len);
 static const char *default_reloc_type_name (int ignore, char *buf, size_t len);
 static bool default_reloc_type_check (int ignore);
 static bool default_reloc_valid_use (Elf *elf, int ignore);
@@ -163,7 +161,6 @@ static const char *default_symbol_binding_name (int ignore, char *buf,
 static const char *default_dynamic_tag_name (int64_t ignore, char *buf,
 					     size_t len);
 static bool default_dynamic_tag_check (int64_t ignore);
-static GElf_Word default_sh_flags_combine (GElf_Word flags1, GElf_Word flags2);
 static const char *default_osabi_name (int ignore, char *buf, size_t len);
 static void default_destr (struct ebl *ignore);
 static const char *default_core_note_type_name (uint32_t, char *buf,
@@ -210,7 +207,6 @@ static int default_abi_cfi (Ebl *ebl, Dwarf_CIE *abi_info);
 static void
 fill_defaults (Ebl *result)
 {
-  result->object_type_name = default_object_type_name;
   result->reloc_type_name = default_reloc_type_name;
   result->reloc_type_check = default_reloc_type_check;
   result->reloc_valid_use = default_reloc_valid_use;
@@ -227,7 +223,6 @@ fill_defaults (Ebl *result)
   result->symbol_binding_name = default_symbol_binding_name;
   result->dynamic_tag_name = default_dynamic_tag_name;
   result->dynamic_tag_check = default_dynamic_tag_check;
-  result->sh_flags_combine = default_sh_flags_combine;
   result->osabi_name = default_osabi_name;
   result->core_note_type_name = default_core_note_type_name;
   result->object_note_type_name = default_object_note_type_name;
@@ -431,14 +426,6 @@ ebl_openbackend_emulation (const char *emulation)
 
 /* Default callbacks.  Mostly they just return the error value.  */
 static const char *
-default_object_type_name (int ignore __attribute__ ((unused)),
-			  char *buf __attribute__ ((unused)),
-			  size_t len __attribute__ ((unused)))
-{
-  return NULL;
-}
-
-static const char *
 default_reloc_type_name (int ignore __attribute__ ((unused)),
 			 char *buf __attribute__ ((unused)),
 			 size_t len __attribute__ ((unused)))
@@ -555,12 +542,6 @@ default_dynamic_tag_check (int64_t ignore __attribute__ ((unused)))
   return false;
 }
 
-static GElf_Word
-default_sh_flags_combine (GElf_Word flags1, GElf_Word flags2)
-{
-  return SH_FLAGS_COMBINE (flags1, flags2);
-}
-
 static void
 default_destr (struct ebl *ignore __attribute__ ((unused)))
 {
diff --git a/libebl/eblshflagscombine.c b/libebl/eblshflagscombine.c
deleted file mode 100644
index 4deaaaa..0000000
--- a/libebl/eblshflagscombine.c
+++ /dev/null
@@ -1,41 +0,0 @@
-/* Return combines section header flags value.
-   Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of either
-
-     * the GNU Lesser General Public License as published by the Free
-       Software Foundation; either version 3 of the License, or (at
-       your option) any later version
-
-   or
-
-     * the GNU General Public License as published by the Free
-       Software Foundation; either version 2 of the License, or (at
-       your option) any later version
-
-   or both in parallel, as here.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received copies of the GNU General Public License and
-   the GNU Lesser General Public License along with this program.  If
-   not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <libeblP.h>
-
-
-GElf_Word
-ebl_sh_flags_combine (Ebl *ebl, GElf_Word flags1, GElf_Word flags2)
-{
-  return ebl->sh_flags_combine (flags1, flags2);
-}
diff --git a/libebl/eblwstrtab.c b/libebl/eblwstrtab.c
deleted file mode 100644
index 08e0ba7..0000000
--- a/libebl/eblwstrtab.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/* ELF string table handling.
-   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of either
-
-     * the GNU Lesser General Public License as published by the Free
-       Software Foundation; either version 3 of the License, or (at
-       your option) any later version
-
-   or
-
-     * the GNU General Public License as published by the Free
-       Software Foundation; either version 2 of the License, or (at
-       your option) any later version
-
-   or both in parallel, as here.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received copies of the GNU General Public License and
-   the GNU Lesser General Public License along with this program.  If
-   not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <inttypes.h>
-#include <libelf.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <wchar.h>
-#include <sys/param.h>
-
-#include "libebl.h"
-#include <system.h>
-
-#ifndef MIN
-# define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-
-struct Ebl_WStrent
-{
-  const wchar_t *string;
-  size_t len;
-  struct Ebl_WStrent *next;
-  struct Ebl_WStrent *left;
-  struct Ebl_WStrent *right;
-  size_t offset;
-  wchar_t reverse[0];
-};
-
-
-struct memoryblock
-{
-  struct memoryblock *next;
-  char memory[0];
-};
-
-
-struct Ebl_WStrtab
-{
-  struct Ebl_WStrent *root;
-  struct memoryblock *memory;
-  char *backp;
-  size_t left;
-  size_t total;
-  bool nullstr;
-
-  struct Ebl_WStrent null;
-};
-
-
-/* Cache for the pagesize.  We correct this value a bit so that `malloc'
-   is not allocating more than a page.  */
-static size_t ps;
-
-
-struct Ebl_WStrtab *
-ebl_wstrtabinit (bool nullstr)
-{
-  struct Ebl_WStrtab *ret;
-
-  if (ps == 0)
-    {
-      ps = sysconf (_SC_PAGESIZE) - 2 * sizeof (void *);
-      assert (sizeof (struct memoryblock) < ps);
-    }
-
-  ret = (struct Ebl_WStrtab *) calloc (1, sizeof (struct Ebl_WStrtab));
-  if (ret != NULL)
-    {
-      ret->nullstr = nullstr;
-      if (nullstr)
-	{
-	  ret->null.len = 1;
-	  ret->null.string = L"";
-	}
-    }
-  return ret;
-}
-
-
-static int
-morememory (struct Ebl_WStrtab *st, size_t len)
-{
-  struct memoryblock *newmem;
-
-  if (len < ps)
-    len = ps;
-  newmem = (struct memoryblock *) malloc (len);
-  if (newmem == NULL)
-    return 1;
-
-  newmem->next = st->memory;
-  st->memory = newmem;
-  st->backp = newmem->memory;
-  st->left = len - offsetof (struct memoryblock, memory);
-
-  return 0;
-}
-
-
-void
-ebl_wstrtabfree (struct Ebl_WStrtab *st)
-{
-  struct memoryblock *mb = st->memory;
-
-  while (mb != NULL)
-    {
-      void *old = mb;
-      mb = mb->next;
-      free (old);
-    }
-
-  free (st);
-}
-
-
-static struct Ebl_WStrent *
-newstring (struct Ebl_WStrtab *st, const wchar_t *str, size_t len)
-{
-  struct Ebl_WStrent *newstr;
-  size_t align;
-  int i;
-
-  /* Compute the amount of padding needed to make the structure aligned.  */
-  align = ((__alignof__ (struct Ebl_WStrent)
-	    - (((uintptr_t) st->backp)
-	       & (__alignof__ (struct Ebl_WStrent) - 1)))
-	   & (__alignof__ (struct Ebl_WStrent) - 1));
-
-  /* Make sure there is enough room in the memory block.  */
-  if (st->left < align + sizeof (struct Ebl_WStrent) + len * sizeof (wchar_t))
-    {
-      if (morememory (st,
-		      sizeof (struct Ebl_WStrent) + len * sizeof (wchar_t)))
-	return NULL;
-
-      align = 0;
-    }
-
-  /* Create the reserved string.  */
-  newstr = (struct Ebl_WStrent *) (st->backp + align);
-  newstr->string = str;
-  newstr->len = len;
-  newstr->next = NULL;
-  newstr->left = NULL;
-  newstr->right = NULL;
-  newstr->offset = 0;
-  for (i = len - 2; i >= 0; --i)
-    newstr->reverse[i] = str[len - 2 - i];
-  newstr->reverse[len - 1] = L'\0';
-  st->backp += align + sizeof (struct Ebl_WStrent) + len * sizeof (wchar_t);
-  st->left -= align + sizeof (struct Ebl_WStrent) + len * sizeof (wchar_t);
-
-  return newstr;
-}
-
-
-/* XXX This function should definitely be rewritten to use a balancing
-   tree algorith (AVL, red-black trees).  For now a simple, correct
-   implementation is enough.  */
-static struct Ebl_WStrent **
-searchstring (struct Ebl_WStrent **sep, struct Ebl_WStrent *newstr)
-{
-  int cmpres;
-
-  /* More strings?  */
-  if (*sep == NULL)
-    {
-      *sep = newstr;
-      return sep;
-    }
-
-  /* Compare the strings.  */
-  cmpres = wmemcmp ((*sep)->reverse, newstr->reverse,
-		    MIN ((*sep)->len, newstr->len) - 1);
-  if (cmpres == 0)
-    /* We found a matching string.  */
-    return sep;
-  else if (cmpres > 0)
-    return searchstring (&(*sep)->left, newstr);
-  else
-    return searchstring (&(*sep)->right, newstr);
-}
-
-
-/* Add new string.  The actual string is assumed to be permanent.  */
-struct Ebl_WStrent *
-ebl_wstrtabadd (struct Ebl_WStrtab *st, const wchar_t *str, size_t len)
-{
-  struct Ebl_WStrent *newstr;
-  struct Ebl_WStrent **sep;
-
-  /* Compute the string length if the caller doesn't know it.  */
-  if (len == 0)
-    len = wcslen (str) + 1;
-
-  /* Make sure all "" strings get offset 0 but only if the table was
-     created with a special null entry in mind.  */
-  if (len == 1 && st->null.string != NULL)
-    return &st->null;
-
-  /* Allocate memory for the new string and its associated information.  */
-  newstr = newstring (st, str, len);
-  if (newstr == NULL)
-    return NULL;
-
-  /* Search in the array for the place to insert the string.  If there
-     is no string with matching prefix and no string with matching
-     leading substring, create a new entry.  */
-  sep = searchstring (&st->root, newstr);
-  if (*sep != newstr)
-    {
-      /* This is not the same entry.  This means we have a prefix match.  */
-      if ((*sep)->len > newstr->len)
-	{
-	  struct Ebl_WStrent *subs;
-
-	  /* Check whether we already know this string.  */
-	  for (subs = (*sep)->next; subs != NULL; subs = subs->next)
-	    if (subs->len == newstr->len)
-	      {
-		/* We have an exact match with a substring.  Free the memory
-		   we allocated.  */
-		st->left += st->backp - (char *) newstr;
-		st->backp = (char *) newstr;
-
-		return subs;
-	      }
-
-	  /* We have a new substring.  This means we don't need the reverse
-	     string of this entry anymore.  */
-	  st->backp -= newstr->len;
-	  st->left += newstr->len;
-
-	  newstr->next = (*sep)->next;
-	  (*sep)->next = newstr;
-	}
-      else if ((*sep)->len != newstr->len)
-	{
-	  /* When we get here it means that the string we are about to
-	     add has a common prefix with a string we already have but
-	     it is longer.  In this case we have to put it first.  */
-	  st->total += newstr->len - (*sep)->len;
-	  newstr->next = *sep;
-	  newstr->left = (*sep)->left;
-	  newstr->right = (*sep)->right;
-	  *sep = newstr;
-	}
-      else
-	{
-	  /* We have an exact match.  Free the memory we allocated.  */
-	  st->left += st->backp - (char *) newstr;
-	  st->backp = (char *) newstr;
-
-	  newstr = *sep;
-	}
-    }
-  else
-    st->total += newstr->len;
-
-  return newstr;
-}
-
-
-static void
-copystrings (struct Ebl_WStrent *nodep, wchar_t **freep, size_t *offsetp)
-{
-  struct Ebl_WStrent *subs;
-
-  if (nodep->left != NULL)
-    copystrings (nodep->left, freep, offsetp);
-
-  /* Process the current node.  */
-  nodep->offset = *offsetp;
-  *freep = wmempcpy (*freep, nodep->string, nodep->len);
-  *offsetp += nodep->len * sizeof (wchar_t);
-
-  for (subs = nodep->next; subs != NULL; subs = subs->next)
-    {
-      assert (subs->len < nodep->len);
-      subs->offset = nodep->offset + nodep->len - subs->len;
-      assert (subs->offset != 0 || subs->string[0] == '\0');
-    }
-
-  if (nodep->right != NULL)
-    copystrings (nodep->right, freep, offsetp);
-}
-
-
-void
-ebl_wstrtabfinalize (struct Ebl_WStrtab *st, Elf_Data *data)
-{
-  size_t copylen;
-  wchar_t *endp;
-  size_t nulllen = st->nullstr ? 1 : 0;
-
-  /* Fill in the information.  */
-  data->d_buf = malloc ((st->total + nulllen) * sizeof (wchar_t));
-  if (data->d_buf == NULL)
-    abort ();
-
-  /* The first byte must always be zero if we created the table with a
-     null string.  */
-  if (st->nullstr)
-    *((wchar_t *) data->d_buf) = L'\0';
-
-  data->d_type = ELF_T_BYTE;
-  data->d_size = st->total + nulllen;
-  data->d_off = 0;
-  data->d_align = 1;
-  data->d_version = EV_CURRENT;
-
-  /* Now run through the tree and add all the string while also updating
-     the offset members of the elfstrent records.  */
-  endp = (wchar_t *) data->d_buf + nulllen;
-  copylen = sizeof (wchar_t) * nulllen;
-  copystrings (st->root, &endp, &copylen);
-  assert (copylen == (st->total + nulllen) * sizeof (wchar_t));
-}
-
-
-size_t
-ebl_wstrtaboffset (struct Ebl_WStrent *se)
-{
-  return se->offset;
-}
diff --git a/libebl/libebl.h b/libebl/libebl.h
index efcb6d6..cef7157 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -1,5 +1,5 @@
 /* Interface for libebl.
-   Copyright (C) 2000-2010, 2013, 2014, 2015 Red Hat, Inc.
+   Copyright (C) 2000-2010, 2013, 2014, 2015, 2016 Red Hat, Inc.
    This file is part of elfutils.
 
    This file is free software; you can redistribute it and/or modify
@@ -89,10 +89,6 @@ extern int ebl_get_elfdata (Ebl *ebl) __attribute__ ((__pure__));
 extern const char *ebl_backend_name (Ebl *ebl);
 
 /* Return relocation type name.  */
-extern const char *ebl_object_type_name (Ebl *ebl, int object,
-					 char *buf, size_t len);
-
-/* Return relocation type name.  */
 extern const char *ebl_reloc_type_name (Ebl *ebl, int reloc,
 					char *buf, size_t len);
 
@@ -163,10 +159,6 @@ extern bool ebl_check_special_symbol (Ebl *ebl, GElf_Ehdr *ehdr,
 /* Check whether only valid bits are set on the st_other symbol flag.  */
 extern bool ebl_check_st_other_bits (Ebl *ebl, unsigned char st_other);
 
-/* Return combined section header flags value.  */
-extern GElf_Word ebl_sh_flags_combine (Ebl *ebl, GElf_Word flags1,
-				       GElf_Word flags2);
-
 /* Return symbolic representation of OS ABI.  */
 extern const char *ebl_osabi_name (Ebl *ebl, int osabi, char *buf, size_t len);
 
@@ -320,50 +312,6 @@ extern size_t ebl_strtaboffset (struct Ebl_Strent *se);
 extern const char *ebl_string (struct Ebl_Strent *se);
 
 
-/* ELF wide char string table handling.  */
-struct Ebl_WStrtab;
-struct Ebl_WStrent;
-
-/* Create new ELF wide char string table object in memory.  */
-extern struct Ebl_WStrtab *ebl_wstrtabinit (bool nullstr);
-
-/* Free resources allocated for ELF wide char string table ST.  */
-extern void ebl_wstrtabfree (struct Ebl_WStrtab *st);
-
-/* Add string STR (length LEN is != 0) to ELF string table ST.  */
-extern struct Ebl_WStrent *ebl_wstrtabadd (struct Ebl_WStrtab *st,
-					   const wchar_t *str, size_t len);
-
-/* Finalize string table ST and store size and memory location information
-   in DATA.  */
-extern void ebl_wstrtabfinalize (struct Ebl_WStrtab *st, Elf_Data *data);
-
-/* Get offset in wide char string table for string associated with SE.  */
-extern size_t ebl_wstrtaboffset (struct Ebl_WStrent *se);
-
-
-/* Generic string table handling.  */
-struct Ebl_GStrtab;
-struct Ebl_GStrent;
-
-/* Create new string table object in memory.  */
-extern struct Ebl_GStrtab *ebl_gstrtabinit (unsigned int width, bool nullstr);
-
-/* Free resources allocated for string table ST.  */
-extern void ebl_gstrtabfree (struct Ebl_GStrtab *st);
-
-/* Add string STR (length LEN is != 0) to string table ST.  */
-extern struct Ebl_GStrent *ebl_gstrtabadd (struct Ebl_GStrtab *st,
-					   const char *str, size_t len);
-
-/* Finalize string table ST and store size and memory location information
-   in DATA.  */
-extern void ebl_gstrtabfinalize (struct Ebl_GStrtab *st, Elf_Data *data);
-
-/* Get offset in wide char string table for string associated with SE.  */
-extern size_t ebl_gstrtaboffset (struct Ebl_GStrent *se);
-
-
 /* Register map info. */
 typedef struct
 {
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 82a2a9f..721beb4 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,3 +1,8 @@
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-knowledge.h (SH_FLAGS_COMBINE): Removed.
+	(SH_FLAGS_IMPORTANT): Likewise.
+
 2016-06-24  John Ogness  <john.ogness@linutronix.de>
 
 	* elf32_updatenull.c (updatenull_wrlock): Find first section.
diff --git a/libelf/elf-knowledge.h b/libelf/elf-knowledge.h
index 24534b3..64f5887 100644
--- a/libelf/elf-knowledge.h
+++ b/libelf/elf-knowledge.h
@@ -1,5 +1,5 @@
 /* Accumulation of various pieces of knowledge about ELF.
-   Copyright (C) 2000-2012, 2014 Red Hat, Inc.
+   Copyright (C) 2000-2012, 2014, 2016 Red Hat, Inc.
    This file is part of elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
 
@@ -62,30 +62,6 @@
    || ((Shdr)->sh_flags & SHF_INFO_LINK) != 0)
 
 
-/* When combining ELF section flags we must distinguish two kinds:
-
-   - flags which cause problem if not added to the result even if not
-     present in all input sections
-
-   - flags which cause problem if added to the result if not present
-     in all input sections
-
-   The following definition is for the general case.  There might be
-   machine specific extensions.  */
-#define SH_FLAGS_COMBINE(Flags1, Flags2) \
-  (((Flags1 | Flags2)							      \
-    & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_LINK_ORDER		      \
-       | SHF_OS_NONCONFORMING | SHF_GROUP))				      \
-   | (Flags1 & Flags2 & (SHF_MERGE | SHF_STRINGS | SHF_INFO_LINK)))
-
-/* Similar macro: return the bits of the flags which necessarily must
-   match if two sections are automatically combined.  Sections still
-   can be forcefully combined in which case SH_FLAGS_COMBINE can be
-   used to determine the combined flags.  */
-#define SH_FLAGS_IMPORTANT(Flags) \
-  ((Flags) & ~((GElf_Xword) 0 | SHF_LINK_ORDER | SHF_OS_NONCONFORMING))
-
-
 /* Size of an entry in the hash table.  The ELF specification says all
    entries are regardless of platform 32-bits in size.  Early 64-bit
    ports (namely Alpha for Linux) got this wrong.  The wording was not
diff --git a/po/ChangeLog b/po/ChangeLog
index c83d53b..6e9900c 100644
--- a/po/ChangeLog
+++ b/po/ChangeLog
@@ -1,3 +1,8 @@
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* po/POTFILES.in: Removed libebl/eblobjecttypename.c,
+	src/i386_ld.c, src/ld.c, src/ldgeneric.c and src/ldscript.y.
+
 2016-03-31  Mark Wielaard  <mjw@redhat.com>
 
 	* *.po: Update for 0.166.
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 02433f9..93bcf6e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -13,7 +13,6 @@ libdwfl/libdwflP.h
 libebl/eblbackendname.c
 libebl/eblcorenotetypename.c
 libebl/ebldynamictagname.c
-libebl/eblobjecttypename.c
 libebl/eblobjnote.c
 libebl/eblobjnotetypename.c
 libebl/eblosabiname.c
@@ -32,10 +31,6 @@ src/arlib.c
 src/elfcmp.c
 src/elflint.c
 src/findtextrel.c
-src/i386_ld.c
-src/ld.c
-src/ldgeneric.c
-src/ldscript.y
 src/nm.c
 src/objdump.c
 src/ranlib.c
diff --git a/src/ChangeLog b/src/ChangeLog
index 21fc7d5..143e628 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,27 @@
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32-i386.script, i386_ld.c, ld.c, ld.h, ldgeneric.c, ldlex.l,
+	ldscript.y, libld_elf_i386.map, none_ld.c, sectionhash.c,
+	sectionhash.h, symbolhash.c, symbolhash.h, unaligned.h,
+	versionhash.c, versionhash.h, xelf.h: Removed.
+	* Makefile.am (YACC): Removed.
+	(AM_YFLAGS): Removed.
+	(AM_LFLAGS): Removed.
+	(native_ld): Removed.
+	(base_cpu): Removed.
+	(bin_PROGRAMS): Removed ld.
+	(ld_dsos): Removed.
+	(ld_SOURCES): Removed.
+	(noinst_LIBRARIES): Only libar.a.
+	(EXTRA_DIST): Just arlib.h and debugpred.h.
+	(ld_LDADD): Removed.
+	(ld_LDFLAGS): Removed.
+	(ldlex.o): Removed.
+	(ldscript.h): Removed.
+	(libld*): Removed.
+	(CLEANFILES): Just *.gconv.
+	(MAINTAINERCLEANFILES): Removed.
+
 2016-06-28  Richard Henderson <rth@redhat.com>
 
 	* elflint.c (valid_e_machine): Add EM_BPF.
diff --git a/src/Makefile.am b/src/Makefile.am
index a39df27..6f796b3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to create Makefile.in
 ##
-## Copyright (C) 1996-2014 Red Hat, Inc.
+## Copyright (C) 1996-2014, 2016 Red Hat, Inc.
 ## This file is part of elfutils.
 ##
 ## This file is free software; you can redistribute it and/or modify
@@ -25,46 +25,14 @@ AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
 
 AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw
 
-YACC = @YACC@ -d
-AM_YFLAGS = -pld
-AM_LFLAGS = -Pld -olex.yy.c
-## Uncomment to enable debugging of linker script parser
-##YYDEBUG = -DYYDEBUG=1
-
-native_ld = @native_ld@
-base_cpu = @base_cpu@
-
-bin_PROGRAMS = readelf nm size strip ld elflint findtextrel addr2line \
+bin_PROGRAMS = readelf nm size strip elflint findtextrel addr2line \
 	       elfcmp objdump ranlib strings ar unstrip stack elfcompress
 
-
-ld_dsos = libld_elf_i386_pic.a
-if NATIVE_LD
-noinst_LIBRARIES = libld_elf.a libar.a
-native_ld_cflags = -DBASE_ELF_NAME=elf_$(base_cpu)
-else
-noinst_LIBRARIES = libld_elf.a libar.a $(ld_dsos)
-noinst_PROGRAMS = $(ld_dsos:_pic.a=.so)
-endif
-if NEVER
-# We never build this library but we need to get the dependency files
-# of all the linker backends that might be used in a non-generic linker.
-noinst_LIBRARIES += libdummy.a
-libdummy_a_SOURCES = i386_ld.c
-endif
-
-
-ld_SOURCES = ld.c ldgeneric.c ldlex.l ldscript.y symbolhash.c sectionhash.c \
-	     versionhash.c
+noinst_LIBRARIES = libar.a
 
 libar_a_SOURCES = arlib.c arlib2.c arlib-argp.c
 
-noinst_HEADERS = ld.h symbolhash.h sectionhash.h versionhash.h \
-		 ldscript.h xelf.h unaligned.h
-
-EXTRA_DIST = elf32-i386.script libld_elf_i386.map $(ld_modules) arlib.h \
-	     debugpred.h
-ld_modules = i386_ld.c
+EXTRA_DIST = arlib.h debugpred.h
 
 bin_SCRIPTS = make-debug-archive
 EXTRA_DIST += make-debug-archive.in
@@ -86,11 +54,6 @@ if DEMANGLE
 demanglelib = -lstdc++
 endif
 
-# XXX While the file is not finished, don't warn about this
-ldgeneric_no_Wunused = yes
-ldgeneric_no_Wstack_usage = yes
-ldlex_no_Wstack_usage = yes
-
 # Bad, bad stack usage...
 readelf_no_Wstack_usage = yes
 nm_no_Wstack_usage = yes
@@ -109,12 +72,6 @@ nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl \
 	   $(demanglelib)
 size_LDADD = $(libelf) $(libeu) $(argp_LDADD)
 strip_LDADD = $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
-ld_LDADD = $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
-if NATIVE_LD
-# -ldl is always needed for libebl.
-ld_LDADD += libld_elf.a
-endif
-ld_LDFLAGS = -rdynamic
 elflint_LDADD  = $(libebl) $(libelf) $(libeu) $(argp_LDADD) -ldl
 findtextrel_LDADD = $(libdw) $(libelf) $(argp_LDADD)
 addr2line_LDADD = $(libdw) $(libelf) $(argp_LDADD) $(demanglelib)
@@ -127,31 +84,6 @@ unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) -ldl
 stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) -ldl $(demanglelib)
 elfcompress_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
 
-ldlex.o: ldscript.c
-ldlex_no_Werror = yes
-ldscript.h: ldscript.c
-
-if NATIVE_LD
-# Machine-specific linker code.
-libld_elf_a_SOURCES := $(base_cpu)_ld.c
-else
-libld_elf_i386_pic_a_SOURCES =
-am_libld_elf_i386_pic_a_OBJECTS = i386_ld.os
-
-libld_elf_i386_so_SOURCES =
-libld_elf_i386.so: libld_elf_i386_pic.a libld_elf_i386.map
-	$(AM_V_CCLD)$(LINK) -shared -o $@ -Wl,--whole-archive,$<,--no-whole-archive \
-		$(libelf) $(libeu) \
-		-Wl,--version-script,$(srcdir)/libld_elf_i386.map
-	@$(textrel_check)
-endif
-
-# Special rule to make it possible to define libld_elf_a_SOURCES as we do.
-# Otherwise make would complain.
-.deps/none_ld.Po: none_ld.os
-	@-:
-
-
 installcheck-binPROGRAMS: $(bin_PROGRAMS)
 	bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
 	  case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
@@ -168,10 +100,7 @@ installcheck-binPROGRAMS: $(bin_PROGRAMS)
 	  done; \
 	done; rm -f c$${pid}_.???; exit $$bad
 
-CLEANFILES += none_ld.os $(ld_modules:.c=.os) *.gconv
-
-MAINTAINERCLEANFILES = ldlex.c ldscript.c ldscript.h
-
+CLEANFILES += *.gconv
 
 make-debug-archive: $(srcdir)/make-debug-archive.in
 	$(AM_V_GEN)UNSTRIP=$(bindir)/`echo unstrip | sed '$(transform)'`; \
diff --git a/src/elf32-i386.script b/src/elf32-i386.script
deleted file mode 100644
index 2083278..0000000
--- a/src/elf32-i386.script
+++ /dev/null
@@ -1,229 +0,0 @@
-ENTRY(_start);
-
-SEARCH_DIR(/lib);
-SEARCH_DIR(/usr/lib);
-SEARCH_DIR(/usr/local/lib);
-SEARCH_DIR(/usr/i686-pc-linux-gnu/lib);
-
-INTERP(/lib/ld-linux.so.2);
-
-PAGESIZE(4k);
-
-SEGMENT [RX]
-{
-#ifdef SHARED
-  . = SIZEOF_HEADERS;
-#else
-  . = 0x08048000 + SIZEOF_HEADERS;
-#endif
-
-  .interp;
-  .note.ABI-tag;
-  .note.gnu.build-id;
-  .hash;
-  .gnu.hash;
-  .dynsym;
-  .dynstr;
-  .gnu.version;
-  .gnu.version_d;
-  .gnu.version_r;
-  .rel.dyn;
-  .rel.plt;
-  .init { KEEP (*(.init)) }
-  .plt;
-  .text
-  {
-    *(.text)
-    *(.text.*)
-    *(.stub)
-    *(.gnu.warning)
-    *(.gnu.linkonce.t.*)
-  }
-  .fini { KEEP (*(.fini)) }
-  PROVIDE (__etext = .);
-  PROVIDE (_etext = .);
-  PROVIDE (etext = .);
-  .rodata
-    {
-      *(.rodata)
-      *(.rodata.*)
-      *(.gnu.linkonce.r.*)
-    }
-  .rodata1;
-  .eh_frame_hdr;
-  . = ALIGN(32 / 8);
-  PROVIDE (__preinit_array_start = .);
-  .preinit_array
-    {
-      *(.preinit_array)
-    }
-  PROVIDE (__preinit_array_end = .);
-  PROVIDE (__init_array_start = .);
-  .init_array
-    {
-      *(.init_array)
-    }
-  PROVIDE (__init_array_end = .);
-  PROVIDE (__fini_array_start = .);
-  .fini_array
-    {
-      *(.fini_array)
-    }
-  PROVIDE (__fini_array_end = .);
-}
-
-SEGMENT [RW]
-{
-  .sdata2
-    {
-      *(.sdata2)
-      *(.sdata2.*)
-      *(.gnu.linkonce.s2.*)
-    }
-  .sbss2
-    {
-      *(.sbss2)
-      *(.sbss2.*)
-      *(.gnu.linkonce.sb2.*)
-    }
-  /* Adjust the address for the data segment.  We want to adjust up to
-     the same address within the page on the next page up.  */
-  . = ALIGN(PAGESIZE) + (. & (PAGESIZE - 1));
-  .eh_frame
-    {
-      KEEP (*(.eh_frame))
-    }
-  .gcc_except_table;
-  .tdata
-    {
-      *(.tdata)
-      *(.tdata.*)
-      *(.gnu.linkone.td.*)
-    }
-  .tbss
-    {
-      *(.tbss)
-      *(.tbss.*)
-      *(.gnu.linkone.tb.*)
-      *(.tcommon)
-    }
-  .ctors
-    {
-      /* gcc uses crtbegin.o to find the start of
-         the constructors, so we make sure it is
-          first.  Because this is a wildcard, it
-         doesn't matter if the user does not
-         actually link against crtbegin.o; the
-         linker won't look for a file to match a
-         wildcard.  The wildcard also means that it
-         doesn't matter which directory crtbegin.o
-         is in.  */
-      KEEP (*crtbegin.o(.ctors))
-      /* We don't want to include the .ctor section from
-         the crtend.o file until after the sorted ctors.
-         The .ctor section from the crtend file contains the
-         end of ctors marker and it must be last */
-      KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors))
-      KEEP (*(SORT(.ctors.*)))
-      KEEP (*(.ctors))
-    }
-  .dtors
-    {
-      KEEP (*crtbegin.o(.dtors))
-      KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors))
-      KEEP (*(SORT(.dtors.*)))
-      KEEP (*(.dtors))
-    }
-  .jcr;
-  .dynamic;
-  .got;
-  .got.plt;
-  .data
-    {
-      *(.data)
-      *(.data.*)
-      *(.gnu.linkonce.d.*)
-    }
-  /* We want the small data sections together, so single-instruction offsets
-     can access them all, and initialized data all before uninitialized, so
-     we can shorten the on-disk segment size.  */
-  .data1;
-  .sdata
-    {
-      *(.sdata)
-      *(.sdata.*)
-      *(.gnu.linkonce.s.*)
-    }
-  _edata = .;
-  PROVIDE (edata = .);
-  __bss_start = .;
-  .sbss
-    {
-      PROVIDE (__sbss_start = .);
-      PROVIDE (___sbss_start = .);
-      *(.dynsbss)
-      *(.sbss)
-      *(.sbss.*)
-      *(.gnu.linkonce.sb.*)
-      *(.scommon)
-      PROVIDE (__sbss_end = .);
-      PROVIDE (___sbss_end = .);
-    }
-  .bss
-    {
-      *(.dynbss)
-      *(.bss)
-      *(.bss.*)
-      *(.gnu.linkonce.b.*)
-      *(COMMON)
-      /* Align here to ensure that the .bss section occupies space up to
-	 _end.  Align after .bss to ensure correct alignment even if the
-	 .bss section disappears because there are no input sections.  */
-      . = ALIGN(32 / 8);
-    }
-  . = ALIGN(32 / 8);
-  _end = .;
-  PROVIDE (end = .);
-}
-
-SEGMENT []
-{
-  /* Stabs debugging sections.  */
-  .stab;
-  .stabstr;
-  .stab.excl;
-  .stab.exclstr;
-  .stab.index;
-  .stab.indexstr;
-  .comment;
-  /* DWARF debug sections.
-     Symbols in the DWARF debugging sections are relative to the beginning
-     of the section so we begin them at 0.  */
-  /* DWARF 1 */
-  .debug;
-  .line;
-  /* GNU DWARF 1 extensions */
-  .debug_srcinfo;
-  .debug_sfnames;
-  /* DWARF 1.1 and DWARF 2 */
-  .debug_aranges;
-  .debug_pubnames;
-  /* DWARF 2 */
-  .debug_info
-    {
-       *(.debug_info)
-       *(.gnu.linkonce.wi.*)
-    }
-  .debug_abbrev;
-  .debug_line;
-  .debug_frame;
-  .debug_str;
-  .debug_loc;
-  .debug_macinfo;
-  /* SGI/MIPS DWARF 2 extensions */
-  .debug_weaknames;
-  .debug_funcnames;
-  .debug_typenames;
-  .debug_varnames;
-  /* These must appear regardless of  .  */
-}
diff --git a/src/i386_ld.c b/src/i386_ld.c
deleted file mode 100644
index d196177..0000000
--- a/src/i386_ld.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2008 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <error.h>
-#include <libintl.h>
-#include <stdlib.h>
-#include <string.h>
-
-// XXX For debugging
-#include <stdio.h>
-
-#include <system.h>
-#include "ld.h"
-#include "list.h"
-/* x86 is little endian.  */
-#define UNALIGNED_ACCESS_CLASS LITTLE_ENDIAN
-#include "unaligned.h"
-#include "xelf.h"
-
-
-/* The old callbacks.  */
-static int (*old_open_outfile) (struct ld_state *, int, int, int);
-
-
-static int
-elf_i386_open_outfile (struct ld_state *statep,
-		       int machine __attribute__ ((unused)),
-		       int klass __attribute__ ((unused)),
-		       int data __attribute__ ((unused)))
-{
-  /* This backend only handles 32-bit object files.  */
-  /* XXX For now just use the generic backend.  */
-  return old_open_outfile (statep, EM_386, ELFCLASS32, ELFDATA2LSB);
-}
-
-
-/* Process relocations for the output in a relocatable file.  This
-   only means adjusting offset and symbol indices.  */
-static void
-elf_i386_relocate_section (struct ld_state *statep __attribute__ ((unused)),
-			   Elf_Scn *outscn, struct scninfo *firstp,
-			   const Elf32_Word *dblindirect)
-{
-  struct scninfo *runp;
-  Elf_Data *data;
-
-  /* Iterate over all the input sections.  Appropriate data buffers in the
-     output sections were already created.  */
-  runp = firstp;
-  data = NULL;
-  do
-    {
-      Elf_Data *reltgtdata;
-      Elf_Data *insymdata;
-      Elf_Data *inxndxdata = NULL;
-      size_t maxcnt;
-      size_t cnt;
-      const Elf32_Word *symindirect;
-      struct symbol **symref;
-      struct usedfiles *file = runp->fileinfo;
-      XElf_Shdr *shdr = &SCNINFO_SHDR (runp->shdr);
-
-      /* Get the output section data buffer for this input section.  */
-      data = elf_getdata (outscn, data);
-      assert (data != NULL);
-
-      /* Get the data for section in the input file this relocation
-	 section is relocating.  Since these buffers are reused in the
-	 output modifying these buffers has the correct result.  */
-      reltgtdata = elf_getdata (file->scninfo[shdr->sh_info].scn, NULL);
-
-      /* Get the data for the input section symbol table for this
-	 relocation section.  */
-      insymdata = elf_getdata (file->scninfo[shdr->sh_link].scn, NULL);
-      assert (insymdata != NULL);
-
-      /* And the extended section index table.  */
-      inxndxdata = runp->fileinfo->xndxdata;
-
-      /* Number of relocations.  */
-      maxcnt = shdr->sh_size / shdr->sh_entsize;
-
-      /* Array directing local symbol table offsets to output symbol
-	 table offsets.  */
-      symindirect = file->symindirect;
-
-      /* References to the symbol records.  */
-      symref = file->symref;
-
-      /* Iterate over all the relocations in the section.  */
-      for (cnt = 0; cnt < maxcnt; ++cnt)
-	{
-	  XElf_Rel_vardef (rel);
-	  Elf32_Word si;
-	  XElf_Sym_vardef (sym);
-	  Elf32_Word xndx;
-
-	  /* Get the relocation data itself.  x86 uses Rel
-	     relocations.  In case we have to handle Rela as well the
-	     whole loop probably should be duplicated.  */
-	  xelf_getrel (data, cnt, rel);
-	  assert (rel != NULL);
-
-	  /* Compute the symbol index in the output file.  */
-	  si = symindirect[XELF_R_SYM (rel->r_info)];
-	  if (si == 0)
-	    {
-	      /* This happens if the symbol is locally undefined or
-		 superceded by some other definition.  */
-	      assert (symref[XELF_R_SYM (rel->r_info)] != NULL);
-	      si = symref[XELF_R_SYM (rel->r_info)]->outsymidx;
-	    }
-	  /* Take reordering performed to sort the symbol table into
-	     account.  */
-	  si = dblindirect[si];
-
-	  /* Get the symbol table entry.  */
-	  xelf_getsymshndx (insymdata, inxndxdata, XELF_R_SYM (rel->r_info),
-			    sym, xndx);
-	  if (sym->st_shndx != SHN_XINDEX)
-	    xndx = sym->st_shndx;
-	  assert (xndx < SHN_LORESERVE || xndx > SHN_HIRESERVE);
-
-	  /* We fortunately don't have to do much.  The relocations
-	     mostly get only updates of the offset.  Only for a
-	     relocation referring to a section do we have to do
-	     something.  In this case the reference to the sections
-	     has no direct equivalent since the part the input section
-	     contributes need not start at the same offset as in the
-	     input file.  Therefore we have to adjust the addend which
-	     in the case of Rel relocations is in the target section
-	     itself.  */
-	  if (XELF_ST_TYPE (sym->st_info) == STT_SECTION)
-	    {
-	      /* We expect here only R_386_32 relocations.  */
-	      assert (XELF_R_TYPE (rel->r_info) == R_386_32);
-
-	      /* Avoid writing to the section memory if this is
-		 effectively a no-op since it might save a
-		 copy-on-write operation.  */
-	      Elf32_Word toadd = file->scninfo[xndx].offset;
-	      if (toadd != 0)
-		add_4ubyte_unaligned (reltgtdata->d_buf + rel->r_offset,
-				      toadd);
-	    }
-
-	  /* Adjust the offset for the position of the input section
-	     content in the output section.  */
-	  rel->r_offset += file->scninfo[shdr->sh_info].offset;
-
-	  /* And finally adjust the index of the symbol in the output
-	     symbol table.  */
-	  rel->r_info = XELF_R_INFO (si, XELF_R_TYPE (rel->r_info));
-
-	  /* Store the result.  */
-	  (void) xelf_update_rel (data, cnt, rel);
-	}
-
-      runp = runp->next;
-    }
-  while (runp != firstp);
-}
-
-
-/* Each PLT entry has 16 bytes.  We need one entry as overhead for
-   the code to set up the call into the runtime relocation.  */
-#define PLT_ENTRY_SIZE 16
-
-static void
-elf_i386_initialize_plt (struct ld_state *statep, Elf_Scn *scn)
-{
-  Elf_Data *data;
-  XElf_Shdr_vardef (shdr);
-
-  /* Change the entry size in the section header.  */
-  xelf_getshdr (scn, shdr);
-  assert (shdr != NULL);
-  shdr->sh_entsize = PLT_ENTRY_SIZE;
-  (void) xelf_update_shdr (scn, shdr);
-
-  data = elf_newdata (scn);
-  if (data == NULL)
-    error (EXIT_FAILURE, 0, gettext ("cannot allocate PLT section: %s"),
-	   elf_errmsg (-1));
-
-  /* We need one special PLT entry (performing the jump to the runtime
-     relocation routines) and one for each function we call in a DSO.  */
-  data->d_size = (1 + statep->nplt) * PLT_ENTRY_SIZE;
-  data->d_buf = xcalloc (1, data->d_size);
-  assert (data->d_type == ELF_T_BYTE);
-  data->d_off = 0;
-  data->d_align = 8;
-
-  statep->nplt_used = 1;
-}
-
-
-static void
-elf_i386_initialize_pltrel (struct ld_state *statep, Elf_Scn *scn)
-{
-  Elf_Data *data;
-
-  data = elf_newdata (scn);
-  if (data == NULL)
-    error (EXIT_FAILURE, 0, gettext ("cannot allocate PLTREL section: %s"),
-	   elf_errmsg (-1));
-
-  /* One relocation per PLT entry.  */
-  size_t size = statep->nplt * sizeof (Elf32_Rel);
-  data->d_buf = xcalloc (1, size);
-  data->d_type = ELF_T_REL;
-  data->d_size = size;
-  data->d_align = 4;
-  data->d_off = 0;
-}
-
-
-static void
-elf_i386_initialize_got (struct ld_state *statep, Elf_Scn *scn)
-{
-  /* If we come here we better need a GOT.  */
-  assert (statep->ngot != 0);
-
-  Elf_Data *data = elf_newdata (scn);
-  if (data == NULL)
-    error (EXIT_FAILURE, 0, gettext ("cannot allocate GOT section: %s"),
-	   elf_errmsg (-1));
-
-  /* Just a single word per GOT entry is needed.  */
-  size_t size = statep->ngot * sizeof (Elf32_Addr);
-  data->d_buf = xcalloc (1, size);
-  data->d_size = size;
-  data->d_type = ELF_T_WORD;
-  data->d_off = 0;
-  data->d_align = sizeof (Elf32_Addr);
-}
-
-
-static void
-elf_i386_initialize_gotplt (struct ld_state *statep, Elf_Scn *scn)
-{
-  /* If we come here we better need a PLT.  */
-  assert (statep->nplt != 0);
-
-  Elf_Data *data = elf_newdata (scn);
-  if (data == NULL)
-    error (EXIT_FAILURE, 0, gettext ("cannot allocate GOTPLT section: %s"),
-	   elf_errmsg (-1));
-
-  /* We construct the .got.plt section in pieces.  Here we only add the data
-     structures which are used by the PLT.  This includes three reserved
-     entries at the beginning (the first will contain a pointer to the
-     .dynamic section), and one word for each PLT entry.  */
-  size_t size = (3 + statep->nplt) * sizeof (Elf32_Addr);
-  data->d_buf = xcalloc (1, size);
-  data->d_type = ELF_T_WORD;
-  data->d_size = size;
-  data->d_off = 0;
-  data->d_align = sizeof (Elf32_Addr);
-}
-
-
-/* The first entry in an absolute procedure linkage table looks like
-   this.  See the SVR4 ABI i386 supplement to see how this works.  */
-static const unsigned char elf_i386_plt0_entry[PLT_ENTRY_SIZE] =
-{
-  0xff, 0x35,	/* pushl contents of address */
-  0, 0, 0, 0,	/* replaced with address of .got + 4.  */
-  0xff, 0x25,	/* jmp indirect */
-  0, 0, 0, 0,	/* replaced with address of .got + 8.  */
-  0x0f, 0x0b,	/* ud2a, to prevent further decoding.  */
-  0, 0		/* pad out to 16 bytes.  */
-};
-
-/* Type describing the first PLT entry in non-PIC.  */
-struct plt0_entry
-{
-  /* First a 'push' of the second GOT entry.  */
-  unsigned char push_instr[2];
-  uint32_t gotp4_addr;
-  /* Second, a 'jmp indirect' to the third GOT entry.  */
-  unsigned char jmp_instr[2];
-  uint32_t gotp8_addr;
-  /* Padding.  */
-  unsigned char padding[4];
-} __attribute__ ((packed));
-
-/* The first entry in a PIC procedure linkage table look like this.  */
-static const unsigned char elf_i386_pic_plt0_entry[PLT_ENTRY_SIZE] =
-{
-  0xff, 0xb3, 4, 0, 0, 0,	/* pushl 4(%ebx) */
-  0xff, 0xa3, 8, 0, 0, 0,	/* jmp *8(%ebx) */
-  0x0f, 0x0b,			/* ud2a, to prevent further decoding.  */
-  0, 0				/* pad out to 16 bytes.  */
-};
-
-/* Contents of all but the first PLT entry in executable.  */
-static const unsigned char elf_i386_plt_entry[PLT_ENTRY_SIZE] =
-{
-  0xff, 0x25,   /* jmp indirect */
-  0, 0, 0, 0,   /* replaced with address of this symbol in .got.  */
-  0x68,         /* pushl immediate */
-  0, 0, 0, 0,   /* replaced with offset into relocation table.  */
-  0xe9,         /* jmp relative */
-  0, 0, 0, 0    /* replaced with offset to start of .plt.  */
-};
-
-/* Contents of all but the first PLT entry in DSOs.  */
-static const unsigned char elf_i386_pic_plt_entry[PLT_ENTRY_SIZE] =
-{
-  0xff, 0xa3,	/* jmp *offset(%ebx) */
-  0, 0, 0, 0,	/* replaced with offset of this symbol in .got.  */
-  0x68,		/* pushl immediate */
-  0, 0, 0, 0,	/* replaced with offset into relocation table.  */
-  0xe9,		/* jmp relative */
-  0, 0, 0, 0	/* replaced with offset to start of .plt.  */
-};
-
-/* Type describing a PLT entry.  */
-struct plt_entry
-{
-  /* The first instruction is 'jmp indirect' or 'jmp *offset(%ebs)'.  */
-  unsigned char jmp_instr[2];
-  uint32_t offset_got;
-  /* The second instruction is 'push immediate'.  */
-  unsigned char push_instr;
-  uint32_t push_imm;
-  /* Finally a 'jmp relative'.  */
-  unsigned char jmp_instr2;
-  uint32_t plt0_offset;
-} __attribute__ ((packed));
-
-
-static void
-elf_i386_finalize_plt (struct ld_state *statep, size_t nsym,
-		       size_t nsym_local, struct symbol **ndxtosym)
-{
-  if (unlikely (statep->nplt + statep->ngot == 0))
-    /* Nothing to be done.  */
-    return;
-
-  Elf_Scn *scn;
-  XElf_Shdr_vardef (shdr);
-  Elf_Data *data;
-  const bool build_dso = statep->file_type == dso_file_type;
-
-  /* Get the address of the .got.plt section.  */
-  scn = elf_getscn (statep->outelf, statep->gotpltscnidx);
-  xelf_getshdr (scn, shdr);
-  data = elf_getdata (scn, NULL);
-  assert (shdr != NULL && data != NULL);
-  /* The address points to the .got.plt section, not the .got section.  */
-  Elf32_Addr gotaddr = shdr->sh_addr;
-
-  /* Now create the initial values for the .got.plt section.  The
-     first word contains the address of the .dynamic section.  The
-     second and third entry are left empty for use by the dynamic
-     linker.  The following entries are pointers to the instructions
-     following the initial jmp instruction in the corresponding PLT
-     entry.  */
-  xelf_getshdr (elf_getscn (statep->outelf, statep->dynamicscnidx), shdr);
-  assert (shdr != NULL);
-  ((Elf32_Word *) data->d_buf)[0] = shdr->sh_addr;
-
-  /* The PLT contains code which a user of a function jumps to.  The first
-     PLT entry is special, so the first used one has the index 1.  */
-  scn = elf_getscn (statep->outelf, statep->pltscnidx);
-  XElf_Shdr_vardef (pltshdr);
-  xelf_getshdr (scn, pltshdr);
-  assert (pltshdr != NULL);
-
-  Elf_Data *dynsymdata = elf_getdata (elf_getscn (statep->outelf,
-						  statep->dynsymscnidx), NULL);
-  assert (dynsymdata != NULL);
-
-  Elf_Data *symdata = NULL;
-  if (statep->symscnidx != 0)
-    {
-      symdata = elf_getdata (elf_getscn (statep->outelf, statep->symscnidx),
-			     NULL);
-      assert (symdata != NULL);
-    }
-
-  /* Create the .plt section.  */
-  scn = elf_getscn (statep->outelf, statep->pltscnidx);
-  Elf_Data *pltdata = elf_getdata (scn, NULL);
-  assert (pltdata != NULL);
-
-  /* Also create the .rel.plt section data.  It simply means relocations
-     addressing the corresponding entry in the .got.plt section.  The
-     section name is misleading.  */
-  scn = elf_getscn (statep->outelf, statep->pltrelscnidx);
-  xelf_getshdr (scn, shdr);
-  Elf_Data *reldata = elf_getdata (scn, NULL);
-  assert (shdr != NULL && reldata != NULL);
-
-  /* Update the sh_link to point to the section being modified.  We
-     point it here (correctly) to the .got.plt section.  Some linkers
-     (e.g., the GNU binutils linker) point to the .plt section.  This
-     is wrong since the .plt section isn't modified even though the
-     name .rel.plt suggests that this is correct.  */
-  shdr->sh_link = statep->dynsymscnidx;
-  shdr->sh_info = statep->gotpltscnidx;
-  (void) xelf_update_shdr (scn, shdr);
-
-  /* Create the first entry of the .plt section.  */
-  assert (pltdata->d_size >= PLT_ENTRY_SIZE);
-  if (build_dso)
-    /* Copy the entry.  It's complete, no relocation needed.  */
-    memcpy (pltdata->d_buf, elf_i386_pic_plt0_entry, PLT_ENTRY_SIZE);
-  else
-    {
-      /* Copy the skeleton.  */
-      memcpy (pltdata->d_buf, elf_i386_plt0_entry, PLT_ENTRY_SIZE);
-
-      /* And fill in the addresses.  */
-      struct plt0_entry *addr = (struct plt0_entry *) pltdata->d_buf;
-      addr->gotp4_addr = target_bswap_32 (gotaddr + 4);
-      addr->gotp8_addr = target_bswap_32 (gotaddr + 8);
-    }
-
-  /* For DSOs we need GOT offsets, otherwise the GOT address.  */
-  Elf32_Addr gotaddr_off = build_dso ? 0 : gotaddr;
-
-  /* Create the remaining entries.  */
-  const unsigned char *plt_template
-    = build_dso ? elf_i386_pic_plt_entry : elf_i386_plt_entry;
-
-  for (size_t idx = nsym_local; idx < nsym; ++idx)
-    {
-      struct symbol *symbol = ndxtosym[idx];
-      if (symbol == NULL || symbol->type != STT_FUNC
-	  || ndxtosym[idx]->outdynsymidx == 0
-	  // XXX is the following test correct?
-	  || ! ndxtosym[idx]->in_dso)
-	continue;
-
-      size_t pltidx = symbol->merge.value;
-
-      assert (pltidx > 0);
-      assert ((3 + pltidx) * sizeof (Elf32_Word) <= data->d_size);
-
-      /* Address in the PLT.  */
-      Elf32_Addr pltentryaddr = (pltshdr->sh_addr + pltidx * PLT_ENTRY_SIZE);
-
-      /* Point the GOT entry at the PLT entry, after the initial jmp.  */
-      ((Elf32_Word *) data->d_buf)[2 + pltidx] = pltentryaddr + 6;
-
-      /* If the symbol is defined, adjust the address.  */
-      if (((Elf32_Sym *) dynsymdata->d_buf)[ndxtosym[idx]->outdynsymidx].st_shndx != SHN_UNDEF)
-	{
-	  /* The value of the symbol is the address of the corresponding PLT
-	     entry.  Store the address, also for the normal symbol table if
-	     this is necessary.  */
-	  ((Elf32_Sym *) dynsymdata->d_buf)[pltidx].st_value = pltentryaddr;
-
-	  if (symdata != NULL)
- {
-   assert(nsym - statep->nplt + (pltidx - 1) == idx);
-	    ((Elf32_Sym *) symdata->d_buf)[nsym - statep->nplt
-					   + (pltidx - 1)].st_value
-	      = pltentryaddr;
- }
-	}
-
-      /* Copy the PLT entry template.  */
-      assert (pltdata->d_size >= (1 + pltidx) * PLT_ENTRY_SIZE);
-      struct plt_entry *addr = (struct plt_entry *) ((char *) pltdata->d_buf
-						     + (pltidx
-							* PLT_ENTRY_SIZE));
-      memcpy (addr, plt_template, PLT_ENTRY_SIZE);
-
-      /* And once more, fill in the addresses.  First the address of
-	 this symbol in .got.  */
-      addr->offset_got = target_bswap_32 (gotaddr_off
-					  + (2 + pltidx) * sizeof (Elf32_Addr));
-      /* Offset into relocation table.  */
-      addr->push_imm = target_bswap_32 ((pltidx - 1) * sizeof (Elf32_Rel));
-      /* Offset to start of .plt.  */
-      addr->plt0_offset = target_bswap_32 (-(1 + pltidx) * PLT_ENTRY_SIZE);
-
-
-      XElf_Rel_vardef (rel);
-      assert (pltidx * sizeof (Elf32_Rel) <= reldata->d_size);
-      xelf_getrel_ptr (reldata, pltidx - 1, rel);
-      rel->r_offset = gotaddr + (2 + pltidx) * sizeof (Elf32_Addr);
-      /* The symbol table entries for the functions from DSOs are at
-	 the beginning of the symbol table.  */
-      rel->r_info = XELF_R_INFO (ndxtosym[idx]->outdynsymidx, R_386_JMP_SLOT);
-      (void) xelf_update_rel (reldata, pltidx - 1, rel);
-    }
-}
-
-
-static int
-elf_i386_rel_type (struct ld_state *statep __attribute__ ((__unused__)))
-{
-  /* ELF/i386 uses REL.  */
-  return DT_REL;
-}
-
-
-static void
-elf_i386_count_relocations (struct ld_state *statep, struct scninfo *scninfo)
-{
-  /* We go through the list of input sections and count those relocations
-     which are not handled by the linker.  At the same time we have to
-     see how many GOT entries we need and how much .bss space is needed
-     for copy relocations.  */
-  Elf_Data *data = elf_getdata (scninfo->scn, NULL);
-  XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
-  size_t maxcnt = shdr->sh_size / shdr->sh_entsize;
-  size_t relsize = 0;
-  size_t cnt;
-  struct symbol *sym;
-
-  assert (shdr->sh_type == SHT_REL);
-
-  for (cnt = 0; cnt < maxcnt; ++cnt)
-    {
-      XElf_Rel_vardef (rel);
-
-      xelf_getrel (data, cnt, rel);
-      /* XXX Should we complain about failing accesses?  */
-      if (rel != NULL)
-	{
-	  Elf32_Word r_sym = XELF_R_SYM (rel->r_info);
-
-	  /* Symbols in COMDAT group sections which are discarded do
-	     not have to be relocated.  */
-	  if (r_sym >= scninfo->fileinfo->nlocalsymbols
-	      && unlikely (scninfo->fileinfo->symref[r_sym] == NULL))
-	    continue;
-
-	  switch (XELF_R_TYPE (rel->r_info))
-	    {
-	    case R_386_GOT32:
-	      if (! scninfo->fileinfo->symref[r_sym]->defined
-		  || scninfo->fileinfo->symref[r_sym]->in_dso
-		  || statep->file_type == dso_file_type)
-		{
-		  relsize += sizeof (Elf32_Rel);
-		  ++statep->nrel_got;
-		}
-
-	      /* Even if this relocation is not emitted in the output
-		 file it requires a GOT entry.  */
-	      ++statep->ngot;
-
-	      /* FALLTHROUGH */
-
-	    case R_386_GOTOFF:
-	    case R_386_GOTPC:
-	      statep->need_got = true;
-	      break;
-
-	    case R_386_32:
-	    case R_386_PC32:
-	      /* These relocations cause text relocations in DSOs.  */
-	      if (linked_from_dso_p (scninfo, r_sym))
-		{
-		  if (statep->file_type == dso_file_type)
-		    {
-		      relsize += sizeof (Elf32_Rel);
-		      // XXX Do we have to check whether the target
-		      // XXX section is read-only first?
-		      statep->dt_flags |= DF_TEXTREL;
-		    }
-		  else
-		    {
-		      /* Non-function objects from a DSO need to get a
-			 copy relocation.  */
-		      sym = scninfo->fileinfo->symref[r_sym];
-
-		      /* Only do this if we have not requested a copy
-			 relocation already.  */
-		      if (unlikely (sym->type != STT_FUNC) && ! sym->need_copy)
-			{
-			  sym->need_copy = 1;
-			  ++statep->ncopy;
-			  relsize += sizeof (Elf32_Rel);
-			}
-		    }
-		}
-	      else if (statep->file_type == dso_file_type
-		       && XELF_R_TYPE (rel->r_info) == R_386_32)
-		relsize += sizeof (Elf32_Rel);
-
-	      break;
-
-	    case R_386_PLT32:
-	      /* We might need a PLT entry.  But we cannot say for sure
-		 here since one of the symbols might turn up being
-		 defined in the executable (if we create such a thing).
-		 If a DSO is created we still might use a local
-		 definition.
-
-		 If the symbol is not defined and we are not creating
-		 a statically linked binary, then we need in any case
-		 a PLT entry.  */
-	      if (! scninfo->fileinfo->symref[r_sym]->defined
-		  && !statep->statically)
-		{
-		  sym = scninfo->fileinfo->symref[r_sym];
-		  sym->type = STT_FUNC;
-		  sym->in_dso = 1;
-		  sym->defined = 1;
-
-		  /* Remove from the list of unresolved symbols.  */
-		  --statep->nunresolved;
-		  if (! sym->weak)
-		    --statep->nunresolved_nonweak;
-		  CDBL_LIST_DEL (statep->unresolved, sym);
-
-		  /* Add to the list of symbols we expect from a DSO.  */
-		  ++statep->nplt;
-		  ++statep->nfrom_dso;
-		  CDBL_LIST_ADD_REAR (statep->from_dso, sym);
-		}
-	      break;
-
-	    case R_386_TLS_LDO_32:
-	      if (statep->file_type != executable_file_type)
-		abort ();
-	      /* We do not need a relocation in the output file.  */
-	      break;
-
-	    case R_386_TLS_LE:
-	      /* We never need a relocation in the output file.  */
-	      break;
-
-	    case R_386_TLS_IE:
-	      if (statep->file_type == dso_file_type)
-		error (EXIT_FAILURE, 0, gettext ("initial-executable TLS relocation cannot be used "));
-	      if (!scninfo->fileinfo->symref[r_sym]->defined
-		  || scninfo->fileinfo->symref[r_sym]->in_dso)
-		{
-		  abort ();
-		}
-	      break;
-
-	    case R_386_TLS_GD:
-	      if (statep->file_type != executable_file_type
-		  || !scninfo->fileinfo->symref[r_sym]->defined
-		  || scninfo->fileinfo->symref[r_sym]->in_dso)
-		{
-		  abort ();
-		}
-	      break;
-
-	    case R_386_TLS_GOTIE:
-	    case R_386_TLS_LDM:
-	    case R_386_TLS_GD_32:
-	    case R_386_TLS_GD_PUSH:
-	    case R_386_TLS_GD_CALL:
-	    case R_386_TLS_GD_POP:
-	    case R_386_TLS_LDM_32:
-	    case R_386_TLS_LDM_PUSH:
-	    case R_386_TLS_LDM_CALL:
-	    case R_386_TLS_LDM_POP:
-	    case R_386_TLS_IE_32:
-	    case R_386_TLS_LE_32:
-	      /* XXX */
-	      abort ();
-	      break;
-
-	    case R_386_NONE:
-	      /* Nothing to be done.  */
-	      break;
-
-	      /* These relocation should never be generated by an
-		 assembler.  */
-	    case R_386_COPY:
-	    case R_386_GLOB_DAT:
-	    case R_386_JMP_SLOT:
-	    case R_386_RELATIVE:
-	    case R_386_TLS_DTPMOD32:
-	    case R_386_TLS_DTPOFF32:
-	    case R_386_TLS_TPOFF32:
-	      /* Unknown relocation.  */
-	    default:
-	      abort ();
-	    }
-	}
-    }
-
-  scninfo->relsize = relsize;
-}
-
-
-static void
-elf_i386_create_relocations (struct ld_state *statep,
-			     const Elf32_Word *dblindirect __attribute__ ((unused)))
-{
-  /* Get the address of the got section.  */
-  Elf_Scn *pltscn = elf_getscn (statep->outelf, statep->pltscnidx);
-  Elf32_Shdr *shdr = elf32_getshdr (pltscn);
-  assert (shdr != NULL);
-  Elf32_Addr pltaddr = shdr->sh_addr;
-
-  Elf_Scn *gotscn = elf_getscn (statep->outelf, statep->gotscnidx);
-  // XXX Adjust the address, if necessary, for relro
-  Elf_Data *gotdata = NULL;
-  if (statep->need_got)
-    {
-      gotdata = elf_getdata (gotscn, NULL);
-      assert (gotdata != NULL);
-    }
-
-  Elf_Scn *gotpltscn = elf_getscn (statep->outelf, statep->gotpltscnidx);
-  shdr = elf32_getshdr (gotpltscn);
-  assert (shdr != NULL);
-  Elf32_Addr gotaddr = shdr->sh_addr;
-
-  Elf_Scn *reldynscn = elf_getscn (statep->outelf, statep->reldynscnidx);
-  Elf_Data *reldyndata = elf_getdata (reldynscn, NULL);
-  assert (reldyndata != NULL);
-
-  size_t nreldyn = 0;
-  size_t ngotconst = statep->nrel_got;
-
-  struct scninfo *first = statep->rellist->next;
-  struct scninfo *runp = first;
-  do
-    {
-      XElf_Shdr *rshdr = &SCNINFO_SHDR (runp->shdr);
-      Elf_Data *reldata = elf_getdata (runp->scn, NULL);
-      int nrels = rshdr->sh_size / rshdr->sh_entsize;
-
-      /* We will need the following values a couple of times.  Help
-	 the compiler and improve readability.  */
-      struct symbol **symref = runp->fileinfo->symref;
-      struct scninfo *scninfo = runp->fileinfo->scninfo;
-
-      /* This is the offset of the input section we are looking at in
-	 the output file.  */
-      XElf_Addr inscnoffset = scninfo[rshdr->sh_info].offset;
-
-      /* The target section.  We use the data from the input file.  */
-      Elf_Data *data = elf_getdata (scninfo[rshdr->sh_info].scn, NULL);
-
-      /* We cannot handle relocations against merge-able sections.  */
-      assert ((SCNINFO_SHDR (scninfo[rshdr->sh_link].shdr).sh_flags
-	       & SHF_MERGE) == 0);
-
-      /* Cache the access to the symbol table data.  */
-      Elf_Data *symdata = elf_getdata (scninfo[rshdr->sh_link].scn, NULL);
-
-      for (int cnt = 0; cnt < nrels; ++cnt)
-	{
-	  XElf_Rel_vardef (rel);
-	  XElf_Rel *rel2;
-	  xelf_getrel (reldata, cnt, rel);
-	  assert (rel != NULL);
-	  XElf_Addr reladdr = inscnoffset + rel->r_offset;
-	  XElf_Addr value;
-
-	  size_t idx = XELF_R_SYM (rel->r_info);
-	  if (idx < runp->fileinfo->nlocalsymbols)
-	    {
-	      XElf_Sym_vardef (sym);
-	      xelf_getsym (symdata, idx, sym);
-
-	      /* The value only depends on the position of the referenced
-		 section in the output file and the addend.  */
-	      value = scninfo[sym->st_shndx].offset + sym->st_value;
-	    }
-	  else
-	    {
-	      if (symref[idx] == NULL)
-		/* Symbol in ignored COMDAT group section.  */
-		continue;
-
-	      value = symref[idx]->merge.value;
-	      if (symref[idx]->in_dso)
-		{
-		  /* MERGE.VALUE contains the PLT index.  If this is not for
-		     a function the actual value will be computed later.  */
-		  assert (value != 0 || symref[idx]->type != STT_FUNC);
-		  value = pltaddr + value * PLT_ENTRY_SIZE;
-		}
-	    }
-
-	  /* Address of the relocated memory in the data buffer.  */
-	  unsigned char *relloc = (unsigned char *) data->d_buf + rel->r_offset;
-
-	  uint32_t thisgotidx;
-	  switch (XELF_R_TYPE (rel->r_info))
-	    {
-	      /* These three cases can be handled together since the
-		 symbol associated with the R_386_GOTPC relocation is
-		 _GLOBAL_OFFSET_TABLE_ which has a value corresponding
-		 to the address of the GOT and the address of the PLT
-		 entry required for R_386_PLT32 is computed above.  */
-	    case R_386_PC32:
-	    case R_386_GOTPC:
-	    case R_386_PLT32:
-	      value -= reladdr;
-	      /* FALLTHROUGH */
-
-	    case R_386_32:
-	      if (linked_from_dso_p (scninfo, idx)
-		  && statep->file_type != dso_file_type
-		  && symref[idx]->type != STT_FUNC)
-		{
-		  value = (ld_state.copy_section->offset
-			   + symref[idx]->merge.value);
-
-		  if (unlikely (symref[idx]->need_copy))
-		    {
-		      /* Add a relocation to initialize the GOT entry.  */
-		      assert (symref[idx]->outdynsymidx != 0);
-#if NATIVE_ELF != 0
-		      xelf_getrel_ptr (reldyndata, nreldyn, rel2);
-#else
-		      rel2 = &rel_mem;
-#endif
-		      rel2->r_offset = value;
-		      rel2->r_info
-			= XELF_R_INFO (symref[idx]->outdynsymidx, R_386_COPY);
-		      (void) xelf_update_rel (reldyndata, nreldyn, rel2);
-		      ++nreldyn;
-		      assert (nreldyn <= statep->nrel_got);
-
-		      /* Update the symbol table record for the new
-			 address.  */
-		      Elf32_Word symidx = symref[idx]->outdynsymidx;
-		      Elf_Scn *symscn = elf_getscn (statep->outelf,
-						    statep->dynsymscnidx);
-		      Elf_Data *outsymdata = elf_getdata (symscn, NULL);
-		      assert (outsymdata != NULL);
-		      XElf_Sym_vardef (sym);
-		      xelf_getsym (outsymdata, symidx, sym);
-		      sym->st_value = value;
-		      sym->st_shndx = statep->copy_section->outscnndx;
-		      (void) xelf_update_sym (outsymdata, symidx, sym);
-
-		      symidx = symref[idx]->outsymidx;
-		      if (symidx != 0)
-			{
-			  symidx = statep->dblindirect[symidx];
-			  symscn = elf_getscn (statep->outelf,
-					       statep->symscnidx);
-			  outsymdata = elf_getdata (symscn, NULL);
-			  assert (outsymdata != NULL);
-			  xelf_getsym (outsymdata, symidx, sym);
-			  sym->st_value = value;
-			  sym->st_shndx = statep->copy_section->outscnndx;
-			  (void) xelf_update_sym (outsymdata, symidx, sym);
-			}
-
-		      /* Remember that we set up the copy relocation.  */
-		      symref[idx]->need_copy = 0;
-		    }
-		}
-	      else if (statep->file_type == dso_file_type
-		       && XELF_R_TYPE (rel->r_info) == R_386_32)
-		{
-#if NATIVE_ELF != 0
-		  xelf_getrel_ptr (reldyndata, nreldyn, rel2);
-#else
-		  rel2 = &rel_mem;
-#endif
-		  rel2->r_offset = value;
-
-		  /* For symbols we do not export we generate a relative
-		     relocation.  */
-		  if (idx < SCNINFO_SHDR (scninfo[rshdr->sh_link].shdr).sh_info
-		      || symref[idx]->outdynsymidx == 0)
-		    rel2->r_info = XELF_R_INFO (0, R_386_RELATIVE);
-		  else
-		    rel2->r_info
-		      = XELF_R_INFO (symref[idx]->outdynsymidx, R_386_32);
-		  (void) xelf_update_rel (reldyndata, nreldyn, rel2);
-		  ++nreldyn;
-		  assert (nreldyn <= statep->nrel_got);
-
-		  value = 0;
-		}
-	      add_4ubyte_unaligned (relloc, value);
-	      break;
-
-	    case R_386_GOT32:
-	      if (! symref[idx]->defined || symref[idx]->in_dso)
-		{
-		  thisgotidx = nreldyn++;
-		  assert (thisgotidx < statep->nrel_got);
-
-		  /* Add a relocation to initialize the GOT entry.  */
-#if NATIVE_ELF != 0
-		  xelf_getrel_ptr (reldyndata, thisgotidx, rel2);
-#else
-		  rel2 = &rel_mem;
-#endif
-		  rel2->r_offset = gotaddr + ((thisgotidx - statep->ngot)
-					      * sizeof (Elf32_Addr));
-		  rel2->r_info
-		    = XELF_R_INFO (symref[idx]->outdynsymidx, R_386_GLOB_DAT);
-		  (void) xelf_update_rel (reldyndata, thisgotidx, rel2);
-		}
-	      else if (statep->file_type != dso_file_type)
-		{
-		  thisgotidx = ngotconst++;
-		  assert (thisgotidx < statep->ngot);
-
-		  /* We have to use a GOT since the generated code
-		     requires it but we know the address and therefore
-		     do not need a relocation.  */
-		  ((uint32_t *) gotdata->d_buf)[thisgotidx] = value;
-		}
-	      else
-		{
-		  thisgotidx = nreldyn++;
-		  assert (thisgotidx < statep->nrel_got);
-
-		  // XXX generate a relative relocation.
-		  abort ();
-		}
-
-	      store_4ubyte_unaligned (relloc,
-				      (thisgotidx - statep->ngot)
-				      * sizeof (Elf32_Addr));
-	      break;
-
-	    case R_386_GOTOFF:
-	      add_4ubyte_unaligned (relloc, value - gotaddr);
-	      break;
-
-	    case R_386_TLS_LE:
-	      value = symref[idx]->merge.value - ld_state.tls_tcb;
-	      store_4ubyte_unaligned (relloc, value);
-	      break;
-
-	    case R_386_TLS_IE:
-	      if (symref[idx]->defined && !symref[idx]->in_dso)
-		{
-		  /* The symbol is defined in the executable.
-		     Perform the IE->LE optimization.
-		     There are multiple versions, though.
-
-		     First version: mov ADDR,REG.  */
-		  if (relloc[-2] == 0x8b
-		      && ((relloc[-1] & 0xc7) == 0x05))
-		    {
-		      relloc[-2] = 0xc7;
-		      relloc[-1] = 0xc0 | ((relloc[-1] >> 3) & 7);
-		      store_4ubyte_unaligned (relloc, (symref[idx]->merge.value
-						       - ld_state.tls_tcb));
-		    }
-		  else
-		    {
-		      abort ();
-		    }
-		}
-	      else
-		{
-		  abort ();
-		}
-	      break;
-
-	    case R_386_TLS_LDO_32:
-	      value = symref[idx]->merge.value - ld_state.tls_start;
-	      store_4ubyte_unaligned (relloc, value);
-	      break;
-
-	    case R_386_TLS_GD:
-	      if (ld_state.file_type == executable_file_type)
-		{
-		  if (symref[idx]->defined && !symref[idx]->in_dso)
-		    {
-		      /* The symbol is defined in the executable.
-			 Perform the GD->LE optimization.  */
-		      static const char gd_to_le[] =
-			{
-			  /* mov %gs:0x0,%eax */
-			  0x65, 0xa1, 0x00, 0x00, 0x00, 0x00,
-			  /* sub $OFFSET,%eax */
-			  0x81, 0xe8
-			};
-#ifndef NDEBUG
-		      static const char gd_text[] =
-			{
-			  /* lea 0x0(,%ebx,1),%eax */
-			  0x8d, 0x04, 0x1d, 0x00, 0x00, 0x00, 0x00,
-			  /* call ___tls_get_addr */
-			  0xe8
-			};
-		      assert (memcmp (relloc - 3, gd_text, sizeof (gd_text))
-			      == 0);
-#endif
-		      relloc = mempcpy (relloc - 3, gd_to_le,
-					sizeof (gd_to_le));
-		      value = ld_state.tls_tcb- symref[idx]->merge.value;
-		      store_4ubyte_unaligned (relloc, value);
-
-		      /* We have to skip over the next relocation which is
-			 the matching R_i386_PLT32 for __tls_get_addr.  */
-		      ++cnt;
-#ifndef NDEBUG
-		      assert (cnt < nrels);
-		      XElf_Off old_offset = rel->r_offset;
-		      xelf_getrel (reldata, cnt, rel);
-		      assert (rel != NULL);
-		      assert (XELF_R_TYPE (rel->r_info) == R_386_PLT32);
-		      idx = XELF_R_SYM (rel->r_info);
-		      assert (strcmp (symref[idx]->name, "___tls_get_addr")
-			      == 0);
-		      assert (old_offset + 5 == rel->r_offset);
-#endif
-
-		      break;
-		    }
-		}
-	      abort ();
-	      break;
-
-	    case R_386_32PLT:
-	    case R_386_TLS_TPOFF:
-	    case R_386_TLS_GOTIE:
-	    case R_386_TLS_LDM:
-	    case R_386_16:
-	    case R_386_PC16:
-	    case R_386_8:
-	    case R_386_PC8:
-	    case R_386_TLS_GD_32:
-	    case R_386_TLS_GD_PUSH:
-	    case R_386_TLS_GD_CALL:
-	    case R_386_TLS_GD_POP:
-	    case R_386_TLS_LDM_32:
-	    case R_386_TLS_LDM_PUSH:
-	    case R_386_TLS_LDM_CALL:
-	    case R_386_TLS_LDM_POP:
-	    case R_386_TLS_IE_32:
-	    case R_386_TLS_LE_32:
-	      // XXX For now fall through
-	      break;
-
-	    case R_386_NONE:
-	      /* Nothing to do.  */
-	      break;
-
-	    case R_386_COPY:
-	    case R_386_JMP_SLOT:
-	    case R_386_RELATIVE:
-	    case R_386_GLOB_DAT:
-	    case R_386_TLS_DTPMOD32:
-	    case R_386_TLS_DTPOFF32:
-	    case R_386_TLS_TPOFF32:
-	    default:
-	      /* Should not happen.  */
-	      abort ();
-	    }
-	}
-    }
-  while ((runp = runp->next) != first);
-}
-
-
-int
-elf_i386_ld_init (struct ld_state *statep)
-{
-  /* We have a few callbacks available.  */
-  old_open_outfile = statep->callbacks.open_outfile;
-  statep->callbacks.open_outfile = elf_i386_open_outfile;
-
-  statep->callbacks.relocate_section  = elf_i386_relocate_section;
-
-  statep->callbacks.initialize_plt = elf_i386_initialize_plt;
-  statep->callbacks.initialize_pltrel = elf_i386_initialize_pltrel;
-
-  statep->callbacks.initialize_got = elf_i386_initialize_got;
-  statep->callbacks.initialize_gotplt = elf_i386_initialize_gotplt;
-
-  statep->callbacks.finalize_plt = elf_i386_finalize_plt;
-
-  statep->callbacks.rel_type = elf_i386_rel_type;
-
-  statep->callbacks.count_relocations = elf_i386_count_relocations;
-
-  statep->callbacks.create_relocations = elf_i386_create_relocations;
-
-  return 0;
-}
diff --git a/src/ld.c b/src/ld.c
deleted file mode 100644
index 59dccb5..0000000
--- a/src/ld.c
+++ /dev/null
@@ -1,1607 +0,0 @@
-/* Copyright (C) 2001-2010, 2012 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <argp.h>
-#include <assert.h>
-#include <error.h>
-#include <fcntl.h>
-#include <libelf.h>
-#include <libintl.h>
-#include <locale.h>
-#include <stdio.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <system.h>
-#include "ld.h"
-#include "list.h"
-
-
-/* Name and version of program.  */
-static void print_version (FILE *stream, struct argp_state *state);
-ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
-
-/* Bug report address.  */
-ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
-
-
-/* Values for the various options.  */
-enum
-  {
-    ARGP_whole_archive = 300,
-    ARGP_no_whole_archive,
-    ARGP_static,
-    ARGP_dynamic,
-    ARGP_pagesize,
-    ARGP_rpath_link,
-    ARGP_runpath,
-    ARGP_runpath_link,
-    ARGP_version_script,
-    ARGP_gc_sections,
-    ARGP_no_gc_sections,
-    ARGP_no_undefined,
-    ARGP_conserve,
-    ARGP_as_needed,
-    ARGP_no_as_needed,
-    ARGP_eh_frame_hdr,
-    ARGP_hash_style,
-    ARGP_build_id,
-#if YYDEBUG
-    ARGP_yydebug,
-#endif
-  };
-
-
-/* Definitions of arguments for argp functions.  */
-static const struct argp_option options[] =
-{
-  { NULL, 0, NULL, 0, N_("Input File Control:"), 0 },
-  { "whole-archive", ARGP_whole_archive, NULL, 0,
-    N_("Include whole archives in the output from now on."), 0 },
-  { "no-whole-archive", ARGP_no_whole_archive, NULL, 0,
-    N_("Stop including the whole archives in the output."), 0 },
-  { NULL, 'l', N_("FILE"), OPTION_HIDDEN, NULL, 0 },
-  { "start-group", '(', NULL, 0, N_("Start a group."), 0 },
-  { "end-group", ')', NULL, 0, N_("End a group."), 0 },
-  { NULL, 'L', N_("PATH"), 0,
-    N_("Add PATH to list of directories files are searched in."), 0 },
-  { "as-needed", ARGP_as_needed, NULL, 0,
-    N_("Only set DT_NEEDED for following dynamic libs if actually used"), 0 },
-  { "no-as-needed", ARGP_no_as_needed, NULL, 0,
-    N_("Always set DT_NEEDED for following dynamic libs"), 0 },
-  { "rpath-link", ARGP_rpath_link, "PATH", OPTION_HIDDEN, NULL, 0 },
-  { NULL, 'i', NULL, 0, N_("Ignore LD_LIBRARY_PATH environment variable."),
-    0 },
-
-  { NULL, 0, NULL, 0, N_("Output File Control:"), 0 },
-  { "output", 'o', N_("FILE"), 0, N_("Place output in FILE."), 0 },
-  { NULL, 'z', "KEYWORD", OPTION_HIDDEN, NULL, 0 },
-  { "-z nodefaultlib", '\0', NULL, OPTION_DOC,
-    N_("Object is marked to not use default search path at runtime."), 0 },
-  { "-z allextract", '\0', NULL, OPTION_DOC,
-    N_("Same as --whole-archive."), 0 },
-  { "-z defaultextract", '\0', NULL, OPTION_DOC, N_("\
-Default rules of extracting from archive; weak references are not enough."),
-    0 },
-  { "-z weakextract", '\0', NULL, OPTION_DOC,
-    N_("Weak references cause extraction from archive."), 0 },
-  { "-z muldefs", '\0', NULL, OPTION_DOC,
-    N_("Allow multiple definitions; first is used."), 0 },
-  { "-z defs | nodefs", '\0', NULL, OPTION_DOC,
-    N_("Disallow/allow undefined symbols in DSOs."), 0 },
-    { "no-undefined", ARGP_no_undefined, NULL, OPTION_HIDDEN, NULL, 0 },
-  { "-z origin", '\0', NULL, OPTION_DOC,
-    N_("Object requires immediate handling of $ORIGIN."), 0 },
-  { "-z now", '\0', NULL, OPTION_DOC,
-    N_("Relocation will not be processed lazily."), 0 },
-  { "-z nodelete", '\0', NULL, OPTION_DOC,
-    N_("Object cannot be unloaded at runtime."), 0 },
-  { "-z initfirst", '\0', NULL, OPTION_DOC,
-    N_("Mark object to be initialized first."), 0 },
-  { "-z lazyload | nolazyload", '\0', NULL, OPTION_DOC,
-    N_("Enable/disable lazy-loading flag for following dependencies."), 0 },
-  { "-z nodlopen", '\0', NULL, OPTION_DOC,
-    N_("Mark object as not loadable with 'dlopen'."), 0 },
-  { "-z ignore | record", '\0', NULL, OPTION_DOC,
-    N_("Ignore/record dependencies on unused DSOs."), 0 },
-  { "-z systemlibrary", '\0', NULL, OPTION_DOC,
-    N_("Generated DSO will be a system library."), 0 },
-  { "entry", 'e', N_("ADDRESS"), 0, N_("Set entry point address."), 0 },
-  { "static", ARGP_static, NULL, OPTION_HIDDEN, NULL, 0 },
-  { "-B static", ARGP_static, NULL, OPTION_DOC,
-    N_("Do not link against shared libraries."), 0 },
-  { "dynamic", ARGP_dynamic, NULL, OPTION_HIDDEN, NULL, 0 },
-  { "-B dynamic", ARGP_dynamic, NULL, OPTION_DOC,
-    N_("Prefer linking against shared libraries."), 0 },
-  { "export-dynamic", 'E', NULL, 0, N_("Export all dynamic symbols."), 0 },
-  { "strip-all", 's', NULL, 0, N_("Strip all symbols."), 0 },
-  { "strip-debug", 'S', NULL, 0, N_("Strip debugging symbols."), 0 },
-  { "pagesize", ARGP_pagesize, "SIZE", 0,
-    N_("Assume pagesize for the target system to be SIZE."), 0 },
-  { "rpath", 'R', "PATH", OPTION_HIDDEN, NULL, 0 },
-  { "runpath", ARGP_runpath, "PATH", 0, N_("Set runtime DSO search path."),
-    0 },
-  { "runpath-link", ARGP_runpath_link, "PATH", 0,
-    N_("Set link time DSO search path."), 0 },
-  { "shared", 'G', NULL, 0, N_("Generate dynamic shared object."), 0 },
-  { NULL, 'r', NULL, 0L, N_("Generate relocatable object."), 0 },
-  { NULL, 'B', "KEYWORD", OPTION_HIDDEN, "", 0 },
-  { "-B local", 'B', NULL, OPTION_DOC,
-    N_("Causes symbol not assigned to a version be reduced to local."), 0 },
-  { "gc-sections", ARGP_gc_sections, NULL, 0, N_("Remove unused sections."),
-    0 },
-  { "no-gc-sections", ARGP_no_gc_sections, NULL, 0,
-    N_("Don't remove unused sections."), 0 },
-  { "soname", 'h', "NAME", 0, N_("Set soname of shared object."), 0 },
-  { "dynamic-linker", 'I', "NAME", 0, N_("Set the dynamic linker name."), 0 },
-  { NULL, 'Q', "YN", OPTION_HIDDEN, NULL, 0 },
-  { "-Q y | n", 'Q', NULL, OPTION_DOC,
-    N_("Add/suppress addition indentifying link-editor to .comment section."),
-    0 },
-  { "eh-frame-hdr", ARGP_eh_frame_hdr, NULL, 0,
-    N_("Create .eh_frame_hdr section"), 0 },
-  { "hash-style", ARGP_hash_style, "STYLE", 0,
-    N_("Set hash style to sysv, gnu or both."), 0 },
-  { "build-id", ARGP_build_id, "STYLE", OPTION_ARG_OPTIONAL,
-    N_("Generate build ID note (md5, sha1 (default), uuid)."), 0 },
-
-  { NULL, 0, NULL, 0, N_("Linker Operation Control:"), 0 },
-  { "verbose", 'v', NULL, 0, N_("Verbose messages."), 0 },
-  { "trace", 't', NULL, 0, N_("Trace file opens."), 0 },
-  { "conserve-memory", ARGP_conserve, NULL, 0,
-    N_("Trade speed for less memory usage"), 0 },
-  { NULL, 'O', N_("LEVEL"), OPTION_ARG_OPTIONAL,
-    N_("Set optimization level to LEVEL."), 0 },
-  { NULL, 'c', N_("FILE"), 0, N_("Use linker script in FILE."), 0 },
-#if YYDEBUG
-  { "yydebug", ARGP_yydebug, NULL, 0,
-    N_("Select to get parser debug information"), 0 },
-#endif
-  { "version-script", ARGP_version_script, "FILE", 0,
-    N_("Read version information from FILE."), 0 },
-  { "emulation", 'm', "NAME", 0, N_("Set emulation to NAME."), 0 },
-
-  { NULL, 0, NULL, 0, NULL, 0 }
-};
-
-/* Short description of program.  */
-static const char doc[] = N_("Combine object and archive files.");
-
-/* Strings for arguments in help texts.  */
-static const char args_doc[] = N_("[FILE]...");
-
-/* Prototype for option handler.  */
-static void replace_args (int argc, char *argv[]);
-static error_t parse_opt_1st (int key, char *arg, struct argp_state *state);
-static error_t parse_opt_2nd (int key, char *arg, struct argp_state *state);
-
-/* Data structure to communicate with argp functions.  */
-static struct argp argp_1st =
-{
-  options, parse_opt_1st, args_doc, doc, NULL, NULL, NULL
-};
-static struct argp argp_2nd =
-{
-  options, parse_opt_2nd, args_doc, doc, NULL, NULL, NULL
-};
-
-
-/* Linker state.  This contains all global information.  */
-struct ld_state ld_state;
-
-/* List of the input files.  */
-static struct file_list
-{
-  const char *name;
-  struct file_list *next;
-} *input_file_list;
-
-/* If nonzero be verbose.  */
-int verbose;
-
-/* If nonzero, trade speed for less memory/address space usage.  */
-int conserve_memory;
-
-/* The emulation name to use.  */
-static const char *emulation;
-
-/* Keep track of the nesting level.  Even though we don't handle nested
-   groups we still keep track to improve the error messages.  */
-static int group_level;
-
-/* The last file we processed.  */
-static struct usedfiles *last_file;
-
-/* The default linker script.  */
-/* XXX We'll do this a bit different in the real solution.  */
-static const char *linker_script = SRCDIR "/elf32-i386.script";
-
-/* Nonzero if an error occurred while loading the input files.  */
-static int error_loading;
-
-
-/* Intermediate storage for the LD_LIBRARY_PATH information from the
-   environment.  */
-static char *ld_library_path1;
-
-/* Flag used to communicate with the scanner.  */
-int ld_scan_version_script;
-
-/* Name of the input file.  */
-const char *ldin_fname;
-
-/* Define by parser if required.  */
-extern int lddebug;
-
-
-/* Prototypes for local functions.  */
-static void parse_z_option (const char *arg);
-static void parse_z_option_2 (const char *arg);
-static void parse_B_option (const char *arg);
-static void parse_B_option_2 (const char *arg);
-static void determine_output_format (void);
-static void load_needed (void);
-static void collect_sections (void);
-static void add_rxxpath (struct pathelement **pathp, const char *str);
-static void gen_rxxpath_data (void);
-static void read_version_script (const char *fname);
-static void create_lscript_symbols (void);
-static void create_special_section_symbol (struct symbol **symp,
-					   const char *name);
-
-
-int
-main (int argc, char *argv[])
-{
-  int remaining;
-  int err;
-
-  /* Sanity check.  We always want to use the LFS functionality.  */
-  if (sizeof (off_t) != 8)
-    abort ();
-
-  /* We use no threads here which can interfere with handling a stream.  */
-  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
-  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
-  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
-
-  /* Set locale.  */
-  setlocale (LC_ALL, "");
-
-  /* Make sure the message catalog can be found.  */
-  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
-
-  /* Initialize the message catalog.  */
-  textdomain (PACKAGE_TARNAME);
-
-  /* Before we start tell the ELF library which version we are using.  */
-  elf_version (EV_CURRENT);
-
-  /* The user can use the LD_LIBRARY_PATH environment variable to add
-     additional lookup directories.  */
-  ld_library_path1 = getenv ("LD_LIBRARY_PATH");
-
-  /* Initialize the memory handling.  */
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
-  obstack_init (&ld_state.smem);
-
-  /* Recognize old-style parameters for compatibility.  */
-  replace_args (argc, argv);
-
-  /* One quick pass over the parameters which allows us to scan for options
-     with global effect which influence the rest of the processing.  */
-  argp_parse (&argp_1st, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
-
-  /* We need at least one input file.  */
-  if (input_file_list == NULL)
-    {
-      error (0, 0, gettext ("At least one input file needed"));
-      argp_help (&argp_1st, stderr, ARGP_HELP_SEE, "ld");
-      exit (EXIT_FAILURE);
-    }
-
-  /* Determine which ELF backend to use.  */
-  determine_output_format ();
-
-  /* If no hash style was specific default to the oldand slow SysV
-     method.  */
-  if (unlikely (ld_state.hash_style == hash_style_none))
-    ld_state.hash_style = hash_style_sysv;
-
-  /* Prepare state.  */
-  err = ld_prepare_state (emulation);
-  if (err != 0)
-    error (EXIT_FAILURE, 0, gettext ("error while preparing linking"));
-
-  /* XXX Read the linker script now.  Since we later will have the linker
-     script built in we don't go into trouble to make sure we handle GROUP
-     statements in the script.  This simply must not happen.  */
-  ldin = fopen (linker_script, "r");
-  if (ldin == NULL)
-    error (EXIT_FAILURE, errno, gettext ("cannot open linker script '%s'"),
-	   linker_script);
-  /* No need for locking.  */
-  __fsetlocking (ldin, FSETLOCKING_BYCALLER);
-
-  ld_state.srcfiles = NULL;
-  ldlineno = 1;
-  ld_scan_version_script = 0;
-  ldin_fname = linker_script;
-  if (ldparse () != 0)
-    /* Something went wrong during parsing.  */
-    exit (EXIT_FAILURE);
-  fclose (ldin);
-
-  /* We now might have a list of directories to look for libraries in
-     named by the linker script.  Put them in a different list so that
-     they are searched after all paths given by the user on the
-     command line.  */
-  ld_state.default_paths = ld_state.paths;
-  ld_state.paths = ld_state.tailpaths = NULL;
-
-  /* Get runpath/rpath information in usable form.  */
-  gen_rxxpath_data ();
-
-  /* Parse and process arguments for real.  */
-  argp_parse (&argp_2nd, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
-  /* All options should have been processed by the argp parser.  */
-  assert (remaining == argc);
-
-  /* Process the last file.  */
-  while (last_file != NULL)
-    /* Try to open the file.  */
-    error_loading |= FILE_PROCESS (-1, last_file, &ld_state, &last_file);
-
-  /* Stop if there has been a problem while reading the input files.  */
-  if (error_loading)
-    exit (error_loading);
-
-  /* See whether all opened -( were closed.  */
-  if (group_level > 0)
-    {
-      error (0, 0, gettext ("-( without matching -)"));
-      argp_help (&argp_1st, stderr, ARGP_HELP_SEE, "ld");
-      exit (EXIT_FAILURE);
-    }
-
-  /* When we create a relocatable file we don't have to look for the
-     DT_NEEDED DSOs and we also don't test for undefined symbols.  */
-  if (ld_state.file_type != relocatable_file_type)
-    {
-      /* At this point we have loaded all the direct dependencies.  What
-	 remains to be done is find the indirect dependencies.  These are
-	 DSOs which are referenced by the DT_NEEDED entries in the DSOs
-	 which are direct dependencies.  We have to transitively find and
-	 load all these dependencies.  */
-      load_needed ();
-
-      /* At this point all object files and DSOs are read.  If there
-	 are still undefined symbols left they might have to be
-	 synthesized from the linker script.  */
-      create_lscript_symbols ();
-
-      /* Now that we have loaded all the object files we can determine
-	 whether we have any non-weak unresolved references left.  If
-	 there are any we stop.  If the user used the '-z nodefs' option
-	 and we are creating a DSO don't perform the tests.  */
-      if (FLAG_UNRESOLVED (&ld_state) != 0)
-	exit (1);
-    }
-
-  /* Collect information about the relocations which will be carried
-     forward into the output.  We have to do this here and now since
-     we need to know which sections have to be created.  */
-  if (ld_state.file_type != relocatable_file_type)
-    {
-      void *p ;
-      struct scnhead *h;
-
-      p = NULL;
-      while ((h = ld_section_tab_iterate (&ld_state.section_tab, &p)) != NULL)
-	if (h->type == SHT_REL || h->type == SHT_RELA)
-	  {
-	    struct scninfo *runp = h->last;
-	    do
-	      {
-		/* If we are processing the relocations determine how
-		   many will be in the output file.  Also determine
-		   how many GOT entries are needed.  */
-		COUNT_RELOCATIONS (&ld_state, runp);
-
-		ld_state.relsize_total += runp->relsize;
-	      }
-	    while ((runp = runp->next) != h->last);
-	  }
-    }
-
-  /* Not part of the gABI, but part of every psABI: the symbols for the
-     GOT section.  Add the symbol if necessary.  */
-  if (ld_state.need_got)
-    create_special_section_symbol (&ld_state.got_symbol,
-				   "_GLOBAL_OFFSET_TABLE_");
-  /* Similarly for the _DYNAMIC symbol which points to the dynamic
-     section.  */
-  if (dynamically_linked_p ())
-    create_special_section_symbol (&ld_state.dyn_symbol, "_DYNAMIC");
-
-  /* We are ready to start working on the output file.  Not all
-     information has been gather or created yet.  This will be done as
-     we go.  Open the file now.  */
-  if (OPEN_OUTFILE (&ld_state, EM_NONE, ELFCLASSNONE, ELFDATANONE) != 0)
-    exit (1);
-
-  /* Create the sections which are generated by the linker and are not
-     present in the input file.  The output file must already have
-     been opened since we need the ELF descriptor to deduce type
-     sizes.  */
-  GENERATE_SECTIONS (&ld_state);
-
-  /* At this point we have read all the files and know all the
-     sections which have to be linked into the application.  We do now
-     create an array listing all the sections.  We will than pass this
-     array to a system specific function which can reorder it at will.
-     The functions can also merge sections if this is what is
-     wanted.  */
-  collect_sections ();
-
-  /* Create the output sections now.  This may requires sorting them
-     first.  */
-  CREATE_SECTIONS (&ld_state);
-
-  /* Create the output file data.  Appropriate code for the selected
-     output file type is called.  */
-  if (CREATE_OUTFILE (&ld_state) != 0)
-    exit (1);
-
-  /* Finalize the output file, write the data out.  */
-  err |= FINALIZE (&ld_state);
-
-  /* Return with an non-zero exit status also if any error message has
-     been printed.  */
-  return err | (error_message_count != 0);
-}
-
-
-static void
-replace_args (int argc, char *argv[])
-{
-  static const struct
-  {
-    const char *from;
-    const char *to;
-  } args[] =
-      {
-	{ "-export-dynamic", "--export-dynamic" },
-	{ "-dynamic-linker", "--dynamic-linker" },
-	{ "-static", "--static" },
-      };
-  const size_t nargs = sizeof (args) / sizeof (args[0]);
-
-  for (int i = 1; i < argc; ++i)
-    if (argv[i][0] == '-' && islower (argv[i][1]) && argv[i][2] != '\0')
-      for (size_t j = 0; j < nargs; ++j)
-	if (strcmp (argv[i], args[j].from) == 0)
-	  {
-	    argv[i] = (char *) args[j].to;
-	    break;
-	  }
-}
-
-
-static int
-valid_hexarg (const char *arg)
-{
-  if (strncasecmp (arg, "0x", 2) != 0)
-    return 0;
-
-  arg += 2;
-  do
-    {
-      if (isxdigit (arg[0]) && isxdigit (arg[1]))
-	{
-	  arg += 2;
-	  if (arg[0] == '-' || arg[0] == ':')
-	    ++arg;
-	}
-      else
-	return 0;
-    }
-  while (*arg != '\0');
-
-  return 1;
-}
-
-
-/* Quick scan of the parameter list for options with global effect.  */
-static error_t
-parse_opt_1st (int key, char *arg,
-	       struct argp_state *state __attribute__ ((unused)))
-{
-  switch (key)
-    {
-    case 'B':
-      parse_B_option (arg);
-      break;
-
-    case 'c':
-      linker_script = arg;
-      break;
-
-    case 'E':
-      ld_state.export_all_dynamic = true;
-      break;
-
-    case 'G':
-      if (ld_state.file_type != no_file_type)
-	error (EXIT_FAILURE, 0,
-	       gettext ("only one option of -G and -r is allowed"));
-      ld_state.file_type = dso_file_type;
-
-      /* If we generate a DSO we have to export all symbols.  */
-      ld_state.export_all_dynamic = true;
-      break;
-
-    case 'h':
-      ld_state.soname = arg;
-      break;
-
-    case 'i':
-      /* Discard the LD_LIBRARY_PATH value we found.  */
-      ld_library_path1 = NULL;
-      break;
-
-    case 'I':
-      ld_state.interp = arg;
-      break;
-
-    case 'm':
-      if (emulation != NULL)
-	error (EXIT_FAILURE, 0, gettext ("more than one '-m' parameter"));
-      emulation = arg;
-      break;
-
-    case 'Q':
-      if (arg[1] == '\0' && (arg[0] == 'y' || arg[0] == 'Y'))
-	ld_state.add_ld_comment = true;
-      else if (arg[1] == '\0' && (arg[0] == 'n' || arg[0] == 'N'))
-	ld_state.add_ld_comment = true;
-      else
-	error (EXIT_FAILURE, 0, gettext ("unknown option `-%c %s'"), 'Q', arg);
-      break;
-
-    case 'r':
-      if (ld_state.file_type != no_file_type)
-	error (EXIT_FAILURE, 0,
-	       gettext ("only one option of -G and -r is allowed"));
-      ld_state.file_type = relocatable_file_type;
-      break;
-
-    case 'S':
-      ld_state.strip = strip_debug;
-      break;
-
-    case 't':
-      ld_state.trace_files = true;
-      break;
-
-    case 'v':
-      verbose = 1;
-      break;
-
-    case 'z':
-      /* The SysV linker used 'z' to pass various flags to the linker.
-	 We follow this.  See 'parse_z_option' for the options we
-	 recognize.  */
-      parse_z_option (arg);
-      break;
-
-    case ARGP_pagesize:
-      {
-	char *endp;
-	ld_state.pagesize = strtoul (arg, &endp, 0);
-	if (*endp != '\0')
-	  {
-	    if (endp[1] == '\0' && tolower (*endp) == 'k')
-	      ld_state.pagesize *= 1024;
-	    else if (endp[1] == '\0' && tolower (*endp) == 'm')
-	      ld_state.pagesize *= 1024 * 1024;
-	    else
-	      {
-		error (0, 0,
-		       gettext ("invalid page size value '%s': ignored"),
-		       arg);
-		ld_state.pagesize = 0;
-	      }
-	  }
-      }
-      break;
-
-    case 'R':
-      add_rxxpath (&ld_state.rpath, arg);
-      break;
-
-    case ARGP_rpath_link:
-      add_rxxpath (&ld_state.rpath_link, arg);
-      break;
-
-    case ARGP_runpath:
-      add_rxxpath (&ld_state.runpath, arg);
-      break;
-
-    case ARGP_runpath_link:
-      add_rxxpath (&ld_state.runpath_link, arg);
-      break;
-
-    case ARGP_gc_sections:
-    case ARGP_no_gc_sections:
-      ld_state.gc_sections = key == ARGP_gc_sections;
-      break;
-
-    case ARGP_eh_frame_hdr:
-      ld_state.eh_frame_hdr = true;
-      break;
-
-    case ARGP_hash_style:
-      if (strcmp (arg, "gnu") == 0)
-	ld_state.hash_style = hash_style_gnu;
-      else if (strcmp (arg, "both") == 0)
-	ld_state.hash_style = hash_style_gnu | hash_style_sysv;
-      else if (strcmp (arg, "sysv") == 0)
-	ld_state.hash_style = hash_style_sysv;
-      else
-	error (EXIT_FAILURE, 0, gettext ("invalid hash style '%s'"), arg);
-      break;
-
-    case ARGP_build_id:
-      if (arg == NULL)
-	ld_state.build_id = "sha1";
-      else if (strcmp (arg, "uuid") != 0
-	       && strcmp (arg, "md5") != 0
-	       && strcmp (arg, "sha1") != 0
-	       && !valid_hexarg (arg))
-	error (EXIT_FAILURE, 0, gettext ("invalid build-ID style '%s'"), arg);
-      else
-	ld_state.build_id = arg;
-      break;
-
-    case 's':
-      if (arg == NULL)
-	{
-	  if (ld_state.strip == strip_all)
-	    ld_state.strip = strip_everything;
-	  else
-	    ld_state.strip = strip_all;
-	  break;
-	}
-      /* FALLTHROUGH */
-
-    case 'e':
-    case 'o':
-    case 'O':
-    case ARGP_whole_archive:
-    case ARGP_no_whole_archive:
-    case ARGP_as_needed:
-    case ARGP_no_as_needed:
-    case 'L':
-    case '(':
-    case ')':
-    case 'l':
-    case ARGP_static:
-    case ARGP_dynamic:
-    case ARGP_version_script:
-      /* We'll handle these in the second pass.  */
-      break;
-
-    case ARGP_KEY_ARG:
-      {
-	struct file_list *newp;
-
-	newp = (struct file_list *) xmalloc (sizeof (struct file_list));
-	newp->name = arg;
-#ifndef NDEBUG
-	newp->next = NULL;
-#endif
-	CSNGL_LIST_ADD_REAR (input_file_list, newp);
-      }
-      break;
-
-#if YYDEBUG
-    case ARGP_yydebug:
-      lddebug = 1;
-      break;
-#endif
-
-    case ARGP_no_undefined:
-      ld_state.nodefs = false;
-      break;
-
-    case ARGP_conserve:
-      conserve_memory = 1;
-      break;
-
-    default:
-      return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
-
-/* Handle program arguments for real.  */
-static error_t
-parse_opt_2nd (int key, char *arg,
-	       struct argp_state *state __attribute__ ((unused)))
-{
-  static bool group_start_requested;
-  static bool group_end_requested;
-
-  switch (key)
-    {
-    case 'B':
-      parse_B_option_2 (arg);
-      break;
-
-    case 'e':
-      ld_state.entry = arg;
-      break;
-
-    case 'o':
-      if (ld_state.outfname != NULL)
-	{
-	  error (0, 0, gettext ("More than one output file name given."));
-	see_help:
-	  argp_help (&argp_2nd, stderr, ARGP_HELP_SEE, "ld");
-	  exit (EXIT_FAILURE);
-	}
-      ld_state.outfname = arg;
-      break;
-
-    case 'O':
-      if (arg == NULL)
-	ld_state.optlevel = 1;
-      else
-	{
-	  char *endp;
-	  unsigned long int level = strtoul (arg, &endp, 10);
-	  if (*endp != '\0')
-	    {
-	      error (0, 0, gettext ("Invalid optimization level `%s'"), arg);
-	      goto see_help;
-	    }
-	  ld_state.optlevel = level;
-	}
-      break;
-
-    case ARGP_whole_archive:
-      ld_state.extract_rule = allextract;
-      break;
-    case ARGP_no_whole_archive:
-      ld_state.extract_rule = defaultextract;
-      break;
-
-    case ARGP_as_needed:
-      ld_state.as_needed = true;
-      break;
-    case ARGP_no_as_needed:
-      ld_state.as_needed = false;
-      break;
-
-    case ARGP_static:
-    case ARGP_dynamic:
-      /* Enable/disable use for DSOs.  */
-      ld_state.statically = key == ARGP_static;
-      break;
-
-    case 'z':
-      /* The SysV linker used 'z' to pass various flags to the linker.
-	 We follow this.  See 'parse_z_option' for the options we
-	 recognize.  */
-      parse_z_option_2 (arg);
-      break;
-
-    case ARGP_version_script:
-      read_version_script (arg);
-      break;
-
-    case 'L':
-      /* Add a new search directory.  */
-      ld_new_searchdir (arg);
-      break;
-
-    case '(':
-      /* Start a link group.  We have to be able to determine the object
-	 file which is named next.  Do this by remembering a pointer to
-	 the pointer which will point to the next object.  */
-      if (verbose && (group_start_requested || !group_end_requested))
-	error (0, 0, gettext ("nested -( -) groups are not allowed"));
-
-      /* Increment the nesting level.  */
-      ++group_level;
-
-      /* Record group start.  */
-      group_start_requested = true;
-      group_end_requested = false;
-      break;
-
-    case ')':
-      /* End a link group.  If there is no group open this is clearly
-	 a bug.  If there is a group open insert a back reference
-	 pointer in the record for the last object of the group.  If
-	 there is no new object or just one don't do anything.  */
-      if (!group_end_requested)
-	{
-	  if (group_level == 0)
-	    {
-	      error (0, 0, gettext ("-) without matching -("));
-	      goto see_help;
-	    }
-	}
-      else
-	last_file->group_end = true;
-
-      if (group_level > 0)
-	--group_level;
-      break;
-
-    case 'l':
-    case ARGP_KEY_ARG:
-      {
-	while (last_file != NULL)
-	  /* Try to open the file.  */
-	  error_loading |= FILE_PROCESS (-1, last_file, &ld_state, &last_file);
-
-	last_file = ld_new_inputfile (arg,
-				      key == 'l'
-				      ? archive_file_type
-				      : relocatable_file_type);
-	if (group_start_requested)
-	  {
-	    last_file->group_start = true;
-
-	    group_start_requested = false;
-	    group_end_requested = true;
-	  }
-      }
-      break;
-
-    default:
-      /* We can catch all other options here.  They either have
-	 already been handled or, if the parameter was not correct,
-	 the error has been reported.  */
-      break;
-    }
-  return 0;
-}
-
-
-/* Load all the DSOs named as dependencies in other DSOs we already
-   loaded.  */
-static void
-load_needed (void)
-{
-  struct usedfiles *first;
-  struct usedfiles *runp;
-
-  /* XXX There is one problem here: do we allow references from
-     regular object files to be satisfied by these implicit
-     dependencies?  The old linker allows this and several libraries
-     depend on this.  Solaris' linker does not allow this; it provides
-     the user with a comprehensive error message explaining the
-     situation.
-
-     XXX IMO the old ld behavior is correct since this is also how the
-     dynamic linker will work.  It will look for unresolved references
-     in all loaded DSOs.
-
-     XXX Should we add an option to get Solaris compatibility?  */
-  if (ld_state.needed == NULL)
-    return;
-
-  runp = first = ld_state.needed->next;
-  do
-    {
-      struct usedfiles *ignore;
-      struct usedfiles *next = runp->next;
-      int err;
-
-      err = FILE_PROCESS (-1, runp, &ld_state, &ignore);
-      if (err != 0)
-	/* Something went wrong.  */
-	exit (err);
-
-      runp = next;
-    }
-  while (runp != first);
-}
-
-
-/* Print the version information.  */
-static void
-print_version (FILE *stream, struct argp_state *state __attribute__ ((unused)))
-{
-  fprintf (stream, "ld (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION);
-  fprintf (stream, gettext ("\
-Copyright (C) %s Red Hat, Inc.\n\
-This is free software; see the source for copying conditions.  There is NO\n\
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
-"), "2012");
-  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
-}
-
-
-/* There are a lot of -z options, parse them here.  Some of them have
-   to be parsed in the first pass, others must be handled in the
-   second pass.  */
-static void
-parse_z_option (const char *arg)
-{
-  if (strcmp (arg, "nodefaultlib") == 0
-      /* This is only meaningful if we create a DSO.  */
-      && ld_state.file_type == dso_file_type)
-    ld_state.dt_flags_1 |= DF_1_NODEFLIB;
-  else if (strcmp (arg, "muldefs") == 0)
-    ld_state.muldefs = true;
-  else if (strcmp (arg, "nodefs") == 0)
-    ld_state.nodefs = true;
-  else if (strcmp (arg, "defs") == 0)
-    ld_state.nodefs = false;
-  else if (strcmp (arg, "now") == 0)
-    /* We could also set the DF_1_NOW flag in DT_FLAGS_1 but this isn't
-       necessary.  */
-    ld_state.dt_flags |= DF_BIND_NOW;
-  else if (strcmp (arg, "origin") == 0)
-    /* We could also set the DF_1_ORIGIN flag in DT_FLAGS_1 but this isn't
-       necessary.  */
-    ld_state.dt_flags |= DF_ORIGIN;
-  else if (strcmp (arg, "nodelete") == 0
-	   /* This is only meaningful if we create a DSO.  */
-	   && ld_state.file_type == dso_file_type)
-    ld_state.dt_flags_1 |= DF_1_NODELETE;
-  else if (strcmp (arg, "initfirst") == 0)
-    ld_state.dt_flags_1 |= DF_1_INITFIRST;
-  else if (strcmp (arg, "nodlopen") == 0
-	   /* This is only meaningful if we create a DSO.  */
-	   && ld_state.file_type == dso_file_type)
-    ld_state.dt_flags_1 |= DF_1_NOOPEN;
-  else if (strcmp (arg, "systemlibrary") == 0)
-    ld_state.is_system_library = true;
-  else if (strcmp (arg, "execstack") == 0)
-    ld_state.execstack = execstack_true;
-  else if (strcmp (arg, "noexecstack") == 0)
-    ld_state.execstack = execstack_false_force;
-  else if (strcmp (arg, "allextract") != 0
-	   && strcmp (arg, "defaultextract") != 0
-	   && strcmp (arg, "weakextract") != 0
-	   && strcmp (arg, "lazyload") != 0
-	   && strcmp (arg, "nolazyload") != 0
-	   && strcmp (arg, "ignore") != 0
-	   && strcmp (arg, "record") != 0)
-    error (0, 0, gettext ("unknown option `-%c %s'"), 'z', arg);
-}
-
-
-static void
-parse_z_option_2 (const char *arg)
-{
-  if (strcmp (arg, "allextract") == 0)
-    ld_state.extract_rule = allextract;
-  else if (strcmp (arg, "defaultextract") == 0)
-    ld_state.extract_rule = defaultextract;
-  else if (strcmp (arg, "weakextract") == 0)
-    ld_state.extract_rule = weakextract;
-  else if (strcmp (arg, "lazyload") == 0)
-    ld_state.lazyload = true;
-  else if (strcmp (arg, "nolazyload") == 0)
-    ld_state.lazyload = false;
-  else if (strcmp (arg, "ignore") == 0)
-    ld_state.as_needed = true;
-  else if (strcmp (arg, "record") == 0)
-    ld_state.as_needed = false;
-}
-
-
-/* There are a lot of -B options, parse them here.  */
-static void
-parse_B_option (const char *arg)
-{
-  if (strcmp (arg, "local") == 0)
-    ld_state.default_bind_local = true;
-  else if (strcmp (arg, "symbolic") != 0
-	   && strcmp (arg, "static") != 0
-	   && strcmp (arg, "dynamic") != 0)
-    error (0, 0, gettext ("unknown option '-%c %s'"), 'B', arg);
-}
-
-
-/* The same functionality, but called in the second pass over the
-   parameters.  */
-static void
-parse_B_option_2 (const char *arg)
-{
-  if (strcmp (arg, "static") == 0)
-    ld_state.statically = true;
-  else if (strcmp (arg, "dynamic") == 0)
-    ld_state.statically = false;
-  else if (strcmp (arg, "symbolic") == 0
-	   /* This is only meaningful if we create a DSO.  */
-	   && ld_state.file_type == dso_file_type)
-    ld_state.dt_flags |= DF_SYMBOLIC;
-}
-
-
-static inline int
-try (int fd, Elf *elf)
-{
-  int result = 0;
-
-  if (elf == NULL)
-    return 0;
-
-  if (elf_kind (elf) == ELF_K_ELF)
-    {
-      /* We have an ELF file.  We now can find out
-	 what the output format should be.  */
-      XElf_Ehdr_vardef(ehdr);
-
-      /* Get the ELF header of the object.  */
-      xelf_getehdr (elf, ehdr);
-      if (ehdr != NULL)
-	ld_state.ebl =
-	  ebl_openbackend_machine (ehdr->e_machine);
-
-      result = 1;
-    }
-  else if (elf_kind (elf) == ELF_K_AR)
-    {
-      /* Try the archive members.  This could
-	 potentially lead to wrong results if the
-	 archive contains files for more than one
-	 architecture.  But this is the user's
-	 problem.  */
-      Elf *subelf;
-      Elf_Cmd cmd = ELF_C_READ_MMAP;
-
-      while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
-	{
-	  cmd = elf_next (subelf);
-
-	  if (try (fd, subelf) != 0)
-	    break;
-	}
-    }
-
-  elf_end (elf);
-
-  return result;
-}
-
-
-static void
-determine_output_format (void)
-{
-  /* First change the 'input_file_list' variable in a simple
-     single-linked list.  */
-  struct file_list *last = input_file_list;
-  input_file_list = input_file_list->next;
-  last->next = NULL;
-
-  /* Determine the target configuration which we are supposed to use.
-     The user can use the '-m' option to select one.  If this is
-     missing we are trying to load one file and determine the
-     architecture from that.  */
-  if (emulation != NULL)
-    {
-      ld_state.ebl = ebl_openbackend_emulation (emulation);
-
-      assert (ld_state.ebl != NULL);
-    }
-  else
-    {
-      /* Find an ELF input file and let it determine the ELf backend.  */
-      struct file_list *runp = input_file_list;
-
-      while (runp != NULL)
-	{
-	  int fd = open (runp->name, O_RDONLY);
-	  if (fd != -1)
-	    {
-	      if (try (fd, elf_begin (fd, ELF_C_READ_MMAP, NULL)) != 0)
-		/* Found a file.  */
-		break;
-	    }
-
-	  runp = runp->next;
-	}
-
-      if (ld_state.ebl == NULL)
-	{
-	  error (0, 0, gettext ("\
-could not find input file to determine output file format"));
-	  error (EXIT_FAILURE, 0, gettext ("\
-try again with an appropriate '-m' parameter"));
-	}
-    }
-
-  /* We don't need the list of input files anymore.  The second run over
-     the parameters will handle them.  */
-  while (input_file_list != NULL)
-    {
-      struct file_list *oldp = input_file_list;
-      input_file_list = input_file_list->next;
-      free (oldp);
-    }
-
-  /* We also know now what kind of file we are supposed to create.  If
-     the user hasn't selected anythign we create and executable.  */
-  if (ld_state.file_type == no_file_type)
-    ld_state.file_type = executable_file_type;
-}
-
-/* Add DIR to the list of directories searched for object files and
-   libraries.  */
-void
-ld_new_searchdir (const char *dir)
-{
-  struct pathelement *newpath;
-
-  newpath = (struct pathelement *)
-    obstack_calloc (&ld_state.smem, sizeof (struct pathelement));
-
-  newpath->pname = dir;
-
-  /* Enqueue the file.  */
-  if (ld_state.tailpaths == NULL)
-    ld_state.paths = ld_state.tailpaths = newpath->next = newpath;
-  else
-    {
-      ld_state.tailpaths->next = newpath;
-      ld_state.tailpaths = newpath;
-      newpath->next = ld_state.paths;
-    }
-}
-
-
-struct usedfiles *
-ld_new_inputfile (const char *fname, enum file_type type)
-{
-  struct usedfiles *newfile = (struct usedfiles *)
-    obstack_calloc (&ld_state.smem, sizeof (struct usedfiles));
-
-  newfile->soname = newfile->fname = newfile->rfname = fname;
-  newfile->file_type = type;
-  newfile->extract_rule = ld_state.extract_rule;
-  newfile->as_needed = ld_state.as_needed;
-  newfile->lazyload = ld_state.lazyload;
-  newfile->status = not_opened;
-
-  return newfile;
-}
-
-
-/* Create an array listing all the sections.  We will than pass this
-   array to a system specific function which can reorder it at will.
-   The functions can also merge sections if this is what is
-   wanted.  */
-static void
-collect_sections (void)
-{
-  void *p ;
-  struct scnhead *h;
-  size_t cnt;
-
-  /* We have that many sections.  At least for now.  */
-  ld_state.nallsections = ld_state.section_tab.filled;
-
-  /* Allocate the array.  We allocate one more entry than computed so
-     far since we might need a new section for the copy relocations.  */
-  ld_state.allsections =
-    (struct scnhead **) obstack_alloc (&ld_state.smem,
-				       (ld_state.nallsections + 1)
-				       * sizeof (struct scnhead *));
-
-  /* Fill the array.  We rely here on the hash table iterator to
-     return the entries in the order they were added.  */
-  cnt = 0;
-  p = NULL;
-  while ((h = ld_section_tab_iterate (&ld_state.section_tab, &p)) != NULL)
-    {
-      struct scninfo *runp;
-      bool used = false;
-
-      if (h->kind == scn_normal)
-	{
-	  runp = h->last;
-	  do
-	    {
-	      if (h->type == SHT_REL || h->type == SHT_RELA)
-		{
-		  if (runp->used)
-		    /* This is a relocation section.  If the section
-		       it is relocating is used in the result so must
-		       the relocation section.  */
-		    runp->used
-		      = runp->fileinfo->scninfo[SCNINFO_SHDR (runp->shdr).sh_info].used;
-		}
-
-	      /* Accumulate the result.  */
-	      used |= runp->used;
-
-	      /* Next input section.  */
-	      runp = runp->next;
-	    }
-	  while (runp != h->last);
-
-	  h->used = used;
-	}
-
-      ld_state.allsections[cnt++] = h;
-    }
-  ld_state.nusedsections = cnt;
-
-  assert (cnt == ld_state.nallsections);
-}
-
-
-/* Add given path to the end of list.  */
-static void
-add_rxxpath (struct pathelement **pathp, const char *str)
-{
-  struct pathelement *newp;
-
-  /* The path elements can in theory be freed after we read all the
-     files.  But the amount of memory we are talking about is small
-     and the cost of free() calls is not neglectable.  */
-  newp = (struct pathelement *) obstack_alloc (&ld_state.smem, sizeof (*newp));
-  newp->pname = str;
-  newp->exist = 0;
-#ifndef NDEBUG
-  newp->next = NULL;
-#endif
-
-  CSNGL_LIST_ADD_REAR (*pathp, newp);
-}
-
-
-/* Convert lists of possibly colon-separated directory lists into lists
-   where each entry is for a single directory.  */
-static void
-normalize_dirlist (struct pathelement **pathp)
-{
-  struct pathelement *firstp = *pathp;
-
-  do
-    {
-      const char *pname = (*pathp)->pname;
-      const char *colonp = strchrnul (pname, ':');
-
-      if (colonp != NULL)
-	{
-	  struct pathelement *lastp = *pathp;
-	  struct pathelement *newp;
-
-	  while (1)
-	    {
-	      if (colonp == pname)
-		lastp->pname = ".";
-	      else
-		lastp->pname = obstack_strndup (&ld_state.smem, pname,
-						colonp - pname);
-
-	      if (*colonp == '\0')
-		break;
-	      pname = colonp + 1;
-
-	      newp = (struct pathelement *) obstack_alloc (&ld_state.smem,
-							   sizeof (*newp));
-	      newp->next = lastp->next;
-	      newp->exist = 0;
-	      lastp = lastp->next = newp;
-
-	      colonp = strchrnul (pname, ':');
-	    }
-
-	  pathp = &lastp->next;
-	}
-      else
-	pathp = &(*pathp)->next;
-    }
-  while (*pathp != firstp);
-}
-
-
-/* Called after all parameters are parsed to bring the runpath/rpath
-   information into a usable form.  */
-static void
-gen_rxxpath_data (void)
-{
-  char *ld_library_path2;
-
-  /* Convert the information in true single-linked lists for easy use.
-     At this point we also discard the rpath information if runpath
-     information is provided.  rpath is deprecated and should not be
-     used (or ever be invented for that matter).  */
-  if (ld_state.rpath != NULL)
-    {
-      struct pathelement *endp = ld_state.rpath;
-      ld_state.rpath = ld_state.rpath->next;
-      endp->next = NULL;
-    }
-  if (ld_state.rpath_link != NULL)
-    {
-      struct pathelement *endp = ld_state.rpath_link;
-      ld_state.rpath_link = ld_state.rpath_link->next;
-      endp->next = NULL;
-    }
-
-  if (ld_state.runpath != NULL)
-    {
-      struct pathelement *endp = ld_state.runpath;
-      ld_state.runpath = ld_state.runpath->next;
-      endp->next = NULL;
-
-      /* If rpath information is also available discard it.
-	 XXX Should there be a possibility to avoid this?  */
-      while (ld_state.rpath != NULL)
-	{
-	  struct pathelement *old = ld_state.rpath;
-	  ld_state.rpath = ld_state.rpath->next;
-	  free (old);
-	}
-    }
-  if (ld_state.runpath_link != NULL)
-    {
-      struct pathelement *endp = ld_state.runpath_link;
-      ld_state.runpath_link = ld_state.runpath_link->next;
-      endp->next = NULL;
-
-      /* If rpath information is also available discard it.
-	 XXX Should there be a possibility to avoid this?  */
-      while (ld_state.rpath_link != NULL)
-	{
-	  struct pathelement *old = ld_state.rpath_link;
-	  ld_state.rpath_link = ld_state.rpath_link->next;
-	  free (old);
-	}
-
-      /* The information in the strings in the list can actually be
-	 directory lists themselves, with entries separated by colons.
-	 Convert the list now to a list with one list entry for each
-	 directory.  */
-      normalize_dirlist (&ld_state.runpath_link);
-    }
-  else if (ld_state.rpath_link != NULL)
-    /* Same as for the runpath_link above.  */
-    normalize_dirlist (&ld_state.rpath_link);
-
-
-  /* As a related task, handle the LD_LIBRARY_PATH value here.  First
-     we have to possibly split the value found (if it contains a
-     semicolon).  Then we have to split the value in list of
-     directories, i.e., split at the colons.  */
-  if (ld_library_path1 != NULL)
-    {
-      ld_library_path2 = strchr (ld_library_path1, ';');
-      if (ld_library_path2 == NULL)
-	{
-	  /* If no semicolon is present the directories are looked at
-	     after the -L parameters (-> ld_library_path2).  */
-	  ld_library_path2 = ld_library_path1;
-	  ld_library_path1 = NULL;
-	}
-      else
-	{
-	  /* NUL terminate the first part.  */
-	  *ld_library_path2++ = '\0';
-
-	  /* Convert the string value in a list.  */
-	  add_rxxpath (&ld_state.ld_library_path1, ld_library_path1);
-	  normalize_dirlist (&ld_state.ld_library_path1);
-	}
-
-      add_rxxpath (&ld_state.ld_library_path2, ld_library_path2);
-      normalize_dirlist (&ld_state.ld_library_path2);
-    }
-}
-
-
-static void
-read_version_script (const char *fname)
-{
-  /* Open the file.  The name is supposed to be the complete (relative
-     or absolute) path.  No search along a path will be performed.  */
-  ldin = fopen (fname, "r");
-  if (ldin == NULL)
-    error (EXIT_FAILURE, errno, gettext ("cannot read version script '%s'"),
-	   fname);
-  /* No need for locking.  */
-  __fsetlocking (ldin, FSETLOCKING_BYCALLER);
-
-  /* Tell the parser that this is a version script.  */
-  ld_scan_version_script = 1;
-
-  ldlineno = 1;
-  ldin_fname = fname;
-  if (ldparse () != 0)
-    /* Something went wrong during parsing.  */
-    exit (EXIT_FAILURE);
-
-  fclose (ldin);
-}
-
-
-static void
-create_lscript_symbols (void)
-{
-  /* Walk through the data from the linker script and generate all the
-     symbols which are required to be present and those marked
-     with PROVIDE if there is a undefined reference.  */
-  if (ld_state.output_segments == NULL)
-    return;
-
-  struct output_segment *segment = ld_state.output_segments->next;
-  do
-    {
-      struct output_rule *orule;
-
-      for (orule = segment->output_rules; orule != NULL; orule = orule->next)
-	if (orule->tag == output_assignment
-	    /* The assignments to "." (i.e., the PC) have to be
-	       ignored here.  */
-	    && strcmp (orule->val.assignment->variable, ".") != 0)
-	  {
-	    struct symbol *s = ld_state.unresolved;
-
-	    /* Check whether the symbol is needed.  */
-	    if (likely (s != NULL))
-	      {
-		struct symbol *first = s;
-		const char *providename = orule->val.assignment->variable;
-
-		/* Determine whether the provided symbol is still
-		   undefined.  */
-		// XXX TODO Loop inside a loop.  Gag!  Must rewrite.  */
-		do
-		  if (strcmp (s->name, providename) == 0)
-		    {
-		      /* Not defined but referenced.  */
-		      if (unlikely (!s->defined))
-			{
-			  /* Put on the list of symbols.  First remove it from
-			     whatever list it currently is on.  */
-			  CDBL_LIST_DEL (ld_state.unresolved, s);
-			  --ld_state.nunresolved;
-			  goto use_it;
-			}
-
-		      if (unlikely (!orule->val.assignment->provide_flag))
-			{
-			  /* The symbol is already defined and now again
-			     in the linker script.  This is an error.  */
-			  error (0, 0, gettext ("\
-duplicate definition of '%s' in linker script"),
-				 providename);
-			  goto next_rule;
-			}
-		    }
-		while ((s = s->next) != first);
-	      }
-
-	    /* If the symbol only has to be provided if it is needed,
-	       ignore it here since it is not undefined.  */
-	    if (orule->val.assignment->provide_flag)
-	      continue;
-
-	    /* Allocate memory for this new symbol.  */
-	    s = (struct symbol *)
-	      obstack_calloc (&ld_state.smem, sizeof (struct symbol));
-
-	    /* Initialize it.  */
-	    s->name = orule->val.assignment->variable;
-
-	    /* Insert it into the symbol hash table.  */
-	    unsigned long int hval = elf_hash (s->name);
-	    if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
-						hval, s) != 0))
-	      {
-		/* This means the symbol is defined somewhere else.
-		   Maybe it comes from a DSO or so.  Get the
-		   definition.  */
-		free (s);
-		struct symbol *old = ld_symbol_tab_find (&ld_state.symbol_tab,
-							 hval, s);
-		assert (old != NULL);
-		free (s);
-
-		/* If this is a definition from the application itself
-		   this means a duplicate definition.  */
-		if (! old->in_dso)
-		  {
-		    error (0, 0, gettext ("\
-duplicate definition of '%s' in linker script"),
-			   s->name);
-		    goto next_rule;
-		  }
-
-		/* We use the definition from the linker script.  */
-		s = old;
-	      }
-
-	  use_it:
-	    /* The symbol is (now) defined.  */
-	    s->defined = 1;
-	    s->type = STT_NOTYPE;
-
-	    /* Add a reference to the symbol record.  We will come
-	       across it when creating the output file.  */
-	    orule->val.assignment->sym = s;
-
-	    SNGL_LIST_PUSH (ld_state.lscript_syms, s);
-	    ++ld_state.nlscript_syms;
-
-	  next_rule:
-	    ;
-	  }
-
-      segment = segment->next;
-    }
-  while (segment != ld_state.output_segments->next);
-}
-
-
-/* Create creation of spection section symbols representing sections in the
-   output file.  This is done for symbols like _GLOBAL_OFFSET_TABLE_ and
-   _DYNAMIC.  */
-static void
-create_special_section_symbol (struct symbol **symp, const char *name)
-{
-  if (*symp == NULL)
-    {
-      /* No symbol defined found yet.  Create one.  */
-      struct symbol *newsym = (struct symbol *)
-	obstack_calloc (&ld_state.smem, sizeof (*newsym));
-
-      newsym->name = name;
-      // XXX Should we mark the symbol hidden?  They are hardly useful
-      // used outside the current object.
-
-      /* Add to the symbol table.  */
-      if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
-					  elf_hash (name), newsym) != 0))
-	abort ();
-
-      *symp = newsym;
-    }
-  else if ((*symp)->defined)
-    /* Cannot happen.  We do use this symbol from any input file.  */
-    abort ();
-
-  (*symp)->defined = 1;
-  (*symp)->local = 1;
-  (*symp)->hidden = 1;
-  (*symp)->type = STT_OBJECT;
-
-  ++ld_state.nsymtab;
-}
-
-
-#include "debugpred.h"
diff --git a/src/ld.h b/src/ld.h
deleted file mode 100644
index 29f4031..0000000
--- a/src/ld.h
+++ /dev/null
@@ -1,1135 +0,0 @@
-/* Copyright (C) 2001, 2002, 2003, 2005, 2006, 2008, 2009 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifndef LD_H
-#define LD_H	1
-
-#include <dlfcn.h>
-#include <obstack.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include "xelf.h"
-
-
-/* Recommended size of the buffer passed to ld_strerror.  */
-#define ERRBUFSIZE	(512)
-
-/* Character used to introduce version name after symbol.  */
-#define VER_CHR	'@'
-
-
-/* Methods for handling archives.  */
-enum extract_rule
-  {
-    defaultextract,	/* Weak references don't cause archive member to
-			   be used.  */
-    weakextract,	/* Weak references cause archive member to be
-			   extracted.  */
-    allextract		/* Extract all archive members regardless of
-			   references (aka whole-archive).  */
-  };
-
-
-/* Type of output file.  */
-enum file_type
-  {
-    no_file_type = 0,		/* None selected so far.  */
-    executable_file_type,	/* Executable.  */
-    dso_file_type,		/* DSO.  */
-    dso_needed_file_type,	/* DSO introduced by DT_NEEDED.  */
-    relocatable_file_type,	/* Relocatable object file.  */
-    archive_file_type		/* Archive (input only).  */
-  };
-
-
-struct usedfiles
-{
-  /* The next file given at the command line.  */
-  struct usedfiles *next;
-  /* Nonzero if this file is the beginning of a group.  */
-  bool group_start;
-  /* Nonzero if this file is the end of a group.  */
-  bool group_end;
-  /* Pointer to the beginning of the group.  It is necessary to
-     explain why we cannot simply use the 'next' pointer and have a
-     circular single-linked list like in many cases.  The problem is
-     that the last archive of the group, if it is the last file of the
-     group, contains the only existing pointer to the next file we
-     have to look at.  All files are initially connected via the
-     'next' pointer in a single-linked list.  Therefore we cannot
-     overwrite this value.  It instead will be used once the group is
-     handled and we go on processing the rest of the files.  */
-  struct usedfiles *group_backref;
-
-  /* Name/path of the file.  */
-  const char *fname;
-  /* Resolved file name.  */
-  const char *rfname;
-  /* Name used as reference in DT_NEEDED entries.  This is normally
-     the SONAME.  If it is missing it's normally the fname above.  */
-  const char *soname;
-  /* Handle for the SONAME in the string table.  */
-  struct Ebl_Strent *sonameent;
-
-  /* Help to identify duplicates.  */
-  dev_t dev;
-  ino_t ino;
-
-  enum
-    {
-      not_opened,
-      opened,
-      in_archive,
-      closed
-    } status;
-
-  /* How to extract elements from archives.  */
-  enum extract_rule extract_rule;
-
-  /* Lazy-loading rule.  */
-  bool lazyload;
-
-  /* If this is a DSO the flag indicates whether the file is directly
-     used in a reference.  */
-  bool used;
-
-  /* True when file should be added to DT_NEEDED list only when
-     directly referenced.  */
-  bool as_needed;
-
-  /* If nonzero this is the archive sequence number which can be used to
-     determine whether back refernces from -( -) or GROUP statements
-     have to be followed.  */
-  int archive_seq;
-
-  /* Pointer to the record for the archive containing this file.  */
-  struct usedfiles *archive_file;
-
-  /* Type of file.  We have to distinguish these types since they
-     are searched for differently.  */
-  enum file_type file_type;
-  /* This is the ELF library handle for this file.  */
-  Elf *elf;
-
-  /* The ELF header.  */
-#if NATIVE_ELF != 0
-  XElf_Ehdr *ehdr;
-# define FILEINFO_EHDR(fi) (*(fi))
-#else
-  XElf_Ehdr ehdr;
-# define FILEINFO_EHDR(fi) (fi)
-#endif
-
-  /* Index of the section header string table section.  We use a
-     separate field and not the e_shstrndx field in the ELF header
-     since in case of a file with more than 64000 sections the index
-     might be stored in the section header of section zero.  The
-     elf_getshdrstrndx() function can find the value but it is too
-     costly to repeat this call over and over.  */
-  size_t shstrndx;
-
-  /* Info about the sections of the file.  */
-  struct scninfo
-  {
-    /* Handle for the section.  Note that we can store a section
-       handle here because the file is not changing.  This together
-       with the knowledge about the libelf library is enough for us to
-       assume the section reference remains valid at all times.  */
-    Elf_Scn *scn;
-    /* Section header.  */
-#if NATIVE_ELF != 0
-    XElf_Shdr *shdr;
-# define SCNINFO_SHDR(si) (*(si))
-#else
-    XElf_Shdr shdr;
-# define SCNINFO_SHDR(si) (si)
-#endif
-    /* Offset of this files section in the combined section.  */
-    XElf_Off offset;
-    /* Index of the section in the output file.  */
-    Elf32_Word outscnndx;
-    /* Index of the output section in the 'allsection' array.  */
-    Elf32_Word allsectionsidx;
-    /* True if the section is used.  */
-    bool used;
-    /* True if section is an unused COMDAT section.  */
-    bool unused_comdat;
-    /* True if this is a COMDAT group section.  */
-    bool comdat_group;
-    /* Section group number.  This is the index of the SHT_GROUP section.  */
-    Elf32_Word grpid;
-    /* Pointer back to the containing file information structure.  */
-    struct usedfiles *fileinfo;
-    /* List of symbols in this section (set only for merge-able sections
-       and group sections).  */
-    struct symbol *symbols;
-    /* Size of relocations in this section.  Only used for relocation
-       sections.  */
-    size_t relsize;
-    /* Pointer to next section which is put in the given output
-       section.  */
-    struct scninfo *next;
-  } *scninfo;
-
-  /* List of section group sections.  */
-  struct scninfo *groups;
-
-  /* The symbol table section.
-
-     XXX Maybe support for more than one symbol table is needed.  */
-  Elf_Data *symtabdata;
-  /* Extra section index table section.  */
-  Elf_Data *xndxdata;
-  /* Dynamic symbol table section.  */
-  Elf_Data *dynsymtabdata;
-  /* The version number section.  */
-  Elf_Data *versymdata;
-  /* The defined versions.  */
-  Elf_Data *verdefdata;
-  /* Number of versions defined.  */
-  size_t nverdef;
-  /* True if the version with the given index number is used in the
-     output.  */
-  XElf_Versym *verdefused;
-  /* How many versions are used.  */
-  size_t nverdefused;
-  /* Handle for name of the version.  */
-  struct Ebl_Strent **verdefent;
-  /* The needed versions.  */
-  Elf_Data *verneeddata;
-  /* String table section associated with the symbol table.  */
-  Elf32_Word symstridx;
-  /* String table section associated with the dynamic symbol table.  */
-  Elf32_Word dynsymstridx;
-  /* Number of entries in the symbol table.  */
-  size_t nsymtab;
-  size_t nlocalsymbols;
-  size_t ndynsymtab;
-  /* Dynamic section.  */
-  Elf_Scn *dynscn;
-
-  /* Indirection table for the symbols defined here.  */
-  Elf32_Word *symindirect;
-  Elf32_Word *dynsymindirect;
-  /* For undefined or common symbols we need a reference to the symbol
-     record.  */
-  struct symbol **symref;
-  struct symbol **dynsymref;
-
-  /* This is the file descriptor.  The value is -1 if the descriptor
-     was already closed.  This can happen if we needed file descriptors
-     to open new files.  */
-  int fd;
-  /* This flag is true if the descriptor was passed to the generic
-     functions from somewhere else.  This is an implementation detail;
-     no machine-specific code must use this flag.  */
-  bool fd_passed;
-
-  /* True if any of the sections is merge-able.  */
-  bool has_merge_sections;
-};
-
-
-/* Functions to test for the various types of files we handle.  */
-static inline int
-ld_file_rel_p (struct usedfiles *file)
-{
-  return (elf_kind (file->elf) == ELF_K_ELF
-	  && FILEINFO_EHDR (file->ehdr).e_type == ET_REL);
-}
-
-static inline int
-ld_file_dso_p (struct usedfiles *file)
-{
-  return (elf_kind (file->elf) == ELF_K_ELF
-	  && FILEINFO_EHDR (file->ehdr).e_type == ET_DYN);
-}
-
-static inline int
-ld_file_ar_p (struct usedfiles *file)
-{
-  return elf_kind (file->elf) == ELF_K_AR;
-}
-
-
-struct pathelement
-{
-  /* The next path to search.  */
-  struct pathelement *next;
-  /* The path name.  */
-  const char *pname;
-  /* Larger than zero if the directory exists, smaller than zero if not,
-     zero if it is not yet known.  */
-  int exist;
-};
-
-
-/* Forward declaration.  */
-struct ld_state;
-
-
-/* Callback functions.  */
-struct callbacks
-{
-  /* Library names passed to the linker as -lXXX represent files named
-     libXXX.YY.  The YY part can have different forms, depending on the
-     architecture.  The generic set is .so and .a (in this order).  */
-  const char **(*lib_extensions) (struct ld_state *)
-       __attribute__ ((__const__));
-#define LIB_EXTENSION(state) \
-  DL_CALL_FCT ((state)->callbacks.lib_extensions, (state))
-
-  /* Process the given file.  If the file is not yet open, open it.
-     The first parameter is a file descriptor for the file which can
-     be -1 to indicate the file has not yet been found.  The second
-     parameter describes the file to be opened, the last one is the
-     state of the linker which among other information contain the
-     paths we look at.*/
-  int (*file_process) (int fd, struct usedfiles *, struct ld_state *,
-		       struct usedfiles **);
-#define FILE_PROCESS(fd, file, state, nextp) \
-  DL_CALL_FCT ((state)->callbacks.file_process, (fd, file, state, nextp))
-
-  /* Close the given file.  */
-  int (*file_close) (struct usedfiles *, struct ld_state *);
-#define FILE_CLOSE(file, state) \
-  DL_CALL_FCT ((state)->callbacks.file_close, (file, state))
-
-  /* Create the output sections now.  This requires knowledge about
-     all the sections we will need.  It may be necessary to sort the
-     sections in the order they are supposed to appear in the
-     executable.  The sorting use many different kinds of information
-     to optimize the resulting binary.  Important is to respect
-     segment boundaries and the needed alignment.  The mode of the
-     segments will be determined afterwards automatically by the
-     output routines.  */
-  void (*create_sections) (struct ld_state *);
-#define CREATE_SECTIONS(state) \
-  DL_CALL_FCT ((state)->callbacks.create_sections, (state))
-
-  /* Determine whether we have any non-weak unresolved references left.  */
-  int (*flag_unresolved) (struct ld_state *);
-#define FLAG_UNRESOLVED(state) \
-  DL_CALL_FCT ((state)->callbacks.flag_unresolved, (state))
-
-  /* Create the sections which are generated by the linker and are not
-     present in the input file.  */
-  void (*generate_sections) (struct ld_state *);
-#define GENERATE_SECTIONS(state) \
-  DL_CALL_FCT ((state)->callbacks.generate_sections, (state))
-
-  /* Open the output file.  The file name is given or "a.out".  We
-     create as much of the ELF structure as possible.  */
-  int (*open_outfile) (struct ld_state *, int, int, int);
-#define OPEN_OUTFILE(state, machine, class, data) \
-  DL_CALL_FCT ((state)->callbacks.open_outfile, (state, machine, class, data))
-
-  /* Create the data for the output file.  */
-  int (*create_outfile) (struct ld_state *);
-#define CREATE_OUTFILE(state) \
-  DL_CALL_FCT ((state)->callbacks.create_outfile, (state))
-
-  /* Process a relocation section.  */
-  void (*relocate_section) (struct ld_state *, Elf_Scn *, struct scninfo *,
-			    const Elf32_Word *);
-#define RELOCATE_SECTION(state, outscn, first, dblindirect) \
-  DL_CALL_FCT ((state)->callbacks.relocate_section, (state, outscn, first,    \
-						     dblindirect))
-
-  /* Allocate a data buffer for the relocations of the given output
-     section.  */
-  void (*count_relocations) (struct ld_state *, struct scninfo *);
-#define COUNT_RELOCATIONS(state, scninfo) \
-  DL_CALL_FCT ((state)->callbacks.count_relocations, (state, scninfo))
-
-  /* Create relocations for executable or DSO.  */
-  void (*create_relocations) (struct ld_state *, const Elf32_Word *);
-#define CREATE_RELOCATIONS(state, dlbindirect) \
-  DL_CALL_FCT ((state)->callbacks.create_relocations, (state, dblindirect))
-
-  /* Finalize the output file.  */
-  int (*finalize) (struct ld_state *);
-#define FINALIZE(state) \
-  DL_CALL_FCT ((state)->callbacks.finalize, (state))
-
-  /* Check whether special section number is known.  */
-  bool (*special_section_number_p) (struct ld_state *, size_t);
-#define SPECIAL_SECTION_NUMBER_P(state, number) \
-  DL_CALL_FCT ((state)->callbacks.special_section_number_p, (state, number))
-
-  /* Check whether section type is known.  */
-  bool (*section_type_p) (struct ld_state *, XElf_Word);
-#define SECTION_TYPE_P(state, type) \
-  DL_CALL_FCT ((state)->callbacks.section_type_p, (state, type))
-
-  /* Return section flags for .dynamic section.  */
-  XElf_Xword (*dynamic_section_flags) (struct ld_state *);
-#define DYNAMIC_SECTION_FLAGS(state) \
-  DL_CALL_FCT ((state)->callbacks.dynamic_section_flags, (state))
-
-  /* Create the data structures for the .plt section and initialize it.  */
-  void (*initialize_plt) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_PLT(state, scn) \
-  DL_CALL_FCT ((state)->callbacks.initialize_plt, (state, scn))
-
-  /* Create the data structures for the .rel.plt section and initialize it.  */
-  void (*initialize_pltrel) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_PLTREL(state, scn) \
-  DL_CALL_FCT ((state)->callbacks.initialize_pltrel, (state, scn))
-
-  /* Finalize the .plt section the what belongs to them.  */
-  void (*finalize_plt) (struct ld_state *, size_t, size_t, struct symbol **);
-#define FINALIZE_PLT(state, nsym, nsym_dyn, ndxtosym) \
-  DL_CALL_FCT ((state)->callbacks.finalize_plt, (state, nsym, nsym_dyn, \
-						 ndxtosym))
-
-  /* Create the data structures for the .got section and initialize it.  */
-  void (*initialize_got) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_GOT(state, scn) \
-  DL_CALL_FCT ((state)->callbacks.initialize_got, (state, scn))
-
-  /* Create the data structures for the .got.plt section and initialize it.  */
-  void (*initialize_gotplt) (struct ld_state *, Elf_Scn *scn);
-#define INITIALIZE_GOTPLT(state, scn) \
-  DL_CALL_FCT ((state)->callbacks.initialize_gotplt, (state, scn))
-
-  /* Return the tag corresponding to the native relocation type for
-     the platform.  */
-  int (*rel_type) (struct ld_state *);
-#define REL_TYPE(state) \
-  DL_CALL_FCT ((state)->callbacks.rel_type, (state))
-};
-
-
-/* Structure for symbol representation.  This data structure is used a
-   lot, so size is important.  */
-struct symbol
-{
-  /* Symbol name.  */
-  const char *name;
-  /* Size of the object.  */
-  XElf_Xword size;
-  /* Index of the symbol in the symbol table of the object.  */
-  size_t symidx;
-  /* Index of the symbol in the symbol table of the output file.  */
-  size_t outsymidx;
-
-  /* Description where the symbol is found/needed.  */
-  size_t scndx;
-  struct usedfiles *file;
-  /* Index of the symbol table.  */
-  Elf32_Word symscndx;
-
-  /* Index of the symbol in the dynamic symbol table of the output
-     file.  Note that the value only needs to be 16 bit wide since
-     there cannot be more sections in an executable or DSO.  */
-  unsigned int outdynsymidx:16;
-
-  /* Type of the symbol.  */
-  unsigned int type:4;
-  /* Various flags.  */
-  unsigned int defined:1;
-  unsigned int common:1;
-  unsigned int weak:1;
-  unsigned int added:1;
-  unsigned int merged:1;
-  unsigned int local:1;
-  unsigned int hidden:1;
-  /* Nonzero if the symbol is on the from_dso list.  */
-  unsigned int on_dsolist:1;
-  /* Nonzero if symbol needs copy relocation, reset when the
-     relocation has been created.  */
-  unsigned int need_copy:1;
-  unsigned int in_dso:1;
-
-  union
-  {
-    /* Pointer to the handle created by the functions which create
-       merged section contents.  We use 'void *' because there are
-       different implementations used.  */
-    void *handle;
-    XElf_Addr value;
-  } merge;
-
-  /* Pointer to next/previous symbol on whatever list the symbol is.  */
-  struct symbol *next;
-  struct symbol *previous;
-  /* Pointer to next symbol of the same section (only set for merge-able
-     sections).  */
-  struct symbol *next_in_scn;
-};
-
-
-/* Get the definition for the symbol table.  */
-#include <symbolhash.h>
-
-/* Simple single linked list of file names.  */
-struct filename_list
-{
-  const char *name;
-  struct usedfiles *real;
-  struct filename_list *next;
-  bool group_start;
-  bool group_end;
-  bool as_needed;
-};
-
-
-/* Data structure to describe expression in linker script.  */
-struct expression
-{
-  enum expression_tag
-    {
-      exp_num,
-      exp_sizeof_headers,
-      exp_pagesize,
-      exp_id,
-      exp_mult,
-      exp_div,
-      exp_mod,
-      exp_plus,
-      exp_minus,
-      exp_and,
-      exp_or,
-      exp_align
-    } tag;
-
-  union
-  {
-    uintmax_t num;
-    struct expression *child;
-    struct
-    {
-      struct expression *left;
-      struct expression *right;
-    } binary;
-    const char *str;
-  } val;
-};
-
-
-/* Data structure for section name with flags.  */
-struct input_section_name
-{
-  const char *name;
-  bool sort_flag;
-};
-
-/* File name mask with section name.  */
-struct filemask_section_name
-{
-  const char *filemask;
-  const char *excludemask;
-  struct input_section_name *section_name;
-  bool keep_flag;
-};
-
-/* Data structure for assignments.  */
-struct assignment
-{
-  const char *variable;
-  struct expression *expression;
-  struct symbol *sym;
-  bool provide_flag;
-};
-
-
-/* Data structure describing input for an output section.  */
-struct input_rule
-{
-  enum
-    {
-      input_section,
-      input_assignment
-    } tag;
-
-  union
-  {
-    struct assignment *assignment;
-    struct filemask_section_name *section;
-  } val;
-
-  struct input_rule *next;
-};
-
-
-/* Data structure to describe output section.  */
-struct output_section
-{
-  const char *name;
-  struct input_rule *input;
-  XElf_Addr max_alignment;
-  bool ignored;
-};
-
-
-/* Data structure to describe output file format.  */
-struct output_rule
-{
-  enum
-    {
-      output_section,
-      output_assignment
-    } tag;
-
-  union
-  {
-    struct assignment *assignment;
-    struct output_section section;
-  } val;
-
-  struct output_rule *next;
-};
-
-
-/* List of all the segments the linker script describes.  */
-struct output_segment
-{
-  int mode;
-  struct output_rule *output_rules;
-  struct output_segment *next;
-
-  XElf_Off offset;
-  XElf_Addr addr;
-  XElf_Xword align;
-};
-
-
-/* List of identifiers.  */
-struct id_list
-{
-  union
-  {
-    enum id_type
-      {
-	id_str,		/* Normal string.  */
-	id_all,		/* "*", matches all.  */
-	id_wild		/* Globbing wildcard string.  */
-      } id_type;
-    struct
-    {
-      bool local;
-      const char *versionname;
-    } s;
-  } u;
-  const char *id;
-  struct id_list *next;
-};
-
-
-/* Version information.  */
-struct version
-{
-  struct version *next;
-  struct id_list *local_names;
-  struct id_list *global_names;
-  const char *versionname;
-  const char *parentname;
-};
-
-
-/* Head for list of sections.  */
-struct scnhead
-{
-  /* Name of the sections.  */
-  const char *name;
-
-  /* Accumulated flags for the sections.  */
-  XElf_Xword flags;
-
-  /* Type of the sections.  */
-  XElf_Word type;
-
-  /* Entry size.  If there are differencs between the sections with
-     the same name this field contains 1.  */
-  XElf_Word entsize;
-
-  /* If non-NULL pointer to group signature.  */
-  const char *grp_signature;
-
-  /* Maximum alignment for all sections.  */
-  XElf_Word align;
-
-  /* Distinguish between normal sections coming from the input file
-     and sections generated by the linker.  */
-  enum scn_kind
-    {
-      scn_normal,		/* Section from the input file(s).  */
-      scn_dot_interp,		/* Generated .interp section.  */
-      scn_dot_got,		/* Generated .got section.  */
-      scn_dot_gotplt,		/* Generated .got.plt section.  */
-      scn_dot_dynrel,		/* Generated .rel.dyn section.  */
-      scn_dot_dynamic,		/* Generated .dynamic section.  */
-      scn_dot_dynsym,		/* Generated .dynsym section.  */
-      scn_dot_dynstr,		/* Generated .dynstr section.  */
-      scn_dot_hash,		/* Generated .hash section.  */
-      scn_dot_gnu_hash,		/* Generated .gnu.hash section.  */
-      scn_dot_plt,		/* Generated .plt section.  */
-      scn_dot_pltrel,		/* Generated .rel.plt section.  */
-      scn_dot_version,		/* Generated .gnu.version section.  */
-      scn_dot_version_r,	/* Generated .gnu.version_r section.  */
-      scn_dot_note_gnu_build_id	/* Generated .note.gnu.build-id section.  */
-    } kind;
-
-  /* True is the section is used in the output.  */
-  bool used;
-
-  /* Total size (only determined this way for relocation sections).  */
-  size_t relsize;
-
-  /* Filled in by the section sorting to indicate which segment the
-     section goes in.  */
-  int segment_nr;
-
-  /* Index of the output section.  We cannot store the section handle
-     directly here since the handle is a pointer in a dynamically
-     allocated table which might move if it becomes too small for all
-     the sections.  Using the index the correct value can be found at
-     all times.  */
-  XElf_Word scnidx;
-
-  /* Index of the STT_SECTION entry for this section in the symbol
-     table.  */
-  XElf_Word scnsymidx;
-
-  /* Address of the section in the output file.  */
-  XElf_Addr addr;
-
-  /* Handle for the section name in the output file's section header
-     string table.  */
-  struct Ebl_Strent *nameent;
-
-  /* Tail of list of symbols for this section.  Only set if the
-     section is merge-able.  */
-  struct symbol *symbols;
-
-  /* Pointer to last section.  */
-  struct scninfo *last;
-};
-
-
-/* Define hash table for sections.  */
-#include <sectionhash.h>
-
-/* Define hash table for version symbols.  */
-#include <versionhash.h>
-
-
-/* State of the linker.  */
-struct ld_state
-{
-  /* ELF backend library handle.  */
-  Ebl *ebl;
-
-  /* List of all archives participating, in this order.  */
-  struct usedfiles *archives;
-  /* End of the list.  */
-  struct usedfiles *tailarchives;
-  /* If nonzero we are looking for the beginning of a group.  */
-  bool group_start_requested;
-  /* Pointer to the archive starting the group.  */
-  struct usedfiles *group_start_archive;
-
-  /* List of the DSOs we found.  */
-  struct usedfiles *dsofiles;
-  /* Number of DSO files.  */
-  size_t ndsofiles;
-  /* Ultimate list of object files which are linked in.  */
-  struct usedfiles *relfiles;
-
-  /* List the DT_NEEDED DSOs.  */
-  struct usedfiles *needed;
-
-  /* Temporary storage for the parser.  */
-  struct filename_list *srcfiles;
-
-  /* List of all the paths to look at.  */
-  struct pathelement *paths;
-  /* Tail of the list.  */
-  struct pathelement *tailpaths;
-
-  /* User provided paths for lookup of DSOs.  */
-  struct pathelement *rpath;
-  struct pathelement *rpath_link;
-  struct pathelement *runpath;
-  struct pathelement *runpath_link;
-  struct Ebl_Strent *rxxpath_strent;
-  int rxxpath_tag;
-
-  /* From the environment variable LD_LIBRARY_PATH.  */
-  struct pathelement *ld_library_path1;
-  struct pathelement *ld_library_path2;
-
-  /* Name of the output file.  */
-  const char *outfname;
-  /* Name of the temporary file we initially create.  */
-  const char *tempfname;
-  /* File descriptor opened for the output file.  */
-  int outfd;
-  /* The ELF descriptor for the output file.  */
-  Elf *outelf;
-
-  /* Type of output file.  */
-  enum file_type file_type;
-
-  /* Is this a system library or not.  */
-  bool is_system_library;
-
-  /* Page size to be assumed for the binary.  */
-  size_t pagesize;
-
-  /* Name of the interpreter for dynamically linked objects.  */
-  const char *interp;
-  /* Index of the .interp section.  */
-  Elf32_Word interpscnidx;
-
-  /* Optimization level.  */
-  unsigned long int optlevel;
-
-  /* If true static linking is requested.  */
-  bool statically;
-
-  /* If true, add DT_NEEDED entries for following files if they are
-     needed.  */
-  bool as_needed;
-
-  /* How to extract elements from archives.  */
-  enum extract_rule extract_rule;
-
-  /* Sequence number of the last archive we used.  */
-  int last_archive_used;
-
-  /* If true print to stdout information about the files we are
-     trying to open.  */
-  bool trace_files;
-
-  /* If true multiple definitions are not considered an error; the
-     first is used.  */
-  bool muldefs;
-
-  /* If true undefined symbols when building DSOs are not fatal.  */
-  bool nodefs;
-
-  /* If true add line indentifying link-editor to .comment section.  */
-  bool add_ld_comment;
-
-  /* Stripping while linking.  */
-  enum
-    {
-      strip_none,
-      strip_debug,
-      strip_all,
-      strip_everything
-    } strip;
-
-  /* The callback function vector.  */
-  struct callbacks callbacks;
-
-  /* Name of the entry symbol.  Can also be a numeric value.  */
-  const char *entry;
-
-  /* The description of the segments in the output file.  */
-  struct output_segment *output_segments;
-
-  /* List of the symbols we created from linker script definitions.  */
-  struct symbol *lscript_syms;
-  size_t nlscript_syms;
-
-  /* Table with known symbols.  */
-  ld_symbol_tab symbol_tab;
-
-  /* Table with used sections.  */
-  ld_section_tab section_tab;
-
-  /* The list of sections once we collected them.   */
-  struct scnhead **allsections;
-  size_t nallsections;
-  size_t nusedsections;
-  size_t nnotesections;
-
-  /* Beginning of the list of symbols which are still unresolved.  */
-  struct symbol *unresolved;
-  /* Number of truely unresolved entries in the list.  */
-  size_t nunresolved;
-  /* Number of truely unresolved, non-weak entries in the list.  */
-  size_t nunresolved_nonweak;
-
-  /* List of common symbols.  */
-  struct symbol *common_syms;
-  /* Section for the common symbols.  */
-  struct scninfo *common_section;
-
-  /* List of symbols defined in DSOs and used in a relocatable file.
-     DSO symbols not referenced in the relocatable files are not on
-     the list.  If a symbol is on the list the on_dsolist field in the
-     'struct symbol' is nonzero.  */
-  struct symbol *from_dso;
-  /* Number of entries in from_dso.  */
-  size_t nfrom_dso;
-  /* Number of entries in the dynamic symbol table.  */
-  size_t ndynsym;
-  /* Number of PLT entries from DSO references.  */
-  size_t nplt;
-  /* Number of PLT entries from DSO references.  */
-  size_t ngot;
-  /* Number of copy relocations.  */
-  size_t ncopy;
-  /* Section for copy relocations.  */
-  struct scninfo *copy_section;
-
-  /* Keeping track of the number of symbols in the output file.  */
-  size_t nsymtab;
-  size_t nlocalsymbols;
-
-  /* Special symbols.  */
-  struct symbol *init_symbol;
-  struct symbol *fini_symbol;
-
-  /* The description of the segments in the output file as described
-     in the default linker script.  This information will be used in
-     addition to the user-provided information.  */
-  struct output_segment *default_output_segments;
-  /* Search paths added by the default linker script.  */
-  struct pathelement *default_paths;
-
-#ifndef BASE_ELF_NAME
-  /* The handle of the ld backend library.  */
-  void *ldlib;
-#endif
-
-  /* String table for the section headers.  */
-  struct Ebl_Strtab *shstrtab;
-
-  /* True if output file should contain symbol table.  */
-  bool need_symtab;
-  /* Symbol table section.  */
-  Elf32_Word symscnidx;
-  /* Extended section table section.  */
-  Elf32_Word xndxscnidx;
-  /* Symbol string table section.  */
-  Elf32_Word strscnidx;
-
-  /* True if output file should contain dynamic symbol table.  */
-  bool need_dynsym;
-  /* Dynamic symbol table section.  */
-  Elf32_Word dynsymscnidx;
-  /* Dynamic symbol string table section.  */
-  Elf32_Word dynstrscnidx;
-  /* Dynamic symbol hash tables.  */
-  size_t hashscnidx;
-  size_t gnuhashscnidx;
-
-  /* Procedure linkage table section.  */
-  Elf32_Word pltscnidx;
-  /* Number of entries already in the PLT section.  */
-  size_t nplt_used;
-  /* Relocation for procedure linkage table section.  */
-  Elf32_Word pltrelscnidx;
-
-  /* Global offset table section.  */
-  Elf32_Word gotscnidx;
-  /* And the part of the PLT.  */
-  Elf32_Word gotpltscnidx;
-
-  /* This section will hole all non-PLT relocations.  */
-  Elf32_Word reldynscnidx;
-
-  /* Index of the sections to handle versioning.  */
-  Elf32_Word versymscnidx;
-  Elf32_Word verneedscnidx;
-  /* XXX Should the following names be verneed...?  */
-  /* Number of version definitions in input DSOs used.  */
-  int nverdefused;
-  /* Number of input DSOs using versioning.  */
-  int nverdeffile;
-  /* Index of next version.  */
-  int nextveridx;
-
-  /* TLS segment.  */
-  bool need_tls;
-  XElf_Addr tls_start;
-  XElf_Addr tls_tcb;
-
-  /* Hash table for version symbol strings.  Only strings without
-     special characters are hashed here.  */
-  ld_version_str_tab version_str_tab;
-  /* At most one of the following two variables is set to true if either
-     global or local symbol binding is selected as the default.  */
-  bool default_bind_local;
-  bool default_bind_global;
-
-  /* Execuatable stack selection.  */
-  enum execstack
-    {
-      execstack_false = 0,
-      execstack_true,
-      execstack_false_force
-    } execstack;
-
-  /* True if only used sections are used.  */
-  bool gc_sections;
-
-  /* Array to determine final index of symbol.  */
-  Elf32_Word *dblindirect;
-
-  /* Section group handling.  */
-  struct scngroup
-  {
-    Elf32_Word outscnidx;
-    int nscns;
-    struct member
-    {
-      struct scnhead *scn;
-      struct member *next;
-    } *member;
-    struct Ebl_Strent *nameent;
-    struct symbol *symbol;
-    struct scngroup *next;
-  } *groups;
-
-  /* True if the output file needs a .got section.  */
-  bool need_got;
-  /* Number of relocations for GOT section caused.  */
-  size_t nrel_got;
-
-  /* Number of entries needed in the .dynamic section.  */
-  int ndynamic;
-  /* To keep track of added entries.  */
-  int ndynamic_filled;
-  /* Index for the dynamic section.  */
-  Elf32_Word dynamicscnidx;
-
-  /* Flags set in the DT_FLAGS word.  */
-  Elf32_Word dt_flags;
-  /* Flags set in the DT_FLAGS_1 word.  */
-  Elf32_Word dt_flags_1;
-  /* Flags set in the DT_FEATURE_1 word.  */
-  Elf32_Word dt_feature_1;
-
-  /* Lazy-loading state for dependencies.  */
-  bool lazyload;
-
-  /* True if an .eh_frame_hdr section should be generated.  */
-  bool eh_frame_hdr;
-
-  /* What hash style to generate.  */
-  enum
-    {
-      hash_style_none = 0,
-      hash_style_sysv = 1,
-#define GENERATE_SYSV_HASH ((ld_state.hash_style & hash_style_sysv) != 0)
-      hash_style_gnu = 2
-#define GENERATE_GNU_HASH ((ld_state.hash_style & hash_style_gnu) != 0)
-    }
-  hash_style;
-
-
-  /* True if in executables all global symbols should be exported in
-     the dynamic symbol table.  */
-  bool export_all_dynamic;
-
-  /* Build-ID style.  NULL is none.  */
-  const char *build_id;
-  Elf32_Word buildidscnidx;
-
-  /* If DSO is generated, this is the SONAME.  */
-  const char *soname;
-
-  /* List of all relocation sections.  */
-  struct scninfo *rellist;
-  /* Total size of non-PLT relocations.  */
-  size_t relsize_total;
-
-  /* Record for the GOT symbol, if known.  */
-  struct symbol *got_symbol;
-  /* Record for the dynamic section symbol, if known.  */
-  struct symbol *dyn_symbol;
-
-  /* Obstack used for small objects which will not be deleted.  */
-  struct obstack smem;
-};
-
-
-/* The interface to the scanner.  */
-
-/* Parser entry point.  */
-extern int ldparse (void);
-
-/* The input file.  */
-extern FILE *ldin;
-
-/* Name of the input file.  */
-extern const char *ldin_fname;
-
-/* Current line number.  Must be reset for a new file.  */
-extern int ldlineno;
-
-/* If nonzero we are currently parsing a version script.  */
-extern int ld_scan_version_script;
-
-/* Flags defined in ld.c.  */
-extern int verbose;
-extern int conserve_memory;
-
-
-/* Linker state.  This contains all global information.  */
-extern struct ld_state ld_state;
-
-
-/* Generic ld helper functions.  */
-
-/* Append a new directory to search libraries in.  */
-extern void ld_new_searchdir (const char *dir);
-
-/* Append a new file to the list of input files.  */
-extern struct usedfiles *ld_new_inputfile (const char *fname,
-					   enum file_type type);
-
-
-/* These are the generic implementations for the callbacks used by ld.  */
-
-/* Initialize state object.  This callback function is called after the
-   parameters are parsed but before any file is searched for.  */
-extern int ld_prepare_state (const char *emulation);
-
-
-/* Function to determine whether an object will be dynamically linked.  */
-extern bool dynamically_linked_p (void);
-
-/* Helper functions for the architecture specific code.  */
-
-/* Checked whether the symbol is undefined and referenced from a DSO.  */
-extern bool linked_from_dso_p (struct scninfo *scninfo, size_t symidx);
-#ifdef __GNUC_STDC_INLINE__
-__attribute__ ((__gnu_inline__))
-#endif
-extern inline bool
-linked_from_dso_p (struct scninfo *scninfo, size_t symidx)
-{
-  struct usedfiles *file = scninfo->fileinfo;
-
-  /* If this symbol is not undefined in this file it cannot come from
-     a DSO.  */
-  if (symidx < file->nlocalsymbols)
-    return false;
-
-  struct symbol *sym = file->symref[symidx];
-
-  return sym->defined && sym->in_dso;
-}
-
-#endif	/* ld.h */
diff --git a/src/ldgeneric.c b/src/ldgeneric.c
deleted file mode 100644
index 1b5d0f9..0000000
--- a/src/ldgeneric.c
+++ /dev/null
@@ -1,7132 +0,0 @@
-/* Copyright (C) 2001-2011 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <dlfcn.h>
-#include <errno.h>
-#include <error.h>
-#include <fcntl.h>
-#include <fnmatch.h>
-#include <gelf.h>
-#include <inttypes.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdio_ext.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/param.h>
-#include <sys/stat.h>
-
-#include <elf-knowledge.h>
-#include "ld.h"
-#include "list.h"
-#include <md5.h>
-#include <sha1.h>
-#include <system.h>
-
-
-/* Header of .eh_frame_hdr section.  */
-struct unw_eh_frame_hdr
-{
-  unsigned char version;
-  unsigned char eh_frame_ptr_enc;
-  unsigned char fde_count_enc;
-  unsigned char table_enc;
-};
-#define EH_FRAME_HDR_VERSION 1
-
-
-/* Prototypes for local functions.  */
-static const char **ld_generic_lib_extensions (struct ld_state *)
-     __attribute__ ((__const__));
-static int ld_generic_file_close (struct usedfiles *fileinfo,
-				  struct ld_state *statep);
-static int ld_generic_file_process (int fd, struct usedfiles *fileinfo,
-				    struct ld_state *statep,
-				    struct usedfiles **nextp);
-static void ld_generic_generate_sections (struct ld_state *statep);
-static void ld_generic_create_sections (struct ld_state *statep);
-static int ld_generic_flag_unresolved (struct ld_state *statep);
-static int ld_generic_open_outfile (struct ld_state *statep, int machine,
-				    int class, int data);
-static int ld_generic_create_outfile (struct ld_state *statep);
-static void ld_generic_relocate_section (struct ld_state *statep,
-					 Elf_Scn *outscn,
-					 struct scninfo *firstp,
-					 const Elf32_Word *dblindirect);
-static int ld_generic_finalize (struct ld_state *statep);
-static bool ld_generic_special_section_number_p (struct ld_state *statep,
-						 size_t number);
-static bool ld_generic_section_type_p (struct ld_state *statep,
-				       XElf_Word type);
-static XElf_Xword ld_generic_dynamic_section_flags (struct ld_state *statep);
-static void ld_generic_initialize_plt (struct ld_state *statep, Elf_Scn *scn);
-static void ld_generic_initialize_pltrel (struct ld_state *statep,
-					  Elf_Scn *scn);
-static void ld_generic_initialize_got (struct ld_state *statep, Elf_Scn *scn);
-static void ld_generic_initialize_gotplt (struct ld_state *statep,
-					  Elf_Scn *scn);
-static void ld_generic_finalize_plt (struct ld_state *statep, size_t nsym,
-				     size_t nsym_dyn,
-				     struct symbol **ndxtosymp);
-static int ld_generic_rel_type (struct ld_state *statep);
-static void ld_generic_count_relocations (struct ld_state *statep,
-					  struct scninfo *scninfo);
-static void ld_generic_create_relocations (struct ld_state *statep,
-					   const Elf32_Word *dblindirect);
-
-static int file_process2 (struct usedfiles *fileinfo);
-static void mark_section_used (struct scninfo *scninfo, Elf32_Word shndx,
-			       struct scninfo **grpscnp);
-
-
-/* Map symbol index to struct symbol record.  */
-static struct symbol **ndxtosym;
-
-/* String table reference to all symbols in the symbol table.  */
-static struct Ebl_Strent **symstrent;
-
-
-/* Check whether file associated with FD is a DSO.  */
-static bool
-is_dso_p (int fd)
-{
-  /* We have to read the 'e_type' field.  It has the same size (16
-     bits) in 32- and 64-bit ELF.  */
-  XElf_Half e_type;
-
-  return (pread (fd, &e_type, sizeof (e_type), offsetof (XElf_Ehdr, e_type))
-	  == sizeof (e_type)
-	  && e_type == ET_DYN);
-}
-
-
-/* Print the complete name of a file, including the archive it is
-   contained in.  */
-static int
-print_file_name (FILE *s, struct usedfiles *fileinfo, int first_level,
-		 int newline)
-{
-  int npar = 0;
-
-  if (fileinfo->archive_file != NULL)
-    {
-      npar = print_file_name (s, fileinfo->archive_file, 0, 0) + 1;
-      fputc_unlocked ('(', s);
-      fputs_unlocked (fileinfo->rfname, s);
-
-      if (first_level)
-	while (npar-- > 0)
-	  fputc_unlocked (')', s);
-    }
-  else
-    fputs_unlocked (fileinfo->rfname, s);
-
-  if (first_level && newline)
-    fputc_unlocked ('\n', s);
-
-  return npar;
-}
-
-
-/* Function to determine whether an object will be dynamically linked.  */
-bool
-dynamically_linked_p (void)
-{
-  return (ld_state.file_type == dso_file_type || ld_state.nplt > 0
-	  || ld_state.ngot > 0);
-}
-
-
-bool
-linked_from_dso_p (struct scninfo *scninfo, size_t symidx)
-{
-  struct usedfiles *file = scninfo->fileinfo;
-
-  /* If this symbol is not undefined in this file it cannot come from
-     a DSO.  */
-  if (symidx < file->nlocalsymbols)
-    return false;
-
-  struct symbol *sym = file->symref[symidx];
-
-  return sym->defined && sym->in_dso;
-}
-
-
-/* Initialize state object.  This callback function is called after the
-   parameters are parsed but before any file is searched for.  */
-int
-ld_prepare_state (const char *emulation)
-{
-  /* When generating DSO we normally allow undefined symbols.  */
-  ld_state.nodefs = true;
-
-  /* To be able to detect problems we add a .comment section entry by
-     default.  */
-  ld_state.add_ld_comment = true;
-
-  /* XXX We probably should find a better place for this.  The index
-     of the first user-defined version is 2.  */
-  ld_state.nextveridx = 2;
-
-  /* Pick an not too small number for the initial size of the tables.  */
-  ld_symbol_tab_init (&ld_state.symbol_tab, 1027);
-  ld_section_tab_init (&ld_state.section_tab, 67);
-  ld_version_str_tab_init (&ld_state.version_str_tab, 67);
-
-  /* Initialize the section header string table.  */
-  ld_state.shstrtab = ebl_strtabinit (true);
-  if (ld_state.shstrtab == NULL)
-    error (EXIT_FAILURE, errno, gettext ("cannot create string table"));
-
-  /* Initialize the callbacks.  These are the defaults, the appropriate
-     backend can later install its own callbacks.  */
-  ld_state.callbacks.lib_extensions = ld_generic_lib_extensions;
-  ld_state.callbacks.file_process = ld_generic_file_process;
-  ld_state.callbacks.file_close = ld_generic_file_close;
-  ld_state.callbacks.generate_sections = ld_generic_generate_sections;
-  ld_state.callbacks.create_sections = ld_generic_create_sections;
-  ld_state.callbacks.flag_unresolved = ld_generic_flag_unresolved;
-  ld_state.callbacks.open_outfile = ld_generic_open_outfile;
-  ld_state.callbacks.create_outfile = ld_generic_create_outfile;
-  ld_state.callbacks.relocate_section = ld_generic_relocate_section;
-  ld_state.callbacks.finalize = ld_generic_finalize;
-  ld_state.callbacks.special_section_number_p =
-    ld_generic_special_section_number_p;
-  ld_state.callbacks.section_type_p = ld_generic_section_type_p;
-  ld_state.callbacks.dynamic_section_flags = ld_generic_dynamic_section_flags;
-  ld_state.callbacks.initialize_plt = ld_generic_initialize_plt;
-  ld_state.callbacks.initialize_pltrel = ld_generic_initialize_pltrel;
-  ld_state.callbacks.initialize_got = ld_generic_initialize_got;
-  ld_state.callbacks.initialize_gotplt = ld_generic_initialize_gotplt;
-  ld_state.callbacks.finalize_plt = ld_generic_finalize_plt;
-  ld_state.callbacks.rel_type = ld_generic_rel_type;
-  ld_state.callbacks.count_relocations = ld_generic_count_relocations;
-  ld_state.callbacks.create_relocations = ld_generic_create_relocations;
-
-#ifndef BASE_ELF_NAME
-  /* Find the ld backend library.  Use EBL to determine the name if
-     the user hasn't provided one on the command line.  */
-  if (emulation == NULL)
-    {
-      emulation = ebl_backend_name (ld_state.ebl);
-      assert (emulation != NULL);
-    }
-  size_t emulation_len = strlen (emulation);
-
-  /* Construct the file name.  */
-  char *fname = (char *) alloca (sizeof "libld_" - 1 + emulation_len
-				 + sizeof ".so");
-  strcpy (mempcpy (stpcpy (fname, "libld_"), emulation, emulation_len), ".so");
-
-  /* Try loading.  */
-  void *h = dlopen (fname, RTLD_LAZY);
-  if (h == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot load ld backend library '%s': %s"),
-	   fname, dlerror ());
-
-  /* Find the initializer.  It must be present.  */
-  char *initname = (char *) alloca (emulation_len + sizeof "_ld_init");
-  strcpy (mempcpy (initname, emulation, emulation_len), "_ld_init");
-  int (*initfct) (struct ld_state *)
-    = (int (*) (struct ld_state *)) dlsym (h, initname);
-
-  if (initfct == NULL)
-    error (EXIT_FAILURE, 0, gettext ("\
-cannot find init function in ld backend library '%s': %s"),
-	   fname, dlerror ());
-
-  /* Store the handle.  */
-  ld_state.ldlib = h;
-
-  /* Call the init function.  */
-  return initfct (&ld_state);
-#else
-# define INIT_FCT_NAME(base) _INIT_FCT_NAME(base)
-# define _INIT_FCT_NAME(base) base##_ld_init
-  /* Declare and call the initialization function.  */
-  extern int INIT_FCT_NAME(BASE_ELF_NAME) (struct ld_state *);
-  return INIT_FCT_NAME(BASE_ELF_NAME) (&ld_state);
-#endif
-}
-
-
-static int
-check_for_duplicate2 (struct usedfiles *newp, struct usedfiles *list)
-{
-  struct usedfiles *first;
-
-  if (list == NULL)
-    return 0;
-
-  list = first = list->next;
-  do
-    {
-      /* When searching the needed list we might come across entries
-	 for files which are not yet opened.  Stop then, there is
-	 nothing more to test.  */
-      if (likely (list->status == not_opened))
-	break;
-
-      if (unlikely (list->ino == newp->ino)
-	  && unlikely (list->dev == newp->dev))
-	{
-	  close (newp->fd);
-	  newp->fd = -1;
-	  newp->status = closed;
-	  if (newp->file_type == relocatable_file_type)
-	    error (0, 0, gettext ("%s listed more than once as input"),
-		   newp->rfname);
-
-	  return 1;
-	}
-      list = list->next;
-    }
-  while (likely (list != first));
-
-  return 0;
-}
-
-
-static int
-check_for_duplicate (struct usedfiles *newp)
-{
-  struct stat st;
-
-  if (unlikely (fstat (newp->fd, &st) < 0))
-    {
-      close (newp->fd);
-      return errno;
-    }
-
-  newp->dev = st.st_dev;
-  newp->ino = st.st_ino;
-
-  return (check_for_duplicate2 (newp, ld_state.relfiles)
-	  || check_for_duplicate2 (newp, ld_state.dsofiles)
-	  || check_for_duplicate2 (newp, ld_state.needed));
-}
-
-
-/* Find a file along the path described in the state.  */
-static int
-open_along_path2 (struct usedfiles *fileinfo, struct pathelement *path)
-{
-  const char *fname = fileinfo->fname;
-  size_t fnamelen = strlen (fname);
-  int err = ENOENT;
-  struct pathelement *firstp = path;
-
-  if (path == NULL)
-    /* Cannot find anything since we have no path.  */
-    return ENOENT;
-
-  do
-    {
-      if (likely (path->exist >= 0))
-	{
-	  /* Create the file name.  */
-	  char *rfname = NULL;
-	  size_t dirlen = strlen (path->pname);
-	  int fd = -1;
-
-	  if (fileinfo->file_type == archive_file_type)
-	    {
-	      const char **exts = (ld_state.statically
-				   ? (const char *[2]) { ".a", NULL }
-				   : LIB_EXTENSION (&ld_state));
-
-	      /* We have to create the actual file name.  We prepend "lib"
-		 and add one of the extensions the platform has.  */
-	      while (*exts != NULL)
-		{
-		  size_t extlen = strlen (*exts);
-		  rfname = (char *) alloca (dirlen + 5 + fnamelen + extlen);
-		  memcpy (mempcpy (stpcpy (mempcpy (rfname, path->pname,
-						    dirlen),
-					   "/lib"),
-				   fname, fnamelen),
-			  *exts, extlen + 1);
-
-		  fd = open (rfname, O_RDONLY);
-		  if (likely (fd != -1) || errno != ENOENT)
-		    {
-		      err = fd == -1 ? errno : 0;
-		      break;
-		    }
-
-		  /* Next extension.  */
-		  ++exts;
-		}
-	    }
-	  else
-	    {
-	      assert (fileinfo->file_type == dso_file_type
-		      || fileinfo->file_type == dso_needed_file_type);
-
-	      rfname = (char *) alloca (dirlen + 1 + fnamelen + 1);
-	      memcpy (stpcpy (mempcpy (rfname, path->pname, dirlen), "/"),
-		      fname, fnamelen + 1);
-
-	      fd = open (rfname, O_RDONLY);
-	      if (unlikely (fd == -1))
-		err = errno;
-	    }
-
-	  if (likely (fd != -1))
-	    {
-	      /* We found the file.  This also means the directory
-		 exists.  */
-	      fileinfo->fd = fd;
-	      path->exist = 1;
-
-	      /* Check whether we have this file already loaded.  */
-	      if (unlikely (check_for_duplicate (fileinfo) != 0))
-		return EAGAIN;
-
-	      /* Make a copy of the name.  */
-	      fileinfo->rfname = obstack_strdup (&ld_state.smem, rfname);
-
-	      if (unlikely (ld_state.trace_files))
-		printf (fileinfo->file_type == archive_file_type
-			? gettext ("%s (for -l%s)\n")
-			: gettext ("%s (for DT_NEEDED %s)\n"),
-			rfname, fname);
-
-	      return 0;
-	    }
-
-	  /* The file does not exist.  Maybe the whole directory doesn't.
-	     Check it unless we know it exists.  */
-	  if (unlikely (path->exist == 0))
-	    {
-	      struct stat st;
-
-	      /* Keep only the directory name.  Note that the path
-		 might be relative.  This doesn't matter here.  We do
-		 the test in any case even if there is the chance that
-		 somebody wants to change the programs working
-		 directory at some point which would make the result
-		 of this test void.  Since changing the working
-		 directory is completely wrong we are not taking this
-		 case into account.  */
-	      rfname[dirlen] = '\0';
-	      if (unlikely (stat (rfname, &st) < 0) || ! S_ISDIR (st.st_mode))
-		/* The directory does not exist or the named file is no
-		   directory.  */
-		path->exist = -1;
-	      else
-		path->exist = 1;
-	    }
-	}
-
-      /* Next path element.  */
-      path = path->next;
-    }
-  while (likely (err == ENOENT && path != firstp));
-
-  return err;
-}
-
-
-static int
-open_along_path (struct usedfiles *fileinfo)
-{
-  const char *fname = fileinfo->fname;
-  int err = ENOENT;
-
-  if (fileinfo->file_type == relocatable_file_type)
-    {
-      /* Only libraries are searched along the path.  */
-      fileinfo->fd = open (fname, O_RDONLY);
-
-      if (likely (fileinfo->fd != -1))
-	{
-	  /* We found the file.  */
-	  if (unlikely (ld_state.trace_files))
-	    print_file_name (stdout, fileinfo, 1, 1);
-
-	  return check_for_duplicate (fileinfo);
-	}
-
-      /* If the name is an absolute path we are done.  */
-      err = errno;
-    }
-  else
-    {
-      /* If the user specified two parts to the LD_LIBRARY_PATH variable
-	 try the first part now.  */
-      err = open_along_path2 (fileinfo, ld_state.ld_library_path1);
-
-      /* Try the user-specified path next.  */
-      if (err == ENOENT)
-	err = open_along_path2 (fileinfo,
-				fileinfo->file_type == archive_file_type
-				? ld_state.paths : ld_state.rpath_link);
-
-      /* Then the second part of the LD_LIBRARY_PATH value.  */
-      if (unlikely (err == ENOENT))
-	{
-	  err = open_along_path2 (fileinfo, ld_state.ld_library_path2);
-
-	  /* In case we look for a DSO handle now the RUNPATH.  */
-	  if (err == ENOENT)
-	    {
-	      if (fileinfo->file_type == dso_file_type)
-		err = open_along_path2 (fileinfo, ld_state.runpath_link);
-
-	      /* Finally the path from the default linker script.  */
-	      if (err == ENOENT)
-		err = open_along_path2 (fileinfo, ld_state.default_paths);
-	    }
-	}
-    }
-
-  if (unlikely (err != 0)
-      && (err != EAGAIN || fileinfo->file_type == relocatable_file_type))
-    error (0, err, gettext ("cannot open %s"), fileinfo->fname);
-
-  return err;
-}
-
-
-static int
-matching_group_comdat_scn (const XElf_Sym *sym, size_t shndx,
-			   struct usedfiles *fileinfo, struct symbol *oldp)
-{
-  if ((shndx >= SHN_LORESERVE && shndx <= SHN_HIRESERVE)
-      || (oldp->scndx >= SHN_LORESERVE && oldp->scndx <= SHN_HIRESERVE))
-    /* Cannot be a group COMDAT section.  */
-    return 0;
-
-  size_t newgrpid = fileinfo->scninfo[shndx].grpid;
-  size_t oldgrpid = oldp->file->scninfo[oldp->scndx].grpid;
-  if (newgrpid == 0 || oldgrpid == 0)
-    return 0;
-
-  assert (SCNINFO_SHDR (fileinfo->scninfo[newgrpid].shdr).sh_type
-	  == SHT_GROUP);
-  assert (SCNINFO_SHDR (oldp->file->scninfo[oldgrpid].shdr).sh_type
-	  == SHT_GROUP);
-
-  if (! fileinfo->scninfo[newgrpid].comdat_group
-      || ! oldp->file->scninfo[oldgrpid].comdat_group)
-    return 0;
-
-  if (strcmp (fileinfo->scninfo[newgrpid].symbols->name,
-	      oldp->file->scninfo[oldgrpid].symbols->name) != 0)
-    return 0;
-
-  /* This is a matching, duplicate COMDAT group section.  Ignore it.  */
-  return 1;
-}
-
-
-static void
-check_type_and_size (const XElf_Sym *sym, struct usedfiles *fileinfo,
-		     struct symbol *oldp)
-{
-  /* We check the type and size of the symbols.  In both cases the
-     information can be missing (size is zero, type is STT_NOTYPE) in
-     which case we issue no warnings.  Otherwise everything must
-     match.  If the type does not match there is no point in checking
-     the size.  */
-
-  if (XELF_ST_TYPE (sym->st_info) != STT_NOTYPE && oldp->type != STT_NOTYPE
-      && unlikely (oldp->type != XELF_ST_TYPE (sym->st_info)))
-    {
-      char buf1[64];
-      char buf2[64];
-
-      error (0, 0, gettext ("\
-Warning: type of `%s' changed from %s in %s to %s in %s"),
-	     oldp->name,
-	     ebl_symbol_type_name (ld_state.ebl, oldp->type,
-				   buf1, sizeof (buf1)),
-	     oldp->file->rfname,
-	     ebl_symbol_type_name (ld_state.ebl, XELF_ST_TYPE (sym->st_info),
-				   buf2, sizeof (buf2)),
-	     fileinfo->rfname);
-    }
-  else if (XELF_ST_TYPE (sym->st_info) == STT_OBJECT
-	   && oldp->size != 0
-	   && unlikely (oldp->size != sym->st_size))
-    error (0, 0, gettext ("\
-Warning: size of `%s' changed from %" PRIu64 " in %s to %" PRIu64 " in %s"),
-	   oldp->name, (uint64_t) oldp->size, oldp->file->rfname,
-	   (uint64_t) sym->st_size, fileinfo->rfname);
-}
-
-
-static int
-check_definition (const XElf_Sym *sym, size_t shndx, size_t symidx,
-		  struct usedfiles *fileinfo, struct symbol *oldp)
-{
-  int result = 0;
-  bool old_in_dso = FILEINFO_EHDR (oldp->file->ehdr).e_type == ET_DYN;
-  bool new_in_dso = FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_DYN;
-  bool use_new_def = false;
-
-  if (shndx != SHN_UNDEF
-      && (! oldp->defined
-	  || (shndx != SHN_COMMON && oldp->common && ! new_in_dso)
-	  || (old_in_dso && ! new_in_dso)))
-    {
-      /* We found a definition for a previously undefined symbol or a
-	 real definition for a previous common-only definition or a
-	 redefinition of a symbol definition in an object file
-	 previously defined in a DSO.  First perform some tests which
-	 will show whether the common is really matching the
-	 definition.  */
-      check_type_and_size (sym, fileinfo, oldp);
-
-      /* We leave the next element intact to not interrupt the list
-	 with the unresolved symbols.  Whoever walks the list will
-	 have to check the `defined' flag.  But we remember that this
-	 list element is not unresolved anymore.  */
-      if (! oldp->defined)
-	{
-	  /* Remove from the list.  */
-	  --ld_state.nunresolved;
-	  if (! oldp->weak)
-	    --ld_state.nunresolved_nonweak;
-	  CDBL_LIST_DEL (ld_state.unresolved, oldp);
-	}
-      else if (oldp->common)
-	/* Remove from the list.  */
-	CDBL_LIST_DEL (ld_state.common_syms, oldp);
-
-      /* Use the values of the definition from now on.  */
-      use_new_def = true;
-    }
-  else if (shndx != SHN_UNDEF
-	   && oldp->defined
-	   && matching_group_comdat_scn (sym, shndx, fileinfo, oldp))
-    /* The duplicate symbol is in a group COMDAT section with the same
-       signature as the one containing the original definition.
-       Just ignore the second definition.  */
-    /* nothing */;
-  else if (shndx != SHN_UNDEF
-	   && unlikely (! oldp->common)
-	   && oldp->defined
-	   && shndx != SHN_COMMON
-	   /* Multiple definitions are no fatal errors if the -z muldefs flag
-	      is used.  We don't warn about the multiple definition unless we
-	      are told to be verbose.  */
-	   && (!ld_state.muldefs || verbose)
-	   && ! old_in_dso && fileinfo->file_type == relocatable_file_type)
-    {
-      /* We have a double definition.  This is a problem.  */
-      char buf[64];
-      XElf_Sym_vardef (oldsym);
-      struct usedfiles *oldfile;
-      const char *scnname;
-      Elf32_Word xndx;
-      size_t shnum;
-
-      if (elf_getshdrnum (fileinfo->elf, &shnum) < 0)
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot determine number of sections: %s"),
-	       elf_errmsg (-1));
-
-      /* XXX Use only ebl_section_name.  */
-      if (shndx < SHN_LORESERVE || (shndx > SHN_HIRESERVE && shndx < shnum))
-	scnname = elf_strptr (fileinfo->elf,
-			      fileinfo->shstrndx,
-			      SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_name);
-      else
-	// XXX extended section
-	scnname = ebl_section_name (ld_state.ebl, shndx, 0, buf, sizeof (buf),
-				    NULL, shnum);
-
-      /* XXX Print source file and line number.  */
-      print_file_name (stderr, fileinfo, 1, 0);
-      fprintf (stderr,
-	       gettext ("(%s+%#" PRIx64 "): multiple definition of %s `%s'\n"),
-	       scnname,
-	       (uint64_t) sym->st_value,
-	       ebl_symbol_type_name (ld_state.ebl, XELF_ST_TYPE (sym->st_info),
-				     buf, sizeof (buf)),
-	       oldp->name);
-
-      oldfile = oldp->file;
-      xelf_getsymshndx (oldfile->symtabdata, oldfile->xndxdata, oldp->symidx,
-			oldsym, xndx);
-      assert (oldsym != NULL);
-
-      /* XXX Use only ebl_section_name.  */
-      if (oldp->scndx < SHN_LORESERVE || oldp->scndx > SHN_HIRESERVE)
-	scnname = elf_strptr (oldfile->elf,
-			      oldfile->shstrndx,
-			      SCNINFO_SHDR (oldfile->scninfo[shndx].shdr).sh_name);
-      else
-	scnname = ebl_section_name (ld_state.ebl, oldp->scndx, oldp->scndx,
-				    buf, sizeof (buf), NULL, shnum);
-
-      /* XXX Print source file and line number.  */
-      print_file_name (stderr, oldfile, 1, 0);
-      fprintf (stderr, gettext ("(%s+%#" PRIx64 "): first defined here\n"),
-	       scnname, (uint64_t) oldsym->st_value);
-
-      if (likely (!ld_state.muldefs))
-	result = 1;
-    }
-  else if (old_in_dso && fileinfo->file_type == relocatable_file_type
-	   && shndx != SHN_UNDEF)
-    /* We use the definition from a normal relocatable file over the
-       definition in a DSO.  This is what the dynamic linker would
-       do, too.  */
-    use_new_def = true;
-  else if (old_in_dso && !new_in_dso && oldp->defined && !oldp->on_dsolist)
-    {
-      CDBL_LIST_ADD_REAR (ld_state.from_dso, oldp);
-      ++ld_state.nfrom_dso;
-
-      /* If the object is a function we allocate a PLT entry,
-	 otherwise only a GOT entry.  */
-      if (oldp->type == STT_FUNC)
-	++ld_state.nplt;
-      else
-	++ld_state.ngot;
-
-      oldp->on_dsolist = 1;
-    }
-  else if (oldp->common && shndx == SHN_COMMON)
-    {
-      /* The symbol size is the largest of all common definitions.  */
-      oldp->size = MAX (oldp->size, sym->st_size);
-      /* Similarly for the alignment.  */
-      oldp->merge.value = MAX (oldp->merge.value, sym->st_value);
-    }
-
-  if (unlikely (use_new_def))
-    {
-      /* Adjust the symbol record appropriately and remove
-	 the symbol from the list of symbols which are taken from DSOs.  */
-      if (old_in_dso && fileinfo->file_type == relocatable_file_type)
-	{
-	  CDBL_LIST_DEL (ld_state.from_dso, oldp);
-	  --ld_state.nfrom_dso;
-
-	  if (likely (oldp->type == STT_FUNC))
-	    --ld_state.nplt;
-	  else
-	    --ld_state.ngot;
-
-	  oldp->on_dsolist = 0;
-	}
-
-      /* Use the values of the definition from now on.  */
-      oldp->size = sym->st_size;
-      oldp->type = XELF_ST_TYPE (sym->st_info);
-      oldp->symidx = symidx;
-      oldp->scndx = shndx;
-      //oldp->symscndx = THESYMSCNDX must be passed;
-      oldp->file = fileinfo;
-      oldp->defined = 1;
-      oldp->in_dso = new_in_dso;
-      oldp->common = shndx == SHN_COMMON;
-      if (likely (fileinfo->file_type == relocatable_file_type))
-	{
-	  /* If the definition comes from a DSO we pertain the weak flag
-	     and it's indicating whether the reference is weak or not.  */
-	  oldp->weak = XELF_ST_BIND (sym->st_info) == STB_WEAK;
-
-	  // XXX Really exclude SHN_ABS?
-	  if (shndx != SHN_COMMON && shndx != SHN_ABS)
-	    {
-	      struct scninfo *ignore;
-	      mark_section_used (&fileinfo->scninfo[shndx], shndx, &ignore);
-	    }
-	}
-
-      /* Add to the list of symbols used from DSOs if necessary.  */
-      if (new_in_dso && !old_in_dso)
-	{
-	  CDBL_LIST_ADD_REAR (ld_state.from_dso, oldp);
-	  ++ld_state.nfrom_dso;
-
-	  /* If the object is a function we allocate a PLT entry,
-	     otherwise only a GOT entry.  */
-	  if (oldp->type == STT_FUNC)
-	    ++ld_state.nplt;
-	  else
-	    ++ld_state.ngot;
-
-	  oldp->on_dsolist = 1;
-	}
-      else if (shndx == SHN_COMMON)
-	{
-	  /* Store the alignment.  */
-	  oldp->merge.value = sym->st_value;
-
-	  CDBL_LIST_ADD_REAR (ld_state.common_syms, oldp);
-	}
-    }
-
-  return result;
-}
-
-
-static struct scninfo *
-find_section_group (struct usedfiles *fileinfo, Elf32_Word shndx,
-		    Elf_Data **datap)
-{
-  struct scninfo *runp;
-
-  for (runp = fileinfo->groups; runp != NULL; runp = runp->next)
-    if (!runp->used)
-      {
-	Elf32_Word *grpref;
-	size_t cnt;
-	Elf_Data *data;
-
-	data = elf_getdata (runp->scn, NULL);
-	if (data == NULL)
-	  error (EXIT_FAILURE, 0,
-		 gettext ("%s: cannot get section group data: %s"),
-		 fileinfo->fname, elf_errmsg (-1));
-
-	/* There cannot be another data block.  */
-	assert (elf_getdata (runp->scn, data) == NULL);
-
-	grpref = (Elf32_Word *) data->d_buf;
-	cnt = data->d_size / sizeof (Elf32_Word);
-	/* Note that we stop after looking at index 1 since index 0
-	   contains the flags for the section group.  */
-	while (cnt > 1)
-	  if (grpref[--cnt] == shndx)
-	    {
-	      *datap = data;
-	      return runp;
-	    }
-      }
-
-  /* If we come here no section group contained the given section
-     despite the SHF_GROUP flag.  This is an error in the input
-     file.  */
-  error (EXIT_FAILURE, 0, gettext ("\
-%s: section '%s' with group flag set does not belong to any group"),
-	 fileinfo->fname,
-	 elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-		     SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_name));
-  return NULL;
-}
-
-
-/* Mark all sections which belong to the same group as section SHNDX
-   as used.  */
-static void
-mark_section_group (struct usedfiles *fileinfo, Elf32_Word shndx,
-		    struct scninfo **grpscnp)
-{
-  /* First locate the section group.  There can be several (many) of
-     them.  */
-  size_t cnt;
-  Elf32_Word *grpref;
-  Elf_Data *data;
-  struct scninfo *grpscn = find_section_group (fileinfo, shndx, &data);
-  *grpscnp = grpscn;
-
-  /* Mark all the sections as used.
-
-     XXX Two possible problems here:
-
-     - the gABI says "The section must be referenced by a section of type
-       SHT_GROUP".  I hope everybody reads this as "exactly one section".
-
-     - section groups are also useful to mark the debugging section which
-       belongs to a text section.  Unconditionally adding debugging sections
-       is therefore probably not what is wanted if stripping is required.  */
-
-  /* Mark the section group as handled.  */
-  grpscn->used = true;
-
-  grpref = (Elf32_Word *) data->d_buf;
-  cnt = data->d_size / sizeof (Elf32_Word);
-  while (cnt > 1)
-    {
-      Elf32_Word idx = grpref[--cnt];
-      XElf_Shdr *shdr = &SCNINFO_SHDR (fileinfo->scninfo[idx].shdr);
-
-      if (fileinfo->scninfo[idx].grpid != grpscn->grpid)
-	error (EXIT_FAILURE, 0, gettext ("\
-%s: section [%2d] '%s' is not in the correct section group"),
-	       fileinfo->fname, (int) idx,
-	       elf_strptr (fileinfo->elf, fileinfo->shstrndx, shdr->sh_name));
-
-      if (ld_state.strip == strip_none
-	  /* If we are stripping, remove debug sections.  */
-	  || (!ebl_debugscn_p (ld_state.ebl,
-			       elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-					   shdr->sh_name))
-	      /* And the relocation sections for the debug sections.  */
-	      && ((shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL)
-		  || !ebl_debugscn_p (ld_state.ebl,
-				      elf_strptr (fileinfo->elf,
-						  fileinfo->shstrndx,
-						  SCNINFO_SHDR (fileinfo->scninfo[shdr->sh_info].shdr).sh_name)))))
-	{
-	  struct scninfo *ignore;
-
-	  mark_section_used (&fileinfo->scninfo[idx], idx, &ignore);
-	}
-    }
-}
-
-
-static void
-mark_section_used (struct scninfo *scninfo, Elf32_Word shndx,
-		   struct scninfo **grpscnp)
-{
-  if (likely (scninfo->used))
-    /* Nothing to be done.  */
-    return;
-
-  /* We need this section.  */
-  scninfo->used = true;
-
-  /* Make sure the section header has been read from the file.  */
-  XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
-#if NATIVE_ELF
-  if (unlikely (scninfo->shdr == NULL))
-#else
-  if (unlikely (scninfo->shdr.sh_type == SHT_NULL))
-#endif
-    {
-#if NATIVE_ELF != 0
-      shdr = xelf_getshdr (scninfo->scn, scninfo->shdr);
-#else
-      xelf_getshdr_copy (scninfo->scn, shdr, scninfo->shdr);
-#endif
-      if (unlikely (shdr == NULL))
-	/* Something is very wrong.  The calling code will notice it
-	   soon and print a message.  */
-	return;
-    }
-
-  /* Handle section linked by 'sh_link'.  */
-  if (unlikely (shdr->sh_link != 0))
-    {
-      struct scninfo *ignore;
-      mark_section_used (&scninfo->fileinfo->scninfo[shdr->sh_link],
-			 shdr->sh_link, &ignore);
-    }
-
-  /* Handle section linked by 'sh_info'.  */
-  if (unlikely (shdr->sh_info != 0) && (shdr->sh_flags & SHF_INFO_LINK))
-    {
-      struct scninfo *ignore;
-      mark_section_used (&scninfo->fileinfo->scninfo[shdr->sh_info],
-			 shdr->sh_info, &ignore);
-    }
-
-  if (unlikely (shdr->sh_flags & SHF_GROUP) && ld_state.gc_sections)
-    /* Find the section group which contains this section.  */
-    mark_section_group (scninfo->fileinfo, shndx, grpscnp);
-}
-
-
-/* We collect all sections in a hashing table.  All sections with the
-   same name are collected in a list.  Note that we do not determine
-   which sections are finally collected in the same output section
-   here.  This would be terribly inefficient.  It will be done later.  */
-static void
-add_section (struct usedfiles *fileinfo, struct scninfo *scninfo)
-{
-  struct scnhead *queued;
-  struct scnhead search;
-  unsigned long int hval;
-  XElf_Shdr *shdr = &SCNINFO_SHDR (scninfo->shdr);
-  struct scninfo *grpscn = NULL;
-  Elf_Data *grpscndata = NULL;
-
-  /* See whether we can determine right away whether we need this
-     section in the output.
-
-     XXX I assume here that --gc-sections only affects extraction
-     from an archive.  If it also affects objects files given on
-     the command line then somebody must explain to me how the
-     dependency analysis should work.  Should the entry point be
-     the root?  What if it is a numeric value?  */
-  if (!scninfo->used
-      && (ld_state.strip == strip_none
-	  || (shdr->sh_flags & SHF_ALLOC) != 0
-	  || shdr->sh_type == SHT_NOTE
-	  || (shdr->sh_type == SHT_PROGBITS
-	      && strcmp (elf_strptr (fileinfo->elf,
-				     fileinfo->shstrndx,
-				     shdr->sh_name), ".comment") == 0))
-      && (fileinfo->status != in_archive || !ld_state.gc_sections))
-    /* Mark as used and handle reference recursively if necessary.  */
-    mark_section_used (scninfo, elf_ndxscn (scninfo->scn), &grpscn);
-
-  if ((shdr->sh_flags & SHF_GROUP) && grpscn == NULL)
-    /* Determine the symbol which name constitutes the signature
-       for the section group.  */
-    grpscn = find_section_group (fileinfo, elf_ndxscn (scninfo->scn),
-				 &grpscndata);
-  assert (grpscn == NULL || grpscn->symbols->name != NULL);
-
-  /* Determine the section name.  */
-  search.name = elf_strptr (fileinfo->elf, fileinfo->shstrndx, shdr->sh_name);
-  search.type = shdr->sh_type;
-  search.flags = shdr->sh_flags;
-  search.entsize = shdr->sh_entsize;
-  search.grp_signature = grpscn != NULL ? grpscn->symbols->name : NULL;
-  search.kind = scn_normal;
-  hval = elf_hash (search.name);
-
-  /* Find already queued sections.  */
-  queued = ld_section_tab_find (&ld_state.section_tab, hval, &search);
-  if (queued != NULL)
-    {
-      bool is_comdat = false;
-
-      /* If this section is part of a COMDAT section group we simply
-	 ignore it since we already have a copy.  */
-      if (unlikely (shdr->sh_flags & SHF_GROUP))
-	{
-	  /* Get the data of the section group section.  */
-	  if (grpscndata == NULL)
-	    {
-	      grpscndata = elf_getdata (grpscn->scn, NULL);
-	      assert (grpscndata != NULL);
-	    }
-
-	  /* XXX Possibly unaligned memory access.  */
-	  if ((((Elf32_Word *) grpscndata->d_buf)[0] & GRP_COMDAT) != 0)
-	    {
-	      /* We have to compare the group signatures.  There might
-		 be sections with the same name but belonging to
-		 groups with different signatures.  This means we have
-		 to compare the new group signature with all those
-		 already collected.  There might also be some
-		 non-group sections in the mix.  */
-	      struct scninfo *runp = queued->last;
-	      do
-		{
-		  if (SCNINFO_SHDR (runp->shdr).sh_flags & SHF_GROUP)
-		    {
-		      struct scninfo *grpscn2
-			= find_section_group (runp->fileinfo,
-					      elf_ndxscn (runp->scn),
-					      &grpscndata);
-
-		      if (strcmp (grpscn->symbols->name,
-				  grpscn2->symbols->name) == 0)
-			{
-			  scninfo->unused_comdat = is_comdat = true;
-			  break;
-			}
-		    }
-
-		  runp = runp->next;
-		}
-	      while (runp != queued->last);
-	    }
-	}
-
-      if (!is_comdat)
-	{
-	  /* No COMDAT section, we use the data.  */
-	  scninfo->next = queued->last->next;
-	  queued->last = queued->last->next = scninfo;
-
-	  queued->flags = ebl_sh_flags_combine (ld_state.ebl, queued->flags,
-						shdr->sh_flags);
-	  queued->align = MAX (queued->align, shdr->sh_addralign);
-	}
-    }
-  else
-    {
-      /* We do not use obstacks here since the memory might be
-	 deallocated.  */
-      queued = (struct scnhead *) xcalloc (sizeof (struct scnhead), 1);
-      queued->kind = scn_normal;
-      queued->name = search.name;
-      queued->type = shdr->sh_type;
-      queued->flags = shdr->sh_flags;
-      queued->align = shdr->sh_addralign;
-      queued->entsize = shdr->sh_entsize;
-      queued->grp_signature = grpscn != NULL ? grpscn->symbols->name : NULL;
-      queued->segment_nr = ~0;
-      queued->last = scninfo->next = scninfo;
-
-      /* Check whether we need a TLS segment.  */
-      ld_state.need_tls |= (shdr->sh_flags & SHF_TLS) != 0;
-
-      /* Add to the hash table and possibly overwrite existing value.  */
-      ld_section_tab_insert (&ld_state.section_tab, hval, queued);
-    }
-}
-
-
-static int
-add_relocatable_file (struct usedfiles *fileinfo, GElf_Word secttype)
-{
-  size_t scncnt;
-  size_t cnt;
-  Elf_Data *symtabdata = NULL;
-  Elf_Data *xndxdata = NULL;
-  Elf_Data *versymdata = NULL;
-  Elf_Data *verdefdata = NULL;
-  Elf_Data *verneeddata = NULL;
-  size_t symstridx = 0;
-  size_t nsymbols = 0;
-  size_t nlocalsymbols = 0;
-  bool has_merge_sections = false;
-  bool has_tls_symbols = false;
-  /* Unless we have different information we assume the code needs
-     an executable stack.  */
-  enum execstack execstack = execstack_true;
-
-  /* Prerequisites.  */
-  assert (fileinfo->elf != NULL);
-
-  /* Allocate memory for the sections.  */
-  if (unlikely (elf_getshdrnum (fileinfo->elf, &scncnt) < 0))
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot determine number of sections: %s"),
-	   elf_errmsg (-1));
-
-  fileinfo->scninfo = (struct scninfo *)
-    obstack_calloc (&ld_state.smem, scncnt * sizeof (struct scninfo));
-
-  /* Read all the section headers and find the symbol table.  Note
-     that we don't skip the section with index zero.  Even though the
-     section itself is always empty the section header contains
-     informaton for the case when the section index for the section
-     header string table is too large to fit in the ELF header.  */
-  for (cnt = 0; cnt < scncnt; ++cnt)
-    {
-      /* Store the handle for the section.  */
-      fileinfo->scninfo[cnt].scn = elf_getscn (fileinfo->elf, cnt);
-
-      /* Get the ELF section header and data.  */
-      XElf_Shdr *shdr;
-#if NATIVE_ELF != 0
-      if (fileinfo->scninfo[cnt].shdr == NULL)
-#else
-      if (fileinfo->scninfo[cnt].shdr.sh_type == SHT_NULL)
-#endif
-	{
-#if NATIVE_ELF != 0
-	  shdr = xelf_getshdr (fileinfo->scninfo[cnt].scn,
-			       fileinfo->scninfo[cnt].shdr);
-#else
-	  xelf_getshdr_copy (fileinfo->scninfo[cnt].scn, shdr,
-			     fileinfo->scninfo[cnt].shdr);
-#endif
-	  if (shdr == NULL)
-	    {
-	      /* This should never happen.  */
-	      fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-		       fileinfo->rfname, __FILE__, __LINE__);
-	      return 1;
-	    }
-	}
-      else
-	shdr = &SCNINFO_SHDR (fileinfo->scninfo[cnt].shdr);
-
-      Elf_Data *data = elf_getdata (fileinfo->scninfo[cnt].scn, NULL);
-
-      /* Check whether this section is marked as merge-able.  */
-      has_merge_sections |= (shdr->sh_flags & SHF_MERGE) != 0;
-      has_tls_symbols |= (shdr->sh_flags & SHF_TLS) != 0;
-
-      /* Get the ELF section header and data.  */
-      /* Make the file structure available.  */
-      fileinfo->scninfo[cnt].fileinfo = fileinfo;
-
-      if (unlikely (shdr->sh_type == SHT_SYMTAB)
-	  || unlikely (shdr->sh_type == SHT_DYNSYM))
-	{
-	  if (shdr->sh_type == SHT_SYMTAB)
-	    {
-	      assert (fileinfo->symtabdata == NULL);
-	      fileinfo->symtabdata = data;
-	      fileinfo->nsymtab = shdr->sh_size / shdr->sh_entsize;
-	      fileinfo->nlocalsymbols = shdr->sh_info;
-	      fileinfo->symstridx = shdr->sh_link;
-	    }
-	  else
-	    {
-	      assert (fileinfo->dynsymtabdata == NULL);
-	      fileinfo->dynsymtabdata = data;
-	      fileinfo->ndynsymtab = shdr->sh_size / shdr->sh_entsize;
-	      fileinfo->dynsymstridx = shdr->sh_link;
-	    }
-
-	  /* If we are looking for the normal symbol table we just
-	     found it.  */
-	  if (secttype == shdr->sh_type)
-	    {
-	      assert (symtabdata == NULL);
-	      symtabdata = data;
-	      symstridx = shdr->sh_link;
-	      nsymbols = shdr->sh_size / shdr->sh_entsize;
-	      nlocalsymbols = shdr->sh_info;
-	    }
-	}
-      else if (unlikely (shdr->sh_type == SHT_SYMTAB_SHNDX))
-	{
-	  assert (xndxdata == NULL);
-	  fileinfo->xndxdata = xndxdata = data;
-	}
-      else if (unlikely (shdr->sh_type == SHT_GNU_versym))
-	{
-	  assert (versymdata == 0);
-	  fileinfo->versymdata = versymdata = data;
-	}
-      else if (unlikely (shdr->sh_type == SHT_GNU_verdef))
-	{
-	  size_t nversions;
-
-	  assert (verdefdata == 0);
-	  fileinfo->verdefdata = verdefdata = data;
-
-	  /* Allocate the arrays flagging the use of the version and
-	     to track of allocated names.  */
-	  fileinfo->nverdef = nversions = shdr->sh_info;
-	  /* We have NVERSIONS + 1 because the indeces used to access the
-	     sectino start with one; zero represents local binding.  */
-	  fileinfo->verdefused = (XElf_Versym *)
-	    obstack_calloc (&ld_state.smem,
-			    sizeof (XElf_Versym) * (nversions + 1));
-	  fileinfo->verdefent = (struct Ebl_Strent **)
-	    obstack_alloc (&ld_state.smem,
-			   sizeof (struct Ebl_Strent *) * (nversions + 1));
-	}
-      else if (unlikely (shdr->sh_type == SHT_GNU_verneed))
-	{
-	  assert (verneeddata == 0);
-	  fileinfo->verneeddata = verneeddata = data;
-	}
-      else if (unlikely (shdr->sh_type == SHT_DYNAMIC))
-	{
-	  assert (fileinfo->dynscn == NULL);
-	  fileinfo->dynscn = fileinfo->scninfo[cnt].scn;
-	}
-      else if (unlikely (shdr->sh_type == SHT_GROUP))
-	{
-	  Elf_Scn *symscn;
-	  XElf_Shdr_vardef (symshdr);
-	  Elf_Data *symdata;
-
-	  if (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_REL)
-	    error (EXIT_FAILURE, 0, gettext ("\
-%s: only files of type ET_REL might contain section groups"),
-		   fileinfo->fname);
-
-	  fileinfo->scninfo[cnt].next = fileinfo->groups;
-	  fileinfo->scninfo[cnt].grpid = cnt;
-	  fileinfo->groups = &fileinfo->scninfo[cnt];
-
-	  /* Determine the signature.  We create a symbol record for
-	     it.  Only the name element is important.  */
-	  fileinfo->scninfo[cnt].symbols = (struct symbol *)
-	    obstack_calloc (&ld_state.smem, sizeof (struct symbol));
-
-	  symscn = elf_getscn (fileinfo->elf, shdr->sh_link);
-	  xelf_getshdr (symscn, symshdr);
-	  symdata = elf_getdata (symscn, NULL);
-
-	  if (symshdr != NULL)
-	    {
-	      XElf_Sym_vardef (sym);
-
-	      /* We don't need the section index and therefore we don't
-		 have to use 'xelf_getsymshndx'.  */
-	      xelf_getsym (symdata, shdr->sh_info, sym);
-	      if (sym != NULL)
-		{
-		  struct symbol *symbol = fileinfo->scninfo[cnt].symbols;
-
-#ifndef NO_HACKS
-		  if (XELF_ST_TYPE (sym->st_info) == STT_SECTION)
-		    {
-		      XElf_Shdr_vardef (buggyshdr);
-		      xelf_getshdr (elf_getscn (fileinfo->elf, sym->st_shndx),
-				    buggyshdr);
-
-		      symbol->name = elf_strptr (fileinfo->elf,
-						 FILEINFO_EHDR (fileinfo->ehdr).e_shstrndx,
-						 buggyshdr->sh_name);
-		      symbol->symidx = -1;
-		    }
-		  else
-#endif
-		    {
-		      symbol->name = elf_strptr (fileinfo->elf,
-						 symshdr->sh_link,
-						 sym->st_name);
-		      symbol->symidx = shdr->sh_info;
-		    }
-		  symbol->file = fileinfo;
-		}
-	    }
-	  if (fileinfo->scninfo[cnt].symbols->name == NULL)
-	    error (EXIT_FAILURE, 0, gettext ("\
-%s: cannot determine signature of section group [%2zd] '%s': %s"),
-		   fileinfo->fname,
-		   elf_ndxscn (fileinfo->scninfo[cnt].scn),
-		   elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-			       shdr->sh_name),
-		   elf_errmsg (-1));
-
-
-	  /* For all the sections which are part of this group, add
-	     the reference.  */
-	  if (data == NULL)
-	    error (EXIT_FAILURE, 0, gettext ("\
-%s: cannot get content of section group [%2zd] '%s': %s'"),
-		   fileinfo->fname, elf_ndxscn (fileinfo->scninfo[cnt].scn),
-		   elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-			       shdr->sh_name),
-		   elf_errmsg (-1));
-
-	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
-	  if (grpdata[0] & GRP_COMDAT)
-	    fileinfo->scninfo[cnt].comdat_group = true;
-	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
-	       ++inner)
-	    {
-	      if (grpdata[inner] >= scncnt)
-		error (EXIT_FAILURE, 0, gettext ("\
-%s: group member %zu of section group [%2zd] '%s' has too high index: %" PRIu32),
-		       fileinfo->fname,
-		       inner, elf_ndxscn (fileinfo->scninfo[cnt].scn),
-		       elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-				   shdr->sh_name),
-		       grpdata[inner]);
-
-	      fileinfo->scninfo[grpdata[inner]].grpid = cnt;
-	    }
-
-	  /* The 'used' flag is used to indicate when the information
-	     in the section group is used to mark all other sections
-	     as used.  So it must not be true yet.  */
-	  assert (fileinfo->scninfo[cnt].used == false);
-	}
-      else if (! SECTION_TYPE_P (&ld_state, shdr->sh_type)
-	       && unlikely ((shdr->sh_flags & SHF_OS_NONCONFORMING) != 0))
-	/* According to the gABI it is a fatal error if the file contains
-	   a section with unknown type and the SHF_OS_NONCONFORMING flag
-	   set.  */
-	error (EXIT_FAILURE, 0,
-	       gettext ("%s: section '%s' has unknown type: %d"),
-	       fileinfo->fname,
-	       elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-			   shdr->sh_name),
-	       (int) shdr->sh_type);
-      /* We don't have to add a few section types here.  These will be
-	 generated from scratch for the new output file.  We also
-	 don't add the sections of DSOs here since these sections are
-	 not used in the resulting object file.  */
-      else if (likely (fileinfo->file_type == relocatable_file_type)
-	       && likely (cnt > 0)
-	       && likely (shdr->sh_type == SHT_PROGBITS
-			  || shdr->sh_type == SHT_RELA
-			  || shdr->sh_type == SHT_REL
-			  || shdr->sh_type == SHT_NOTE
-			  || shdr->sh_type == SHT_NOBITS
-			  || shdr->sh_type == SHT_INIT_ARRAY
-			  || shdr->sh_type == SHT_FINI_ARRAY
-			  || shdr->sh_type == SHT_PREINIT_ARRAY))
-	{
-	  /* Check whether the section needs to be executable.  */
-	  if (shdr->sh_type == SHT_PROGBITS
-	      && (shdr->sh_flags & SHF_EXECINSTR) == 0
-	      && strcmp (elf_strptr (fileinfo->elf, fileinfo->shstrndx,
-				     shdr->sh_name),
-			 ".note.GNU-stack") == 0)
-	    execstack = execstack_false;
-
-	  add_section (fileinfo, &fileinfo->scninfo[cnt]);
-	}
-    }
-
-  /* Now we know more about the requirements for an executable stack
-     of the result.  */
-  if (fileinfo->file_type == relocatable_file_type
-      && execstack == execstack_true
-      && ld_state.execstack != execstack_false_force)
-    ld_state.execstack = execstack_true;
-
-  /* Handle the symbols.  Record defined and undefined symbols in the
-     hash table.  In theory there can be a file without any symbol
-     table.  */
-  if (likely (symtabdata != NULL))
-    {
-      /* In case this file contains merge-able sections we have to
-	 locate the symbols which are in these sections.  */
-      fileinfo->has_merge_sections = has_merge_sections;
-      if (likely (has_merge_sections || has_tls_symbols))
-	{
-	  fileinfo->symref = (struct symbol **)
-	    obstack_calloc (&ld_state.smem,
-			    nsymbols * sizeof (struct symbol *));
-
-	  /* Only handle the local symbols here.  */
-	  for (cnt = 0; cnt < nlocalsymbols; ++cnt)
-	    {
-	      Elf32_Word shndx;
-	      XElf_Sym_vardef (sym);
-
-	      xelf_getsymshndx (symtabdata, xndxdata, cnt, sym, shndx);
-	      if (sym == NULL)
-		{
-		  /* This should never happen.  */
-		  fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-			   fileinfo->rfname, __FILE__, __LINE__);
-		  return 1;
-		}
-
-	      if (likely (shndx != SHN_XINDEX))
-		shndx = sym->st_shndx;
-	      else if (unlikely (shndx == 0))
-		{
-		  fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-			   fileinfo->rfname, __FILE__, __LINE__);
-		  return 1;
-		}
-
-	      if (XELF_ST_TYPE (sym->st_info) != STT_SECTION
-		  && (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE)
-		  && ((SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_flags
-		       & SHF_MERGE)
-		      || XELF_ST_TYPE (sym->st_info) == STT_TLS))
-		{
-		  /* Create a symbol record for this symbol and add it
-		     to the list for this section.  */
-		  struct symbol *newp;
-
-		  newp = (struct symbol *)
-		    obstack_calloc (&ld_state.smem, sizeof (struct symbol));
-
-		  newp->symidx = cnt;
-		  newp->scndx = shndx;
-		  newp->file = fileinfo;
-		  newp->defined = 1;
-		  fileinfo->symref[cnt] = newp;
-
-		  if (fileinfo->scninfo[shndx].symbols == NULL)
-		    fileinfo->scninfo[shndx].symbols = newp->next_in_scn
-		      = newp;
-		  else
-		    {
-		      newp->next_in_scn
-			= fileinfo->scninfo[shndx].symbols->next_in_scn;
-		      fileinfo->scninfo[shndx].symbols
-			= fileinfo->scninfo[shndx].symbols->next_in_scn = newp;
-		    }
-		}
-	    }
-	}
-      else
-	/* Create array with pointers to the symbol definitions.  Note
-	   that we only allocate memory for the non-local symbols
-	   since we have no merge-able sections.  But we store the
-	   pointer as if it was for the whole symbol table.  This
-	   saves some memory.  */
-	fileinfo->symref = (struct symbol **)
-	  obstack_calloc (&ld_state.smem, ((nsymbols - nlocalsymbols)
-					   * sizeof (struct symbol *)))
-	  - nlocalsymbols;
-
-      /* Don't handle local symbols here.  It's either not necessary
-	 at all or has already happened.  */
-      for (cnt = nlocalsymbols; cnt < nsymbols; ++cnt)
-	{
-	  XElf_Sym_vardef (sym);
-	  Elf32_Word shndx;
-	  xelf_getsymshndx (symtabdata, xndxdata, cnt, sym, shndx);
-
-	  if (sym == NULL)
-	    {
-	      /* This should never happen.  */
-	      fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-		       fileinfo->rfname, __FILE__, __LINE__);
-	      return 1;
-	    }
-
-	  if (likely (shndx != SHN_XINDEX))
-	    shndx = sym->st_shndx;
-	  else if (unlikely (shndx == 0))
-	    {
-	      fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-		       fileinfo->rfname, __FILE__, __LINE__);
-	      return 1;
-	    }
-
-	  /* We ignore ABS symbols from DSOs.  */
-	  // XXX Is this correct?
-	  if (unlikely (shndx == SHN_ABS) && secttype == SHT_DYNSYM)
-	    continue;
-
-	  if ((shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE)
-	      && fileinfo->scninfo[shndx].unused_comdat)
-	    /* The symbol is not used.  */
-	    continue;
-
-	  /* If the DSO uses symbol versions determine whether this is
-	     the default version.  Otherwise we'll ignore the symbol.  */
-	  if (versymdata != NULL)
-	    {
-	      XElf_Versym versym;
-
-	      if (xelf_getversym_copy (versymdata, cnt, versym) == NULL)
-		/* XXX Should we handle faulty input files more graceful?  */
-		assert (! "xelf_getversym failed");
-
-	      if ((versym & 0x8000) != 0)
-		/* Ignore the symbol, it's not the default version.  */
-		continue;
-	    }
-
-	  /* See whether we know anything about this symbol.  */
-	  struct symbol search;
-	  search.name = elf_strptr (fileinfo->elf, symstridx, sym->st_name);
-	  unsigned long int hval = elf_hash (search.name);
-
-	  /* We ignore the symbols the linker generates.  This are
-	     _GLOBAL_OFFSET_TABLE_, _DYNAMIC.  */
-	  // XXX This loop is hot and the following tests hardly ever match.
-	  // XXX Maybe move the tests somewhere they are executed less often.
-	  if (((unlikely (hval == 165832675ul)
-		&& strcmp (search.name, "_DYNAMIC") == 0)
-	       || (unlikely (hval == 102264335ul)
-		   && strcmp (search.name, "_GLOBAL_OFFSET_TABLE_") == 0))
-	      && sym->st_shndx != SHN_UNDEF
-	      /* If somebody defines such a variable in a relocatable we
-		 don't ignore it.  Let the user get what s/he deserves.  */
-	      && fileinfo->file_type != relocatable_file_type)
-	    continue;
-
-	  struct symbol *oldp = ld_symbol_tab_find (&ld_state.symbol_tab,
-						    hval, &search);
-	  struct symbol *newp;
-	  if (likely (oldp == NULL))
-	    {
-	      /* No symbol of this name known.  Add it.  */
-	      newp = (struct symbol *) obstack_alloc (&ld_state.smem,
-						      sizeof (*newp));
-	      newp->name = search.name;
-	      newp->size = sym->st_size;
-	      newp->type = XELF_ST_TYPE (sym->st_info);
-	      newp->symidx = cnt;
-	      newp->outsymidx = 0;
-	      newp->outdynsymidx = 0;
-	      newp->scndx = shndx;
-	      newp->file = fileinfo;
-	      newp->defined = newp->scndx != SHN_UNDEF;
-	      newp->common = newp->scndx == SHN_COMMON;
-	      newp->weak = XELF_ST_BIND (sym->st_info) == STB_WEAK;
-	      newp->added = 0;
-	      newp->merged = 0;
-	      newp->local = 0;
-	      newp->hidden = 0;
-	      newp->need_copy = 0;
-	      newp->on_dsolist = 0;
-	      newp->in_dso = secttype == SHT_DYNSYM;
-	      newp->next_in_scn = NULL;
-#ifndef NDEBUG
-	      newp->next = NULL;
-	      newp->previous = NULL;
-#endif
-
-	      if (newp->scndx == SHN_UNDEF)
-		{
-		  CDBL_LIST_ADD_REAR (ld_state.unresolved, newp);
-		  ++ld_state.nunresolved;
-		  if (! newp->weak)
-		    ++ld_state.nunresolved_nonweak;
-		}
-	      else if (newp->scndx == SHN_COMMON)
-		{
-		  /* Store the alignment requirement.  */
-		  newp->merge.value = sym->st_value;
-
-		  CDBL_LIST_ADD_REAR (ld_state.common_syms, newp);
-		}
-
-	      /* Insert the new symbol.  */
-	      if (unlikely (ld_symbol_tab_insert (&ld_state.symbol_tab,
-						  hval, newp) != 0))
-		/* This cannot happen.  */
-		abort ();
-
-	      fileinfo->symref[cnt] = newp;
-
-	      /* We have a few special symbols to recognize.  The symbols
-		 _init and _fini are the initialization and finalization
-		 functions respectively.  They have to be made known in
-		 the dynamic section and therefore we have to find out
-		 now whether these functions exist or not.  */
-	      if (hval == 6685956 && strcmp (newp->name, "_init") == 0)
-		ld_state.init_symbol = newp;
-	      else if (hval == 6672457 && strcmp (newp->name, "_fini") == 0)
-		ld_state.fini_symbol = newp;
-	    }
-	  else if (unlikely (check_definition (sym, shndx, cnt, fileinfo, oldp)
-			     != 0))
-	    /* A fatal error (multiple definition of a symbol)
-	       occurred, no need to continue.  */
-	    return 1;
-	  else
-	    /* Use the previously allocated symbol record.  It has
-	       been updated in check_definition(), if necessary.  */
-	    newp = fileinfo->symref[cnt] = oldp;
-
-	  /* Mark the section the symbol we need comes from as used.  */
-	  if (shndx != SHN_UNDEF
-	      && (shndx < SHN_LORESERVE || shndx > SHN_HIRESERVE))
-	    {
-	      struct scninfo *ignore;
-
-#ifndef NDEBUG
-	      size_t shnum;
-	      assert (elf_getshdrnum (fileinfo->elf, &shnum) == 0);
-	      assert (shndx < shnum);
-#endif
-
-	      /* Mark section (and all dependencies) as used.  */
-	      mark_section_used (&fileinfo->scninfo[shndx], shndx, &ignore);
-
-	      /* Check whether the section is merge-able.  In this case we
-		 have to record the symbol.  */
-	      if (SCNINFO_SHDR (fileinfo->scninfo[shndx].shdr).sh_flags
-		  & SHF_MERGE)
-		{
-		  if (fileinfo->scninfo[shndx].symbols == NULL)
-		    fileinfo->scninfo[shndx].symbols = newp->next_in_scn
-		      = newp;
-		  else
-		    {
-		      newp->next_in_scn
-			= fileinfo->scninfo[shndx].symbols->next_in_scn;
-		      fileinfo->scninfo[shndx].symbols
-			= fileinfo->scninfo[shndx].symbols->next_in_scn = newp;
-		    }
-		}
-	    }
-	}
-
-      /* This file is used.  */
-      if (likely (fileinfo->file_type == relocatable_file_type))
-	{
-	  if (unlikely (ld_state.relfiles == NULL))
-	    ld_state.relfiles = fileinfo->next = fileinfo;
-	  else
-	    {
-	      fileinfo->next = ld_state.relfiles->next;
-	      ld_state.relfiles = ld_state.relfiles->next = fileinfo;
-	    }
-
-	  /* Update some summary information in the state structure.  */
-	  ld_state.nsymtab += fileinfo->nsymtab;
-	  ld_state.nlocalsymbols += fileinfo->nlocalsymbols;
-	}
-      else if (likely (fileinfo->file_type == dso_file_type))
-	{
-	  CSNGL_LIST_ADD_REAR (ld_state.dsofiles, fileinfo);
-	  ++ld_state.ndsofiles;
-
-	  if (fileinfo->lazyload)
-	    /* We have to create another dynamic section entry for the
-	       DT_POSFLAG_1 entry.
-
-	       XXX Once more functionality than the lazyloading flag
-	       are suppported the test must be extended.  */
-	    ++ld_state.ndsofiles;
-	}
-    }
-
-  return 0;
-}
-
-
-int
-ld_handle_filename_list (struct filename_list *fnames)
-{
-  struct filename_list *runp;
-  int res = 0;
-
-  for (runp = fnames; runp != NULL; runp = runp->next)
-    {
-      struct usedfiles *curp;
-
-      /* Create a record for the new file.  */
-      curp = runp->real = ld_new_inputfile (runp->name, relocatable_file_type);
-
-      /* Set flags for group handling.  */
-      curp->group_start = runp->group_start;
-      curp->group_end = runp->group_end;
-
-      /* Set as-needed flag from the file, not the command line.  */
-      curp->as_needed = runp->as_needed;
-
-      /* Read the file and everything else which comes up, including
-	 handling groups.  */
-      do
-	res |= FILE_PROCESS (-1, curp, &ld_state, &curp);
-      while (curp != NULL);
-    }
-
-  /* Free the list.  */
-  while (fnames != NULL)
-    {
-      runp = fnames;
-      fnames = fnames->next;
-      free (runp);
-    }
-
-  return res;
-}
-
-
-/* Handle opening of the given file with ELF descriptor.  */
-static int
-open_elf (struct usedfiles *fileinfo, Elf *elf)
-{
-  int res = 0;
-
-  if (elf == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot get descriptor for ELF file (%s:%d): %s\n"),
-	   __FILE__, __LINE__, elf_errmsg (-1));
-
-  if (unlikely (elf_kind (elf) == ELF_K_NONE))
-    {
-      struct filename_list *fnames;
-
-      /* We don't have to look at this file again.  */
-      fileinfo->status = closed;
-
-      /* Let's see whether this is a linker script.  */
-      if (fileinfo->fd != -1)
-	/* Create a stream from the file handle we know.  */
-	ldin = fdopen (fileinfo->fd, "r");
-      else
-	{
-	  /* Get the memory for the archive member.  */
-	  char *content;
-	  size_t contentsize;
-
-	  /* Get the content of the file.  */
-	  content = elf_rawfile (elf, &contentsize);
-	  if (content == NULL)
-	    {
-	      fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-		       fileinfo->rfname, __FILE__, __LINE__);
-	      return 1;
-	    }
-
-	  /* The content of the file is available in memory.  Read the
-	     memory region as a stream.  */
-	  ldin = fmemopen (content, contentsize, "r");
-	}
-
-      /* No need for locking.  */
-      __fsetlocking (ldin, FSETLOCKING_BYCALLER);
-
-      if (ldin == NULL)
-	error (EXIT_FAILURE, errno, gettext ("cannot open '%s'"),
-	       fileinfo->rfname);
-
-      /* Parse the file.  If it is a linker script no problems will be
-	 reported.  */
-      ld_state.srcfiles = NULL;
-      ldlineno = 1;
-      ld_scan_version_script = 0;
-      ldin_fname = fileinfo->rfname;
-      res = ldparse ();
-
-      fclose (ldin);
-      if (fileinfo->fd != -1 && !fileinfo->fd_passed)
-	{
-	  /* We won't need the file descriptor again.  */
-	  close (fileinfo->fd);
-	  fileinfo->fd = -1;
-	}
-
-      elf_end (elf);
-
-      if (unlikely (res != 0))
-	/* Something went wrong during parsing.  */
-	return 1;
-
-      /* This is no ELF file.  */
-      fileinfo->elf = NULL;
-
-      /* Now we have to handle eventual INPUT and GROUP statements in
-	 the script.  Read the files mentioned.  */
-      fnames = ld_state.srcfiles;
-      if (fnames != NULL)
-	{
-	  struct filename_list *oldp;
-
-	  /* Convert the list into a normal single-linked list.  */
-	  oldp = fnames;
-	  fnames = fnames->next;
-	  oldp->next = NULL;
-
-	  /* Remove the list from the state structure.  */
-	  ld_state.srcfiles = NULL;
-
-	  if (unlikely (ld_handle_filename_list (fnames) != 0))
-	    return 1;
-	}
-
-      return 0;
-    }
-
-  /* Store the file info.  */
-  fileinfo->elf = elf;
-
-  /* The file is ready for action.  */
-  fileinfo->status = opened;
-
-  return 0;
-}
-
-
-static int
-add_whole_archive (struct usedfiles *fileinfo)
-{
-  Elf *arelf;
-  Elf_Cmd cmd = ELF_C_READ_MMAP_PRIVATE;
-  int res = 0;
-
-  while ((arelf = elf_begin (fileinfo->fd, cmd, fileinfo->elf)) != NULL)
-    {
-      Elf_Arhdr *arhdr = elf_getarhdr (arelf);
-      struct usedfiles *newp;
-
-      if (arhdr == NULL)
-	abort ();
-
-      /* Just to be sure; since these are no files in the archive
-	 these names should never be returned.  */
-      assert (strcmp (arhdr->ar_name, "/") != 0);
-      assert (strcmp (arhdr->ar_name, "//") != 0);
-
-      newp = ld_new_inputfile (arhdr->ar_name, relocatable_file_type);
-      newp->archive_file = fileinfo;
-
-      if (unlikely (ld_state.trace_files))
-	print_file_name (stdout, newp, 1, 1);
-
-      /* This shows that this file is contained in an archive.  */
-      newp->fd = -1;
-      /* Store the ELF descriptor.  */
-      newp->elf = arelf;
-      /* Show that we are open for business.  */
-      newp->status = opened;
-
-      /* Proces the file, add all the symbols etc.  */
-      res = file_process2 (newp);
-      if (unlikely (res != 0))
-	    break;
-
-      /* Advance to the next archive element.  */
-      cmd = elf_next (arelf);
-    }
-
-  return res;
-}
-
-
-static int
-extract_from_archive (struct usedfiles *fileinfo)
-{
-  static int archive_seq;
-  int res = 0;
-
-  if (fileinfo->archive_seq == 0)
-    /* This is an archive we are not using completely.  Give it a
-       unique number.  */
-    fileinfo->archive_seq = ++archive_seq;
-
-  /* If there are no unresolved symbols don't do anything.  */
-  assert (ld_state.extract_rule == defaultextract
-	  || ld_state.extract_rule == weakextract);
-  if ((likely (ld_state.extract_rule == defaultextract)
-       ? ld_state.nunresolved_nonweak : ld_state.nunresolved) == 0)
-    return 0;
-
-  Elf_Arsym *syms;
-  size_t nsyms;
-
-  /* Get all the symbols.  */
-  syms = elf_getarsym (fileinfo->elf, &nsyms);
-  if (syms == NULL)
-    {
-    cannot_read_archive:
-      error (0, 0, gettext ("cannot read archive `%s': %s"),
-	     fileinfo->rfname, elf_errmsg (-1));
-
-      /* We cannot use this archive anymore.  */
-      fileinfo->status = closed;
-
-      return 1;
-    }
-
-  /* Now add all the symbols to the hash table.  Note that there
-     can potentially be duplicate definitions.  We'll always use
-     the first definition.  */
-  // XXX Is this a compatible behavior?
-  bool any_used;
-  do
-    {
-      any_used = false;
-
-      size_t cnt;
-      for (cnt = 0; cnt < nsyms; ++cnt)
-	{
-	  struct symbol search = { .name = syms[cnt].as_name };
-	  struct symbol *sym = ld_symbol_tab_find (&ld_state.symbol_tab,
-						   syms[cnt].as_hash, &search);
-	  if (sym != NULL && ! sym->defined)
-	    {
-	      /* The symbol is referenced and not defined.  */
-	      Elf *arelf;
-	      Elf_Arhdr *arhdr;
-	      struct usedfiles *newp;
-
-	      /* Find the archive member for this symbol.  */
-	      if (unlikely (elf_rand (fileinfo->elf, syms[cnt].as_off)
-			    != syms[cnt].as_off))
-		goto cannot_read_archive;
-
-	      /* Note: no test of a failing 'elf_begin' call.  That's fine
-		 since 'elf'getarhdr' will report the problem.  */
-	      arelf = elf_begin (fileinfo->fd, ELF_C_READ_MMAP_PRIVATE,
-				 fileinfo->elf);
-	      arhdr = elf_getarhdr (arelf);
-	      if (arhdr == NULL)
-		goto cannot_read_archive;
-
-	      /* We have all the information and an ELF handle for the
-		 archive member.  Create the normal data structure for
-		 a file now.  */
-	      newp = ld_new_inputfile (obstack_strdup (&ld_state.smem,
-						       arhdr->ar_name),
-				       relocatable_file_type);
-	      newp->archive_file = fileinfo;
-
-	      if (unlikely (ld_state.trace_files))
-		print_file_name (stdout, newp, 1, 1);
-
-	      /* This shows that this file is contained in an archive.  */
-	      newp->fd = -1;
-	      /* Store the ELF descriptor.  */
-	      newp->elf = arelf;
-	      /* Show that we are open for business.  */
-	      newp->status = in_archive;
-
-	      /* Now read the file and add all the symbols.  */
-	      res = file_process2 (newp);
-	      if (unlikely (res != 0))
-		return res;
-
-	      any_used = true;
-	    }
-	}
-
-      if (any_used)
-	{
-	  /* This is an archive therefore it must have a number.  */
-	  assert (fileinfo->archive_seq != 0);
-	  ld_state.last_archive_used = fileinfo->archive_seq;
-	}
-    }
-  while (any_used);
-
-  return res;
-}
-
-
-static int
-file_process2 (struct usedfiles *fileinfo)
-{
-  int res;
-
-  if (likely (elf_kind (fileinfo->elf) == ELF_K_ELF))
-    {
-      /* The first time we get here we read the ELF header.  */
-#if NATIVE_ELF != 0
-      if (likely (fileinfo->ehdr == NULL))
-#else
-      if (likely (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_NONE))
-#endif
-	{
-	  XElf_Ehdr *ehdr;
-#if NATIVE_ELF != 0
-	  ehdr = xelf_getehdr (fileinfo->elf, fileinfo->ehdr);
-#else
-	  xelf_getehdr_copy (fileinfo->elf, ehdr, fileinfo->ehdr);
-#endif
-	  if (ehdr == NULL)
-	    {
-	      fprintf (stderr, gettext ("%s: invalid ELF file (%s:%d)\n"),
-		       fileinfo->rfname, __FILE__, __LINE__);
-	      fileinfo->status = closed;
-	      return 1;
-	    }
-
-	  if (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_REL
-	      && unlikely (FILEINFO_EHDR (fileinfo->ehdr).e_type != ET_DYN))
-	    /* XXX Add ebl* function to query types which are allowed
-	       to link in.  */
-	    {
-	      char buf[64];
-
-	      print_file_name (stderr, fileinfo, 1, 0);
-	      fprintf (stderr,
-		       gettext ("file of type %s cannot be linked in\n"),
-		       ebl_object_type_name (ld_state.ebl,
-					     FILEINFO_EHDR (fileinfo->ehdr).e_type,
-					     buf, sizeof (buf)));
-	      fileinfo->status = closed;
-	      return 1;
-	    }
-
-	  /* Make sure the file type matches the backend.  */
-	  if (FILEINFO_EHDR (fileinfo->ehdr).e_machine
-	      != ebl_get_elfmachine (ld_state.ebl))
-	    {
-	      fprintf (stderr, gettext ("\
-%s: input file incompatible with ELF machine type %s\n"),
-		       fileinfo->rfname,
-		       ebl_backend_name (ld_state.ebl));
-	      fileinfo->status = closed;
-	      return 1;
-	    }
-
-	  /* Determine the section header string table section index.  */
-	  if (unlikely (elf_getshdrstrndx (fileinfo->elf, &fileinfo->shstrndx)
-			< 0))
-	    {
-	      fprintf (stderr, gettext ("\
-%s: cannot get section header string table index: %s\n"),
-		       fileinfo->rfname, elf_errmsg (-1));
-	      fileinfo->status = closed;
-	      return 1;
-	    }
-	}
-
-      /* Now handle the different types of files.  */
-      if (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_REL)
-	{
-	  /* Add all the symbol.  Relocatable files have symbol
-	     tables.  */
-	  res = add_relocatable_file (fileinfo, SHT_SYMTAB);
-	}
-      else
-	{
-	  bool has_l_name = fileinfo->file_type == archive_file_type;
-
-	  assert (FILEINFO_EHDR (fileinfo->ehdr).e_type == ET_DYN);
-
-	  /* If the file is a DT_NEEDED dependency then the type is
-	     already correctly specified.  */
-	  if (fileinfo->file_type != dso_needed_file_type)
-	    fileinfo->file_type = dso_file_type;
-
-	  /* We cannot use DSOs when generating relocatable objects.  */
-	  if (ld_state.file_type == relocatable_file_type)
-	    {
-	      error (0, 0, gettext ("\
-cannot use DSO '%s' when generating relocatable object file"),
-		     fileinfo->fname);
-	      return 1;
-	    }
-
-	  /* Add all the symbols.  For DSOs we are looking at the
-	     dynamic symbol table.  */
-	  res = add_relocatable_file (fileinfo, SHT_DYNSYM);
-
-	  /* We always have to have a dynamic section.  */
-	  assert (fileinfo->dynscn != NULL);
-
-	  /* We have to remember the dependencies for this object.  It
-	     is necessary to look them up.  */
-	  XElf_Shdr_vardef (dynshdr);
-	  xelf_getshdr (fileinfo->dynscn, dynshdr);
-
-	  Elf_Data *dyndata = elf_getdata (fileinfo->dynscn, NULL);
-	  /* XXX Should we flag the failure to get the dynamic section?  */
-	  if (dynshdr != NULL)
-	    {
-	      int cnt = dynshdr->sh_size / dynshdr->sh_entsize;
-	      XElf_Dyn_vardef (dyn);
-
-	      while (--cnt >= 0)
-		{
-		  xelf_getdyn (dyndata, cnt, dyn);
-		  if (dyn != NULL)
-		    {
-		      if(dyn->d_tag == DT_NEEDED)
-			{
-			  struct usedfiles *newp;
-
-			  newp = ld_new_inputfile (elf_strptr (fileinfo->elf,
-							       dynshdr->sh_link,
-							       dyn->d_un.d_val),
-						   dso_needed_file_type);
-
-			  /* Enqueue the newly found dependencies.  */
-			  // XXX Check that there not already a file with the
-			  // same name.
-			  CSNGL_LIST_ADD_REAR (ld_state.needed, newp);
-			}
-		      else if (dyn->d_tag == DT_SONAME)
-			{
-			  /* We use the DT_SONAME (this is what's there
-			     for).  */
-			  fileinfo->soname = elf_strptr (fileinfo->elf,
-							 dynshdr->sh_link,
-							 dyn->d_un.d_val);
-			  has_l_name = false;
-			}
-		    }
-		}
-	    }
-
-	  /* Construct the file name if the DSO has no SONAME and the
-	     file name comes from a -lXX parameter on the comment
-	     line.  */
-	  if (unlikely (has_l_name))
-	    {
-	      /* The FNAME is the parameter the user specified on the
-		 command line.  We prepend "lib" and append ".so".  */
-	      size_t len = strlen (fileinfo->fname) + 7;
-	      char *newp;
-
-	      newp = (char *) obstack_alloc (&ld_state.smem, len);
-	      strcpy (stpcpy (stpcpy (newp, "lib"), fileinfo->fname), ".so");
-
-	      fileinfo->soname = newp;
-	    }
-	}
-    }
-  else if (likely (elf_kind (fileinfo->elf) == ELF_K_AR))
-    {
-      if (unlikely (ld_state.extract_rule == allextract))
-	/* Which this option enabled we have to add all the object
-	   files in the archive.  */
-	res = add_whole_archive (fileinfo);
-      else if (ld_state.file_type == relocatable_file_type)
-	{
-	  /* When generating a relocatable object we don't find files
-	     in archives.  */
-	  if (verbose)
-	    error (0, 0, gettext ("input file '%s' ignored"), fileinfo->fname);
-
-	  res = 0;
-	}
-      else
-	{
-	  if (ld_state.group_start_requested
-	      && ld_state.group_start_archive == NULL)
-	    ld_state.group_start_archive = fileinfo;
-
-	  if (ld_state.archives == NULL)
-	    ld_state.archives = fileinfo;
-
-	  if (ld_state.tailarchives != NULL)
-	    ld_state.tailarchives->next = fileinfo;
-	  ld_state.tailarchives = fileinfo;
-
-	  /* Extract only the members from the archive which are
-	     currently referenced by unresolved symbols.  */
-	  res = extract_from_archive (fileinfo);
-	}
-    }
-  else
-    /* This should never happen, we know about no other types.  */
-    abort ();
-
-  return res;
-}
-
-
-/* Process a given file.  The first parameter is a file descriptor for
-   the file which can be -1 to indicate the file has not yet been
-   found.  The second parameter describes the file to be opened, the
-   last one is the state of the linker which among other information
-   contain the paths we look at.  */
-static int
-ld_generic_file_process (int fd, struct usedfiles *fileinfo,
-			 struct ld_state *statep, struct usedfiles **nextp)
-{
-  int res = 0;
-
-  /* By default we go to the next file in the list.  */
-  *nextp = fileinfo->next;
-
-  /* Set the flag to signal we are looking for a group start.  */
-  if (unlikely (fileinfo->group_start))
-    {
-      ld_state.group_start_requested = true;
-      fileinfo->group_start = false;
-    }
-
-  /* If the file isn't open yet, open it now.  */
-  if (likely (fileinfo->status == not_opened))
-    {
-      bool fd_passed = true;
-
-      if (likely (fd == -1))
-	{
-	  /* Find the file ourselves.  */
-	  int err = open_along_path (fileinfo);
-	  if (unlikely (err != 0))
-	    /* We allow libraries and DSOs to be named more than once.
-	       Don't report an error to the caller.  */
-	    return err == EAGAIN ? 0 : err;
-
-	  fd_passed = false;
-	}
-      else
-	fileinfo->fd = fd;
-
-      /* Remember where we got the descriptor from.  */
-      fileinfo->fd_passed = fd_passed;
-
-      /* We found the file.  Now test whether it is a file type we can
-	 handle.
-
-	 XXX Do we need to have the ability to start from a given
-	 position in the search path again to look for another file if
-	 the one found has not the right type?  */
-      res = open_elf (fileinfo, elf_begin (fileinfo->fd,
-					   is_dso_p (fileinfo->fd)
-					   ? ELF_C_READ_MMAP
-					   : ELF_C_READ_MMAP_PRIVATE, NULL));
-      if (unlikely (res != 0))
-	return res;
-    }
-
-  /* Now that we have opened the file start processing it.  */
-  if (likely (fileinfo->status != closed))
-    res = file_process2 (fileinfo);
-
-  /* Determine which file to look at next.  */
-  if (unlikely (fileinfo->group_backref != NULL))
-    {
-      /* We only go back if an archive other than the one we would go
-	 back to has been used in the last round.  */
-      if (ld_state.last_archive_used > fileinfo->group_backref->archive_seq)
-	{
-	  *nextp = fileinfo->group_backref;
-	  ld_state.last_archive_used = 0;
-	}
-      else
-	{
-	  /* If we come here this means that the archives we read so
-	     far are not needed anymore.  We can free some of the data
-	     now.  */
-	  struct usedfiles *runp = ld_state.archives;
-
-	  do
-	    {
-	      /* We don't need the ELF descriptor anymore.  Unless there
-		 are no files from the archive used this will not free
-		 the whole file but only some data structures.  */
-	      elf_end (runp->elf);
-	      runp->elf = NULL;
-
-	      runp = runp->next;
-	    }
-	  while (runp != fileinfo->next);
-
-	  /* Do not do this again.  */
-	  ld_state.archives = NULL;
-
-	  /* Do not move on to the next archive.  */
-	  *nextp = fileinfo->next = NULL;
-	}
-    }
-  else if (unlikely (fileinfo->group_end))
-    {
-      /* This is the end of a group.  We possibly have to go back.
-	 Determine which file we would go back to and see whether it
-	 makes sense.  If there has not been an archive we don't have
-	 to do anything.  */
-      if (ld_state.group_start_requested)
-	{
-	  if (ld_state.group_start_archive != ld_state.tailarchives)
-	    /* The loop includes more than one archive, add the pointer.  */
-	    {
-	      *nextp = ld_state.tailarchives->group_backref =
-		ld_state.group_start_archive;
-	      ld_state.last_archive_used = 0;
-	    }
-	  else
-	    /* We might still have to go back to the beginning of the
-	       group if since the last archive other files have been
-	       added.  But we go back exactly once.  */
-	    if (ld_state.tailarchives != fileinfo)
-	      {
-		*nextp = ld_state.group_start_archive;
-		ld_state.last_archive_used = 0;
-	      }
-	}
-
-      /* Clear the flags.  */
-      ld_state.group_start_requested = false;
-      ld_state.group_start_archive = NULL;
-      fileinfo->group_end = false;
-    }
-
-  return res;
-}
-
-
-/* Library names passed to the linker as -lXX represent files named
-   libXX.YY.  The YY part can have different forms, depending on the
-   platform.  The generic set is .so and .a (in this order).  */
-static const char **
-ld_generic_lib_extensions (struct ld_state *statep __attribute__ ((__unused__)))
-{
-  static const char *exts[] =
-    {
-      ".so", ".a", NULL
-    };
-
-  return exts;
-}
-
-
-/* Flag unresolved symbols.  */
-static int
-ld_generic_flag_unresolved (struct ld_state *statep)
-{
-  int retval = 0;
-
-  if (ld_state.nunresolved_nonweak > 0)
-    {
-      /* Go through the list and determine the unresolved symbols.  */
-      struct symbol *first;
-      struct symbol *s;
-
-      s = first = ld_state.unresolved->next;
-      do
-	{
-	  if (! s->defined && ! s->weak)
-	    {
-	      /* Two special symbol we recognize: the symbol for the
-		 GOT and the dynamic section.  */
-	      if (strcmp (s->name, "_GLOBAL_OFFSET_TABLE_") == 0
-		  || strcmp (s->name, "_DYNAMIC") == 0)
-		{
-		  /* We will have to fill in more information later.  */
-		  ld_state.need_got = true;
-
-		  /* Remember that we found it.  */
-		  if (s->name[1] == 'G')
-		    ld_state.got_symbol = s;
-		  else
-		    ld_state.dyn_symbol = s;
-		}
-	      else if (ld_state.file_type != dso_file_type || !ld_state.nodefs)
-		{
-		  /* XXX The error message should get better.  It should use
-		     the debugging information if present to tell where in the
-		     sources the undefined reference is.  */
-		  error (0, 0, gettext ("undefined symbol `%s' in %s"),
-			 s->name, s->file->fname);
-
-		  retval = 1;
-		}
-	    }
-
-	  /* We cannot decide here what to do with undefined
-	     references which will come from DSO since we do not know
-	     what kind of symbol we expect.  Only when looking at the
-	     relocations we can see whether we need a PLT entry or
-	     only a GOT entry.  */
-
-	  s = s->next;
-	}
-      while (s != first);
-    }
-
-  return retval;
-}
-
-
-/* Close the given file.  */
-static int
-ld_generic_file_close (struct usedfiles *fileinfo, struct ld_state *statep)
-{
-  /* Close the ELF descriptor.  */
-  elf_end (fileinfo->elf);
-
-  /* If we have opened the file descriptor close it.  But we might
-     have done this already in which case FD is -1.  */
-  if (!fileinfo->fd_passed && fileinfo->fd != -1)
-    close (fileinfo->fd);
-
-  /* We allocated the resolved file name.  */
-  if (fileinfo->fname != fileinfo->rfname)
-    free ((char *) fileinfo->rfname);
-
-  return 0;
-}
-
-
-static void
-new_generated_scn (enum scn_kind kind, const char *name, int type, int flags,
-		   int entsize, int align)
-{
-  struct scnhead *newp;
-
-  newp = (struct scnhead *) obstack_calloc (&ld_state.smem,
-					    sizeof (struct scnhead));
-  newp->kind = kind;
-  newp->name = name;
-  newp->nameent = ebl_strtabadd (ld_state.shstrtab, name, 0);
-  newp->type = type;
-  newp->flags = flags;
-  newp->entsize = entsize;
-  newp->align = align;
-  newp->grp_signature = NULL;
-  newp->used = true;
-
-  /* All is well.  Create now the data for the section and insert it
-     into the section table.  */
-  ld_section_tab_insert (&ld_state.section_tab, elf_hash (name), newp);
-}
-
-
-/* Create the sections which are generated by the linker and are not
-   present in the input file.  */
-static void
-ld_generic_generate_sections (struct ld_state *statep)
-{
-  /* The relocation section type.  */
-  int rel_type = REL_TYPE (&ld_state) == DT_REL ? SHT_REL : SHT_RELA;
-
-  /* When requested, every output file will have a build ID section.  */
-  if (statep->build_id != NULL)
-    new_generated_scn (scn_dot_note_gnu_build_id, ".note.gnu.build-id",
-		       SHT_NOTE, SHF_ALLOC, 0, 4);
-
-  /* When building dynamically linked object we have to include a
-     section containing a string describing the interpreter.  This
-     should be at the very beginning of the file together with the
-     other information the ELF loader (kernel or wherever) has to look
-     at.  We put it as the first section in the file.
-
-     We also have to create the dynamic segment which is a special
-     section the dynamic linker locates through an entry in the
-     program header.  */
-  if (dynamically_linked_p ())
-    {
-      /* Use any versioning (defined or required)?  */
-      bool use_versioning = false;
-      /* Use version requirements?  */
-      bool need_version = false;
-
-      /* First the .interp section.  */
-      if (ld_state.interp != NULL || ld_state.file_type != dso_file_type)
-	new_generated_scn (scn_dot_interp, ".interp", SHT_PROGBITS, SHF_ALLOC,
-			   0, 1);
-
-      /* Now the .dynamic section.  */
-      new_generated_scn (scn_dot_dynamic, ".dynamic", SHT_DYNAMIC,
-			 DYNAMIC_SECTION_FLAGS (&ld_state),
-			 xelf_fsize (ld_state.outelf, ELF_T_DYN, 1),
-			 xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
-      /* We will need in any case the dynamic symbol table (even in
-	 the unlikely case that no symbol is exported or referenced
-	 from a DSO).  */
-      ld_state.need_dynsym = true;
-      new_generated_scn (scn_dot_dynsym, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
-			 xelf_fsize (ld_state.outelf, ELF_T_SYM, 1),
-			 xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-      /* It comes with a string table.  */
-      new_generated_scn (scn_dot_dynstr, ".dynstr", SHT_STRTAB, SHF_ALLOC,
-			 0, 1);
-      /* And a hashing table.  */
-      // XXX For Linux/Alpha we need other sizes unless they change...
-      if (GENERATE_SYSV_HASH)
-	new_generated_scn (scn_dot_hash, ".hash", SHT_HASH, SHF_ALLOC,
-			   sizeof (Elf32_Word), sizeof (Elf32_Word));
-      if (GENERATE_GNU_HASH)
-	new_generated_scn (scn_dot_gnu_hash, ".gnu.hash", SHT_GNU_HASH,
-			   SHF_ALLOC, sizeof (Elf32_Word),
-			   sizeof (Elf32_Word));
-
-      /* Create the section associated with the PLT if necessary.  */
-      if (ld_state.nplt > 0)
-	{
-	  /* Create the .plt section.  */
-	  /* XXX We might need a function which returns the section flags.  */
-	  new_generated_scn (scn_dot_plt, ".plt", SHT_PROGBITS,
-			     SHF_ALLOC | SHF_EXECINSTR,
-			     /* XXX Is the size correct?  */
-			     xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
-			     xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
-	  /* Create the relocation section for the .plt.  This is always
-	     separate even if the other relocation sections are combined.  */
-	  new_generated_scn (scn_dot_pltrel, ".rel.plt", rel_type, SHF_ALLOC,
-			     rel_type == SHT_REL
-			     ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
-			     : xelf_fsize (ld_state.outelf, ELF_T_RELA, 1),
-			     xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
-	  /* XXX We might need a function which returns the section flags.  */
-	  new_generated_scn (scn_dot_gotplt, ".got.plt", SHT_PROGBITS,
-			     SHF_ALLOC | SHF_WRITE,
-			     xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
-			     xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
-	  /* Mark all used DSOs as used.  Determine whether any referenced
-	     object uses symbol versioning.  */
-	  if (ld_state.from_dso != NULL)
-	    {
-	      struct symbol *srunp = ld_state.from_dso;
-
-	      do
-		{
-		  srunp->file->used = true;
-
-		  if (srunp->file->verdefdata != NULL)
-		    {
-		      XElf_Versym versym;
-
-		      /* The input DSO uses versioning.  */
-		      use_versioning = true;
-		      /* We reference versions.  */
-		      need_version = true;
-
-		      if (xelf_getversym_copy (srunp->file->versymdata,
-					       srunp->symidx, versym) == NULL)
-			assert (! "xelf_getversym failed");
-
-		      /* We cannot link explicitly with an older
-			 version of a symbol.  */
-		      assert ((versym & 0x8000) == 0);
-		      /* We cannot reference local (index 0) or plain
-			 global (index 1) versions.  */
-		      assert (versym > 1);
-
-		      /* Check whether we have already seen the
-			 version and if not add it to the referenced
-			 versions in the output file.  */
-		      if (! srunp->file->verdefused[versym])
-			{
-			  srunp->file->verdefused[versym] = 1;
-
-			  if (++srunp->file->nverdefused == 1)
-			    /* Count the file if it is using versioning.  */
-			    ++ld_state.nverdeffile;
-			  ++ld_state.nverdefused;
-			}
-		    }
-		}
-	      while ((srunp = srunp->next) != ld_state.from_dso);
-	    }
-
-	  /* Create the sections used to record version dependencies.  */
-	  if (need_version)
-	    new_generated_scn (scn_dot_version_r, ".gnu.version_r",
-			       SHT_GNU_verneed, SHF_ALLOC, 0,
-			       xelf_fsize (ld_state.outelf, ELF_T_WORD, 1));
-	}
-
-      /* Now count the used DSOs since this is what the user
-	 wants.  */
-      int ndt_needed = 0;
-      if (ld_state.ndsofiles > 0)
-	{
-	  struct usedfiles *frunp = ld_state.dsofiles;
-
-	  do
-	    if (! frunp->as_needed || frunp->used)
-	      {
-		++ndt_needed;
-		if (frunp->lazyload)
-		  /* We have to create another dynamic section
-		     entry for the DT_POSFLAG_1 entry.
-
-		     XXX Once more functionality than the lazyloading
-		     flag are suppported the test must be
-		     extended.  */
-		  ++ndt_needed;
-	      }
-	  while ((frunp = frunp->next) != ld_state.dsofiles);
-	}
-
-      if (use_versioning)
-	new_generated_scn (scn_dot_version, ".gnu.version", SHT_GNU_versym,
-			   SHF_ALLOC,
-			   xelf_fsize (ld_state.outelf, ELF_T_HALF, 1),
-			   xelf_fsize (ld_state.outelf, ELF_T_HALF, 1));
-
-      /* We need some entries all the time.  */
-      ld_state.ndynamic = (7 + (ld_state.runpath != NULL
-				|| ld_state.rpath != NULL)
-			   + ndt_needed
-			   + (ld_state.init_symbol != NULL ? 1 : 0)
-			   + (ld_state.fini_symbol != NULL ? 1 : 0)
-			   + (use_versioning ? 1 : 0)
-			   + (need_version ? 2 : 0)
-			   + (ld_state.nplt > 0 ? 4 : 0)
-			   + (ld_state.relsize_total > 0 ? 3 : 0));
-    }
-
-  /* When creating a relocatable file or when we are not stripping the
-     output file we create a symbol table.  */
-  ld_state.need_symtab = (ld_state.file_type == relocatable_file_type
-			  || ld_state.strip == strip_none);
-
-  /* Add the .got section if needed.  */
-  if (ld_state.need_got)
-    /* XXX We might need a function which returns the section flags.  */
-    new_generated_scn (scn_dot_got, ".got", SHT_PROGBITS,
-		       SHF_ALLOC | SHF_WRITE,
-		       xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1),
-		       xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-
-  /* Add the .rel.dyn section.  */
-  if (ld_state.relsize_total > 0)
-    new_generated_scn (scn_dot_dynrel, ".rel.dyn", rel_type, SHF_ALLOC,
-		       rel_type == SHT_REL
-		       ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
-		       : xelf_fsize (ld_state.outelf, ELF_T_RELA, 1),
-		       xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1));
-}
-
-
-/* Callback function registered with on_exit to make sure the temporary
-   files gets removed if something goes wrong.  */
-static void
-remove_tempfile (int status, void *arg)
-{
-  if (status != 0 && ld_state.tempfname != NULL)
-    unlink (ld_state.tempfname);
-}
-
-
-/* Create the output file.  The file name is given or "a.out".  We
-   create as much of the ELF structure as possible.  */
-static int
-ld_generic_open_outfile (struct ld_state *statep, int machine, int klass,
-			 int data)
-{
-  /* We do not create the new file right away with the final name.
-     This would destroy an existing file with this name before a
-     replacement is finalized.  We create instead a temporary file in
-     the same directory.  */
-  if (ld_state.outfname == NULL)
-    ld_state.outfname = "a.out";
-
-  size_t outfname_len = strlen (ld_state.outfname);
-  char *tempfname = (char *) obstack_alloc (&ld_state.smem,
-					    outfname_len + sizeof (".XXXXXX"));
-  ld_state.tempfname = tempfname;
-
-  int fd;
-  int try = 0;
-  while (1)
-    {
-      strcpy (mempcpy (tempfname, ld_state.outfname, outfname_len), ".XXXXXX");
-
-      /* The use of mktemp() here is fine.  We do not want to use
-	 mkstemp() since then the umask isn't used.  And the output
-	 file will have these permissions anyhow.  Any intruder could
-	 change the file later if it would be possible now.  */
-      if (mktemp (tempfname) != NULL
-	  && (fd = open (tempfname, O_RDWR | O_EXCL | O_CREAT | O_NOFOLLOW,
-			 ld_state.file_type == relocatable_file_type
-			 ? DEFFILEMODE : ACCESSPERMS)) != -1)
-	break;
-
-      /* Failed this round.  We keep trying a number of times.  */
-      if (++try >= 10)
-	error (EXIT_FAILURE, errno, gettext ("cannot create output file"));
-    }
-  ld_state.outfd = fd;
-
-  /* Make sure we remove the temporary file in case something goes
-     wrong.  */
-  on_exit (remove_tempfile, NULL);
-
-  /* Create the ELF file data for the output file.  */
-  Elf *elf = ld_state.outelf = elf_begin (fd,
-					  conserve_memory
-					  ? ELF_C_WRITE : ELF_C_WRITE_MMAP,
-					  NULL);
-  if (elf == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create ELF descriptor for output file: %s"),
-	   elf_errmsg (-1));
-
-  /* Create the basic data structures.  */
-  if (! xelf_newehdr (elf, klass))
-    /* Couldn't create the ELF header.  Very bad.  */
-    error (EXIT_FAILURE, 0,
-	   gettext ("could not create ELF header for output file: %s"),
-	   elf_errmsg (-1));
-
-  /* And get the current header so that we can modify it.  */
-  XElf_Ehdr_vardef (ehdr);
-  xelf_getehdr (elf, ehdr);
-  assert (ehdr != NULL);
-
-  /* Set the machine type.  */
-  ehdr->e_machine = machine;
-
-  /* Modify it according to the info we have here and now.  */
-  if (ld_state.file_type == executable_file_type)
-    ehdr->e_type = ET_EXEC;
-  else if (ld_state.file_type == dso_file_type)
-    ehdr->e_type = ET_DYN;
-  else
-    {
-      assert (ld_state.file_type == relocatable_file_type);
-      ehdr->e_type = ET_REL;
-    }
-
-  /* Set the ELF version.  */
-  ehdr->e_version = EV_CURRENT;
-
-  /* Set the endianness.  */
-  ehdr->e_ident[EI_DATA] = data;
-
-  /* Write the ELF header information back.  */
-  (void) xelf_update_ehdr (elf, ehdr);
-
-  return 0;
-}
-
-
-/* We compute the offsets of the various copied objects and the total
-   size of the memory needed.  */
-// XXX The method used here is simple: go from front to back and pack
-// the objects in this order.  A more space efficient way would
-// actually trying to pack the objects as dense as possible.  But this
-// is more expensive.
-static void
-compute_copy_reloc_offset (XElf_Shdr *shdr)
-{
-  struct symbol *runp = ld_state.from_dso;
-  assert (runp != NULL);
-
-  XElf_Off maxalign = 1;
-  XElf_Off offset = 0;
-
-  do
-    if (runp->need_copy)
-      {
-	/* Determine alignment for the symbol.  */
-	// XXX The question is how?  The symbol record itself does not
-	// have the information.  So we have to be conservative and
-	// assume the alignment of the section the symbol is in.
-
-	// XXX We can be more precise.  Use the offset from the beginning
-	// of the section and determine the largest power of two with
-	// module zero.
-	XElf_Off symalign = MAX (SCNINFO_SHDR (runp->file->scninfo[runp->scndx].shdr).sh_addralign, 1);
-	/* Keep track of the maximum alignment requirement.  */
-	maxalign = MAX (maxalign, symalign);
-
-	/* Align current position.  */
-	offset = (offset + symalign - 1) & ~(symalign - 1);
-
-	runp->merge.value = offset;
-
-	offset += runp->size;
-      }
-  while ((runp = runp->next) != ld_state.from_dso);
-
-  shdr->sh_type = SHT_NOBITS;
-  shdr->sh_size = offset;
-  shdr->sh_addralign = maxalign;
-}
-
-
-static void
-compute_common_symbol_offset (XElf_Shdr *shdr)
-{
-  struct symbol *runp = ld_state.common_syms;
-  assert (runp != NULL);
-
-  XElf_Off maxalign = 1;
-  XElf_Off offset = 0;
-
-  do
-    {
-      /* Determine alignment for the symbol.  */
-      XElf_Off symalign = runp->merge.value;
-
-      /* Keep track of the maximum alignment requirement.  */
-      maxalign = MAX (maxalign, symalign);
-
-      /* Align current position.  */
-      offset = (offset + symalign - 1) & ~(symalign - 1);
-
-      runp->merge.value = offset;
-
-      offset += runp->size;
-    }
-  while ((runp = runp->next) != ld_state.common_syms);
-
-  shdr->sh_type = SHT_NOBITS;
-  shdr->sh_size = offset;
-  shdr->sh_addralign = maxalign;
-}
-
-
-static void
-sort_sections_generic (void)
-{
-  /* XXX TBI */
-  abort ();
-}
-
-
-static int
-match_section (const char *osectname, struct filemask_section_name *sectmask,
-	       struct scnhead **scnhead, bool new_section, size_t segment_nr)
-{
-  struct scninfo *prevp;
-  struct scninfo *runp;
-  struct scninfo *notused;
-
-  if (fnmatch (sectmask->section_name->name, (*scnhead)->name, 0) != 0)
-    /* The section name does not match.  */
-    return new_section;
-
-  /* If this is a section generated by the linker it doesn't contain
-     the regular information (i.e., input section data etc) and must
-     be handle special.  */
-  if ((*scnhead)->kind != scn_normal)
-    {
-      (*scnhead)->name = osectname;
-      (*scnhead)->segment_nr = segment_nr;
-
-      /* We have to count note section since they get their own
-	 program header entry.  */
-      if ((*scnhead)->type == SHT_NOTE)
-	++ld_state.nnotesections;
-
-      ld_state.allsections[ld_state.nallsections++] = (*scnhead);
-      return true;
-    }
-
-  /* Now we have to match the file names of the input files.  Some of
-     the sections here might not match.    */
-  runp = (*scnhead)->last->next;
-  prevp = (*scnhead)->last;
-  notused = NULL;
-
-  do
-    {
-      /* Base of the file name the section comes from.  */
-      const char *brfname = basename (runp->fileinfo->rfname);
-
-      /* If the section isn't used, the name doesn't match the positive
-	 inclusion list, or the name does match the negative inclusion
-	 list, ignore the section.  */
-      if (!runp->used
-	  || (sectmask->filemask != NULL
-	      && fnmatch (sectmask->filemask, brfname, 0) != 0)
-	  || (sectmask->excludemask != NULL
-	      && fnmatch (sectmask->excludemask, brfname, 0) == 0))
-	{
-	  /* This file does not match the file name masks.  */
-	  if (notused == NULL)
-	    notused = runp;
-
-	  prevp = runp;
-	  runp = runp->next;
-	  if (runp == notused)
-	    runp = NULL;
-	}
-      /* The section fulfills all requirements, add it to the output
-	 file with the correct section name etc.  */
-      else
-	{
-	  struct scninfo *found = runp;
-
-	  /* Remove this input section data buffer from the list.  */
-	  if (prevp != runp)
-	    runp = prevp->next = runp->next;
-	  else
-	    {
-	      free (*scnhead);
-	      *scnhead = NULL;
-	      runp = NULL;
-	    }
-
-	  /* Create a new section for the output file if the 'new_section'
-	     flag says so.  Otherwise append the buffer to the last
-	     section which we created in one of the last calls.  */
-	  if (new_section)
-	    {
-	      struct scnhead *newp;
-
-	      newp = (struct scnhead *) obstack_calloc (&ld_state.smem,
-							sizeof (*newp));
-	      newp->kind = scn_normal;
-	      newp->name = osectname;
-	      newp->type = SCNINFO_SHDR (found->shdr).sh_type;
-	      /* Executable or DSO do not have section groups.  Drop that
-		 information.  */
-	      newp->flags = SCNINFO_SHDR (found->shdr).sh_flags & ~SHF_GROUP;
-	      newp->segment_nr = segment_nr;
-	      newp->last = found->next = found;
-	      newp->used = true;
-	      newp->relsize = found->relsize;
-	      newp->entsize = SCNINFO_SHDR (found->shdr).sh_entsize;
-
-	      /* We have to count note section since they get their own
-		 program header entry.  */
-	      if (newp->type == SHT_NOTE)
-		++ld_state.nnotesections;
-
-	      ld_state.allsections[ld_state.nallsections++] = newp;
-	      new_section = false;
-	    }
-	  else
-	    {
-	      struct scnhead *queued;
-
-	      queued = ld_state.allsections[ld_state.nallsections - 1];
-
-	      found->next = queued->last->next;
-	      queued->last = queued->last->next = found;
-
-	      /* If the linker script forces us to add incompatible
-		 sections together do so.  But reflect this in the
-		 type and flags of the resulting file.  */
-	      if (queued->type != SCNINFO_SHDR (found->shdr).sh_type)
-		/* XXX Any better choice?  */
-		queued->type = SHT_PROGBITS;
-	      if (queued->flags != SCNINFO_SHDR (found->shdr).sh_flags)
-		/* Executable or DSO do not have section groups.  Drop that
-		   information.  */
-		queued->flags = ebl_sh_flags_combine (ld_state.ebl,
-						      queued->flags,
-						      SCNINFO_SHDR (found->shdr).sh_flags
-						      & ~SHF_GROUP);
-
-	      /* Accumulate the relocation section size.  */
-	      queued->relsize += found->relsize;
-	    }
-	}
-    }
-  while (runp != NULL);
-
-  return new_section;
-}
-
-
-static void
-sort_sections_lscript (void)
-{
-  struct scnhead *temp[ld_state.nallsections];
-
-  /* Make a copy of the section head pointer array.  */
-  memcpy (temp, ld_state.allsections,
-	  ld_state.nallsections * sizeof (temp[0]));
-  size_t nallsections = ld_state.nallsections;
-
-  /* Convert the output segment list in a single-linked list.  */
-  struct output_segment *segment = ld_state.output_segments->next;
-  ld_state.output_segments->next = NULL;
-  ld_state.output_segments = segment;
-
-  /* Put the sections in the correct order in the array in the state
-     structure.  This might involve merging of sections and also
-     renaming the containing section in the output file.  */
-  ld_state.nallsections = 0;
-  size_t segment_nr;
-  size_t last_writable = ~0ul;
-  for (segment_nr = 0; segment != NULL; segment = segment->next, ++segment_nr)
-    {
-      struct output_rule *orule;
-
-      for (orule = segment->output_rules; orule != NULL; orule = orule->next)
-	if (orule->tag == output_section)
-	  {
-	    struct input_rule *irule;
-	    bool new_section = true;
-
-	    for (irule = orule->val.section.input; irule != NULL;
-		 irule = irule->next)
-	      if (irule->tag == input_section)
-		{
-		  size_t cnt;
-
-		  for (cnt = 0; cnt < nallsections; ++cnt)
-		    if (temp[cnt] != NULL)
-		      new_section =
-			match_section (orule->val.section.name,
-				       irule->val.section, &temp[cnt],
-				       new_section, segment_nr);
-		}
-	  }
-
-      if ((segment->mode & PF_W) != 0)
-	last_writable = ld_state.nallsections - 1;
-    }
-
-  /* In case we have to create copy relocations or we have common
-     symbols, find the last writable segment and add one more data
-     block.  It will be a NOBITS block and take up no disk space.
-     This is why it is important to get the last block.  */
-  if (ld_state.ncopy > 0 || ld_state.common_syms !=  NULL)
-    {
-      if (last_writable == ~0ul)
-	error (EXIT_FAILURE, 0, "no writable segment");
-
-      if (ld_state.allsections[last_writable]->type != SHT_NOBITS)
-	{
-	  /* Make room in the ALLSECTIONS array for a new section.
-	     There is guaranteed room in the array.  We add the new
-	     entry after the last writable section.  */
-	  ++last_writable;
-	  memmove (&ld_state.allsections[last_writable + 1],
-		   &ld_state.allsections[last_writable],
-		   (ld_state.nallsections - last_writable)
-		   * sizeof (ld_state.allsections[0]));
-
-	  ld_state.allsections[last_writable] = (struct scnhead *)
-	    obstack_calloc (&ld_state.smem, sizeof (struct scnhead));
-
-	  /* Name for the new section.  */
-	  ld_state.allsections[last_writable]->name = ".bss";
-	  /* Type: NOBITS.  */
-	  ld_state.allsections[last_writable]->type = SHT_NOBITS;
-	  /* Same segment as the last writable section.  */
-	  ld_state.allsections[last_writable]->segment_nr
-	    = ld_state.allsections[last_writable - 1]->segment_nr;
-	}
-    }
-
-  /* Create common symbol data block.  */
-  if (ld_state.ncopy > 0)
-    {
-#if NATIVE_ELF
-      struct scninfo *si = (struct scninfo *)
-	obstack_calloc (&ld_state.smem, sizeof (*si) + sizeof (XElf_Shdr));
-      si->shdr = (XElf_Shdr *) (si + 1);
-#else
-      struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem,
-							      sizeof (*si));
-#endif
-
-      /* Get the information regarding the symbols with copy relocations.  */
-      compute_copy_reloc_offset (&SCNINFO_SHDR (si->shdr));
-
-      /* This section is needed.  */
-      si->used = true;
-      /* Remember for later the section data structure.  */
-      ld_state.copy_section = si;
-
-      if (likely (ld_state.allsections[last_writable]->last != NULL))
-	{
-	  si->next = ld_state.allsections[last_writable]->last->next;
-	  ld_state.allsections[last_writable]->last->next = si;
-	  ld_state.allsections[last_writable]->last = si;
-	}
-      else
-	ld_state.allsections[last_writable]->last = si->next = si;
-    }
-
-  /* Create common symbol data block.  */
-  if (ld_state.common_syms != NULL)
-    {
-#if NATIVE_ELF
-      struct scninfo *si = (struct scninfo *)
-	obstack_calloc (&ld_state.smem, sizeof (*si) + sizeof (XElf_Shdr));
-      si->shdr = (XElf_Shdr *) (si + 1);
-#else
-      struct scninfo *si = (struct scninfo *) obstack_calloc (&ld_state.smem,
-							      sizeof (*si));
-#endif
-
-      /* Get the information regarding the symbols with copy relocations.  */
-      compute_common_symbol_offset (&SCNINFO_SHDR (si->shdr));
-
-      /* This section is needed.  */
-      si->used = true;
-      /* Remember for later the section data structure.  */
-      ld_state.common_section = si;
-
-      if (likely (ld_state.allsections[last_writable]->last != NULL))
-	{
-	  si->next = ld_state.allsections[last_writable]->last->next;
-	  ld_state.allsections[last_writable]->last->next = si;
-	  ld_state.allsections[last_writable]->last = si;
-	}
-      else
-	ld_state.allsections[last_writable]->last = si->next = si;
-    }
-}
-
-
-/* Create the output sections now.  This requires knowledge about all
-   the sections we will need.  It may be necessary to sort sections in
-   the order they are supposed to appear in the executable.  The
-   sorting use many different kinds of information to optimize the
-   resulting binary.  Important is to respect segment boundaries and
-   the needed alignment.  The mode of the segments will be determined
-   afterwards automatically by the output routines.
-
-   The generic sorting routines work in one of two possible ways:
-
-   - if a linker script specifies the sections to be used in the
-     output and assigns them to a segment this information is used;
-
-   - otherwise the linker will order the sections based on permissions
-     and some special knowledge about section names.*/
-static void
-ld_generic_create_sections (struct ld_state *statep)
-{
-  struct scngroup *groups;
-  size_t cnt;
-
-  /* For relocatable object we don't have to bother sorting the
-     sections and we do want to preserve the relocation sections as
-     they appear in the input files.  */
-  if (ld_state.file_type != relocatable_file_type)
-    {
-      /* Collect all the relocation sections.  They are handled
-	 separately.  */
-      struct scninfo *list = NULL;
-      for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
-	if ((ld_state.allsections[cnt]->type == SHT_REL
-	     || ld_state.allsections[cnt]->type == SHT_RELA)
-	    /* The generated relocation sections are not of any
-	       interest here.  */
-	    && ld_state.allsections[cnt]->last != NULL)
-	  {
-	    if (list == NULL)
-	      list = ld_state.allsections[cnt]->last;
-	    else
-	      {
-		/* Merge the sections list.  */
-		struct scninfo *first = list->next;
-		list->next = ld_state.allsections[cnt]->last->next;
-		ld_state.allsections[cnt]->last->next = first;
-		list = ld_state.allsections[cnt]->last;
-	      }
-
-	    /* Remove the entry from the section list.  */
-	    ld_state.allsections[cnt] = NULL;
-	  }
-      ld_state.rellist = list;
-
-      if (ld_state.output_segments == NULL)
-	/* Sort using builtin rules.  */
-	sort_sections_generic ();
-      else
-	sort_sections_lscript ();
-    }
-
-  /* Now iterate over the input sections and create the sections in the
-     order they are required in the output file.  */
-  for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
-    {
-      struct scnhead *head = ld_state.allsections[cnt];
-      Elf_Scn *scn;
-      XElf_Shdr_vardef (shdr);
-
-      /* Don't handle unused sections.  */
-      if (!head->used)
-	continue;
-
-      /* We first have to create the section group if necessary.
-	 Section group sections must come (in section index order)
-	 before any of the section contained.  This all is necessary
-	 only for relocatable object as other object types are not
-	 allowed to contain section groups.  */
-      if (ld_state.file_type == relocatable_file_type
-	  && unlikely (head->flags & SHF_GROUP))
-	{
-	  /* There is at least one section which is contained in a
-	     section group in the input file.  This means we must
-	     create a section group here as well.  The only problem is
-	     that not all input files have to have to same kind of
-	     partitioning of the sections.  I.e., sections A and B in
-	     one input file and sections B and C in another input file
-	     can be in one group.  That will result in a group
-	     containing the sections A, B, and C in the output
-	     file.  */
-	  struct scninfo *runp;
-	  Elf32_Word here_groupidx = 0;
-	  struct scngroup *here_group;
-	  struct member *newp;
-
-	  /* First check whether any section is already in a group.
-	     In this case we have to add this output section, too.  */
-	  runp = head->last;
-	  do
-	    {
-	      assert (runp->grpid != 0);
-
-	      here_groupidx = runp->fileinfo->scninfo[runp->grpid].outscnndx;
-	      if (here_groupidx != 0)
-		break;
-	    }
-	  while ((runp = runp->next) != head->last);
-
-	  if (here_groupidx == 0)
-	    {
-	      /* We need a new section group section.  */
-	      scn = elf_newscn (ld_state.outelf);
-	      xelf_getshdr (scn, shdr);
-	      if (shdr == NULL)
-		error (EXIT_FAILURE, 0,
-		       gettext ("cannot create section for output file: %s"),
-		       elf_errmsg (-1));
-
-	      here_group = (struct scngroup *) xmalloc (sizeof (*here_group));
-	      here_group->outscnidx = here_groupidx = elf_ndxscn (scn);
-	      here_group->nscns = 0;
-	      here_group->member = NULL;
-	      here_group->next = ld_state.groups;
-	      /* Pick a name for the section.  To keep it meaningful
-		 we use a name used in the input files.  If the
-		 section group in the output file should contain
-		 section which were in section groups of different
-		 names in the input files this is the users
-		 problem.  */
-	      here_group->nameent
-		= ebl_strtabadd (ld_state.shstrtab,
-				 elf_strptr (runp->fileinfo->elf,
-					     runp->fileinfo->shstrndx,
-					     SCNINFO_SHDR (runp->shdr).sh_name),
-				 0);
-	      /* Signature symbol.  */
-	      here_group->symbol
-		= runp->fileinfo->scninfo[runp->grpid].symbols;
-
-	      ld_state.groups = here_group;
-	    }
-	  else
-	    {
-	      /* Search for the group with this index.  */
-	      here_group = ld_state.groups;
-	      while (here_group->outscnidx != here_groupidx)
-		here_group = here_group->next;
-	    }
-
-	  /* Add the new output section.  */
-	  newp = (struct member *) alloca (sizeof (*newp));
-	  newp->scn = head;
-#ifndef NDT_NEEDED
-	  newp->next = NULL;
-#endif
-	  CSNGL_LIST_ADD_REAR (here_group->member, newp);
-	  ++here_group->nscns;
-
-	  /* Store the section group index in all input files.  */
-	  runp = head->last;
-	  do
-	    {
-	      assert (runp->grpid != 0);
-
-	      if (runp->fileinfo->scninfo[runp->grpid].outscnndx == 0)
-		runp->fileinfo->scninfo[runp->grpid].outscnndx = here_groupidx;
-	      else
-		assert (runp->fileinfo->scninfo[runp->grpid].outscnndx
-			== here_groupidx);
-	    }
-	  while ((runp = runp->next) != head->last);
-	}
-
-      /* We'll use this section so get it's name in the section header
-	 string table.  */
-      if (head->kind == scn_normal)
-	head->nameent = ebl_strtabadd (ld_state.shstrtab, head->name, 0);
-
-      /* Create a new section in the output file and add all data
-	 from all the sections we read.  */
-      scn = elf_newscn (ld_state.outelf);
-      head->scnidx = elf_ndxscn (scn);
-      xelf_getshdr (scn, shdr);
-      if (shdr == NULL)
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot create section for output file: %s"),
-	       elf_errmsg (-1));
-
-      assert (head->type != SHT_NULL);
-      assert (head->type != SHT_SYMTAB);
-      assert (head->type != SHT_DYNSYM || head->kind != scn_normal);
-      assert (head->type != SHT_STRTAB || head->kind != scn_normal);
-      assert (head->type != SHT_GROUP);
-      shdr->sh_type = head->type;
-      shdr->sh_flags = head->flags;
-      shdr->sh_addralign = head->align;
-      shdr->sh_entsize = head->entsize;
-      assert (shdr->sh_entsize != 0 || (shdr->sh_flags & SHF_MERGE) == 0);
-      (void) xelf_update_shdr (scn, shdr);
-
-      /* We have to know the section index of the dynamic symbol table
-	 right away.  */
-      if (head->kind == scn_dot_dynsym)
-	ld_state.dynsymscnidx = elf_ndxscn (scn);
-    }
-
-  /* Actually create the section group sections.  */
-  groups = ld_state.groups;
-  while (groups != NULL)
-    {
-      Elf_Scn *scn;
-      Elf_Data *data;
-      Elf32_Word *grpdata;
-      struct member *runp;
-
-      scn = elf_getscn (ld_state.outelf, groups->outscnidx);
-      assert (scn != NULL);
-
-      data = elf_newdata (scn);
-      if (data == NULL)
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot create section for output file: %s"),
-	       elf_errmsg (-1));
-
-      data->d_size = (groups->nscns + 1) * sizeof (Elf32_Word);
-      data->d_buf = grpdata = (Elf32_Word *) xmalloc (data->d_size);
-      data->d_type = ELF_T_WORD;
-      data->d_version = EV_CURRENT;
-      data->d_off = 0;
-      /* XXX What better to use?  */
-      data->d_align = sizeof (Elf32_Word);
-
-      /* The first word in the section is the flag word.  */
-      /* XXX Set COMDATA flag is necessary.  */
-      grpdata[0] = 0;
-
-      runp = groups->member->next;
-      cnt = 1;
-      do
-	/* Fill in the index of the section.  */
-	grpdata[cnt++] = runp->scn->scnidx;
-      while ((runp = runp->next) != groups->member->next);
-
-      groups = groups->next;
-    }
-}
-
-
-static bool
-reduce_symbol_p (XElf_Sym *sym, struct Ebl_Strent *strent)
-{
-  const char *str;
-  const char *version;
-  struct id_list search;
-  struct id_list *verp;
-  bool result = ld_state.default_bind_local;
-
-  if (XELF_ST_BIND (sym->st_info) == STB_LOCAL || sym->st_shndx == SHN_UNDEF)
-    /* We don't have to do anything to local symbols here.  */
-    /* XXX Any section value in [SHN_LORESERVER,SHN_XINDEX) need
-       special treatment?  */
-    return false;
-
-  /* XXX Handle other symbol bindings.  */
-  assert (XELF_ST_BIND (sym->st_info) == STB_GLOBAL
-	  || XELF_ST_BIND (sym->st_info) == STB_WEAK);
-
-  str = ebl_string (strent);
-  version = strchr (str, VER_CHR);
-  if (version != NULL)
-    {
-      search.id = strndupa (str, version - str);
-      if (*++version == VER_CHR)
-	/* Skip the second '@' signaling a default definition.  */
-	++version;
-    }
-  else
-    {
-      search.id = str;
-      version = "";
-    }
-
-  verp = ld_version_str_tab_find (&ld_state.version_str_tab,
-				  elf_hash (search.id), &search);
-  while (verp != NULL)
-    {
-      /* We have this symbol in the version hash table.  Now match the
-	 version name.  */
-      if (strcmp (verp->u.s.versionname, version) == 0)
-	/* Match!  */
-	return verp->u.s.local;
-
-      verp = verp->next;
-    }
-
-  /* XXX Add test for wildcard version symbols.  */
-
-  return result;
-}
-
-
-static XElf_Addr
-eval_expression (struct expression *expr, XElf_Addr addr)
-{
-  XElf_Addr val = ~((XElf_Addr) 0);
-
-  switch (expr->tag)
-    {
-    case exp_num:
-      val = expr->val.num;
-      break;
-
-    case exp_sizeof_headers:
-      {
-	/* The 'elf_update' call determine the offset of the first
-	   section.  The the size of the header.  */
-	XElf_Shdr_vardef (shdr);
-
-	xelf_getshdr (elf_getscn (ld_state.outelf, 1), shdr);
-	assert (shdr != NULL);
-
-	val = shdr->sh_offset;
-      }
-      break;
-
-    case exp_pagesize:
-      val = ld_state.pagesize;
-      break;
-
-    case exp_id:
-      /* We are here computing only address expressions.  It seems not
-	 to be necessary to handle any variable but ".".  Let's avoid
-	 the complication.  If it turns up to be needed we can add
-	 it.  */
-      if (strcmp (expr->val.str, ".") != 0)
-	error (EXIT_FAILURE, 0, gettext ("\
-address computation expression contains variable '%s'"),
-	       expr->val.str);
-
-      val = addr;
-      break;
-
-    case exp_mult:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     * eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_div:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     / eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_mod:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     % eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_plus:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     + eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_minus:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     - eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_and:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     & eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_or:
-      val = (eval_expression (expr->val.binary.left, addr)
-	     | eval_expression (expr->val.binary.right, addr));
-      break;
-
-    case exp_align:
-      val = eval_expression (expr->val.child, addr);
-      if ((val & (val - 1)) != 0)
-	error (EXIT_FAILURE, 0, gettext ("argument '%" PRIuMAX "' of ALIGN in address computation expression is no power of two"),
-	       (uintmax_t) val);
-      val = (addr + val - 1) & ~(val - 1);
-      break;
-    }
-
-  return val;
-}
-
-
-/* Find a good as possible size for the hash table so that all the
-   non-zero entries in HASHCODES don't collide too much and the table
-   isn't too large.  There is no exact formular for this so we use a
-   heuristic.  Depending on the optimization level the search is
-   longer or shorter.  */
-static size_t
-optimal_bucket_size (Elf32_Word *hashcodes, size_t maxcnt, int optlevel)
-{
-  size_t minsize;
-  size_t maxsize;
-  size_t bestsize;
-  uint64_t bestcost;
-  size_t size;
-  uint32_t *counts;
-  uint32_t *lengths;
-
-  if (maxcnt == 0)
-    return 0;
-
-  /* When we are not optimizing we run only very few tests.  */
-  if (optlevel <= 0)
-    {
-      minsize = maxcnt;
-      maxsize = maxcnt + 10000 / maxcnt;
-    }
-  else
-    {
-      /* Does not make much sense to start with a smaller table than
-	 one which has at least four collisions.  */
-      minsize = MAX (1, maxcnt / 4);
-      /* We look for a best fit in the range of up to eigth times the
-	 number of elements.  */
-      maxsize = 2 * maxcnt + (6 * MIN (optlevel, 100) * maxcnt) / 100;
-    }
-  bestsize = maxcnt;
-  bestcost = UINT_MAX;
-
-  /* Array for counting the collisions and chain lengths.  */
-  counts = (uint32_t *) xmalloc ((maxcnt + 1 + maxsize) * sizeof (uint32_t));
-  lengths = &counts[maxcnt + 1];
-
-  for (size = minsize; size <= maxsize; ++size)
-    {
-      size_t inner;
-      uint64_t cost;
-      uint32_t maxlength;
-      uint64_t success;
-      uint32_t acc;
-      double factor;
-
-      memset (lengths, '\0', size * sizeof (uint32_t));
-      memset (counts, '\0', (maxcnt + 1) * sizeof (uint32_t));
-
-      /* Determine how often each hash bucket is used.  */
-      assert (hashcodes[0] == 0);
-      for (inner = 1; inner < maxcnt; ++inner)
-	++lengths[hashcodes[inner] % size];
-
-      /* Determine the lengths.  */
-      maxlength = 0;
-      for (inner = 0; inner < size; ++inner)
-	{
-	  ++counts[lengths[inner]];
-
-	  if (lengths[inner] > maxlength)
-	    maxlength = lengths[inner];
-	}
-
-      /* Determine successful lookup length.  */
-      acc = 0;
-      success = 0;
-      for (inner = 0; inner <= maxlength; ++inner)
-	{
-	  acc += inner;
-	  success += counts[inner] * acc;
-	}
-
-      /* We can compute two factors now: the average length of a
-	 positive search and the average length of a negative search.
-	 We count the number of comparisons which have to look at the
-	 names themselves.  Recognizing that the chain ended is not
-	 accounted for since it's almost for free.
-
-	 Which lookup is more important depends on the kind of DSO.
-	 If it is a system DSO like libc it is expected that most
-	 lookups succeed.  Otherwise most lookups fail.  */
-      if (ld_state.is_system_library)
-	factor = (1.0 * (double) success / (double) maxcnt
-		  + 0.3 * (double) maxcnt / (double) size);
-      else
-	factor = (0.3 * (double) success / (double) maxcnt
-		  + 1.0 * (double) maxcnt / (double) size);
-
-      /* Combine the lookup cost factor.  The 1/16th addend adds
-	 penalties for too large table sizes.  */
-      cost = (2 + maxcnt + size) * (factor + 1.0 / 16.0);
-
-#if 0
-      printf ("maxcnt = %d, size = %d, cost = %Ld, success = %g, fail = %g, factor = %g\n",
-	      maxcnt, size, cost, (double) success / (double) maxcnt, (double) maxcnt / (double) size, factor);
-#endif
-
-      /* Compare with current best results.  */
-      if (cost < bestcost)
-	{
-	  bestcost = cost;
-	  bestsize = size;
-	}
-    }
-
-  free (counts);
-
-  return bestsize;
-}
-
-
-static void
-optimal_gnu_hash_size (Elf32_Word *hashcodes, size_t maxcnt, int optlevel,
-		       size_t *bitmask_nwords, size_t *shift, size_t *nbuckets)
-{
-  // XXX Implement something real
-  *bitmask_nwords = 256;
-  *shift = 6;
-  *nbuckets = 3 * maxcnt / 2;
-}
-
-
-static XElf_Addr
-find_entry_point (void)
-{
-  XElf_Addr result;
-
-  if (ld_state.entry != NULL)
-    {
-      struct symbol search = { .name = ld_state.entry };
-      struct symbol *syment;
-
-      syment = ld_symbol_tab_find (&ld_state.symbol_tab,
-				   elf_hash (ld_state.entry), &search);
-      if (syment != NULL && syment->defined)
-	{
-	  /* We found the symbol.  */
-	  Elf_Data *data = elf_getdata (elf_getscn (ld_state.outelf,
-						    ld_state.symscnidx), NULL);
-
-	  XElf_Sym_vardef (sym);
-
-	  sym = NULL;
-	  if (data != NULL)
-	    xelf_getsym (data, ld_state.dblindirect[syment->outsymidx], sym);
-
-	  if (sym == NULL && ld_state.need_dynsym && syment->outdynsymidx != 0)
-	    {
-	      /* Use the dynamic symbol table if available.  */
-	      data = elf_getdata (elf_getscn (ld_state.outelf,
-					      ld_state.dynsymscnidx), NULL);
-
-	      sym = NULL;
-	      if (data != NULL)
-		xelf_getsym (data, syment->outdynsymidx, sym);
-	    }
-
-	  if (sym != NULL)
-	    return sym->st_value;
-
-	  /* XXX What to do if the output has no non-dynamic symbol
-	     table and the dynamic symbol table does not contain the
-	     symbol?  */
-	  assert (ld_state.need_symtab);
-	  assert (ld_state.symscnidx != 0);
-	}
-    }
-
-  /* We couldn't find the symbol or none was given.  Use the first
-     address of the ".text" section then.  */
-
-
-  result = 0;
-
-  /* In DSOs this is no fatal error.  They usually have no entry
-     points.  In this case we set the entry point to zero, which makes
-     sure it will always fail.  */
-  if (ld_state.file_type == executable_file_type)
-    {
-      if (ld_state.entry != NULL)
-	error (0, 0, gettext ("\
-cannot find entry symbol '%s': defaulting to %#0*" PRIx64),
-	       ld_state.entry,
-	       xelf_getclass (ld_state.outelf) == ELFCLASS32 ? 10 : 18,
-	       (uint64_t) result);
-      else
-	error (0, 0, gettext ("\
-no entry symbol specified: defaulting to %#0*" PRIx64),
-	       xelf_getclass (ld_state.outelf) == ELFCLASS32 ? 10 : 18,
-	       (uint64_t) result);
-    }
-
-  return result;
-}
-
-
-static void
-fillin_special_symbol (struct symbol *symst, size_t scnidx, size_t nsym,
-		       Elf_Data *symdata, struct Ebl_Strtab *strtab)
-{
-  assert (ld_state.file_type != relocatable_file_type);
-
-  XElf_Sym_vardef (sym);
-  xelf_getsym_ptr (symdata, nsym, sym);
-
-  /* The name offset will be filled in later.  */
-  sym->st_name = 0;
-  /* Traditionally: globally visible.  */
-  sym->st_info = XELF_ST_INFO (symst->local ? STB_LOCAL : STB_GLOBAL,
-			       symst->type);
-  sym->st_other = symst->hidden ? STV_HIDDEN : STV_DEFAULT;
-  /* Reference to the GOT or dynamic section.  Since the GOT and
-     dynamic section are only created for executables and DSOs it
-     cannot be that the section index is too large.  */
-  assert (scnidx != 0);
-  assert (scnidx < SHN_LORESERVE || scnidx == SHN_ABS);
-  sym->st_shndx = scnidx;
-  /* We want the beginning of the section.  */
-  sym->st_value = 0;
-  // XXX What size?
-  sym->st_size = 0;
-
-  /* Determine the size of the section.  */
-  if (scnidx != SHN_ABS)
-    {
-      Elf_Data *data = elf_getdata (elf_getscn (ld_state.outelf, scnidx),
-				    NULL);
-      assert (data != NULL);
-      sym->st_size = data->d_size;
-      /* Make sure there is no second data block.  */
-      assert (elf_getdata (elf_getscn (ld_state.outelf, scnidx), data)
-	      == NULL);
-    }
-
-  /* Insert symbol into the symbol table.  Note that we do not have to
-     use xelf_update_symshdx.  */
-  (void) xelf_update_sym (symdata, nsym, sym);
-
-  /* Cross-references.  */
-  ndxtosym[nsym] = symst;
-  symst->outsymidx = nsym;
-
-  /* Add the name to the string table.  */
-  symstrent[nsym] = ebl_strtabadd (strtab, symst->name, 0);
-}
-
-
-static void
-new_dynamic_entry (Elf_Data *data, int idx, XElf_Sxword tag, XElf_Addr val)
-{
-  XElf_Dyn_vardef (dyn);
-  xelf_getdyn_ptr (data, idx, dyn);
-  dyn->d_tag = tag;
-  dyn->d_un.d_ptr = val;
-  (void) xelf_update_dyn (data, idx, dyn);
-}
-
-
-static void
-allocate_version_names (struct usedfiles *runp, struct Ebl_Strtab *dynstrtab)
-{
-  /* If this DSO has no versions skip it.  */
-  if (runp->status != opened || runp->verdefdata == NULL)
-    return;
-
-  /* Add the object name.  */
-  int offset = 0;
-  while (1)
-    {
-      XElf_Verdef_vardef (def);
-      XElf_Verdaux_vardef (aux);
-
-      /* Get data at the next offset.  */
-      xelf_getverdef (runp->verdefdata, offset, def);
-      assert (def != NULL);
-      xelf_getverdaux (runp->verdefdata, offset + def->vd_aux, aux);
-      assert (aux != NULL);
-
-      assert (def->vd_ndx <= runp->nverdef);
-      if (def->vd_ndx == 1 || runp->verdefused[def->vd_ndx] != 0)
-	{
-	  runp->verdefent[def->vd_ndx]
-	    = ebl_strtabadd (dynstrtab, elf_strptr (runp->elf,
-						    runp->dynsymstridx,
-						    aux->vda_name), 0);
-
-	  if (def->vd_ndx > 1)
-	    runp->verdefused[def->vd_ndx] = ld_state.nextveridx++;
-	}
-
-      if (def->vd_next == 0)
-	/* That were all versions.  */
-	break;
-
-      offset += def->vd_next;
-    }
-}
-
-
-static XElf_Off
-create_verneed_data (XElf_Off offset, Elf_Data *verneeddata,
-		     struct usedfiles *runp, int *ntotal)
-{
-  size_t verneed_size = xelf_fsize (ld_state.outelf, ELF_T_VNEED, 1);
-  size_t vernaux_size = xelf_fsize (ld_state.outelf, ELF_T_VNAUX, 1);
-  int need_offset;
-  bool filled = false;
-  GElf_Verneed verneed;
-  GElf_Vernaux vernaux;
-  int ndef = 0;
-  size_t cnt;
-
-  /* If this DSO has no versions skip it.  */
-  if (runp->nverdefused == 0)
-    return offset;
-
-  /* We fill in the Verneed record last.  Remember the offset.  */
-  need_offset = offset;
-  offset += verneed_size;
-
-  for (cnt = 2; cnt <= runp->nverdef; ++cnt)
-    if (runp->verdefused[cnt] != 0)
-      {
-	assert (runp->verdefent[cnt] != NULL);
-
-	if (filled)
-	  {
-	    vernaux.vna_next = vernaux_size;
-	    (void) gelf_update_vernaux (verneeddata, offset, &vernaux);
-	    offset += vernaux_size;
-	  }
-
-	vernaux.vna_hash = elf_hash (ebl_string (runp->verdefent[cnt]));
-	vernaux.vna_flags = 0;
-	vernaux.vna_other = runp->verdefused[cnt];
-	vernaux.vna_name = ebl_strtaboffset (runp->verdefent[cnt]);
-	filled = true;
-	++ndef;
-      }
-
-  assert (filled);
-  vernaux.vna_next = 0;
-  (void) gelf_update_vernaux (verneeddata, offset, &vernaux);
-  offset += vernaux_size;
-
-  verneed.vn_version = VER_NEED_CURRENT;
-  verneed.vn_cnt = ndef;
-  verneed.vn_file = ebl_strtaboffset (runp->verdefent[1]);
-  /* The first auxiliary entry is always found directly
-     after the verneed entry.  */
-  verneed.vn_aux = verneed_size;
-  verneed.vn_next = --*ntotal > 0 ? offset - need_offset : 0;
-  (void) gelf_update_verneed (verneeddata, need_offset, &verneed);
-
-  return offset;
-}
-
-
-/* Callback for qsort to sort dynamic string table.  */
-static Elf32_Word *global_hashcodes;
-static size_t global_nbuckets;
-static int
-sortfct_hashval (const void *p1, const void *p2)
-{
-  size_t idx1 = *(size_t *) p1;
-  size_t idx2 = *(size_t *) p2;
-
-  int def1 = ndxtosym[idx1]->defined && !ndxtosym[idx1]->in_dso;
-  int def2 = ndxtosym[idx2]->defined && !ndxtosym[idx2]->in_dso;
-
-  if (! def1 && def2)
-    return -1;
-  if (def1 && !def2)
-    return 1;
-  if (! def1)
-    return 0;
-
-  Elf32_Word hval1 = (global_hashcodes[ndxtosym[idx1]->outdynsymidx]
-		      % global_nbuckets);
-  Elf32_Word hval2 = (global_hashcodes[ndxtosym[idx2]->outdynsymidx]
-		      % global_nbuckets);
-
-  if (hval1 < hval2)
-    return -1;
-  if (hval1 > hval2)
-    return 1;
-  return 0;
-}
-
-
-/* Sort the dynamic symbol table.  The GNU hash table lookup assumes
-   that all symbols with the same hash value module the bucket table
-   size follow one another.  This avoids the extra hash chain table.
-   There is no need (and no way) to perform this operation if we do
-   not use the new hash table format.  */
-static void
-create_gnu_hash (size_t nsym_local, size_t nsym, size_t nsym_dyn,
-		 Elf32_Word *gnuhashcodes)
-{
-  size_t gnu_bitmask_nwords = 0;
-  size_t gnu_shift = 0;
-  size_t gnu_nbuckets = 0;
-  Elf32_Word *gnu_bitmask = NULL;
-  Elf32_Word *gnu_buckets = NULL;
-  Elf32_Word *gnu_chain = NULL;
-  XElf_Shdr_vardef (shdr);
-
-  /* Determine the "optimal" bucket size.  */
-  optimal_gnu_hash_size (gnuhashcodes, nsym_dyn, ld_state.optlevel,
-			 &gnu_bitmask_nwords, &gnu_shift, &gnu_nbuckets);
-
-  /* Create the .gnu.hash section data structures.  */
-  Elf_Scn *hashscn = elf_getscn (ld_state.outelf, ld_state.gnuhashscnidx);
-  xelf_getshdr (hashscn, shdr);
-  Elf_Data *hashdata = elf_newdata (hashscn);
-  if (shdr == NULL || hashdata == NULL)
-    error (EXIT_FAILURE, 0, gettext ("\
-cannot create GNU hash table section for output file: %s"),
-	   elf_errmsg (-1));
-
-  shdr->sh_link = ld_state.dynsymscnidx;
-  (void) xelf_update_shdr (hashscn, shdr);
-
-  hashdata->d_size = (xelf_fsize (ld_state.outelf, ELF_T_ADDR,
-				  gnu_bitmask_nwords)
-		      + (4 + gnu_nbuckets + nsym_dyn) * sizeof (Elf32_Word));
-  hashdata->d_buf = xcalloc (1, hashdata->d_size);
-  hashdata->d_align = sizeof (Elf32_Word);
-  hashdata->d_type = ELF_T_WORD;
-  hashdata->d_off = 0;
-
-  ((Elf32_Word *) hashdata->d_buf)[0] = gnu_nbuckets;
-  ((Elf32_Word *) hashdata->d_buf)[2] = gnu_bitmask_nwords;
-  ((Elf32_Word *) hashdata->d_buf)[3] = gnu_shift;
-  gnu_bitmask = &((Elf32_Word *) hashdata->d_buf)[4];
-  gnu_buckets = &gnu_bitmask[xelf_fsize (ld_state.outelf, ELF_T_ADDR,
-					 gnu_bitmask_nwords)
-			     / sizeof (*gnu_buckets)];
-  gnu_chain = &gnu_buckets[gnu_nbuckets];
-#ifndef NDEBUG
-  void *endp = &gnu_chain[nsym_dyn];
-#endif
-  assert (endp == (void *) ((char *) hashdata->d_buf + hashdata->d_size));
-
-
-  size_t *remap = xmalloc (nsym_dyn * sizeof (size_t));
-#ifndef NDEBUG
-  size_t nsym_dyn_cnt = 1;
-#endif
-  for (size_t cnt = nsym_local; cnt < nsym; ++cnt)
-    if (symstrent[cnt] != NULL)
-      {
-	assert (ndxtosym[cnt]->outdynsymidx > 0);
-	assert (ndxtosym[cnt]->outdynsymidx < nsym_dyn);
-	remap[ndxtosym[cnt]->outdynsymidx] = cnt;
-#ifndef NDEBUG
-	++nsym_dyn_cnt;
-#endif
-      }
-  assert (nsym_dyn_cnt == nsym_dyn);
-
-  // XXX Until we can rely on qsort_r use global variables.
-  global_hashcodes = gnuhashcodes;
-  global_nbuckets = gnu_nbuckets;
-  qsort (remap + 1, nsym_dyn - 1, sizeof (size_t), sortfct_hashval);
-
-  bool bm32 = (xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1)
-	       ==  sizeof (Elf32_Word));
-
-  size_t first_defined = 0;
-  Elf64_Word bitmask_idxbits = gnu_bitmask_nwords - 1;
-  Elf32_Word last_bucket = 0;
-  for (size_t cnt = 1; cnt < nsym_dyn; ++cnt)
-    {
-      if (first_defined == 0)
-	{
-	  if (! ndxtosym[remap[cnt]]->defined
-	      || ndxtosym[remap[cnt]]->in_dso)
-	    goto next;
-
-	  ((Elf32_Word *) hashdata->d_buf)[1] = first_defined = cnt;
-	}
-
-      Elf32_Word hval = gnuhashcodes[ndxtosym[remap[cnt]]->outdynsymidx];
-
-      if (bm32)
-	{
-	  Elf32_Word *bsw = &gnu_bitmask[(hval / 32) & bitmask_idxbits];
-	  assert ((void *) gnu_bitmask <= (void *) bsw);
-	  assert ((void *) bsw < (void *) gnu_buckets);
-	  *bsw |= 1 << (hval & 31);
-	  *bsw |= 1 << ((hval >> gnu_shift) & 31);
-	}
-      else
-	{
-	  Elf64_Word *bsw = &((Elf64_Word *) gnu_bitmask)[(hval / 64)
-							  & bitmask_idxbits];
-	  assert ((void *) gnu_bitmask <= (void *) bsw);
-	  assert ((void *) bsw < (void *) gnu_buckets);
-	  *bsw |= 1 << (hval & 63);
-	  *bsw |= 1 << ((hval >> gnu_shift) & 63);
-	}
-
-      size_t this_bucket = hval % gnu_nbuckets;
-      if (cnt == first_defined || this_bucket != last_bucket)
-	{
-	  if (cnt != first_defined)
-	    {
-	      /* Terminate the previous chain.  */
-	      assert ((void *) &gnu_chain[cnt - first_defined - 1] < endp);
-	      gnu_chain[cnt - first_defined - 1] |= 1;
-	    }
-
-	  assert (this_bucket < gnu_nbuckets);
-	  gnu_buckets[this_bucket] = cnt;
-	  last_bucket = this_bucket;
-	}
-
-      assert (cnt >= first_defined);
-      assert (cnt - first_defined < nsym_dyn);
-      gnu_chain[cnt - first_defined] = hval & ~1u;
-
-    next:
-      ndxtosym[remap[cnt]]->outdynsymidx = cnt;
-    }
-
-  /* Terminate the last chain.  */
-  if (first_defined != 0)
-    {
-      assert (nsym_dyn > first_defined);
-      assert (nsym_dyn - first_defined - 1 < nsym_dyn);
-      gnu_chain[nsym_dyn - first_defined - 1] |= 1;
-
-      hashdata->d_size -= first_defined * sizeof (Elf32_Word);
-    }
-  else
-    /* We do not need any hash table.  */
-    // XXX
-    do { } while (0);
-
-  free (remap);
-}
-
-
-/* Create the SysV-style hash table.  */
-static void
-create_hash (size_t nsym_local, size_t nsym, size_t nsym_dyn,
-	     Elf32_Word *hashcodes)
-{
-  size_t nbucket = 0;
-  Elf32_Word *bucket = NULL;
-  Elf32_Word *chain = NULL;
-  XElf_Shdr_vardef (shdr);
-
-  /* Determine the "optimal" bucket size.  If we also generate the
-     new-style hash function there is no need to waste effort and
-     space on the old one which should not be used.  Make it as small
-     as possible.  */
-  if (GENERATE_GNU_HASH)
-    nbucket = 1;
-  else
-    nbucket = optimal_bucket_size (hashcodes, nsym_dyn, ld_state.optlevel);
-  /* Create the .hash section data structures.  */
-  Elf_Scn *hashscn = elf_getscn (ld_state.outelf, ld_state.hashscnidx);
-  xelf_getshdr (hashscn, shdr);
-  Elf_Data *hashdata = elf_newdata (hashscn);
-  if (shdr == NULL || hashdata == NULL)
-    error (EXIT_FAILURE, 0, gettext ("\
-cannot create hash table section for output file: %s"),
-	   elf_errmsg (-1));
-
-  shdr->sh_link = ld_state.dynsymscnidx;
-  (void) xelf_update_shdr (hashscn, shdr);
-
-  hashdata->d_size = (2 + nsym_dyn + nbucket) * sizeof (Elf32_Word);
-  hashdata->d_buf = xcalloc (1, hashdata->d_size);
-  hashdata->d_align = sizeof (Elf32_Word);
-  hashdata->d_type = ELF_T_WORD;
-  hashdata->d_off = 0;
-
-  ((Elf32_Word *) hashdata->d_buf)[0] = nbucket;
-  ((Elf32_Word *) hashdata->d_buf)[1] = nsym_dyn;
-  bucket = &((Elf32_Word *) hashdata->d_buf)[2];
-  chain = &((Elf32_Word *) hashdata->d_buf)[2 + nbucket];
-
-  for (size_t cnt = nsym_local; cnt < nsym; ++cnt)
-    if (symstrent[cnt] != NULL)
-      {
-	size_t dynidx = ndxtosym[cnt]->outdynsymidx;
-	size_t hashidx = hashcodes[dynidx] % nbucket;
-	if (bucket[hashidx] == 0)
-	  bucket[hashidx] = dynidx;
-	else
-	  {
-	    hashidx = bucket[hashidx];
-	    while (chain[hashidx] != 0)
-	      hashidx = chain[hashidx];
-
-	    chain[hashidx] = dynidx;
-	  }
-      }
-}
-
-
-static void
-create_build_id_section (Elf_Scn *scn)
-{
-  /* We know how large the section will be so we can create it now.  */
-  Elf_Data *d = elf_newdata (scn);
-  if (d == NULL)
-    error (EXIT_FAILURE, 0, gettext ("cannot create build ID section: %s"),
-	   elf_errmsg (-1));
-
-  d->d_type = ELF_T_BYTE;
-  d->d_version = EV_CURRENT;
-
-  /* The note section header.  */
-  assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
-  d->d_size = sizeof (GElf_Nhdr);
-  /* The string is four bytes long.  */
-  d->d_size += sizeof (ELF_NOTE_GNU);
-  assert (d->d_size % 4 == 0);
-
-  if (strcmp (ld_state.build_id, "md5") == 0
-      || strcmp (ld_state.build_id, "uuid") == 0)
-    d->d_size += 16;
-  else if (strcmp (ld_state.build_id, "sha1") == 0)
-    d->d_size += 20;
-  else
-    {
-      assert (ld_state.build_id[0] == '0' && ld_state.build_id[1] == 'x');
-      /* Use an upper limit of the possible number of bytes generated
-	 from the string.  */
-      d->d_size += strlen (ld_state.build_id) / 2;
-    }
-
-  d->d_buf = xcalloc (d->d_size, 1);
-  d->d_off = 0;
-  d->d_align = 0;
-}
-
-
-static void
-compute_hash_sum (void (*hashfct) (const void *, size_t, void *), void *ctx)
-{
-  /* The call cannot fail.  */
-  size_t shstrndx;
-  (void) elf_getshdrstrndx (ld_state.outelf, &shstrndx);
-
-  const char *ident = elf_getident (ld_state.outelf, NULL);
-  bool same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
-			   && __BYTE_ORDER == __LITTLE_ENDIAN)
-			  || (ident[EI_DATA] == ELFDATA2MSB
-			      && __BYTE_ORDER == __BIG_ENDIAN));
-
-  /* Iterate over all sections to find those which are not strippable.  */
-  Elf_Scn *scn = NULL;
-  while ((scn = elf_nextscn (ld_state.outelf, scn)) != NULL)
-    {
-      /* Get the section header.  */
-      GElf_Shdr shdr_mem;
-      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-      assert (shdr != NULL);
-
-      if (SECTION_STRIP_P (shdr, elf_strptr (ld_state.outelf, shstrndx,
-					     shdr->sh_name), true))
-	/* The section can be stripped.  Don't use it.  */
-	continue;
-
-      /* Do not look at NOBITS sections.  */
-      if (shdr->sh_type == SHT_NOBITS)
-	continue;
-
-      /* Iterate through the list of data blocks.  */
-      Elf_Data *data = NULL;
-      while ((data = INTUSE(elf_getdata) (scn, data)) != NULL)
-	/* If the file byte order is the same as the host byte order
-	   process the buffer directly.  If the data is just a stream
-	   of bytes which the library will not convert we can use it
-	   as well.  */
-	if (likely (same_byte_order) || data->d_type == ELF_T_BYTE)
-	  hashfct (data->d_buf, data->d_size, ctx);
-	else
-	  {
-	    /* Convert the data to file byte order.  */
-	    if (gelf_xlatetof (ld_state.outelf, data, data, ident[EI_DATA])
-		== NULL)
-	      error (EXIT_FAILURE, 0, gettext ("\
-cannot convert section data to file format: %s"),
-		     elf_errmsg (-1));
-
-	    hashfct (data->d_buf, data->d_size, ctx);
-
-	    /* And convert it back.  */
-	    if (gelf_xlatetom (ld_state.outelf, data, data, ident[EI_DATA])
-		== NULL)
-	      error (EXIT_FAILURE, 0, gettext ("\
-cannot convert section data to memory format: %s"),
-		     elf_errmsg (-1));
-	  }
-    }
-}
-
-
-/* Iterate over the sections */
-static void
-compute_build_id (void)
-{
-  Elf_Data *d = elf_getdata (elf_getscn (ld_state.outelf,
-					 ld_state.buildidscnidx), NULL);
-  assert (d != NULL);
-
-  GElf_Nhdr *hdr = d->d_buf;
-  hdr->n_namesz = sizeof (ELF_NOTE_GNU);
-  hdr->n_type = NT_GNU_BUILD_ID;
-  char *dp = mempcpy (hdr + 1, ELF_NOTE_GNU, sizeof (ELF_NOTE_GNU));
-
-  if (strcmp (ld_state.build_id, "sha1") == 0)
-    {
-      /* Compute the SHA1 sum of various parts of the generated file.
-	 We compute the hash sum over the external representation.  */
-      struct sha1_ctx ctx;
-      sha1_init_ctx (&ctx);
-
-      /* Compute the hash sum by running over all sections.  */
-      compute_hash_sum ((void (*) (const void *, size_t, void *)) sha1_process_bytes,
-			&ctx);
-
-      /* We are done computing the checksum.  */
-      (void) sha1_finish_ctx (&ctx, dp);
-
-      hdr->n_descsz = SHA1_DIGEST_SIZE;
-    }
-  else if (strcmp (ld_state.build_id, "md5") == 0)
-    {
-      /* Compute the MD5 sum of various parts of the generated file.
-	 We compute the hash sum over the external representation.  */
-      struct md5_ctx ctx;
-      md5_init_ctx (&ctx);
-
-      /* Compute the hash sum by running over all sections.  */
-      compute_hash_sum ((void (*) (const void *, size_t, void *)) md5_process_bytes,
-			&ctx);
-
-      /* We are done computing the checksum.  */
-      (void) md5_finish_ctx (&ctx, dp);
-
-      hdr->n_descsz = MD5_DIGEST_SIZE;
-    }
-  else if (strcmp (ld_state.build_id, "uuid") == 0)
-    {
-      int fd = open ("/dev/urandom", O_RDONLY);
-      if (fd == -1)
-	error (EXIT_FAILURE, errno, gettext ("cannot open '%s'"),
-	       "/dev/urandom");
-
-      if (TEMP_FAILURE_RETRY (read (fd, dp, 16)) != 16)
-	error (EXIT_FAILURE, 0, gettext ("cannot read enough data for UUID"));
-
-      close (fd);
-
-      hdr->n_descsz = 16;
-    }
-  else
-    {
-      const char *cp = ld_state.build_id + 2;
-
-      /* The form of the string has been verified before so here we can
-	 simplify the scanning.  */
-      do
-	{
-	  if (isxdigit (cp[0]))
-	    {
-	      char ch1 = tolower (cp[0]);
-	      char ch2 = tolower (cp[1]);
-
-	      *dp++ = (((isdigit (ch1) ? ch1 - '0' : ch1 - 'a' + 10) << 4)
-		       | (isdigit (ch2) ? ch2 - '0' : ch2 - 'a' + 10));
-	    }
-	  else
-	    ++cp;
-	}
-      while (*cp != '\0');
-    }
-}
-
-
-/* Create the output file.
-
-   For relocatable files what basically has to happen is that all
-   sections from all input files are written into the output file.
-   Sections with the same name are combined (offsets adjusted
-   accordingly).  The symbol tables are combined in one single table.
-   When stripping certain symbol table entries are omitted.
-
-   For executables (shared or not) we have to create the program header,
-   additional sections like the .interp, eventually (in addition) create
-   a dynamic symbol table and a dynamic section.  Also the relocations
-   have to be processed differently.  */
-static int
-ld_generic_create_outfile (struct ld_state *statep)
-{
-  struct scnlist
-  {
-    size_t scnidx;
-    struct scninfo *scninfo;
-    struct scnlist *next;
-  };
-  struct scnlist *rellist = NULL;
-  size_t cnt;
-  Elf_Scn *symscn = NULL;
-  Elf_Scn *xndxscn = NULL;
-  Elf_Scn *strscn = NULL;
-  struct Ebl_Strtab *strtab = NULL;
-  struct Ebl_Strtab *dynstrtab = NULL;
-  XElf_Shdr_vardef (shdr);
-  Elf_Data *data;
-  Elf_Data *symdata = NULL;
-  Elf_Data *xndxdata = NULL;
-  struct usedfiles *file;
-  size_t nsym;
-  size_t nsym_local;
-  size_t nsym_allocated;
-  size_t nsym_dyn = 0;
-  Elf32_Word *dblindirect = NULL;
-#ifndef NDEBUG
-  bool need_xndx;
-#endif
-  Elf_Scn *shstrtab_scn;
-  size_t shstrtab_ndx;
-  XElf_Ehdr_vardef (ehdr);
-  struct Ebl_Strent *symtab_ent = NULL;
-  struct Ebl_Strent *xndx_ent = NULL;
-  struct Ebl_Strent *strtab_ent = NULL;
-  struct Ebl_Strent *shstrtab_ent;
-  struct scngroup *groups;
-  Elf_Scn *dynsymscn = NULL;
-  Elf_Data *dynsymdata = NULL;
-  Elf_Data *dynstrdata = NULL;
-  Elf32_Word *hashcodes = NULL;
-  Elf32_Word *gnuhashcodes = NULL;
-  size_t nsym_dyn_allocated = 0;
-  Elf_Scn *versymscn = NULL;
-  Elf_Data *versymdata = NULL;
-
-  if (ld_state.need_symtab)
-    {
-      /* First create the symbol table.  We need the symbol section itself
-	 and the string table for it.  */
-      symscn = elf_newscn (ld_state.outelf);
-      ld_state.symscnidx = elf_ndxscn (symscn);
-      symdata = elf_newdata (symscn);
-      if (symdata == NULL)
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot create symbol table for output file: %s"),
-	       elf_errmsg (-1));
-
-      symdata->d_type = ELF_T_SYM;
-      /* This is an estimated size, but it will definitely cap the real value.
-	 We might have to adjust the number later.  */
-      nsym_allocated = (1 + ld_state.nsymtab + ld_state.nplt + ld_state.ngot
-			+ ld_state.nusedsections + ld_state.nlscript_syms);
-      symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM,
-				    nsym_allocated);
-
-      /* Optionally the extended section table.  */
-      /* XXX Is SHN_LORESERVE correct?  Do we need some other sections?  */
-      if (unlikely (ld_state.nusedsections >= SHN_LORESERVE))
-	{
-	  xndxscn = elf_newscn (ld_state.outelf);
-	  ld_state.xndxscnidx = elf_ndxscn (xndxscn);
-
-	  xndxdata = elf_newdata (xndxscn);
-	  if (xndxdata == NULL)
-	    error (EXIT_FAILURE, 0,
-		   gettext ("cannot create symbol table for output file: %s"),
-		   elf_errmsg (-1));
-
-	  /* The following relies on the fact that Elf32_Word and Elf64_Word
-	     have the same size.  */
-	  xndxdata->d_type = ELF_T_WORD;
-	  /* This is an estimated size, but it will definitely cap the
-	     real value.  we might have to adjust the number later.  */
-	  xndxdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_WORD,
-					 nsym_allocated);
-	  /* The first entry is left empty, clear it here and now.  */
-	  xndxdata->d_buf = memset (xmalloc (xndxdata->d_size), '\0',
-				    xelf_fsize (ld_state.outelf, ELF_T_WORD,
-						1));
-	  xndxdata->d_off = 0;
-	  /* XXX Should use an ebl function.  */
-	  xndxdata->d_align = sizeof (Elf32_Word);
-	}
-    }
-  else
-    {
-      assert (ld_state.need_dynsym);
-
-      /* First create the symbol table.  We need the symbol section itself
-	 and the string table for it.  */
-      symscn = elf_getscn (ld_state.outelf, ld_state.dynsymscnidx);
-      symdata = elf_newdata (symscn);
-      if (symdata == NULL)
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot create symbol table for output file: %s"),
-	       elf_errmsg (-1));
-
-      symdata->d_version = EV_CURRENT;
-      symdata->d_type = ELF_T_SYM;
-      /* This is an estimated size, but it will definitely cap the real value.
-	 We might have to adjust the number later.  */
-      nsym_allocated = (1 + ld_state.nsymtab + ld_state.nplt + ld_state.ngot
-			- ld_state.nlocalsymbols + ld_state.nlscript_syms);
-      symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM,
-				    nsym_allocated);
-    }
-
-  /* The first entry is left empty, clear it here and now.  */
-  symdata->d_buf = memset (xmalloc (symdata->d_size), '\0',
-			   xelf_fsize (ld_state.outelf, ELF_T_SYM, 1));
-  symdata->d_off = 0;
-  /* XXX This is ugly but how else can it be done.  */
-  symdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
-  /* Allocate another array to keep track of the handles for the symbol
-     names.  */
-  symstrent = (struct Ebl_Strent **) xcalloc (nsym_allocated,
-					      sizeof (struct Ebl_Strent *));
-
-  /* By starting at 1 we effectively add a null entry.  */
-  nsym = 1;
-
-  /* Iteration over all sections.  */
-  for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
-    {
-      struct scnhead *head = ld_state.allsections[cnt];
-      Elf_Scn *scn;
-      struct scninfo *runp;
-      XElf_Off offset;
-      Elf32_Word xndx;
-
-      /* Don't handle unused sections at all.  */
-      if (!head->used)
-	continue;
-
-      /* Get the section handle.  */
-      scn = elf_getscn (ld_state.outelf, head->scnidx);
-
-      if (unlikely (head->kind == scn_dot_interp))
-	{
-	  Elf_Data *outdata = elf_newdata (scn);
-	  if (outdata == NULL)
-	    error (EXIT_FAILURE, 0,
-		   gettext ("cannot create section for output file: %s"),
-		   elf_errmsg (-1));
-
-	  /* This is the string we'll put in the section.  */
-	  const char *interp = ld_state.interp ?: "/lib/ld.so.1";
-
-	  /* Create the section data.  */
-	  outdata->d_buf = (void *) interp;
-	  outdata->d_size = strlen (interp) + 1;
-	  outdata->d_type = ELF_T_BYTE;
-	  outdata->d_off = 0;
-	  outdata->d_align = 1;
-	  outdata->d_version = EV_CURRENT;
-
-	  /* Remember the index of this section.  */
-	  ld_state.interpscnidx = head->scnidx;
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_got))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.gotscnidx = elf_ndxscn (scn);
-
-	  /* Give the backend the change to initialize the section.  */
-	  INITIALIZE_GOT (&ld_state, scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_gotplt))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.gotpltscnidx = elf_ndxscn (scn);
-
-	  /* Give the backend the change to initialize the section.  */
-	  INITIALIZE_GOTPLT (&ld_state, scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_dynrel))
-	{
-	  Elf_Data *outdata;
-
-	  outdata = elf_newdata (scn);
-	  if (outdata == NULL)
-	    error (EXIT_FAILURE, 0,
-		   gettext ("cannot create section for output file: %s"),
-		   elf_errmsg (-1));
-
-	  outdata->d_size = ld_state.relsize_total;
-	  outdata->d_buf = xmalloc (outdata->d_size);
-	  outdata->d_type = (REL_TYPE (&ld_state) == DT_REL
-			     ? ELF_T_REL : ELF_T_RELA);
-	  outdata->d_off = 0;
-	  outdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
-	  /* Remember the index of this section.  */
-	  ld_state.reldynscnidx = elf_ndxscn (scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_dynamic))
-	{
-	  /* Only create the data for now.  */
-	  Elf_Data *outdata;
-
-	  /* Account for a few more entries we have to add.  */
-	  if (ld_state.dt_flags != 0)
-	    ++ld_state.ndynamic;
-	  if (ld_state.dt_flags_1 != 0)
-	    ++ld_state.ndynamic;
-	  if (ld_state.dt_feature_1 != 0)
-	    ++ld_state.ndynamic;
-
-	  outdata = elf_newdata (scn);
-	  if (outdata == NULL)
-	    error (EXIT_FAILURE, 0,
-		   gettext ("cannot create section for output file: %s"),
-		   elf_errmsg (-1));
-
-	  /* Create the section data.  */
-	  outdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_DYN,
-					ld_state.ndynamic);
-	  outdata->d_buf = xcalloc (1, outdata->d_size);
-	  outdata->d_type = ELF_T_DYN;
-	  outdata->d_off = 0;
-	  outdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
-	  /* Remember the index of this section.  */
-	  ld_state.dynamicscnidx = elf_ndxscn (scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_dynsym))
-	{
-	  /* We already know the section index.  */
-	  assert (ld_state.dynsymscnidx == elf_ndxscn (scn));
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_dynstr))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.dynstrscnidx = elf_ndxscn (scn);
-
-	  /* Create the string table.  */
-	  dynstrtab = ebl_strtabinit (true);
-
-	  /* XXX TBI
-	     We have to add all the strings which are needed in the
-	     dynamic section here.  This means DT_FILTER,
-	     DT_AUXILIARY, ... entries.  */
-	  if (ld_state.ndsofiles > 0)
-	    {
-	      struct usedfiles *frunp = ld_state.dsofiles;
-
-	      do
-		if (! frunp->as_needed || frunp->used)
-		  frunp->sonameent = ebl_strtabadd (dynstrtab, frunp->soname,
-						    0);
-	      while ((frunp = frunp->next) != ld_state.dsofiles);
-	    }
-
-
-	  /* Add the runtime path information.  The strings are stored
-	     in the .dynstr section.  If both rpath and runpath are defined
-	     the runpath information is used.  */
-	  if (ld_state.runpath != NULL || ld_state.rpath != NULL)
-	    {
-	      struct pathelement *startp;
-	      struct pathelement *prunp;
-	      int tag;
-	      size_t len;
-	      char *str;
-	      char *cp;
-
-	      if (ld_state.runpath != NULL)
-		{
-		  startp = ld_state.runpath;
-		  tag = DT_RUNPATH;
-		}
-	      else
-		{
-		  startp = ld_state.rpath;
-		  tag = DT_RPATH;
-		}
-
-	      /* Determine how long the string will be.  */
-	      for (len = 0, prunp = startp; prunp != NULL; prunp = prunp->next)
-		len += strlen (prunp->pname) + 1;
-
-	      cp = str = (char *) obstack_alloc (&ld_state.smem, len);
-	      /* Copy the string.  */
-	      for (prunp = startp; prunp != NULL; prunp = prunp->next)
-		{
-		  cp = stpcpy (cp, prunp->pname);
-		  *cp++ = ':';
-		}
-	      /* Remove the last colon.  */
-	      cp[-1] = '\0';
-
-	      /* Remember the values until we can generate the dynamic
-		 section.  */
-	      ld_state.rxxpath_strent = ebl_strtabadd (dynstrtab, str, len);
-	      ld_state.rxxpath_tag = tag;
-	    }
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_hash))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.hashscnidx = elf_ndxscn (scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_gnu_hash))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.gnuhashscnidx = elf_ndxscn (scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_plt))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.pltscnidx = elf_ndxscn (scn);
-
-	  /* Give the backend the change to initialize the section.  */
-	  INITIALIZE_PLT (&ld_state, scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_pltrel))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.pltrelscnidx = elf_ndxscn (scn);
-
-	  /* Give the backend the change to initialize the section.  */
-	  INITIALIZE_PLTREL (&ld_state, scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_version))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.versymscnidx = elf_ndxscn (scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_version_r))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.verneedscnidx = elf_ndxscn (scn);
-
-	  continue;
-	}
-
-      if (unlikely (head->kind == scn_dot_note_gnu_build_id))
-	{
-	  /* Remember the index of this section.  */
-	  ld_state.buildidscnidx = elf_ndxscn (scn);
-
-	  create_build_id_section (scn);
-
-	  continue;
-	}
-
-      /* If we come here we must be handling a normal section.  */
-      assert (head->kind == scn_normal);
-
-      /* Create an STT_SECTION entry in the symbol table.  But not for
-	 the symbolic symbol table.  */
-      if (ld_state.need_symtab)
-	{
-	  /* XXX Can we be cleverer and do this only if needed?  */
-	  XElf_Sym_vardef (sym);
-
-	  /* Optimization ahead: in the native linker we get a pointer
-	     to the final location so that the following code writes
-	     directly in the correct place.  Otherwise we write into
-	     the local variable first.  */
-	  xelf_getsym_ptr (symdata, nsym, sym);
-
-	  /* Usual section symbol: local, no specific information,
-	     except the section index.  The offset here is zero, the
-	     start address will later be added.  */
-	  sym->st_name = 0;
-	  sym->st_info = XELF_ST_INFO (STB_LOCAL, STT_SECTION);
-	  sym->st_other = 0;
-	  sym->st_value = 0;
-	  sym->st_size = 0;
-	  /* In relocatable files the section index can be too big for
-	     the ElfXX_Sym struct.  we have to deal with the extended
-	     symbol table.  */
-	  if (likely (head->scnidx < SHN_LORESERVE))
-	    {
-	      sym->st_shndx = head->scnidx;
-	      xndx = 0;
-	    }
-	  else
-	    {
-	      sym->st_shndx = SHN_XINDEX;
-	      xndx = head->scnidx;
-	    }
-	  /* Commit the change.  See the optimization above, this does
-	     not change the symbol table entry.  But the extended
-	     section index table entry is always written, if there is
-	     such a table.  */
-	  assert (nsym < nsym_allocated);
-	  xelf_update_symshndx (symdata, xndxdata, nsym, sym, xndx, 0);
-
-	  /* Remember the symbol's index in the symbol table.  */
-	  head->scnsymidx = nsym++;
-	}
-
-      if (head->type == SHT_REL || head->type == SHT_RELA)
-	{
-	  /* Remember that we have to fill in the symbol table section
-	     index.  */
-	  if (ld_state.file_type == relocatable_file_type)
-	    {
-	      struct scnlist *newp;
-
-	      newp = (struct scnlist *) alloca (sizeof (*newp));
-	      newp->scnidx = head->scnidx;
-	      newp->scninfo = head->last->next;
-#ifndef NDEBUG
-	      newp->next = NULL;
-#endif
-	      SNGL_LIST_PUSH (rellist, newp);
-	    }
-	  else
-	    {
-	      /* When we create an executable or a DSO we don't simply
-		 copy the existing relocations.  Instead many will be
-		 resolved, others will be converted.  Create a data buffer
-		 large enough to contain the contents which we will fill
-		 in later.  */
-	      int type = head->type == SHT_REL ? ELF_T_REL : ELF_T_RELA;
-
-	      data = elf_newdata (scn);
-	      if (data == NULL)
-		error (EXIT_FAILURE, 0,
-		       gettext ("cannot create section for output file: %s"),
-		       elf_errmsg (-1));
-
-	      data->d_size = xelf_fsize (ld_state.outelf, type, head->relsize);
-	      data->d_buf = xcalloc (data->d_size, 1);
-	      data->d_type = type;
-	      data->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-	      data->d_off = 0;
-
-	      continue;
-	    }
-	}
-
-      /* Recognize string and merge flag and handle them.  */
-      if (head->flags & SHF_MERGE)
-	{
-	  /* We merge the contents of the sections.  For this we do
-	     not look at the contents of section directly.  Instead we
-	     look at the symbols of the section.  */
-	  Elf_Data *outdata;
-
-	  /* Concatenate the lists of symbols for all sections.
-
-	     XXX In case any input section has no symbols associated
-	     (this happens for debug sections) we cannot use this
-	     method.  Implement parsing the other debug sections and
-	     find the string pointers.  For now we don't merge.  */
-	  runp = head->last->next;
-	  if (runp->symbols == NULL)
-	    {
-	      head->flags &= ~SHF_MERGE;
-	      goto no_merge;
-	    }
-	  head->symbols = runp->symbols;
-
-	  while ((runp = runp->next) != head->last->next)
-	    {
-	      if (runp->symbols == NULL)
-		{
-		  head->flags &= ~SHF_MERGE;
-		  head->symbols = NULL;
-		  goto no_merge;
-		}
-
-	      struct symbol *oldhead = head->symbols->next_in_scn;
-
-	      head->symbols->next_in_scn = runp->symbols->next_in_scn;
-	      runp->symbols->next_in_scn = oldhead;
-	      head->symbols = runp->symbols;
-	    }
-
-	  /* Create the output section.  */
-	  outdata = elf_newdata (scn);
-	  if (outdata == NULL)
-	    error (EXIT_FAILURE, 0,
-		   gettext ("cannot create section for output file: %s"),
-		   elf_errmsg (-1));
-
-	  /* We use different merging algorithms for performance
-	     reasons.  We can easily handle single-byte and
-	     wchar_t-wide character strings.  All other cases (which
-	     really should happen in real life) are handled by the
-	     generic code.  */
-	  if (SCNINFO_SHDR (head->last->shdr).sh_entsize == 1
-	      && (head->flags & SHF_STRINGS))
-	    {
-	      /* Simple, single-byte string matching.  */
-	      struct Ebl_Strtab *mergestrtab;
-	      struct symbol *symrunp;
-	      Elf_Data *locsymdata = NULL;
-	      Elf_Data *locdata = NULL;
-
-	      mergestrtab = ebl_strtabinit (false);
-
-	      symrunp = head->symbols->next_in_scn;
-	      file = NULL;
-	      do
-		{
-		  /* Accelarate the loop.  We cache the file
-		     information since it might very well be the case
-		     that the previous entry was from the same
-		     file.  */
-		  if (symrunp->file != file)
-		    {
-		      /* Remember the file.  */
-		      file = symrunp->file;
-		      /* Symbol table data from that file.  */
-		      locsymdata = file->symtabdata;
-		      /* String section data.  */
-		      locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn,
-					     NULL);
-		      assert (locdata != NULL);
-		      /* While we are at it, remember the output
-			 section.  If we don't access the string data
-			 section the section won't be in the output
-			 file.  So it is sufficient to do the work
-			 here.  */
-		      file->scninfo[symrunp->scndx].outscnndx = head->scnidx;
-		    }
-
-		  /* Get the symbol information.  This provides us the
-		     offset into the string data section.  */
-		  XElf_Sym_vardef (sym);
-		  xelf_getsym (locsymdata, symrunp->symidx, sym);
-		  assert (sym != NULL);
-
-		  /* Get the data from the file.  Note that we access
-		     the raw section data; no endian-ness issues with
-		     single-byte strings.  */
-		  symrunp->merge.handle
-		    = ebl_strtabadd (mergestrtab,
-				     (char *) locdata->d_buf + sym->st_value,
-				     0);
-		}
-	      while ((symrunp = symrunp->next_in_scn)
-		     != head->symbols->next_in_scn);
-
-	      /* All strings have been added.  Create the final table.  */
-	      ebl_strtabfinalize (mergestrtab, outdata);
-
-	      /* Compute the final offsets in the section.  */
-	      symrunp = runp->symbols;
-	      do
-		{
-		  symrunp->merge.value
-		    = ebl_strtaboffset (symrunp->merge.handle);
-		  symrunp->merged = 1;
-		}
-	      while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
-	      /* We don't need the string table anymore.  */
-	      ebl_strtabfree (mergestrtab);
-	    }
-	  else if (likely (SCNINFO_SHDR (head->last->shdr).sh_entsize
-			   == sizeof (wchar_t))
-		   && likely (head->flags & SHF_STRINGS))
-	    {
-	      /* Simple, wchar_t string merging.  */
-	      struct Ebl_WStrtab *mergestrtab;
-	      struct symbol *symrunp;
-	      Elf_Data *locsymdata = NULL;
-	      Elf_Data *locdata = NULL;
-
-	      mergestrtab = ebl_wstrtabinit (false);
-
-	      symrunp = runp->symbols;
-	      file = NULL;
-	      do
-		{
-		  /* Accelarate the loop.  We cache the file
-		     information since it might very well be the case
-		     that the previous entry was from the same
-		     file.  */
-		  if (symrunp->file != file)
-		    {
-		      /* Remember the file.  */
-		      file = symrunp->file;
-		      /* Symbol table data from that file.  */
-		      locsymdata = file->symtabdata;
-		      /* String section data.  */
-		      locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn,
-					     NULL);
-		      assert (locdata != NULL);
-
-		      /* While we are at it, remember the output
-			 section.  If we don't access the string data
-			 section the section won't be in the output
-			 file.  So it is sufficient to do the work
-			 here.  */
-		      file->scninfo[symrunp->scndx].outscnndx = head->scnidx;
-		    }
-
-		  /* Get the symbol information.  This provides us the
-		     offset into the string data section.  */
-		  XElf_Sym_vardef (sym);
-		  xelf_getsym (locsymdata, symrunp->symidx, sym);
-		  assert (sym != NULL);
-
-		  /* Get the data from the file.  Using the raw
-		     section data here is possible since we don't
-		     interpret the string themselves except for
-		     looking for the wide NUL character.  The NUL
-		     character has fortunately the same representation
-		     regardless of the byte order.  */
-		  symrunp->merge.handle
-		    = ebl_wstrtabadd (mergestrtab,
-				      (wchar_t *) ((char *) locdata->d_buf
-						   + sym->st_value), 0);
-		}
-	      while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
-	      /* All strings have been added.  Create the final table.  */
-	      ebl_wstrtabfinalize (mergestrtab, outdata);
-
-	      /* Compute the final offsets in the section.  */
-	      symrunp = runp->symbols;
-	      do
-		{
-		  symrunp->merge.value
-		    = ebl_wstrtaboffset (symrunp->merge.handle);
-		  symrunp->merged = 1;
-		}
-	      while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
-	      /* We don't need the string table anymore.  */
-	      ebl_wstrtabfree (mergestrtab);
-	    }
-	  else
-	    {
-	      /* Non-standard merging.  */
-	      struct Ebl_GStrtab *mergestrtab;
-	      struct symbol *symrunp;
-	      Elf_Data *locsymdata = NULL;
-	      Elf_Data *locdata = NULL;
-	      /* If this is no string section the length of each "string"
-		 is always one.  */
-	      unsigned int len = (head->flags & SHF_STRINGS) ? 0 : 1;
-
-	      /* This is the generic string table functionality.  Much
-		 slower than the specialized code.  */
-	      mergestrtab
-		= ebl_gstrtabinit (SCNINFO_SHDR (head->last->shdr).sh_entsize,
-				   false);
-
-	      symrunp = runp->symbols;
-	      file = NULL;
-	      do
-		{
-		  /* Accelarate the loop.  We cache the file
-		     information since it might very well be the case
-		     that the previous entry was from the same
-		     file.  */
-		  if (symrunp->file != file)
-		    {
-		      /* Remember the file.  */
-		      file = symrunp->file;
-		      /* Symbol table data from that file.  */
-		      locsymdata = file->symtabdata;
-		      /* String section data.  */
-		      locdata = elf_rawdata (file->scninfo[symrunp->scndx].scn,
-					     NULL);
-		      assert (locdata != NULL);
-
-		      /* While we are at it, remember the output
-			 section.  If we don't access the string data
-			 section the section won't be in the output
-			 file.  So it is sufficient to do the work
-			 here.  */
-		      file->scninfo[symrunp->scndx].outscnndx = head->scnidx;
-		    }
-
-		  /* Get the symbol information.  This provides us the
-		     offset into the string data section.  */
-		  XElf_Sym_vardef (sym);
-		  xelf_getsym (locsymdata, symrunp->symidx, sym);
-		  assert (sym != NULL);
-
-		  /* Get the data from the file.  Using the raw
-		     section data here is possible since we don't
-		     interpret the string themselves except for
-		     looking for the wide NUL character.  The NUL
-		     character has fortunately the same representation
-		     regardless of the byte order.  */
-		  symrunp->merge.handle
-		    = ebl_gstrtabadd (mergestrtab,
-				      (char *) locdata->d_buf + sym->st_value,
-				      len);
-		}
-	      while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
-	      /* Create the final table.  */
-	      ebl_gstrtabfinalize (mergestrtab, outdata);
-
-	      /* Compute the final offsets in the section.  */
-	      symrunp = runp->symbols;
-	      do
-		{
-		  symrunp->merge.value
-		    = ebl_gstrtaboffset (symrunp->merge.handle);
-		  symrunp->merged = 1;
-		}
-	      while ((symrunp = symrunp->next_in_scn) != runp->symbols);
-
-	      /* We don't need the string table anymore.  */
-	      ebl_gstrtabfree (mergestrtab);
-	    }
-	}
-      else
-	{
-	no_merge:
-	  assert (head->scnidx == elf_ndxscn (scn));
-
-	  /* It is important to start with the first list entry (and
-	     not just any one) to add the sections in the correct
-	     order.  */
-	  runp = head->last->next;
-	  offset = 0;
-	  do
-	    {
-	      Elf_Data *outdata = elf_newdata (scn);
-	      if (outdata == NULL)
-		error (EXIT_FAILURE, 0,
-		       gettext ("cannot create section for output file: %s"),
-		       elf_errmsg (-1));
-
-	      /* Exceptional case: if we synthesize a data block SCN
-		 is NULL and the sectio header info must be for a
-		 SHT_NOBITS block and the size and alignment are
-		 filled in.  */
-	      if (likely (runp->scn != NULL))
-		{
-		  data = elf_getdata (runp->scn, NULL);
-		  assert (data != NULL);
-
-		  /* We reuse the data buffer in the input file.  */
-		  *outdata = *data;
-
-		  /* Given that we read the input file from disk we know there
-		     cannot be another data part.  */
-		  assert (elf_getdata (runp->scn, data) == NULL);
-		}
-	      else
-		{
-		  /* Must be a NOBITS section.  */
-		  assert  (SCNINFO_SHDR (runp->shdr).sh_type == SHT_NOBITS);
-
-		  outdata->d_buf = NULL;	/* Not needed.  */
-		  outdata->d_type = ELF_T_BYTE;
-		  outdata->d_version = EV_CURRENT;
-		  outdata->d_size = SCNINFO_SHDR (runp->shdr).sh_size;
-		  outdata->d_align = SCNINFO_SHDR (runp->shdr).sh_addralign;
-		}
-
-	      XElf_Off align =  MAX (1, outdata->d_align);
-	      assert (powerof2 (align));
-	      offset = ((offset + align - 1) & ~(align - 1));
-
-	      runp->offset = offset;
-	      runp->outscnndx = head->scnidx;
-	      runp->allsectionsidx = cnt;
-
-	      outdata->d_off = offset;
-
-	      offset += outdata->d_size;
-	    }
-	  while ((runp = runp->next) != head->last->next);
-
-	  /* If necessary add the additional line to the .comment section.  */
-	  if (ld_state.add_ld_comment
-	      && head->flags == 0
-	      && head->type == SHT_PROGBITS
-	      && strcmp (head->name, ".comment") == 0
-	      && head->entsize == 0)
-	    {
-	      Elf_Data *outdata = elf_newdata (scn);
-
-	      if (outdata == NULL)
-		error (EXIT_FAILURE, 0,
-		       gettext ("cannot create section for output file: %s"),
-		       elf_errmsg (-1));
-
-	      outdata->d_buf = (void *) "\0ld (" PACKAGE_NAME ") " PACKAGE_VERSION;
-	      outdata->d_size = strlen ((char *) outdata->d_buf + 1) + 2;
-	      outdata->d_off = offset;
-	      outdata->d_type = ELF_T_BYTE;
-	      outdata->d_align = 1;
-	    }
-	  /* XXX We should create a .comment section if none exists.
-	     This requires that we early on detect that no such
-	     section exists.  This should probably be implemented
-	     together with some merging of the section contents.
-	     Currently identical entries are not merged.  */
-	}
-    }
-
-  /* The table we collect the strings in.  */
-  strtab = ebl_strtabinit (true);
-  if (strtab == NULL)
-    error (EXIT_FAILURE, errno, gettext ("cannot create string table"));
-
-
-#ifndef NDEBUG
-  /* Keep track of the use of the XINDEX.  */
-  need_xndx = false;
-#endif
-
-  /* We we generate a normal symbol table for an executable and the
-     --export-dynamic option is not given, we need an extra table
-     which keeps track of the symbol entry belonging to the symbol
-     table entry.  Note that EXPORT_ALL_DYNAMIC is always set if we
-     generate a DSO so we do not have to test this separately.  */
-  ndxtosym = (struct symbol **) xcalloc (nsym_allocated,
-					 sizeof (struct symbol));
-
-  /* Create the special symbol for the GOT section.  */
-  if (ld_state.got_symbol != NULL)
-    {
-      assert (nsym < nsym_allocated);
-      // XXX Fix so that it works even if no PLT is needed.
-      fillin_special_symbol (ld_state.got_symbol, ld_state.gotpltscnidx,
-			     nsym++, symdata, strtab);
-    }
-
-  /* Similarly for the dynamic section symbol.  */
-  if (ld_state.dyn_symbol != NULL)
-    {
-      assert (nsym < nsym_allocated);
-      fillin_special_symbol (ld_state.dyn_symbol, ld_state.dynamicscnidx,
-			     nsym++, symdata, strtab);
-    }
-
-  /* Create symbol table entries for the symbols defined in the linker
-     script.  */
-  if (ld_state.lscript_syms != NULL)
-    {
-      struct symbol *rsym = ld_state.lscript_syms;
-      do
-	{
-	  assert (nsym < nsym_allocated);
-	  fillin_special_symbol (rsym, SHN_ABS, nsym++, symdata, strtab);
-	}
-      while ((rsym = rsym->next) != NULL);
-    }
-
-  /* Iterate over all input files to collect the symbols.  */
-  file = ld_state.relfiles->next;
-  symdata = elf_getdata (elf_getscn (ld_state.outelf, ld_state.symscnidx),
-			 NULL);
-
-  do
-    {
-      size_t maxcnt;
-      Elf_Data *insymdata;
-      Elf_Data *inxndxdata;
-
-      /* There must be no dynamic symbol table when creating
-	 relocatable files.  */
-      assert (ld_state.file_type != relocatable_file_type
-	      || file->dynsymtabdata == NULL);
-
-      insymdata = file->symtabdata;
-      assert (insymdata != NULL);
-      inxndxdata = file->xndxdata;
-
-      maxcnt = file->nsymtab;
-
-      file->symindirect = (Elf32_Word *) xcalloc (maxcnt, sizeof (Elf32_Word));
-
-      /* The dynamic symbol table does not contain local symbols.  So
-         we skip those entries.  */
-      for (cnt = ld_state.need_symtab ? 1 : file->nlocalsymbols; cnt < maxcnt;
-	   ++cnt)
-	{
-	  XElf_Sym_vardef (sym);
-	  Elf32_Word xndx;
-	  struct symbol *defp = NULL;
-
-	  xelf_getsymshndx (insymdata, inxndxdata, cnt, sym, xndx);
-	  assert (sym != NULL);
-
-	  if (unlikely (XELF_ST_TYPE (sym->st_info) == STT_SECTION))
-	    {
-	      /* Section symbols should always be local but who knows...  */
-	      if (ld_state.need_symtab)
-		{
-		  /* Determine the real section index in the source file.
-		     Use the XINDEX section content if necessary.  We don't
-		     add this information to the dynamic symbol table.  */
-		  if (sym->st_shndx != SHN_XINDEX)
-		    xndx = sym->st_shndx;
-
-		  assert (file->scninfo[xndx].allsectionsidx
-			  < ld_state.nallsections);
-		  file->symindirect[cnt] = ld_state.allsections[file->scninfo[xndx].allsectionsidx]->scnsymidx;
-		  /* Note that the resulting index can be zero here.  There is
-		     no guarantee that the output file will contain all the
-		     sections the input file did.  */
-		}
-	      continue;
-	    }
-
-	  if ((ld_state.strip >= strip_all || !ld_state.need_symtab)
-	      /* XXX Do we need these entries?  */
-	      && XELF_ST_TYPE (sym->st_info) == STT_FILE)
-	    continue;
-
-#if NATIVE_ELF != 0
-	  /* Copy old data.  We create a temporary copy because the
-	     symbol might still be discarded.  */
-	  XElf_Sym sym_mem;
-	  sym_mem = *sym;
-	  sym = &sym_mem;
-#endif
-
-	  if (sym->st_shndx != SHN_UNDEF
-	      && (sym->st_shndx < SHN_LORESERVE
-		  || sym->st_shndx == SHN_XINDEX))
-	    {
-	      /* If we are creating an executable with no normal
-		 symbol table and we do not export all symbols and
-		 this symbol is not defined in a DSO as well, ignore
-		 it.  */
-	      if (!ld_state.export_all_dynamic && !ld_state.need_symtab)
-		{
-		  assert (cnt >= file->nlocalsymbols);
-		  defp = file->symref[cnt];
-		  assert (defp != NULL);
-
-		  if (!defp->in_dso)
-		    /* Ignore it.  */
-		    continue;
-		}
-
-	      /* Determine the real section index in the source file.  Use
-		 the XINDEX section content if necessary.  */
-	      if (sym->st_shndx != SHN_XINDEX)
-		xndx = sym->st_shndx;
-
-	      sym->st_value += file->scninfo[xndx].offset;
-
-	      assert (file->scninfo[xndx].outscnndx < SHN_LORESERVE
-		      || file->scninfo[xndx].outscnndx > SHN_HIRESERVE);
-	      if (unlikely (file->scninfo[xndx].outscnndx > SHN_LORESERVE))
-		{
-		  /* It is not possible to have an extended section index
-		     table for the dynamic symbol table.  */
-		  if (!ld_state.need_symtab)
-		    error (EXIT_FAILURE, 0, gettext ("\
-section index too large in dynamic symbol table"));
-
-		  assert (xndxdata != NULL);
-		  sym->st_shndx = SHN_XINDEX;
-		  xndx = file->scninfo[xndx].outscnndx;
-#ifndef NDEBUG
-		  need_xndx = true;
-#endif
-		}
-	      else
-		{
-		  sym->st_shndx = file->scninfo[xndx].outscnndx;
-		  xndx = 0;
-		}
-	    }
-	  else if (sym->st_shndx == SHN_COMMON || sym->st_shndx == SHN_UNDEF)
-	    {
-	      /* Check whether we have a (real) definition for this
-		 symbol.  If this is the case we skip this symbol
-		 table entry.  */
-	      assert (cnt >= file->nlocalsymbols);
-	      defp = file->symref[cnt];
-	      assert (defp != NULL);
-
-	      assert (sym->st_shndx != SHN_COMMON || defp->defined);
-
-	      if ((sym->st_shndx == SHN_COMMON && !defp->common)
-		  || (sym->st_shndx == SHN_UNDEF && defp->defined)
-		  || defp->added)
-		/* Ignore this symbol table entry, there is a
-		   "better" one or we already added it.  */
-		continue;
-
-	      /* Remember that we already added this symbol.  */
-	      defp->added = 1;
-
-	      /* Adjust the section number for common symbols.  */
-	      if (sym->st_shndx == SHN_COMMON)
-		{
-		  sym->st_value = (ld_state.common_section->offset
-				   + file->symref[cnt]->merge.value);
-		  assert (ld_state.common_section->outscnndx < SHN_LORESERVE);
-		  sym->st_shndx = ld_state.common_section->outscnndx;
-		  xndx = 0;
-		}
-	    }
-	  else if (unlikely (sym->st_shndx != SHN_ABS))
-	    {
-	      if (SPECIAL_SECTION_NUMBER_P (&ld_state, sym->st_shndx))
-		/* XXX Add code to handle machine specific special
-		   sections.  */
-		abort ();
-	    }
-
-	  /* Add the symbol name to the string table.  If the user
-	     chooses the highest level of stripping avoid adding names
-	     for local symbols in the string table.  */
-	  if (sym->st_name != 0
-	      && (ld_state.strip < strip_everything
-		  || XELF_ST_BIND (sym->st_info) != STB_LOCAL))
-	    symstrent[nsym] = ebl_strtabadd (strtab,
-					     elf_strptr (file->elf,
-							 file->symstridx,
-							 sym->st_name), 0);
-
-	  /* Once we know the name this field will get the correct
-	     offset.  For now set it to zero which means no name
-	     associated.  */
-	  GElf_Word st_name = sym->st_name;
-	  sym->st_name = 0;
-
-	  /* If we had to merge sections we have a completely new
-	     offset for the symbol.  */
-	  if (file->has_merge_sections && file->symref[cnt] != NULL
-	      && file->symref[cnt]->merged)
-	    sym->st_value = file->symref[cnt]->merge.value;
-
-	  /* Create the record in the output sections.  */
-	  assert (nsym < nsym_allocated);
-	  xelf_update_symshndx (symdata, xndxdata, nsym, sym, xndx, 1);
-
-	  /* Add the reference to the symbol record in case we need it.
-	     Find the symbol if this has not happened yet.  We do
-	     not need the information for local symbols.  */
-	  if (defp == NULL && cnt >= file->nlocalsymbols)
-	    {
-	      defp = file->symref[cnt];
-
-	      if (defp == NULL)
-		{
-		  /* This is a symbol in a discarded COMDAT section.
-		     Find the definition we actually use.  */
-		  // XXX The question is: do we have to do this here
-		  // XXX or can we do it earlier when we discard the
-		  // XXX section.
-		  struct symbol search;
-		  search.name = elf_strptr (file->elf, file->symstridx,
-					    st_name);
-		  struct symbol *realp
-		    = ld_symbol_tab_find (&ld_state.symbol_tab,
-					  elf_hash (search.name), &search);
-		  if (realp == NULL)
-		    // XXX What to do here?
-		    error (EXIT_FAILURE, 0,
-			   "couldn't find symbol from COMDAT section");
-
-		  file->symref[cnt] = realp;
-
-		  continue;
-		}
-	    }
-
-	  /* Store the reference to the symbol record.  The sorting
-	     code will have to keep this array in the correct order, too.  */
-	  ndxtosym[nsym] = defp;
-
-	  /* One more entry finished.  */
-	  if (cnt >= file->nlocalsymbols)
-	    {
-	      assert (file->symref[cnt]->outsymidx == 0);
-	      file->symref[cnt]->outsymidx = nsym;
-	    }
-	  file->symindirect[cnt] = nsym++;
-	}
-    }
-  while ((file = file->next) != ld_state.relfiles->next);
-  /* Make sure we didn't create the extended section index table for
-     nothing.  */
-  assert (xndxdata == NULL || need_xndx);
-
-  /* Create the version related sections.  */
-  if (ld_state.verneedscnidx != 0)
-    {
-      /* We know the number of input files and total number of
-	 referenced versions.  This allows us to allocate the memory
-	 and then we iterate over the DSOs to get the version
-	 information.  */
-      struct usedfiles *runp;
-
-      runp = ld_state.dsofiles->next;
-      do
-	allocate_version_names (runp, dynstrtab);
-      while ((runp = runp->next) != ld_state.dsofiles->next);
-
-      if (ld_state.needed != NULL)
-	{
-	  runp = ld_state.needed->next;
-	  do
-	    allocate_version_names (runp, dynstrtab);
-	  while ((runp = runp->next) != ld_state.needed->next);
-	}
-    }
-
-  /* At this point we should hide symbols and so on.  */
-  if (ld_state.default_bind_local || ld_state.version_str_tab.filled > 0)
-    /* XXX Add one more test when handling of wildcard symbol names
-       is supported.  */
-    {
-    /* Check all non-local symbols whether they are on the export list.  */
-      bool any_reduced = false;
-
-      for (cnt = 1; cnt < nsym; ++cnt)
-	{
-	  XElf_Sym_vardef (sym);
-
-	  /* Note that we don't have to use 'xelf_getsymshndx' since we
-	     only need the binding and the symbol name.  */
-	  xelf_getsym (symdata, cnt, sym);
-	  assert (sym != NULL);
-
-	  if (reduce_symbol_p (sym, symstrent[cnt]))
-	    {
-	      // XXX Check whether this is correct...
-	      assert (ndxtosym[cnt]->outdynsymidx != 0);
-	      ndxtosym[cnt]->outdynsymidx = 0;
-
-	      sym->st_info = XELF_ST_INFO (STB_LOCAL,
-					   XELF_ST_TYPE (sym->st_info));
-	      (void) xelf_update_sym (symdata, cnt, sym);
-
-	      /* Show that we don't need this string anymore.  */
-	      if (ld_state.strip == strip_everything)
-		{
-		  symstrent[cnt] = NULL;
-		  any_reduced = true;
-		}
-	    }
-	}
-
-      if (unlikely (any_reduced))
-	{
-	  /* Since we will not write names of local symbols in the
-	     output file and we have reduced the binding of some
-	     symbols the string table previously constructed contains
-	     too many string.  Correct it.  */
-	  struct Ebl_Strtab *newp = ebl_strtabinit (true);
-
-	  for (cnt = 1; cnt < nsym; ++cnt)
-	    if (symstrent[cnt] != NULL)
-	      symstrent[cnt] = ebl_strtabadd (newp,
-					      ebl_string (symstrent[cnt]), 0);
-
-	  ebl_strtabfree (strtab);
-	  strtab = newp;
-	}
-    }
-
-  /* Add the references to DSOs.  We can add these entries this late
-     (after sorting out versioning) because references to DSOs are not
-     effected.  */
-  if (ld_state.from_dso != NULL)
-    {
-      struct symbol *runp;
-      size_t plt_base = nsym + ld_state.nfrom_dso - ld_state.nplt;
-      size_t plt_idx = 0;
-      size_t obj_idx = 0;
-
-      assert (ld_state.nfrom_dso >= ld_state.nplt);
-      runp = ld_state.from_dso;
-      do
-	{
-	  // XXX What about functions which are only referenced via
-	  // pointers and not PLT entries?  Can we distinguish such uses?
-	  size_t idx;
-	  if (runp->type == STT_FUNC)
-	    {
-	      /* Store the PLT entry number.  */
-	      runp->merge.value = plt_idx + 1;
-	      idx = plt_base + plt_idx++;
-	    }
-	  else
-	    idx = nsym + obj_idx++;
-
-	  XElf_Sym_vardef (sym);
-	  xelf_getsym_ptr (symdata, idx, sym);
-
-	  sym->st_value = 0;
-	  sym->st_size = runp->size;
-	  sym->st_info = XELF_ST_INFO (runp->weak ? STB_WEAK : STB_GLOBAL,
-				       runp->type);
-	  sym->st_other = STV_DEFAULT;
-	  sym->st_shndx = SHN_UNDEF;
-
-	  /* Create the record in the output sections.  */
-	  xelf_update_symshndx (symdata, xndxdata, idx, sym, 0, 0);
-
-	  const char *name = runp->name;
-	  size_t namelen = 0;
-
-	  if (runp->file->verdefdata != NULL)
-	    {
-	      // XXX Is it useful to add the versym value to struct symbol?
-	      XElf_Versym versym;
-
-	      (void) xelf_getversym_copy (runp->file->versymdata, runp->symidx,
-					  versym);
-
-	      /* One can only link with the default version.  */
-	      assert ((versym & 0x8000) == 0);
-
-	      const char *versname
-		= ebl_string (runp->file->verdefent[versym]);
-
-	      size_t versname_len = strlen (versname) + 1;
-	      namelen = strlen (name) + versname_len + 2;
-	      char *newp = (char *) obstack_alloc (&ld_state.smem, namelen);
-	      memcpy (stpcpy (stpcpy (newp, name), "@@"),
-		      versname, versname_len);
-	      name = newp;
-	    }
-
-	  symstrent[idx] = ebl_strtabadd (strtab, name, namelen);
-
-	  /* Record the initial index in the symbol table.  */
-	  runp->outsymidx = idx;
-
-	  /* Remember the symbol record this ELF symbol came from.  */
-	  ndxtosym[idx] = runp;
-	}
-      while ((runp = runp->next) != ld_state.from_dso);
-
-      assert (nsym + obj_idx == plt_base);
-      assert (plt_idx == ld_state.nplt);
-      nsym = plt_base + plt_idx;
-    }
-
-  /* Now we know how many symbols will be in the output file.  Adjust
-     the count in the section data.  */
-  symdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym);
-  if (unlikely (xndxdata != NULL))
-    xndxdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_WORD, nsym);
-
-  /* Create the symbol string table section.  */
-  strscn = elf_newscn (ld_state.outelf);
-  ld_state.strscnidx = elf_ndxscn (strscn);
-  data = elf_newdata (strscn);
-  xelf_getshdr (strscn, shdr);
-  if (data == NULL || shdr == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create section for output file: %s"),
-	   elf_errmsg (-1));
-
-  /* Create a compact string table, allocate the memory for it, and
-     fill in the section data information.  */
-  ebl_strtabfinalize (strtab, data);
-
-  shdr->sh_type = SHT_STRTAB;
-  assert (shdr->sh_entsize == 0);
-
-  if (unlikely (xelf_update_shdr (strscn, shdr) == 0))
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create section for output file: %s"),
-	   elf_errmsg (-1));
-
-  /* Fill in the offsets of the symbol names.  */
-  for (cnt = 1; cnt < nsym; ++cnt)
-    if (symstrent[cnt] != NULL)
-      {
-	XElf_Sym_vardef (sym);
-
-	/* Note that we don't have to use 'xelf_getsymshndx' since we don't
-	   modify the section index.  */
-	xelf_getsym (symdata, cnt, sym);
-	/* This better worked, we did it before.  */
-	assert (sym != NULL);
-	sym->st_name = ebl_strtaboffset (symstrent[cnt]);
-	(void) xelf_update_sym (symdata, cnt, sym);
-      }
-
-  /* Since we are going to reorder the symbol table but still have to
-     be able to find the new position based on the old one (since the
-     latter is stored in 'symindirect' information of the input file
-     data structure) we have to create yet another indirection
-     table.  */
-  ld_state.dblindirect = dblindirect
-    = (Elf32_Word *) xmalloc (nsym * sizeof (Elf32_Word));
-
-  /* Sort the symbol table so that the local symbols come first.  */
-  /* XXX We don't use stable sorting here.  It seems not necessary and
-     would be more expensive.  If it turns out to be necessary this can
-     be fixed easily.  */
-  nsym_local = 1;
-  cnt = nsym - 1;
-  while (nsym_local < cnt)
-    {
-      XElf_Sym_vardef (locsym);
-      Elf32_Word locxndx;
-      XElf_Sym_vardef (globsym);
-      Elf32_Word globxndx;
-
-      do
-	{
-	  xelf_getsymshndx (symdata, xndxdata, nsym_local, locsym, locxndx);
-	  /* This better works.  */
-	  assert (locsym != NULL);
-
-	  if (XELF_ST_BIND (locsym->st_info) != STB_LOCAL
-	      && (ld_state.need_symtab || ld_state.export_all_dynamic))
-	    {
-	      do
-		{
-		  xelf_getsymshndx (symdata, xndxdata, cnt, globsym, globxndx);
-		  /* This better works.  */
-		  assert (globsym != NULL);
-
-		  if (unlikely (XELF_ST_BIND (globsym->st_info) == STB_LOCAL))
-		    {
-		      /* We swap the two entries.  */
-#if NATIVE_ELF != 0
-		      /* Since we directly modify the data in the ELF
-			 data structure we have to make a copy of one
-			 of the entries.  */
-		      XElf_Sym locsym_copy = *locsym;
-		      locsym = &locsym_copy;
-#endif
-		      xelf_update_symshndx (symdata, xndxdata, nsym_local,
-					    globsym, globxndx, 1);
-		      xelf_update_symshndx (symdata, xndxdata, cnt,
-					    locsym, locxndx, 1);
-
-		      /* Also swap the cross references.  */
-		      dblindirect[nsym_local] = cnt;
-		      dblindirect[cnt] = nsym_local;
-
-		      /* And the entries for the symbol names.  */
-		      struct Ebl_Strent *strtmp = symstrent[nsym_local];
-		      symstrent[nsym_local] = symstrent[cnt];
-		      symstrent[cnt] = strtmp;
-
-		      /* And the mapping from symbol table entry to
-			 struct symbol record.  */
-		      struct symbol *symtmp = ndxtosym[nsym_local];
-		      ndxtosym[nsym_local] = ndxtosym[cnt];
-		      ndxtosym[cnt] = symtmp;
-
-		      /* Go to the next entry.  */
-		      ++nsym_local;
-		      --cnt;
-
-		      break;
-		    }
-
-		  dblindirect[cnt] = cnt;
-		}
-	      while (nsym_local < --cnt);
-
-	      break;
-	    }
-
-	  dblindirect[nsym_local] = nsym_local;
-	}
-      while (++nsym_local < cnt);
-    }
-
-  /* The symbol 'nsym_local' is currently pointing to might be local,
-     too.  Check and increment the variable if this is the case.  */
-  if (likely (nsym_local < nsym))
-    {
-      XElf_Sym_vardef (locsym);
-
-      /* This entry isn't moved.  */
-      dblindirect[nsym_local] = nsym_local;
-
-      /* Note that it is OK to not use 'xelf_getsymshndx' here.  */
-      xelf_getsym (symdata, nsym_local, locsym);
-      /* This better works.  */
-      assert (locsym != NULL);
-
-      if (XELF_ST_BIND (locsym->st_info) == STB_LOCAL)
-	++nsym_local;
-    }
-
-
-  /* We need the versym array right away to keep track of the version
-     symbols.  */
-  if (ld_state.versymscnidx != 0)
-    {
-      /* We allocate more memory than we need since the array is morroring
-	 the dynamic symbol table and not the normal symbol table.  I.e.,
-	 no local symbols are present.  */
-      versymscn = elf_getscn (ld_state.outelf, ld_state.versymscnidx);
-      versymdata = elf_newdata (versymscn);
-      if (versymdata == NULL)
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot create versioning section: %s"),
-	       elf_errmsg (-1));
-
-      versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF,
-				       nsym - nsym_local + 1);
-      versymdata->d_buf = xcalloc (1, versymdata->d_size);
-      versymdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_HALF, 1);
-      versymdata->d_off = 0;
-      versymdata->d_type = ELF_T_HALF;
-    }
-
-
-  /* If we have to construct the dynamic symbol table we must not include
-     the local symbols.  If the normal symbol has to be emitted as well
-     we haven't done anything else yet and we can construct it from
-     scratch now.  */
-  if (unlikely (!ld_state.need_symtab))
-    {
-      /* Note that the following code works even if there is no entry
-	 to remove since the zeroth entry is always local.  */
-      size_t reduce = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_local - 1);
-
-      XElf_Sym_vardef (nullsym);
-      xelf_getsym_ptr (symdata, nsym_local - 1, nullsym);
-
-      /* Note that we don't have to use 'xelf_update_symshndx' since
-	 this is the dynamic symbol table we write.  */
-      (void) xelf_update_sym (symdata, nsym_local - 1,
-			      memset (nullsym, '\0', sizeof (*nullsym)));
-
-      /* Update the buffer pointer and size in the output data.  */
-      symdata->d_buf = (char *) symdata->d_buf + reduce;
-      symdata->d_size -= reduce;
-
-      /* Add the version symbol information.  */
-      if (versymdata != NULL)
-	{
-	  nsym_dyn = 1;
-	  for (cnt = nsym_local; cnt < nsym; ++cnt, ++nsym_dyn)
-	    {
-	      struct symbol *symp = ndxtosym[cnt];
-
-	      if (symp->file->versymdata != NULL)
-		{
-		  GElf_Versym versym;
-
-		  gelf_getversym (symp->file->versymdata, symp->symidx,
-				  &versym);
-
-		  (void) gelf_update_versym (versymdata, symp->outdynsymidx,
-					     &symp->file->verdefused[versym]);
-		}
-	      }
-	}
-
-      /* Since we only created the dynamic symbol table the number of
-	 dynamic symbols is the total number of symbols.  */
-      nsym_dyn = nsym - nsym_local + 1;
-
-      /* XXX TBI.  Create whatever data structure is missing.  */
-      abort ();
-    }
-  else if (ld_state.need_dynsym)
-    {
-      /* Create the dynamic symbol table section data along with the
-	 string table.  We look at all non-local symbols we found for
-	 the normal symbol table and add those.  */
-      dynsymscn = elf_getscn (ld_state.outelf, ld_state.dynsymscnidx);
-      dynsymdata = elf_newdata (dynsymscn);
-
-      dynstrdata = elf_newdata (elf_getscn (ld_state.outelf,
-					    ld_state.dynstrscnidx));
-      if (dynsymdata == NULL || dynstrdata == NULL)
-	error (EXIT_FAILURE, 0, gettext ("\
-cannot create dynamic symbol table for output file: %s"),
-	       elf_errmsg (-1));
-
-      nsym_dyn_allocated = nsym - nsym_local + 1;
-      dynsymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM,
-				       nsym_dyn_allocated);
-      dynsymdata->d_buf = memset (xmalloc (dynsymdata->d_size), '\0',
-				  xelf_fsize (ld_state.outelf, ELF_T_SYM, 1));
-      dynsymdata->d_type = ELF_T_SYM;
-      dynsymdata->d_off = 0;
-      dynsymdata->d_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
-      /* We need one more array which contains the hash codes of the
-	 symbol names.  */
-      hashcodes = (Elf32_Word *) xcalloc (__builtin_popcount ((int) ld_state.hash_style)
-					  * nsym_dyn_allocated,
-					  sizeof (Elf32_Word));
-      gnuhashcodes = hashcodes;
-      if (GENERATE_SYSV_HASH)
-	gnuhashcodes += nsym_dyn_allocated;
-
-      /* We have and empty entry at the beginning.  */
-      nsym_dyn = 1;
-
-      /* Populate the table.  */
-      for (cnt = nsym_local; cnt < nsym; ++cnt)
-	{
-	  XElf_Sym_vardef (sym);
-
-	  xelf_getsym (symdata, cnt, sym);
-	  assert (sym != NULL);
-
-	  if (sym->st_shndx == SHN_XINDEX)
-	    error (EXIT_FAILURE, 0, gettext ("\
-section index too large in dynamic symbol table"));
-
-	  /* We do not add the symbol to the dynamic symbol table if
-
-	     - the symbol is for a file
-	     - it is not externally visible (internal, hidden)
-	     - export_all_dynamic is not set and the symbol is only defined
-	       in the executable (i.e., it is defined, but not (also) in DSO)
-
-	     Set symstrent[cnt] to NULL in case an entry is ignored.  */
-	  if (XELF_ST_TYPE (sym->st_info) == STT_FILE
-	      || XELF_ST_VISIBILITY (sym->st_other) == STV_INTERNAL
-	      || XELF_ST_VISIBILITY (sym->st_other) == STV_HIDDEN
-	      || (!ld_state.export_all_dynamic
-		  && !ndxtosym[cnt]->in_dso && ndxtosym[cnt]->defined))
-	    {
-	      symstrent[cnt] = NULL;
-	      continue;
-	    }
-
-	  /* Store the index of the symbol in the dynamic symbol
-	     table.  This is a preliminary value in case we use the
-	     GNU-style hash table.  */
-	  ndxtosym[cnt]->outdynsymidx = nsym_dyn;
-
-	  /* Create a new string table entry.  */
-	  const char *str = ndxtosym[cnt]->name;
-	  symstrent[cnt] = ebl_strtabadd (dynstrtab, str, 0);
-	  if (GENERATE_SYSV_HASH)
-	    hashcodes[nsym_dyn] = elf_hash (str);
-	  if (GENERATE_GNU_HASH)
-	    gnuhashcodes[nsym_dyn] = elf_gnu_hash (str);
-	  ++nsym_dyn;
-	}
-
-      if (ld_state.file_type != relocatable_file_type)
-	{
-	  /* Finalize the dynamic string table.  */
-	  ebl_strtabfinalize (dynstrtab, dynstrdata);
-
-	  assert (ld_state.hashscnidx != 0 || ld_state.gnuhashscnidx != 0);
-
-	  /* Create the GNU-style hash table.  */
-	  if (GENERATE_GNU_HASH)
-	    create_gnu_hash (nsym_local, nsym, nsym_dyn, gnuhashcodes);
-
-	  /* Create the SysV-style hash table.  This has to happen
-	     after the GNU-style table is created since
-	     CREATE-GNU-HASH might reorder the dynamic symbol table.  */
-	  if (GENERATE_SYSV_HASH)
-	    create_hash (nsym_local, nsym, nsym_dyn, hashcodes);
-	}
-
-	  /* Add the version information.  */
-      if (versymdata != NULL)
-	for (cnt = nsym_local; cnt < nsym; ++cnt)
-	  if (symstrent[cnt] != NULL)
-	    {
-	      struct symbol *symp = ndxtosym[cnt];
-
-	      /* Synthetic symbols (i.e., those with no file attached)
-		 have no version information.  */
-	      if (symp->file != NULL && symp->file->verdefdata != NULL)
-		{
-		  GElf_Versym versym;
-
-		  gelf_getversym (symp->file->versymdata, symp->symidx,
-				  &versym);
-
-		  (void) gelf_update_versym (versymdata, symp->outdynsymidx,
-					     &symp->file->verdefused[versym]);
-		}
-	      else
-		{
-		  /* XXX Add support for version definitions.  */
-		  GElf_Versym global = VER_NDX_GLOBAL;
-		  (void) gelf_update_versym (versymdata, nsym_dyn, &global);
-		}
-	    }
-
-      /* Update the information about the symbol section.  */
-      if (versymdata != NULL)
-	{
-	  /* Correct the size now that we know how many entries the
-	     dynamic symbol table has.  */
-	  versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF,
-					   nsym_dyn);
-
-	  /* Add the reference to the symbol table.  */
-	  xelf_getshdr (versymscn, shdr);
-	  assert (shdr != NULL);
-
-	  shdr->sh_link = ld_state.dynsymscnidx;
-
-	  (void) xelf_update_shdr (versymscn, shdr);
-	}
-    }
-
-  if (ld_state.file_type != relocatable_file_type)
-    {
-      /* Now put the names in.  */
-      for (cnt = nsym_local; cnt < nsym; ++cnt)
-	if (symstrent[cnt] != NULL)
-	  {
-	    XElf_Sym_vardef (sym);
-	    size_t dynidx = ndxtosym[cnt]->outdynsymidx;
-
-#if NATIVE_ELF != 0
-	    XElf_Sym *osym;
-	    memcpy (xelf_getsym (dynsymdata, dynidx, sym),
-		    xelf_getsym (symdata, cnt, osym),
-		    sizeof (XElf_Sym));
-#else
-	    xelf_getsym (symdata, cnt, sym);
-	    assert (sym != NULL);
-#endif
-
-	    sym->st_name = ebl_strtaboffset (symstrent[cnt]);
-
-	    (void) xelf_update_sym (dynsymdata, dynidx, sym);
-	  }
-
-      free (hashcodes);
-
-      /* Create the required version section.  */
-      if (ld_state.verneedscnidx != 0)
-	{
-	  Elf_Scn *verneedscn;
-	  Elf_Data *verneeddata;
-	  struct usedfiles *runp;
-	  size_t verneed_size = xelf_fsize (ld_state.outelf, ELF_T_VNEED, 1);
-	  size_t vernaux_size = xelf_fsize (ld_state.outelf, ELF_T_VNAUX, 1);
-	  size_t offset;
-	  int ntotal;
-
-	  verneedscn = elf_getscn (ld_state.outelf, ld_state.verneedscnidx);
-	  xelf_getshdr (verneedscn, shdr);
-	  verneeddata = elf_newdata (verneedscn);
-	  if (shdr == NULL || verneeddata == NULL)
-	    error (EXIT_FAILURE, 0,
-		   gettext ("cannot create versioning data: %s"),
-		   elf_errmsg (-1));
-
-	  verneeddata->d_size = (ld_state.nverdeffile * verneed_size
-				 + ld_state.nverdefused * vernaux_size);
-	  verneeddata->d_buf = xmalloc (verneeddata->d_size);
-	  verneeddata->d_type = ELF_T_VNEED;
-	  verneeddata->d_align = xelf_fsize (ld_state.outelf, ELF_T_WORD, 1);
-	  verneeddata->d_off = 0;
-
-	  offset = 0;
-	  ntotal = ld_state.nverdeffile;
-	  runp = ld_state.dsofiles->next;
-	  do
-	    {
-	      offset = create_verneed_data (offset, verneeddata, runp,
-					    &ntotal);
-	      runp = runp->next;
-	    }
-	  while (ntotal > 0 && runp != ld_state.dsofiles->next);
-
-	  if (ntotal > 0)
-	    {
-	      runp = ld_state.needed->next;
-	      do
-		{
-		  offset = create_verneed_data (offset, verneeddata, runp,
-						&ntotal);
-		  runp = runp->next;
-		}
-	      while (ntotal > 0 && runp != ld_state.needed->next);
-	    }
-
-	  assert (offset == verneeddata->d_size);
-
-	  /* Add the needed information to the section header.  */
-	  shdr->sh_link = ld_state.dynstrscnidx;
-	  shdr->sh_info = ld_state.nverdeffile;
-	  (void) xelf_update_shdr (verneedscn, shdr);
-	}
-
-      /* Adjust the section size.  */
-      dynsymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_SYM, nsym_dyn);
-      if (versymdata != NULL)
-	versymdata->d_size = xelf_fsize (ld_state.outelf, ELF_T_HALF,
-					 nsym_dyn);
-
-      /* Add the remaining information to the section header.  */
-      xelf_getshdr (dynsymscn, shdr);
-      /* There is always exactly one local symbol.  */
-      shdr->sh_info = 1;
-      /* Reference the string table.  */
-      shdr->sh_link = ld_state.dynstrscnidx;
-      /* Write the updated info back.  */
-      (void) xelf_update_shdr (dynsymscn, shdr);
-    }
-
-  /* We don't need the string table anymore.  */
-  free (symstrent);
-
-  /* Remember the total number of symbols in the dynamic symbol table.  */
-  ld_state.ndynsym = nsym_dyn;
-
-  /* Fill in the section header information.  */
-  symscn = elf_getscn (ld_state.outelf, ld_state.symscnidx);
-  xelf_getshdr (symscn, shdr);
-  if (shdr == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create symbol table for output file: %s"),
-	   elf_errmsg (-1));
-
-  shdr->sh_type = SHT_SYMTAB;
-  shdr->sh_link = ld_state.strscnidx;
-  shdr->sh_info = nsym_local;
-  shdr->sh_entsize = xelf_fsize (ld_state.outelf, ELF_T_SYM, 1);
-
-  (void) xelf_update_shdr (symscn, shdr);
-
-
-  /* Add names for the generated sections.  */
-  if (ld_state.symscnidx != 0)
-      symtab_ent = ebl_strtabadd (ld_state.shstrtab, ".symtab", 8);
-  if (ld_state.xndxscnidx != 0)
-    xndx_ent = ebl_strtabadd (ld_state.shstrtab, ".symtab_shndx", 14);
-  if (ld_state.strscnidx != 0)
-    strtab_ent = ebl_strtabadd (ld_state.shstrtab, ".strtab", 8);
-  /* At this point we would have to test for failures in the
-     allocation.  But we skip this.  First, the problem will be caught
-     later when doing more allocations for the section header table.
-     Even if this would not be the case all that would happen is that
-     the section names are empty.  The binary would still be usable if
-     it is an executable or a DSO.  Not adding the test here saves
-     quite a bit of code.  */
-
-
-  /* Finally create the section for the section header string table.  */
-  shstrtab_scn = elf_newscn (ld_state.outelf);
-  shstrtab_ndx = elf_ndxscn (shstrtab_scn);
-  if (unlikely (shstrtab_ndx == SHN_UNDEF))
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create section header string section: %s"),
-	   elf_errmsg (-1));
-
-  /* Add the name of the section to the string table.  */
-  shstrtab_ent = ebl_strtabadd (ld_state.shstrtab, ".shstrtab", 10);
-  if (unlikely (shstrtab_ent == NULL))
-    error (EXIT_FAILURE, errno,
-	   gettext ("cannot create section header string section"));
-
-  /* Finalize the section header string table.  */
-  data = elf_newdata (shstrtab_scn);
-  if (data == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create section header string section: %s"),
-	   elf_errmsg (-1));
-  ebl_strtabfinalize (ld_state.shstrtab, data);
-
-  /* Now we know the string offsets for all section names.  */
-  for (cnt = 0; cnt < ld_state.nallsections; ++cnt)
-    if (ld_state.allsections[cnt]->scnidx != 0)
-      {
-	Elf_Scn *scn;
-
-	scn = elf_getscn (ld_state.outelf, ld_state.allsections[cnt]->scnidx);
-
-	xelf_getshdr (scn, shdr);
-	assert (shdr != NULL);
-
-	shdr->sh_name = ebl_strtaboffset (ld_state.allsections[cnt]->nameent);
-
-	if (xelf_update_shdr (scn, shdr) == 0)
-	  assert (0);
-      }
-
-  /* Add the names for the generated sections to the respective
-     section headers.  */
-  if (symtab_ent != NULL)
-    {
-      Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.symscnidx);
-
-      xelf_getshdr (scn, shdr);
-      /* This cannot fail, we already accessed the header before.  */
-      assert (shdr != NULL);
-
-      shdr->sh_name = ebl_strtaboffset (symtab_ent);
-
-      (void) xelf_update_shdr (scn, shdr);
-    }
-  if (xndx_ent != NULL)
-    {
-      Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.xndxscnidx);
-
-      xelf_getshdr (scn, shdr);
-      /* This cannot fail, we already accessed the header before.  */
-      assert (shdr != NULL);
-
-      shdr->sh_name = ebl_strtaboffset (xndx_ent);
-
-      (void) xelf_update_shdr (scn, shdr);
-    }
-  if (strtab_ent != NULL)
-    {
-      Elf_Scn *scn = elf_getscn (ld_state.outelf, ld_state.strscnidx);
-
-      xelf_getshdr (scn, shdr);
-      /* This cannot fail, we already accessed the header before.  */
-      assert (shdr != NULL);
-
-      shdr->sh_name = ebl_strtaboffset (strtab_ent);
-
-      (void) xelf_update_shdr (scn, shdr);
-    }
-
-  /* And the section header table section itself.  */
-  xelf_getshdr (shstrtab_scn, shdr);
-  if (shdr == NULL)
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create section header string section: %s"),
-	   elf_errmsg (-1));
-
-  shdr->sh_name = ebl_strtaboffset (shstrtab_ent);
-  shdr->sh_type = SHT_STRTAB;
-
-  if (unlikely (xelf_update_shdr (shstrtab_scn, shdr) == 0))
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot create section header string section: %s"),
-	   elf_errmsg (-1));
-
-
-  /* Add the correct section header info to the section group sections.  */
-  groups = ld_state.groups;
-  while (groups != NULL)
-    {
-      Elf_Scn *scn = elf_getscn (ld_state.outelf, groups->outscnidx);
-      xelf_getshdr (scn, shdr);
-      assert (shdr != NULL);
-
-      shdr->sh_name = ebl_strtaboffset (groups->nameent);
-      shdr->sh_type = SHT_GROUP;
-      shdr->sh_flags = 0;
-      shdr->sh_link = ld_state.symscnidx;
-      shdr->sh_entsize = sizeof (Elf32_Word);
-
-      /* Determine the index for the signature symbol.  */
-      Elf32_Word si
-	= groups->symbol->file->symindirect[groups->symbol->symidx];
-      if (si == 0)
-	{
-	  assert (groups->symbol->file->symref[groups->symbol->symidx]
-		  != NULL);
-	  si = groups->symbol->file->symref[groups->symbol->symidx]->outsymidx;
-	  assert (si != 0);
-	}
-      shdr->sh_info = ld_state.dblindirect[si];
-
-      (void) xelf_update_shdr (scn, shdr);
-
-      struct scngroup *oldp = groups;
-      groups = groups->next;
-      free (oldp);
-    }
-
-
-  if (ld_state.file_type != relocatable_file_type)
-    {
-      /* Every executable needs a program header.  The number of entries
-	 varies.  One exists for each segment.  Each SHT_NOTE section gets
-	 one, too.  For dynamically linked executables we have to create
-	 one for the program header, the interpreter, and the dynamic
-	 section.  First count the number of segments.
-
-	 XXX Determine whether the segment is non-empty.  */
-      size_t nphdr = 0;
-
-      /* We always add a PT_GNU_stack entry.  */
-      ++nphdr;
-
-      struct output_segment *segment = ld_state.output_segments;
-      while (segment != NULL)
-	{
-	  ++nphdr;
-	  segment = segment->next;
-	}
-
-      /* Add the number of SHT_NOTE sections.  We counted them earlier.  */
-      nphdr += ld_state.nnotesections;
-
-      /* If we create a DSO or the file is linked against DSOs we have
-	 at least one more entry: DYNAMIC.  If an interpreter is
-	 specified we add PHDR and INTERP, too.  */
-      if (dynamically_linked_p ())
-	{
-	  ++nphdr;
-
-	  if (ld_state.interp != NULL || ld_state.file_type != dso_file_type)
-	    nphdr += 2;
-	}
-
-      /* If we need a TLS segment we need an entry for that.  */
-      if (ld_state.need_tls)
-	++nphdr;
-
-      /* Create the program header structure.  */
-      XElf_Phdr_vardef (phdr);
-      if (xelf_newphdr (ld_state.outelf, nphdr) == 0)
-	error (EXIT_FAILURE, 0, gettext ("cannot create program header: %s"),
-	       elf_errmsg (-1));
-
-
-      /* Determine the section sizes and offsets.  We have to do this
-	 to be able to determine the memory layout (which normally
-	 differs from the file layout).  */
-      if (elf_update (ld_state.outelf, ELF_C_NULL) == -1)
-	error (EXIT_FAILURE, 0, gettext ("while determining file layout: %s"),
-	       elf_errmsg (-1));
-
-
-      /* Now determine the memory addresses of all the sections and
-	 segments.  */
-      Elf32_Word nsec = 0;
-      Elf_Scn *scn = elf_getscn (ld_state.outelf,
-				 ld_state.allsections[nsec]->scnidx);
-      xelf_getshdr (scn, shdr);
-      assert (shdr != NULL);
-
-      /* The address we start with is the offset of the first (not
-	 zeroth) section.  */
-      XElf_Addr addr = shdr->sh_offset;
-      XElf_Addr tls_offset = 0;
-      XElf_Addr tls_start = ~((XElf_Addr) 0);
-      XElf_Addr tls_end = 0;
-      XElf_Off tls_filesize = 0;
-      XElf_Addr tls_align = 0;
-
-      /* The index of the first loadable segment.  */
-      nphdr = 0;
-      if (dynamically_linked_p ())
-	{
-	  ++nphdr;
-	  if (ld_state.interp != NULL
-	      || ld_state.file_type != dso_file_type)
-	    nphdr += 2;
-	}
-
-      segment = ld_state.output_segments;
-      while (segment != NULL)
-	{
-	  struct output_rule *orule;
-	  bool first_section = true;
-	  XElf_Off nobits_size = 0;
-	  XElf_Off memsize = 0;
-
-	  /* The minimum alignment is a page size.  */
-	  segment->align = ld_state.pagesize;
-
-	  for (orule = segment->output_rules; orule != NULL;
-	       orule = orule->next)
-	    if (orule->tag == output_section)
-	      {
-		/* See whether this output rule corresponds to the next
-		   section.  Yes, this is a pointer comparison.  */
-		if (ld_state.allsections[nsec]->name
-		    != orule->val.section.name)
-		  /* No, ignore this output rule.  */
-		  continue;
-
-		/* We assign addresses only in segments which are actually
-		   loaded.  */
-		if (segment->mode != 0)
-		  {
-		    /* Adjust the offset of the input sections.  */
-		    struct scninfo *isect;
-		    struct scninfo *first;
-
-		    isect = first = ld_state.allsections[nsec]->last;
-		    if (isect != NULL)
-		      do
-			isect->offset += addr;
-		      while ((isect = isect->next) != first);
-
-		    /* Set the address of current section.  */
-		    shdr->sh_addr = addr;
-
-		    /* Write the result back.  */
-		    (void) xelf_update_shdr (scn, shdr);
-
-		    /* Remember the address.  */
-		    ld_state.allsections[nsec]->addr = addr;
-
-		    /* Handle TLS sections.  */
-		    if (unlikely (shdr->sh_flags & SHF_TLS))
-		      {
-			if (tls_start > addr)
-			  {
-			    tls_start = addr;
-			    tls_offset = shdr->sh_offset;
-			  }
-			if (tls_end < addr + shdr->sh_size)
-			  tls_end = addr + shdr->sh_size;
-			if (shdr->sh_type != SHT_NOBITS)
-			  tls_filesize += shdr->sh_size;
-			if (shdr->sh_addralign > tls_align)
-			  tls_align = shdr->sh_addralign;
-		      }
-		  }
-
-		if (first_section)
-		  {
-		    /* The first segment starts at offset zero.  */
-		    if (segment == ld_state.output_segments)
-		      {
-			segment->offset = 0;
-			segment->addr = addr - shdr->sh_offset;
-		      }
-		    else
-		      {
-			segment->offset = shdr->sh_offset;
-			segment->addr = addr;
-		      }
-
-		    /* Determine the maximum alignment requirement.  */
-		    segment->align = MAX (segment->align, shdr->sh_addralign);
-
-		    first_section = false;
-		  }
-
-		/* NOBITS TLS sections are not laid out in address space
-		   along with the other sections.  */
-		if (shdr->sh_type != SHT_NOBITS
-		    || (shdr->sh_flags & SHF_TLS) == 0)
-		  {
-		    memsize = (shdr->sh_offset - segment->offset
-			       + shdr->sh_size);
-		    if (nobits_size != 0 && shdr->sh_type != SHT_NOTE)
-		      error (EXIT_FAILURE, 0, gettext ("\
-internal error: non-nobits section follows nobits section"));
-		    if (shdr->sh_type == SHT_NOBITS)
-		      nobits_size += shdr->sh_size;
-		  }
-
-		/* Determine the new address which is computed using
-		   the difference of the offsets on the sections.  Note
-		   that this assumes that the sections following each
-		   other in the section header table are also
-		   consecutive in the file.  This is true here because
-		   libelf constructs files this way.  */
-		XElf_Off oldoff = shdr->sh_offset;
-
-		if (++nsec >= ld_state.nallsections)
-		  break;
-
-		scn = elf_getscn (ld_state.outelf,
-				  ld_state.allsections[nsec]->scnidx);
-		xelf_getshdr (scn, shdr);
-		assert (shdr != NULL);
-
-		/* This is the new address resulting from the offsets
-		   in the file.  */
-		assert (oldoff <= shdr->sh_offset);
-		addr += shdr->sh_offset - oldoff;
-	      }
-	    else
-	      {
-		assert (orule->tag == output_assignment);
-
-		if (strcmp (orule->val.assignment->variable, ".") == 0)
-		  /* This is a change of the address.  */
-		  addr = eval_expression (orule->val.assignment->expression,
-					  addr);
-		else if (orule->val.assignment->sym != NULL)
-		  {
-		    /* This symbol is used.  Update the symbol table
-		       entry.  */
-		    XElf_Sym_vardef (sym);
-		    size_t idx;
-
-		    /* Note that we do not have to use
-		       xelf_getsymshndx since we only update the
-		       symbol address, not the section
-		       information.  */
-		    idx = dblindirect[orule->val.assignment->sym->outsymidx];
-		    xelf_getsym (symdata, idx, sym);
-		    sym->st_value = addr;
-		    (void) xelf_update_sym (symdata, idx, sym);
-
-		    idx = orule->val.assignment->sym->outdynsymidx;
-		    if (idx != 0)
-		      {
-			assert (dynsymdata != NULL);
-			xelf_getsym (dynsymdata, idx, sym);
-			sym->st_value = addr;
-			(void) xelf_update_sym (dynsymdata, idx, sym);
-		      }
-		  }
-	      }
-
-	  /* Store the segment parameter for loadable segments.  */
-	  if (segment->mode != 0)
-	    {
-	      xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr);
-
-	      phdr->p_type = PT_LOAD;
-	      phdr->p_offset = segment->offset;
-	      phdr->p_vaddr = segment->addr;
-	      phdr->p_paddr = phdr->p_vaddr;
-	      phdr->p_filesz = memsize - nobits_size;
-	      phdr->p_memsz = memsize;
-	      phdr->p_flags = segment->mode;
-	      phdr->p_align = segment->align;
-
-	      (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr);
-	      ++nphdr;
-	    }
-
-	  segment = segment->next;
-	}
-
-      /* Create the other program header entries.  */
-      xelf_getehdr (ld_state.outelf, ehdr);
-      assert (ehdr != NULL);
-
-      /* Add the TLS information.  */
-      if (ld_state.need_tls)
-	{
-	  xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr);
-	  phdr->p_type = PT_TLS;
-	  phdr->p_offset = tls_offset;
-	  phdr->p_vaddr = tls_start;
-	  phdr->p_paddr = tls_start;
-	  phdr->p_filesz = tls_filesize;
-	  phdr->p_memsz = tls_end - tls_start;
-	  phdr->p_flags = PF_R;
-	  phdr->p_align = tls_align;
-	  ld_state.tls_tcb = tls_end;
-	  ld_state.tls_start = tls_start;
-
-	  (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr);
-	  ++nphdr;
-	}
-
-      /* Add the stack information.  */
-      xelf_getphdr_ptr (ld_state.outelf, nphdr, phdr);
-      phdr->p_type = PT_GNU_STACK;
-      phdr->p_offset = 0;
-      phdr->p_vaddr = 0;
-      phdr->p_paddr = 0;
-      phdr->p_filesz = 0;
-      phdr->p_memsz = 0;
-      phdr->p_flags = (PF_R | PF_W
-		       | (ld_state.execstack == execstack_true ? PF_X : 0));
-      phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
-      (void) xelf_update_phdr (ld_state.outelf, nphdr, phdr);
-      ++nphdr;
-
-
-      /* Adjust the addresses in the address fields of the symbol
-	 records according to the load addresses of the sections.  */
-      if (ld_state.need_symtab)
-	for (cnt = 1; cnt < nsym; ++cnt)
-	  {
-	    XElf_Sym_vardef (sym);
-	    Elf32_Word shndx;
-
-	    xelf_getsymshndx (symdata, xndxdata, cnt, sym, shndx);
-	    assert (sym != NULL);
-
-	    if (sym->st_shndx != SHN_XINDEX)
-	      shndx = sym->st_shndx;
-
-	    if ((shndx > SHN_UNDEF && shndx < SHN_LORESERVE)
-		|| shndx > SHN_HIRESERVE)
-	      {
-		/* Note we subtract 1 from the section index since ALLSECTIONS
-		   does not store the dummy section with offset zero.  */
-		sym->st_value += ld_state.allsections[shndx - 1]->addr;
-
-		/* We don't have to use 'xelf_update_symshndx' since the
-		   section number doesn't change.  */
-		(void) xelf_update_sym (symdata, cnt, sym);
-	      }
-	  }
-
-      if (ld_state.need_dynsym)
-	for (cnt = 1; cnt < nsym_dyn; ++cnt)
-	  {
-	    XElf_Sym_vardef (sym);
-
-	    xelf_getsym (dynsymdata, cnt, sym);
-	    assert (sym != NULL);
-
-	    if (sym->st_shndx > SHN_UNDEF && sym->st_shndx < SHN_LORESERVE)
-	      {
-		/* Note we subtract 1 from the section index since ALLSECTIONS
-		   does not store the dummy section with offset zero.  */
-		sym->st_value += ld_state.allsections[sym->st_shndx - 1]->addr;
-
-		/* We don't have to use 'xelf_update_symshndx' since the
-		   section number doesn't change.  */
-		(void) xelf_update_sym (dynsymdata, cnt, sym);
-	      }
-	  }
-
-      /* Now is a good time to determine the values of all the symbols
-	 we encountered.  */
-      // XXX This loop is very inefficient.  The hash tab iterator also
-      // returns all symbols in DSOs.
-      struct symbol *se;
-      void *p = NULL;
-      while ((se = ld_symbol_tab_iterate (&ld_state.symbol_tab, &p)) != NULL)
-	if (! se->in_dso)
-	  {
-	    XElf_Sym_vardef (sym);
-
-	    addr = 0;
-
-	    if (se->outdynsymidx != 0)
-	      {
-		xelf_getsym (dynsymdata, se->outdynsymidx, sym);
-		assert (sym != NULL);
-		addr = sym->st_value;
-	      }
-	    else if (se->outsymidx != 0)
-	      {
-		assert (dblindirect[se->outsymidx] != 0);
-		xelf_getsym (symdata, dblindirect[se->outsymidx], sym);
-		assert (sym != NULL);
-		addr = sym->st_value;
-	      }
-	    else
-	      abort ();
-
-	    se->merge.value = addr;
-	  }
-
-      /* Complete the header of the .rel.dyn/.rela.dyn section.  Point
-	 to the symbol table.  The sh_info field is left zero since
-	 there is no specific section the contained relocations are
-	 for.  */
-      if (ld_state.reldynscnidx != 0)
-	{
-	  assert (ld_state.dynsymscnidx != 0);
-	  scn = elf_getscn (ld_state.outelf, ld_state.reldynscnidx);
-	  xelf_getshdr (scn, shdr);
-	  assert (shdr != NULL);
-
-	  shdr->sh_link = ld_state.dynsymscnidx;
-
-	  (void) xelf_update_shdr (scn, shdr);
-	}
-
-      /* Fill in the dynamic segment/section.  */
-      if (dynamically_linked_p ())
-	{
-	  Elf_Scn *outscn;
-
-	  int idx = 0;
-	  if (ld_state.interp != NULL || ld_state.file_type != dso_file_type)
-	    {
-	      assert (ld_state.interpscnidx != 0);
-	      xelf_getshdr (elf_getscn (ld_state.outelf,
-					ld_state.interpscnidx), shdr);
-	      assert (shdr != NULL);
-
-	      xelf_getphdr_ptr (ld_state.outelf, idx, phdr);
-	      phdr->p_type = PT_PHDR;
-	      phdr->p_offset = ehdr->e_phoff;
-	      phdr->p_vaddr = ld_state.output_segments->addr + phdr->p_offset;
-	      phdr->p_paddr = phdr->p_vaddr;
-	      phdr->p_filesz = ehdr->e_phnum * ehdr->e_phentsize;
-	      phdr->p_memsz = phdr->p_filesz;
-	      phdr->p_flags = 0;	/* No need to set PF_R or so.  */
-	      phdr->p_align = xelf_fsize (ld_state.outelf, ELF_T_ADDR, 1);
-
-	      (void) xelf_update_phdr (ld_state.outelf, idx, phdr);
-	      ++idx;
-
-	      /* The interpreter string.  */
-	      xelf_getphdr_ptr (ld_state.outelf, idx, phdr);
-	      phdr->p_type = PT_INTERP;
-	      phdr->p_offset = shdr->sh_offset;
-	      phdr->p_vaddr = shdr->sh_addr;
-	      phdr->p_paddr = phdr->p_vaddr;
-	      phdr->p_filesz = shdr->sh_size;
-	      phdr->p_memsz = phdr->p_filesz;
-	      phdr->p_flags = 0;	/* No need to set PF_R or so.  */
-	      phdr->p_align = 1;	/* It's a string.  */
-
-	      (void) xelf_update_phdr (ld_state.outelf, idx, phdr);
-	      ++idx;
-	    }
-
-	  /* The pointer to the dynamic section.  We this we need to
-	     get the information for the dynamic section first.  */
-	  assert (ld_state.dynamicscnidx);
-	  outscn = elf_getscn (ld_state.outelf, ld_state.dynamicscnidx);
-	  xelf_getshdr (outscn, shdr);
-	  assert (shdr != NULL);
-
-	  xelf_getphdr_ptr (ld_state.outelf, idx, phdr);
-	  phdr->p_type = PT_DYNAMIC;
-	  phdr->p_offset = shdr->sh_offset;
-	  phdr->p_vaddr = shdr->sh_addr;
-	  phdr->p_paddr = phdr->p_vaddr;
-	  phdr->p_filesz = shdr->sh_size;
-	  phdr->p_memsz = phdr->p_filesz;
-	  phdr->p_flags = 0;		/* No need to set PF_R or so.  */
-	  phdr->p_align = shdr->sh_addralign;
-
-	  (void) xelf_update_phdr (ld_state.outelf, idx, phdr);
-
-	  /* Fill in the reference to the .dynstr section.  */
-	  assert (ld_state.dynstrscnidx != 0);
-	  shdr->sh_link = ld_state.dynstrscnidx;
-	  (void) xelf_update_shdr (outscn, shdr);
-
-	  /* And fill the remaining entries.  */
-	  Elf_Data *dyndata = elf_getdata (outscn, NULL);
-	  assert (dyndata != NULL);
-
-	  /* Add the DT_NEEDED entries.  */
-	  if (ld_state.ndsofiles > 0)
-	    {
-	      struct usedfiles *runp = ld_state.dsofiles->next;
-
-	      do
-		if (runp->used || !runp->as_needed)
-		  {
-		    /* Add the position-dependent flag if necessary.  */
-		    if (runp->lazyload)
-		      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-					 DT_POSFLAG_1, DF_P1_LAZYLOAD);
-
-		    new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				       DT_NEEDED,
-				       ebl_strtaboffset (runp->sonameent));
-		  }
-	      while ((runp = runp->next) != ld_state.dsofiles->next);
-	    }
-
-	  /* We can finish the DT_RUNPATH/DT_RPATH entries now.  */
-	  if (ld_state.rxxpath_strent != NULL)
-	    new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-			       ld_state.rxxpath_tag,
-			       ebl_strtaboffset (ld_state.rxxpath_strent));
-
-	  /* Reference to initialization and finalization functions.  */
-	  // XXX This code depends on symbol table being relocated.
-	  if (ld_state.init_symbol != NULL)
-	    {
-	      XElf_Sym_vardef (sym);
-
-	      if (ld_state.need_symtab)
-		xelf_getsym (symdata,
-			     dblindirect[ld_state.init_symbol->outsymidx],
-			     sym);
-	      else
-		xelf_getsym (dynsymdata, ld_state.init_symbol->outdynsymidx,
-			     sym);
-	      assert (sym != NULL);
-
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_INIT, sym->st_value);
-	    }
-	  if (ld_state.fini_symbol != NULL)
-	    {
-	      XElf_Sym_vardef (sym);
-
-	      if (ld_state.need_symtab)
-		xelf_getsym (symdata,
-			     dblindirect[ld_state.fini_symbol->outsymidx],
-			     sym);
-	      else
-		xelf_getsym (dynsymdata, ld_state.fini_symbol->outdynsymidx,
-			     sym);
-	      assert (sym != NULL);
-
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_FINI, sym->st_value);
-	    }
-	  // XXX Support init,fini,preinit arrays
-
-	  /* The hash table which comes with dynamic symbol table.  */
-	  xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.hashscnidx),
-			shdr);
-	  assert (shdr != NULL);
-	  new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_HASH,
-			     shdr->sh_addr);
-
-	  /* Reference to the symbol table section.  */
-	  assert (ld_state.dynsymscnidx != 0);
-	  xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.dynsymscnidx),
-			shdr);
-	  assert (shdr != NULL);
-	  new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_SYMTAB,
-			     shdr->sh_addr);
-
-	  new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_SYMENT,
-			     xelf_fsize (ld_state.outelf, ELF_T_SYM, 1));
-
-	  /* And the string table which comes with it.  */
-	  xelf_getshdr (elf_getscn (ld_state.outelf, ld_state.dynstrscnidx),
-			shdr);
-	  assert (shdr != NULL);
-	  new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_STRTAB,
-			     shdr->sh_addr);
-
-	  new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_STRSZ,
-			     shdr->sh_size);
-
-	  /* Add the entries related to the .plt.  */
-	  if (ld_state.nplt > 0)
-	    {
-	      // XXX Make this work if there is no PLT
-	      xelf_getshdr (elf_getscn (ld_state.outelf,
-					ld_state.gotpltscnidx), shdr);
-	      assert (shdr != NULL);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 // XXX This should probably be machine
-				 // dependent.
-				 DT_PLTGOT, shdr->sh_addr);
-
-	      xelf_getshdr (elf_getscn (ld_state.outelf,
-					ld_state.pltrelscnidx), shdr);
-	      assert (shdr != NULL);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_PLTRELSZ, shdr->sh_size);
-
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_JMPREL, shdr->sh_addr);
-
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_PLTREL, REL_TYPE (statep));
-	    }
-
-	  if (ld_state.relsize_total > 0)
-	    {
-	      int rel = REL_TYPE (statep);
-	      xelf_getshdr (elf_getscn (ld_state.outelf,
-					ld_state.reldynscnidx), shdr);
-	      assert (shdr != NULL);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 rel, shdr->sh_addr);
-
-	      /* Trick ahead.  Use arithmetic to get the right tag.
-		 We check the validity of this assumption in the asserts.  */
-	      assert (DT_RELASZ - DT_RELA == 1);
-	      assert (DT_RELSZ - DT_REL == 1);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 rel + 1, shdr->sh_size);
-
-	      /* Similar for the entry size tag.  */
-	      assert (DT_RELAENT - DT_RELA == 2);
-	      assert (DT_RELENT - DT_REL == 2);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 rel + 2,
-				 rel == DT_REL
-				 ? xelf_fsize (ld_state.outelf, ELF_T_REL, 1)
-				 : xelf_fsize (ld_state.outelf, ELF_T_RELA,
-					       1));
-	    }
-
-	  if (ld_state.verneedscnidx != 0)
-	    {
-	      xelf_getshdr (elf_getscn (ld_state.outelf,
-					ld_state.verneedscnidx), shdr);
-	      assert (shdr != NULL);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_VERNEED, shdr->sh_addr);
-
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_VERNEEDNUM, ld_state.nverdeffile);
-	    }
-
-	  if (ld_state.versymscnidx != 0)
-	    {
-	      xelf_getshdr (elf_getscn (ld_state.outelf,
-					ld_state.versymscnidx), shdr);
-	      assert (shdr != NULL);
-	      new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-				 DT_VERSYM, shdr->sh_addr);
-	    }
-
-	  /* We always create the DT_DEBUG entry.  */
-	  new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_DEBUG, 0);
-	  assert (ld_state.ndynamic_filled < ld_state.ndynamic);
-
-	  /* Add the flag words if necessary.  */
-	  if (ld_state.dt_flags != 0)
-	    new_dynamic_entry (dyndata, ld_state.ndynamic_filled++, DT_FLAGS,
-			       ld_state.dt_flags);
-
-	  /* Create entry for the DT_FLAGS_1 flag.  */
-	  if (ld_state.dt_flags_1 != 0)
-	    new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-			       DT_FLAGS_1, ld_state.dt_flags_1);
-
-	  /* Create entry for the DT_FEATURE_1 flag.  */
-	  if (ld_state.dt_feature_1 != 0)
-	    new_dynamic_entry (dyndata, ld_state.ndynamic_filled++,
-			       DT_FEATURE_1, ld_state.dt_feature_1);
-
-	  assert (ld_state.ndynamic_filled <= ld_state.ndynamic);
-	}
-    }
-
-
-  // XXX The following code isn't nice.  We use two different
-  // mechanisms to handle relocations, one for relocatable files, one
-  // for executables and DSOs.  Maybe this is the best method but also
-  // maybe it can be somewhat unified.
-
-  /* Now that we created the symbol table we can add the reference to
-     it in the sh_link field of the section headers of the relocation
-     sections.  */
-  while (rellist != NULL)
-    {
-      assert (ld_state.file_type == relocatable_file_type);
-      Elf_Scn *outscn;
-
-      outscn = elf_getscn (ld_state.outelf, rellist->scnidx);
-      xelf_getshdr (outscn, shdr);
-      /* This must not fail since we did it before.  */
-      assert (shdr != NULL);
-
-      /* Remember the symbol table which belongs to the relocation section.  */
-      shdr->sh_link = ld_state.symscnidx;
-
-      /* And the reference to the section which is relocated by this
-	 relocation section.  We use the info from the first input
-	 section but all records should have the same information.  */
-      shdr->sh_info =
-	rellist->scninfo->fileinfo->scninfo[SCNINFO_SHDR (rellist->scninfo->shdr).sh_info].outscnndx;
-
-
-      /* Perform the actual relocations.  We only have to adjust
-	 offsets and symbol indices.  */
-      RELOCATE_SECTION (statep, outscn, rellist->scninfo, dblindirect);
-
-      /* Store the changes.  */
-      (void) xelf_update_shdr (outscn, shdr);
-
-      /* Up to the next relocation section.  */
-      rellist = rellist->next;
-    }
-
-  if (ld_state.rellist != NULL)
-    {
-      assert (ld_state.file_type != relocatable_file_type);
-      /* Create the relocations for the output file.  */
-      CREATE_RELOCATIONS (statep, dblindirect);
-    }
-
-
-  /* We need the ELF header once more.  */
-  xelf_getehdr (ld_state.outelf, ehdr);
-  assert (ehdr != NULL);
-
-  /* Set the section header string table index.  */
-  if (likely (shstrtab_ndx < SHN_HIRESERVE)
-      && likely (shstrtab_ndx != SHN_XINDEX))
-    ehdr->e_shstrndx = shstrtab_ndx;
-  else
-    {
-      /* We have to put the section index in the sh_link field of the
-	 zeroth section header.  */
-      Elf_Scn *scn = elf_getscn (ld_state.outelf, 0);
-
-      xelf_getshdr (scn, shdr);
-      if (unlikely (shdr == NULL))
-	error (EXIT_FAILURE, 0,
-	       gettext ("cannot get header of 0th section: %s"),
-	       elf_errmsg (-1));
-
-      shdr->sh_link = shstrtab_ndx;
-
-      (void) xelf_update_shdr (scn, shdr);
-
-      ehdr->e_shstrndx = SHN_XINDEX;
-    }
-
-  if (ld_state.file_type != relocatable_file_type)
-    /* DSOs and executables have to define the entry point symbol.  */
-    ehdr->e_entry = find_entry_point ();
-
-  if (unlikely (xelf_update_ehdr (ld_state.outelf, ehdr) == 0))
-    error (EXIT_FAILURE, 0,
-	   gettext ("cannot update ELF header: %s"),
-	   elf_errmsg (-1));
-
-
-  /* Free the data which we don't need anymore.  */
-  free (ld_state.dblindirect);
-
-
-  /* Finalize the .plt section and what else belongs to it.  */
-  FINALIZE_PLT (statep, nsym, nsym_local, ndxtosym);
-
-
-  /* Finally, if we have to compute the build ID.  */
-  if (ld_state.build_id != NULL)
-    compute_build_id ();
-
-
-  /* We don't need the map from the symbol table index to the symbol
-     structure anymore.  */
-  free (ndxtosym);
-
-  return 0;
-}
-
-
-/* This is a function which must be specified in all backends.  */
-static void
-ld_generic_relocate_section (struct ld_state *statep, Elf_Scn *outscn,
-			     struct scninfo *firstp,
-			     const Elf32_Word *dblindirect)
-{
-  error (EXIT_FAILURE, 0, gettext ("\
-linker backend didn't specify function to relocate section"));
-  /* NOTREACHED */
-}
-
-
-/* Finalize the output file.  */
-static int
-ld_generic_finalize (struct ld_state *statep)
-{
-  /* Write out the ELF file data.  */
-  if (elf_update (ld_state.outelf, ELF_C_WRITE) == -1)
-      error (EXIT_FAILURE, 0, gettext ("while writing output file: %s"),
-	     elf_errmsg (-1));
-
-  /* Free the resources.  */
-  if (elf_end (ld_state.outelf) != 0)
-    error (EXIT_FAILURE, 0, gettext ("while finishing output file: %s"),
-	   elf_errmsg (-1));
-
-  /* Get the file status of the temporary file.  */
-  struct stat temp_st;
-  if (fstat (ld_state.outfd, &temp_st) != 0)
-    error (EXIT_FAILURE, errno, gettext ("cannot stat output file"));
-
-  /* Now it's time to rename the file.  Remove an old existing file
-     first.  */
-  if (rename (ld_state.tempfname, ld_state.outfname) != 0)
-    /* Something went wrong.  */
-    error (EXIT_FAILURE, errno, gettext ("cannot rename output file"));
-
-  /* Make sure the output file is really the one we created.  */
-  struct stat new_st;
-  if (stat (ld_state.outfname, &new_st) != 0
-      || new_st.st_ino != temp_st.st_ino
-      || new_st.st_dev != temp_st.st_dev)
-    {
-      /* Wow, somebody overwrote the output file, probably some intruder.  */
-      unlink (ld_state.outfname);
-      error (EXIT_FAILURE, 0, gettext ("\
-WARNING: temporary output file overwritten before linking finished"));
-    }
-
-  /* Close the file descriptor.  */
-  (void) close (ld_state.outfd);
-
-  /* Signal the cleanup handler that the file is correctly created.  */
-  ld_state.tempfname = NULL;
-
-  return 0;
-}
-
-
-static bool
-ld_generic_special_section_number_p (struct ld_state *statep, size_t number)
-{
-  /* There are no special section numbers in the gABI.  */
-  return false;
-}
-
-
-static bool
-ld_generic_section_type_p (struct ld_state *statep, GElf_Word type)
-{
-  if (type < SHT_NUM
-      /* XXX Enable the following two when implemented.  */
-      // || type == SHT_GNU_LIBLIST
-      // || type == SHT_CHECKSUM
-      /* XXX Eventually include SHT_SUNW_move, SHT_SUNW_COMDAT, and
-	 SHT_SUNW_syminfo.  */
-      || (type >= SHT_GNU_verdef && type <= SHT_GNU_versym))
-    return true;
-
-  return false;
-}
-
-
-static XElf_Xword
-ld_generic_dynamic_section_flags (struct ld_state *statep)
-{
-  /* By default the .dynamic section is writable (and is of course
-     loaded).  Few architecture differ from this.  */
-  return SHF_ALLOC | SHF_WRITE;
-}
-
-
-static void
-ld_generic_initialize_plt (struct ld_state *statep, Elf_Scn *scn)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "initialize_plt");
-}
-
-
-static void
-ld_generic_initialize_pltrel (struct ld_state *statep, Elf_Scn *scn)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "initialize_pltrel");
-}
-
-
-static void
-ld_generic_initialize_got (struct ld_state *statep, Elf_Scn *scn)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "initialize_got");
-}
-
-
-static void
-ld_generic_initialize_gotplt (struct ld_state *statep, Elf_Scn *scn)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "initialize_gotplt");
-}
-
-
-static void
-ld_generic_finalize_plt (struct ld_state *statep, size_t nsym, size_t nsym_dyn,
-			 struct symbol **ndxtosymp)
-{
-  /* By default we assume that nothing has to be done.  */
-}
-
-
-static int
-ld_generic_rel_type (struct ld_state *statep)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "rel_type");
-  /* Just to keep the compiler calm.  */
-  return 0;
-}
-
-
-static void
-ld_generic_count_relocations (struct ld_state *statep, struct scninfo *scninfo)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "count_relocations");
-}
-
-
-static void
-ld_generic_create_relocations (struct ld_state *statep,
-			       const Elf32_Word *dblindirect)
-{
-  /* This cannot be implemented generally.  There should have been a
-     machine dependent implementation and we should never have arrived
-     here.  */
-  error (EXIT_FAILURE, 0, gettext ("no machine specific '%s' implementation"),
-	 "create_relocations");
-}
diff --git a/src/ldlex.l b/src/ldlex.l
deleted file mode 100644
index 835c2dc..0000000
--- a/src/ldlex.l
+++ /dev/null
@@ -1,353 +0,0 @@
-%{
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <ctype.h>
-#include <elf.h>
-#include <error.h>
-#include <inttypes.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <system.h>
-#include <ld.h>
-#include "ldscript.h"
-
-/* We sure use no threads to read the stream, so use the _unlocked
-   variants of the functions.  */
-#undef getc
-#define getc(s) getc_unlocked (s)
-#undef ferror
-#define ferror(s) ferror_unlocked (s)
-#undef fread
-#define fread(b, m, n, s) fread_unlocked (b, m, n, s)
-#undef fwrite
-#define fwrite(b, m, n, s) fwrite_unlocked (b, m, n, s)
-
-/* ECHO must be redefined since the default implementation ignores
-   the return value of fwrite_unlocked.  */
-#define ECHO do { size_t n__ __attribute__ ((unused)) \
-			   = fwrite (yytext, yyleng, 1, yyout); } while (0)
-
-/* Defined in ld.c.  */
-extern int ld_scan_version_script;
-
-#define MAX_PREPDEPTH 20
-static enum prepstate
-{
-  prep_normal,
-  skip_if,
-  skip_to_endif
-} prepstate[MAX_PREPDEPTH];
-static int prepdepth;
-
-static void eat_comment (void);
-static void eat_to_eol (bool empty);
-static int attrib_convert (int c);
-static void push_state (enum prepstate);
-static int pop_state (void);
-static int handle_ifdef (void);
-static void invalid_char (int ch);
-%}
-
-ID		[a-zA-Z0-9_.*?][a-zA-Z0-9_.*?-]*
-FILENAMECHAR1	[a-zA-Z0-9_/.\\~]
-FILENAMECHAR	[^][{}[:space:]():;]+
-HEX		0[xX][0-9a-fA-F]+[kKmM]?
-OCT		0[0-7]*[kKmM]?
-DEC		[0-9]+[kKmM]?
-WHITE		[[:space:]]+
-
-%option yylineno
-%option never-interactive
-%option noyywrap
-
-%x IGNORE
-
-%%
-				if (unlikely (ld_scan_version_script))
-				  {
-				    ld_scan_version_script = -1;
-				    return kVERSION_SCRIPT;
-				  }
-
-^"#"ifdef/[[:space:]]		{ BEGIN (handle_ifdef ()); }
-^"#"else/[[:space:]\n]		{ eat_to_eol (true);
-				  push_state (skip_to_endif);
-				  BEGIN (IGNORE); }
-^"#"elifdef/[[:space:]]		{ eat_to_eol (false);
-				  push_state (skip_to_endif);
-				  BEGIN (IGNORE); }
-^"#"endif/[[:space:]\n]		{ eat_to_eol (true) ; }
-
-<IGNORE>^"#"ifdef/[[:space:]\n] { eat_to_eol (false);
-				  push_state (skip_to_endif); }
-<IGNORE>^"#"else/[[:space:]\n]	{ eat_to_eol (true);
-				  assert (prepdepth > 0);
-				  if (prepstate[prepdepth - 1] == skip_if)
-				    {
-				      /* Back to normal processing.  */
-				      assert (prepdepth == 1);
-				      BEGIN (pop_state ());
-				    }
-				}
-<IGNORE>^"#"elifdef/[[:space:]]	{ assert (prepdepth > 0);
-				  if (prepstate[prepdepth - 1] == skip_if)
-				    {
-				      /* Maybe this symbol is defined.  */
-				      pop_state ();
-				      BEGIN (handle_ifdef ());
-				    }
-				}
-<IGNORE>^"#"endif/[[:space:]\n] { eat_to_eol (true);
-				  BEGIN (pop_state ()); }
-<IGNORE>.|\n			{ /* nothing */ }
-
-
-"/*"				{ eat_comment (); }
-
-ALIGN				{ return kALIGN; }
-AS_NEEDED			{ return kAS_NEEDED; }
-ENTRY				{ return kENTRY; }
-EXCLUDE_FILE			{ return kEXCLUDE_FILE; }
-"global:"			{ return kGLOBAL; }
-GROUP				{ return kGROUP; }
-INPUT				{ return kINPUT; }
-INTERP				{ return kINTERP; }
-KEEP				{ return kKEEP; }
-"local:"			{ return kLOCAL; }
-OUTPUT_FORMAT			{ return kOUTPUT_FORMAT; }
-PAGESIZE			{ return kPAGESIZE; }
-PROVIDE				{ return kPROVIDE; }
-SEARCH_DIR			{ return kSEARCH_DIR; }
-SEGMENT				{ return kSEGMENT; }
-SIZEOF_HEADERS			{ return kSIZEOF_HEADERS; }
-SORT				{ return kSORT; }
-VERSION				{ return kVERSION; }
-
-"["([RWX]){0,3}"]"		{ unsigned int cnt = 1 ;
-				  ldlval.num = 0;
-				  while (cnt < yyleng - 1)
-				    ldlval.num |= attrib_convert (yytext[cnt++]);
-				  return kMODE; }
-
-"{"				{ return '{'; }
-"}"				{ return '}'; }
-"("				{ return '('; }
-")"				{ return ')'; }
-":"				{ return ':'; }
-";"				{ return ';'; }
-"="				{ return '='; }
-"+"				{ ldlval.op = exp_plus; return kADD_OP; }
-"-"				{ ldlval.op = exp_minus; return kADD_OP; }
-"*"				{ return '*'; }
-"/"				{ ldlval.op = exp_div; return kMUL_OP; }
-"%"				{ ldlval.op = exp_mod; return kMUL_OP; }
-"&"				{ return '&'; }
-"|"				{ return '|'; }
-
-","				{ return ','; }
-
-{HEX}|{OCT}|{DEC}		{ char *endp;
-				  ldlval.num = strtoumax (yytext, &endp, 0);
-				  if (*endp != '\0')
-				    {
-				      if (tolower (*endp) == 'k')
-					ldlval.num *= 1024;
-				      else
-					{
-					  assert (tolower (*endp) == 'm');
-					  ldlval.num *= 1024 * 1024;
-					}
-				    }
-				  return kNUM; }
-
-{ID}				{ ldlval.str = obstack_strndup (&ld_state.smem,
-								yytext, yyleng);
-				  return kID; }
-
-{FILENAMECHAR1}{FILENAMECHAR}	{ ldlval.str = obstack_strndup (&ld_state.smem,
-								yytext, yyleng);
-				  return kFILENAME; }
-
-{WHITE}				{ /* IGNORE */ }
-
-.				{ invalid_char (*yytext); }
-
-%%
-
-static void
-eat_comment (void)
-{
-  while (1)
-    {
-      int c = input ();
-
-      while (c != '*' && c != EOF)
-	c = input ();
-
-      if (c == '*')
-	{
-	  c = input ();
-	  while (c == '*')
-	    c = input ();
-	  if (c == '/')
-	    break;
-	}
-
-      if (c == EOF)
-	{
-	  /* XXX Use the setjmp buffer and signal EOF in comment */
-	  error (0, 0, gettext ("EOF in comment"));
-	  break;
-	}
-    }
-}
-
-
-static void
-eat_to_eol (bool empty)
-{
-  bool warned = false;
-
-  while (1)
-    {
-      int c = input ();
-
-      if (c == EOF)
-	break;
-      if (c == '\n')
-	{
-	  ++yylineno;
-	  break;
-	}
-
-      if (empty && ! isspace (c) && ! warned)
-	{
-	  error (0, 0, gettext ("%d: garbage at end of line"), yylineno);
-	  warned = true;
-	}
-    }
-}
-
-
-static int
-attrib_convert (int c)
-{
-  if (c == 'X')
-    return PF_X;
-  if (c == 'W')
-    return PF_W;
-  assert (c == 'R');
-  return PF_R;
-}
-
-
-static void
-push_state (enum prepstate state)
-{
-  if (prepdepth >= MAX_PREPDEPTH)
-    error (EXIT_FAILURE, 0, gettext ("%d: conditionals nested too deep"),
-	   yylineno);
-
-  prepstate[prepdepth++] = state;
-}
-
-
-static int
-pop_state (void)
-{
-  if (prepdepth == 0)
-    error (0, 0, gettext ("%d: unexpected #endif"), yylineno);
-  else
-    --prepdepth;
-
-  return prepdepth == 0 ? INITIAL : IGNORE;
-}
-
-
-static int
-handle_ifdef (void)
-{
-  char idbuf[50];
-  char *id = idbuf;
-  size_t idlen = 0;
-  size_t idmax = sizeof (idbuf);
-  bool ignore_ws = true;
-  bool defined = false;
-  int result;
-
-  while (1)
-    {
-      int c = input ();
-
-      if (isspace (c) && ignore_ws)
-	continue;
-
-      if (c != '_' && (c < 'a' || c > 'z') && (c < 'A' || c > 'Z')
-	  && (idlen == 0 || c < '0' || c > '9'))
-	{
-	  unput (c);
-	  break;
-	}
-
-      if (idlen == idmax)
-	{
-	  char *newp = (char *) alloca (idmax *= 2);
-	  id = memcpy (newp, id, idlen);
-	}
-
-      id[idlen++] = c;
-      ignore_ws = false;
-    }
-
-  /* XXX Compare in a better way.  */
-  if (idlen == 6 && strncmp (id, "SHARED", 6) == 0)
-    defined = ld_state.file_type == dso_file_type;
-
-  if (defined)
-    result = INITIAL;
-  else
-    {
-      push_state (skip_if);
-      result = IGNORE;
-    }
-
-  return result;
-}
-
-
-static void
-invalid_char (int ch)
-{
-  error (0, 0, (isascii (ch)
-		? gettext ("invalid character '%c' at line %d; ignored")
-		: gettext ("invalid character '\\%o' at line %d; ignored")),
-	 ch, yylineno);
-}
-
-
-// Local Variables:
-// mode: C
-// End:
diff --git a/src/ldscript.y b/src/ldscript.y
deleted file mode 100644
index 3502ce1..0000000
--- a/src/ldscript.y
+++ /dev/null
@@ -1,803 +0,0 @@
-%{
-/* Parser for linker scripts.
-   Copyright (C) 2001-2011 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <assert.h>
-#include <error.h>
-#include <libintl.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <system.h>
-#include <ld.h>
-
-/* The error handler.  */
-static void yyerror (const char *s);
-
-/* Some helper functions we need to construct the data structures
-   describing information from the file.  */
-static struct expression *new_expr (int tag);
-static struct input_section_name *new_input_section_name (const char *name,
-							  bool sort_flag);
-static struct input_rule *new_input_rule (int tag);
-static struct output_rule *new_output_rule (int tag);
-static struct assignment *new_assignment (const char *variable,
-					  struct expression *expression,
-					  bool provide_flag);
-static void new_segment (int mode, struct output_rule *output_rule);
-static struct filename_list *new_filename_listelem (const char *string);
-static void add_inputfiles (struct filename_list *fnames);
-static struct id_list *new_id_listelem (const char *str);
- static struct filename_list *mark_as_needed (struct filename_list *listp);
-static struct version *new_version (struct id_list *local,
-				    struct id_list *global);
-static struct version *merge_versions (struct version *one,
-				       struct version *two);
-static void add_versions (struct version *versions);
-
-extern int yylex (void);
-%}
-
-%union {
-  uintmax_t num;
-  enum expression_tag op;
-  char *str;
-  struct expression *expr;
-  struct input_section_name *sectionname;
-  struct filemask_section_name *filemask_section_name;
-  struct input_rule *input_rule;
-  struct output_rule *output_rule;
-  struct assignment *assignment;
-  struct filename_list *filename_list;
-  struct version *version;
-  struct id_list *id_list;
-}
-
-%token kADD_OP
-%token kALIGN
-%token kAS_NEEDED
-%token kENTRY
-%token kEXCLUDE_FILE
-%token <str> kFILENAME
-%token kGLOBAL
-%token kGROUP
-%token <str> kID
-%token kINPUT
-%token kINTERP
-%token kKEEP
-%token kLOCAL
-%token <num> kMODE
-%token kMUL_OP
-%token <num> kNUM
-%token kOUTPUT_FORMAT
-%token kPAGESIZE
-%token kPROVIDE
-%token kSEARCH_DIR
-%token kSEGMENT
-%token kSIZEOF_HEADERS
-%token kSORT
-%token kVERSION
-%token kVERSION_SCRIPT
-
-%left '|'
-%left '&'
-%left ADD_OP
-%left MUL_OP '*'
-
-%type <op> kADD_OP
-%type <op> kMUL_OP
-%type <str> filename_id
-%type <str> filename_id_star
-%type <str> exclude_opt
-%type <expr> expr
-%type <sectionname> sort_opt_name
-%type <filemask_section_name> sectionname
-%type <input_rule> inputsection
-%type <input_rule> inputsections
-%type <output_rule> outputsection
-%type <output_rule> outputsections
-%type <assignment> assignment
-%type <filename_list> filename_id_list
-%type <filename_list> filename_id_listelem
-%type <version> versionlist
-%type <version> version
-%type <version> version_stmt_list
-%type <version> version_stmt
-%type <id_list> filename_id_star_list
-
-%expect 16
-
-%%
-
-script_or_version:
-		  file
-		| kVERSION_SCRIPT versionlist
-		    { add_versions ($2); }
-		;
-
-file:		  file content
-		| content
-		;
-
-content:	  kENTRY '(' kID ')' ';'
-		    {
-		      if (likely (ld_state.entry == NULL))
-			ld_state.entry = $3;
-		    }
-		| kSEARCH_DIR '(' filename_id ')' ';'
-		    {
-		      ld_new_searchdir ($3);
-		    }
-		| kPAGESIZE '(' kNUM ')' ';'
-		    {
-		      if (likely (ld_state.pagesize == 0))
-			ld_state.pagesize = $3;
-		    }
-		| kINTERP '(' filename_id ')' ';'
-		    {
-		      if (likely (ld_state.interp == NULL)
-			  && ld_state.file_type != dso_file_type)
-			ld_state.interp = $3;
-		    }
-		| kSEGMENT kMODE '{' outputsections '}'
-		    {
-		      new_segment ($2, $4);
-		    }
-		| kSEGMENT error '{' outputsections '}'
-		    {
-		      fputs_unlocked (gettext ("mode for segment invalid\n"),
-				      stderr);
-		      new_segment (0, $4);
-		    }
-		| kGROUP '(' filename_id_list ')'
-		    {
-		      /* First little optimization.  If there is only one
-			 file in the group don't do anything.  */
-		      if ($3 != $3->next)
-			{
-			  $3->next->group_start = 1;
-			  $3->group_end = 1;
-			}
-		      add_inputfiles ($3);
-		    }
-		| kINPUT '(' filename_id_list ')'
-		    { add_inputfiles ($3); }
-		| kAS_NEEDED '(' filename_id_list ')'
-		    { add_inputfiles (mark_as_needed ($3)); }
-		| kVERSION '{' versionlist '}'
-		    { add_versions ($3); }
-		| kOUTPUT_FORMAT '(' filename_id ')'
-		    { /* XXX TODO */ }
-		;
-
-outputsections:	  outputsections outputsection
-		    {
-		      $2->next = $1->next;
-		      $$ = $1->next = $2;
-		    }
-		| outputsection
-		    { $$ = $1; }
-		;
-
-outputsection:	  assignment ';'
-		    {
-		      $$ = new_output_rule (output_assignment);
-		      $$->val.assignment = $1;
-		    }
-		| kID '{' inputsections '}'
-		    {
-		      $$ = new_output_rule (output_section);
-		      $$->val.section.name = $1;
-		      $$->val.section.input = $3->next;
-		      if (ld_state.strip == strip_debug
-			  && ebl_debugscn_p (ld_state.ebl, $1))
-			$$->val.section.ignored = true;
-		      else
-			$$->val.section.ignored = false;
-		      $3->next = NULL;
-		    }
-		| kID ';'
-		    {
-		      /* This is a short cut for "ID { *(ID) }".  */
-		      $$ = new_output_rule (output_section);
-		      $$->val.section.name = $1;
-		      $$->val.section.input = new_input_rule (input_section);
-		      $$->val.section.input->next = NULL;
-		      $$->val.section.input->val.section =
-			(struct filemask_section_name *)
-			  obstack_alloc (&ld_state.smem,
-					 sizeof (struct filemask_section_name));
-		      $$->val.section.input->val.section->filemask = NULL;
-		      $$->val.section.input->val.section->excludemask = NULL;
-		      $$->val.section.input->val.section->section_name =
-			new_input_section_name ($1, false);
-		      $$->val.section.input->val.section->keep_flag = false;
-		      if (ld_state.strip == strip_debug
-			  && ebl_debugscn_p (ld_state.ebl, $1))
-			$$->val.section.ignored = true;
-		      else
-			$$->val.section.ignored = false;
-		    }
-		;
-
-assignment:	  kID '=' expr
-		    { $$ = new_assignment ($1, $3, false); }
-		| kPROVIDE '(' kID '=' expr ')'
-		    { $$ = new_assignment ($3, $5, true); }
-		;
-
-inputsections:	  inputsections inputsection
-		    {
-		      $2->next = $1->next;
-		      $$ = $1->next = $2;
-		    }
-		| inputsection
-		    { $$ = $1; }
-		;
-
-inputsection:	  sectionname
-		    {
-		      $$ = new_input_rule (input_section);
-		      $$->val.section = $1;
-		    }
-		| kKEEP '(' sectionname ')'
-		    {
-		      $3->keep_flag = true;
-
-		      $$ = new_input_rule (input_section);
-		      $$->val.section = $3;
-		    }
-		| assignment ';'
-		    {
-		      $$ = new_input_rule (input_assignment);
-		      $$->val.assignment = $1;
-		    }
-		;
-
-sectionname:	  filename_id_star '(' exclude_opt sort_opt_name ')'
-		    {
-		      $$ = (struct filemask_section_name *)
-			obstack_alloc (&ld_state.smem, sizeof (*$$));
-		      $$->filemask = $1;
-		      $$->excludemask = $3;
-		      $$->section_name = $4;
-		      $$->keep_flag = false;
-		    }
-		;
-
-sort_opt_name:	  kID
-		    { $$ = new_input_section_name ($1, false); }
-		| kSORT '(' kID ')'
-		    { $$ = new_input_section_name ($3, true); }
-		;
-
-exclude_opt:	  kEXCLUDE_FILE '(' filename_id ')'
-		    { $$ = $3; }
-		|
-		    { $$ = NULL; }
-		;
-
-expr:		  kALIGN '(' expr ')'
-		    {
-		      $$ = new_expr (exp_align);
-		      $$->val.child = $3;
-		    }
-		| '(' expr ')'
-		    { $$ = $2; }
-		| expr '*' expr
-		    {
-		      $$ = new_expr (exp_mult);
-		      $$->val.binary.left = $1;
-		      $$->val.binary.right = $3;
-		    }
-		| expr kMUL_OP expr
-		    {
-		      $$ = new_expr ($2);
-		      $$->val.binary.left = $1;
-		      $$->val.binary.right = $3;
-		    }
-		| expr kADD_OP expr
-		    {
-		      $$ = new_expr ($2);
-		      $$->val.binary.left = $1;
-		      $$->val.binary.right = $3;
-		    }
-		| expr '&' expr
-		    {
-		      $$ = new_expr (exp_and);
-		      $$->val.binary.left = $1;
-		      $$->val.binary.right = $3;
-		    }
-		| expr '|' expr
-		    {
-		      $$ = new_expr (exp_or);
-		      $$->val.binary.left = $1;
-		      $$->val.binary.right = $3;
-		    }
-		| kNUM
-		    {
-		      $$ = new_expr (exp_num);
-		      $$->val.num = $1;
-		    }
-		| kID
-		    {
-		      $$ = new_expr (exp_id);
-		      $$->val.str = $1;
-		    }
-		| kSIZEOF_HEADERS
-		    { $$ = new_expr (exp_sizeof_headers); }
-		| kPAGESIZE
-		    { $$ = new_expr (exp_pagesize); }
-		;
-
-filename_id_list: filename_id_list comma_opt filename_id_listelem
-		    {
-		      $3->next = $1->next;
-		      $$ = $1->next = $3;
-		    }
-		| filename_id_listelem
-		    { $$ = $1; }
-		;
-
-comma_opt:	  ','
-		|
-		;
-
-filename_id_listelem: kGROUP '(' filename_id_list ')'
-		    {
-		      /* First little optimization.  If there is only one
-			 file in the group don't do anything.  */
-		      if ($3 != $3->next)
-			{
-			  $3->next->group_start = 1;
-			  $3->group_end = 1;
-			}
-		      $$ = $3;
-		    }
-		| kAS_NEEDED '(' filename_id_list ')'
-		    { $$ = mark_as_needed ($3); }
-		| filename_id
-		    { $$ = new_filename_listelem ($1); }
-		;
-
-
-versionlist:	  versionlist version
-		    {
-		      $2->next = $1->next;
-		      $$ = $1->next = $2;
-		    }
-		| version
-		    { $$ = $1; }
-		;
-
-version:	  '{' version_stmt_list '}' ';'
-		    {
-		      $2->versionname = "";
-		      $2->parentname = NULL;
-		      $$ = $2;
-		    }
-		| filename_id '{' version_stmt_list '}' ';'
-		    {
-		      $3->versionname = $1;
-		      $3->parentname = NULL;
-		      $$ = $3;
-		    }
-		| filename_id '{' version_stmt_list '}' filename_id ';'
-		    {
-		      $3->versionname = $1;
-		      $3->parentname = $5;
-		      $$ = $3;
-		    }
-		;
-
-version_stmt_list:
-		  version_stmt_list version_stmt
-		    { $$ = merge_versions ($1, $2); }
-		| version_stmt
-		    { $$ = $1; }
-		;
-
-version_stmt:	  kGLOBAL filename_id_star_list
-		    { $$ = new_version (NULL, $2); }
-		| kLOCAL filename_id_star_list
-		    { $$ = new_version ($2, NULL); }
-		;
-
-filename_id_star_list:
-		  filename_id_star_list filename_id_star ';'
-		    {
-		      struct id_list *newp = new_id_listelem ($2);
-		      newp->next = $1->next;
-		      $$ = $1->next = newp;
-		    }
-		| filename_id_star ';'
-		    { $$ = new_id_listelem ($1); }
-		;
-
-filename_id:	  kFILENAME
-		    { $$ = $1; }
-		| kID
-		    { $$ = $1; }
-		;
-
-filename_id_star: filename_id
-		    { $$ = $1; }
-		| '*'
-		    { $$ = NULL; }
-		;
-
-%%
-
-static void
-yyerror (const char *s)
-{
-  error (0, 0, (ld_scan_version_script
-		? gettext ("while reading version script '%s': %s at line %d")
-		: gettext ("while reading linker script '%s': %s at line %d")),
-	 ldin_fname, gettext (s), ldlineno);
-}
-
-
-static struct expression *
-new_expr (int tag)
-{
-  struct expression *newp = (struct expression *)
-    obstack_alloc (&ld_state.smem, sizeof (*newp));
-
-  newp->tag = tag;
-  return newp;
-}
-
-
-static struct input_section_name *
-new_input_section_name (const char *name, bool sort_flag)
-{
-  struct input_section_name *newp = (struct input_section_name *)
-    obstack_alloc (&ld_state.smem, sizeof (*newp));
-
-  newp->name = name;
-  newp->sort_flag = sort_flag;
-  return newp;
-}
-
-
-static struct input_rule *
-new_input_rule (int tag)
-{
-  struct input_rule *newp = (struct input_rule *)
-    obstack_alloc (&ld_state.smem, sizeof (*newp));
-
-  newp->tag = tag;
-  newp->next = newp;
-  return newp;
-}
-
-
-static struct output_rule *
-new_output_rule (int tag)
-{
-  struct output_rule *newp = (struct output_rule *)
-    memset (obstack_alloc (&ld_state.smem, sizeof (*newp)),
-	    '\0', sizeof (*newp));
-
-  newp->tag = tag;
-  newp->next = newp;
-  return newp;
-}
-
-
-static struct assignment *
-new_assignment (const char *variable, struct expression *expression,
-		bool provide_flag)
-{
-  struct assignment *newp = (struct assignment *)
-    obstack_alloc (&ld_state.smem, sizeof (*newp));
-
-  newp->variable = variable;
-  newp->expression = expression;
-  newp->sym = NULL;
-  newp->provide_flag = provide_flag;
-
-  /* Insert the symbol into a hash table.  We will later have to matc*/
-  return newp;
-}
-
-
-static void
-new_segment (int mode, struct output_rule *output_rule)
-{
-  struct output_segment *newp;
-
-  newp
-    = (struct output_segment *) obstack_alloc (&ld_state.smem, sizeof (*newp));
-  newp->mode = mode;
-  newp->next = newp;
-
-  newp->output_rules = output_rule->next;
-  output_rule->next = NULL;
-
-  /* Enqueue the output segment description.  */
-  if (ld_state.output_segments == NULL)
-    ld_state.output_segments = newp;
-  else
-    {
-      newp->next = ld_state.output_segments->next;
-      ld_state.output_segments = ld_state.output_segments->next = newp;
-    }
-
-  /* If the output file should be stripped of all symbol set the flag
-     in the structures of all output sections.  */
-  if (mode == 0 && ld_state.strip == strip_all)
-    {
-      struct output_rule *runp;
-
-      for (runp = newp->output_rules; runp != NULL; runp = runp->next)
-	if (runp->tag == output_section)
-	  runp->val.section.ignored = true;
-    }
-}
-
-
-static struct filename_list *
-new_filename_listelem (const char *string)
-{
-  struct filename_list *newp;
-
-  /* We use calloc and not the obstack since this object can be freed soon.  */
-  newp = (struct filename_list *) xcalloc (1, sizeof (*newp));
-  newp->name = string;
-  newp->next = newp;
-  return newp;
-}
-
-
-static struct filename_list *
-mark_as_needed (struct filename_list *listp)
-{
-  struct filename_list *runp = listp;
-  do
-    {
-      runp->as_needed = true;
-      runp = runp->next;
-    }
-  while (runp != listp);
-
-  return listp;
-}
-
-
-static void
-add_inputfiles (struct filename_list *fnames)
-{
-  assert (fnames != NULL);
-
-  if (ld_state.srcfiles == NULL)
-    ld_state.srcfiles = fnames;
-  else
-    {
-      struct filename_list *first = ld_state.srcfiles->next;
-
-      ld_state.srcfiles->next = fnames->next;
-      fnames->next = first;
-      ld_state.srcfiles->next = fnames;
-    }
-}
-
-
-static _Bool
-special_char_p (const char *str)
-{
-  while (*str != '\0')
-    {
-      if (__builtin_expect (*str == '*', 0)
-	  || __builtin_expect (*str == '?', 0)
-	  || __builtin_expect (*str == '[', 0))
-	return true;
-
-      ++str;
-    }
-
-  return false;
-}
-
-
-static struct id_list *
-new_id_listelem (const char *str)
-{
-  struct id_list *newp;
-
-  newp = (struct id_list *) obstack_alloc (&ld_state.smem, sizeof (*newp));
-  if (str == NULL)
-    newp->u.id_type = id_all;
-  else if (__builtin_expect (special_char_p (str), false))
-    newp->u.id_type = id_wild;
-  else
-    newp->u.id_type = id_str;
-  newp->id = str;
-  newp->next = newp;
-
-  return newp;
-}
-
-
-static struct version *
-new_version (struct id_list *local, struct id_list *global)
-{
-  struct version *newp;
-
-  newp = (struct version *) obstack_alloc (&ld_state.smem, sizeof (*newp));
-  newp->next = newp;
-  newp->local_names = local;
-  newp->global_names = global;
-  newp->versionname = NULL;
-  newp->parentname = NULL;
-
-  return newp;
-}
-
-
-static struct version *
-merge_versions (struct version *one, struct version *two)
-{
-  assert (two->local_names == NULL || two->global_names == NULL);
-
-  if (two->local_names != NULL)
-    {
-      if (one->local_names == NULL)
-	one->local_names = two->local_names;
-      else
-	{
-	  two->local_names->next = one->local_names->next;
-	  one->local_names = one->local_names->next = two->local_names;
-	}
-    }
-  else
-    {
-      if (one->global_names == NULL)
-	one->global_names = two->global_names;
-      else
-	{
-	  two->global_names->next = one->global_names->next;
-	  one->global_names = one->global_names->next = two->global_names;
-	}
-    }
-
-  return one;
-}
-
-
-static void
-add_id_list (const char *versionname, struct id_list *runp, _Bool local)
-{
-  struct id_list *lastp = runp;
-
-  if (runp == NULL)
-    /* Nothing to do.  */
-    return;
-
-  /* Convert into a simple single-linked list.  */
-  runp = runp->next;
-  assert (runp != NULL);
-  lastp->next = NULL;
-
-  do
-    if (runp->u.id_type == id_str)
-      {
-	struct id_list *curp;
-	struct id_list *defp;
-	unsigned long int hval = elf_hash (runp->id);
-
-	curp = runp;
-	runp = runp->next;
-
-	defp = ld_version_str_tab_find (&ld_state.version_str_tab, hval, curp);
-	if (defp != NULL)
-	  {
-	    /* There is already a version definition for this symbol.  */
-	    while (strcmp (defp->u.s.versionname, versionname) != 0)
-	      {
-		if (defp->next == NULL)
-		  {
-		    /* No version like this so far.  */
-		    defp->next = curp;
-		    curp->u.s.local = local;
-		    curp->u.s.versionname = versionname;
-		    curp->next = NULL;
-		    defp = NULL;
-		    break;
-		  }
-
-		defp = defp->next;
-	      }
-
-	    if (defp != NULL && defp->u.s.local != local)
-	      error (EXIT_FAILURE, 0, versionname[0] == '\0'
-		     ? gettext ("\
-symbol '%s' is declared both local and global for unnamed version '%s'")
-		     : gettext ("\
-symbol '%s' is declared both local and global for version '%s'"),
-		     runp->id, versionname);
-	  }
-	else
-	  {
-	    /* This is the first version definition for this symbol.  */
-	    ld_version_str_tab_insert (&ld_state.version_str_tab, hval, curp);
-
-	    curp->u.s.local = local;
-	    curp->u.s.versionname = versionname;
-	    curp->next = NULL;
-	  }
-      }
-    else if (runp->u.id_type == id_all)
-      {
-	if (local)
-	  {
-	    if (ld_state.default_bind_global)
-	      error (EXIT_FAILURE, 0,
-		     gettext ("default visibility set as local and global"));
-	    ld_state.default_bind_local = true;
-	  }
-	else
-	  {
-	    if (ld_state.default_bind_local)
-	      error (EXIT_FAILURE, 0,
-		     gettext ("default visibility set as local and global"));
-	    ld_state.default_bind_global = true;
-	  }
-
-	runp = runp->next;
-      }
-    else
-      {
-	assert (runp->u.id_type == id_wild);
-	/* XXX TBI */
-	abort ();
-      }
-  while (runp != NULL);
-}
-
-
-static void
-add_versions (struct version *versions)
-{
-  struct version *lastp = versions;
-
-  if (versions == NULL)
-    return;
-
-  /* Convert into a simple single-linked list.  */
-  versions = versions->next;
-  assert (versions != NULL);
-  lastp->next = NULL;
-
-  do
-    {
-      add_id_list (versions->versionname, versions->local_names, true);
-      add_id_list (versions->versionname, versions->global_names, false);
-
-      versions = versions->next;
-    }
-  while (versions != NULL);
-}
diff --git a/src/libld_elf_i386.map b/src/libld_elf_i386.map
deleted file mode 100644
index 703af6d..0000000
--- a/src/libld_elf_i386.map
+++ /dev/null
@@ -1,7 +0,0 @@
-ELFUTILS_1.0 {
-  global:
-    elf_i386_ld_init;
-
-  local:
-    *;
-};
diff --git a/src/none_ld.c b/src/none_ld.c
deleted file mode 100644
index fb0f0fb..0000000
--- a/src/none_ld.c
+++ /dev/null
@@ -1 +0,0 @@
-/* Nothing here.  This is just a testimony of automake inflexibility.  */
diff --git a/src/sectionhash.c b/src/sectionhash.c
deleted file mode 100644
index 83a7cca..0000000
--- a/src/sectionhash.c
+++ /dev/null
@@ -1,73 +0,0 @@
-/* Section hash table implementation.
-   Copyright (C) 2001, 2002, 2005 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-
-#include <elf-knowledge.h>
-#include <ld.h>
-
-
-/* Comparison function for sections.  */
-static int
-scnhead_compare (struct scnhead *one, struct scnhead *two)
-{
-  int result = strcmp (one->name, two->name);
-
-  if (result == 0)
-    {
-      result = one->type - two->type;
-
-      if (result == 0)
-	{
-	  GElf_Sxword diff = (SH_FLAGS_IMPORTANT (one->flags)
-			     - SH_FLAGS_IMPORTANT (two->flags));
-	  result = diff < 0 ? -1 : diff == 0 ? 0 : 1;
-
-	  if (result == 0)
-	    {
-	      result = one->entsize - two->entsize;
-
-	      if (result == 0)
-		{
-		  result = (one->grp_signature == NULL
-			    ? (two->grp_signature == NULL ? 0 : -1)
-			    : (two->grp_signature == NULL
-			       ? 1 : strcmp (one->grp_signature,
-					     two->grp_signature)));
-
-		  if (result == 0)
-		    result = one->kind - two->kind;
-		}
-	    }
-	}
-    }
-
-  return result;
-}
-
-/* Definitions for the section hash table.  */
-#define TYPE struct scnhead *
-#define NAME ld_section_tab
-#define ITERATE 1
-#define COMPARE(a, b) scnhead_compare (a, b)
-
-#include "../lib/dynamicsizehash.c"
diff --git a/src/sectionhash.h b/src/sectionhash.h
deleted file mode 100644
index 96da336..0000000
--- a/src/sectionhash.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/* Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifndef SECTIONHASH_H
-#define SECTIONHASH_H	1
-
-/* Definitions for the section hash table.  */
-#define TYPE struct scnhead *
-#define NAME ld_section_tab
-#define ITERATE 1
-#include <dynamicsizehash.h>
-
-#endif	/* sectionhash.h */
diff --git a/src/symbolhash.c b/src/symbolhash.c
deleted file mode 100644
index 3fd9649..0000000
--- a/src/symbolhash.c
+++ /dev/null
@@ -1,33 +0,0 @@
-/* Symbol hash table implementation.
-   Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-
-#include <ld.h>
-
-/* Definitions for the symbol hash table.  */
-#define TYPE struct symbol *
-#define NAME ld_symbol_tab
-#define ITERATE 1
-#define COMPARE(a, b) strcmp ((a)->name, (b)->name)
-
-#include "../lib/dynamicsizehash.c"
diff --git a/src/symbolhash.h b/src/symbolhash.h
deleted file mode 100644
index 062dade..0000000
--- a/src/symbolhash.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifndef SYMBOLHASH_H
-#define SYMBOLHASH_H	1
-
-/* Definitions for the symbol hash table.  */
-#define TYPE struct symbol *
-#define NAME ld_symbol_tab
-#define ITERATE 1
-#define COMPARE(a, b) strcmp ((a)->name, (b)->name)
-#include <dynamicsizehash.h>
-
-#endif	/* symbolhash.h */
diff --git a/src/unaligned.h b/src/unaligned.h
deleted file mode 100644
index 2916653..0000000
--- a/src/unaligned.h
+++ /dev/null
@@ -1,102 +0,0 @@
-/* Unaligned memory access functionality.
-   Copyright (C) 2000, 2001, 2002, 2003, 2008 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifndef _UNALIGNED_H
-#define _UNALIGNED_H	1
-
-#include <byteswap.h>
-#include <endian.h>
-
-
-#ifndef UNALIGNED_ACCESS_CLASS
-# error "UNALIGNED_ACCESS_CLASS must be defined"
-#endif
-
-
-/* Macros to convert from the host byte order to that of the object file.  */
-#if UNALIGNED_ACCESS_CLASS == BYTE_ORDER
-# define target_bswap_16(n) (n)
-# define target_bswap_32(n) (n)
-# define target_bswap_64(n) (n)
-#else
-# define target_bswap_16(n) bswap_16 (n)
-# define target_bswap_32(n) bswap_32 (n)
-# define target_bswap_64(n) bswap_64 (n)
-#endif
-
-
-union u_2ubyte_unaligned
-{
-  uint16_t u;
-  char c[2];
-} __attribute__((packed));
-
-union u_4ubyte_unaligned
-{
-  uint32_t u;
-  char c[4];
-} __attribute__((packed));
-
-union u_8ubyte_unaligned
-{
-  uint64_t u;
-  char c[8];
-} __attribute__((packed));
-
-
-/* Macros to store value at unaligned address.  */
-#define store_2ubyte_unaligned(ptr, value) \
-  (void) (((union u_2ubyte_unaligned *) (ptr))->u = target_bswap_16 (value))
-#define store_4ubyte_unaligned(ptr, value) \
-  (void) (((union u_4ubyte_unaligned *) (ptr))->u = target_bswap_32 (value))
-#define store_8ubyte_unaligned(ptr, value) \
-  (void) (((union u_8ubyte_unaligned *) (ptr))->u = target_bswap_64 (value))
-
-
-/* Macros to add value to unaligned address.  This is a bit more
-   complicated since the value must be read from memory and eventually
-   converted twice.  */
-#if UNALIGNED_ACCESS_CLASS == BYTE_ORDER
-# define add_2ubyte_unaligned(ptr, value) \
-  (void) (((union u_2ubyte_unaligned *) (ptr))->u += value)
-# define add_4ubyte_unaligned(ptr, value) \
-  (void) (((union u_4ubyte_unaligned *) (ptr))->u += value)
-# define add_8ubyte_unaligned(ptr, value) \
-  (void) (((union u_8ubyte_unaligned *) (ptr))->u += value)
-#else
-# define add_2ubyte_unaligned(ptr, value) \
-  do {									      \
-    union u_2ubyte_unaligned *_ptr = (void *) (ptr);			      \
-    uint16_t _val = bswap_16 (_ptr->u) + (value);			      \
-    _ptr->u = bswap_16 (_val);						      \
-  } while (0)
-# define add_4ubyte_unaligned(ptr, value) \
-  do {									      \
-    union u_4ubyte_unaligned *_ptr = (void *) (ptr);			      \
-    uint32_t _val = bswap_32 (_ptr->u) + (value);			      \
-    _ptr->u = bswap_32 (_val);						      \
-  } while (0)
-# define add_8ubyte_unaligned(ptr, value) \
-  do {									      \
-    union u_8ubyte_unaligned *_ptr = (void *) (ptr);			      \
-    uint64_t _val = bswap_64 (_ptr->u) + (value);			      \
-    _ptr->u = bswap_64 (_val);						      \
-  } while (0)
-#endif
-
-#endif /* unaligned.h */
diff --git a/src/versionhash.c b/src/versionhash.c
deleted file mode 100644
index cc4d283..0000000
--- a/src/versionhash.c
+++ /dev/null
@@ -1,32 +0,0 @@
-/* Version symbol hash table implementation.
-   Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <string.h>
-
-#include <ld.h>
-
-/* Definitions for the symbol hash table.  */
-#define TYPE struct id_list *
-#define NAME ld_version_str_tab
-#define COMPARE(a, b) strcmp ((a)->id, (b)->id)
-
-#include "../lib/dynamicsizehash.c"
diff --git a/src/versionhash.h b/src/versionhash.h
deleted file mode 100644
index 4434e05..0000000
--- a/src/versionhash.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright (C) 2001, 2002 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifndef VERSIONHASH_H
-#define VERSIONHASH_H	1
-
-/* Definitions for the symbol hash table.  */
-#define TYPE struct id_list *
-#define NAME ld_version_str_tab
-#include <dynamicsizehash.h>
-
-#endif	/* versionhash.h */
diff --git a/src/xelf.h b/src/xelf.h
deleted file mode 100644
index f292327..0000000
--- a/src/xelf.h
+++ /dev/null
@@ -1,391 +0,0 @@
-/* Macros to enable writing native and generic ELF access code.
-   Copyright (C) 2003 Red Hat, Inc.
-   This file is part of elfutils.
-   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
-
-   This file is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 3 of the License, or
-   (at your option) any later version.
-
-   elfutils is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#include <libebl.h>
-
-
-/* By default the linker is handling all architectures.  But it can
-   be configured to be a native-only linker.  */
-#if NATIVE_ELF == 32
-/* 32-bit only.  */
-# define XElf_Ehdr Elf32_Ehdr
-# define XElf_Shdr Elf32_Shdr
-# define XElf_Off Elf32_Off
-# define XElf_Addr Elf32_Addr
-# define XElf_Half Elf32_Half
-# define XElf_Word Elf32_Word
-# define XElf_Xword Elf32_Word
-# define XElf_Sxword Elf32_Sword
-# define XElf_Versym Elf32_Versym
-# define XElf_Sym Elf32_Sym
-# define XElf_Rel Elf32_Rel
-# define XElf_Rela Elf32_Rela
-
-# define XElf_Ehdr_vardef(name) Elf32_Ehdr *name
-# define xelf_getehdr(elf, name) name = elf32_getehdr (elf)
-# define xelf_getehdr_copy(elf, name, copy) \
-  (copy) = *(name = elf32_getehdr (elf))
-# define xelf_newehdr(elf, klass) elf32_newehdr (elf)
-# define xelf_update_ehdr(elf, ehdr) \
-  /* nothing */ ((void) (elf), (void) (ehdr), 1)
-
-# define xelf_getclass(elf) ELFCLASS32
-
-# define XElf_Phdr_vardef(name) Elf32_Phdr *name
-# define xelf_newphdr(elf, n) elf32_newphdr (elf, n)
-# define xelf_getphdr(elf, idx, name) name = elf32_getphdr (elf) + idx
-# define xelf_getphdr_ptr(elf, idx, name) name = elf32_getphdr (elf) + idx
-# define xelf_update_phdr(elf, idx, phdr) \
-  /* nothing */ ((void) (elf), (void) (idx), (void) (phdr), 1)
-
-# define XElf_Shdr_vardef(name) Elf32_Shdr *name
-# define xelf_getshdr(scn, name) name = elf32_getshdr (scn)
-# define xelf_getshdr_copy(scn, name, copy) \
-  (copy) = *(name = elf32_getshdr (scn))
-# define xelf_update_shdr(scn, shdr) \
-  /* nothing */ ((void) (scn), (void) (shdr), 1)
-
-# define XElf_Sym_vardef(name) Elf32_Sym *name
-# define xelf_getsym(data, idx, name) \
-  name = &((Elf32_Sym *) (data)->d_buf)[idx]
-# define xelf_getsym_ptr(data, idx, name) \
-  name = &((Elf32_Sym *) (data)->d_buf)[idx]
-# define xelf_getsymshndx(data, ndxdata, idx, name1, name2) \
-  (name1 = &((Elf32_Sym *) ((data)->d_buf))[idx]);			      \
-  name2 = (unlikely ((ndxdata) != NULL)					      \
-	   ? ((Elf32_Word *) ((ndxdata)->d_buf))[idx] : 0)
-# define xelf_update_sym(data, idx, sym) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (sym), 1)
-# define xelf_update_symshndx(data, ndxdata, idx, name1, name2, datachanged) \
-  if (datachanged)							      \
-    ((Elf32_Sym *) ((data)->d_buf))[idx] = *name1;			      \
-  if (unlikely (ndxdata != NULL))					      \
-    ((Elf32_Word *) ((ndxdata)->d_buf))[idx] = name2
-
-# define XElf_Versym_vardef(name) Elf32_Versym name
-# define xelf_getversym_copy(data, idx, name) \
-  (name = ((Elf32_Versym *) ((data)->d_buf))[idx], &name)
-
-# define XElf_Dyn_vardef(name) Elf32_Dyn *name
-# define xelf_getdyn(data, idx, name) \
-  name = &((Elf32_Dyn *) ((data)->d_buf))[idx]
-# define xelf_getdyn_ptr(data, idx, name) \
-  name = &((Elf32_Dyn *) ((data)->d_buf))[idx]
-# define xelf_update_dyn(data, idx, name) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rel_vardef(name) Elf32_Rel *name
-# define xelf_getrel(data, idx, name) \
-  name = &((Elf32_Rel *) ((data)->d_buf))[idx]
-# define xelf_getrel_ptr(data, idx, name) \
-  name = &((Elf32_Rel *) ((data)->d_buf))[idx]
-# define xelf_update_rel(data, idx, name) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rela_vardef(name) Elf32_Rela *name
-# define xelf_getrela(data, idx, name) \
-  name = &((Elf32_Rela *) ((data)->d_buf))[idx]
-# define xelf_getrela_ptr(data, idx, name) \
-  name = &((Elf32_Rela *) ((data)->d_buf))[idx]
-# define xelf_update_rela(data, idx, name) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Verdef_vardef(name) Elf32_Verdef *name
-# define xelf_getverdef(data, offset, name) \
-  name = ((Elf32_Verdef *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XElf_Verdaux_vardef(name) Elf32_Verdaux *name
-# define xelf_getverdaux(data, offset, name) \
-  name = ((Elf32_Verdaux *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XELF_ST_TYPE(info) ELF32_ST_TYPE (info)
-# define XELF_ST_BIND(info) ELF32_ST_BIND (info)
-# define XELF_ST_INFO(bind, type) ELF32_ST_INFO (bind, type)
-# define XELF_ST_VISIBILITY(info) ELF32_ST_VISIBILITY (info)
-
-# define XELF_R_SYM(info) ELF32_R_SYM (info)
-# define XELF_R_TYPE(info) ELF32_R_TYPE (info)
-# define XELF_R_INFO(sym, type) ELF32_R_INFO (sym, type)
-
-# define xelf_fsize(elf, type, cnt) \
-  (__builtin_constant_p (type)						      \
-   ? ({ size_t fsize;							      \
-        switch (type)							      \
-	  {								      \
-	  case ELF_T_BYTE: fsize = 1; break;				      \
-	  case ELF_T_ADDR: fsize = sizeof (Elf32_Addr); break;		      \
-	  case ELF_T_DYN: fsize = sizeof (Elf32_Dyn); break;		      \
-	  case ELF_T_EHDR: fsize = sizeof (Elf32_Ehdr); break;		      \
-	  case ELF_T_HALF: fsize = sizeof (Elf32_Half); break;		      \
-	  case ELF_T_OFF: fsize = sizeof (Elf32_Off); break;		      \
-	  case ELF_T_PHDR: fsize = sizeof (Elf32_Phdr); break;		      \
-	  case ELF_T_RELA: fsize = sizeof (Elf32_Rela); break;		      \
-	  case ELF_T_REL: fsize = sizeof (Elf32_Rel); break;		      \
-	  case ELF_T_SHDR: fsize = sizeof (Elf32_Shdr); break;		      \
-	  case ELF_T_SWORD: fsize = sizeof (Elf32_Sword); break;	      \
-	  case ELF_T_SYM: fsize = sizeof (Elf32_Sym); break;		      \
-	  case ELF_T_WORD: fsize = sizeof (Elf32_Word); break;		      \
-	  case ELF_T_XWORD: fsize = sizeof (Elf32_Xword); break;	      \
-	  case ELF_T_SXWORD: fsize = sizeof (Elf32_Sxword); break;	      \
-	  case ELF_T_VDEF: fsize = sizeof (Elf32_Verdef); break;	      \
-	  case ELF_T_VDAUX: fsize = sizeof (Elf32_Verdaux); break;	      \
-	  case ELF_T_VNEED: fsize = sizeof (Elf32_Verneed); break;	      \
-	  case ELF_T_VNAUX: fsize = sizeof (Elf32_Vernaux); break;	      \
-	  case ELF_T_NHDR: fsize = sizeof (Elf32_Nhdr); break;		      \
-	  case ELF_T_SYMINFO: fsize = sizeof (Elf32_Syminfo); break;	      \
-	  case ELF_T_MOVE: fsize = sizeof (Elf32_Move); break;		      \
-          default: fsize = 0; break;					      \
-	  }								      \
-        fsize * (cnt); })						      \
-   : gelf_fsize (elf, type, cnt, EV_CURRENT))
-#elif NATIVE_ELF == 64
-/* 64-bit only.  */
-# define XElf_Ehdr Elf64_Ehdr
-# define XElf_Shdr Elf64_Shdr
-# define XElf_Addr Elf64_Addr
-# define XElf_Half Elf64_Half
-# define XElf_Off Elf64_Off
-# define XElf_Word Elf64_Word
-# define XElf_Xword Elf64_Xword
-# define XElf_Sxword Elf64_Sxword
-# define XElf_Versym Elf64_Versym
-# define XElf_Sym Elf64_Sym
-# define XElf_Rel Elf64_Rel
-# define XElf_Rela Elf64_Rela
-
-# define XElf_Ehdr_vardef(name) Elf64_Ehdr *name
-# define xelf_getehdr(elf, name) name = elf64_getehdr (elf)
-# define xelf_getehdr_copy(elf, name, copy) \
-  (copy) = *(name = elf64_getehdr (elf))
-# define xelf_newehdr(elf, klass) elf64_newehdr (elf)
-# define xelf_update_ehdr(elf, ehdr) \
-  /* nothing */ ((void) (elf), (void) (ehdr), 1)
-
-# define xelf_getclass(elf) ELFCLASS32
-
-# define XElf_Phdr_vardef(name) Elf64_Phdr *name
-# define xelf_newphdr(elf, n) elf64_newphdr (elf, n)
-# define xelf_getphdr(elf, idx, name) name = elf64_getphdr (elf) + idx
-# define xelf_getphdr_ptr(elf, idx, name) name = elf64_getphdr (elf) + idx
-# define xelf_update_phdr(elf, idx, phdr) \
-  /* nothing */ ((void) (elf), (void) (idx), (void) (phdr), 1)
-
-# define XElf_Shdr_vardef(name) Elf64_Shdr *name
-# define xelf_getshdr(scn, name) name = elf64_getshdr (scn)
-# define xelf_getshdr_copy(scn, name, copy) \
-  (copy) = *(name = elf64_getshdr (scn))
-# define xelf_update_shdr(scn, shdr) \
-  /* nothing */ ((void) (scn), (void) (shdr), 1)
-
-# define XElf_Sym_vardef(name) Elf64_Sym *name
-# define xelf_getsym(data, idx, name) \
-  name = &((Elf64_Sym *) (data)->d_buf)[idx]
-# define xelf_getsym_ptr(data, idx, name) \
-  name = &((Elf64_Sym *) (data)->d_buf)[idx]
-# define xelf_getsymshndx(data, ndxdata, idx, name1, name2) \
-  (name1 = &((Elf64_Sym *) ((data)->d_buf))[idx]);			      \
-  name2 = (unlikely ((ndxdata) != NULL)					      \
-	   ? ((Elf32_Word *) ((ndxdata)->d_buf))[idx] : 0)
-# define xelf_update_sym(data, idx, sym) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (sym), 1)
-# define xelf_update_symshndx(data, ndxdata, idx, name1, name2, datachanged) \
-  if (datachanged)							      \
-    ((Elf64_Sym *) ((data)->d_buf))[idx] = *name1;			      \
-  if (ndxdata != NULL)							      \
-    (((Elf32_Word *) ((ndxdata)->d_buf))[idx] = name2)
-
-# define XElf_Versym_vardef(name) Elf64_Versym name
-# define xelf_getversym_copy(data, idx, name) \
-  (name = ((Elf64_Versym *) ((data)->d_buf))[idx], (&name))
-
-# define XElf_Dyn_vardef(name) Elf64_Dyn *name
-# define xelf_getdyn(data, idx, name) \
-  name = &((Elf64_Dyn *) ((data)->d_buf))[idx]
-# define xelf_getdyn_ptr(data, idx, name) \
-  name = &((Elf64_Dyn *) ((data)->d_buf))[idx]
-# define xelf_update_dyn(data, idx, name) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rel_vardef(name) Elf64_Rel *name
-# define xelf_getrel(data, idx, name) \
-  name = &((Elf64_Rel *) ((data)->d_buf))[idx]
-# define xelf_getrel_ptr(data, idx, name) \
-  name = &((Elf64_Rel *) ((data)->d_buf))[idx]
-# define xelf_update_rel(data, idx, name) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Rela_vardef(name) Elf64_Rela *name
-# define xelf_getrela(data, idx, name) \
-  name = &((Elf64_Rela *) ((data)->d_buf))[idx]
-# define xelf_getrela_ptr(data, idx, name) \
-  name = &((Elf64_Rela *) ((data)->d_buf))[idx]
-# define xelf_update_rela(data, idx, name) \
-  /* nothing */ ((void) (data), (void) (idx), (void) (name), 1)
-
-# define XElf_Verdef_vardef(name) Elf64_Verdef *name
-# define xelf_getverdef(data, offset, name) \
-  name = ((Elf64_Verdef *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XElf_Verdaux_vardef(name) Elf64_Verdaux *name
-# define xelf_getverdaux(data, offset, name) \
-  name = ((Elf64_Verdaux *) ((char *) ((data)->d_buf) + (offset)))
-
-# define XELF_ST_TYPE(info) ELF64_ST_TYPE (info)
-# define XELF_ST_BIND(info) ELF64_ST_BIND (info)
-# define XELF_ST_INFO(bind, type) ELF64_ST_INFO (bind, type)
-# define XELF_ST_VISIBILITY(info) ELF64_ST_VISIBILITY (info)
-
-# define XELF_R_SYM(info) ELF64_R_SYM (info)
-# define XELF_R_TYPE(info) ELF64_R_TYPE (info)
-# define XELF_R_INFO(sym, type) ELF64_R_INFO (sym, type)
-
-# define xelf_fsize(elf, type, cnt) \
-  (__builtin_constant_p (type)						      \
-   ? ({ size_t fsize;							      \
-        switch (type)							      \
-	  {								      \
-	  case ELF_T_BYTE: fsize = 1; break;				      \
-	  case ELF_T_ADDR: fsize = sizeof (Elf64_Addr); break;		      \
-	  case ELF_T_DYN: fsize = sizeof (Elf64_Dyn); break;		      \
-	  case ELF_T_EHDR: fsize = sizeof (Elf64_Ehdr); break;		      \
-	  case ELF_T_HALF: fsize = sizeof (Elf64_Half); break;		      \
-	  case ELF_T_OFF: fsize = sizeof (Elf64_Off); break;		      \
-	  case ELF_T_PHDR: fsize = sizeof (Elf64_Phdr); break;		      \
-	  case ELF_T_RELA: fsize = sizeof (Elf64_Rela); break;		      \
-	  case ELF_T_REL: fsize = sizeof (Elf64_Rel); break;		      \
-	  case ELF_T_SHDR: fsize = sizeof (Elf64_Shdr); break;		      \
-	  case ELF_T_SWORD: fsize = sizeof (Elf64_Sword); break;	      \
-	  case ELF_T_SYM: fsize = sizeof (Elf64_Sym); break;		      \
-	  case ELF_T_WORD: fsize = sizeof (Elf64_Word); break;		      \
-	  case ELF_T_XWORD: fsize = sizeof (Elf64_Xword); break;	      \
-	  case ELF_T_SXWORD: fsize = sizeof (Elf64_Sxword); break;	      \
-	  case ELF_T_VDEF: fsize = sizeof (Elf64_Verdef); break;	      \
-	  case ELF_T_VDAUX: fsize = sizeof (Elf64_Verdaux); break;	      \
-	  case ELF_T_VNEED: fsize = sizeof (Elf64_Verneed); break;	      \
-	  case ELF_T_VNAUX: fsize = sizeof (Elf64_Vernaux); break;	      \
-	  case ELF_T_NHDR: fsize = sizeof (Elf64_Nhdr); break;		      \
-	  case ELF_T_SYMINFO: fsize = sizeof (Elf64_Syminfo); break;	      \
-	  case ELF_T_MOVE: fsize = sizeof (Elf64_Move); break;		      \
-          default: fsize = 0; break;					      \
-	  }								      \
-        fsize * (cnt); })						      \
-   : gelf_fsize (elf, type, cnt, EV_CURRENT))
-#else
-# include <gelf.h>
-
-/* Generic linker.  */
-# define XElf_Ehdr GElf_Ehdr
-# define XElf_Shdr GElf_Shdr
-# define XElf_Addr GElf_Addr
-# define XElf_Half GElf_Half
-# define XElf_Off GElf_Off
-# define XElf_Word GElf_Word
-# define XElf_Xword GElf_Xword
-# define XElf_Sxword GElf_Sxword
-# define XElf_Versym GElf_Versym
-# define XElf_Sym GElf_Sym
-# define XElf_Rel GElf_Rel
-# define XElf_Rela GElf_Rela
-
-# define XElf_Ehdr_vardef(name) GElf_Ehdr name##_mem; GElf_Ehdr *name
-# define xelf_getehdr(elf, name) name = gelf_getehdr (elf, &name##_mem)
-# define xelf_getehdr_copy(elf, name, copy) \
-  name = gelf_getehdr (elf, &(copy))
-# define xelf_newehdr(elf, klass) gelf_newehdr (elf, klass)
-# define xelf_update_ehdr(elf, ehdr) gelf_update_ehdr (elf, ehdr)
-
-# define xelf_getclass(elf) gelf_getclass (elf)
-
-# define XElf_Phdr_vardef(name) GElf_Phdr name##_mem; GElf_Phdr *name
-# define xelf_newphdr(elf, n) gelf_newphdr (elf, n)
-# define xelf_getphdr(elf, idx, name) \
-  name = gelf_getphdr (elf, idx, &name##_mem)
-# define xelf_getphdr_ptr(elf, idx, name) \
-  name = &name##_mem
-# define xelf_update_phdr(elf, idx, phdr) \
-  gelf_update_phdr (elf, idx, phdr)
-
-# define XElf_Shdr_vardef(name) GElf_Shdr name##_mem; GElf_Shdr *name
-# define xelf_getshdr(scn, name) name = gelf_getshdr (scn, &name##_mem)
-# define xelf_getshdr_copy(scn, name, copy) \
-  name = gelf_getshdr (scn, &(copy))
-# define xelf_update_shdr(scn, shdr) gelf_update_shdr (scn, shdr)
-
-# define XElf_Sym_vardef(name) GElf_Sym name##_mem; GElf_Sym *name
-# define xelf_getsym(data, idx, name) \
-  name = gelf_getsym (data, idx, &name##_mem)
-# define xelf_getsym_ptr(data, idx, name) \
-  name = &name##_mem
-# define xelf_getsymshndx(data, ndxdata, idx, name1, name2) \
-  name1 = gelf_getsymshndx (data, ndxdata, idx, &name1##_mem, &(name2))
-# define xelf_update_sym(data, idx, sym) gelf_update_sym (data, idx, sym)
-# define xelf_update_symshndx(data, ndxdata, idx, name1, name2, datachanged) \
-  gelf_update_symshndx (data, ndxdata, idx, name1, name2)
-
-# define XElf_Versym_vardef(name) GElf_Versym name
-# define xelf_getversym_copy(data, idx, name) \
-  gelf_getversym (data, idx, &name)
-
-# define XElf_Dyn_vardef(name) GElf_Dyn name##_mem; GElf_Dyn *name
-# define xelf_getdyn(data, idx, name) \
-  name = gelf_getdyn (data, idx, &name##_mem)
-# define xelf_getdyn_ptr(data, idx, name) \
-  name = &name##_mem
-# define xelf_update_dyn(data, idx, name) \
-  gelf_update_dyn (data, idx, name)
-
-# define XElf_Rel_vardef(name) GElf_Rel name##_mem; GElf_Rel *name
-# define xelf_getrel(data, idx, name) \
-  name = gelf_getrel (data, idx, &name##_mem)
-# define xelf_getrel_ptr(data, idx, name) \
-  name = &name##_mem
-# define xelf_update_rel(data, idx, name) \
-  gelf_update_rel (data, idx, name)
-
-# define XElf_Rela_vardef(name) GElf_Rela name##_mem; GElf_Rela *name
-# define xelf_getrela(data, idx, name) \
-  name = gelf_getrela (data, idx, &name##_mem)
-# define xelf_getrela_ptr(data, idx, name) \
-  name = &name##_mem
-# define xelf_update_rela(data, idx, name) \
-  gelf_update_rela (data, idx, name)
-
-# define XElf_Verdef_vardef(name) GElf_Verdef name##_mem; GElf_Verdef *name
-# define xelf_getverdef(data, offset, name) \
-  name = gelf_getverdef (data, offset, &name##_mem)
-
-# define XElf_Verdaux_vardef(name) GElf_Verdaux name##_mem; GElf_Verdaux *name
-# define xelf_getverdaux(data, offset, name) \
-  name = gelf_getverdaux (data, offset, &name##_mem)
-
-# define XELF_ST_TYPE(info) GELF_ST_TYPE (info)
-# define XELF_ST_BIND(info) GELF_ST_BIND (info)
-# define XELF_ST_INFO(bind, type) GELF_ST_INFO (bind, type)
-# define XELF_ST_VISIBILITY(info) GELF_ST_VISIBILITY (info)
-
-# define XELF_R_SYM(info) GELF_R_SYM (info)
-# define XELF_R_TYPE(info) GELF_R_TYPE (info)
-# define XELF_R_INFO(sym, type) GELF_R_INFO (sym, type)
-
-# define xelf_fsize(elf, type, cnt) \
-  gelf_fsize (elf, type, cnt, EV_CURRENT)
-#endif
-- 
2.7.4

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2016-08-03 16:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-08-03 16:26 [PATCH] Remove eu-ld and unused code Mark Wielaard
  -- strict thread matches above, loose matches on Subject: below --
2016-07-08 13:09 Mark Wielaard
2016-07-07  7:55 Mark Wielaard
2016-07-06 22:04 Ulrich Drepper
2016-07-06 21:10 Mark Wielaard

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).