summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/ChangeLog23
-rw-r--r--backends/Makefile.am6
-rw-r--r--backends/alpha_auxv.c46
-rw-r--r--backends/alpha_init.c3
-rw-r--r--backends/i386_corenote.c32
-rw-r--r--backends/ppc_attrs.c76
-rw-r--r--backends/ppc_corenote.c15
-rw-r--r--backends/ppc_init.c3
-rw-r--r--libdwfl/ChangeLog16
-rw-r--r--libdwfl/dwfl_build_id_find_elf.c5
-rw-r--r--libdwfl/dwfl_module_getdwarf.c9
-rw-r--r--libdwfl/relocate.c28
-rw-r--r--libebl/ChangeLog22
-rw-r--r--libebl/Makefile.am4
-rw-r--r--libebl/ebl-hooks.h6
-rw-r--r--libebl/eblcheckobjattr.c81
-rw-r--r--libebl/eblcorenotetypename.c4
-rw-r--r--libebl/eblopenbackend.c19
-rw-r--r--libebl/eblsectiontypename.c51
-rw-r--r--libebl/libebl.h11
-rw-r--r--libelf/ChangeLog17
-rw-r--r--libelf/elf.h7
-rw-r--r--libelf/elf_begin.c133
-rw-r--r--src/ChangeLog24
-rw-r--r--src/elfcmp.c6
-rw-r--r--src/elflint.c201
-rw-r--r--src/readelf.c211
-rw-r--r--tests/ChangeLog6
-rw-r--r--tests/Makefile.am3
-rwxr-xr-xtests/run-elflint-test.sh5
-rw-r--r--tests/testfile46.bz2bin0 -> 322 bytes
31 files changed, 908 insertions, 165 deletions
diff --git a/backends/ChangeLog b/backends/ChangeLog
index 25155db3..681ba94c 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,26 @@
+2008-02-20 Roland McGrath <roland@redhat.com>
+
+ * ppc_attrs.c: New file.
+ * Makefile.am (ppc_SRCS, ppc64_SRCS): Add it.
+ * ppc_init.c (ppc_init): Initialize check_object_attribute hook.
+
+2008-02-14 Roland McGrath <roland@redhat.com>
+
+ * alpha_auxv.c: New file.
+ * Makefile.am (alpha_SRCS): Add it.
+ * alpha_init.c (alpha_init): Initialize auxv_info hook.
+
+2008-02-08 Roland McGrath <roland@redhat.com>
+
+ * ppc_corenote.c (spe_regs): New const variable.
+ (EXTRA_NOTES): Use it for NT_PPC_SPE.
+
+2008-01-02 Roland McGrath <roland@redhat.com>
+
+ * i386_corenote.c (tls_items): New const table.
+ (tls_info): New function, uses it.
+ (EXTRA_NOTES): Use it to handle NT_386_TLS.
+
2008-01-08 Ulrich Drepper <drepper@redhat.com>
* Makefile.am: Add x86-64 disassembler.
diff --git a/backends/Makefile.am b/backends/Makefile.am
index 79fccfdc..75eacde9 100644
--- a/backends/Makefile.am
+++ b/backends/Makefile.am
@@ -81,7 +81,7 @@ libebl_ia64_pic_a_SOURCES = $(ia64_SRCS)
am_libebl_ia64_pic_a_OBJECTS = $(ia64_SRCS:.c=.os)
alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c \
- alpha_corenote.c
+ alpha_corenote.c alpha_auxv.c
libebl_alpha_pic_a_SOURCES = $(alpha_SRCS)
am_libebl_alpha_pic_a_OBJECTS = $(alpha_SRCS:.c=.os)
@@ -95,12 +95,12 @@ libebl_sparc_pic_a_SOURCES = $(sparc_SRCS)
am_libebl_sparc_pic_a_OBJECTS = $(sparc_SRCS:.c=.os)
ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \
- ppc_corenote.c ppc_auxv.c
+ ppc_corenote.c ppc_auxv.c ppc_attrs.c
libebl_ppc_pic_a_SOURCES = $(ppc_SRCS)
am_libebl_ppc_pic_a_OBJECTS = $(ppc_SRCS:.c=.os)
ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c \
- ppc64_corenote.c ppc_regs.c ppc_auxv.c
+ ppc64_corenote.c ppc_regs.c ppc_auxv.c ppc_attrs.c
libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS)
am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os)
diff --git a/backends/alpha_auxv.c b/backends/alpha_auxv.c
new file mode 100644
index 00000000..38a8bcdf
--- /dev/null
+++ b/backends/alpha_auxv.c
@@ -0,0 +1,46 @@
+/* Alpha-specific auxv handling.
+ Copyright (C) 2008 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+ if (a_type != AT_HWCAP)
+ return 0;
+
+ *name = "HWCAP";
+ *format = "b"
+ "bwx\0" "fix\0" "cix\0" "0x08\0"
+ "0x10\0" "0x20\0" "0x40\0" "0x80\0"
+ "max\0" "precise_trap\0"
+ "\0";
+ return 1;
+}
diff --git a/backends/alpha_init.c b/backends/alpha_init.c
index 794d412a..3c9e29d2 100644
--- a/backends/alpha_init.c
+++ b/backends/alpha_init.c
@@ -1,5 +1,5 @@
/* Initialization of Alpha specific backend library.
- Copyright (C) 2002, 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2002, 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -57,6 +57,7 @@ alpha_init (elf, machine, eh, ehlen)
HOOK (eh, machine_section_flag_check);
HOOK (eh, register_info);
HOOK (eh, core_note);
+ HOOK (eh, auxv_info);
eh->sysvhash_entrysize = sizeof (Elf64_Xword);
return MODVERSION;
diff --git a/backends/i386_corenote.c b/backends/i386_corenote.c
index f6c4c1de..02d8ec38 100644
--- a/backends/i386_corenote.c
+++ b/backends/i386_corenote.c
@@ -1,5 +1,5 @@
/* i386 specific core note handling.
- Copyright (C) 2007 Red Hat, Inc.
+ Copyright (C) 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -101,6 +101,34 @@ static const Ebl_Register_Location prxfpreg_regs[] =
};
#define EXTRA_NOTES \
- EXTRA_REGSET (NT_PRFPXREG, 512, prxfpreg_regs)
+ EXTRA_REGSET (NT_PRFPXREG, 512, prxfpreg_regs) \
+ case NT_386_TLS: \
+ return tls_info (descsz, regs_offset, nregloc, reglocs, nitems, items);
+
+#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
+
+static const Ebl_Core_Item tls_items[] =
+ {
+ { .type = ELF_T_WORD, .offset = 0x0, .format = 'd', .name = "index" },
+ { .type = ELF_T_WORD, .offset = 0x4, .format = 'x', .name = "base" },
+ { .type = ELF_T_WORD, .offset = 0x8, .format = 'x', .name = "limit" },
+ { .type = ELF_T_WORD, .offset = 0xc, .format = 'x', .name = "flags" },
+ };
+
+static int
+tls_info (GElf_Word descsz, GElf_Word *regs_offset,
+ size_t *nregloc, const Ebl_Register_Location **reglocs,
+ size_t *nitems, const Ebl_Core_Item **items)
+{
+ if (descsz % 16 != 0)
+ return 0;
+
+ *regs_offset = 0;
+ *nregloc = 0;
+ *reglocs = NULL;
+ *nitems = sizeof tls_items / sizeof tls_items[0];
+ *items = tls_items;
+ return 1;
+}
#include "linux-core-note.c"
diff --git a/backends/ppc_attrs.c b/backends/ppc_attrs.c
new file mode 100644
index 00000000..733b8749
--- /dev/null
+++ b/backends/ppc_attrs.c
@@ -0,0 +1,76 @@
+/* Object attribute tags for PowerPC.
+ Copyright (C) 2008 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+bool
+ppc_check_object_attribute (ebl, vendor, tag, value, tag_name, value_name)
+ Ebl *ebl __attribute__ ((unused));
+ const char *vendor;
+ int tag;
+ uint64_t value;
+ const char **tag_name;
+ const char **value_name;
+{
+ if (!strcmp (vendor, "gnu"))
+ switch (tag)
+ {
+ case 4:
+ *tag_name = "GNU_Power_ABI_FP";
+ static const char *fp_kinds[] =
+ {
+ "Hard or soft float",
+ "Hard float",
+ "Soft float",
+ };
+ if (value < sizeof fp_kinds / sizeof fp_kinds[0])
+ *value_name = fp_kinds[value];
+ return true;
+
+ case 8:
+ *tag_name = "GNU_Power_ABI_Vector";
+ static const char *vector_kinds[] =
+ {
+ "Any", "Generic", "AltiVec", "SPE"
+ };
+ if (value < sizeof vector_kinds / sizeof vector_kinds[0])
+ *value_name = vector_kinds[value];
+ return true;
+ }
+
+ return false;
+}
+
+__typeof (ppc_check_object_attribute)
+ ppc64_check_object_attribute
+ __attribute__ ((alias ("ppc_check_object_attribute")));
diff --git a/backends/ppc_corenote.c b/backends/ppc_corenote.c
index daadbb48..59e619e1 100644
--- a/backends/ppc_corenote.c
+++ b/backends/ppc_corenote.c
@@ -1,5 +1,5 @@
/* PowerPC specific core note handling.
- Copyright (C) 2007 Red Hat, Inc.
+ Copyright (C) 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -81,8 +81,19 @@ static const Ebl_Register_Location altivec_regs[] =
{ .offset = 33 * 16, .regno = 356, .count = 1, .bits = 32, .pad = 12 }
};
+static const Ebl_Register_Location spe_regs[] =
+ {
+ /* evr0-evr31
+ { .offset = 0, .regno = ???, .count = 32, .bits = 32 },
+ * acc *
+ { .offset = 32 * 4, .regno = ???, .count = 1, .bits = 64 }, */
+ /* spefscr */
+ { .offset = 34 * 4, .regno = 612, .count = 1, .bits = 32 }
+ };
+
#define EXTRA_NOTES \
- EXTRA_REGSET (NT_PPC_VMX, 34 * 16, altivec_regs)
+ EXTRA_REGSET (NT_PPC_VMX, 34 * 16, altivec_regs) \
+ EXTRA_REGSET (NT_PPC_SPE, 35 * 4, spe_regs)
#if BITS == 32
# define ULONG uint32_t
diff --git a/backends/ppc_init.c b/backends/ppc_init.c
index 7edc8fad..2e587167 100644
--- a/backends/ppc_init.c
+++ b/backends/ppc_init.c
@@ -1,5 +1,5 @@
/* Initialization of PPC specific backend library.
- Copyright (C) 2004, 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2004.
@@ -59,6 +59,7 @@ ppc_init (elf, machine, eh, ehlen)
HOOK (eh, register_info);
HOOK (eh, core_note);
HOOK (eh, auxv_info);
+ HOOK (eh, check_object_attribute);
return MODVERSION;
}
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
index f878c0d6..01a2537e 100644
--- a/libdwfl/ChangeLog
+++ b/libdwfl/ChangeLog
@@ -1,3 +1,19 @@
+2008-02-19 Roland McGrath <roland@redhat.com>
+
+ * relocate.c (relocate_section): Check for an unhandled relocation
+ type before resolving a reloc's symbol. Lift DWFL_E_BADRELTYPE ->
+ DWFL_E_UNKNOWN_MACHINE check out of loops.
+
+ * dwfl_module_getdwarf.c (load_dw): Skip relocation if
+ DEBUGFILE->relocated is already set.
+
+2008-01-26 Roland McGrath <roland@redhat.com>
+
+ * dwfl_module_getdwarf.c (open_elf): Open FILE->name if it's non-null.
+
+ * dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Don't clear
+ incoming *FILE_NAME at the start.
+
2008-01-08 Roland McGrath <roland@redhat.com>
* Makefile.am (euinclude): Variable removed.
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
index c6215012..a6e38ce7 100644
--- a/libdwfl/dwfl_build_id_find_elf.c
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -1,5 +1,5 @@
/* Find an ELF file for a module from its build ID.
- Copyright (C) 2007 Red Hat, Inc.
+ Copyright (C) 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -57,7 +57,8 @@ int
internal_function
__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
{
- *file_name = NULL;
+ /* If *FILE_NAME was primed into the module, leave it there
+ as the fallback when we have nothing to offer. */
errno = 0;
if (mod->build_id_len <= 0)
return -1;
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
index 775df731..7dd9b53f 100644
--- a/libdwfl/dwfl_module_getdwarf.c
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -1,5 +1,5 @@
/* Find debugging and symbol information for a module in libdwfl.
- Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -61,6 +61,11 @@ open_elf (Dwfl_Module *mod, struct dwfl_file *file)
{
if (file->elf == NULL)
{
+ /* If there was a pre-primed file name left that the callback left
+ behind, try to open that file name. */
+ if (file->fd < 0 && file->name != NULL)
+ file->fd = TEMP_FAILURE_RETRY (open64 (file->name, O_RDONLY));
+
if (file->fd < 0)
return CBFAIL;
@@ -585,7 +590,7 @@ __libdwfl_module_getebl (Dwfl_Module *mod)
static Dwfl_Error
load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
{
- if (mod->e_type == ET_REL)
+ if (mod->e_type == ET_REL && !debugfile->relocated)
{
const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
index 6265f1bf..abacc041 100644
--- a/libdwfl/relocate.c
+++ b/libdwfl/relocate.c
@@ -1,5 +1,5 @@
/* Relocate debug information.
- Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -306,6 +306,12 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
Dwfl_Error relocate (GElf_Addr offset, const GElf_Sxword *addend,
int rtype, int symndx)
{
+ /* First see if this is a reloc we can handle.
+ If we are skipping it, don't bother resolving the symbol. */
+ Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
+ if (unlikely (type == ELF_T_NUM))
+ return DWFL_E_BADRELTYPE;
+
/* First, resolve the symbol to an absolute value. */
GElf_Addr value;
@@ -342,7 +348,6 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword); \
DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
size_t size;
- Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype);
switch (type)
{
#define DO_TYPE(NAME, Name) \
@@ -352,10 +357,6 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
TYPES;
#undef DO_TYPE
default:
- /* This might be because ebl_openbackend failed to find
- any libebl_CPU.so library. Diagnose that clearly. */
- if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
- return DWFL_E_UNKNOWN_MACHINE;
return DWFL_E_BADRELTYPE;
}
@@ -437,6 +438,19 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
return DWFL_E_LIBELF;
Dwfl_Error result = DWFL_E_NOERROR;
+ bool first_badreltype = true;
+ inline void check_badreltype (void)
+ {
+ if (first_badreltype)
+ {
+ first_badreltype = false;
+ if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
+ /* This might be because ebl_openbackend failed to find
+ any libebl_CPU.so library. Diagnose that clearly. */
+ result = DWFL_E_UNKNOWN_MACHINE;
+ }
+ }
+
size_t nrels = shdr->sh_size / shdr->sh_entsize;
size_t complete = 0;
if (shdr->sh_type == SHT_REL)
@@ -448,6 +462,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
result = relocate (r->r_offset, NULL,
GELF_R_TYPE (r->r_info),
GELF_R_SYM (r->r_info));
+ check_badreltype ();
if (partial)
switch (result)
{
@@ -476,6 +491,7 @@ relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
result = relocate (r->r_offset, &r->r_addend,
GELF_R_TYPE (r->r_info),
GELF_R_SYM (r->r_info));
+ check_badreltype ();
if (partial)
switch (result)
{
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
index 86c91781..8ebc6c19 100644
--- a/libebl/ChangeLog
+++ b/libebl/ChangeLog
@@ -1,3 +1,25 @@
+2008-02-20 Roland McGrath <roland@redhat.com>
+
+ * libebl.h: Declare ebl_check_object_attribute.
+ * eblcheckobjattr.c: New file.
+ * Makefile.am (gen_SOURCES): Add it.
+ * ebl-hooks.h: Add check_object_attribute hook.
+ * eblopenbackend.c (default_check_object_attribute): New function.
+ (fill_defaults): Initialize pointer to it.
+
+2008-02-19 Roland McGrath <roland@redhat.com>
+
+ * eblsectiontypename.c (ebl_section_type_name):
+ Handle SHT_GNU_ATTRIBUTES.
+
+2008-02-08 Roland McGrath <roland@redhat.com>
+
+ * eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_PPC_SPE.
+
+2008-01-30 Roland McGrath <roland@redhat.com>
+
+ * eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_386_TLS.
+
2007-10-18 Roland McGrath <roland@redhat.com>
* eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_PPC_VMX.
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
index 2cf570e7..1e36b334 100644
--- a/libebl/Makefile.am
+++ b/libebl/Makefile.am
@@ -1,6 +1,6 @@
## Process this file with automake to create Makefile.in
##
-## Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+## Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
## This file is part of Red Hat elfutils.
##
## Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -58,7 +58,7 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \
eblelfclass.c eblelfdata.c eblelfmachine.c \
ebl_check_special_symbol.c eblbsspltp.c eblretval.c \
eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \
- eblsysvhashentrysize.c eblauxvinfo.c
+ eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c
libebl_a_SOURCES = $(gen_SOURCES)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index c0c929bd..c236b35e 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -115,6 +115,10 @@ int EBLHOOK(core_note) (GElf_Word, GElf_Word, GElf_Word *, size_t *,
/* Handle object file note. */
bool EBLHOOK(object_note) (const char *, uint32_t, uint32_t, const char *);
+/* Check object attribute. */
+bool EBLHOOK(check_object_attribute) (Ebl *, const char *, int, uint64_t,
+ const char **, const char **);
+
/* Describe auxv element type. */
int EBLHOOK(auxv_info) (GElf_Xword, const char **, const char **);
@@ -148,7 +152,7 @@ ssize_t EBLHOOK(register_info) (Ebl *ebl,
const char **prefix, const char **setname,
int *bits, int *type);
- /* Disassembler function. */
+/* Disassembler function. */
int EBLHOOK(disasm) (const uint8_t **startp, const uint8_t *end,
GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb,
DisasmGetSymCB_t symcb, void *outcbarg, void *symcbarg);
diff --git a/libebl/eblcheckobjattr.c b/libebl/eblcheckobjattr.c
new file mode 100644
index 00000000..fe75de74
--- /dev/null
+++ b/libebl/eblcheckobjattr.c
@@ -0,0 +1,81 @@
+/* Check object attributes.
+ Copyright (C) 2008 Red Hat, Inc.
+ This file is part of Red Hat elfutils.
+
+ Red Hat elfutils is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by the
+ Free Software Foundation; version 2 of the License.
+
+ Red Hat elfutils is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with Red Hat elfutils; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
+
+ In addition, as a special exception, Red Hat, Inc. gives You the
+ additional right to link the code of Red Hat elfutils with code licensed
+ under any Open Source Initiative certified open source license
+ (http://www.opensource.org/licenses/index.php) which requires the
+ distribution of source code with any binary distribution and to
+ distribute linked combinations of the two. Non-GPL Code permitted under
+ this exception must only link to the code of Red Hat elfutils through
+ those well defined interfaces identified in the file named EXCEPTION
+ found in the source code files (the "Approved Interfaces"). The files
+ of Non-GPL Code may instantiate templates or use macros or inline
+ functions from the Approved Interfaces without causing the resulting
+ work to be covered by the GNU General Public License. Only Red Hat,
+ Inc. may make changes or additions to the list of Approved Interfaces.
+ Red Hat's grant of this exception is conditioned upon your not adding
+ any new exceptions. If you wish to add a new Approved Interface or
+ exception, please contact Red Hat. You must obey the GNU General Public
+ License in all respects for all of the Red Hat elfutils code and other
+ code used in conjunction with Red Hat elfutils except the Non-GPL Code
+ covered by this exception. If you modify this file, you may extend this
+ exception to your version of the file, but you are not obligated to do
+ so. If you do not wish to provide this exception without modification,
+ you must delete this exception statement from your version and license
+ this file solely under the GPL without exception.
+
+ Red Hat elfutils is an included package of the Open Invention Network.
+ An included package of the Open Invention Network is a package for which
+ Open Invention Network licensees cross-license their patents. No patent
+ license is granted, either expressly or impliedly, by designation as an
+ included package. Should you wish to participate in the Open Invention
+ Network licensing program, please visit www.openinventionnetwork.com
+ <http://www.openinventionnetwork.com>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <libeblP.h>
+
+
+bool
+ebl_check_object_attribute (ebl, vendor, tag, value, tag_name, value_name)
+ Ebl *ebl;
+ const char *vendor;
+ int tag;
+ uint64_t value;
+ const char **tag_name;
+ const char **value_name;
+{
+ if (ebl->check_object_attribute (ebl, vendor, tag, value,
+ tag_name, value_name))
+ return true;
+
+ if (strcmp (vendor, "gnu"))
+ return false;
+
+ if (tag == 32)
+ {
+ *tag_name = "compatibility";
+ return true;
+ }
+
+ return false;
+}
diff --git a/libebl/eblcorenotetypename.c b/libebl/eblcorenotetypename.c
index 44b02376..d01932fc 100644
--- a/libebl/eblcorenotetypename.c
+++ b/libebl/eblcorenotetypename.c
@@ -1,5 +1,5 @@
/* Return note type name.
- Copyright (C) 2002, 2007 Red Hat, Inc.
+ Copyright (C) 2002, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -99,6 +99,8 @@ ebl_core_note_type_name (ebl, type, buf, len)
#define KNOWNSTYPE(name) case NT_##name: res = #name; break
KNOWNSTYPE (PRXFPREG);
KNOWNSTYPE (PPC_VMX);
+ KNOWNSTYPE (PPC_SPE);
+ KNOWNSTYPE (386_TLS);
#undef KNOWNSTYPE
default:
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 8a44f904..08817f66 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -1,5 +1,5 @@
/* Generate ELF backend handle.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -210,6 +210,10 @@ static ssize_t default_register_info (Ebl *ebl,
const char **prefix,
const char **setname,
int *bits, int *type);
+static bool default_check_object_attribute (Ebl *ebl, const char *vendor,
+ int tag, uint64_t value,
+ const char **tag_name,
+ const char **value_name);
static void
@@ -246,6 +250,7 @@ fill_defaults (Ebl *result)
result->bss_plt_p = default_bss_plt_p;
result->return_value_location = default_return_value_location;
result->register_info = default_register_info;
+ result->check_object_attribute = default_check_object_attribute;
result->disasm = NULL;
result->destr = default_destr;
result->sysvhash_entrysize = sizeof (Elf32_Word);
@@ -700,3 +705,15 @@ default_register_info (Ebl *ebl __attribute__ ((unused)),
*type = DW_ATE_void;
return snprintf (name, namelen, "reg%d", regno);
}
+
+static bool
+default_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+ const char *vendor __attribute__ ((unused)),
+ int tag __attribute__ ((unused)),
+ uint64_t value __attribute__ ((unused)),
+ const char **tag_name, const char **value_name)
+{
+ *tag_name = NULL;
+ *value_name = NULL;
+ return false;
+}
diff --git a/libebl/eblsectiontypename.c b/libebl/eblsectiontypename.c
index b62c37b3..a37e5f6d 100644
--- a/libebl/eblsectiontypename.c
+++ b/libebl/eblsectiontypename.c
@@ -1,5 +1,5 @@
/* Return section type name.
- Copyright (C) 2001, 2002, 2006 Red Hat, Inc.
+ Copyright (C) 2001, 2002, 2006, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -110,31 +110,38 @@ ebl_section_type_name (ebl, section, buf, len)
res = sunwtypes[section - SHT_LOSUNW];
}
else
- {
- /* A few GNU additions. */
- if (section == SHT_CHECKSUM)
+ /* A few GNU additions. */
+ switch (section)
+ {
+ case SHT_CHECKSUM:
res = "CHECKSUM";
- else if (section == SHT_GNU_LIBLIST)
+ break;
+ case SHT_GNU_LIBLIST:
res = "GNU_LIBLIST";
- else if (section == SHT_GNU_HASH)
+ break;
+ case SHT_GNU_HASH:
res = "GNU_HASH";
- /* Handle OS-specific section names. */
- else
- {
- if (section >= SHT_LOOS && section <= SHT_HIOS)
- snprintf (buf, len, "SHT_LOOS+%x", section - SHT_LOOS);
- /* Handle processor-specific section names. */
- else if (section >= SHT_LOPROC && section <= SHT_HIPROC)
- snprintf (buf, len, "SHT_LOPROC+%x", section - SHT_LOPROC);
- else if ((unsigned int) section >= SHT_LOUSER
- && (unsigned int) section <= SHT_HIUSER)
- snprintf (buf, len, "SHT_LOUSER+%x", section - SHT_LOUSER);
- else
- snprintf (buf, len, "%s: %d", gettext ("<unknown>"), section);
+ break;
+ case SHT_GNU_ATTRIBUTES:
+ res = "GNU_ATTRIBUTES";
+ break;
- res = buf;
- }
- }
+ default:
+ /* Handle OS-specific section names. */
+ if (section >= SHT_LOOS && section <= SHT_HIOS)
+ snprintf (buf, len, "SHT_LOOS+%x", section - SHT_LOOS);
+ /* Handle processor-specific section names. */
+ else if (section >= SHT_LOPROC && section <= SHT_HIPROC)
+ snprintf (buf, len, "SHT_LOPROC+%x", section - SHT_LOPROC);
+ else if ((unsigned int) section >= SHT_LOUSER
+ && (unsigned int) section <= SHT_HIUSER)
+ snprintf (buf, len, "SHT_LOUSER+%x", section - SHT_LOUSER);
+ else
+ snprintf (buf, len, "%s: %d", gettext ("<unknown>"), section);
+
+ res = buf;
+ break;
+ }
}
return res;
diff --git a/libebl/libebl.h b/libebl/libebl.h
index 7e29168d..083de03a 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -1,5 +1,5 @@
/* Interface for libebl.
- Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -182,6 +182,15 @@ extern const char *ebl_object_note_type_name (Ebl *ebl, uint32_t type,
extern void ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
uint32_t descsz, const char *desc);
+/* Check whether an attribute in a .gnu_attributes section is recognized.
+ Fills in *TAG_NAME with the name for this tag.
+ If VALUE is a known value for that tag, also fills in *VALUE_NAME. */
+extern bool ebl_check_object_attribute (Ebl *ebl, const char *vendor,
+ int tag, uint64_t value,
+ const char **tag_name,
+ const char **value_name);
+
+
/* Check section name for being that of a debug informatino section. */
extern bool ebl_debugscn_p (Ebl *ebl, const char *name);
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
index 17633ba7..ef7b37a1 100644
--- a/libelf/ChangeLog
+++ b/libelf/ChangeLog
@@ -1,8 +1,25 @@
+2008-02-19 Roland McGrath <roland@redhat.com>
+
+ * elf.h: Update from glibc.
+
+2008-02-08 Roland McGrath <roland@redhat.com>
+
+ * elf.h: Update from glibc.
+
2008-01-31 Ulrich Drepper <drepper@redhat.com>
* elf_strptr.c (elf_strptr): Don't fail if the ELF file is currently
under construction and no raw data can be read from disk.
+2008-01-30 Roland McGrath <roland@redhat.com>
+
+ * elf.h: Update from glibc.
+
+2008-01-26 Roland McGrath <roland@redhat.com>
+
+ * elf_begin.c (__libelf_next_arhdr): Rewrite conversions using a macro.
+ Fixes various pastos in wrong type in sizeof, wrong string parsed.
+
2008-01-20 Roland McGrath <roland@redhat.com>
* elf_getaroff.c: Calculate from start_offset, instead of using
diff --git a/libelf/elf.h b/libelf/elf.h
index acd3d3e1..928e9ec9 100644
--- a/libelf/elf.h
+++ b/libelf/elf.h
@@ -1,5 +1,6 @@
/* This file defines standard ELF types, structures, and macros.
- Copyright (C) 1995-2003,2004,2005,2006,2007 Free Software Foundation, Inc.
+ Copyright (C) 1995-2003,2004,2005,2006,2007,2008
+ Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -330,6 +331,7 @@ typedef struct
#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */
#define SHT_NUM 19 /* Number of defined types. */
#define SHT_LOOS 0x60000000 /* Start OS-specific. */
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */
#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */
#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */
#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */
@@ -605,6 +607,8 @@ typedef struct
#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct */
#define NT_PRXFPREG 0x46e62b7f /* Contains copy of user_fxsr_struct */
#define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE 0x101 /* PowerPC SPE/EVR registers */
+#define NT_386_TLS 0x200 /* i386 TLS slots (struct user_desc) */
/* Legal values for the note segment descriptor types for object files. */
@@ -1278,6 +1282,7 @@ typedef struct
#define HWCAP_SPARC_V9 16 /* The CPU is v9, so v8plus is ok. */
#define HWCAP_SPARC_ULTRA3 32
#define HWCAP_SPARC_BLKINIT 64 /* Sun4v with block-init/load-twin. */
+#define HWCAP_SPARC_N2 128
/* MIPS R3000 specific definitions. */
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
index d84f9047..b95b06bf 100644
--- a/libelf/elf_begin.c
+++ b/libelf/elf_begin.c
@@ -1,5 +1,5 @@
/* Create descriptor for processing file.
- Copyright (C) 1998-2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 1998-2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
@@ -850,112 +850,45 @@ __libelf_next_arhdr (elf)
elf_ar_hdr->ar_name = elf->state.ar.ar_name;
}
+ if (unlikely (ar_hdr->ar_size[0] == ' '))
+ /* Something is really wrong. We cannot live without a size for
+ the member since it will not be possible to find the next
+ archive member. */
+ {
+ __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
+ return -1;
+ }
+
/* Since there are no specialized functions to convert ASCII to
time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
atoll depending on the size of the types. We are also prepared
for the case where the whole field in the `struct ar_hdr' is
filled in which case we cannot simply use atol/l but instead have
to create a temporary copy. */
- if (ar_hdr->ar_date[sizeof (ar_hdr->ar_date) - 1] == ' ')
- {
- if (ar_hdr->ar_date[0] == ' ')
- elf_ar_hdr->ar_date = 0;
- else
- elf_ar_hdr->ar_date = (sizeof (time_t) <= sizeof (long int)
- ? (time_t) atol (ar_hdr->ar_date)
- : (time_t) atoll (ar_hdr->ar_date));
- }
- else
- {
- char buf[sizeof (ar_hdr->ar_date) + 1];
- *((char *) __mempcpy (buf, ar_hdr->ar_date, sizeof (ar_hdr->ar_date)))
- = '\0';
- elf_ar_hdr->ar_date = (sizeof (time_t) <= sizeof (long int)
- ? (time_t) atol (ar_hdr->ar_date)
- : (time_t) atoll (ar_hdr->ar_date));
- }
- if (ar_hdr->ar_uid[sizeof (ar_hdr->ar_uid) - 1] == ' ')
- {
- if (ar_hdr->ar_uid[0] == ' ')
- elf_ar_hdr->ar_uid = 0;
- else
- elf_ar_hdr->ar_uid = (sizeof (uid_t) <= sizeof (long int)
- ? (uid_t) atol (ar_hdr->ar_uid)
- : (uid_t) atoll (ar_hdr->ar_uid));
- }
- else
- {
- char buf[sizeof (ar_hdr->ar_uid) + 1];
- *((char *) __mempcpy (buf, ar_hdr->ar_uid, sizeof (ar_hdr->ar_uid)))
- = '\0';
- elf_ar_hdr->ar_uid = (sizeof (uid_t) <= sizeof (long int)
- ? (uid_t) atol (ar_hdr->ar_uid)
- : (uid_t) atoll (ar_hdr->ar_uid));
- }
-
- if (ar_hdr->ar_gid[sizeof (ar_hdr->ar_gid) - 1] == ' ')
- {
- if (ar_hdr->ar_gid[0] == ' ')
- elf_ar_hdr->ar_gid = 0;
- else
- elf_ar_hdr->ar_gid = (sizeof (gid_t) <= sizeof (long int)
- ? (gid_t) atol (ar_hdr->ar_gid)
- : (gid_t) atoll (ar_hdr->ar_gid));
- }
- else
- {
- char buf[sizeof (ar_hdr->ar_gid) + 1];
- *((char *) __mempcpy (buf, ar_hdr->ar_gid, sizeof (ar_hdr->ar_gid)))
- = '\0';
- elf_ar_hdr->ar_gid = (sizeof (gid_t) <= sizeof (long int)
- ? (gid_t) atol (ar_hdr->ar_gid)
- : (gid_t) atoll (ar_hdr->ar_gid));
- }
-
- if (ar_hdr->ar_mode[sizeof (ar_hdr->ar_mode) - 1] == ' ')
- {
- if (ar_hdr->ar_mode[0] == ' ')
- elf_ar_hdr->ar_mode = 0;
- else
- elf_ar_hdr->ar_mode = (sizeof (mode_t) <= sizeof (long int)
- ? (mode_t) strtol (ar_hdr->ar_mode, NULL, 8)
- : (mode_t) strtoll (ar_hdr->ar_mode, NULL, 8));
- }
- else
- {
- char buf[sizeof (ar_hdr->ar_mode) + 1];
- *((char *) __mempcpy (buf, ar_hdr->ar_mode, sizeof (ar_hdr->ar_mode)))
- = '\0';
- elf_ar_hdr->ar_mode = (sizeof (mode_t) <= sizeof (long int)
- ? (mode_t) strtol (ar_hdr->ar_mode, NULL, 8)
- : (mode_t) strtoll (ar_hdr->ar_mode, NULL, 8));
- }
-
- if (ar_hdr->ar_size[sizeof (ar_hdr->ar_size) - 1] == ' ')
- {
- if (unlikely (ar_hdr->ar_size[0] == ' '))
- /* Something is really wrong. We cannot live without a size for
- the member since it will not be possible to find the next
- archive member. */
- {
- __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
- return -1;
- }
- else
- elf_ar_hdr->ar_size = (sizeof (time_t) == sizeof (long int)
- ? (off_t) atol (ar_hdr->ar_size)
- : (off_t) atoll (ar_hdr->ar_size));
- }
- else
- {
- char buf[sizeof (ar_hdr->ar_size) + 1];
- *((char *) __mempcpy (buf, ar_hdr->ar_size, sizeof (ar_hdr->ar_size)))
- = '\0';
- elf_ar_hdr->ar_size = (sizeof (time_t) == sizeof (long int)
- ? (off_t) atol (ar_hdr->ar_size)
- : (off_t) atoll (ar_hdr->ar_size));
- }
+#define INT_FIELD(FIELD) \
+ do \
+ { \
+ char buf[sizeof (ar_hdr->FIELD) + 1]; \
+ const char *string = ar_hdr->FIELD; \
+ if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ') \
+ { \
+ *((char *) __mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD))) \
+ = '\0'; \
+ string = buf; \
+ } \
+ if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int)) \
+ elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string); \
+ else \
+ elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string); \
+ } \
+ while (0)
+
+ INT_FIELD (ar_date);
+ INT_FIELD (ar_uid);
+ INT_FIELD (ar_gid);
+ INT_FIELD (ar_mode);
+ INT_FIELD (ar_size);
return 0;
}
diff --git a/src/ChangeLog b/src/ChangeLog
index d3e49e41..f28c7006 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,21 @@
+2008-02-20 Roland McGrath <roland@redhat.com>
+
+ * readelf.c (print_attributes): New function.
+ (process_elf_file): Call it under -A.
+
+ * elflint.c (check_attributes): Implement it for real.
+
+2008-02-19 Roland McGrath <roland@redhat.com>
+
+ * elflint.c (special_sections): Handle .gnu.attributes section.
+ (check_sections): Likewise.
+ (check_attributes): New function.
+
+2008-02-10 Roland McGrath <roland@redhat.com>
+
+ * elfcmp.c (main): Ignore sh_offset differences in non-SHF_ALLOC
+ sections and ET_REL files.
+
2008-02-02 Ulrich Drepper <drepper@redhat.com>
* elf32-i386.script: Add .eh_frame_hdr, .tdata, and .tbss sections.
@@ -110,6 +128,12 @@
2008-01-04 Roland McGrath <roland@redhat.com>
+ * readelf.c (handle_core_items): Take new arg DESCSZ; if nonzero,
+ a size greater than the items cover means multiple sets of items.
+ (handle_core_note): Update caller.
+
+2008-01-04 Roland McGrath <roland@redhat.com>
+
* strip.c (handle_elf): Move SHDRIDX defn to silence gcc warning.
2008-01-03 Roland McGrath <roland@redhat.com>
diff --git a/src/elfcmp.c b/src/elfcmp.c
index be9aaccd..0e134df8 100644
--- a/src/elfcmp.c
+++ b/src/elfcmp.c
@@ -1,5 +1,5 @@
/* Compare relevant content of two ELF files.
- Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2005.
@@ -259,7 +259,9 @@ main (int argc, char *argv[])
// XXX Any flags which should be ignored?
|| shdr1->sh_flags != shdr2->sh_flags
|| shdr1->sh_addr != shdr2->sh_addr
- || shdr1->sh_offset != shdr2->sh_offset
+ || (shdr1->sh_offset != shdr2->sh_offset
+ && (shdr1->sh_flags & SHF_ALLOC)
+ && ehdr1->e_type != ET_REL)
|| shdr1->sh_size != shdr2->sh_size
|| shdr1->sh_link != shdr2->sh_link
|| shdr1->sh_info != shdr2->sh_info
diff --git a/src/elflint.c b/src/elflint.c
index b65170ce..9a1a7179 100644
--- a/src/elflint.c
+++ b/src/elflint.c
@@ -46,7 +46,12 @@
#include <elf-knowledge.h>
#include <system.h>
+#include "../libelf/libelfP.h"
+#include "../libelf/common.h"
#include "../libebl/libeblP.h"
+#include "../libdw/libdwP.h"
+#include "../libdwfl/libdwflP.h"
+#include "../libdw/memory-access.h"
/* Name and version of program. */
@@ -3099,6 +3104,194 @@ section [%2d] '%s': unknown parent version '%s'\n"),
}
}
+static void
+check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+ if (shdr->sh_size == 0)
+ {
+ ERROR (gettext ("section [%2d] '%s': empty object attributes section\n"),
+ idx, section_name (ebl, idx));
+ return;
+ }
+
+ Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
+ if (data == NULL || data->d_size == 0)
+ {
+ ERROR (gettext ("section [%2d] '%s': cannot get section data\n"),
+ idx, section_name (ebl, idx));
+ return;
+ }
+
+ inline size_t pos (const unsigned char *p)
+ {
+ return p - (const unsigned char *) data->d_buf;
+ }
+
+ const unsigned char *p = data->d_buf;
+ if (*p++ != 'A')
+ {
+ ERROR (gettext ("section [%2d] '%s': unrecognized attribute format\n"),
+ idx, section_name (ebl, idx));
+ return;
+ }
+
+ inline size_t left (void)
+ {
+ return (const unsigned char *) data->d_buf + data->d_size - p;
+ }
+
+ while (left () >= 4)
+ {
+ uint32_t len;
+ memcpy (&len, p, sizeof len);
+
+ if (len == 0)
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: zero length field in attribute section\n"),
+ idx, section_name (ebl, idx), pos (p));
+
+ if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+ CONVERT (len);
+
+ if (len > left ())
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
+ idx, section_name (ebl, idx), pos (p));
+ break;
+ }
+
+ const unsigned char *name = p + sizeof len;
+ p += len;
+
+ unsigned const char *q = memchr (name, '\0', len);
+ if (q == NULL)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
+ idx, section_name (ebl, idx), pos (p));
+ continue;
+ }
+ ++q;
+
+ if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
+ while (q < p)
+ {
+ unsigned const char *chunk = q;
+
+ unsigned int subsection_tag;
+ get_uleb128 (subsection_tag, q);
+
+ if (q >= p)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
+ idx, section_name (ebl, idx), pos (chunk));
+ break;
+ }
+
+ uint32_t subsection_len;
+ if (p - q < (ptrdiff_t) sizeof subsection_len)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: truncated attribute section\n"),
+ idx, section_name (ebl, idx), pos (q));
+ break;
+ }
+
+ memcpy (&subsection_len, q, sizeof subsection_len);
+ if (subsection_len == 0)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
+ idx, section_name (ebl, idx), pos (q));
+
+ q += sizeof subsection_len;
+ continue;
+ }
+
+ if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+ CONVERT (subsection_len);
+
+ if (p - chunk < subsection_len)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
+ idx, section_name (ebl, idx), pos (q));
+ break;
+ }
+
+ const unsigned char *subsection_end = chunk + subsection_len;
+ chunk = q;
+ q = subsection_end;
+
+ if (subsection_tag != 1) /* Tag_File */
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
+ idx, section_name (ebl, idx), pos (chunk), subsection_tag);
+ else
+ {
+ chunk += sizeof subsection_len;
+ while (chunk < q)
+ {
+ unsigned int tag;
+ get_uleb128 (tag, chunk);
+
+ uint64_t value = 0;
+ const unsigned char *r = chunk;
+ if (tag == 32 || (tag & 1) == 0)
+ {
+ get_uleb128 (value, r);
+ if (r > q)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
+ idx, section_name (ebl, idx), pos (chunk));
+ break;
+ }
+ }
+ if (tag == 32 || (tag & 1) != 0)
+ {
+ r = memchr (r, '\0', q - r);
+ if (r == NULL)
+ {
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
+ idx, section_name (ebl, idx), pos (chunk));
+ break;
+ }
+ ++r;
+ }
+
+ const char *tag_name = NULL;
+ const char *value_name = NULL;
+ if (!ebl_check_object_attribute (ebl, (const char *) name,
+ tag, value,
+ &tag_name, &value_name))
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
+ idx, section_name (ebl, idx), pos (chunk), tag);
+ else if ((tag & 1) == 0 && value_name == NULL)
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
+ idx, section_name (ebl, idx), pos (chunk),
+ tag_name, value);
+
+ chunk = r;
+ }
+ }
+ }
+ else
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
+ idx, section_name (ebl, idx), pos (p), name);
+ }
+
+ if (left () != 0)
+ ERROR (gettext ("\
+section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
+ idx, section_name (ebl, idx), pos (p));
+}
static bool has_loadable_segment;
static bool has_interp_segment;
@@ -3150,7 +3343,8 @@ static const struct
/* The following are GNU extensions. */
{ ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
{ ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
- { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 }
+ { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
+ { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
};
#define nspecial_sections \
(sizeof (special_sections) / sizeof (special_sections[0]))
@@ -3365,6 +3559,7 @@ section [%2zu] '%s': size not multiple of entry size\n"),
ERROR (gettext ("cannot get section header\n"));
if (shdr->sh_type >= SHT_NUM
+ && shdr->sh_type != SHT_GNU_ATTRIBUTES
&& shdr->sh_type != SHT_GNU_LIBLIST
&& shdr->sh_type != SHT_CHECKSUM
&& shdr->sh_type != SHT_GNU_verdef
@@ -3557,6 +3752,10 @@ section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
check_verdef (ebl, shdr, cnt);
break;
+ case SHT_GNU_ATTRIBUTES:
+ check_attributes (ebl, ehdr, shdr, cnt);
+ break;
+
default:
/* Nothing. */
break;
diff --git a/src/readelf.c b/src/readelf.c
index 90c460f9..0f0773c8 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -1,5 +1,5 @@
/* Print information from ELF file in human-readable form.
- Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007 Red Hat, Inc.
+ Copyright (C) 1999,2000,2001,2002,2003,2004,2005,2006,2007,2008 Red Hat, Inc.
This file is part of Red Hat elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 1999.
@@ -52,6 +52,7 @@
#include <system.h>
#include "../libelf/libelfP.h"
+#include "../libelf/common.h"
#include "../libebl/libeblP.h"
#include "../libdw/libdwP.h"
#include "../libdwfl/libdwflP.h"
@@ -221,6 +222,7 @@ static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
static void handle_hash (Ebl *ebl);
static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
static void print_liblist (Ebl *ebl);
+static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
static void dump_data (Ebl *ebl);
static void dump_strings (Ebl *ebl);
static void print_strings (Ebl *ebl);
@@ -640,6 +642,8 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
print_symtab (ebl, SHT_SYMTAB);
if (print_arch)
print_liblist (ebl);
+ if (print_arch)
+ print_attributes (ebl, ehdr);
if (dump_data_sections != NULL)
dump_data (pure_ebl);
if (string_sections != NULL)
@@ -2777,6 +2781,166 @@ print_liblist (Ebl *ebl)
}
}
+static void
+print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
+{
+ /* Find the object attributes sections. For this we have to search
+ through the section table. */
+ Elf_Scn *scn = NULL;
+
+ /* Get the section header string table index. */
+ size_t shstrndx;
+ if (unlikely (elf_getshstrndx (ebl->elf, &shstrndx) < 0))
+ error (EXIT_FAILURE, 0,
+ gettext ("cannot get section header string table index"));
+
+ while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+ {
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+ if (shdr == NULL || shdr->sh_type != SHT_GNU_ATTRIBUTES)
+ continue;
+
+ printf (gettext ("\
+\nObject attributes section [%2zu] '%s' of %" PRIu64
+ " bytes at offset %#0" PRIx64 ":\n"),
+ elf_ndxscn (scn),
+ elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+ shdr->sh_size, shdr->sh_offset);
+
+ Elf_Data *data = elf_rawdata (scn, NULL);
+ if (data == NULL)
+ return;
+
+ const unsigned char *p = data->d_buf;
+
+ if (unlikely (*p++ != 'A'))
+ return;
+
+ fputs_unlocked (gettext (" Owner Size\n"), stdout);
+
+ inline size_t left (void)
+ {
+ return (const unsigned char *) data->d_buf + data->d_size - p;
+ }
+
+ while (left () >= 4)
+ {
+ uint32_t len;
+ memcpy (&len, p, sizeof len);
+
+ if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+ CONVERT (len);
+
+ if (unlikely (len > left ()))
+ break;
+
+ const unsigned char *name = p + sizeof len;
+ p += len;
+
+ unsigned const char *q = memchr (name, '\0', len);
+ if (unlikely (q == NULL))
+ continue;
+ ++q;
+
+ printf (gettext (" %-13s %4" PRIu32 "\n"), name, len);
+
+ if (q - name == sizeof "gnu"
+ && !memcmp (name, "gnu", sizeof "gnu"))
+ while (q < p)
+ {
+ const unsigned char *const sub = q;
+
+ unsigned int subsection_tag;
+ get_uleb128 (subsection_tag, q);
+ if (unlikely (q >= p))
+ break;
+
+ uint32_t subsection_len;
+ if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
+ break;
+
+ memcpy (&subsection_len, q, sizeof subsection_len);
+
+ if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+ CONVERT (subsection_len);
+
+ if (unlikely (p - sub < subsection_len))
+ break;
+
+ const unsigned char *r = q + sizeof subsection_len;
+ q = sub + subsection_len;
+
+ switch (subsection_tag)
+ {
+ default:
+ printf (gettext (" %-4u %12" PRIu32 "\n"),
+ subsection_tag, subsection_len);
+ break;
+
+ case 1: /* Tag_File */
+ printf (gettext (" File: %11" PRIu32 "\n"),
+ subsection_len);
+
+ while (r < q)
+ {
+ unsigned int tag;
+ get_uleb128 (tag, r);
+ if (unlikely (r >= q))
+ break;
+
+ uint64_t value = 0;
+ const char *string = NULL;
+ if (tag == 32 || (tag & 1) == 0)
+ {
+ get_uleb128 (value, r);
+ if (r > q)
+ break;
+ }
+ if (tag == 32 || (tag & 1) != 0)
+ {
+ r = memchr (r, '\0', q - r);
+ if (r == NULL)
+ break;
+ ++r;
+ }
+
+ const char *tag_name = NULL;
+ const char *value_name = NULL;
+ ebl_check_object_attribute (ebl, (const char *) name,
+ tag, value,
+ &tag_name, &value_name);
+
+ if (tag_name != NULL)
+ {
+ if (tag == 32)
+ printf (gettext (" %s: %" PRId64 ", %s\n"),
+ tag_name, value, string);
+ else if (string == NULL && value_name == NULL)
+ printf (gettext (" %s: %" PRId64 "\n"),
+ tag_name, value);
+ else
+ printf (gettext (" %s: %s\n"),
+ tag_name, string ?: value_name);
+ }
+ else
+ {
+ assert (tag != 32);
+ if (string == NULL)
+ printf (gettext (" %u: %" PRId64 "\n"),
+ tag, value);
+ else
+ printf (gettext (" %u: %s\n"),
+ tag, string);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
static char *
format_dwarf_addr (Dwfl_Module *dwflmod,
@@ -5426,7 +5590,7 @@ compare_core_item_groups (const void *a, const void *b)
}
static unsigned int
-handle_core_items (Elf *core, const void *desc,
+handle_core_items (Elf *core, const void *desc, size_t descsz,
const Ebl_Core_Item *items, size_t nitems)
{
if (nitems == 0)
@@ -5450,18 +5614,35 @@ handle_core_items (Elf *core, const void *desc,
/* Write out all the groups. */
unsigned int colno = 0;
- for (size_t i = 0; i < ngroups; ++i)
+
+ do
{
- for (const Ebl_Core_Item **item = groups[i];
- (item < &sorted_items[nitems]
- && ((*item)->group == groups[i][0]->group
- || !strcmp ((*item)->group, groups[i][0]->group)));
- ++item)
- colno = handle_core_item (core, *item, desc, colno);
+ for (size_t i = 0; i < ngroups; ++i)
+ {
+ for (const Ebl_Core_Item **item = groups[i];
+ (item < &sorted_items[nitems]
+ && ((*item)->group == groups[i][0]->group
+ || !strcmp ((*item)->group, groups[i][0]->group)));
+ ++item)
+ colno = handle_core_item (core, *item, desc, colno);
+
+ /* Force a line break at the end of the group. */
+ colno = ITEM_WRAP_COLUMN;
+ }
- /* Force a line break at the end of the group. */
- colno = ITEM_WRAP_COLUMN;
+ if (descsz == 0)
+ break;
+
+ /* This set of items consumed a certain amount of the note's data.
+ If there is more data there, we have another unit of the same size.
+ Loop to print that out too. */
+ const Ebl_Core_Item *item = &items[nitems - 1];
+ size_t eltsz = item->offset + gelf_fsize (core, item->type,
+ item->count ?: 1, EV_CURRENT);
+ descsz -= eltsz;
+ desc += eltsz;
}
+ while (descsz > 0);
return colno;
}
@@ -5807,7 +5988,13 @@ handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const void *desc)
&regs_offset, &nregloc, &reglocs, &nitems, &items))
return;
- unsigned int colno = handle_core_items (ebl->elf, desc, items, nitems);
+ /* Pass 0 for DESCSZ when there are registers in the note,
+ so that the ITEMS array does not describe the whole thing.
+ For non-register notes, the actual descsz might be a multiple
+ of the unit size, not just exactly the unit size. */
+ unsigned int colno = handle_core_items (ebl->elf, desc,
+ nregloc == 0 ? nhdr->n_descsz : 0,
+ items, nitems);
if (colno != 0)
putchar_unlocked ('\n');
diff --git a/tests/ChangeLog b/tests/ChangeLog
index 97865b5d..f4bedcb4 100644
--- a/tests/ChangeLog
+++ b/tests/ChangeLog
@@ -1,3 +1,9 @@
+2008-02-20 Roland McGrath <roland@redhat.com>
+
+ * testfile46.bz2: New data file.
+ * Makefile.am (EXTRA_DIST): Add it.
+ * run-elflint-test.sh: Test on it.
+
2008-02-01 Ulrich Drepper <drepper@redhat.com>
* Makefile.am: Hook up sha1-tst.c.
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 5d5c9185..a058e589 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -136,7 +136,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \
testfile38.bz2 testfile39.bz2 testfile40.bz2 testfile40.debug.bz2 \
testfile41.bz2 testfile42.bz2 testfile43.bz2 \
testfile44.S.bz2 testfile44.expect.bz2 run-disasm-x86.sh \
- testfile45.S.bz2 testfile45.expect.bz2 run-disasm-x86-64.sh
+ testfile45.S.bz2 testfile45.expect.bz2 run-disasm-x86-64.sh \
+ testfile46.bz2
installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir) \
bindir=$(DESTDIR)$(bindir) \
diff --git a/tests/run-elflint-test.sh b/tests/run-elflint-test.sh
index a0b93a25..9f45d51e 100755
--- a/tests/run-elflint-test.sh
+++ b/tests/run-elflint-test.sh
@@ -1,5 +1,5 @@
#! /bin/sh
-# Copyright (C) 2005, 2007 Red Hat, Inc.
+# Copyright (C) 2005, 2007, 2008 Red Hat, Inc.
# This file is part of Red Hat elfutils.
# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
#
@@ -41,4 +41,7 @@ testrun ../src/elflint -q testfile33
testfiles testfile42
testrun ../src/elflint -q --gnu-ld testfile42
+testfiles testfile47
+testrun ../src/elflint -q testfile47
+
exit 0
diff --git a/tests/testfile46.bz2 b/tests/testfile46.bz2
new file mode 100644
index 00000000..db83b278
--- /dev/null
+++ b/tests/testfile46.bz2
Binary files differ