summaryrefslogtreecommitdiff
path: root/elfutils
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2003-03-06 00:57:54 +0000
committerjbj <devnull@localhost>2003-03-06 00:57:54 +0000
commit29cffe52fca8d5480c333c557996d2bc0196a801 (patch)
tree6f222be8cb18848730bd6a36fd07e37a39785deb /elfutils
parente8cf6cbb056a5b4517191b2a216d48a712993460 (diff)
downloadrpm-29cffe52fca8d5480c333c557996d2bc0196a801.tar.gz
rpm-29cffe52fca8d5480c333c557996d2bc0196a801.tar.bz2
rpm-29cffe52fca8d5480c333c557996d2bc0196a801.zip
Revert c99 syntax in elfutils.
Fiddles to build on Red Hat 7.3. CVS patchset: 6654 CVS date: 2003/03/06 00:57:54
Diffstat (limited to 'elfutils')
-rw-r--r--elfutils/libasm/asm_addint8.c29
-rw-r--r--elfutils/libasm/asm_addsleb128.c22
-rw-r--r--elfutils/libasm/asm_adduleb128.c22
-rw-r--r--elfutils/libasm/asm_align.c44
-rw-r--r--elfutils/libasm/asm_end.c142
-rw-r--r--elfutils/libdw/dwarf_begin_elf.c18
-rw-r--r--elfutils/libdw/dwarf_get_pubnames.c28
-rw-r--r--elfutils/libebl/eblcorenote.c24
-rw-r--r--elfutils/libebl/eblobjnote.c21
-rw-r--r--elfutils/libebl/eblopenbackend.c246
-rw-r--r--elfutils/libebl/i386_corenote.c44
-rw-r--r--elfutils/po/elfutils.pot198
-rw-r--r--elfutils/src/elflint.c515
-rw-r--r--elfutils/src/nm.c484
-rw-r--r--elfutils/src/readelf.c1103
-rw-r--r--elfutils/src/strip.c937
-rw-r--r--elfutils/tests/ecp.c19
-rw-r--r--elfutils/tests/get-pubnames2.c5
-rw-r--r--elfutils/tests/newscn.c4
19 files changed, 3042 insertions, 863 deletions
diff --git a/elfutils/libasm/asm_addint8.c b/elfutils/libasm/asm_addint8.c
index b089d1cc0..677d484ce 100644
--- a/elfutils/libasm/asm_addint8.c
+++ b/elfutils/libasm/asm_addint8.c
@@ -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>
@@ -37,11 +34,13 @@
#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;
diff --git a/elfutils/libasm/asm_addsleb128.c b/elfutils/libasm/asm_addsleb128.c
index e517202c7..f02a2a7ec 100644
--- a/elfutils/libasm/asm_addsleb128.c
+++ b/elfutils/libasm/asm_addsleb128.c
@@ -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)
diff --git a/elfutils/libasm/asm_adduleb128.c b/elfutils/libasm/asm_adduleb128.c
index d7923b44c..8fb1ac595 100644
--- a/elfutils/libasm/asm_adduleb128.c
+++ b/elfutils/libasm/asm_adduleb128.c
@@ -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)
diff --git a/elfutils/libasm/asm_align.c b/elfutils/libasm/asm_align.c
index eb6db67ef..c19996621 100644
--- a/elfutils/libasm/asm_align.c
+++ b/elfutils/libasm/asm_align.c
@@ -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;
}
diff --git a/elfutils/libasm/asm_end.c b/elfutils/libasm/asm_end.c
index 3f1085620..39bc6b2bb 100644
--- a/elfutils/libasm/asm_end.c
+++ b/elfutils/libasm/asm_end.c
@@ -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);
diff --git a/elfutils/libdw/dwarf_begin_elf.c b/elfutils/libdw/dwarf_begin_elf.c
index 7523aa23a..aaa0c1dac 100644
--- a/elfutils/libdw/dwarf_begin_elf.c
+++ b/elfutils/libdw/dwarf_begin_elf.c
@@ -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;
}
diff --git a/elfutils/libdw/dwarf_get_pubnames.c b/elfutils/libdw/dwarf_get_pubnames.c
index 022e06de3..1bbcdadea 100644
--- a/elfutils/libdw/dwarf_get_pubnames.c
+++ b/elfutils/libdw/dwarf_get_pubnames.c
@@ -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;
diff --git a/elfutils/libebl/eblcorenote.c b/elfutils/libebl/eblcorenote.c
index 54b68f727..5a246d27e 100644
--- a/elfutils/libebl/eblcorenote.c
+++ b/elfutils/libebl/eblcorenote.c
@@ -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:
diff --git a/elfutils/libebl/eblobjnote.c b/elfutils/libebl/eblobjnote.c
index 816dd7443..87aadb753 100644
--- a/elfutils/libebl/eblobjnote.c
+++ b/elfutils/libebl/eblobjnote.c
@@ -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)
diff --git a/elfutils/libebl/eblopenbackend.c b/elfutils/libebl/eblopenbackend.c
index be899db6c..ef195057f 100644
--- a/elfutils/libebl/eblopenbackend.c
+++ b/elfutils/libebl/eblopenbackend.c
@@ -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;
+}
diff --git a/elfutils/libebl/i386_corenote.c b/elfutils/libebl/i386_corenote.c
index 55464057b..08de2821a 100644
--- a/elfutils/libebl/i386_corenote.c
+++ b/elfutils/libebl/i386_corenote.c
@@ -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;
diff --git a/elfutils/po/elfutils.pot b/elfutils/po/elfutils.pot
index eb2c1da91..f330eaa7b 100644
--- a/elfutils/po/elfutils.pot
+++ b/elfutils/po/elfutils.pot
@@ -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 ""
diff --git a/elfutils/src/elflint.c b/elfutils/src/elflint.c
index 09b0007a5..1f0e222d6 100644
--- a/elfutils/src/elflint.c
+++ b/elfutils/src/elflint.c
@@ -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);
}
diff --git a/elfutils/src/nm.c b/elfutils/src/nm.c
index 6e35028f7..069f408b4 100644
--- a/elfutils/src/nm.c
+++ b/elfutils/src/nm.c
@@ -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.
diff --git a/elfutils/src/readelf.c b/elfutils/src/readelf.c
index 5e2a5d66a..a7fe87e83 100644
--- a/elfutils/src/readelf.c
+++ b/elfutils/src/readelf.c
@@ -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);
+ }
+}
diff --git a/elfutils/src/strip.c b/elfutils/src/strip.c
index 765d2ace0..faf937625 100644
--- a/elfutils/src/strip.c
+++ b/elfutils/src/strip.c
@@ -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);
diff --git a/elfutils/tests/ecp.c b/elfutils/tests/ecp.c
index 15bc71cc3..ef231d8a8 100644
--- a/elfutils/tests/ecp.c
+++ b/elfutils/tests/ecp.c
@@ -21,33 +21,39 @@
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);
diff --git a/elfutils/tests/get-pubnames2.c b/elfutils/tests/get-pubnames2.c
index 9aa6451a1..2fa32edb1 100644
--- a/elfutils/tests/get-pubnames2.c
+++ b/elfutils/tests/get-pubnames2.c
@@ -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;
}
diff --git a/elfutils/tests/newscn.c b/elfutils/tests/newscn.c
index 58cffe3dd..6196831cf 100644
--- a/elfutils/tests/newscn.c
+++ b/elfutils/tests/newscn.c
@@ -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)
{