Revert c99 syntax in elfutils.
authorjbj <devnull@localhost>
Thu, 6 Mar 2003 00:57:54 +0000 (00:57 +0000)
committerjbj <devnull@localhost>
Thu, 6 Mar 2003 00:57:54 +0000 (00:57 +0000)
Fiddles to build on Red Hat 7.3.

CVS patchset: 6654
CVS date: 2003/03/06 00:57:54

19 files changed:
elfutils/libasm/asm_addint8.c
elfutils/libasm/asm_addsleb128.c
elfutils/libasm/asm_adduleb128.c
elfutils/libasm/asm_align.c
elfutils/libasm/asm_end.c
elfutils/libdw/dwarf_begin_elf.c
elfutils/libdw/dwarf_get_pubnames.c
elfutils/libebl/eblcorenote.c
elfutils/libebl/eblobjnote.c
elfutils/libebl/eblopenbackend.c
elfutils/libebl/i386_corenote.c
elfutils/po/elfutils.pot
elfutils/src/elflint.c
elfutils/src/nm.c
elfutils/src/readelf.c
elfutils/src/strip.c
elfutils/tests/ecp.c
elfutils/tests/get-pubnames2.c
elfutils/tests/newscn.c

index b089d1c..677d484 100644 (file)
@@ -2,18 +2,15 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #define BSWAP(size) _BSWAP(size)
 #define _BSWAP(size) bswap_##size
 
+
 int
 FCT(SIZE) (asmscn, num)
      AsmScn_t *asmscn;
      TYPE(SIZE) num;
 {
+  TYPE(SIZE) var;
   if (asmscn == NULL)
     return -1;
 
@@ -79,10 +78,11 @@ FCT(SIZE) (asmscn, num)
       bool is_leb = (elf_getident (asmscn->ctx->out.elf, NULL)[EI_DATA]
                     == ELFDATA2LSB);
 #endif
-      TYPE(SIZE) var = num;
+      var = num;
 
       /* Make sure we have enough room.  */
-      __libasm_ensure_section_space (asmscn, SIZE / 8);
+      if (__libasm_ensure_section_space (asmscn, SIZE / 8) != 0)
+       return -1;
 
 #if SIZE > 8
       if ((BYTE_ORDER == LITTLE_ENDIAN && !is_leb)
@@ -91,7 +91,8 @@ FCT(SIZE) (asmscn, num)
 #endif
 
       /* Copy the variable value.  */
-      memcpy (&asmscn->content->data[asmscn->content->len], &var, SIZE / 8);
+      if (likely (asmscn->type == SHT_NOBITS))
+       memcpy (&asmscn->content->data[asmscn->content->len], &var, SIZE / 8);
 
       /* Adjust the pointer in the data buffer.  */
       asmscn->content->len += SIZE / 8;
index e517202..f02a2a7 100644 (file)
@@ -2,18 +2,15 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -47,6 +44,7 @@ asm_addsleb128 (asmscn, num)
       char *dest = tmpbuf;
       uint32_t byte;
       int32_t endval = num >> 31;
+      size_t nbytes;
 
       if (num == 0)
        byte = 0;
@@ -66,7 +64,7 @@ asm_addsleb128 (asmscn, num)
       *dest++ = byte;
 
       /* Number of bytes produced.  */
-      size_t nbytes = dest - tmpbuf;
+      nbytes = dest - tmpbuf;
 
       /* Make sure we have enough room.  */
       if (__libasm_ensure_section_space (asmscn, nbytes) != 0)
index d7923b4..8fb1ac5 100644 (file)
@@ -2,18 +2,15 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -46,6 +43,7 @@ asm_adduleb128 (asmscn, num)
       char tmpbuf[(sizeof (num) * 8 + 6) / 7];
       char *dest = tmpbuf;
       uint32_t byte;
+      size_t nbytes;
 
       while (1)
        {
@@ -62,7 +60,7 @@ asm_adduleb128 (asmscn, num)
       *dest++ = byte;
 
       /* Number of bytes produced.  */
-      size_t nbytes = dest - tmpbuf;
+      nbytes = dest - tmpbuf;
 
       /* Make sure we have enough room.  */
       if (__libasm_ensure_section_space (asmscn, nbytes) != 0)
index eb6db67..c199966 100644 (file)
@@ -2,23 +2,21 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#include <stdlib.h>
 #include <sys/param.h>
 
 #include <libasmP.h>
@@ -30,6 +28,7 @@ asm_align (asmscn, value)
      AsmScn_t *asmscn;
      GElf_Word value;
 {
+  int result = 0;
   if (asmscn == NULL)
     /* An earlier error.  */
     return -1;
@@ -53,7 +52,9 @@ asm_align (asmscn, value)
       cnt = value - (asmscn->offset & (value - 1));
 
       /* Ensure there is enough room to add the fill bytes.  */
-      __libasm_ensure_section_space (asmscn, cnt);
+      result = __libasm_ensure_section_space (asmscn, cnt);
+      if (result != 0)
+       goto out;
 
       /* Fill in the bytes.  We align the pattern according to the
         current offset.  */
@@ -90,15 +91,16 @@ asm_align (asmscn, value)
        }
     }
 
+ out:
   rwlock_unlock (asmscn->ctx->lock);
 
-  return 0;
+  return result;
 }
 
 
 /* Ensure there are at least LEN bytes available in the output buffer
    for ASMSCN.  */
-void
+int
 __libasm_ensure_section_space (asmscn, len)
      AsmScn_t *asmscn;
      size_t len;
@@ -112,8 +114,10 @@ __libasm_ensure_section_space (asmscn, len)
       /* This is the first block.  */
       size = MAX (2 * len, 960);
 
-      asmscn->content = (struct AsmData *) xmalloc (sizeof (struct AsmData)
-                                                   + size);
+      asmscn->content = (struct AsmData *) malloc (sizeof (struct AsmData)
+                                                  + size);
+      if (asmscn->content == NULL)
+       return -1;
 
       asmscn->content->next = asmscn->content;
     }
@@ -123,11 +127,13 @@ __libasm_ensure_section_space (asmscn, len)
 
       if (asmscn->content->maxlen - asmscn->content->len >= len)
        /* Nothing to do, there is enough space.  */
-       return;
+       return 0;
 
       size = MAX (2 *len, MIN (32768, 2 * asmscn->offset));
 
-      newp = (struct AsmData *) xmalloc (sizeof (struct AsmData) + size);
+      newp = (struct AsmData *) malloc (sizeof (struct AsmData) + size);
+      if (newp == NULL)
+       return -1;
 
       newp->next = asmscn->content->next;
       asmscn->content = asmscn->content->next = newp;
@@ -135,4 +141,6 @@ __libasm_ensure_section_space (asmscn, len)
 
   asmscn->content->len = 0;
   asmscn->content->maxlen = size;
+
+  return 0;
 }
index 3f10856..39bc6b2 100644 (file)
@@ -1,19 +1,16 @@
 /* Finalize operations on the assembler context, free all resources.
-   Copyright (C) 2002 Red Hat, Inc.
+   Copyright (C) 2002, 2003 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -55,11 +52,16 @@ binary_end (AsmCtx_t *ctx)
   size_t strscnndx = 0;
   size_t xndxscnndx = 0;
   Elf_Data *data;
+  Elf_Data *shstrtabdata;
+  Elf_Data *strtabdata = NULL;
+  Elf_Data *xndxdata = NULL;
   GElf_Shdr shdr_mem;
   GElf_Shdr *shdr;
   GElf_Ehdr ehdr_mem;
   GElf_Ehdr *ehdr;
   AsmScn_t *asmscn;
+  int result = 0;
+  AsmScnGrp_t *scngrp;
 
   /* Iterate over the created sections and compute the offsets of the
      various subsections and fill in the content.  */
@@ -128,14 +130,14 @@ binary_end (AsmCtx_t *ctx)
 
       /* Create the symbol string table section.  */
       strscn = elf_newscn (ctx->out.elf);
-      data = elf_newdata (strscn);
+      strtabdata = elf_newdata (strscn);
       shdr = gelf_getshdr (strscn, &shdr_mem);
-      if (data == NULL || shdr == NULL)
+      if (strtabdata == NULL || shdr == NULL)
        error (EXIT_FAILURE, 0, _("cannot create section for output file: %s"),
               elf_errmsg (-1));
       strscnndx = elf_ndxscn (strscn);
 
-      ebl_strtabfinalize (ctx->symbol_strtab, data);
+      ebl_strtabfinalize (ctx->symbol_strtab, strtabdata);
 
       shdr->sh_type = SHT_STRTAB;
       assert (shdr->sh_entsize == 0);
@@ -154,7 +156,9 @@ binary_end (AsmCtx_t *ctx)
       /* We know how many symbols there will be in the symbol table.  */
       data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
                                 ctx->nsymbol_tab + 1, EV_CURRENT);
-      symtab = xmalloc (data->d_size);
+      symtab = malloc (data->d_size);
+      if (symtab == NULL)
+       return -1;
       data->d_buf = symtab;
       data->d_type = ELF_T_SYM;
       data->d_off = 0;
@@ -182,7 +186,8 @@ binary_end (AsmCtx_t *ctx)
            syment.st_value = sym->scn->offset + sym->offset;
            syment.st_size = sym->size;
 
-           /* Add local symbols at the beginning, the other from the end.  */
+           /* Add local symbols at the beginning, the other from
+              the end.  */
            ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
 
            /* Determine the section index.  We have to handle the
@@ -203,7 +208,6 @@ binary_end (AsmCtx_t *ctx)
                       exist.  */
                    Elf_Scn *xndxscn;
                    size_t symscnndx = elf_ndxscn (symscn);
-                   Elf_Data *xndxdata;
 
                    xndxscn = elf_newscn (ctx->out.elf);
                    xndxdata = elf_newdata (xndxscn);
@@ -216,6 +220,7 @@ cannot create extended section index table: %s"),
 
                    shdr->sh_type = SHT_SYMTAB_SHNDX;
                    shdr->sh_entsize = sizeof (Elf32_Word);
+                   shdr->sh_addralign = sizeof (Elf32_Word);
                    shdr->sh_link = symscnndx;
 
                    (void) gelf_update_shdr (xndxscn, shdr);
@@ -228,7 +233,9 @@ cannot create extended section index table: %s"),
                    xndxdata->d_size = elf32_fsize (ELF_T_WORD,
                                                    ctx->nsymbol_tab + 1,
                                                    EV_CURRENT);
-                   xshndx = xndxdata->d_buf = xcalloc (1, xndxdata->d_size);
+                   xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
+                   if (xshndx == NULL)
+                     return -1;
                    /* Using ELF_T_WORD here relies on the fact that the
                       32- and 64-bit types are the same size.  */
                    xndxdata->d_type = ELF_T_WORD;
@@ -257,6 +264,8 @@ cannot create extended section index table: %s"),
       shdr->sh_link = strscnndx;
       shdr->sh_info = ptr_local;
       shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
+      shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
+                                      EV_CURRENT);
 
       (void) gelf_update_shdr (symscn, shdr);
     }
@@ -265,9 +274,9 @@ cannot create extended section index table: %s"),
   /* Create the section header string table section and fill in the
      references in the section headers.  */
   shstrscn = elf_newscn (ctx->out.elf);
-  data = elf_newdata (shstrscn);
+  shstrtabdata = elf_newdata (shstrscn);
   shdr = gelf_getshdr (shstrscn, &shdr_mem);
-  if (shstrscn == NULL || data == NULL || shdr == NULL)
+  if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
     error (EXIT_FAILURE, 0, _("cannot create section for output file: %s"),
           elf_errmsg (-1));
 
@@ -275,7 +284,7 @@ cannot create extended section index table: %s"),
   /* Add the name of the section header string table.  */
   shstrscn_strent = ebl_strtabadd (ctx->section_strtab, ".shstrtab", 10);
 
-  ebl_strtabfinalize (ctx->section_strtab, data);
+  ebl_strtabfinalize (ctx->section_strtab, shstrtabdata);
 
   shdr->sh_type = SHT_STRTAB;
   assert (shdr->sh_entsize == 0);
@@ -312,7 +321,9 @@ cannot create extended section index table: %s"),
             here.  */
          data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
                                      EV_CURRENT);
-         grpdata = data->d_buf = xmalloc (data->d_size);
+         grpdata = data->d_buf = malloc (data->d_size);
+         if (grpdata == NULL)
+           return -1;
          data->d_type = ELF_T_WORD;
          data->d_off = 0;
          data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
@@ -438,19 +449,36 @@ cannot create extended section index table: %s"),
   /* Write out the ELF file.  */
   if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP)) < 0)
     {
-    err_libelf:
       __libasm_seterrno (ASM_E_LIBELF);
-      return -1;
+      result = -1;
     }
 
+  /* We do not need the section header and symbol string tables anymore.  */
+  free (shstrtabdata->d_buf);
+  if (strtabdata != NULL)
+    free (strtabdata->d_buf);
+  /* We might have allocated the extended symbol table index.  */
+  if (xndxdata != NULL)
+    free (xndxdata->d_buf);
+
+  /* Free section groups memory.  */
+  scngrp = ctx->groups;
+  if (scngrp != NULL)
+    do
+      free (elf_getdata (scngrp->scn, NULL)->d_buf);
+    while ((scngrp = scngrp->next) != ctx->groups);
+
   /* Finalize the ELF handling.  */
   if (unlikely (elf_end (ctx->out.elf)) != 0)
-    goto err_libelf;
+    {
+      __libasm_seterrno (ASM_E_LIBELF);
+      result = -1;
+    }
 
   /* Free the temporary resources.  */
   free (symtab);
 
-  return 0;
+  return result;
 }
 
 
@@ -489,10 +517,65 @@ asm_end (ctx)
 }
 
 
