This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Remove eu-ld and unused code.


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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]