]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: More restructuring of checks
authorPetr Machata <pmachata@redhat.com>
Fri, 16 Oct 2009 14:18:43 +0000 (16:18 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 18 Aug 2010 12:55:11 +0000 (14:55 +0200)
src/Makefile.am
src/dwarflint-checks.cc [new file with mode: 0644]
src/dwarflint-checks.hh
src/dwarflint-low.c
src/dwarflint-low.h
src/dwarflint-main.cc
src/dwarflint-where.h

index 9ffa1871944f830090fdba2e9ee9f540fa6c1db7..74ed80f4cf2781839774a19d4b33194e3d5a57d1 100644 (file)
@@ -87,7 +87,7 @@ dwarflint_SOURCES = dwarfstrings.c \
                    dwarflint-messages.cc dwarflint-messages.h \
                    dwarflint-where.c dwarflint-where.h \
                    dwarflint-config.cc dwarflint-config.h \
-                   dwarflnit-checks.hh
+                   dwarflint-checks.cc dwarflint-checks.hh
 
 readelf_SOURCES = readelf.c dwarfstrings.c
 
diff --git a/src/dwarflint-checks.cc b/src/dwarflint-checks.cc
new file mode 100644 (file)
index 0000000..126446e
--- /dev/null
@@ -0,0 +1,256 @@
+/* Pedantic checking of DWARF files
+   Copyright (C) 2009 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 "dwarflint-checks.hh"
+#include <map>
+#include <sstream>
+
+struct secentry
+{
+  Elf_Data *reldata;   /* Relocation data if any found.  */
+  size_t reltype;      /* SHT_REL or SHT_RELA.  We need this
+                          temporary store to be able to resolve
+                          relocation section appearing before
+                          relocated section.  */
+  size_t secndx;       /* Index into file->sec or 0 if not yet loaded.  */
+  section_id id;       /* Section type.  */
+
+  explicit secentry (section_id a_id = sec_invalid)
+    : reldata (NULL)
+    , reltype (0)
+    , secndx (0)
+    , id (a_id)
+  {}
+};
+
+struct secinfo_map
+  : public std::map <std::string, secentry>
+{
+  secentry *get (const char *name)
+  {
+    iterator it = find (std::string (name));
+    if (it == end ())
+      return NULL;
+    else
+      return &it->second;
+  }
+};
+
+bool
+elf_file_init (struct elf_file *file, Elf *elf)
+{
+  WIPE (*file);
+
+  file->elf = elf;
+  file->ebl = ebl_openbackend (elf);
+
+  if (file->ebl == NULL
+      || gelf_getehdr (elf, &file->ehdr) == NULL)
+    return false;
+
+  file->addr_64 = file->ehdr.e_ident[EI_CLASS] == ELFCLASS64;
+
+  /* Taken from dwarf_begin_elf.c.  */
+  if ((BYTE_ORDER == LITTLE_ENDIAN
+       && file->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
+      || (BYTE_ORDER == BIG_ENDIAN
+         && file->ehdr.e_ident[EI_DATA] == ELFDATA2LSB))
+    file->other_byte_order = true;
+
+  Elf_Scn *reloc_symtab = NULL;
+
+  secinfo_map secinfo;
+#define SEC(n) secinfo[".debug_" #n] = secentry (sec_##n);
+    DEBUGINFO_SECTIONS
+#undef SEC
+
+  /* Now find all necessary debuginfo sections and associated
+     relocation sections.  */
+
+  /* Section 0 is special, skip it.  */
+  REALLOC (file, sec);
+  file->sec[file->size++].id = sec_invalid;
+
+  bool check_rel = true;
+
+  for (Elf_Scn *scn = NULL; (scn = elf_nextscn (elf, scn)); )
+    {
+      REALLOC (file, sec);
+      size_t curndx = file->size++;
+      struct sec *cursec = file->sec + curndx;
+
+      GElf_Shdr *shdr = gelf_getshdr (scn, &cursec->shdr);
+      if (shdr == NULL)
+       {
+       invalid_elf:
+         wr_error (NULL, "Broken ELF.\n");
+         return false;
+       }
+
+      const char *scnname = elf_strptr (elf, file->ehdr.e_shstrndx,
+                                       shdr->sh_name);
+      if (scnname == NULL)
+       goto invalid_elf;
+
+      if (!address_aligned (shdr->sh_addr, shdr->sh_addralign))
+       {
+         std::ostringstream s;
+         s << "Base address of section " << scnname << ", "
+           << "0x" << std::hex << shdr->sh_addr
+           << ", should have an alignment of "
+           << std::dec << shdr->sh_addralign;
+         wr_error (NULL, "%s\n", s.str ().c_str ());
+       }
+
+      secentry *entry = secinfo.get (scnname);
+      cursec->scn = scn;
+      cursec->id = entry != NULL ? entry->id : sec_invalid;
+      cursec->name = scnname;
+      cursec->rel = (struct relocation_data){NULL, SHT_NULL, NULL, 0, 0, 0};
+
+      /* Dwarf section.  */
+      if (entry != NULL)
+       {
+         if (unlikely (entry->secndx != 0))
+           wr_error (NULL, "Multiple occurrences of section %s.\n", scnname);
+         else
+           {
+             /* Haven't seen a section of that name yet.  */
+             cursec->data = elf_getdata (scn, NULL);
+             if (cursec->data == NULL || cursec->data->d_buf == NULL)
+               /* Don't print out a warning, we'll get to that in
+                  process_file.  */
+               cursec->data = NULL;
+             entry->secndx = curndx;
+           }
+       }
+      /* Relocation section.  */
+      else if (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL)
+       {
+         /* Get data of section that this REL(A) section relocates.  */
+         Elf_Scn *relocated_scn = elf_getscn (elf, shdr->sh_info);
+         Elf_Scn *symtab_scn = elf_getscn (elf, shdr->sh_link);
+         if (relocated_scn == NULL || symtab_scn == NULL)
+           goto invalid_elf;
+
+         GElf_Shdr relocated_shdr_mem;
+         GElf_Shdr *relocated_shdr = gelf_getshdr (relocated_scn,
+                                                   &relocated_shdr_mem);
+         if (relocated_shdr == NULL)
+           goto invalid_elf;
+
+         const char *relocated_scnname
+           = elf_strptr (elf, file->ehdr.e_shstrndx,
+                         relocated_shdr->sh_name);
+
+         secentry *relocated = secinfo.get (relocated_scnname);
+
+         if (relocated != NULL)
+           {
+             if (relocated->reldata != NULL)
+               wr_error (NULL,
+                         "Several relocation sections for debug section %s."
+                         "  Ignoring %s.\n",
+                         relocated_scnname, scnname);
+             else
+               {
+                 relocated->reldata = elf_getdata (scn, NULL);
+                 if (unlikely (relocated->reldata == NULL
+                               || relocated->reldata->d_buf == NULL))
+                   {
+                     wr_error (NULL,
+                               "Data-less relocation section %s.\n", scnname);
+                     relocated->reldata = NULL;
+                   }
+                 else
+                   relocated->reltype = shdr->sh_type;
+               }
+
+             if (reloc_symtab == NULL)
+               reloc_symtab = symtab_scn;
+             else if (reloc_symtab != symtab_scn)
+               wr_error (NULL,
+                         "Relocation sections use multiple symbol tables.\n");
+           }
+       }
+    }
+
+  for (secinfo_map::iterator it = secinfo.begin (); it != secinfo.end (); ++it)
+    if (it->second.secndx != 0)
+      file->debugsec[it->second.id] = file->sec + it->second.secndx;
+
+  if (check_rel)
+    {
+      Elf_Data *reloc_symdata = NULL;
+      if (reloc_symtab != NULL)
+       {
+         reloc_symdata = elf_getdata (reloc_symtab, NULL);
+         if (reloc_symdata == NULL)
+           /* Not a show stopper, we can check a lot of stuff even
+              without a symbol table.  */
+             wr_error (NULL,
+                       "Couldn't obtain symtab data.\n");
+       }
+
+      /* Check relocation sections that we've got.  */
+      for (secinfo_map::iterator it = secinfo.begin (); it != secinfo.end (); ++it)
+       {
+         secentry *cur = &it->second;
+         if (cur->secndx != 0 && cur->reldata != NULL)
+           {
+             struct sec *sec = file->sec + cur->secndx;
+             sec->rel.type = cur->reltype;
+             if (sec->data == NULL)
+               {
+                 where wh = WHERE (sec->id, NULL);
+                 wr_error (&wh,
+                           ": this data-less section has a relocation section.\n");
+               }
+             else if (read_rel (file, sec, cur->reldata, file->addr_64))
+               sec->rel.symdata = reloc_symdata;
+           }
+       }
+
+      if (secentry *str = secinfo.get (".debug_str"))
+       if (str->reldata != NULL)
+         {
+           where wh = WHERE (sec_str, NULL);
+           wr_message (mc_impact_2 | mc_elf, &wh,
+                       ": there's a relocation section associated with this section.\n");
+         }
+    }
+
+  return true;
+}
+
+section_base::section_base (__attribute__ ((unused)) dwarflint &lint,
+                           __attribute__ ((unused)) section_id secid)
+{
+  
+}
index 37f569b20ab8c51e20e6ab809b690a7444382c29..b22d02a61117977a10c4e3939e245ee7d6b52642 100644 (file)
@@ -1,10 +1,11 @@
 #ifndef DWARFLINT_CHECKS_HH
 #define DWARFLINT_CHECKS_HH
 
-#include <iostream>
 #include <stdexcept>
 #include <string>
+#include <iostream>
 #include "dwarflint-where.h"
+#include "dwarflint-low.h"
 #include "dwarflint-main.hh"
 
 struct check_base
@@ -14,8 +15,7 @@ struct check_base
   {
     failed (std::string const &msg)
       : std::runtime_error (msg)
-    {
-    }
+    {}
   };
 };
 