+static void
+free_section (AsmScn_t *scnp)
+{
+  void *oldp;
+  struct AsmData *data;
+
+  if (scnp->subnext != NULL)
+    free_section (scnp->subnext);
+
+  data = scnp->content;
+  if (data != NULL)
+    do
+      {
+       oldp = data;
+       data = data->next;
+       free (oldp);
+      }
+    while (oldp != scnp->content);
+
+  free (scnp);
+}
+
+
 void
 __libasm_finictx (ctx)
      AsmCtx_t *ctx;
 {
+  void *runp = NULL;
+  AsmSym_t *sym;
+  AsmScnGrp_t *scngrp;
+
+  /* Iterate through section table and free individual entries.  */
+  AsmScn_t *scn = ctx->section_list;
+  while (scn != NULL)
+    {
+      AsmScn_t *oldp = scn;
+      scn = scn->allnext;
+      free_section (oldp);
+    }
+
+  /* Free the resources of the symbol table.  */
+  while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
+    free (sym);
+  asm_symbol_tab_free (&ctx->symbol_tab);
+
+
+  /* Free section groups.  */
+  scngrp = ctx->groups;
+  if (scngrp != NULL)
+    do
+      {
+       AsmScnGrp_t *oldp = scngrp;
+
+       scngrp = scngrp->next;
+       free (oldp);
+      }
+    while (scngrp != ctx->groups);
+
+
   if (unlikely (ctx->textp))
     {
       /* Close the stream.  */
@@ -505,11 +588,6 @@ __libasm_finictx (ctx)
         find any.  */
       (void) close (ctx->fd);
 
-
-      /* XXX Iterate through section table and free individual entries.  */
-
-      /* Free the resources of the hash table.  */
-      asm_symbol_tab_free (&ctx->symbol_tab);
       /* And the string tables.  */
       ebl_strtabfree (ctx->section_strtab);
       ebl_strtabfree (ctx->symbol_strtab);
index 7523aa2..aaa0c1d 100644 (file)
@@ -54,6 +54,8 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
 {
   GElf_Shdr shdr_mem;
   GElf_Shdr *shdr;
+  const char *scnname;
+  int cnt;
 
   /* Get the section header data.  */
   shdr = gelf_getshdr (scn, &shdr_mem);
@@ -75,7 +77,7 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
 
   /* We recognize the DWARF section by their names.  This is not very
      safe and stable but the best we can do.  */
-  const char *scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
+  scnname = elf_strptr (result->elf, ehdr->e_shstrndx,
                                    shdr->sh_name);
   if (scnname == NULL)
     {
@@ -88,17 +90,17 @@ check_section (Dwarf *result, GElf_Ehdr *ehdr, Elf_Scn *scn, bool inscngrp)
 
 
   /* Recognize the various sections.  Most names start with .debug_.  */
-  int cnt;
   for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
     if (strcmp (scnname, dwarf_scnnames[cnt]) == 0)
       {
+       Elf_Data *data;
        /* Found it.  Remember where the data is.  */
        if (unlikely (result->sectiondata[cnt] != NULL))
          /* A section appears twice.  That's bad.  We ignore the section.  */
          break;
 
        /* Get the section data.  */
-       Elf_Data *data = elf_getdata (scn, NULL);
+       data = elf_getdata (scn, NULL);
        if (data != NULL && data->d_size != 0)
          /* Yep, there is actually data available.  */
          result->sectiondata[cnt] = data;
@@ -144,6 +146,8 @@ static Dwarf *
 scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Dwarf_Cmd cmd,
             Elf_Scn *scngrp)
 {
+  Elf32_Word *scnidx;
+  size_t cnt;
   /* SCNGRP is the section descriptor for a section group which might
      contain debug sections.  */
   Elf_Data *data = elf_getdata (scngrp, NULL);
@@ -156,8 +160,7 @@ scngrp_read (Dwarf *result, Elf *elf, GElf_Ehdr *ehdr, Dwarf_Cmd cmd,
 
   /* The content of the section is a number of 32-bit words which
      represent section indices.  The first word is a flag word.  */
-  Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
-  size_t cnt;
+  scnidx = (Elf32_Word *) data->d_buf;
   for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
     {
       Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
@@ -185,6 +188,7 @@ dwarf_begin_elf (elf, cmd, scngrp)
 {
   GElf_Ehdr *ehdr;
   GElf_Ehdr ehdr_mem;
+  Dwarf *result;
 
   /* Get the ELF header of the file.  We need various pieces of
      information from it.  */
@@ -201,7 +205,7 @@ dwarf_begin_elf (elf, cmd, scngrp)
 
 
   /* Allocate the data structure.  */
-  Dwarf *result = (Dwarf *) calloc (1, sizeof (Dwarf));
+  result = (Dwarf *) calloc (1, sizeof (Dwarf));
   if (result == NULL)
     {
       __libdwarf_seterrno (DWARF_E_NOMEM);
@@ -235,7 +239,7 @@ dwarf_begin_elf (elf, cmd, scngrp)
       return NULL;
     }
 
-  __libdwarf_seterrno (DWARF_E_INVALIDCMD);
+  __libdwarf_seterrno (DWARF_E_INVALID_CMD);
   free (result);
   return NULL;
 }
index 022e06d..1bbcdad 100644 (file)
@@ -40,12 +40,17 @@ get_offsets (Dwarf *dbg)
 
   while (readp + 14 < endp)
     {
+      int len_bytes;
+      Dwarf_Off len;
+      uint16_t version;
+      unsigned char *infop;
+
       /* If necessary, allocate more entries.  */
       if (cnt >= allocated)
        {
+         struct pubnames_s *newmem;
          allocated = MAX (10, 2 * allocated);
-         struct pubnames_s *newmem
-           = (struct pubnames_s *) realloc (mem, allocated * entsize);
+         newmem = (struct pubnames_s *) realloc (mem, allocated * entsize);
          if (newmem == NULL)
            {
              __libdwarf_seterrno (DWARF_E_NOMEM);
@@ -58,8 +63,8 @@ get_offsets (Dwarf *dbg)
        }
 
       /* Read the set header.  */
-      int len_bytes = 4;
-      Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp);
+      len_bytes = 4;
+      len = read_4ubyte_unaligned_inc (dbg, readp);
       if (len == 0xffffffff)
        {
          len = read_8ubyte_unaligned_inc (dbg, readp);
@@ -75,7 +80,7 @@ get_offsets (Dwarf *dbg)
        break;
 
       /* Read the version.  It better be two for now.  */
-      uint16_t version = read_2ubyte_unaligned (dbg, readp);
+      version = read_2ubyte_unaligned (dbg, readp);
       if (version != 2)
        {
          __libdwarf_seterrno (DWARF_E_INVALID_VERSION);
@@ -93,8 +98,7 @@ get_offsets (Dwarf *dbg)
       assert (dbg->sectiondata[IDX_debug_info]->d_buf != NULL);
       assert (mem[cnt].cu_offset + 3
              < dbg->sectiondata[IDX_debug_info]->d_size);
-      unsigned char *infop
-       = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
+      infop = ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
           + mem[cnt].cu_offset);
       if (read_4ubyte_unaligned_noncvt (infop) == 0xffffffff)
        mem[cnt].cu_header_size = 23;
@@ -127,6 +131,10 @@ dwarf_get_pubnames (dbg, callback, arg, offset)
      void *arg;
      size_t offset;
 {
+  size_t cnt;
+  unsigned char *startp;
+  unsigned char *readp;
+
   /* Make sure it is a valid offset.  */
   if (unlikely (dbg->sectiondata[IDX_debug_pubnames] == NULL
                || offset >= dbg->sectiondata[IDX_debug_pubnames]->d_size))
@@ -138,7 +146,6 @@ dwarf_get_pubnames (dbg, callback, arg, offset)
     return (size_t) -1;
 
   /* Find the place where to start.  */
-  size_t cnt;
   if (offset == 0)
     {
       cnt = 0;
@@ -155,9 +162,8 @@ dwarf_get_pubnames (dbg, callback, arg, offset)
       assert (cnt + 1 < dbg->pubnames_nsets);
     }
 
-  unsigned char *startp
-    = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
-  unsigned char *readp = startp + offset;
+  startp = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+  readp = startp + offset;
   while (1)
     {
       Dwarf_Global gl;
index 54b68f7..5a246d2 100644 (file)
@@ -2,18 +2,15 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -44,10 +41,11 @@ ebl_core_note (ebl, name, type, descsz, desc)
        break;
 
       case NT_AUXV:
-       ;
+      {
        size_t cnt;
        size_t elsize = (class == ELFCLASS32
                         ? sizeof (Elf32_auxv_t) : sizeof (Elf64_auxv_t));
+       const char *at;
 
        for (cnt = 0; (cnt + 1) * elsize <= descsz; ++cnt)
          {
@@ -71,7 +69,6 @@ ebl_core_note (ebl, name, type, descsz, desc)
 
            /* XXX Do we need the auxiliary vector info anywhere
               else?  If yes, move code into a separate function.  */
-           const char *at;
 
            switch (type)
              {
@@ -145,6 +142,7 @@ ebl_core_note (ebl, name, type, descsz, desc)
              /* Reached the end.  */
              break;
          }
+      }
        break;
 
       default:
index 816dd74..87aadb7 100644 (file)
@@ -2,18 +2,15 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -45,6 +42,7 @@ ebl_object_note (ebl, name, type, descsz, desc)
              uint32_t os;
              uint32_t version[descsz / 4 - 1];
            } *tag = (__typeof (tag)) desc;
+           size_t cnt;
 
            const char *os;
            switch (tag->os)
@@ -71,7 +69,6 @@ ebl_object_note (ebl, name, type, descsz, desc)
              }
 
            printf (gettext ("    OS: %s, ABI: "), os);
-           size_t cnt;
            for (cnt = 0; cnt < descsz / 4 - 1; ++cnt)
              {
                if (cnt != 0)
index be899db..ef19505 100644 (file)
@@ -1,27 +1,24 @@
 /* Generate ELF backend handle.
-   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
 #include <assert.h>
+#include <dlfcn.h>
 #include <error.h>
 #include <gelf.h>
-#include <ltdl.h>
 #include <stdlib.h>
 #include <string.h>
 
@@ -41,46 +38,85 @@ static const struct
   int em;
 } machines[] =
 {
-  { "libebl_m32", "elf_m32", "m32", 3, EM_M32 },
-  { "libebl_SPARC", "elf_sparc", "sparc", 5, EM_SPARC },
-  { "libebl_i386", "elf_i386", "i386", 4, EM_386 },
-  { "libebl_m68k", "elf_m68k", "m68k", 4, EM_68K },
-  { "libebl_m88k", "elf_m88k", "m88k", 4, EM_88K },
-  { "libebl_i860", "elf_i860", "i860", 4, EM_860 },
-  { "libebl_mips", "elf_mips", "mips", 4, EM_MIPS },
-  { "libebl_s370", "ebl_s370", "s370", 4, EM_S370 },
-  { "libebl_mips", "elf_mipsel", "mips", 4, EM_MIPS_RS3_LE },
-  { "libebl_parisc", "elf_parisc", "parisc", 6, EM_PARISC },
-  { "libebl_vpp500", "elf_vpp500", "vpp500", 5, EM_VPP500 },
-  { "libebl_v8plus", "elf_v8plus", "v8plus", 6, EM_SPARC32PLUS },
-  { "libebl_i960", "elf_i960", "i960", 4, EM_960 },
-  { "libebl_ppc", "elf_ppc", "ppc", 3, EM_PPC },
-  { "libebl_ppc64", "elf_ppc64", "ppc64", 5, EM_PPC64 },
-  { "libebl_s390", "ebl_s390", "s390", 4, EM_S390 },
-  { "libebl_v800", "ebl_v800", "v800", 4, EM_V800 },
-  { "libebl_fr20", "ebl_fr20", "fr20", 4, EM_FR20 },
-  { "libebl_rh32", "ebl_rh32", "rh32", 4, EM_RH32 },
-  { "libebl_rce", "ebl_rce", "rce", 3, EM_RCE },
-  { "libebl_arm", "ebl_arm", "arm", 3, EM_ARM },
-  { "libebl_sh", "elf_sh", "sh", 2, EM_SH },
-  /* XXX Many more missing ... */
+  { "i386", "elf_i386", "i386", 4, EM_386 },
+  { "ia64", "elf_ia64", "ia64", 4, EM_IA_64 },
+  { "alpha", "elf_alpha", "alpha", 5, EM_ALPHA },
+  { "x86_64", "elf_x86_64", "x86_64", 6, EM_X86_64 },
+  { "sh", "elf_sh", "sh", 2, EM_SH },
+  { "arm", "ebl_arm", "arm", 3, EM_ARM },
+  { "sparc", "elf_sparcv9", "sparc", 5, EM_SPARCV9 },
+  { "sparc", "elf_sparc", "sparc", 5, EM_SPARC },
+  { "sparc", "elf_sparcv8plus", "sparc", 5, EM_SPARC32PLUS },
+
+  { "m32", "elf_m32", "m32", 3, EM_M32 },
+  { "m68k", "elf_m68k", "m68k", 4, EM_68K },
+  { "m88k", "elf_m88k", "m88k", 4, EM_88K },
+  { "i860", "elf_i860", "i860", 4, EM_860 },
+  { "mips", "elf_mips", "mips", 4, EM_MIPS },
+  { "s370", "ebl_s370", "s370", 4, EM_S370 },
+  { "mips", "elf_mipsel", "mips", 4, EM_MIPS_RS3_LE },
+  { "parisc", "elf_parisc", "parisc", 6, EM_PARISC },
+  { "vpp500", "elf_vpp500", "vpp500", 5, EM_VPP500 },
+  { "sparc", "elf_v8plus", "v8plus", 6, EM_SPARC32PLUS },
+  { "i960", "elf_i960", "i960", 4, EM_960 },
+  { "ppc", "elf_ppc", "ppc", 3, EM_PPC },
+  { "ppc64", "elf_ppc64", "ppc64", 5, EM_PPC64 },
+  { "s390", "ebl_s390", "s390", 4, EM_S390 },
+  { "v800", "ebl_v800", "v800", 4, EM_V800 },
+  { "fr20", "ebl_fr20", "fr20", 4, EM_FR20 },
+  { "rh32", "ebl_rh32", "rh32", 4, EM_RH32 },
+  { "rce", "ebl_rce", "rce", 3, EM_RCE },
+  { "tricore", "elf_tricore", "tricore", 7, EM_TRICORE },
+  { "arc", "elf_arc", "arc", 3, EM_ARC },
+  { "h8", "elf_h8_300", "h8_300", 6, EM_H8_300 },
+  { "h8", "elf_h8_300h", "h8_300h", 6, EM_H8_300H },
+  { "h8", "elf_h8s", "h8s", 6, EM_H8S },
+  { "h8", "elf_h8_500", "h8_500", 6, EM_H8_500 },
+  { "mips_x", "elf_mips_x", "mips_x", 6, EM_MIPS_X },
+  { "coldfire", "elf_coldfire", "coldfire", 8, EM_COLDFIRE },
+  { "m68k", "elf_68hc12", "68hc12", 6, EM_68HC12 },
+  { "mma", "elf_mma", "mma", 3, EM_MMA },
+  { "pcp", "elf_pcp", "pcp", 3, EM_PCP },
+  { "ncpu", "elf_ncpu", "ncpu", 4, EM_NCPU },
+  { "ndr1", "elf_ndr1", "ndr1", 4, EM_NDR1 },
+  { "starcore", "elf_starcore", "starcore", 8, EM_STARCORE },
+  { "me16", "elf_me16", "em16", 4, EM_ME16 },
+  { "st100", "elf_st100", "st100", 5, EM_ST100 },
+  { "tinyj", "elf_tinyj", "tinyj", 5, EM_TINYJ },
+  { "pdsp", "elf_pdsp", "pdsp", 4, EM_PDSP },
+  { "fx66", "elf_fx66", "fx66", 4, EM_FX66 },
+  { "st9plus", "elf_st9plus", "st9plus", 7, EM_ST9PLUS },
+  { "st7", "elf_st7", "st7", 3, EM_ST7 },
+  { "m68k", "elf_68hc16", "68hc16", 6, EM_68HC16 },
+  { "m68k", "elf_68hc11", "68hc11", 6, EM_68HC11 },
+  { "m68k", "elf_68hc08", "68hc08", 6, EM_68HC08 },
+  { "m68k", "elf_68hc05", "68hc05", 6, EM_68HC05 },
+  { "svx", "elf_svx", "svx", 3, EM_SVX },
+  { "st19", "elf_st19", "st19", 4, EM_ST19 },
+  { "vax", "elf_vax", "vax", 3, EM_VAX },
+  { "cris", "elf_cris", "cris", 4, EM_CRIS },
+  { "javelin", "elf_javelin", "javelin", 7, EM_JAVELIN },
+  { "firepath", "elf_firepath", "firepath", 8, EM_FIREPATH },
+  { "zsp", "elf_zsp", "zsp", 3, EM_ZSP},
+  { "mmix", "elf_mmix", "mmix", 4, EM_MMIX },
+  { "hunay", "elf_huany", "huany", 5, EM_HUANY },
+  { "prism", "elf_prism", "prism", 5, EM_PRISM },
+  { "avr", "elf_avr", "avr", 3, EM_AVR },
+  { "fr30", "elf_fr30", "fr30", 4, EM_FR30 },
+  { "dv10", "elf_dv10", "dv10", 4, EM_D10V },
+  { "dv30", "elf_dv30", "dv30", 4, EM_D30V },
+  { "v850", "elf_v850", "v850", 4, EM_V850 },
+  { "m32r", "elf_m32r", "m32r", 4, EM_M32R },
+  { "mn10300", "elf_mn10300", "mn10300", 7, EM_MN10300 },
+  { "mn10200", "elf_mn10200", "mn10200", 7, EM_MN10200 },
+  { "pj", "elf_pj", "pj", 2, EM_PJ },
+  { "openrisc", "elf_openrisc", "openrisc", 8, EM_OPENRISC },
+  { "arc", "elf_arc_a5", "arc_a5", 6, EM_ARC_A5 },
+  { "xtensa", "elf_xtensa", "xtensa", 6, EM_XTENSA },
 };
 #define nmachines (sizeof (machines) / sizeof (machines[0]))
 
 
-/* Initialize the ltdl library.  */
-static void
-dlinit (void)
-{
-  if (lt_dlinit () != 0)
-    error (EXIT_FAILURE, 0, _("initialization of libltdl failed"));
-
-  /* Make sure we can find our modules.  */
-  /* XXX Use the correct path when done.  */
-  lt_dladdsearchdir (OBJDIR "/.libs");
-}
-
-
 /* Default callbacks.  Mostly they just return the error value.  */
 static const char *default_object_type_name (int ignore, char *buf,
                                             size_t len);
@@ -104,6 +140,15 @@ 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,
+                                               size_t len);
+static const char *default_object_note_type_name (uint32_t, char *buf,
+                                                 size_t len);
+static bool default_core_note (const char *name, uint32_t type,
+                              uint32_t descsz, const char *desc);
+static bool default_object_note (const char *name, uint32_t type,
+                                uint32_t descsz, const char *desc);
+static bool default_debugscn_p (const char *name);
 
 
 /* Find an appropriate backend for the file associated with ELF.  */
@@ -113,7 +158,6 @@ openbackend (elf, emulation, machine)
      const char *emulation;
      GElf_Half machine;
 {
-  once_define (static, once);
   Ebl *result;
   int cnt;
 
@@ -128,9 +172,6 @@ openbackend (elf, emulation, machine)
       return NULL;
     }
 
-  /* We have to initialized the dynamic loading library.  */
-  once_execute (once, dlinit);
-
   /* Fill in the default callbacks.  The initializer for the machine
      specific module can overwrite the values.  */
   result->object_type_name = default_object_type_name;
@@ -147,6 +188,11 @@ openbackend (elf, emulation, machine)
   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;
+  result->core_note = default_core_note;
+  result->object_note = default_object_note;
+  result->debugscn_p = default_debugscn_p;
   result->destr = default_destr;
 
   /* XXX Currently all we do is to look at 'e_machine' value in the
@@ -162,11 +208,19 @@ openbackend (elf, emulation, machine)
     if ((emulation != NULL && strcmp (emulation, machines[cnt].emulation) == 0)
        || (emulation == NULL && machines[cnt].em == machine))
       {
+       char dsoname[100];
+       void *h;
+
+       /* Well, we know the emulation name now.  */
+       result->emulation = machines[cnt].emulation;
+
        /* Give it a try.  At least the machine type matches.  First
            try to load the module.  */
-       lt_dlhandle h;
+       strcpy (stpcpy (stpcpy (dsoname, "$ORIGIN/elfutils/libebl_"),
+                       machines[cnt].dsoname),
+               ".so");
 
-       h = lt_dlopenext (machines[cnt].dsoname);
+       h = dlopen (dsoname, RTLD_LAZY);
        if (h != NULL)
          {
            /* We managed to load the object.  Now see whether the
@@ -177,14 +231,13 @@ openbackend (elf, emulation, machine)
            strcpy (mempcpy (symname, machines[cnt].prefix,
                             machines[cnt].prefix_len), "_init");
 
-           initp = (ebl_bhinit_t) lt_dlsym (h, symname);
+           initp = (ebl_bhinit_t) dlsym (h, symname);
            if (initp != NULL
                && initp (elf, machine, result, sizeof (Ebl)) == 0)
              {
                /* We found a module to handle our file.  */
                result->dlhandle = h;
                result->elf = elf;
-               result->emulation = machines[cnt].emulation;
 
                /* A few entries are mandatory.  */
                assert (result->name != NULL);
@@ -194,8 +247,16 @@ openbackend (elf, emulation, machine)
              }
 
            /* Not the module we need.  */
-           (void) lt_dlclose (h);
+           (void) dlclose (h);
          }
+
+       /* We cannot find a DSO but the emulation/machine ID matches.
+          Return that information.  */
+       result->dlhandle = NULL;
+       result->elf = elf;
+       result->name = machines[cnt].prefix;
+
+       return result;
       }
 
   /* Nothing matched.  We use only the default callbacks.   */
@@ -335,3 +396,72 @@ default_osabi_name (int ignore, char *buf, size_t len)
 {
   return NULL;
 }
+
+static const char *
+default_core_note_type_name (uint32_t ignore, char *buf, size_t len)
+{
+  return NULL;
+}
+
+static const char *
+default_object_note_type_name (uint32_t ignore, char *buf, size_t len)
+{
+  return NULL;
+}
+
+static bool
+default_core_note (const char *name, uint32_t type, uint32_t descsz,
+                  const char *desc)
+{
+  return false;
+}
+
+static bool
+default_object_note (const char *name, uint32_t type, uint32_t descsz,
+                    const char *desc)
+{
+  return false;
+}
+
+static bool
+default_debugscn_p (const char *name)
+{
+  /* We know by default only about the DWARF debug sections which have
+     fixed names.  */
+  static const char *dwarf_scn_names[] =
+    {
+      /* 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_abbrev",
+      ".debug_line",
+      ".debug_frame",
+      ".debug_str",
+      ".debug_loc",
+      ".debug_macinfo",
+      /* DWARF 3 */
+      ".debug_ranges",
+      /* SGI/MIPS DWARF 2 extensions */
+      ".debug_weaknames",
+      ".debug_funcnames",
+      ".debug_typenames",
+      ".debug_varnames"
+    };
+  const size_t ndwarf_scn_names = (sizeof (dwarf_scn_names)
+                                  / sizeof (dwarf_scn_names[0]));
+  size_t cnt;
+
+  for (cnt = 0; cnt < ndwarf_scn_names; ++cnt)
+    if (strcmp (name, dwarf_scn_names[cnt]) == 0)
+      return true;
+
+  return false;
+}
index 5546405..08de282 100644 (file)
@@ -2,18 +2,15 @@
    Copyright (C) 2002 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -62,7 +59,10 @@ struct elf_prpsinfo
     unsigned long int pr_flag;         /* Flags.  */
     unsigned short int pr_uid;
     unsigned short int pr_gid;
-    int pr_pid, pr_ppid, pr_pgrp, pr_sid;
+    int pr_pid;
+    int pr_ppid;
+    int pr_pgrp;
+    int pr_sid;
     /* Lots missing */
     char pr_fname[16];                 /* Filename of executable.  */
     char pr_psargs[80];                        /* Initial part of arg list.  */
@@ -81,12 +81,12 @@ i386_core_note (name, type, descsz, desc)
   switch (type)
     {
     case NT_PRSTATUS:
+    { struct elf_prstatus *stat = (struct elf_prstatus *) desc;
+
       if (descsz < sizeof (struct elf_prstatus))
        /* Not enough data.  */
        break;
 
-      struct elf_prstatus *stat = (struct elf_prstatus *) desc;
-
       printf ("    SIGINFO:  signo: %d, code = %d, errno = %d\n"
              "    signal: %hd, pending: %#08lx, holding: %#08lx\n"
              "    pid: %d, ppid = %d, pgrp = %d, sid = %d\n"
@@ -104,10 +104,10 @@ i386_core_note (name, type, descsz, desc)
              stat->pr_cursig,
              stat->pr_sigpend, stat->pr_sighold,
              stat->pr_pid, stat->pr_ppid, stat->pr_pgrp, stat->pr_sid,
-             stat->pr_utime.tv_sec, stat->pr_utime.tv_usec,
-             stat->pr_stime.tv_sec, stat->pr_stime.tv_usec,
-             stat->pr_cutime.tv_sec, stat->pr_cutime.tv_usec,
-             stat->pr_cstime.tv_sec, stat->pr_cstime.tv_usec,
+             stat->pr_utime.tv_sec, (long int) stat->pr_utime.tv_usec,
+             stat->pr_stime.tv_sec, (long int) stat->pr_stime.tv_usec,
+             stat->pr_cutime.tv_sec, (long int) stat->pr_cutime.tv_usec,
+             stat->pr_cstime.tv_sec, (long int) stat->pr_cstime.tv_usec,
              stat->pr_reg[6], stat->pr_reg[0], stat->pr_reg[1],
              stat->pr_reg[2], stat->pr_reg[3], stat->pr_reg[4],
              stat->pr_reg[5], stat->pr_reg[15], stat->pr_reg[12],
@@ -118,15 +118,15 @@ i386_core_note (name, type, descsz, desc)
 
       /* We handled this entry.  */
       result = true;
-      break;
+    } break;
 
     case NT_PRPSINFO:
+    { struct elf_prpsinfo *info = (struct elf_prpsinfo *) desc;
+
       if (descsz < sizeof (struct elf_prpsinfo))
        /* Not enough data.  */
        break;
 
-      struct elf_prpsinfo *info = (struct elf_prpsinfo *) desc;
-
       printf ("    state: %c (%hhd),  zombie: %hhd,  nice: %hhd\n"
              "    flags: %08lx,  uid: %hd,  gid: %hd\n"
              "    pid: %d,  ppid: %d,  pgrp: %d,  sid: %d\n"
@@ -139,7 +139,7 @@ i386_core_note (name, type, descsz, desc)
 
       /* We handled this entry.  */
       result = true;
-      break;
+    } break;
 
     default:
       break;
index eb2c1da..f330eaa 100644 (file)
@@ -7,7 +7,7 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2003-02-19 13:48-0800\n"
+"POT-Creation-Date: 2003-03-05 15:25-0500\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -170,15 +170,15 @@ msgstr ""
 msgid "%s%s%s: file format not recognized"
 msgstr ""
 
-#: src/nm.c:792 src/nm.c:1174 src/readelf.c:661 src/readelf.c:791
+#: src/nm.c:791 src/nm.c:1173 src/readelf.c:661 src/readelf.c:791
 #: src/readelf.c:875 src/readelf.c:1059 src/readelf.c:1279 src/readelf.c:1431
 #: src/readelf.c:1605 src/readelf.c:1864 src/readelf.c:1941 src/readelf.c:2029
-#: src/readelf.c:2309 src/readelf.c:3726 src/size.c:424 src/size.c:498
-#: src/strip.c:428
+#: src/readelf.c:2309 src/readelf.c:3730 src/size.c:424 src/size.c:498
+#: src/strip.c:433
 msgid "cannot get section header string table index"
 msgstr ""
 
-#: src/nm.c:810
+#: src/nm.c:809
 #, c-format
 msgid ""
 "\n"
@@ -187,7 +187,7 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/nm.c:812
+#: src/nm.c:811
 #, c-format
 msgid ""
 "\n"
@@ -196,29 +196,29 @@ msgid ""
 "\n"
 msgstr ""
 
-#: src/nm.c:815
+#: src/nm.c:814
 #, c-format
 msgid ""
 "%*s%-*s %-*s Class  Type     %-*s Line          Section\n"
 "\n"
 msgstr ""
 
-#: src/nm.c:1184
+#: src/nm.c:1183
 #, c-format
 msgid "%s: entry size in section `%s' is not what we expect"
 msgstr ""
 
-#: src/nm.c:1188
+#: src/nm.c:1187
 #, c-format
 msgid "%s: size of section `%s' is not multiple of entry size"
 msgstr ""
 
-#: src/nm.c:1288
+#: src/nm.c:1287
 #, c-format
 msgid "%s%s%s%s: Invalid operation"
 msgstr ""
 
-#: src/nm.c:1345
+#: src/nm.c:1344
 #, c-format
 msgid "%s%s%s: no symbols"
 msgstr ""
@@ -312,7 +312,7 @@ msgstr ""
 msgid "Not an ELF file - it has the wrong magic bytes at the start"
 msgstr ""
 
-#: src/readelf.c:448 src/elflint.c:2021
+#: src/readelf.c:448 src/elflint.c:2028
 #, c-format
 msgid "cannot read ELF header: %s"
 msgstr ""
@@ -321,7 +321,7 @@ msgstr ""
 msgid "cannot create EBL handle"
 msgstr ""
 
-#: src/readelf.c:462 src/strip.c:485 src/ldgeneric.c:575 src/ldgeneric.c:966
+#: src/readelf.c:462 src/strip.c:490 src/ldgeneric.c:575 src/ldgeneric.c:966
 #, c-format
 msgid "cannot determine number of sections: %s"
 msgstr ""
@@ -869,7 +869,7 @@ msgstr ""
 msgid "unknown form %<PRIx64>"
 msgstr ""
 
-#: src/readelf.c:3113
+#: src/readelf.c:3114
 #, c-format
 msgid ""
 "\n"
@@ -877,50 +877,50 @@ msgid ""
 " [ Code]\n"
 msgstr ""
 
-#: src/readelf.c:3136
+#: src/readelf.c:3137
 #, c-format
 msgid " *** error while reading abbreviation: %s\n"
 msgstr ""
 
-#: src/readelf.c:3147
+#: src/readelf.c:3148
 #, c-format
 msgid " *** error while reading abbreviation code: %s\n"
 msgstr ""
 
-#: src/readelf.c:3154
+#: src/readelf.c:3155
 #, c-format
 msgid " *** error while reading abbreviation tag: %s\n"
 msgstr ""
 
-#: src/readelf.c:3162
+#: src/readelf.c:3163
 #, c-format
 msgid " *** error while reading abbreviation children flag: %s\n"
 msgstr ""
 
-#: src/readelf.c:3168
+#: src/readelf.c:3169
 #, c-format
 msgid " [%5<PRId64>] offset: %<PRId64>, children: %s, tag: %s\n"
 msgstr ""
 
-#: src/readelf.c:3171
+#: src/readelf.c:3172
 msgid "yes"
 msgstr ""
 
-#: src/readelf.c:3171
+#: src/readelf.c:3172
 msgid "no"
 msgstr ""
 
-#: src/readelf.c:3186
+#: src/readelf.c:3187
 #, c-format
 msgid " *** error while reading abbreviation entries: %s\n"
 msgstr ""
 
-#: src/readelf.c:3210
+#: src/readelf.c:3211
 #, c-format
 msgid "cannot get .debug_aranges content: %s"
 msgstr ""
 
-#: src/readelf.c:3215 src/readelf.c:3648
+#: src/readelf.c:3216 src/readelf.c:3652
 #, c-format
 msgid ""
 "\n"
@@ -931,19 +931,19 @@ msgid_plural ""
 msgstr[0] ""
 msgstr[1] ""
 
-#: src/readelf.c:3230 src/readelf.c:3663
+#: src/readelf.c:3231 src/readelf.c:3667
 #, c-format
 msgid " [%5<PRId64>] ???\n"
 msgstr ""
 
-#: src/readelf.c:3232
+#: src/readelf.c:3233
 #, c-format
 msgid ""
 " [%5<PRId64>] start: %0#*<PRIx64>, length: %5<PRIu64>, CU DIE offset: %"
 "6<PRId64>\n"
 msgstr ""
 
-#: src/readelf.c:3256
+#: src/readelf.c:3270
 #, c-format
 msgid ""
 "\n"
@@ -951,12 +951,12 @@ msgid ""
 " [Offset]\n"
 msgstr ""
 
-#: src/readelf.c:3284
+#: src/readelf.c:3288
 #, c-format
 msgid "cannot get CU header in section '%s': %s"
 msgstr ""
 
-#: src/readelf.c:3289
+#: src/readelf.c:3293
 #, c-format
 msgid ""
 " Compilation unit at offset %<PRIu64>:\n"
@@ -964,70 +964,70 @@ msgid ""
 "<PRIu16>\n"
 msgstr ""
 
-#: src/readelf.c:3301
+#: src/readelf.c:3305
 #, c-format
 msgid "cannot get DIE at offset %<PRIu64> in section '%s': %s"
 msgstr ""
 
-#: src/readelf.c:3311
+#: src/readelf.c:3372
 #, c-format
 msgid "cannot get DIE offset: %s"
 msgstr ""
 
-#: src/readelf.c:3319
+#: src/readelf.c:3379
 #, c-format
 msgid "cannot get tag of DIE at offset %<PRIu64> in section '%s': %s"
 msgstr ""
 
-#: src/readelf.c:3418
+#: src/readelf.c:3424
 #, c-format
 msgid "cannot get attributes of DIE: %s"
 msgstr ""
 
-#: src/readelf.c:3430
+#: src/readelf.c:3436
 #, c-format
 msgid "cannot get attribute code: %s"
 msgstr ""
 
-#: src/readelf.c:3438
+#: src/readelf.c:3443
 #, c-format
 msgid "cannot get attribute form: %s"
 msgstr ""
 
-#: src/readelf.c:3451
+#: src/readelf.c:3456
 #, c-format
 msgid "cannot get attribute value: %s"
 msgstr ""
 
-#: src/readelf.c:3579
+#: src/readelf.c:3583
 #, c-format
 msgid "cannot get next DIE: %s\n"
 msgstr ""
 
-#: src/readelf.c:3586
+#: src/readelf.c:3590
 #, c-format
 msgid "cannot get next DIE: %s"
 msgstr ""
 
-#: src/readelf.c:3614 src/readelf.c:3624
+#: src/readelf.c:3618 src/readelf.c:3628
 #, c-format
 msgid ""
 "\n"
 "DWARF section '%s' at offset %#<PRIx64>:\n"
 msgstr ""
 
-#: src/readelf.c:3643
+#: src/readelf.c:3647
 #, c-format
 msgid "cannot get .debug_pubnames content: %s"
 msgstr ""
 
-#: src/readelf.c:3665
+#: src/readelf.c:3669
 #, c-format
 msgid ""
 " [%5<PRId64>] DIE offset: %6<PRId64>, CU DIE offset: %6<PRId64>, name: %s\n"
 msgstr ""
 
-#: src/readelf.c:3687
+#: src/readelf.c:3691
 #, c-format
 msgid ""
 "\n"
@@ -1035,33 +1035,33 @@ msgid ""
 " [Offset]  String\n"
 msgstr ""
 
-#: src/readelf.c:3699
+#: src/readelf.c:3703
 #, c-format
 msgid " *** error while reading strings: %s\n"
 msgstr ""
 
-#: src/readelf.c:3718
+#: src/readelf.c:3722
 #, c-format
 msgid "cannot get debug context descriptor: %s"
 msgstr ""
 
-#: src/readelf.c:3792
+#: src/readelf.c:3799
 #, c-format
 msgid ""
 "\n"
 "Note segment of %<PRId64> bytes at offset %#0*<PRIx64>:\n"
 msgstr ""
 
-#: src/readelf.c:3799
+#: src/readelf.c:3806
 #, c-format
 msgid "cannot get content of note section: %s"
 msgstr ""
 
-#: src/readelf.c:3802
+#: src/readelf.c:3809
 msgid "  Owner          Data size  Type\n"
 msgstr ""
 
-#: src/readelf.c:3841
+#: src/readelf.c:3848
 #, c-format
 msgid "  %-13.*s  %9<PRId32>  %s\n"
 msgstr ""
@@ -1184,61 +1184,61 @@ msgstr ""
 msgid "cannot set access and modification date of \"%s\""
 msgstr ""
 
-#: src/strip.c:388 src/strip.c:414
+#: src/strip.c:394 src/strip.c:419
 #, c-format
 msgid "cannot open `%s'"
 msgstr ""
 
-#: src/strip.c:401
+#: src/strip.c:407
 msgid "cannot open EBL backend"
 msgstr ""
 
-#: src/strip.c:437 src/strip.c:463
+#: src/strip.c:442 src/strip.c:468
 #, c-format
 msgid "cannot create new file `%s': %s"
 msgstr ""
 
-#: src/strip.c:524
+#: src/strip.c:529
 #, c-format
 msgid "illformed file `%s'"
 msgstr ""
 
-#: src/strip.c:788 src/strip.c:873
+#: src/strip.c:793 src/strip.c:878
 #, c-format
 msgid "while generating output file: %s"
 msgstr ""
 
-#: src/strip.c:837 src/strip.c:1218
+#: src/strip.c:842 src/strip.c:1224
 #, c-format
 msgid "%s: error while creating ELF header: %s"
 msgstr ""
 
-#: src/strip.c:845 src/strip.c:1240
+#: src/strip.c:850 src/strip.c:1246
 #, c-format
 msgid "while writing `%s': %s"
 msgstr ""
 
-#: src/strip.c:860
+#: src/strip.c:865
 #, c-format
 msgid "while preparing output for `%s'"
 msgstr ""
 
-#: src/strip.c:914 src/strip.c:971
+#: src/strip.c:919 src/strip.c:976
 #, c-format
 msgid "while create section header section: %s"
 msgstr ""
 
-#: src/strip.c:920
+#: src/strip.c:925
 #, c-format
 msgid "cannot allocate section data: %s"
 msgstr ""
 
-#: src/strip.c:1226
+#: src/strip.c:1232
 #, c-format
 msgid "%s: error while reading the file: %s"
 msgstr ""
 
-#: src/strip.c:1254 src/strip.c:1261
+#: src/strip.c:1260 src/strip.c:1267
 #, c-format
 msgid "error while finishing `%s': %s"
 msgstr ""
@@ -2297,190 +2297,190 @@ msgstr ""
 msgid "section [%2d] '%s' is contained in more than one section group"
 msgstr ""
 
-#: src/elflint.c:1563
+#: src/elflint.c:1565
 msgid "cannot get section header of zeroth section"
 msgstr ""
 
-#: src/elflint.c:1567
+#: src/elflint.c:1569
 msgid "zeroth section has nonzero name"
 msgstr ""
 
-#: src/elflint.c:1569
+#: src/elflint.c:1571
 msgid "zeroth section has nonzero type"
 msgstr ""
 
-#: src/elflint.c:1571
+#: src/elflint.c:1573
 msgid "zeroth section has nonzero flags"
 msgstr ""
 
-#: src/elflint.c:1573
+#: src/elflint.c:1575
 msgid "zeroth section has nonzero address"
 msgstr ""
 
-#: src/elflint.c:1575
+#: src/elflint.c:1577
 msgid "zeroth section has nonzero offset"
 msgstr ""
 
-#: src/elflint.c:1577
+#: src/elflint.c:1579
 msgid "zeroth section has nonzero info field"
 msgstr ""
 
-#: src/elflint.c:1579
+#: src/elflint.c:1581
 msgid "zeroth section has nonzero align value"
 msgstr ""
 
-#: src/elflint.c:1581
+#: src/elflint.c:1583
 msgid "zeroth section has nonzero entry size value"
 msgstr ""
 
-#: src/elflint.c:1584
+#: src/elflint.c:1586
 msgid ""
 "zeroth section has nonzero size value while ELF header has nonzero shnum "
 "value"
 msgstr ""
 
-#: src/elflint.c:1587
+#: src/elflint.c:1589
 msgid ""
 "zeroth section has nonzero link value while ELF header does not signal "
 "overflow in shstrndx"
 msgstr ""
 
-#: src/elflint.c:1598
+#: src/elflint.c:1601
 #, c-format
 msgid "cannot get section header for section [%2d] '%s': %s"
 msgstr ""
 
-#: src/elflint.c:1607
+#: src/elflint.c:1610
 #, c-format
 msgid "section [%2d]: invalid name"
 msgstr ""
 
-#: src/elflint.c:1622
+#: src/elflint.c:1625
 #, c-format
 msgid "section [%2zd] '%s' has wrong type: expected %s, is %s"
 msgstr ""
 
-#: src/elflint.c:1637
+#: src/elflint.c:1640
 #, c-format
 msgid "section [%2d] '%s' has wrong flags: expected %s, is %s"
 msgstr ""
 
-#: src/elflint.c:1655
+#: src/elflint.c:1658
 #, c-format
 msgid "section [%2d] '%s' has wrong flags: expected %s and possibly %s, is %s"
 msgstr ""
 
-#: src/elflint.c:1685
+#: src/elflint.c:1688
 #, c-format
 msgid ""
 "section [%2d] '%s' has SHF_ALLOC flag set but there is no loadable segment"
 msgstr ""
 
-#: src/elflint.c:1690
+#: src/elflint.c:1693
 #, c-format
 msgid ""
 "section [%2d] '%s' has SHF_ALLOC flag not set but there are loadable segments"
 msgstr ""
 
-#: src/elflint.c:1700
+#: src/elflint.c:1703
 #, c-format
 msgid "section [%2d] '%s': size not multiple of entry size"
 msgstr ""
 
-#: src/elflint.c:1705
+#: src/elflint.c:1708
 msgid "cannot get section header"
 msgstr ""
 
-#: src/elflint.c:1713
+#: src/elflint.c:1716
 #, c-format
 msgid "unsupported section type %d"
 msgstr ""
 
-#: src/elflint.c:1719
+#: src/elflint.c:1722
 #, c-format
 msgid "section [%2d] '%s' contain unknown flag"
 msgstr ""
 
-#: src/elflint.c:1722
+#: src/elflint.c:1725
 #, c-format
 msgid "section [%2d] '%s': thread-local data sections not yet supported"
 msgstr ""
 
-#: src/elflint.c:1727
+#: src/elflint.c:1730
 #, c-format
 msgid "section [%2d] '%s': invalid section reference in link value"
 msgstr ""
 
-#: src/elflint.c:1732
+#: src/elflint.c:1735
 #, c-format
 msgid "section [%2d] '%s': invalid section reference in info value"
 msgstr ""
 
-#: src/elflint.c:1739
+#: src/elflint.c:1742
 #, c-format
 msgid "section [%2d] '%s': strings flag set without merge flag"
 msgstr ""
 
-#: src/elflint.c:1744
+#: src/elflint.c:1747
 #, c-format
 msgid "section [%2d] '%s': merge flag set but entry size is zero"
 msgstr ""
 
-#: src/elflint.c:1752
+#: src/elflint.c:1755
 #, c-format
 msgid ""
 "section [%2d] '%s': ELF header says this is the section header string table "
 "but type is not SHT_TYPE"
 msgstr ""
 
-#: src/elflint.c:1798
+#: src/elflint.c:1801
 msgid "INTERP program header entry but no .interp section"
 msgstr ""
 
-#: src/elflint.c:1808
+#: src/elflint.c:1815
 #, c-format
 msgid "phdr[%d]: no note entries defined for the type of file"
 msgstr ""
 
-#: src/elflint.c:1890
+#: src/elflint.c:1897
 #, c-format
 msgid "phdr[%d]: note entries probably in form of a 32-bit ELF file"
 msgstr ""
 
-#: src/elflint.c:1893
+#: src/elflint.c:1900
 #, c-format
 msgid "phdr[%d]: extra %zu bytes after last note"
 msgstr ""
 
-#: src/elflint.c:1922
+#: src/elflint.c:1929
 #, c-format
 msgid "phdr[%d]: unknown core file note type %<PRIu64> at offset %<PRIu64>"
 msgstr ""
 
-#: src/elflint.c:1930
+#: src/elflint.c:1937
 #, c-format
 msgid "phdr[%d]: unknown object file note type %<PRIu64> at offset %<PRIu64>"
 msgstr ""
 
-#: src/elflint.c:1956
+#: src/elflint.c:1963
 msgid ""
 "only executables, shared objects, and core files can have program headers"
 msgstr ""
 
-#: src/elflint.c:1967
+#: src/elflint.c:1974
 #, c-format
 msgid "cannot get program header entry %d: %s"
 msgstr ""
 
-#: src/elflint.c:1973
+#: src/elflint.c:1980
 #, c-format
 msgid "program header entry %d: unknown program header entry type"
 msgstr ""
 
-#: src/elflint.c:1984
+#: src/elflint.c:1991
 msgid "more than one INTERP entry in program header"
 msgstr ""
 
-#: src/elflint.c:1993
+#: src/elflint.c:2000
 msgid "more than one TLS entry in program header"
 msgstr ""
index 09b0007..1f0e222 100644 (file)
@@ -1,19 +1,16 @@
 /* Pedantic checking of ELF files compliance with gABI/psABI spec.
-   Copyright (C) 2001, 2002 Red Hat, Inc.
+   Copyright (C) 2001, 2002, 2003 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2001.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -21,6 +18,8 @@
 
 #include <argp.h>
 #include <assert.h>
+#include <byteswap.h>
+#include <endian.h>
 #include <error.h>
 #include <fcntl.h>
 #include <gelf.h>
@@ -32,6 +31,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <sys/param.h>
 
 #include <elf-knowledge.h>
 #include <system.h>
@@ -76,9 +76,9 @@ static struct argp argp =
 
 /* Declarations of local functions.  */
 static void process_file (int fd, Elf *elf, const char *prefix,
-                         const char *fname, bool only_one);
+                         const char *fname, size_t size, bool only_one);
 static void process_elf_file (Elf *elf, const char *prefix, const char *fname,
-                             bool only_one);
+                             size_t size, bool only_one);
 
 /* True if we should perform very strict testing.  */
 static bool be_strict;
@@ -142,8 +142,16 @@ main (int argc, char *argv[])
       else
        {
          int prev_error_message_count = error_message_count;
+         struct stat64 st;
+
+         if (fstat64 (fd, &st) != 0)
+           {
+             printf ("cannot stat '%s': %m\n", argv[remaining]);
+             close (fd);
+             continue;
+           }
 
-         process_file (fd, elf, NULL, argv[remaining], only_one);
+         process_file (fd, elf, NULL, argv[remaining], st.st_size, only_one);
 
          /* Now we can close the descriptor.  */
          if (elf_end (elf) != 0)
@@ -222,7 +230,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
 /* Process one file.  */
 static void
 process_file (int fd, Elf *elf, const char *prefix, const char *fname,
-             bool only_one)
+             size_t size, bool only_one)
 {
   /* We can handle two types of files: ELF files and archives.  */
   Elf_Kind kind = elf_kind (elf);
@@ -231,7 +239,7 @@ process_file (int fd, Elf *elf, const char *prefix, const char *fname,
     {
     case ELF_K_ELF:
       /* Yes!  It's an ELF file.  */
-      process_elf_file (elf, prefix, fname, only_one);
+      process_elf_file (elf, prefix, fname, size, only_one);
       break;
 
     case ELF_K_AR:
@@ -262,7 +270,8 @@ process_file (int fd, Elf *elf, const char *prefix, const char *fname,
                Elf_Arhdr *arhdr = elf_getarhdr (subelf);
                assert (arhdr != NULL);
 
-               process_file (fd, subelf, new_prefix, arhdr->ar_name, false);
+               process_file (fd, subelf, new_prefix, arhdr->ar_name,
+                             arhdr->ar_size, false);
              }
 
            /* Get next archive element.  */
@@ -305,7 +314,7 @@ static const int valid_e_machine[] =
     EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
     EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
     EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
-    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_AT19, EM_VAX,
+    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
     EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
     EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
     EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA
@@ -319,7 +328,7 @@ static int shnum;
 
 
 static void
-check_elf_header (Ebl *ebl, GElf_Ehdr *ehdr)
+check_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
 {
   char buf[512];
   int cnt;
@@ -459,10 +468,14 @@ invalid number of section header table entries"));
       if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
        error (0, 0, gettext ("invalid program header size: %hd"),
               ehdr->e_phentsize);
+      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
+       error (0, 0, gettext ("invalid program header position or size"));
 
       if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
        error (0, 0, gettext ("invalid section header size: %hd"),
               ehdr->e_shentsize);
+      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
+       error (0, 0, gettext ("invalid section header position or size"));
     }
   else if (gelf_getclass (ebl->elf) == ELFCLASS64)
     {
@@ -472,10 +485,14 @@ invalid number of section header table entries"));
       if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
        error (0, 0, gettext ("invalid program header size: %hd"),
               ehdr->e_phentsize);
+      else if (ehdr->e_phoff + ehdr->e_phnum * ehdr->e_phentsize > size)
+       error (0, 0, gettext ("invalid program header position or size"));
 
       if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
        error (0, 0, gettext ("invalid section header size: %hd"),
               ehdr->e_shentsize);
+      else if (ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize > size)
+       error (0, 0, gettext ("invalid section header position or size"));
     }
 }
 
@@ -669,12 +686,12 @@ section [%2d] '%s': symbol %d: XINDEX used for index which would fit in st_shndx
                   xndx);
        }
       else if ((sym->st_shndx >= SHN_LORESERVE
-               && sym->st_shndx <= SHN_HIRESERVE
+               // && sym->st_shndx <= SHN_HIRESERVE    always true
                && sym->st_shndx != SHN_ABS
                && sym->st_shndx != SHN_COMMON)
               || (sym->st_shndx >= shnum
                   && (sym->st_shndx < SHN_LORESERVE
-                      || sym->st_shndx > SHN_HIRESERVE)))
+                      /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
        error (0, 0, gettext ("\
 section [%2d] '%s': symbol %d: invalid section index"),
               idx, section_name (ebl, ehdr, idx), cnt);
@@ -705,11 +722,7 @@ section [%2d] '%s': symbol %d: st_value out of bounds"),
 
       if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
        {
-         if (shdr->sh_type == SHT_DYNSYM)
-           error (0, 0, gettext ("\
-section [%2d] '%s': symbol %d: dynamic symbol table contain local symbol"),
-                  idx, section_name (ebl, ehdr, idx), cnt);
-         else if (cnt >= shdr->sh_info)
+         if (cnt >= shdr->sh_info)
            error (0, 0, gettext ("\
 section [%2d] '%s': symbol %d: local symbol outside range described in sh_info"),
                   idx, section_name (ebl, ehdr, idx), cnt);
@@ -731,6 +744,9 @@ section [%2d] '%s': symbol %d: non-local section symbol"),
 }
 
 
+#define REL_DYN_P(name) (strcmp (name, ".rel.dyn") == 0)
+
+
 static void
 check_rela (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
 {
@@ -767,7 +783,8 @@ check_rela (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
                               &destshdr_mem);
       if (destshdr != NULL
          && destshdr->sh_type != SHT_PROGBITS
-         && destshdr->sh_type != SHT_NOBITS)
+         && destshdr->sh_type != SHT_NOBITS
+         && ! REL_DYN_P (section_name (ebl, ehdr, idx)))
        error (0, 0, gettext ("\
 section [%2d] '%s': invalid destination section type"),
               idx, section_name (ebl, ehdr, idx));
@@ -852,7 +869,8 @@ check_rel (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
                               &destshdr_mem);
       if (destshdr != NULL
          && destshdr->sh_type != SHT_PROGBITS
-         && destshdr->sh_type != SHT_NOBITS)
+         && destshdr->sh_type != SHT_NOBITS
+         && ! REL_DYN_P (section_name (ebl, ehdr, idx)))
        error (0, 0, gettext ("\
 section [%2d] '%s': invalid destination section type"),
               idx, section_name (ebl, ehdr, idx));
@@ -945,6 +963,15 @@ check_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, int idx)
       [DT_RPATH] = true, [DT_SYMBOLIC] = true, [DT_TEXTREL] = true,
       [DT_BIND_NOW] = true
     };
+  static const bool mandatory[DT_NUM] =
+    {
+      [DT_NULL] = true,
+      [DT_HASH] = true,
+      [DT_STRTAB] = true,
+      [DT_SYMTAB] = true,
+      [DT_STRSZ] = true,
+      [DT_SYMENT] = true
+    };
   GElf_Addr reladdr = 0;
   GElf_Word relsz = 0;
   GElf_Addr pltreladdr = 0;
@@ -1064,6 +1091,33 @@ section [%2d] '%s': contains %s entry but not %s"),
                     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
            }
       }
+    else
+      {
+       if (mandatory[cnt])
+         {
+           char buf[50];
+           error (0, 0, gettext ("\
+section [%2d] '%s': mandatory tag %s not present"),
+                  idx, section_name (ebl, ehdr, idx),
+                  ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
+         }
+      }
+
+  /* Check the rel/rela tags.  At least one group must be available.  */
+  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
+      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
+    error (0, 0, gettext ("\
+section [%2d] '%s': not all of %s, %s, and %s are present"),
+          idx, section_name (ebl, ehdr, idx),
+          "DT_RELA", "DT_RELASZ", "DT_RELAENT");
+
+  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
+      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
+    error (0, 0, gettext ("\
+section [%2d] '%s': not all of %s, %s, and %s are present"),
+          idx, section_name (ebl, ehdr, idx),
+          "DT_REL", "DT_RELSZ", "DT_RELENT");
+
 }
 
 
@@ -1384,7 +1438,108 @@ section [%2d] '%s' is contained in more than one section group"),
 }
 
 
-static bool dot_interp_section;
+static bool has_loadable_segment;
+static bool has_interp_segment;
+
+static const struct
+{
+  const char *name;
+  size_t namelen;
+  int type;
+  enum { unused, exact, atleast } attrflag;
+  int attr;
+  int attr2;
+} special_sections[] =
+  {
+    /* See figure 4-14 in the gABI.  */
+    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".comment", 8, SHT_PROGBITS, exact, 0, 0 },
+    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".debug", 7, SHT_PROGBITS, exact, 0, 0 },
+    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
+    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
+    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
+    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
+    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
+    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
+    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
+    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
+    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
+    { ".note", 6, SHT_NOTE, exact, 0, 0 },
+    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
+    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".rodata", 8, SHT_PROGBITS, exact, SHF_ALLOC, 0 },
+    { ".rodata1", 9, SHT_PROGBITS, exact, SHF_ALLOC, 0 },
+    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
+    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
+    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
+    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
+    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 }
+  };
+#define nspecial_sections \
+  (sizeof (special_sections) / sizeof (special_sections[0]))
+
+
+static const char *
+section_flags_string (GElf_Word flags, char *buf, size_t len)
+{
+  static const struct
+  {
+    GElf_Word flag;
+    const char *name;
+  } known_flags[] =
+    {
+#define NEWFLAG(name) { SHF_##name, #name }
+      NEWFLAG (WRITE),
+      NEWFLAG (ALLOC),
+      NEWFLAG (EXECINSTR),
+      NEWFLAG (MERGE),
+      NEWFLAG (STRINGS),
+      NEWFLAG (INFO_LINK),
+      NEWFLAG (LINK_ORDER),
+      NEWFLAG (OS_NONCONFORMING),
+      NEWFLAG (GROUP),
+      NEWFLAG (TLS)
+    };
+#undef NEWFLAG
+  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
+
+  char *cp = buf;
+  size_t cnt;
+
+  for (cnt = 0; cnt < nknown_flags; ++cnt)
+    if (flags & known_flags[cnt].flag)
+      {
+       size_t ncopy;
+
+       if (cp != buf && len > 1)
+         {
+           *cp++ = '|';
+           --len;
+         }
+
+       ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
+       cp = mempcpy (cp, known_flags[cnt].name, ncopy);
+       len -= ncopy;
+
+       flags ^= known_flags[cnt].flag;
+      }
+
+  if (flags != 0 || cp == buf)
+    snprintf (cp, len - 1, "%" PRIx64, (uint64_t) flags);
+
+  *cp = '\0';
+
+  return buf;
+}
 
 
 static void
