Finish elflint .gnu.attributes checking
authorRoland McGrath <roland@redhat.com>
Thu, 21 Feb 2008 06:19:39 +0000 (06:19 +0000)
committerRoland McGrath <roland@redhat.com>
Thu, 21 Feb 2008 06:19:39 +0000 (06:19 +0000)
31 files changed:
backends/ChangeLog
backends/Makefile.am
backends/alpha_auxv.c [new file with mode: 0644]
backends/alpha_init.c
backends/i386_corenote.c
backends/ppc_attrs.c [new file with mode: 0644]
backends/ppc_corenote.c
backends/ppc_init.c
libdwfl/ChangeLog
libdwfl/dwfl_build_id_find_elf.c
libdwfl/dwfl_module_getdwarf.c
libdwfl/relocate.c
libebl/ChangeLog
libebl/Makefile.am
libebl/ebl-hooks.h
libebl/eblcheckobjattr.c [new file with mode: 0644]
libebl/eblcorenotetypename.c
libebl/eblopenbackend.c
libebl/eblsectiontypename.c
libebl/libebl.h
libelf/ChangeLog
libelf/elf.h
libelf/elf_begin.c
src/ChangeLog
src/elfcmp.c
src/elflint.c
src/readelf.c
tests/ChangeLog
tests/Makefile.am
tests/run-elflint-test.sh
tests/testfile46.bz2 [new file with mode: 0644]

index 25155db..681ba94 100644 (file)
@@ -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.
index 79fccfd..75eacde 100644 (file)
@@ -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 (file)
index 0000000..38a8bcd
--- /dev/null
@@ -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;
+}
index 794d412..3c9e29d 100644 (file)
@@ -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;
index f6c4c1d..02d8ec3 100644 (file)
@@ -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 (file)
index 0000000..733b874
--- /dev/null
@@ -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")));
index daadbb4..59e619e 100644 (file)
@@ -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
index 7edc8fa..2e58716 100644 (file)
@@ -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;
 }
index f878c0d..01a2537 100644 (file)
@@ -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.
index c621501..a6e38ce 100644 (file)
@@ -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;
index 775df73..7dd9b53 100644 (file)
@@ -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;
 
index 6265f1b..abacc04 100644 (file)
@@ -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)
            {
index 86c9178..8ebc6c1 100644 (file)
@@ -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.
index 2cf570e..1e36b33 100644 (file)
@@ -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)
 
index c0c929b..c236b35 100644 (file)
@@ -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 (file)
index 0000000..fe75de7
--- /dev/null
@@ -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;
+}
index 44b0237..d01932f 100644 (file)
@@ -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:
index 8a44f90..08817f6 100644 (file)
@@ -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;
+}
index b62c37b..a37e5f6 100644 (file)
@@ -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;
index 7e29168..083de03 100644 (file)
@@ -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);
 
index 17633ba..ef7b37a 100644 (file)
@@ -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
index acd3d3e..928e9ec 100644 (file)
@@ -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.  */
 
index d84f904..b95b06b 100644 (file)
@@ -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;
 }
index d3e49e4..f28c700 100644 (file)
@@ -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.
 
 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>
index be9aacc..0e134df 100644 (file)
@@ -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
index b65170c..9a1a717 100644 (file)
 
 #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;
index 90c460f..0f0773c 100644 (file)
@@ -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');
 
index 97865b5..f4bedcb 100644 (file)
@@ -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.
index 5d5c918..a058e58 100644 (file)
@@ -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) \
index a0b93a2..9f45d51 100755 (executable)
@@ -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 (file)
index 0000000..db83b27
Binary files /dev/null and b/tests/testfile46.bz2 differ