@@ -30,20 +30,6 @@ public:
   }
 };
 
-template <class T>
-struct reg
-  : public dwarflint::check_registrar::item
-{
-  reg ()
-  {
-    dwarflint::check_registrar::inst ()->add (this);
-  }
-
-  virtual void run (dwarflint &lint) {
-    lint.toplev_check <T> ();
-  }
-};
-
 template <class T>
 void
 toplev_check (dwarflint &lint)
@@ -58,4 +44,36 @@ toplev_check (dwarflint &lint)
     }
 }
 
+template <class T>
+struct reg
+  : public dwarflint::check_registrar::item
+{
+  reg ()
+  {
+    dwarflint::check_registrar::inst ()->add (this);
+  }
+
+  virtual void run (dwarflint &lint)
+  {
+    toplev_check <T> (lint);
+  }
+};
+
+struct section_base
+  : public check<section_base>
+  , public sec
+{
+  section_base (dwarflint &lint, section_id secid);
+};
+
+template<section_id sec_id>
+class section
+  : public section_base
+{
+public:
+  explicit section (dwarflint &lint)
+    : section_base (lint, sec_id)
+  {}
+};
+
 #endif//DWARFLINT_CHECKS_HH
index 6f099f696762820825f3b7f1469a47ec0af602fa..822fb84e0fb33bc82c90670c81c682fae85b7d92 100644 (file)
@@ -180,219 +180,18 @@ static bool check_location_expression (struct elf_file *file,
                                       size_t length,
                                       struct where *wh);
 