@@ -1393,6 +1548,7 @@ check_sections (Ebl *ebl, GElf_Ehdr *ehdr)
   GElf_Shdr shdr_mem;
   GElf_Shdr *shdr;
   int cnt;
+  bool dot_interp_section = false;
 
   /* Allocate array to count references in section groups.  */
   scnref = (int *) xcalloc (shnum, sizeof (int));
@@ -1436,6 +1592,7 @@ check_sections (Ebl *ebl, GElf_Ehdr *ehdr)
   for (cnt = 1; cnt < shnum; ++cnt)
     {
       Elf_Scn *scn;
+      const char *scnname;
 
       scn = elf_getscn (ebl->elf, cnt);
       shdr = gelf_getshdr (scn, &shdr_mem);
@@ -1447,9 +1604,100 @@ cannot get section header for section [%2d] '%s': %s"),
          continue;
        }
 
-      if (strcmp (elf_strptr (ebl->elf, shstrndx, shdr->sh_name), ".interp")
-         == 0)
-       dot_interp_section = true;
+      scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+
+      if (scnname == NULL)
+       error (0, 0, gettext ("section [%2d]: invalid name"), cnt);
+      else
+       {
+         /* Check whether it is one of the special sections defined in
+            the gABI.  */
+         size_t s;
+         for (s = 0; s < nspecial_sections; ++s)
+           if (strncmp (scnname, special_sections[s].name,
+                        special_sections[s].namelen) == 0)
+             {
+               char stbuf1[100];
+               char stbuf2[100];
+               char stbuf3[100];
+
+               if (shdr->sh_type != special_sections[s].type)
+                 error (0, 0, gettext ("section [%2zd] '%s' has wrong type:"
+                                       " expected %s, is %s"),
+                        s, scnname,
+                        ebl_section_type_name (ebl, special_sections[s].type,
+                                               stbuf1, sizeof (stbuf1)),
+                        ebl_section_type_name (ebl, shdr->sh_type,
+                                               stbuf2, sizeof (stbuf2)));
+
+               if (special_sections[s].attrflag == exact)
+                 {
+                   /* Except for the link order and group bit all the
+                      other bits should match exactly.  */
+                   if ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP))
+                       != special_sections[s].attr)
+                     error (0, 0,
+                            gettext ("section [%2d] '%s' has wrong flags:"
+                                     " expected %s, is %s"),
+                            cnt, scnname,
+                            section_flags_string (special_sections[s].attr,
+                                                  stbuf1, sizeof (stbuf1)),
+                            section_flags_string (shdr->sh_flags
+                                                  & ~SHF_LINK_ORDER,
+                                                  stbuf2, sizeof (stbuf2)));
+                 }
+               else if (special_sections[s].attrflag == atleast)
+                 {
+                   if ((shdr->sh_flags & special_sections[s].attr)
+                       != special_sections[s].attr
+                       || ((shdr->sh_flags & ~(SHF_LINK_ORDER | SHF_GROUP
+                                               | special_sections[s].attr
+                                               | special_sections[s].attr2))
+                           != 0))
+                     error (0, 0,
+                            gettext ("section [%2d] '%s' has wrong flags:"
+                                     " expected %s and possibly %s, is %s"),
+                            cnt, scnname,
+                            section_flags_string (special_sections[s].attr,
+                                                  stbuf1, sizeof (stbuf1)),
+                            section_flags_string (special_sections[s].attr2,
+                                                  stbuf2, sizeof (stbuf2)),
+                            section_flags_string (shdr->sh_flags
+                                                  & ~(SHF_LINK_ORDER
+                                                      | SHF_GROUP),
+                                                  stbuf3, sizeof (stbuf3)));
+                 }
+
+               if (strcmp (scnname, ".interp") == 0)
+                 dot_interp_section = true;
+
+               if (strcmp (scnname, ".interp") == 0
+                   || strncmp (scnname, ".rel", 4) == 0
+                   || strcmp (scnname, ".strtab") == 0
+                   || strcmp (scnname, ".symtab") == 0
+                   || strcmp (scnname, ".symtab_shndx") == 0)
+                 {
+                   /* These sections must have the SHF_ALLOC flag set iff
+                      a loadable segment is available.
+
+                      XXX These tests are no 100% correct since strtab,
+                      symtab, etc only have to have the alloc bit set if
+                      any loadable section is affected.  */
+                   if ((shdr->sh_flags & SHF_ALLOC) != 0
+                       && !has_loadable_segment)
+                     error (0, 0, gettext ("\
+section [%2d] '%s' has SHF_ALLOC flag set but there is no loadable segment"),
+                            cnt, scnname);
+                   else if ((shdr->sh_flags & SHF_ALLOC) == 0
+                            && has_loadable_segment)
+                     error (0, 0, gettext ("\
+section [%2d] '%s' has SHF_ALLOC flag not set but there are loadable segments"),
+                            cnt, scnname);
+                 }
+
+               break;
+             }
+       }
 
       if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
        error (0, 0, gettext ("\
@@ -1547,27 +1795,173 @@ section [%2d] '%s': merge flag set but entry size is zero"),
          break;
        }
     }
+
+  if (has_interp_segment && !dot_interp_section)
+    error (0, 0,
+          gettext ("INTERP program header entry but no .interp section"));
 }
 
 
 static void
-check_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
+check_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
 {
-  int cnt;
+  char *notemem;
+  GElf_Xword align;
+  GElf_Xword idx;
 
-  if (ehdr->e_phoff == 0)
+  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
+      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+    error (0, 0,
+          gettext ("phdr[%d]: no note entries defined for the type of file"),
+          cnt);
+
+  notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
+
+  /* ELF64 files often use note section entries in the 32-bit format.
+     The p_align field is set to 8 in case the 64-bit format is used.
+     In case the p_align value is 0 or 4 the 32-bit format is
+     used.  */
+  align = phdr->p_align == 0 || phdr->p_align == 4 ? 4 : 8;
+#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
+
+  idx = 0;
+  while (idx < phdr->p_filesz)
     {
-      /* No program header.  */
-      if (dot_interp_section)
-       error (0, 0,
-              gettext (".interp section present but no program header"));
+      uint64_t namesz;
+      uint64_t descsz;
+      uint64_t type;
+      uint32_t namesz32;
+      uint32_t descsz32;
+
+      if (align == 4)
+       {
+         uint32_t *ptr = (uint32_t *) (notemem + idx);
+
+         if ((__BYTE_ORDER == __LITTLE_ENDIAN
+              && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+             || (__BYTE_ORDER == __BIG_ENDIAN
+                 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+           {
+             namesz32 = namesz = bswap_32 (*ptr);
+             ++ptr;
+             descsz32 = descsz = bswap_32 (*ptr);
+             ++ptr;
+             type = bswap_32 (*ptr);
+           }
+         else
+           {
+             namesz32 = namesz = *ptr++;
+             descsz32 = descsz = *ptr++;
+             type = *ptr;
+           }
+       }
+      else
+       {
+         uint64_t *ptr = (uint64_t *) (notemem + idx);
+         uint32_t *ptr32 = (uint32_t *) (notemem + idx);
+
+         if ((__BYTE_ORDER == __LITTLE_ENDIAN
+              && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+             || (__BYTE_ORDER == __BIG_ENDIAN
+                 && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+           {
+             namesz = bswap_64 (*ptr);
+             ++ptr;
+             descsz = bswap_64 (*ptr);
+             ++ptr;
+             type = bswap_64 (*ptr);
+
+             namesz32 = bswap_32 (*ptr32);
+             ++ptr32;
+             descsz32 = bswap_32 (*ptr32);
+           }
+         else
+           {
+             namesz = *ptr++;
+             descsz = *ptr++;
+             type = *ptr;
+
+             namesz32 = *ptr32++;
+             descsz32 = *ptr32;
+           }
+       }
+
+      if (idx + 3 * align > phdr->p_filesz
+         || (idx + 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz)
+             > phdr->p_filesz))
+       {
+         if (ehdr->e_ident[EI_CLASS] == ELFCLASS64
+             && idx + 3 * 4 <= phdr->p_filesz
+             && (idx + 3 * 4 + ALIGNED_LEN (namesz32) + ALIGNED_LEN (descsz32)
+                 <= phdr->p_filesz))
+           error (0, 0, gettext ("\
+phdr[%d]: note entries probably in form of a 32-bit ELF file"), cnt);
+         else
+           error (0, 0, gettext ("phdr[%d]: extra %zu bytes after last note"),
+                  cnt, (size_t) (phdr->p_filesz - idx));
+         break;
+       }
+
+      /* Make sure it is one of the note types we know about.  */
+      if (ehdr->e_type == ET_CORE)
+       {
+         switch (type)
+           {
+           case NT_PRSTATUS:
+           case NT_FPREGSET:
+           case NT_PRPSINFO:
+           case NT_TASKSTRUCT:         /* NT_PRXREG on Solaris.  */
+           case NT_PLATFORM:
+           case NT_AUXV:
+           case NT_GWINDOWS:
+           case NT_ASRS:
+           case NT_PSTATUS:
+           case NT_PSINFO:
+           case NT_PRCRED:
+           case NT_UTSNAME:
+           case NT_LWPSTATUS:
+           case NT_LWPSINFO:
+           case NT_PRFPXREG:
+             /* Known type.  */
+             break;
+
+           default:
+             error (0, 0, gettext ("\
+phdr[%d]: unknown core file note type %" PRIu64 " at offset %" PRIu64),
+                    cnt, type, idx);
+           }
+       }
+      else
+       {
+         if (type != NT_VERSION)
+           error (0, 0, gettext ("\
+phdr[%d]: unknown object file note type %" PRIu64 " at offset %" PRIu64),
+                  cnt, type, idx);
+       }
+
+      /* Move to the next entry.  */
+      idx += 3 * align + ALIGNED_LEN (namesz) + ALIGNED_LEN (descsz);
 
-      return;
     }
 
-  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+  gelf_freechunk (ebl->elf, notemem);
+}
+
+
+static void
+check_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  int cnt;
+  int num_pt_interp = 0;
+  int num_pt_tls = 0;
+
+  if (ehdr->e_phoff == 0)
+    return;
+
+  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
+      && ehdr->e_type != ET_CORE)
     error (0, 0, gettext ("\
-only executables and shared objects can have program headers"));
+only executables, shared objects, and core files can have program headers"));
 
   for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
     {
@@ -1582,14 +1976,31 @@ only executables and shared objects can have program headers"));
          continue;
        }
 
-      if (phdr->p_type >= PT_NUM)
+      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME)
        error (0, 0, gettext ("\
 program header entry %d: unknown program header entry type"),
               cnt);
 
-      if (phdr->p_type == PT_INTERP && !dot_interp_section)
-       error (0, 0,
-              gettext ("INTERP program header entry but no .interp section"));
+      if (phdr->p_type == PT_LOAD)
+       has_loadable_segment = true;
+      else if (phdr->p_type == PT_INTERP)
+       {
+         if (++num_pt_interp != 1)
+           {
+             if (num_pt_interp == 2)
+               error (0, 0, gettext ("\
+more than one INTERP entry in program header"));
+           }
+         has_interp_segment = true;
+       }
+      else if (phdr->p_type == PT_TLS)
+       {
+         if (++num_pt_tls == 2)
+           error (0, 0,
+                  gettext ("more than one TLS entry in program header"));
+       }
+      else if (phdr->p_type == PT_NOTE)
+       check_note (ebl, ehdr, phdr, cnt);
     }
 }
 
@@ -1597,7 +2008,7 @@ program header entry %d: unknown program header entry type"),
 /* Process one file.  */
 static void
 process_elf_file (Elf *elf, const char *prefix, const char *fname,
-                 bool only_one)
+                 size_t size, bool only_one)
 {
   GElf_Ehdr ehdr_mem;
   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
@@ -1624,12 +2035,12 @@ process_elf_file (Elf *elf, const char *prefix, const char *fname,
      is an error.  */
 
   /* Go straight by the gABI, check all the parts in turn.  */
-  check_elf_header (ebl, ehdr);
+  check_elf_header (ebl, ehdr, size);
+
+  /* Check the program header.  */
+  check_program_header (ebl, ehdr);
 
   /* Next the section headers.  It is OK if there are no section
      headers at all.  */
   check_sections (ebl, ehdr);
-
-  /* Finally check the program header.  */
-  check_program_header (ebl, ehdr);
 }
index 6e35028..069f408 100644 (file)
@@ -1,27 +1,26 @@
 /* Print information from ELF file in human-readable form.
-   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 
+#include <ar.h>
 #include <argp.h>
 #include <assert.h>
 #include <ctype.h>
+#include <dwarf.h>
 #include <errno.h>
 #include <error.h>
 #include <fcntl.h>
@@ -33,6 +32,7 @@
 #include <locale.h>
 #include <mcheck.h>
 #include <search.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
@@ -61,17 +61,23 @@ static const struct argp_option options[] =
   { "dynamic", 'D', NULL, 0, N_("Display dynamic symbols instead of normal symbols") },
   { "extern-only", 'g', NULL, 0, N_("Display only external symbols") },
   { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols") },
+  { "print-armap", 's', NULL, 0,
+    N_("Include index for symbols from archive members") },
+
   { NULL, 0, NULL, 0, N_("Output format:") },
   { "print-file-name", 'A', NULL, 0, N_("Print name of the input file before every symbol") },
-  { NULL, 'o', NULL, 0, N_("Same as -A") },
+  { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A" },
   { "format", 'f', "FORMAT", 0, N_("Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The default is `sysv'") },
   { NULL, 'B', NULL, 0, N_("Same as --format=bsd") },
   { "portability", 'P', NULL, 0, N_("Same as --format=posix") },
   { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values") },
-  { "mark-weak", OPT_MARK_WEAK, NULL, 0, N_("mark weak symbols") },
+  { "mark-weak", OPT_MARK_WEAK, NULL, 0, N_("Mark weak symbols") },
+  { "print-size", 'S', NULL, 0, N_("Print size of defined symbols") },
+
   { NULL, 0, NULL, 0, N_("Output options:") },
   { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address") },
   { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols") },
+  { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort") },
   { NULL, 0, NULL, 0, N_("Miscellaneous:") },
   { NULL, 0, NULL, 0, NULL }
 };
@@ -96,7 +102,7 @@ static struct argp argp =
 
 
 /* Print symbols in file named FNAME.  */
-static int process_file (const char *fname);
+static int process_file (const char *fname, bool more_than_one);
 
 /* Handle content of archive.  */
 static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
@@ -131,14 +137,23 @@ static enum
 } format;
 
 /* Print defined, undefined, or both?  */
-static int hide_undefined;
-static int hide_defined;
+static bool hide_undefined;
+static bool hide_defined;
 
 /* Print local symbols also?  */
-static int hide_local;
+static bool hide_local;
 
 /* Nonzero if full filename should precede every symbol.  */
-static int print_file_name;
+static bool print_file_name;
+
+/* If true print size of defined symbols in BSD format.  */
+static bool print_size;
+
+/* If true print archive index.  */
+static bool print_armap;
+
+/* If true reverse sorting.  */
+static bool reverse_sort;
 
 /* Type of the section we are printing.  */
 static int symsec_type = SHT_SYMTAB;
@@ -161,7 +176,7 @@ static enum
 
 /* If nonzero weak symbols are distinguished from global symbols by adding
    a `*' after the identifying letter for the symbol class and type.  */
-static int mark_weak;
+static bool mark_weak;
 
 
 int
@@ -195,12 +210,16 @@ main (int argc, char *argv[])
 
   if (remaining == argc)
     /* The user didn't specify a name so we use a.out.  */
-    result = process_file ("a.out");
+    result = process_file ("a.out", false);
   else
-    /* Process all the remaining files.  */
-    do
-      result |= process_file (argv[remaining]);
-    while (++remaining < argc);
+    {
+      /* Process all the remaining files.  */
+      bool more_than_one = remaining + 1 < argc;
+
+      do
+       result |= process_file (argv[remaining], more_than_one);
+      while (++remaining < argc);
+    }
 
   return result;
 }
@@ -215,7 +234,7 @@ print_version (FILE *stream, struct argp_state *state)
 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\
-"), "2002");
+"), "2003");
   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
@@ -242,7 +261,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case 'g':
-      hide_local = 1;
+      hide_local = true;
       break;
 
     case 'n':
@@ -263,13 +282,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case 'u':
-      hide_undefined = 0;
-      hide_defined = 1;
+      hide_undefined = false;
+      hide_defined = true;
       break;
 
     case 'A':
     case 'o':
-      print_file_name = 1;
+      print_file_name = true;
       break;
 
     case 'B':
@@ -285,12 +304,24 @@ parse_opt (int key, char *arg, struct argp_state *state)
       break;
 
     case OPT_DEFINED:
-      hide_undefined = 1;
-      hide_defined = 0;
+      hide_undefined = true;
+      hide_defined = false;
       break;
 
     case OPT_MARK_WEAK:
-      mark_weak = 1;
+      mark_weak = true;
+      break;
+
+    case 'S':
+      print_size = true;
+      break;
+
+    case 's':
+      print_armap = true;
+      break;
+
+    case 'r':
+      reverse_sort = true;
       break;
 
     default:
@@ -317,7 +348,7 @@ Report bugs to <drepper@redhat.com>.\n"));
 
 
 static int
-process_file (const char *fname)
+process_file (const char *fname, bool more_than_one)
 {
   /* Open the file and determine the type.  */
   int fd;
@@ -337,7 +368,8 @@ process_file (const char *fname)
     {
       if (elf_kind (elf) == ELF_K_ELF)
        {
-         int result = handle_elf (elf, NULL, fname, NULL);
+         int result = handle_elf (elf, more_than_one ? "" : NULL,
+                                  fname, NULL);
 
          if (elf_end (elf) != 0)
            INTERNAL_ERROR (fname);
@@ -389,12 +421,50 @@ handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
   if (prefix != NULL)
     cp = stpcpy (cp, prefix);
   cp = stpcpy (cp, fname);
-  stpcpy (cp, "(");
+  stpcpy (cp, "[");
 
   cp = new_suffix;
   if (suffix != NULL)
     cp = stpcpy (cp, suffix);
-  stpcpy (cp, ")");
+  stpcpy (cp, "]");
+
+  /* First print the archive index if this is wanted.  */
+  if (print_armap)
+    {
+      Elf_Arsym *arsym = elf_getarsym (elf, NULL);
+
+      if (arsym != NULL)
+       {
+         Elf_Arhdr *arhdr = NULL;
+         size_t arhdr_off = 0; /* Note: 0 is no valid offset.  */
+
+         puts (gettext("\nArchive index:"));
+
+         while (arsym->as_off != 0)
+           {
+             if (arhdr_off != arsym->as_off
+                 && (elf_rand (elf, arsym->as_off) != arsym->as_off
+                     || (subelf = elf_begin (fd, cmd, elf)) == NULL
+                     || (arhdr = elf_getarhdr (subelf)) == NULL))
+               {
+                 error (0, 0, gettext ("invalid offset %zu for symbol %s"),
+                        arsym->as_off, arsym->as_name);
+                 continue;
+               }
+
+             printf (gettext ("%s in %s\n"), arsym->as_name, arhdr->ar_name);
+
+             ++arsym;
+           }
+
+         if (elf_rand (elf, SARMAG) != SARMAG)
+           {
+             error (0, 0,
+                    gettext ("cannot reset archive offset to beginning"));
+             return 1;
+           }
+       }
+    }
 
   /* Process all the files contained in the archive.  */
   while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
@@ -402,16 +472,22 @@ handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
       /* The the header for this element.  */
       Elf_Arhdr *arhdr = elf_getarhdr (subelf);
 
-        if (elf_kind (subelf) == ELF_K_ELF)
-       result |= handle_elf (subelf, new_prefix, arhdr->ar_name, new_suffix);
-      else if (elf_kind (subelf) == ELF_K_AR)
-       result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
-                            new_suffix);
-      else
+      /* Skip over the index entries.  */
+      if (strcmp (arhdr->ar_name, "/") != 0
+         && strcmp (arhdr->ar_name, "//") != 0)
        {
-         error (0, 0, gettext ("%s%s%s: file format not recognized"),
-                new_prefix, arhdr->ar_name, new_suffix);
-         result = 1;
+         if (elf_kind (subelf) == ELF_K_ELF)
+           result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
+                                 new_suffix);
+         else if (elf_kind (subelf) == ELF_K_AR)
+           result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
+                                new_suffix);
+         else
+           {
+             error (0, 0, gettext ("%s%s%s: file format not recognized"),
+                    new_prefix, arhdr->ar_name, new_suffix);
+             result = 1;
+           }
        }
 
       /* Get next archive element.  */
@@ -424,6 +500,172 @@ handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
 }
 
 
+struct local_name
+{
+  const char *name;
+  size_t lineno;
+  Dwarf_Addr lowpc;
+  Dwarf_Addr highpc;
+  char file[0];
+};
+
+
+static int
+local_compare (const void *p1, const void *p2)
+{
+  struct local_name *g1 = (struct local_name *) p1;
+  struct local_name *g2 = (struct local_name *) p2;
+  int result;
+
+  result = strcmp (g1->name, g2->name);
+  if (result == 0)
+    {
+      if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
+       {
+         /* g2 is contained in g1.  Update the data.  */
+         g2->lowpc = g1->lowpc;
+         g2->highpc = g1->highpc;
+         result = 0;
+       }
+      else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
+       {
+         /* g1 is contained in g2.  Update the data.  */
+         g1->lowpc = g2->lowpc;
+         g1->highpc = g2->highpc;
+         result = 0;
+       }
+      else
+       result = g1->lowpc < g2->lowpc ? -1 : 1;
+    }
+
+  return result;
+}
+
+
+static int
+get_var_range (Dwarf_Die die, Dwarf_Unsigned *lowpc, Dwarf_Unsigned *highpc)
+{
+  Dwarf_Attribute loc;
+  Dwarf_Error err;
+  Dwarf_Locdesc *locdesc;
+  Dwarf_Signed len;
+
+  if (dwarf_attr (die, DW_AT_location, &loc, &err) != DW_DLV_OK)
+    return 1;
+
+  if (dwarf_loclist (loc, &locdesc, &len, &err) != DW_DLV_OK)
+    return 1;
+
+  /* XXX incomplete.  */
+  return 1;
+}
+
+
+static void *
+get_local_names (Ebl *ebl, Dwarf_Debug dbg)
+{
+  /* We iterate over the content of the .debug_info section.  We only
+     look at the level immediately below the compile unit DIE.  */
+  int ret;
+  Dwarf_Error err;
+  Dwarf_Unsigned culen;
+  Dwarf_Unsigned nextcu;
+  Dwarf_Off offset = 0;
+  void *root = NULL;
+
+  while ((ret = dwarf_next_cu_header (dbg, &culen, NULL, NULL, NULL, &nextcu,
+                                     &err)) == DW_DLV_OK)
+    {
+      Dwarf_Half tag;
+      Dwarf_Die die;
+      Dwarf_Die old = NULL;
+      char **files = NULL;
+      Dwarf_Signed nfiles;
+
+      offset += culen;
+
+      if (dwarf_offdie (dbg, offset, &die, &err) == DW_DLV_OK
+         /* This better be a compile unit DIE. */
+         && dwarf_tag (die, &tag, &err) == DW_DLV_OK
+         && tag == DW_TAG_compile_unit
+         /* Get the source files for this compilation unit.  */
+         && dwarf_srcfiles (die, &files, &nfiles, &err) != DW_DLV_ERROR
+         /* Search all immediate children for subprogram and variable
+            DIEs.  */
+         && (old = die, dwarf_child (die, &die, &err) == DW_DLV_OK))
+       do
+         {
+           dwarf_dealloc (dbg, old, DW_DLA_DIE);
+
+           if (dwarf_tag (die, &tag, &err) == DW_DLV_OK
+               && (tag == DW_TAG_subprogram || tag == DW_TAG_variable))
+             {
+               /* We are interested in five attributes: name,
+                  decl_file, decl_line, low_pc, and high_pc.  */
+               Dwarf_Attribute name = NULL;
+               Dwarf_Attribute file = NULL;
+               Dwarf_Attribute line = NULL;
+               char *namestr;
+               Dwarf_Unsigned fileidx;
+               Dwarf_Unsigned lineno;
+               Dwarf_Addr lowpc;
+               Dwarf_Addr highpc;
+
+               if (dwarf_attr (die, DW_AT_name, &name, &err) == DW_DLV_OK
+                   && dwarf_formstring (name, &namestr, &err) == DW_DLV_OK
+                   && (dwarf_attr (die, DW_AT_decl_file, &file, &err)
+                       == DW_DLV_OK)
+                   && dwarf_formudata (file, &fileidx, &err) == DW_DLV_OK
+                   && fileidx > 0 && fileidx <= nfiles
+                   && (dwarf_attr (die, DW_AT_decl_line, &line, &err)
+                       == DW_DLV_OK)
+                   && dwarf_formudata (line, &lineno, &err) == DW_DLV_OK
+                   && lineno != 0
+                   && ((tag = DW_TAG_subprogram
+                        && dwarf_lowpc (die, &lowpc, &err) == DW_DLV_OK
+                        && dwarf_highpc (die, &highpc, &err) == DW_DLV_OK)
+                       || (tag == DW_TAG_variable
+                           && get_var_range (die, &lowpc, &highpc) == 0)))
+                 {
+                   struct local_name *newp;
+                   size_t namelen = strlen (namestr) + 1;
+                   const char *bfile = basename (files[fileidx - 1]);
+                   size_t filelen = strlen (bfile) + 1;
+
+                   newp = xmalloc (sizeof (*newp) + namelen + filelen);
+                   newp->name = memcpy (mempcpy (newp->file, bfile, filelen),
+                                        namestr, namelen);
+                   newp->lineno = lineno;
+                   newp->lowpc = lowpc;
+                   newp->highpc = highpc;
+
+                   /* XXX Return value shouldn't be ignored.  If the
+                      new entry is not added to the tree the data
+                      structure should be freed.  */
+                   tsearch (newp, &root, local_compare);
+                 }
+
+               dwarf_dealloc (dbg, name, DW_DLA_ATTR);
+               dwarf_dealloc (dbg, file, DW_DLA_ATTR);
+               dwarf_dealloc (dbg, line, DW_DLA_ATTR);
+             }
+
+           old = die;
+         }
+       while (dwarf_siblingof (dbg, die, &die, &err) == DW_DLV_OK);
+
+      dwarf_dealloc (dbg, old, DW_DLA_DIE);
+      while (nfiles-- > 0)
+       dwarf_dealloc (dbg, files[nfiles], DW_DLA_STRING);
+      dwarf_dealloc (dbg, files, DW_DLA_LIST);
+
+      offset = nextcu;
+    }
+
+  return root;
+}
+
+
 /* Mapping of radix and binary class to length.  */
 static const int length_map[2][3] =
 {
@@ -459,6 +701,17 @@ global_compare (const void *p1, const void *p2)
 }
 
 
+static void
+free_global (void *p)
+{
+  struct global_name *g = (struct global_name *) p;
+
+  free ((char *) g->name);
+
+  free (p);
+}
+
+
 /* Show symbols in SysV format.  */
 static void
 show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
@@ -472,14 +725,15 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
   const char **scnnames;
   bool scnnames_malloced;
   const char *fmtstr;
-  uint32_t shstrndx;
+  size_t shstrndx;
   Dwarf_Debug dbg;
   Dwarf_Global *globals;
   Dwarf_Signed globcnt;
   Dwarf_Error err;
   const char *linenum;
   char linenumbuf[PATH_MAX + 10];
-  void *root = NULL;
+  void *global_root = NULL;
+  void *local_root = NULL;
 
   if (elf_getshnum (ebl->elf, &shnum) < 0)
     INTERNAL_ERROR (fullname);
@@ -513,12 +767,20 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
                {
                  newp->global = globals[cnt];
                  newp->name = name;
-                 tsearch (newp, &root, global_compare);
+                 /* XXX Return value shouldn't be ignored.  If the
+                    new entry is not added to the tree the data
+                    structure should be freed.  */
+                 tsearch (newp, &global_root, global_compare);
                }
            }
        }
       else
        globals = NULL;
+
+      /* Try to get the local symbols which are not in the
+        .debug_pubnames section.  */
+      if (! hide_local)
+       local_root = get_local_names (ebl, dbg);
     }
   else
     dbg = NULL;
@@ -535,7 +797,7 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
     {
       GElf_Shdr shdr_mem;
 
-      assert (elf_ndxscn (scn) != cnt++);
+      assert (elf_ndxscn (scn) == cnt++);
 
       scnnames[elf_ndxscn (scn)]
        = elf_strptr (ebl->elf, shstrndx,
@@ -543,8 +805,8 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
     }
 
   /* We always print this prolog.  */
-  if (prefix == NULL)
-    printf (gettext ("\n\nSymbols from %s:\n\n"), fname);
+  if (prefix == NULL || 1)
+    printf (gettext ("\n\nSymbols from %s:\n\n"), fullname);
   else
     printf (gettext ("\n\nSymbols from %s[%s]:\n\n"), prefix, fname);
 
@@ -582,17 +844,19 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
        continue;
 
       linenum = "";
-      if (root != NULL)
+      if (syms[cnt].sym.st_shndx != SHN_UNDEF
+         && GELF_ST_BIND (syms[cnt].sym.st_info) != STB_LOCAL
+         && global_root != NULL)
        {
          struct global_name fake;
          struct global_name **found;
          Dwarf_Off dieoff;
          Dwarf_Off cudieoff;
-         Dwarf_Die die;
-         Dwarf_Die cudie;
+         Dwarf_Die die = NULL;
+         Dwarf_Die cudie = NULL;
 
          fake.name = symstr;
-         found = tfind (&fake, &root, global_compare);
+         found = tfind (&fake, &global_root, global_compare);
          if (found != NULL
              && dwarf_global_name_offsets ((*found)->global, NULL, &dieoff,
                                            &cudieoff, &err) == DW_DLV_OK
@@ -600,8 +864,9 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
              && dwarf_offdie (dbg, cudieoff, &cudie, &err) == DW_DLV_OK)
            {
              Dwarf_Addr lowpc;
-             Dwarf_Line *lines;
+             Dwarf_Line *lines = NULL;
              Dwarf_Signed nlines;
+             int inner;
 
              if (dwarf_srclines (cudie, &lines, &nlines, &err) == DW_DLV_OK
                  && dwarf_lowpc (die, &lowpc, &err) == DW_DLV_OK)
@@ -609,7 +874,6 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
                  Dwarf_Addr addr;
                  Dwarf_Unsigned lineno;
                  char *linesrc;
-                 int inner;
 
                  for (inner = 1; inner < nlines; ++inner)
                    if (dwarf_lineaddr (lines[inner], &addr, &err) != DW_DLV_OK
@@ -628,13 +892,36 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
 
                      dwarf_dealloc (dbg, linesrc, DW_DLA_STRING);
                    }
+               }
 
+             if (lines != NULL)
+               {
                  for (inner = 0; inner < nlines; ++inner)
                    dwarf_dealloc (dbg, lines[inner], DW_DLA_LINE);
                  dwarf_dealloc (dbg, lines, DW_DLA_LIST);
                }
+           }
+
+         dwarf_dealloc (dbg, die, DW_DLA_DIE);
+         dwarf_dealloc (dbg, cudie, DW_DLA_DIE);
+       }
+
+      if (*linenum == '\0'
+         && *symstr != '\0'
+         && syms[cnt].sym.st_shndx != SHN_UNDEF
+         && local_root != NULL)
+       {
+         struct local_name fake;
+         struct local_name **found;
 
-             dwarf_dealloc (dbg, die, DW_DLA_DIE);
+         fake.name = symstr;
+         fake.lowpc = fake.highpc = syms[cnt].sym.st_value;
+         found = tfind (&fake, &local_root, local_compare);
+         if (found != NULL)
+           {
+             snprintf (linenumbuf, sizeof (linenumbuf), "%s:%" PRIu64,
+                       (*found)->file, (uint64_t) (*found)->lineno);
+             linenum = linenumbuf;
            }
        }
 