-static bool read_rel (struct elf_file *file,
-                     struct sec *sec,
-                     Elf_Data *reldata,
-                     bool elf_64);
-
-static bool
+bool
 address_aligned (uint64_t addr, uint64_t align)
 {
   return align < 2 || (addr % align == 0);
 }
 
-static bool
+bool
 necessary_alignment (uint64_t start, uint64_t length, uint64_t align)
 {
   return address_aligned (start + length, align) && length < align;
 }
 
-bool
-elf_file_init (struct elf_file *file, Elf *elf)
-{
-  WIPE (*file);
-
-  file->elf = elf;
-  file->ebl = ebl_openbackend (elf);
-
-  if (file->ebl == NULL
-      || gelf_getehdr (elf, &file->ehdr) == NULL)
-    return false;
-
-  file->addr_64 = file->ehdr.e_ident[EI_CLASS] == ELFCLASS64;
-
-  /* Taken from dwarf_begin_elf.c.  */
-  if ((BYTE_ORDER == LITTLE_ENDIAN
-       && file->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)
-      || (BYTE_ORDER == BIG_ENDIAN
-         && file->ehdr.e_ident[EI_DATA] == ELFDATA2LSB))
-    file->other_byte_order = true;
-
-  struct secinfo
-  {
-    const char *name;
-    Elf_Data *reldata;  /* Relocation data if any found.  */
-    size_t reltype;    /* SHT_REL or SHT_RELA.  We need this
-                          temporary store to be able to resolve
-                          relocation section appearing before
-                          relocated section.  */
-    size_t secndx;     /* Index into file->sec or 0 if not yet loaded.  */
-    enum section_id id;        /* Section type.  */
-  };
-  struct secinfo secinfo[] = {
-#define SEC(n) {".debug_" #n, NULL, 0, 0, sec_##n},
-    DEBUGINFO_SECTIONS
-#undef SEC
-  };
-
-  Elf_Scn *reloc_symtab = NULL;
-
-  struct secinfo *find_secentry (const char *secname)
-  {
-    for (size_t i = 0; i < sizeof (secinfo) / sizeof (*secinfo); ++i)
-      if (strcmp (secinfo[i].name, secname) == 0)
-       return secinfo + i;
-    return NULL;
-  }
-
-  /* Now find all necessary debuginfo sections and associated
-     relocation sections.  */
-
-  /* Section 0 is special, skip it.  */
-  REALLOC (file, sec);
-  file->sec[file->size++].id = sec_invalid;
-
-  bool check_rel = true;
-
-  for (Elf_Scn *scn = NULL; (scn = elf_nextscn (elf, scn)); )
-    {
-      REALLOC (file, sec);
-      size_t curndx = file->size++;
-      struct sec *cursec = file->sec + curndx;
-
-      GElf_Shdr *shdr = gelf_getshdr (scn, &cursec->shdr);
-      if (shdr == NULL)
-       {
-       invalid_elf:
-         wr_error (NULL, "Broken ELF.\n");
-         return false;
-       }
-
-      const char *scnname = elf_strptr (elf, file->ehdr.e_shstrndx,
-                                       shdr->sh_name);
-      if (scnname == NULL)
-       goto invalid_elf;
-
-      if (!address_aligned (shdr->sh_addr, shdr->sh_addralign))
-       wr_error (NULL, "Base address of section %s, %#" PRIx64
-                 ", should have an alignment of %" PRId64 ".\n",
-                 scnname, shdr->sh_addr, shdr->sh_addralign);
-
-      struct secinfo *secentry = find_secentry (scnname);
-      cursec->scn = scn;
-      cursec->id = secentry != NULL ? secentry->id : sec_invalid;
-      cursec->name = scnname;
-      cursec->rel = (struct relocation_data){NULL, SHT_NULL, NULL, 0, 0, 0};
-
-      /* Dwarf section.  */
-      if (secentry != NULL)
-       {
-         if (unlikely (secentry->secndx != 0))
-           wr_error (NULL, "Multiple occurrences of section %s.\n", scnname);
-         else
-           {
-             /* Haven't seen a section of that name yet.  */
-             cursec->data = elf_getdata (scn, NULL);
-             if (cursec->data == NULL || cursec->data->d_buf == NULL)
-               /* Don't print out a warning, we'll get to that in
-                  process_file.  */
-               cursec->data = NULL;
-             secentry->secndx = curndx;
-           }
-       }
-      /* Relocation section.  */
-      else if (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL)
-       {
-         /* Get data of section that this REL(A) section relocates.  */
-         Elf_Scn *relocated_scn = elf_getscn (elf, shdr->sh_info);
-         Elf_Scn *symtab_scn = elf_getscn (elf, shdr->sh_link);
-         if (relocated_scn == NULL || symtab_scn == NULL)
-           goto invalid_elf;
-
-         GElf_Shdr relocated_shdr_mem;
-         GElf_Shdr *relocated_shdr = gelf_getshdr (relocated_scn,
-                                                   &relocated_shdr_mem);
-         if (relocated_shdr == NULL)
-           goto invalid_elf;
-
-         const char *relocated_scnname
-           = elf_strptr (elf, file->ehdr.e_shstrndx,
-                         relocated_shdr->sh_name);
-
-         struct secinfo *relocated
-           = find_secentry (relocated_scnname);
-
-         if (relocated != NULL)
-           {
-             if (relocated->reldata != NULL)
-               wr_error (NULL,
-                         "Several relocation sections for debug section %s."
-                         "  Ignoring %s.\n",
-                         relocated_scnname, scnname);
-             else
-               {
-                 relocated->reldata = elf_getdata (scn, NULL);
-                 if (unlikely (relocated->reldata == NULL
-                               || relocated->reldata->d_buf == NULL))
-                   {
-                     wr_error (NULL,
-                               "Data-less relocation section %s.\n", scnname);
-                     relocated->reldata = NULL;
-                   }
-                 else
-                   relocated->reltype = shdr->sh_type;
-               }
-
-             if (reloc_symtab == NULL)
-               reloc_symtab = symtab_scn;
-             else if (reloc_symtab != symtab_scn)
-               wr_error (NULL,
-                         "Relocation sections use multiple symbol tables.\n");
-           }
-       }
-    }
-
-  for (size_t i = 0; i < sizeof (secinfo) / sizeof (*secinfo); ++i)
-    if (secinfo[i].secndx != 0)
-      file->debugsec[secinfo[i].id] = file->sec + secinfo[i].secndx;
-
-  if (check_rel)
-    {
-      Elf_Data *reloc_symdata = NULL;
-      if (reloc_symtab != NULL)
-       {
-         reloc_symdata = elf_getdata (reloc_symtab, NULL);
-         if (reloc_symdata == NULL)
-           /* Not a show stopper, we can check a lot of stuff even
-              without a symbol table.  */
-             wr_error (NULL,
-                       "Couldn't obtain symtab data.\n");
-       }
-
-      /* Check relocation sections that we've got.  */
-      for (size_t i = 0; i < sizeof (secinfo) / sizeof (*secinfo); ++i)
-       {
-         struct secinfo *cur = secinfo + i;
-         if (cur->secndx != 0 && cur->reldata != NULL)
-           {
-             struct sec *sec = file->sec + cur->secndx;
-             sec->rel.type = cur->reltype;
-             if (sec->data == NULL)
-               wr_error (&WHERE (sec->id, NULL),
-                         ": this data-less section has a relocation section.\n");
-             else if (read_rel (file, sec, cur->reldata, file->addr_64))
-               sec->rel.symdata = reloc_symdata;
-           }
-       }
-
-      if (find_secentry (".debug_str")->reldata != NULL)
-       wr_message (mc_impact_2 | mc_elf, &WHERE (sec_str, NULL),
-                   ": there's a relocation section associated with this section.\n");
-    }
-
-  return true;
-}
-
 static bool
 checked_read_uleb128 (struct read_ctx *ctx, uint64_t *ret,
                      struct where *where, const char *what)
@@ -3656,7 +3455,7 @@ get_rel_or_rela (Elf_Data *data, int ndx,
     }
 }
 
-static bool
+bool
 read_rel (struct elf_file *file,
          struct sec *sec,
          Elf_Data *reldata,
index cecd6ab5d5b0f8ad2abb12cb406db8f722e2a73a..34e246f5c90d42daa828a00cfe085585f27af82a 100644 (file)
@@ -105,11 +105,16 @@ extern "C"
   extern bool check_range_out_of_scope (struct hl_ctx *hlctx);
   extern bool elf_file_init (struct elf_file *file, Elf *elf);
 
-  // xxx will go away
+  // xxx some of that will go away
   extern struct abbrev_table * abbrev_table_load (struct read_ctx *ctx);
   extern void abbrev_table_free (struct abbrev_table *abbr);
   extern struct abbrev *abbrev_table_find_abbrev (struct abbrev_table *abbrevs,
                                                  uint64_t abbrev_code);
+  extern bool read_rel (struct elf_file *file, struct sec *sec,
+                       Elf_Data *reldata, bool elf_64);
+  extern bool address_aligned (uint64_t addr, uint64_t align);
+  extern bool necessary_alignment (uint64_t start, uint64_t length,
+                                  uint64_t align);
 
   struct section_coverage
   {
index 249da8c15c26de4efcf3bce45ab432ec31f66ee5..b9706cb6dfa9671464c0a6b4269732b287440289 100644 (file)
@@ -39,6 +39,7 @@
 #include "dwarflint-config.h"
 #include "dwarflint-main.hh"
 #include "dwarflint-readctx.h"
+#include "dwarflint-checks.hh"
 
 /* Bug report address.  */
 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
index 245387aa97ad2abf78c26fb8bd647af24c2c7437..7aa3ee2ec18489ffde80f27742b604e5aa6e6351 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef DWARFLINT_WHERE_H
+#define DWARFLINT_WHERE_H
+
 #include <stdint.h>
 #include <stdlib.h>
 
@@ -77,3 +80,5 @@ extern "C"
 #ifdef __cplusplus
 }
 #endif
+
+#endif//DWARFLINT_WHERE_H