@@ -662,7 +949,8 @@ show_symbols_sysv (Ebl *ebl, GElf_Word strndx,
 
   if (dbg != NULL)
     {
-      tdestroy (root, free);
+      tdestroy (global_root, free_global);
+      tdestroy (local_root, free);
 
       if (globals != NULL)
        {
@@ -708,17 +996,31 @@ show_symbols_bsd (Elf *elf, GElf_Ehdr *ehdr, GElf_Word strndx,
 {
   int digits = length_map[gelf_getclass (elf) - 1][radix];
   const char *fmtstr;
+  const char *sfmtstr;
+  const char *ufmtstr;
   size_t cnt;
 
   if (prefix != NULL && ! print_file_name)
     printf ("\n%s:\n", fname);
 
   if (radix == radix_hex)
-    fmtstr = "%0*" PRIx64 " %c%s %s\n";
+    {
+      fmtstr = "%0*" PRIx64 " %c%s %s\n";
+      sfmtstr = "%2$0*1$" PRIx64 " %7$0*6$" PRIx64 " %3$c%4$s %5$s\n";
+      ufmtstr = "%*s U%s %s\n";
+    }
   else if (radix == radix_decimal)
-    fmtstr = "%*" PRId64 " %c%s %s\n";
+    {
+      fmtstr = "%*" PRId64 " %c%s %s\n";
+      sfmtstr = "%2$*1$" PRId64 " %7$*6$" PRId64 " %3$c%4$s %5$s\n";
+      ufmtstr = "%*s U%s %s\n";
+    }
   else
-    fmtstr = "%0*" PRIo64 " %c%s %s\n";
+    {
+      fmtstr = "%0*" PRIo64 " %c%s %s\n";
+      sfmtstr = "%2$0*1$" PRIo64 " %7$0*6$" PRIo64 " %3$c%4$s %5$s\n";
+      ufmtstr = "%* U%s %s\n";
+    }
 
   /* Iterate over all symbols.  */
   for (cnt = 0; cnt < nsyms; ++cnt)
@@ -745,13 +1047,24 @@ show_symbols_bsd (Elf *elf, GElf_Ehdr *ehdr, GElf_Word strndx,
          putchar_unlocked (':');
        }
 
-      printf (fmtstr,
-             digits, syms[cnt].sym.st_value,
-             class_type_char (&syms[cnt].sym),
-             mark_weak
-             ? (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK ? "*" : " ")
-             : "",
-             elf_strptr (elf, strndx, syms[cnt].sym.st_name));
+      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
+       printf (ufmtstr,
+               digits, "",
+               mark_weak
+               ? (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
+                  ? "*" : " ")
+               : "",
+               elf_strptr (elf, strndx, syms[cnt].sym.st_name));
+      else
+       printf (print_size ? sfmtstr : fmtstr,
+               digits, syms[cnt].sym.st_value,
+               class_type_char (&syms[cnt].sym),
+               mark_weak
+               ? (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
+                  ? "*" : " ")
+               : "",
+               elf_strptr (elf, strndx, syms[cnt].sym.st_name),
+               digits, (uint64_t) syms[cnt].sym.st_size);
     }
 }
 
@@ -766,7 +1079,7 @@ show_symbols_posix (Elf *elf, GElf_Ehdr *ehdr, GElf_Word strndx,
   size_t cnt;
 
   if (prefix != NULL && ! print_file_name)
-    printf ("%s[%s]:\n", prefix, fname);
+    printf ("%s:\n", fullname);
 
   if (radix == radix_hex)
     fmtstr = "%s %c%s %0*" PRIx64 "\n";
@@ -798,6 +1111,7 @@ show_symbols_posix (Elf *elf, GElf_Ehdr *ehdr, GElf_Word strndx,
        {
          fputs_unlocked (fullname, stdout);
          putchar_unlocked (':');
+         putchar_unlocked (' ');
        }
 
       printf (fmtstr,
@@ -819,7 +1133,7 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
              GElf_Shdr *shdr, const char *prefix, const char *fname,
              const char *fullname)
 {
-  uint32_t shstrndx;
+  size_t shstrndx;
   Elf_Data *data;
   Elf_Data *xndxdata;
   size_t size;
@@ -833,18 +1147,24 @@ show_symbols (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, Elf_Scn *xndxscn,
     {
       GElf_SymX *s1 = (GElf_SymX *) p1;
       GElf_SymX *s2 = (GElf_SymX *) p2;
+      int result;
+
+      result = strcmp (elf_strptr (ebl->elf, shdr->sh_link, s1->sym.st_name),
+                      elf_strptr (ebl->elf, shdr->sh_link, s2->sym.st_name));
 
-      return strcmp (elf_strptr (ebl->elf, shdr->sh_link, s1->sym.st_name),
-                    elf_strptr (ebl->elf, shdr->sh_link, s2->sym.st_name));
+      return reverse_sort ? -result : result;
     }
 
   int sort_by_address (const void *p1, const void *p2)
     {
       GElf_SymX *s1 = (GElf_SymX *) p1;
       GElf_SymX *s2 = (GElf_SymX *) p2;
+      int result;
+
+      result = (s1->sym.st_value < s2->sym.st_value
+               ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
 
-      return (s1->sym.st_value < s2->sym.st_value
-             ? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
+      return reverse_sort ? -result : result;
     }
 
   /* Get the section header string table index.  */
@@ -939,8 +1259,9 @@ handle_elf (Elf *elf, const char *prefix, const char *fname,
            const char *suffix)
 {
   size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
   size_t fname_len = strlen (fname) + 1;
-  char fullname[prefix_len + 1 + fname_len];
+  char fullname[prefix_len + 1 + fname_len + suffix_len];
   char *cp = fullname;
   Elf_Scn *scn = NULL;
   int any = 0;
@@ -971,11 +1292,10 @@ handle_elf (Elf *elf, const char *prefix, const char *fname,
 
   /* Create the full name of the file.  */
   if (prefix != NULL)
-    {
-      cp = mempcpy (cp, prefix, prefix_len);
-      *cp++ = ':';
-    }
-  memcpy (cp, fname, fname_len);
+    cp = mempcpy (cp, prefix, prefix_len);
+  cp = mempcpy (cp, fname, fname_len);
+  if (suffix != NULL)
+    memcpy (cp - 1, suffix, suffix_len + 1);
 
   /* Find the symbol table.
 
index 5e2a5d6..a7fe87e 100644 (file)
@@ -1,19 +1,16 @@
 /* Print information from ELF file in human-readable form.
-   Copyright (C) 1999, 2000, 2001, 2002 Red Hat, Inc.
+   Copyright (C) 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 1999.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -27,6 +24,7 @@
 #include <fcntl.h>
 #include <gelf.h>
 #include <inttypes.h>
+#include <langinfo.h>
 #include <libdwarf.h>
 #include <libebl.h>
 #include <libintl.h>
@@ -38,6 +36,7 @@
 #include <sys/param.h>
 
 #include <system.h>
+#include "../libdwarf/libdwarfP.h"
 
 
 /* Name and version of program.  */
@@ -61,6 +60,7 @@ static const struct argp_option options[] =
   { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
     N_("Display DWARF section content.  SECTION can be one of "
        "abbrev, aranges, frame, info, loc, line, pubnames, or str.") },
+  { "notes", 'n', NULL, 0, N_("Display the core notes") },
 
   { NULL, 0, NULL, 0, N_("Output control:") },
 
@@ -119,6 +119,9 @@ static bool print_section_groups;
 /* True if bucket list length histogram should be printed.  */
 static bool print_histogram;
 
+/* True if note section content should be printed.  */
+static bool print_notes;
+
 /* Select printing of debugging sections.  */
 static enum section_e
 {
@@ -166,6 +169,7 @@ static void handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
                           GElf_Shdr *shdr);
 static void print_debug (Ebl *ebl, GElf_Ehdr *ehdr);
 static void handle_hash (Ebl *ebl, GElf_Ehdr *ehdr);
+static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
 
 
 int
@@ -249,6 +253,7 @@ parse_opt (int key, char *arg, struct argp_state *state)
       print_dynamic_table = true;
       print_section_groups = true;
       print_histogram = true;
+      print_notes = true;
       any_control_option = true;
       break;
     case 'd':
@@ -271,9 +276,13 @@ parse_opt (int key, char *arg, struct argp_state *state)
       print_program_header = true;
       any_control_option = true;
       break;
+    case 'n':
+      print_notes = true;
+      any_control_option = true;
+      break;
     case 'r':
       print_relocations = true;
-       any_control_option = true;
+      any_control_option = true;
      break;
     case 'S':
       print_section_header = true;
@@ -340,7 +349,7 @@ print_version (FILE *stream, struct argp_state *state)
 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\
-"), "2002");
+"), "2003");
   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
@@ -475,6 +484,8 @@ process_elf_file (Elf *elf, const char *prefix, const char *fname,
     print_symtab (ebl, ehdr, SHT_SYMTAB);
   if (print_debug_sections != 0)
     print_debug (ebl, ehdr);
+  if (print_notes)
+    handle_notes (ebl, ehdr);
 
   ebl_closebackend (ebl);
 }
@@ -547,8 +558,8 @@ print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
          ehdr->e_version,
          ehdr->e_version  == EV_CURRENT ? gettext ("(current)") : "(\?\?\?)");
 
-  fputs_unlocked (gettext ("  Entry point address:               "), stdout);
-  printf ("%#" PRIx64 "\n", ehdr->e_entry);
+  printf (gettext ("  Entry point address:               %#" PRIx64 "\n"),
+         ehdr->e_entry);
 
   printf (gettext ("  Start of program headers:          %" PRId64 " %s\n"),
          ehdr->e_phoff, gettext ("(bytes into file)"));
@@ -636,7 +647,7 @@ static void
 print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
 {
   size_t cnt;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   if (! print_file_header)
     printf (gettext ("\
@@ -698,7 +709,7 @@ There are %d section headers, starting at offset %#" PRIx64 ":\n\
        *cp++ = 'T';
       *cp = '\0';
 
-      printf ("[%2Zd] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
+      printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
              " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
              " %2" PRId64 "\n",
              cnt,
@@ -721,7 +732,7 @@ static void
 print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
 {
   size_t cnt;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   if (ehdr->e_phnum == 0)
     /* No program header, this is OK in relocatable objects.  */
@@ -788,7 +799,7 @@ print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
       size_t inner;
 
       /* Print the segment number.  */
-      printf ("   %2.2Zd     ", cnt);
+      printf ("   %2.2zu     ", cnt);
 
       /* This must not happen.  */
       if (phdr == NULL)
@@ -845,7 +856,7 @@ handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   Elf_Data *symdata;
   GElf_Sym sym_mem;
   size_t cnt;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -867,13 +878,13 @@ handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 
   printf ((grpref[0] & GRP_COMDAT)
          ? ngettext ("\
-\nCOMDAT section group [%2d] '%s' with signature '%s' contains %zu entry:\n",
+\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
                      "\
-\nCOMDAT section group [%2d] '%s' with signature '%s' contains %zu entries:\n",
+\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
                      data->d_size / sizeof (Elf32_Word) - 1)
          : ngettext ("\
-\nSection group [%2d] '%s' with signature '%s' contains %zu entry:\n", "\
-\nSection group [%2d] '%s' with signature '%s' contains %zu entries:\n",
+\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
+\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
                      data->d_size / sizeof (Elf32_Word) - 1),
          elf_ndxscn (scn),
          elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
@@ -891,9 +902,9 @@ handle_scngrp (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
                              &grpshdr_mem);
 
       if (grpshdr == NULL)
-       printf (gettext ("  [%2d] <INVALID SECTION>\n"), grpref[cnt]);
+       printf (gettext ("  [%2u] <INVALID SECTION>\n"), grpref[cnt]);
       else
-       printf ("  [%2d] %s\n",
+       printf ("  [%2u] %s\n",
                grpref[cnt],
                elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name)
                ?: gettext ("<INVALID SECTION>"));
@@ -1035,7 +1046,7 @@ handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   GElf_Shdr glink;
   Elf_Data *data;
   int cnt;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -1048,15 +1059,13 @@ handle_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
           gettext ("cannot get section header string table index"));
 
   printf (ngettext ("\
-\nDynamic segment contains %lu entry:\n Addr: ", "\
-\nDynamic segment contains %lu entries:\n Addr: ",
+\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+                   "\
+\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
                    shdr->sh_size / shdr->sh_entsize),
-         (unsigned long int) (shdr->sh_size / shdr->sh_entsize));
-  printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, shdr->sh_addr);
-  fputs_unlocked (gettext ("  Offset: "), stdout);
-  printf ("%#08" PRIx64, shdr->sh_offset);
-  fputs_unlocked (gettext ("  Link to section: "), stdout);
-  printf ("[%2d] '%s'\n",
+         (unsigned long int) (shdr->sh_size / shdr->sh_entsize),
+         class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+         shdr->sh_offset,
          (int) shdr->sh_link,
          elf_strptr (ebl->elf, shstrndx,
                      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
@@ -1224,7 +1233,7 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   GElf_Shdr *destshdr;
   Elf_Scn *xndxscn;
   Elf_Data *xndxdata = NULL;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -1242,8 +1251,7 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 
   if (symshdr == NULL || symdata == NULL || destshdr == NULL)
     {
-      fputs_unlocked (gettext ("\nInvalid symbol table at offset "), stdout);
-      printf ("%#0*" PRIx64 "\n",
+      printf (gettext ("\nInvalid symbol table at offset %#0*" PRIx64 "\n"),
              class == ELFCLASS32 ? 10 : 18, shdr->sh_offset);
       return;
     }
@@ -1270,15 +1278,17 @@ handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
     error (EXIT_FAILURE, 0,
           gettext ("cannot get section header string table index"));
 
-  printf (gettext ("\
-\nRelocation section [%2d] '%s' for section [%2d] '%s' at offset "),
-         (int) elf_ndxscn (scn),
+  printf (ngettext ("\
+\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0*" PRIx64 " contains %d entry:\n",
+                   "\
+\nRelocation section [%2u] '%s' for section [%2u] '%s' at offset %#0*" PRIx64 " contains %d entries:\n",
+                   nentries),
+         (unsigned int) elf_ndxscn (scn),
          elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
-         (int) shdr->sh_info,
-         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
-  printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, shdr->sh_offset);
-  printf (ngettext (" contains %d entry:\n", " contains %d entries:\n",
-                   nentries), nentries);
+         (unsigned int) shdr->sh_info,
+         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
+         class == ELFCLASS32 ? 10 : 18, shdr->sh_offset,
+         nentries);
   fputs_unlocked (class == ELFCLASS32
                  ? gettext ("\
   Offset      Type                 Value       Name\n")
@@ -1375,7 +1385,7 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   GElf_Shdr *destshdr;
   Elf_Scn *xndxscn;
   Elf_Data *xndxdata = NULL;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -1393,8 +1403,7 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 
   if (symshdr == NULL || symdata == NULL || destshdr == NULL)
     {
-      fputs_unlocked (gettext ("\nInvalid symbol table at offset "), stdout);
-      printf ("%#0*" PRIx64 "\n",
+      printf (gettext ("\nInvalid symbol table at offset %#0*" PRIx64 "\n"),
              class == ELFCLASS32 ? 10 : 18, shdr->sh_offset);
       return;
     }
@@ -1421,14 +1430,16 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
     error (EXIT_FAILURE, 0,
           gettext ("cannot get section header string table index"));
 
-  printf (gettext ("\
-\nRelocation section '%s' for section [%2d] '%s' at offset "),
+  printf (ngettext ("\
+\nRelocation section '%s' for section [%2u] '%s' at offset %#0*" PRIx64 " contains %d entry:\n",
+                   "\
+\nRelocation section '%s' for section [%2u] '%s' at offset %#0*" PRIx64 " contains %d entries:\n",
+                   nentries),
          elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
-         (int) shdr->sh_info,
-         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
-  printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, shdr->sh_offset);
-  printf (ngettext (" contains %d entry:\n", " contains %d entries:\n",
-                   nentries), nentries);
+         (unsigned int) shdr->sh_info,
+         elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
+         class == ELFCLASS32 ? 10 : 18, shdr->sh_offset,
+         nentries);
   fputs_unlocked (class == ELFCLASS32
                  ? gettext ("\
   Offset      Type            Value       Addend Name\n")
@@ -1544,12 +1555,12 @@ handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   Elf_Scn *runscn;
   Elf_Data *data;
   int class = gelf_getclass (ebl->elf);
-  int nsyms;
-  int cnt;
+  unsigned int nsyms;
+  unsigned int cnt;
   Elf32_Word verneed_stridx = 0;
   Elf32_Word verdef_stridx = 0;
   GElf_Shdr glink;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -1597,15 +1608,16 @@ handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   nsyms = data->d_size / (class == ELFCLASS32
                          ? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
 
-  printf (ngettext ("\nSymbol table [%2d] '%s' contains %d entry:\n",
-                   "\nSymbol table [%2d] '%s' contains %d entries:\n",
+  printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
+                   "\nSymbol table [%2u] '%s' contains %u entries:\n",
                    nsyms),
-         (int) elf_ndxscn (scn),
+         (unsigned int) elf_ndxscn (scn),
          elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
-  printf (ngettext (" %lu local symbol  String table: [%2d] '%s'\n",
-                   " %lu local symbols  String table: [%2d] '%s'\n",
+  printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
+                   " %lu local symbols  String table: [%2u] '%s'\n",
                    shdr->sh_info),
-         (unsigned long int) shdr->sh_info, shdr->sh_link,
+         (unsigned long int) shdr->sh_info,
+         (unsigned int) shdr->sh_link,
          elf_strptr (ebl->elf, shstrndx,
                      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
                                    &glink)->sh_name));
@@ -1633,7 +1645,8 @@ handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
       if (sym->st_shndx != SHN_XINDEX)
        xndx = sym->st_shndx;
 
-      printf ("%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s",
+      printf (gettext ("\
+%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
              cnt,
              class == ELFCLASS32 ? 8 : 16,
              sym->st_value,
@@ -1715,10 +1728,10 @@ handle_symtab (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 
                  if (vernaux != NULL)
                    {
-                     printf ("@%s (%d)",
+                     printf ("@%s (%u)",
                              elf_strptr (ebl->elf, verneed_stridx,
                                          vernaux->vna_name),
-                             vernaux->vna_other);
+                             (unsigned int) vernaux->vna_other);
                      check_def = 0;
                    }
                  else if (! is_nobits)
@@ -1838,7 +1851,7 @@ handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   GElf_Shdr glink;
   int cnt;
   unsigned int offset;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -1851,17 +1864,15 @@ handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
           gettext ("cannot get section header string table index"));
 
   printf (ngettext ("\
-\nVersion needs section [%2d] '%s' contains %d entry:\n Addr: ", "\
-\nVersion needs section [%2d] '%s' contains %d entries:\n Addr: ",
+\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+                   "\
+\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
                    shdr->sh_info),
-         (int) elf_ndxscn (scn),
-         elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info);
-  printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, shdr->sh_addr);
-  fputs_unlocked (gettext ("  Offset: "), stdout);
-  printf ("%#08" PRIx64, shdr->sh_offset);
-  fputs_unlocked (gettext ("  Link to section: "), stdout);
-  printf ("[%2d] '%s'\n",
-         (int) shdr->sh_link,
+         (unsigned int) elf_ndxscn (scn),
+         elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
+         class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+         shdr->sh_offset,
+         (unsigned int) shdr->sh_link,
          elf_strptr (ebl->elf, shstrndx,
                      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
                                    &glink)->sh_name));
@@ -1879,10 +1890,10 @@ handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
       if (need == NULL)
        break;
 
-      printf (gettext ("  %#06x: Version: %hd  File: %s  Cnt: %hd\n"),
-             offset, need->vn_version,
+      printf (gettext ("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
+             offset, (unsigned short int) need->vn_version,
              elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
-             need->vn_cnt);
+             (unsigned short int) need->vn_cnt);
 
       auxoffset = offset + need->vn_aux;
       for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
@@ -1894,10 +1905,11 @@ handle_verneed (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
          if (aux == NULL)
            break;
 
-         printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hd\n"),
+         printf (gettext ("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
                  auxoffset,
                  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
-                 get_ver_flags (aux->vna_flags), aux->vna_other);
+                 get_ver_flags (aux->vna_flags),
+                 (unsigned short int) aux->vna_other);
 
          auxoffset += aux->vna_next;
        }
@@ -1916,7 +1928,7 @@ handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   GElf_Shdr glink;
   int cnt;
   unsigned int offset;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -1929,18 +1941,16 @@ handle_verdef (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
           gettext ("cannot get section header string table index"));
 
   printf (ngettext ("\
-\nVersion definition section [%2d] '%s' contains %d entry:\n Addr: ", "\
-\nVersion definition section [%2d] '%s' contains %d entries:\n Addr: ",
+\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+                   "\
+\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
                    shdr->sh_info),
-         (int) elf_ndxscn (scn),
+         (unsigned int) elf_ndxscn (scn),
          elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
-         shdr->sh_info);
-  printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, shdr->sh_addr);
-  fputs_unlocked (gettext ("  Offset: "), stdout);
-  printf ("%#08" PRIx64, shdr->sh_offset);
-  fputs_unlocked (gettext ("  Link to section: "), stdout);
-  printf ("[%2d] '%s'\n",
-         (int) shdr->sh_link,
+         shdr->sh_info,
+         class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+         shdr->sh_offset,
+         (unsigned int) shdr->sh_link,
          elf_strptr (ebl->elf, shstrndx,
                      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
                                    &glink)->sh_name));
@@ -2006,7 +2016,7 @@ handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
   const char **filename;
   size_t nvername;
   unsigned int cnt;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the data of the section.  */
   data = elf_getdata (scn, NULL);
@@ -2229,18 +2239,16 @@ handle_versym (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
 
   /* Print the header.  */
   printf (ngettext ("\
-\nVersion symbols section [%2d] '%s' contains %d entry:\n Addr: ", "\
-\nVersion symbols section [%2d] '%s' contains %d entries:\n Addr: ",
+\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
+                   "\
+\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
                    shdr->sh_size / shdr->sh_entsize),
-         (int) elf_ndxscn (scn),
+         (unsigned int) elf_ndxscn (scn),
          elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
-         (int) (shdr->sh_size / shdr->sh_entsize));
-  printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, shdr->sh_addr);
-  fputs_unlocked (gettext ("  Offset: "), stdout);
-  printf ("%#08" PRIx64, shdr->sh_offset);
-  fputs_unlocked (gettext ("  Link to section: "), stdout);
-  printf ("[%2d] '%s'",
-         (int) shdr->sh_link,
+         (int) (shdr->sh_size / shdr->sh_entsize),
+         class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+         shdr->sh_offset,
+         (unsigned int) shdr->sh_link,
          elf_strptr (ebl->elf, shstrndx,
                      gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
                                    &glink)->sh_name));
@@ -2293,7 +2301,7 @@ handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
   /* Find the symbol table(s).  For this we have to search through the
      section table.  */
   Elf_Scn *scn = NULL;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Get the section header string table index.  */
   if (elf_getshstrndx (ebl->elf, &shstrndx) < 0)
@@ -2334,20 +2342,17 @@ handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
          chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
 
          printf (ngettext ("\
-\nHistogram for bucket list length in section [%2d] '%s' (total of %d bucket):\n Addr: ", "\
-\nHistogram for bucket list length in section [%2d] '%s' (total of %d buckets):\n Addr: ",
+\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+                           "\
+\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
                            nbucket),
-                 (int) elf_ndxscn (scn),
+                 (unsigned int) elf_ndxscn (scn),
                  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
-                 (int) nbucket);
-         printf ("%#0*" PRIx64,
+                 (int) nbucket,
                  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
-                 shdr->sh_addr);
-         fputs_unlocked (gettext ("  Offset: "), stdout);
-         printf ("%#08" PRIx64, shdr->sh_offset);
-         fputs_unlocked (gettext ("  Link to section: "), stdout);
-         printf ("[%2d] '%s'\n",
-                 (int) shdr->sh_link,
+                 shdr->sh_addr,
+                 shdr->sh_offset,
+                 (unsigned int) shdr->sh_link,
                  elf_strptr (ebl->elf, shstrndx,
                              gelf_getshdr (elf_getscn (ebl->elf,
                                                        shdr->sh_link),
@@ -2382,13 +2387,14 @@ handle_hash (Ebl *ebl, GElf_Ehdr *ehdr)
              Elf32_Word acc;
 
              puts (gettext (" Length  Number  % of total  Coverage"));
-             printf ("      0  %6" PRIu32 "      %5.1f%%\n",
+             printf (gettext ("      0  %6" PRIu32 "      %5.1f%%\n"),
                      counts[0], (counts[0] * 100.0) / nbucket);
 
              for (cnt = 1; cnt <= maxlength; ++cnt)
                {
                  nzero_counts += counts[cnt] * cnt;
-                 printf ("%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n",
+                 printf (gettext ("\
+%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
                          (int) cnt,
                          counts[cnt], (counts[cnt] * 100.0) / nbucket,
                          (nzero_counts * 100.0) / nsyms);
@@ -2739,9 +2745,369 @@ dwarf_form_string (Dwarf_Signed form)
 }
 
 
+static const char *
+dwarf_lang_string (unsigned int lang)
+{
+  static const char *known[] =
+    {
+      [DW_LANG_C89] = "ISO C89",
+      [DW_LANG_C] = "C",
+      [DW_LANG_Ada83] = "Ada83",
+      [DW_LANG_C_plus_plus ] = "C++",
+      [DW_LANG_Cobol74] = "Cobol74",
+      [DW_LANG_Cobol85] = "Cobol85",
+      [DW_LANG_Fortran77] = "Fortran77",
+      [DW_LANG_Fortran90] = "Fortran90",
+      [DW_LANG_Pascal83] = "Pascal83",
+      [DW_LANG_Modula2] = "Modula2",
+      [DW_LANG_Java] = "Java",
+      [DW_LANG_C99] = "ISO C99",
+      [DW_LANG_Ada95] = "Ada95",
+      [DW_LANG_Fortran95] = "Fortran95",
+      [DW_LANG_PL1] = "PL1"
+    };
+
+  if (lang < sizeof (known) / sizeof (known[0]))
+    return known[lang];
+  else if (lang == DW_LANG_Mips_Assembler)
+    /* This language tag is used for assembler in general.  */
+    return "Assembler";
+
+  if (lang >= DW_LANG_lo_user && lang <= DW_LANG_hi_user)
+    {
+      static char buf[100];
+      snprintf (buf, sizeof (buf), "lo_user+%u", lang - DW_LANG_lo_user);
+      return buf;
+    }
+
+  return "???";
+}
+
+
+static void
+print_ops (Dwarf_Debug dbg, int level, Dwarf_Half addrsize, Dwarf_Unsigned len,
+          Dwarf_Ptr data)
+{
+  static const char *known[] =
+    {
+      [DW_OP_addr] = "addr",
+      [DW_OP_deref] = "deref",
+      [DW_OP_const1u] = "const1u",
+      [DW_OP_const1s] = "const1s",
+      [DW_OP_const2u] = "const2u",
+      [DW_OP_const2s] = "const2s",
+      [DW_OP_const4u] = "const4u",
+      [DW_OP_const4s] = "const4s",
+      [DW_OP_const8u] = "const8u",
+      [DW_OP_const8s] = "const8s",
+      [DW_OP_constu] = "constu",
+      [DW_OP_consts] = "consts",
+      [DW_OP_dup] = "dup",
+      [DW_OP_drop] = "drop",
+      [DW_OP_over] = "over",
+      [DW_OP_pick] = "pick",
+      [DW_OP_swap] = "swap",
+      [DW_OP_rot] = "rot",
+      [DW_OP_xderef] = "xderef",
+      [DW_OP_abs] = "abs",
+      [DW_OP_and] = "and",
+      [DW_OP_div] = "div",
+      [DW_OP_minus] = "minus",
+      [DW_OP_mod] = "mod",
+      [DW_OP_mul] = "mul",
+      [DW_OP_neg] = "neg",
+      [DW_OP_not] = "not",
+      [DW_OP_or] = "or",
+      [DW_OP_plus] = "plus",
+      [DW_OP_plus_uconst] = "plus_uconst",
+      [DW_OP_shl] = "shl",
+      [DW_OP_shr] = "shr",
+      [DW_OP_shra] = "shra",
+      [DW_OP_xor] = "xor",
+      [DW_OP_bra] = "bra",
+      [DW_OP_eq] = "eq",
+      [DW_OP_ge] = "ge",
+      [DW_OP_gt] = "gt",
+      [DW_OP_le] = "le",
+      [DW_OP_lt] = "lt",
+      [DW_OP_ne] = "ne",
+      [DW_OP_skip] = "skip",
+      [DW_OP_lit0] = "lit0",
+      [DW_OP_lit1] = "lit1",
+      [DW_OP_lit2] = "lit2",
+      [DW_OP_lit3] = "lit3",
+      [DW_OP_lit4] = "lit4",
+      [DW_OP_lit5] = "lit5",
+      [DW_OP_lit6] = "lit6",
+      [DW_OP_lit7] = "lit7",
+      [DW_OP_lit8] = "lit8",
+      [DW_OP_lit9] = "lit9",
+      [DW_OP_lit10] = "lit10",
+      [DW_OP_lit11] = "lit11",
+      [DW_OP_lit12] = "lit12",
+      [DW_OP_lit13] = "lit13",
+      [DW_OP_lit14] = "lit14",
+      [DW_OP_lit15] = "lit15",
+      [DW_OP_lit16] = "lit16",
+      [DW_OP_lit17] = "lit17",
+      [DW_OP_lit18] = "lit18",
+      [DW_OP_lit19] = "lit19",
+      [DW_OP_lit20] = "lit20",
+      [DW_OP_lit21] = "lit21",
+      [DW_OP_lit22] = "lit22",
+      [DW_OP_lit23] = "lit23",
+      [DW_OP_lit24] = "lit24",
+      [DW_OP_lit25] = "lit25",
+      [DW_OP_lit26] = "lit26",
+      [DW_OP_lit27] = "lit27",
+      [DW_OP_lit28] = "lit28",
+      [DW_OP_lit29] = "lit29",
+      [DW_OP_lit30] = "lit30",
+      [DW_OP_lit31] = "lit31",
+      [DW_OP_reg0] = "reg0",
+      [DW_OP_reg1] = "reg1",
+      [DW_OP_reg2] = "reg2",
+      [DW_OP_reg3] = "reg3",
+      [DW_OP_reg4] = "reg4",
+      [DW_OP_reg5] = "reg5",
+      [DW_OP_reg6] = "reg6",
+      [DW_OP_reg7] = "reg7",
+      [DW_OP_reg8] = "reg8",
+      [DW_OP_reg9] = "reg9",
+      [DW_OP_reg10] = "reg10",
+      [DW_OP_reg11] = "reg11",
+      [DW_OP_reg12] = "reg12",
+      [DW_OP_reg13] = "reg13",
+      [DW_OP_reg14] = "reg14",
+      [DW_OP_reg15] = "reg15",
+      [DW_OP_reg16] = "reg16",
+      [DW_OP_reg17] = "reg17",
+      [DW_OP_reg18] = "reg18",
+      [DW_OP_reg19] = "reg19",
+      [DW_OP_reg20] = "reg20",
+      [DW_OP_reg21] = "reg21",
+      [DW_OP_reg22] = "reg22",
+      [DW_OP_reg23] = "reg23",
+      [DW_OP_reg24] = "reg24",
+      [DW_OP_reg25] = "reg25",
+      [DW_OP_reg26] = "reg26",
+      [DW_OP_reg27] = "reg27",
+      [DW_OP_reg28] = "reg28",
+      [DW_OP_reg29] = "reg29",
+      [DW_OP_reg30] = "reg30",
+      [DW_OP_reg31] = "reg31",
+      [DW_OP_breg0] = "breg0",
+      [DW_OP_breg1] = "breg1",
+      [DW_OP_breg2] = "breg2",
+      [DW_OP_breg3] = "breg3",
+      [DW_OP_breg4] = "breg4",
+      [DW_OP_breg5] = "breg5",
+      [DW_OP_breg6] = "breg6",
+      [DW_OP_breg7] = "breg7",
+      [DW_OP_breg8] = "breg8",
+      [DW_OP_breg9] = "breg9",
+      [DW_OP_breg10] = "breg10",
+      [DW_OP_breg11] = "breg11",
+      [DW_OP_breg12] = "breg12",
+      [DW_OP_breg13] = "breg13",
+      [DW_OP_breg14] = "breg14",
+      [DW_OP_breg15] = "breg15",
+      [DW_OP_breg16] = "breg16",
+      [DW_OP_breg17] = "breg17",
+      [DW_OP_breg18] = "breg18",
+      [DW_OP_breg19] = "breg19",
+      [DW_OP_breg20] = "breg20",
+      [DW_OP_breg21] = "breg21",
+      [DW_OP_breg22] = "breg22",
+      [DW_OP_breg23] = "breg23",
+      [DW_OP_breg24] = "breg24",
+      [DW_OP_breg25] = "breg25",
+      [DW_OP_breg26] = "breg26",
+      [DW_OP_breg27] = "breg27",
+      [DW_OP_breg28] = "breg28",
+      [DW_OP_breg29] = "breg29",
+      [DW_OP_breg30] = "breg30",
+      [DW_OP_breg31] = "breg31",
+      [DW_OP_regx] = "regx",
+      [DW_OP_fbreg] = "fbreg",
+      [DW_OP_bregx] = "bregx",
+      [DW_OP_piece] = "piece",
+      [DW_OP_deref_size] = "deref_size",
+      [DW_OP_xderef_size] = "xderef_size",
+      [DW_OP_nop] = "nop",
+      [DW_OP_push_object_address] = "push_object_address",
+      [DW_OP_call2] = "call2",
+      [DW_OP_call4] = "call4",
+      [DW_OP_call_ref] = "call_ref",
+    };
+
+  Dwarf_Unsigned offset = 0;
+  while (len-- > 0)
+    {
+      size_t op = *((unsigned char *) data)++;
+      Dwarf_Unsigned addr;
+      Dwarf_Ptr start;
+      unsigned int sleb;
+      unsigned int uleb;
+
+      switch (op)
+       {
+       case DW_OP_call_ref:
+       case DW_OP_addr:;
+         /* Address operand.  */
+         if (addrsize == 4)
+           addr = read_4ubyte_unaligned (dbg, data);
+         else
+           {
+             assert (addrsize == 8);
+             addr = read_8ubyte_unaligned (dbg, data);
+           }
+         data += addrsize;
+         len -= addrsize;
+
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", (uintmax_t) addr);
+         offset += 1 + addrsize;
+         break;
+
+       case DW_OP_deref_size:          /* XXX Correct?  */
+       case DW_OP_xderef_size:         /* XXX Correct?  */
+       case DW_OP_pick:
+       case DW_OP_const1u:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRIu8 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", *((uint8_t *) data)++);
+         --len;
+         offset += 2;
+         break;
+
+       case DW_OP_const2u:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRIu16 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", read_2ubyte_unaligned (dbg, data));
+         len -= 2;
+         data += 2;
+         offset += 3;
+         break;
+
+       case DW_OP_const4u:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRIu32 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", read_4ubyte_unaligned (dbg, data));
+         len -= 4;
+         data += 4;
+         offset += 5;
+         break;
+
+       case DW_OP_const8u:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRIu64 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", read_8ubyte_unaligned (dbg, data));
+         len -= 8;
+         data += 8;
+         offset += 9;
+         break;
+
+       case DW_OP_const1s:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRId8 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", *((int8_t *) data)++);
+         --len;
+         offset += 2;
+         break;
+
+       case DW_OP_const2s:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRId16 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", read_2sbyte_unaligned (dbg, data));
+         len -= 2;
+         data += 2;
+         offset += 3;
+         break;
+
+       case DW_OP_const4s:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRId32 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", read_4sbyte_unaligned (dbg, data));
+         len -= 4;
+         data += 4;
+         offset += 5;
+         break;
+
+       case DW_OP_const8s:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRId64 "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", read_8sbyte_unaligned (dbg, data));
+         len -= 8;
+         data += 8;
+         offset += 9;
+         break;
+
+       case DW_OP_piece:               /* XXX Correct?  */
+       case DW_OP_regx:
+       case DW_OP_plus_uconst:
+       case DW_OP_constu:;
+         start = data;
+         get_uleb128 (uleb, ((unsigned char *) data));
+         printf ("           %*s [%4" PRIuMAX "] %s %u\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", uleb);
+         len -= data - start;
+         offset += 1 + (data - start);
+         break;
+
+       case DW_OP_fbreg:
+       case DW_OP_breg0 ... DW_OP_breg31:
+       case DW_OP_consts:;
+         start = data;
+         get_sleb128 (sleb, ((unsigned char *) data));
+         printf ("           %*s [%4" PRIuMAX "] %s %d\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", sleb);
+         len -= data - start;
+         offset += 1 + (data - start);
+         break;
+
+       case DW_OP_bregx:
+         start = data;
+         get_uleb128 (uleb, ((unsigned char *) data));
+         get_sleb128 (sleb, ((unsigned char *) data));
+         printf ("           %*s [%4" PRIuMAX "] %s %u %d\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???", uleb, sleb);
+         len -= data - start;
+         offset += 1 + (data - start);
+         break;
+
+       case DW_OP_call2:
+       case DW_OP_call4:
+       case DW_OP_skip:
+       case DW_OP_bra:
+         printf ("           %*s [%4" PRIuMAX "] %s %" PRIuMAX "\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???",
+                 (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data)));
+         len -= 2;
+         data += 2;
+         offset += 3;
+         break;
+
+       default:
+         /* No Operand.  */
+         printf ("           %*s [%4" PRIuMAX "] %s\n",
+                 (int) (20 + level * 2), "", (uintmax_t) offset,
+                 known[op] ?: "???");
+         ++offset;
+         break;
+       }
+    }
+}
+
+
 static void
-print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                           Dwarf_Debug dbg)
+print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                           GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
   Dwarf_Unsigned offset;
 
@@ -2831,8 +3197,8 @@ print_debug_abbrev_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
    not have to know a bit about the structure of the section, libdwarf
    takes care of it.  */
 static void
-print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                            Dwarf_Debug dbg)
+print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                            GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
   Dwarf_Arange *aranges;
   Dwarf_Arange *runp;
@@ -2878,25 +3244,376 @@ print_debug_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
 
 
 static void
-print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                          Dwarf_Debug dbg)
+print_debug_frame_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                          GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
 }
 
 
 static void
-print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                         Dwarf_Debug dbg)
+print_debug_info_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                         GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
+  Dwarf_Error err;
+  Dwarf_Off offset = 0;
+  size_t maxdies = 20;
+  Dwarf_Die *dies;
+  Dwarf_Unsigned culen;
+  Dwarf_Half version;
+  Dwarf_Unsigned abbroffset;
+  Dwarf_Half addrsize;
+  Dwarf_Unsigned nextcu;
+  int ret;
+  Dwarf_Off cu_offset;
+  int level;
+
   printf (gettext ("\
-\nDWARF section '%s' at offset %#" PRIx64 ":\n"),
+\nDWARF section '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
          ".debug_info", (uint64_t) shdr->sh_offset);
+
+  /* If the section is empty we don't have to do anything.  */
+  if (shdr->sh_size == 0)
+    return;
+
+  dies = (Dwarf_Die *) xmalloc (maxdies * sizeof (Dwarf_Die));
+
+  /* New compilation unit.  */
+ next_cu:
+  ret = dwarf_next_cu_header (dbg, &culen, &version, &abbroffset, &addrsize,
+                             &nextcu, &err);
+  if (ret == DW_DLV_NO_ENTRY)
+    return;
+  if (unlikely (ret != DW_DLV_OK))
+    {
+      error (0, 0, gettext ("cannot get CU header in section '%s': %s"),
+            ".debug_info", dwarf_errmsg (err));
+      return;
+    }
+
+  printf (gettext (" Compilation unit at offset %" PRIu64 ":\n"
+                  " Version: %" PRIu16 ", Abbreviation section offset: %"
+                  PRIu64 ", Address size: %" PRIu16 "\n"),
+         offset, version, abbroffset, addrsize);
+
+  cu_offset = offset;
+  offset += culen;
+
+  level = 0;
+
+  if (unlikely (dwarf_offdie (dbg, offset, &dies[level], &err) != DW_DLV_OK))
+    {
+      error (0, 0, gettext ("cannot get DIE at offset %" PRIu64
+                           " in section '%s': %s"),
+            (uint64_t) offset, ".debug_info", dwarf_errmsg (err));
+      return;
+    }
+
+  do
+    {
+      Dwarf_Half tag;
+      static const char *const lowtags[] =
+       {
+         [DW_TAG_array_type] = "array_type",
+         [DW_TAG_class_type] = "class_type",
+         [DW_TAG_entry_point] = "entry_point",
+         [DW_TAG_enumeration_type] = "enumeration_type",
+         [DW_TAG_formal_parameter] = "formal_parameter",
+         [DW_TAG_imported_declaration] = "imported_declaration",
+         [DW_TAG_label] = "label",
+         [DW_TAG_lexical_block] = "lexical_block",
+         [DW_TAG_member] = "member",
+         [DW_TAG_pointer_type] = "pointer_type",
+         [DW_TAG_reference_type] = "reference_type",
+         [DW_TAG_compile_unit] = "compile_unit",
+         [DW_TAG_string_type] = "string_type",
+         [DW_TAG_structure_type] = "structure_type",
+         [DW_TAG_subroutine_type] = "subroutine_type",
+         [DW_TAG_typedef] = "typedef",
+         [DW_TAG_union_type] = "union_type",
+         [DW_TAG_unspecified_parameters] = "unspecified_parameters",
+         [DW_TAG_variant] = "variant",
+         [DW_TAG_common_block] = "common_block",
+         [DW_TAG_common_inclusion] = "common_inclusion",
+         [DW_TAG_inheritance] = "inheritance",
+         [DW_TAG_inlined_subroutine] = "inlined_subroutine",
+         [DW_TAG_module] = "module",
+         [DW_TAG_ptr_to_member_type] = "ptr_to_member_type",
+         [DW_TAG_set_type] = "set_type",
+         [DW_TAG_subrange_type] = "subrange_type",
+         [DW_TAG_with_stmt] = "with_stmt",
+         [DW_TAG_access_declaration] = "access_declaration",
+         [DW_TAG_base_type] = "base_type",
+         [DW_TAG_catch_block] = "catch_block",
+         [DW_TAG_const_type] = "const_type",
+         [DW_TAG_constant] = "constant",
+         [DW_TAG_enumerator] = "enumerator",
+         [DW_TAG_file_type] = "file_type",
+         [DW_TAG_friend] = "friend",
+         [DW_TAG_namelist] = "namelist",
+         [DW_TAG_namelist_item] = "namelist_item",
+         [DW_TAG_packed_type] = "packed_type",
+         [DW_TAG_subprogram] = "subprogram",
+         [DW_TAG_template_type_param] = "template_type_param",
+         [DW_TAG_template_value_param] = "template_value_param",
+         [DW_TAG_thrown_type] = "thrown_type",
+         [DW_TAG_try_block] = "try_block",
+         [DW_TAG_variant_part] = "variant_part",
+         [DW_TAG_variable] = "variable",
+         [DW_TAG_volatile_type] = "volatile_type"
+       };
+      const char *tagstr;
+      Dwarf_Attribute *attrs;
+      Dwarf_Signed nattrs;
+      size_t cnt;
+      Dwarf_Die child;
+
+      if (unlikely (dwarf_dieoffset (dies[level], &offset, &err) != DW_DLV_OK))
+       {
+         error (0, 0, gettext ("cannot get DIE offset: %s"),
+                dwarf_errmsg (err));
+         return;
+       }
+
+      if (unlikely (dwarf_tag (dies[level], &tag, &err) != DW_DLV_OK))
+       {
+         error (0, 0, gettext ("cannot get tag of DIE at offset %" PRIu64
+                               " in section '%s': %s"),
+                (uint64_t) offset, ".debug_info", dwarf_errmsg (err));
+         return;
+       }
+
+      switch (tag)
+       {
+       case DW_TAG_lo_user:
+         tagstr = "lo_user";
+         break;
+
+       case DW_TAG_MIPS_loop:
+         tagstr = "MIPS_loop";
+         break;
+
+       case DW_TAG_format_label:
+         tagstr = "format_label";
+         break;
+
+       case DW_TAG_function_template:
+         tagstr = "function_template";
+         break;
+
+       case DW_TAG_class_template:
+         tagstr = "class_template";
+         break;
+       case DW_TAG_hi_user:
+         tagstr = "hi_user";
+         break;
+
+       default:
+         if (tag < sizeof (lowtags) / sizeof (lowtags[0]))
+           tagstr = lowtags[tag];
+         else
+           tagstr = "???";
+         break;
+       }
+
+      printf (" [%6" PRIx64 "]  %*s%s\n",
+             (uint64_t) offset, (int) (level * 2), "", tagstr);
+
+      if (unlikely (dwarf_attrlist (dies[level], &attrs, &nattrs, &err)
+                   == DW_DLV_ERROR))
+       {
+         error (0, 0, gettext ("cannot get attributes of DIE: %s"),
+                dwarf_errmsg (err));
+         return;
+       }
+
+      for (cnt = 0; cnt < nattrs; ++cnt)
+       {
+         Dwarf_Half attr;
+         Dwarf_Half form;
+
+         if (unlikely (dwarf_whatattr (attrs[cnt], &attr, &err) != DW_DLV_OK))
+           {
+             error (0, 0, gettext ("cannot get attribute code: %s"),
+                    dwarf_errmsg (err));
+             return;
+           }
+
+         if (unlikely (dwarf_whatform (attrs[cnt], &form, &err) != DW_DLV_OK))
+           {
+             error (0, 0, gettext ("cannot get attribute form: %s"),
+                    dwarf_errmsg (err));
+             return;
+           }
+
+         switch (form)
+           {
+           case DW_FORM_addr:;
+           { Dwarf_Addr addr;
+             if (unlikely (dwarf_formaddr (attrs[cnt], &addr, &err)
+                           != DW_DLV_OK))
+               {
+               attrval_out:
+                 error (0, 0, gettext ("cannot get attribute value: %s"),
+                        dwarf_errmsg (err));
+                 return;
+               }
+             printf ("           %*s%-20s %#0*" PRIxMAX "\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr),
+                     (int) (addrsize * 2), (uintmax_t) addr);
+           } break;
+
+           case DW_FORM_indirect:
+           case DW_FORM_strp:
+           case DW_FORM_string:;
+           { char *str;
+             if (unlikely (dwarf_formstring (attrs[cnt], &str, &err)
+                           != DW_DLV_OK))
+               goto attrval_out;
+             printf ("           %*s%-20s \"%s\"\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr), str);
+           } break;
+
+           case DW_FORM_ref_addr:
+           case DW_FORM_ref_udata:
+           case DW_FORM_ref8:
+           case DW_FORM_ref4:
+           case DW_FORM_ref2:
+           case DW_FORM_ref1:;
+           { Dwarf_Off ref;
+             if (unlikely (dwarf_formref (attrs[cnt], &ref, &err)
+                           != DW_DLV_OK))
+               goto attrval_out;
+
+             printf ("           %*s%-20s [%6" PRIxMAX "]\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr),
+                     (uintmax_t) (ref + cu_offset));
+           } break;
+
+           case DW_FORM_udata:
+           case DW_FORM_sdata:
+           case DW_FORM_data8:
+           case DW_FORM_data4:
+           case DW_FORM_data2:
+           case DW_FORM_data1:;
+           { Dwarf_Unsigned num;
+             if (unlikely (dwarf_formudata (attrs[cnt], &num, &err)
+                           != DW_DLV_OK))
+               goto attrval_out;
+
+             if (attr == DW_AT_language)
+               {
+
+                 printf ("           %*s%-20s %s (%d)\n",
+                         (int) (level * 2), "", dwarf_attr_string (attr),
+                         dwarf_lang_string (num), (int) num);
+                 break;
+               }
+
+             printf ("           %*s%-20s %" PRIuMAX "\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr),
+                     (uintmax_t) num);
+           } break;
+
+           case DW_FORM_flag:;
+           { Dwarf_Bool flag;
+             if (unlikely (dwarf_formflag (attrs[cnt], &flag, &err)
+                           != DW_DLV_OK))
+               goto attrval_out;
+
+             printf ("           %*s%-20s %s\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr),
+                     nl_langinfo (flag ? YESSTR : NOSTR));
+           } break;
+
+           case DW_FORM_block4:
+           case DW_FORM_block2:
+           case DW_FORM_block1:
+           case DW_FORM_block:;
+           { Dwarf_Block *block;
+             if (unlikely (dwarf_formblock (attrs[cnt], &block, &err)
+                           != DW_DLV_OK))
+               goto attrval_out;
+
+             printf ("           %*s%-20s %" PRIxMAX " byte block\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr),
+                     (uintmax_t) block->bl_len);
+
+             if (attr == DW_AT_data_member_location)
+               print_ops (dbg, level, addrsize, block->bl_len,
+                          block->bl_data);
+
+             dwarf_dealloc (dbg, block, DW_DLA_BLOCK);
+           } break;
+
+           default:
+             printf ("           %*s%-20s [form: %d] ???\n",
+                     (int) (level * 2), "", dwarf_attr_string (attr),
+                     (int) form);
+             break;
+           }
+
+
+         /* We don't free the attribute since we got passed a
+            reference to the internal object.  */
+       }
+
+      dwarf_dealloc (dbg, attrs, DW_DLA_LIST);
+
+
+      ret = dwarf_child (dies[level], &child, &err);
+      if (ret == DW_DLV_NO_ENTRY)
+       {
+         Dwarf_Die old = dies[level];
+
+         while ((ret = dwarf_siblingof (dbg, dies[level], &dies[level], &err))
+                == DW_DLV_NO_ENTRY)
+           {
+             if (level-- == 0)
+               break;
+
+             dwarf_dealloc (dbg, old, DW_DLA_DIE);
+
+             old = dies[level];
+           }
+
+         dwarf_dealloc (dbg, old, DW_DLA_DIE);
+
+         if (ret == DW_DLV_ERROR)
+           {
+             error (0, 0, gettext ("cannot get next DIE: %s\n"),
+                    dwarf_errmsg (err));
+             return;
+           }
+       }
+      else if (unlikely (ret != DW_DLV_OK))
+       {
+         error (0, 0, gettext ("cannot get next DIE: %s"),
+                dwarf_errmsg (err));
+         return;
+       }
+      else
+       {
+         if (level + 1 == maxdies)
+           dies = (Dwarf_Die *) xrealloc (dies,
+                                          (maxdies += 10)
+                                          * sizeof (Dwarf_Die));
+
+         dies[++level] = child;
+       }
+    }
+  while (level >= 0);
+
+  offset = nextcu;
+  if (offset != 0)
+     goto next_cu;
+
+  free (dies);
 }
 
 
 static void
-print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                         Dwarf_Debug dbg)
+print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                         GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
   printf (gettext ("\
 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
@@ -2905,8 +3622,8 @@ print_debug_line_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
 
 
 static void
-print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                        Dwarf_Debug dbg)
+print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                        GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
   printf (gettext ("\
 \nDWARF section '%s' at offset %#" PRIx64 ":\n"),
@@ -2916,8 +3633,8 @@ print_debug_loc_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
 
 /* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
 static void
-print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                             Dwarf_Debug dbg)
+print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                             GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
   Dwarf_Global *globals;
   Dwarf_Global *runp;
@@ -2962,8 +3679,8 @@ print_debug_pubnames_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
 
 /* Print the content of the DWARF string section '.debug_str'.  */
 static void
-print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr,
-                        Dwarf_Debug dbg)
+print_debug_str_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+                        GElf_Shdr *shdr, Dwarf_Debug dbg)
 {
   int res;
   Dwarf_Off offset = 0;
@@ -2996,7 +3713,7 @@ print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
   Dwarf_Debug dbg;
   Dwarf_Error err;
   Elf_Scn *scn;
-  uint32_t shstrndx;
+  size_t shstrndx;
 
   /* Before we start the real work get a debug context descriptor.  */
   if (dwarf_elf_init (ebl->elf, DW_DLC_READ, NULL, NULL, &dbg, &err)
@@ -3025,7 +3742,8 @@ print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
          {
            const char *name;
            enum section_e bitmask;
-           void (*fp) (Ebl *, GElf_Ehdr *, GElf_Shdr *, Dwarf_Debug);
+           void (*fp) (Ebl *, GElf_Ehdr *, Elf_Scn *, GElf_Shdr *,
+                       Dwarf_Debug);
          } debug_sections[] =
            {
 #define NEW_SECTION(name) \
@@ -3050,9 +3768,112 @@ print_debug (Ebl *ebl, GElf_Ehdr *ehdr)
            if (strcmp (name, debug_sections[n].name) == 0)
              {
                if (print_debug_sections & debug_sections[n].bitmask)
-                 debug_sections[n].fp (ebl, ehdr, shdr, dbg);
+                 debug_sections[n].fp (ebl, ehdr, scn, shdr, dbg);
                break;
              }
        }
     }
 }
+
+
+static void
+handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  int class = gelf_getclass (ebl->elf);
+  size_t cnt;
+
+  /* We have to look through the program header to find the note
+     sections.  There can be more than one.  */
+  for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+    {
+      GElf_Phdr mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
+      char *notemem;
+      size_t align;
+      size_t idx;
+
+      if (phdr == NULL || phdr->p_type != PT_NOTE)
+       /* Not what we are looking for.  */
+       continue;
+
+      printf (gettext ("\
+\nNote segment of %" PRId64 " bytes at offset %#0*" PRIx64 ":\n"),
+             phdr->p_filesz, class == ELFCLASS32 ? 10 : 18, phdr->p_offset);
+
+      notemem = gelf_rawchunk (ebl->elf, phdr->p_offset, phdr->p_filesz);
+      if (notemem == NULL)
+       error (EXIT_FAILURE, 0,
+              gettext ("cannot get content of note section: %s"),
+              elf_errmsg (-1));
+
+      fputs_unlocked (gettext ("  Owner          Data size  Type\n"), stdout);
+
+
+      /* Handle the note section content.  It consists of one or more
+        entries each of which consists of five parts:
+
+        - a 32-bit name length
+        - a 32-bit descriptor length
+        - a 32-bit type field
+        - the NUL-terminated name, length as specified in the first field
+        - the descriptor, length as specified in the second field
+
+        The variable sized fields are padded to 32- or 64-bits
+        depending on whether the file is a 32- or 64-bit ELF file.
+      */
+      align = class == ELFCLASS32 ? 4 : 8;
+#define ALIGNED_LEN(len) (((len) + align - 1) & ~(align - 1))
+
+      idx = 0;
+      while (idx < phdr->p_filesz)
+       {
+         /* XXX Handle 64-bit note section entries correctly.  */
+         struct
+         {
+           uint32_t namesz;
+           uint32_t descsz;
+           uint32_t type;
+           char name[0];
+         } *noteentry = (__typeof (noteentry)) (notemem + idx);
+         char buf[100];
+         char buf2[100];
+
+         if (idx + 12 > phdr->p_filesz
+             || (idx + 12 + ALIGNED_LEN (noteentry->namesz)
+                 + ALIGNED_LEN (noteentry->descsz) > phdr->p_filesz))
+           /* This entry isn't completely contained in the note
+              section.  Ignore it.  */
+           break;
+
+         printf (gettext ("  %-13.*s  %9" PRId32 "  %s\n"),
+                 (int) noteentry->namesz, noteentry->name,
+                 noteentry->descsz,
+                 ehdr->e_type == ET_CORE
+                 ? ebl_core_note_type_name (ebl, noteentry->type,
+                                            buf, sizeof (buf))
+                 : ebl_object_note_type_name (ebl, noteentry->type,
+                                              buf2, sizeof (buf2)));
+
+         /* Filter out invalid entries.  */
+         if (memchr (noteentry->name, '\0', noteentry->namesz) != NULL
+             /* XXX For now help broken Linux kernels.  */
+             || 1)
+           {
+             if (ehdr->e_type == ET_CORE)
+               ebl_core_note (ebl, noteentry->name, noteentry->type,
+                              noteentry->descsz,
+                              &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
+             else
+               ebl_object_note (ebl, noteentry->name, noteentry->type,
+                                noteentry->descsz,
+                                &noteentry->name[ALIGNED_LEN (noteentry->namesz)]);
+           }
+
+         /* Move to the next entry.  */
+         idx += (12 + ALIGNED_LEN (noteentry->namesz)
+                 + ALIGNED_LEN (noteentry->descsz));
+       }
+
+      gelf_freechunk (ebl->elf, notemem);
+    }
+}
index 765d2ac..faf9376 100644 (file)
@@ -1,19 +1,16 @@
 /* Discard section not used at runtime from object files.
-   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   Copyright (C) 2000, 2001, 2002, 2003 Red Hat, Inc.
    Written by Ulrich Drepper <drepper@redhat.com>, 2000.
 
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License version 2 as
-   published by the Free Software Foundation.
+   This program is Open Source software; you can redistribute it and/or
+   modify it under the terms of the Open Software License version 1.0 as
+   published by the Open Source Initiative.
 
-   This program 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, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the Open Software License along
+   with this program; if not, you may obtain a copy of the Open Software
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
+   by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+   3001 King Ranch Road, Ukiah, CA 95482.   */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
@@ -21,6 +18,7 @@
 
 #include <argp.h>
 #include <assert.h>
+#include <byteswap.h>
 #include <error.h>
 #include <fcntl.h>
 #include <gelf.h>
@@ -28,6 +26,7 @@
 #include <libintl.h>
 #include <locale.h>
 #include <mcheck.h>
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdio_ext.h>
 #include <stdlib.h>
@@ -48,14 +47,24 @@ void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
 
 /* Values for the parameters which have no short form.  */
 #define OPT_REMOVE_COMMENT     0x100
+#define OPT_PERMISSIVE         0x101
 
 
 /* Definitions of arguments for argp functions.  */
 static const struct argp_option options[] =
 {
+  { NULL, 0, NULL, 0, N_("Output selection:") },
   { NULL, 'o', "FILE", 0, N_("Place stripped output into FILE") },
-  { "preserve-dates", 'p', NULL, 0, N_("Copy modified/access timestamps to the output") },
-  { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0, N_("Remove .comment section") },
+  { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE") },
+
+  { NULL, 0, NULL, 0, N_("Output options:") },
+  { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols") },
+  { "preserve-dates", 'p', NULL, 0,
+    N_("Copy modified/access timestamps to the output") },
+  { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
+    N_("Remove .comment section") },
+  { "permissive", OPT_PERMISSIVE, NULL, 0,
+    N_("Relax a few rules to handle slightly broken ELF files") },
   { NULL, 0, NULL, 0, NULL }
 };
 
@@ -93,11 +102,20 @@ static int handle_elf (int fd, Elf *elf, const char *prefix,
 /* Name of the output file.  */
 static const char *output_fname;
 
-/* If nonzero output files shall have same date as the input file.  */
-static int preserve_dates;
+/* Name of the debug output file.  */
+static const char *debug_fname;
+
+/* If true output files shall have same date as the input file.  */
+static bool preserve_dates;
+
+/* If true .comment sections will be removed.  */
+static bool remove_comment;
+
+/* If true remove all debug sections.  */
+static bool remove_debug;
 
-/* If nonzero .comment sections will be removed.  */
-static int remove_comment;
+/* If true relax some ELF rules for input files.  */
+static bool permissive;
 
 
 int
@@ -134,11 +152,12 @@ main (int argc, char *argv[])
     result = process_file ("a.out");
   else
     {
-      /* If we have seen the `-o' option there must be exactly one
+      /* If we have seen the `-o' or '-f' option there must be exactly one
         input file.  */
-      if (output_fname != NULL && remaining + 1 < argc)
-       error (EXIT_FAILURE, 0,
-              gettext ("Only one input file allowed together with `-o'"));
+      if ((output_fname != NULL || debug_fname != NULL)
+         && remaining + 1 < argc)
+       error (EXIT_FAILURE, 0, gettext ("\
+Only one input file allowed together with '-o' and '-f'"));
 
       /* Process all the remaining files.  */
       do
@@ -159,7 +178,7 @@ print_version (FILE *stream, struct argp_state *state)
 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\
-"), "2001");
+"), "2003");
   fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
 }
 
@@ -170,16 +189,28 @@ parse_opt (int key, char *arg, struct argp_state *state)
 {
   switch (key)
     {
+    case 'f':
+      debug_fname = arg;
+      break;
+
     case 'o':
       output_fname = arg;
       break;
 
     case 'p':
-      preserve_dates = 1;
+      preserve_dates = true;
       break;
 
     case OPT_REMOVE_COMMENT:
-      remove_comment = 1;
+      remove_comment = true;
+      break;
+
+    case 'g':
+      remove_debug = true;
+      break;
+
+    case OPT_PERMISSIVE:
+      permissive = true;
       break;
 
     default:
@@ -275,6 +306,31 @@ cannot set access and modification date of \"%s\""),
 }
 
 
+/* Maximum size of array allocated on stack.  */
+#define MAX_STACK_ALLOC        (400 * 1024)
+
+
+static uint32_t
+crc32_file (const char *filename)
+{
+  char buffer[1024 * 8];
+  uint32_t crc = 0;
+  ssize_t count;
+  int fd;
+
+  fd = open (filename, O_RDONLY);
+  if (fd < 0)
+    return 0;
+
+  while ((count = TEMP_FAILURE_RETRY (read (fd, buffer, sizeof (buffer)))) > 0)
+    crc = crc32 (crc, buffer, count);
+
+  close (fd);
+
+  return crc;
+}
+
+
 static int
 handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
            mode_t mode)
@@ -284,27 +340,42 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
   char fullname[prefix_len + 1 + fname_len];
   char *cp = fullname;
   Elf *newelf;
+  Elf *debugelf = NULL;
   int result = 0;
   GElf_Ehdr ehdr_mem;
   GElf_Ehdr *ehdr;
-  uint32_t shstrndx;
+  size_t shstrndx;
   size_t shnum;
-  GElf_Ehdr newehdr_mem;
-  GElf_Ehdr *newehdr;
   struct shdr_info
   {
     Elf_Scn *scn;
     GElf_Shdr shdr;
     Elf_Data *data;
     const char *name;
-    GElf_Section idx;          /* Index in new file.  */
+    Elf32_Word idx;            /* Index in new file.  */
+    Elf_Scn *newscn;
+    size_t symtab_idx;
+    size_t version_idx;
+    size_t group_idx;
+    size_t group_cnt;
     struct Ebl_Strent *se;
-  } *shdr_info;
-  struct Ebl_Strtab *shst;
+  } *shdr_info = NULL;
   Elf_Scn *scn;
-  int changes;
   size_t cnt;
   size_t idx;
+  bool changes;
+  GElf_Ehdr newehdr_mem;
+  GElf_Ehdr *newehdr;
+  GElf_Ehdr debugehdr_mem;
+  GElf_Ehdr *debugehdr;
+  struct Ebl_Strtab *shst;
+  uint32_t debug_crc;
+  size_t shdridx;
+  Ebl *ebl;
+  int debug_fd = -1;
+  Elf_Data *shstrtab_data;
+  GElf_Off lastoffset;
+  size_t offsize;
 
   /* Create the full name of the file.  */
   if (prefix != NULL)
@@ -318,20 +389,46 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
   if (output_fname != NULL)
     {
       fd = open (output_fname, O_RDWR | O_CREAT, mode);
-      if (fd == -1)
+      if (unlikely (fd == -1))
        {
          error (0, errno, gettext ("cannot open `%s'"), output_fname);
          return 1;
        }
     }
 
+  /* Get the EBL handling.  The -g option is currently the only reason
+     we need EBL so dont open the backend unless necessary.  */
+  ebl = NULL;
+  if (remove_debug)
+    {
+      ebl = ebl_openbackend (elf);
+      if (ebl == NULL)
+       {
+         error (0, errno, gettext ("cannot open EBL backend"));
+         result = 1;
+         goto fail;
+       }
+    }
+
+  /* Open the additional file the debug information will be stored in.  */
+  if (debug_fname != NULL)
+    {
+      debug_fd = open (debug_fname, O_RDWR | O_CREAT, mode);
+      if (unlikely (debug_fd == -1))
+       {
+         error (0, errno, gettext ("cannot open `%s'"), debug_fname);
+         result = 1;
+         goto fail;
+       }
+    }
+
   /* Get the information from the old file.  */
   ehdr = gelf_getehdr (elf, &ehdr_mem);
   if (ehdr == NULL)
     INTERNAL_ERROR (fname);
 
   /* Get the section header string table index.  */
-  if (elf_getshstrndx (elf, &shstrndx) < 0)
+  if (unlikely (elf_getshstrndx (elf, &shstrndx) < 0))
     error (EXIT_FAILURE, 0,
           gettext ("cannot get section header string table index"));
 
@@ -360,26 +457,64 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
          INTERNAL_ERROR (fname);
       }
 
+  if (debug_fname != NULL)
+    {
+      /* Also create an ELF descriptor for the debug file */
+      debugelf = elf_begin (debug_fd, ELF_C_WRITE_MMAP, NULL);
+      if (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0
+         || (ehdr->e_type != ET_REL
+             && gelf_newphdr (debugelf, ehdr->e_phnum) == 0))
+       {
+         error (0, 0, gettext ("cannot create new file `%s': %s"),
+                debug_fname, elf_errmsg (-1));
+         goto fail_close;
+       }
+
+      /* Copy over the old program header if needed.  */
+      if (ehdr->e_type != ET_REL)
+       for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+         {
+           GElf_Phdr phdr_mem;
+           GElf_Phdr *phdr;
+
+           phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+           if (phdr == NULL
+               || gelf_update_phdr (debugelf, cnt, phdr) == 0)
+             INTERNAL_ERROR (fname);
+         }
+    }
+
   /* Number of sections.  */
   if (elf_getshnum (elf, &shnum) < 0)
     {
       error (0, 0, gettext ("cannot determine number of sections: %s"),
             elf_errmsg (-1));
-      goto fail;
+      goto fail_close;
     }
 
-  /* Storage for section information.  We leave room for one more
-     entry since we unconditionally create a section header string
-     table.  Maybe some weird tool created an ELF file without one.  */
-  shdr_info = (struct shdr_info *) alloca ((shnum + 1)
-                                          * sizeof (struct shdr_info));
-  memset (shdr_info, '\0', (shnum + 1) * sizeof (struct shdr_info));
+  /* Storage for section information.  We leave room for two more
+     entries since we unconditionally create a section header string
+     table.  Maybe some weird tool created an ELF file without one.
+     The other one is used for the debug link section.  */
+  if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
+    shdr_info = (struct shdr_info *) xcalloc (shnum + 2,
+                                             sizeof (struct shdr_info));
+  else
+    {
+      shdr_info = (struct shdr_info *) alloca ((shnum + 2)
+                                              * sizeof (struct shdr_info));
+      memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
+    }
 
   /* Prepare section information data structure.  */
   scn = NULL;
   cnt = 1;
   while ((scn = elf_nextscn (elf, scn)) != NULL)
     {
+      /* This should always be true (i.e., there should not be any
+        holes in the numbering).  */
+      assert (elf_ndxscn (scn) == cnt);
+
       shdr_info[cnt].scn = scn;
 
       /* Get the header.  */
@@ -398,6 +533,65 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
       /* Mark them as present but not yet investigated.  */
       shdr_info[cnt].idx = 1;
 
+      /* Sections in files other than relocatable object files which
+        are not loaded can be freely moved by us.  In relocatable
+        object files everything can be moved.  */
+      if (ehdr->e_type == ET_REL
+         || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
+       shdr_info[cnt].shdr.sh_offset = 0;
+
+      /* If this is an extended section index table store an
+        appropriate reference.  */
+      if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
+       {
+         assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
+         shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
+       }
+      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
+       {
+         Elf32_Word *grpref;
+         size_t inner;
+
+         /* Cross-reference the sections contained in the section
+            group.  */
+         shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
+         if (shdr_info[cnt].data == NULL)
+           INTERNAL_ERROR (fname);
+
+         /* XXX Fix for unaligned access.  */
+         grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
+         for (inner = 1;
+              inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
+              ++inner)
+           shdr_info[grpref[inner]].group_idx = cnt;
+
+         if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
+           /* If the section group contains only one element and this
+              is n COMDAT section we can drop it right away.  */
+           shdr_info[cnt].idx = 0;
+         else
+           shdr_info[cnt].group_cnt = inner - 1;
+       }
+      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
+       {
+         assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
+         shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
+       }
+
+      /* If this section is part of a group make sure it is not
+        discarded right away.  */
+      if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
+       {
+         assert (shdr_info[cnt].group_idx != 0);
+
+         if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
+           {
+             /* The section group section will be removed.  */
+             shdr_info[cnt].group_idx = 0;
+             shdr_info[cnt].shdr.sh_flags &= ~SHF_GROUP;
+           }
+       }
+
       /* Increment the counter.  */
       ++cnt;
     }
@@ -409,112 +603,146 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
      - special sections named ".comment" and ".note" are kept
      - OS or architecture specific sections are kept since we might not
        know how to handle them
-     - section groups must be observed.  If any section of a section
-       is not removed the entire group is not removed
      - if a section is referred to from a section which is not removed
        in the sh_link or sh_info element it cannot be removed either
   */
   for (cnt = 1; cnt < shnum; ++cnt)
-#if 1
     /* Check whether the section can be removed.  */
-    if (SECTION_STRIP_P (&shdr_info[cnt].shdr, shdr_info[cnt].name,
-                        remove_comment))
-      /* For now assume this section will be removed.  */
-      shdr_info[cnt].idx = 0;
-#else
-    if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
+    if (SECTION_STRIP_P (ebl, elf, ehdr, &shdr_info[cnt].shdr,
+                        shdr_info[cnt].name, remove_comment, remove_debug))
       {
-       /* We are never removing the .note section(s).  */
-       if (shdr_info[cnt].shdr.sh_type == SHT_NOTE)
-         continue;
-
-       /* We are removing the .comment section(s) only if explicitly
-           told so.  */
-       if (shdr_info[cnt].shdr.sh_type == SHT_PROGBITS
-           && ! remove_comment
-           && strcmp (shdr_info[cnt].name, ".comment") == 0)
-         continue;
-
-       /* Don't remove non-standard sections.
-          XXX Once we handle the non-standard sections this can be
-          extended .  */
-       if (shdr_info[cnt].shdr.sh_type >= SHT_NUM)
-         continue;
-
        /* For now assume this section will be removed.  */
        shdr_info[cnt].idx = 0;
+
+       idx = shdr_info[cnt].group_idx;
+       while (idx != 0)
+         {
+           /* If the references section group is a normal section
+              group and has one element remaining, or if it is an
+              empty COMDAT section group it is removed.  */
+           bool is_comdat;
+
+           /* The section group data is already loaded.  */
+           assert (shdr_info[idx].data != NULL);
+
+           is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
+                        & GRP_COMDAT) != 0;
+
+           --shdr_info[idx].group_cnt;
+           if ((!is_comdat && shdr_info[idx].group_cnt == 1)
+               || (is_comdat && shdr_info[idx].group_cnt == 0))
+             {
+               shdr_info[idx].idx = 0;
+               /* Continue recursively.  */
+               idx = shdr_info[idx].group_idx;
+             }
+           else
+             break;
+         }
       }
-#endif
 
   /* Mark the SHT_NULL section as handled.  */
   shdr_info[0].idx = 2;
 
+
   /* Handle exceptions: section groups and cross-references.  We might
      have to repeat this a few times since the resetting of the flag
      might propagate.  */
   do
     {
-      changes = 0;
+      changes = false;
 
       for (cnt = 1; cnt < shnum; ++cnt)
-       if (shdr_info[cnt].idx == 1)
-         {
-           /* The content of symbol tables we don't remove must not
-              reference any section which we do remove.  Otherwise
-              we cannot remove the section.  */
-           if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
-               || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
-             {
-               size_t elsize;
-               size_t inner;
+       {
+         if (shdr_info[cnt].idx == 0)
+           {
+             /* If a relocation section is marked as being removed make
+                sure the section it is relocating is removed, too.  */
+             if ((shdr_info[cnt].shdr.sh_type == SHT_REL
+                  || shdr_info[cnt].shdr.sh_type == SHT_RELA)
+                 && shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
+               shdr_info[cnt].idx = 1;
+           }
 
-               /* Make sure the data is loaded.  */
-               if (shdr_info[cnt].data == NULL)
-                 {
-                   shdr_info[cnt].data =
-                     elf_getdata (shdr_info[cnt].scn, NULL);
-                   if (shdr_info[cnt].data == NULL)
-                     INTERNAL_ERROR (fname);
-                 }
+         if (shdr_info[cnt].idx == 1)
+           {
+             /* The content of symbol tables we don't remove must not
+                reference any section which we do remove.  Otherwise
+                we cannot remove the section.  */
+             if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
+                 || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
+               {
+                 Elf_Data *symdata;
+                 Elf_Data *xndxdata;
+                 size_t elsize;
+                 size_t inner;
 
-               /* Go through all symbols and make sure the section they
-                  reference is not removed.  */
-               elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
+                 /* Make sure the data is loaded.  */
+                 if (shdr_info[cnt].data == NULL)
+                   {
+                     shdr_info[cnt].data
+                       = elf_getdata (shdr_info[cnt].scn, NULL);
+                     if (shdr_info[cnt].data == NULL)
+                       INTERNAL_ERROR (fname);
+                   }
+                 symdata = shdr_info[cnt].data;
 
-               for (inner = 0;
-                    inner < shdr_info[cnt].data->d_size / elsize;
-                    ++inner)
-                 {
-                   GElf_Section scnidx;
-                   GElf_Sym sym_mem;
-                   GElf_Sym *sym = gelf_getsym (shdr_info[cnt].data, inner,
-                                                &sym_mem);
-                   if (sym == NULL)
-                     INTERNAL_ERROR (fname);
+                 /* If there is an extended section index table load it
+                    as well.  */
+                 if (shdr_info[cnt].symtab_idx != 0
+                     && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
+                   {
+                     assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
 
-                   scnidx = sym->st_shndx;
-                   if (scnidx == SHN_UNDEF || scnidx >= shnum)
-                     /* This is no section index, leave it alone.  */
-                     continue;
+                     shdr_info[shdr_info[cnt].symtab_idx].data
+                       = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
+                                      NULL);
+                     if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
+                       INTERNAL_ERROR (fname);
+                   }
+                 xndxdata = shdr_info[shdr_info[cnt].symtab_idx].data;
 
-                   if (shdr_info[scnidx].idx == 0)
-                     {
-                       /* Mark this section and all before it which are
-                          unmarked as used.  */
-                       shdr_info[scnidx].idx = 1;
-                       while (scnidx-- > 1)
-                         if (shdr_info[scnidx].idx == 0)
-                           shdr_info[scnidx].idx = 1;
-                       changes = 1;
-                     }
+                 /* Go through all symbols and make sure the section they
+                    reference is not removed.  */
+                 elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
 
-                   /* XXX We have to decide who to handle the extended
-                      section index table.  Maybe libelf does it itself.  */
-                 }
-             }
+                 for (inner = 0;
+                      inner < shdr_info[cnt].data->d_size / elsize;
+                      ++inner)
+                   {
+                     GElf_Sym sym_mem;
+                     Elf32_Word xndx;
+                     GElf_Sym *sym;
+                     size_t scnidx;
+
+                     sym = gelf_getsymshndx (symdata, xndxdata, inner,
+                                             &sym_mem, &xndx);
+                     if (sym == NULL)
+                       INTERNAL_ERROR (fname);
+
+                     scnidx = sym->st_shndx;
+                     if (scnidx == SHN_UNDEF || scnidx >= shnum
+                         || (scnidx >= SHN_LORESERVE
+                             && scnidx <= SHN_HIRESERVE
+                             && scnidx != SHN_XINDEX)
+                         /* Don't count in the section symbols.  */
+                         || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
+                       /* This is no section index, leave it alone.  */
+                       continue;
+                     else if (scnidx == SHN_XINDEX)
+                       scnidx = xndx;
+
+                     if (shdr_info[scnidx].idx == 0)
+                       {
+                         /* Mark this section as used.  */
+                         shdr_info[scnidx].idx = 1;
+                         changes |= scnidx < cnt;
+                       }
+                   }
+               }
 
-           /* Cross referencing happens:
-              - for the cases the ELF specification says.  That are
+             /* Cross referencing happens:
+                - for the cases the ELF specification says.  That are
                 + SHT_DYNAMIC in sh_link to string table
                 + SHT_HASH in sh_link to symbol table
                 + SHT_REL and SHT_RELA in sh_link to symbol table
@@ -523,129 +751,109 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
                 + SHT_SYMTAB_SHNDX in sh_link to symbol table
                 Other (OS or architecture-specific) sections might as
                 well use this field so we process it unconditionally.
-              - references inside section groups
-              - specially marked references in sh_info if the SHF_INFO_LINK
+                - references inside section groups
+                - specially marked references in sh_info if the SHF_INFO_LINK
                 flag is set
-           */
+             */
 
-           if (shdr_info[shdr_info[cnt].shdr.sh_link].idx != 0)
-             {
-               size_t inner = shdr_info[cnt].shdr.sh_link;
+             if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
+               {
+                 shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
+                 changes |= shdr_info[cnt].shdr.sh_link < cnt;
+               }
 
-               shdr_info[inner].idx = 1;
-               while (inner-- > 1)
-                 if (shdr_info[inner].idx == 0)
-                   shdr_info[inner].idx = 1;
+             /* Handle references through sh_info.  */
+             if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
+                 && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
+               {
+                 shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
+                 changes |= shdr_info[cnt].shdr.sh_info < cnt;
+               }
 
-               changes = 1;
-             }
+             /* Mark the section as investigated.  */
+             shdr_info[cnt].idx = 2;
+           }
+       }
+    }
+  while (changes);
 
-           if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
-             {
-               size_t inner;
-               Elf32_Word *grpref;
+  /* Write out a copy of all the sections to the debug output file.
+     The ones that are not removed in the stripped file are SHT_NOBITS */
+  if (debug_fname != NULL)
+    {
+      for (cnt = 1; cnt < shnum; ++cnt)
+       {
+         Elf_Data *debugdata;
+         GElf_Shdr debugshdr;
+         int discard_section;
 
-               if (shdr_info[cnt].data == NULL)
-                 {
-                   shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn,
-                                                      NULL);
-                   if (shdr_info[cnt].data == NULL)
-                     INTERNAL_ERROR (fname);
-                 }
+         scn = elf_newscn (debugelf);
+         if (scn == NULL)
+           error (EXIT_FAILURE, 0,
+                  gettext ("while generating output file: %s"),
+                  elf_errmsg (-1));
 
-               grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
-               /* The first word of the section is a flag which we can
-                  ignore here.  */
-               for (inner = 1;
-                    inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
-                    ++inner)
-                 if (shdr_info[grpref[inner]].idx == 0)
-                   {
-                     size_t inner2 = grpref[inner];
-
-                     shdr_info[inner2].idx = 1;
-#if 0
-                     /* XXX This isn't correct.  Is it possible to
-                        leave out sections in the middle?  If not we
-                        have to add all sections before the one we
-                        just added as well.  But "before" means in
-                        the address space and not in the section
-                        header table (which is what the current code
-                        does).  */
-                     while (inner2-- > 1)
-                       if (shdr_info[inner2].idx == 0)
-                         shdr_info[inner2].idx = 1;
-#endif
-                     changes = 1;
-                   }
-             }
+         discard_section = shdr_info[cnt].idx > 0 && cnt != ehdr->e_shstrndx;
 
-           /* Handle references through sh_info.  */
-           if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)
-               && shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
-             {
-               size_t inner = shdr_info[cnt].shdr.sh_info;
+         /* Set the section header in the new file.  */
+         debugshdr = shdr_info[cnt].shdr;
+         if (discard_section)
+           debugshdr.sh_type = SHT_NOBITS;
 
-               shdr_info[inner].idx = 1;
-               while (inner-- > 1)
-                 if (shdr_info[inner].idx == 0)
-                   shdr_info[inner].idx = 1;
+         if (unlikely (gelf_update_shdr (scn, &debugshdr)) == 0)
+           /* There cannot be any overflows.  */
+           INTERNAL_ERROR (fname);
 
-               changes = 1;
-             }
+         /* Get the data from the old file if necessary. */
+         if (shdr_info[cnt].data == NULL)
+           {
+             shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
+             if (shdr_info[cnt].data == NULL)
+               INTERNAL_ERROR (fname);
+           }
 
-           /* Mark the section as investigated.  */
-           shdr_info[cnt].idx = 2;
-         }
-       else if (shdr_info[cnt].idx == 0
-                && shdr_info[cnt].shdr.sh_type == SHT_GROUP)
-         {
-           /* If any member of the group isn't removed all of the group
-              stays.  */
-           size_t inner;
-           size_t maxidx = 0;
-           Elf32_Word *grpref;
-           int newval = -1;
+         /* Set the data.  This is done by copying from the old file.  */
+         debugdata = elf_newdata (scn);
+         if (debugdata == NULL)
+           INTERNAL_ERROR (fname);
 
-           if (shdr_info[cnt].data == NULL)
-             {
-               shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
-               if (shdr_info[cnt].data == NULL)
-                 INTERNAL_ERROR (fname);
-             }
+         /* Copy the structure.  */
+         *debugdata = *shdr_info[cnt].data;
+         if (discard_section)
+           debugdata->d_buf = NULL;
+       }
 
-           grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
-           for (inner = 1;
-                inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
-                ++inner)
-             if (shdr_info[grpref[inner]].idx > 0)
-               {
-                 /* The whole group must stay.  Except for debugging
-                    sections and the relocations for those sections.  */
-                 for (inner = 1;
-                      inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
-                      ++inner)
-                   {
-                     shdr_info[grpref[inner]].idx = 1;
-                     maxidx = MAX (maxidx, grpref[inner]);
-                   }
+      /* Finish the ELF header.  Fill in the fields not handled by
+        libelf from the old file.  */
+      debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
+      if (debugehdr == NULL)
+       INTERNAL_ERROR (fname);
 
-                 /* XXX This is wrong.  We must check for file offsets
-                    and not section header table indeces.  */
-                 while (maxidx-- > 1)
-                   if (shdr_info[maxidx].idx == 0)
-                     shdr_info[maxidx].idx = 1;
+      memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
+      debugehdr->e_type = ehdr->e_type;
+      debugehdr->e_machine = ehdr->e_machine;
+      debugehdr->e_version = ehdr->e_version;
+      debugehdr->e_entry = ehdr->e_entry;
+      debugehdr->e_flags = ehdr->e_flags;
+      debugehdr->e_shstrndx = ehdr->e_shstrndx;
 
-                 newval = 2;
-                 changes = 1;
-                 break;
-               }
+      if (unlikely (gelf_update_ehdr (debugelf, debugehdr)) == 0)
+       {
+         error (0, 0, gettext ("%s: error while creating ELF header: %s"),
+                debug_fname, elf_errmsg (-1));
+         goto fail_close;
+       }
 
-           /* Mark section as used or verified to be not used.  */
-           shdr_info[cnt].idx = newval;
-         }
+      /* Finally write the file.  */
+      if (unlikely (elf_update (debugelf, ELF_C_WRITE)) == -1)
+       {
+         error (0, 0, gettext ("while writing `%s': %s"),
+                debug_fname, elf_errmsg (-1));
+         goto fail_close;
+       }
+
+      debug_crc = crc32_file (debug_fname);
     }
-  while (changes);
 
   /* Mark the section header string table as unused, we will create
      a new one.  */
@@ -658,10 +866,19 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
           output_fname ?: fname);
 
   /* Assign new section numbers.  */
+  shdr_info[0].idx = 0;
   for (cnt = idx = 1; cnt < shnum; ++cnt)
     if (shdr_info[cnt].idx > 0)
       {
-       shdr_info[cnt].idx = idx;
+       shdr_info[cnt].idx = idx++;
+
+       /* Create a new section.  */
+       shdr_info[cnt].newscn = elf_newscn (newelf);
+       if (shdr_info[cnt].newscn == NULL)
+         error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
+                elf_errmsg (-1));
+
+       assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
 
        /* Add this name to the section header string table.  */
        shdr_info[cnt].se = ebl_strtabadd (shst, shdr_info[cnt].name, 0);
@@ -672,6 +889,69 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
     /* Nope, all removable sections are already gone.  */
     goto fail_close;
 
+  /* Create the reference to the file with the debug info.  */
+  if (debug_fname != NULL)
+    {
+      char *debug_basename;
+      off_t crc_offset;
+
+      /* Add the section header string table section name.  */
+      shdr_info[cnt].se = ebl_strtabadd (shst, ".gnu_debuglink", 15);
+      shdr_info[cnt].idx = idx++;
+
+      /* Create the section header.  */
+      shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
+      shdr_info[cnt].shdr.sh_flags = 0;
+      shdr_info[cnt].shdr.sh_addr = 0;
+      shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
+      shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
+      shdr_info[cnt].shdr.sh_entsize = 0;
+      shdr_info[cnt].shdr.sh_addralign = 4;
+      /* We set the offset to zero here.  Before we write the ELF file the
+        field must have the correct value.  This is done in the final
+        loop over all section.  Then we have all the information needed.  */
+      shdr_info[cnt].shdr.sh_offset = 0;
+
+      /* Create the section.  */
+      shdr_info[cnt].newscn = elf_newscn (newelf);
+      if (shdr_info[cnt].newscn == NULL)
+       error (EXIT_FAILURE, 0,
+              gettext ("while create section header section: %s"),
+              elf_errmsg (-1));
+      assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
+
+      shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
+      if (shdr_info[cnt].data == NULL)
+       error (EXIT_FAILURE, 0, gettext ("cannot allocate section data: %s"),
+              elf_errmsg (-1));
+
+      debug_basename = basename (debug_fname);
+      crc_offset = strlen (debug_basename) + 1;
+      /* Align to 4 byte boundary */
+      crc_offset = ((crc_offset - 1) & ~3) + 4;
+
+      shdr_info[cnt].data->d_align = 4;
+      shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
+       = crc_offset + 4;
+      shdr_info[cnt].data->d_buf = xcalloc (1, shdr_info[cnt].data->d_size);
+
+      strcpy (shdr_info[cnt].data->d_buf, debug_basename);
+      /* Store the crc value in the correct byteorder */
+      if ((__BYTE_ORDER == __LITTLE_ENDIAN
+          && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+         || (__BYTE_ORDER == __BIG_ENDIAN
+             && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+       debug_crc = bswap_32 (debug_crc);
+      memcpy ((char *)shdr_info[cnt].data->d_buf + crc_offset,
+             (char *) &debug_crc, 4);
+
+      /* One more section done.  */
+      ++cnt;
+    }
+
+  /* Index of the section header table in the shdr_info array.  */
+  shdridx = cnt;
+
   /* Add the section header string table section name.  */
   shdr_info[cnt].se = ebl_strtabadd (shst, ".shstrtab", 10);
   shdr_info[cnt].idx = idx;
@@ -682,37 +962,35 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
   shdr_info[cnt].shdr.sh_addr = 0;
   shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
   shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
-  shdr_info[cnt].shdr.sh_entsize = 1;
-  /* We have to initialize these fields because they might contain
-     values which later get rejected by the `gelf_update_shdr'
-     function.  The values we are using don't matter, they must only
-     be representable.  */
+  shdr_info[cnt].shdr.sh_entsize = 0;
+  /* We set the offset to zero here.  Before we write the ELF file the
+     field must have the correct value.  This is done in the final
+     loop over all section.  Then we have all the information needed.  */
   shdr_info[cnt].shdr.sh_offset = 0;
-  shdr_info[cnt].shdr.sh_size = 0;
-  shdr_info[cnt].shdr.sh_addralign = 0;
+  shdr_info[cnt].shdr.sh_addralign = 1;
 
   /* Create the section.  */
-  for (cnt = 1; cnt <= shnum; ++cnt)
-    if (shdr_info[cnt].idx > 0)
-      {
-       /* Create a new section.  */
-       scn = elf_newscn (newelf);
-       if (scn == NULL)
-         error (EXIT_FAILURE, 0, gettext ("while generating output file: %s"),
-                elf_errmsg (-1));
-
-       assert (elf_ndxscn (scn) == shdr_info[cnt].idx);
-      }
+  shdr_info[cnt].newscn = elf_newscn (newelf);
+  if (shdr_info[cnt].newscn == NULL)
+    error (EXIT_FAILURE, 0,
+          gettext ("while create section header section: %s"),
+          elf_errmsg (-1));
+  assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
 
   /* Finalize the string table and fill in the correct indices in the
      section headers.  */
-  assert (scn == elf_getscn (newelf, idx));
-  ebl_strtabfinalize (shst, elf_newdata (scn));
+  shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
+  ebl_strtabfinalize (shst, shstrtab_data);
+
+  /* We have to set the section size.  */
+  shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
 
   /* Update the section information.  */
-  for (cnt = 1; cnt <= shnum; ++cnt)
+  lastoffset = 0;
+  for (cnt = 1; cnt <= shdridx; ++cnt)
     if (shdr_info[cnt].idx > 0)
       {
+       GElf_Off filesz;
        Elf_Data *newdata;
 
        scn = elf_getscn (newelf, shdr_info[cnt].idx);
@@ -746,11 +1024,6 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
          shdr_info[cnt].shdr.sh_info =
            shdr_info[shdr_info[cnt].shdr.sh_info].idx;
 
-       /* Set the section header in the new file.  */
-       if (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0)
-         /* There cannot be any overflows.  */
-         INTERNAL_ERROR (fname);
-
        /* Get the data from the old file if necessary.  We already
            created the data for the section header string table.  */
        if (cnt < shnum)
@@ -770,6 +1043,9 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
            /* Copy the structure.  */
            *newdata = *shdr_info[cnt].data;
 
+           /* We know the size.  */
+           shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
+
            /* We have to adjust symtol tables.  The st_shndx member might
               have to be updated.  */
            if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
@@ -777,41 +1053,133 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
              {
                size_t elsize;
                size_t inner;
+               Elf_Data *versiondata = NULL;
+               Elf_Data *shndxdata = NULL;
 
                elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
 
-               for (inner = 0;
+               if (shdr_info[cnt].symtab_idx != 0)
+                 {
+                   assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
+                   /* This section has extended section information.
+                      We have to modify that information, too.  */
+                   shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
+                                            NULL);
+
+                   assert ((versiondata->d_size / sizeof (Elf32_Word))
+                           >= shdr_info[cnt].data->d_size / elsize);
+                 }
+
+               if (shdr_info[cnt].version_idx != 0)
+                 {
+                   assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
+                   /* This section has associated version
+                      information.  We have to modify that
+                      information, too.  */
+                   versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
+                                              NULL);
+
+                   assert ((versiondata->d_size / sizeof (GElf_Versym))
+                           >= shdr_info[cnt].data->d_size / elsize);
+                 }
+
+               for (inner = 1;
                     inner < shdr_info[cnt].data->d_size / elsize;
                     ++inner)
                  {
-                   GElf_Section sec;
+                   Elf32_Word sec;
                    GElf_Sym sym_mem;
-                   GElf_Sym *sym = gelf_getsym (shdr_info[cnt].data, inner,
-                                                &sym_mem);
+                   Elf32_Word xshndx;
+                   GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
+                                                     shndxdata, inner,
+                                                     &sym_mem, &xshndx);
                    if (sym == NULL)
                      INTERNAL_ERROR (fname);
 
                    if (sym->st_shndx == SHN_UNDEF
-                       || sym->st_shndx >= shnum)
+                       || (sym->st_shndx >= shnum
+                           && sym->st_shndx != SHN_XINDEX))
                      /* This is no section index, leave it alone.  */
                      continue;
 
-                   sec = shdr_info[sym->st_shndx].idx;
-                   assert (sec != 0);
-                   if (sec != sym->st_shndx)
+                   if (sym->st_shndx != SHN_XINDEX)
+                     sec = shdr_info[sym->st_shndx].idx;
+                   else
+                     {
+                       assert (shndxdata != NULL);
+
+                       sec = shdr_info[xshndx].idx;
+                     }
+
+                   if (sec != 0)
                      {
-                       sym->st_shndx = sec;
-                       if (gelf_update_sym (shdr_info[cnt].data, inner, sym)
-                           == 0)
+                       GElf_Section nshndx;
+                       Elf32_Word nxshndx;
+
+                       if (sec < SHN_LORESERVE)
+                         {
+                           nshndx = sec;
+                           nxshndx = 0;
+                         }
+                       else
+                         {
+                           nshndx = SHN_XINDEX;
+                           nxshndx = sec;
+                         }
+
+                       assert (sec < SHN_LORESERVE || shndxdata != NULL);
+
+                       if ((nshndx != sym->st_shndx
+                            || (shndxdata != NULL && nxshndx != xshndx))
+                           && (sym->st_shndx = nshndx,
+                               gelf_update_symshndx (shdr_info[cnt].data,
+                                                     shndxdata,
+                                                     inner, sym,
+                                                     nxshndx) == 0))
                          INTERNAL_ERROR (fname);
                      }
+                   else
+                     {
+                       assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION);
 
-                   /* XXX We have to update the extended index section
-                      table as well once we decide how to handle it.  Maybe
-                      libelf will do it itself.  */
+                       /* Clear the symbol table entry.  */
+                       memset (&sym_mem, '\0', sizeof (sym_mem));
+                       if (gelf_update_symshndx (shdr_info[cnt].data,
+                                                 shndxdata, inner,
+                                                 &sym_mem, 0) == 0)
+                         INTERNAL_ERROR (fname);
+
+                       if (versiondata != NULL)
+                         {
+                           /* Zero out the version information.  It
+                              should already be zero but who knows.  */
+                           GElf_Versym versym_mem = 0;
+
+                           if (gelf_update_versym (versiondata, inner,
+                                                   &versym_mem) == 0)
+                             INTERNAL_ERROR (fname);
+                         }
+                     }
                  }
              }
          }
+
+       /* If we have to, compute the offset of the section.  */
+       if (shdr_info[cnt].shdr.sh_offset == 0)
+         shdr_info[cnt].shdr.sh_offset
+           = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
+              & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
+
+       /* Set the section header in the new file.  */
+       if (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0)
+         /* There cannot be any overflows.  */
+         INTERNAL_ERROR (fname);
+
+       /* Remember the last section written so far.  */
+       filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
+                          ? shdr_info[cnt].shdr.sh_size : 0);
+       if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
+         lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
       }
 
   /* Finally finish the ELF header.  Fill in the fields not handled by
@@ -826,6 +1194,13 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
   newehdr->e_version = ehdr->e_version;
   newehdr->e_entry = ehdr->e_entry;
   newehdr->e_flags = ehdr->e_flags;
+  newehdr->e_phoff = ehdr->e_phoff;
+  /* We need to position the section header table.  */
+  offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
+  newehdr->e_shoff = ((shdr_info[shdridx].shdr.sh_offset
+                      + shdr_info[shdridx].shdr.sh_size + offsize - 1)
+                     & ~((GElf_Off) (offsize - 1)));
+  newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
 
   /* The new section header string table index.  */
   if (likely (idx < SHN_HIRESERVE) && likely (idx != SHN_XINDEX))
@@ -859,6 +1234,12 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
       return 1;
     }
 
+  /* The ELF library better follows our layout when this is not a
+     relocatable object file.  */
+  elf_flagelf (newelf, ELF_C_SET,
+              (ehdr->e_type != ET_REL ? ELF_F_LAYOUT : 0)
+              | (permissive ? ELF_F_PERMISSIVE : 0));
+
   /* Finally write the file.  */
   if (elf_update (newelf, ELF_C_WRITE) == -1)
     {
@@ -867,8 +1248,13 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
       result = 1;
     }
 
+
  fail_close:
-  /* That was it.  Close the descriptor.  */
+  /* Free the memory.  */
+  if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
+    free (shdr_info);
+
+  /* That was it.  Close the descriptors.  */
   if (elf_end (newelf) != 0)
     {
       error (0, 0, gettext ("error while finishing `%s': %s"), fname,
@@ -876,7 +1262,22 @@ handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
       result = 1;
     }
 
+  if (debugelf != NULL && elf_end (debugelf) != 0)
+    {
+      error (0, 0, gettext ("error while finishing `%s': %s"), debug_fname,
+            elf_errmsg (-1));
+      result = 1;
+    }
+
  fail:
+  /* Close the EBL backend.  */
+  if (ebl != NULL)
+    ebl_closebackend (ebl);
+
+  /* Close debug file descriptor, if opened */
+  if (debug_fd >= 0)
+    close (debug_fd);
+
   /* Close the file descriptor if we created a new file.  */
   if (output_fname != NULL)
     close (fd);
index 15bc71c..ef231d8 100644 (file)
 int
 main (int argc, char *argv[])
 {
+  int infd;
+  Elf *inelf;
+  int outfd;
+  Elf *outelf;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  Elf_Scn *scn = NULL;
+
   if (argc < 3)
     error (EXIT_FAILURE, 0, "usage: %s FROMNAME TONAME", argv[0]);
 
   elf_version (EV_CURRENT);
 
-  int infd = open (argv[1], O_RDONLY);
+  infd = open (argv[1], O_RDONLY);
   if (infd == -1)
     error (EXIT_FAILURE, errno, "cannot open input file '%s'", argv[1]);
 
-  Elf *inelf = elf_begin (infd, ELF_C_READ, NULL);
+  inelf = elf_begin (infd, ELF_C_READ, NULL);
   if (inelf == NULL)
     error (EXIT_FAILURE, 0, "problems opening '%s' as ELF file: %s",
           argv[1], elf_errmsg (-1));
 
-  int outfd = creat (argv[2], 0666);
+  outfd = creat (argv[2], 0666);
   if (outfd == -1)
     error (EXIT_FAILURE, errno, "cannot open output file '%s'", argv[2]);
 
-  Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
+  outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
   if (outelf == NULL)
     error (EXIT_FAILURE, 0, "problems opening '%s' as ELF file: %s",
           argv[2], elf_errmsg (-1));
 
   gelf_newehdr (outelf, gelf_getclass (inelf));
 
-  GElf_Ehdr ehdr_mem;
-  GElf_Ehdr *ehdr;
   gelf_update_ehdr (outelf, (ehdr = gelf_getehdr (inelf, &ehdr_mem)));
 
   if (ehdr->e_phnum > 0)
@@ -66,7 +72,6 @@ main (int argc, char *argv[])
        }
     }
 
-  Elf_Scn *scn = NULL;
   while ((scn = elf_nextscn (inelf, scn)) != NULL)
     {
       Elf_Scn *newscn = elf_newscn (outelf);
index 9aa6451..2fa32ed 100644 (file)
@@ -28,8 +28,11 @@ callback (Dwarf *dbg, Dwarf_Global *gl, void *arg)
          (unsigned long long int) gl->cu_offset);
 
 #if 0
+ {
   Dwarf_Die cu_die;
   const char *cuname;
+  const char *diename;
+
   if (dwarf_offdie (dbg, gl->cu_offset, &cu_die) == NULL
       || (cuname = dwarf_diename (&cu_die)) == NULL)
     {
@@ -42,7 +45,6 @@ callback (Dwarf *dbg, Dwarf_Global *gl, void *arg)
       dwarf_dealloc (dbg, cuname, DW_DLA_STRING);
     }
 
-  const char *diename;
   if (dwarf_offdie (dbg, gl->die_offset, &die) == NULL
       || (diename = dwarf_diename (&die)) == NULL)
     {
@@ -54,6 +56,7 @@ callback (Dwarf *dbg, Dwarf_Global *gl, void *arg)
       printf ("object name: \"%s\"\n", diename);
       dwarf_dealloc (dbg, diename, DW_DLA_STRING);
     }
+ }
 #endif
   return DWARF_CB_OK;
 }
index 58cffe3..6196831 100644 (file)
@@ -6,7 +6,7 @@
 
    You should have received a copy of the Open Software License along
    with this program; if not, you may obtain a copy of the Open Software
-   License version 1.0 from http://www.opensource.org/license/osl.php or
+   License version 1.0 from http://www.opensource.org/licenses/osl.php or
    by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
    3001 King Ranch Road, Ukiah, CA 95482.   */
 
@@ -24,6 +24,7 @@ main (int argc, char *argv[])
   Elf *elf;
   int fd;
   Elf_Scn *section;
+  char name[] = "test.XXXXXX";
 
   if (elf_version (EV_CURRENT) == EV_NONE)
     {
@@ -31,7 +32,6 @@ main (int argc, char *argv[])
       exit (1);
     }
 
-  char name[] = "test.XXXXXX";
   fd = mkstemp (name);
   if (fd < 0)
     {