]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Move more checks to the new dependency infrastructure
authorPetr Machata <pmachata@redhat.com>
Tue, 20 Oct 2009 14:02:14 +0000 (16:02 +0200)
committerPetr Machata <pmachata@redhat.com>
Wed, 18 Aug 2010 12:55:11 +0000 (14:55 +0200)
src/Makefile.am
src/dwarflint-checks-low.cc [new file with mode: 0644]
src/dwarflint-checks-low.hh [new file with mode: 0644]
src/dwarflint-checks.cc
src/dwarflint-checks.hh
src/dwarflint-low.c
src/dwarflint-low.h
src/dwarflint-main.cc
src/dwarflint-main.hh
src/dwarflint-readctx.c
src/dwarflint-readctx.h

index 74ed80f4cf2781839774a19d4b33194e3d5a57d1..d89fb8e7ff9f0a61a377e9f766746c9e3b3aaabb 100644 (file)
@@ -87,7 +87,8 @@ dwarflint_SOURCES = dwarfstrings.c \
                    dwarflint-messages.cc dwarflint-messages.h \
                    dwarflint-where.c dwarflint-where.h \
                    dwarflint-config.cc dwarflint-config.h \
-                   dwarflint-checks.cc dwarflint-checks.hh
+                   dwarflint-checks.hh \
+                   dwarflint-checks-low.cc dwarflint-checks-low.hh
 
 readelf_SOURCES = readelf.c dwarfstrings.c
 
diff --git a/src/dwarflint-checks-low.cc b/src/dwarflint-checks-low.cc
new file mode 100644 (file)
index 0000000..2850456
--- /dev/null
@@ -0,0 +1,315 @@
+/* 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-low.hh"
+#include "dwarflint-low.h"
+#include <map>
+#include <sstream>
+#include <cstring>
+
+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)
+{
+  memset (file, 0, sizeof (*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;
+}
+
+load_sections::load_sections (dwarflint &lint)
+{
+  elf_file_init (&file, lint.elf ());
+}
+
+sec &
+section_base::get_sec_or_throw (section_id secid)
+{
+  if (sec *s = sections->file.debugsec[secid])
+    return *s;
+
+  where wh = WHERE (secid, NULL);
+  std::stringstream ss;
+  ss << where_fmt (&wh) << ": data not found.";
+  throw check_base::failed (ss.str ());
+}
+
+section_base::section_base (dwarflint &lint, section_id secid)
+  : sections (lint.check (sections))
+  , sect (get_sec_or_throw (secid))
+  , file (sections->file)
+{
+}
+
+check_debug_abbrev::check_debug_abbrev (dwarflint &lint)
+  : _m_sec_abbr (lint.check (_m_sec_abbr))
+{
+  read_ctx ctx;
+  read_ctx_init (&ctx, _m_sec_abbr->sect.data,
+                _m_sec_abbr->file.other_byte_order);
+
+  /* xxx wrap C routine before proper loading is in place.  */
+  abbrev_table *chain = abbrev_table_load (&ctx);
+  if (chain == NULL)
+    throw check_base::failed (""); // xxx
+  for (abbrev_table *it = chain; it != NULL; it = it->next)
+    abbrevs[it->offset] = *it;
+  // abbrev_table_free (chain); xxx
+  abbrev_chain = chain;
+}
+
+check_debug_info::check_debug_info (dwarflint &lint)
+  : _m_sec_info (lint.check (_m_sec_info))
+  , _m_sec_abbrev (lint.check (_m_sec_abbrev))
+  , _m_sec_str (lint.check (_m_sec_str))
+  , _m_abbrevs (lint.check (_m_abbrevs))
+{
+  memset (&cu_cov, 0, sizeof (cu_cov));
+
+  /* xxx wrap C routine before proper loading is in place.  */
+  cu *chain = check_info_structural
+    (&_m_sec_info->file, &_m_sec_info->sect,
+     _m_abbrevs->abbrev_chain, _m_sec_str->sect.data, &cu_cov);
+
+  if (chain == NULL)
+    throw check_base::failed (""); // xxx
+
+  for (cu *cu = chain; cu != NULL; cu = cu->next)
+    cus.push_back (*cu);
+  // cu_free (chain); xxx
+  cu_chain = chain;
+}
diff --git a/src/dwarflint-checks-low.hh b/src/dwarflint-checks-low.hh
new file mode 100644 (file)
index 0000000..5872570
--- /dev/null
@@ -0,0 +1,62 @@
+#include "dwarflint-checks.hh"
+#include "dwarflint-low.h"
+
+class load_sections
+  : public check<load_sections>
+{
+public:
+  elf_file file;
+  explicit load_sections (dwarflint &lint);
+};
+
+class section_base
+{
+  load_sections *sections;
+  sec &get_sec_or_throw (section_id secid);
+public:
+  sec &sect;
+  elf_file &file;
+  section_base (dwarflint &lint, section_id secid);
+};
+
+template<section_id sec_id>
+class section
+  : public section_base
+  , public check<section<sec_id> >
+{
+public:
+  explicit section (dwarflint &lint)
+    : section_base (lint, sec_id)
+  {}
+};
+
+class check_debug_abbrev
+  : public check<check_debug_abbrev>
+{
+  section<sec_abbrev> *_m_sec_abbr;
+
+public:
+  explicit check_debug_abbrev (dwarflint &lint);
+
+  // offset -> abbreviations
+  std::map < ::Dwarf_Off, abbrev_table> abbrevs;
+  struct abbrev_table *abbrev_chain; // xxx
+};
+static reg <check_debug_abbrev> reg_debug_abbrev;
+
+class check_debug_info
+  : public check<check_debug_info>
+{
+  section<sec_info> *_m_sec_info;
+  section<sec_abbrev> *_m_sec_abbrev;
+  section<sec_str> *_m_sec_str;
+  check_debug_abbrev *_m_abbrevs;
+
+public:
+  cu_coverage cu_cov;
+  std::vector <cu> cus;
+  cu *cu_chain; // xxx
+
+  explicit check_debug_info (dwarflint &lint);
+};
+static reg <check_debug_info> reg_debug_info;
index 126446e0c993a29f18add13b8e55f899e4d1a338..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,256 +0,0 @@
-/* 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 b22d02a61117977a10c4e3939e245ee7d6b52642..4ca86e142d4ff37928686a48e9028e1d227ddcfe 100644 (file)
@@ -5,7 +5,6 @@
 #include <string>
 #include <iostream>
 #include "dwarflint-where.h"
-#include "dwarflint-low.h"
 #include "dwarflint-main.hh"
 
 struct check_base
@@ -59,21 +58,4 @@ struct reg
   }
 };
 
-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 822fb84e0fb33bc82c90670c81c682fae85b7d92..502324c680e8af4dba8949212bd34e939893b22d 100644 (file)
@@ -69,56 +69,11 @@ check_category (enum message_category cat)
 /* Functions and data structures related to raw (i.e. unassisted by
    libdw) Dwarf abbreviation handling.  */
 
-struct abbrev
-{
-  uint64_t code;
-  struct where where;
-
-  /* Attributes.  */
-  struct abbrev_attrib
-  {
-    struct where where;
-    uint16_t name;
-    uint8_t form;
-  } *attribs;
-  size_t size;
-  size_t alloc;
-
-  /* While ULEB128 can hold numbers > 32bit, these are not legal
-     values of many enum types.  So just use as large type as
-     necessary to cover valid values.  */
-  uint16_t tag;
-  bool has_children;
-
-  /* Whether some DIE uses this abbrev.  */
-  bool used;
-};
-
-struct abbrev_table
-{
-  struct abbrev_table *next;
-  struct abbrev *abbr;
-  uint64_t offset;
-  size_t size;
-  size_t alloc;
-  bool used;           /* There are CUs using this table.  */
-  bool skip_check;     /* There were errors during loading one of the
-                          CUs that use this table.  Check for unused
-                          abbrevs should be skipped.  */
-};
-
 /* Functions and data structures for address record handling.  We use
    that to check that all DIE references actually point to an existing
    die, not somewhere mid-DIE, where it just happens to be
    interpretable as a DIE.  */
 
-struct addr_record
-{
-  size_t size;
-  size_t alloc;
-  uint64_t *addrs;
-};
-
 static size_t addr_record_find_addr (struct addr_record *ar, uint64_t addr);
 static bool addr_record_has_addr (struct addr_record *ar, uint64_t addr);
 static void addr_record_add (struct addr_record *ar, uint64_t addr);
@@ -130,46 +85,9 @@ static void addr_record_free (struct addr_record *ar);
    the above, this is not stored as sorted set, but simply as an array
    of records, because duplicates are unlikely.  */
 
-struct ref
-{
-  uint64_t addr; // Referree address
-  struct where who;  // Referrer
-};
-
-struct ref_record
-{
-  size_t size;
-  size_t alloc;
-  struct ref *refs;
-};
-
 static void ref_record_add (struct ref_record *rr, uint64_t addr, struct where *referrer);
 static void ref_record_free (struct ref_record *rr);
 
-
-/* Functions and data structures for CU handling.  */
-
-struct cu
-{
-  struct cu *next;
-  uint64_t offset;
-  uint64_t cudie_offset;
-  uint64_t length;
-  uint64_t low_pc;              // DW_AT_low_pc value of CU DIE, -1 if not present.
-  struct addr_record die_addrs; // Addresses where DIEs begin in this CU.
-  struct ref_record die_refs;   // DIE references into other CUs from this CU.
-  struct ref_record loc_refs;   // references into .debug_loc from this CU.
-  struct ref_record range_refs; // references into .debug_ranges from this CU.
-  struct ref_record line_refs; // references into .debug_line from this CU.
-  struct where where;           // Where was this section defined.
-  int address_size;             // Address size in bytes on the target machine.
-  int offset_size;             // Offset size in this CU.
-  int version;                 // CU version
-  bool has_arange;              // Whether we saw arange section pointing to this CU.
-  bool has_pubnames;            // Likewise for pubnames.
-  bool has_pubtypes;            // Likewise for pubtypes.
-};
-
 static struct cu *cu_find_cu (struct cu *cu_chain, uint64_t offset);
 
 static bool check_location_expression (struct elf_file *file,
@@ -2286,7 +2204,7 @@ check_info_structural (struct elf_file *file,
                       struct cu_coverage *cu_coverage)
 {
   struct read_ctx ctx;
-  read_ctx_init (&ctx, file, sec->data);
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
 
   struct ref_record die_refs;
   WIPE (die_refs);
@@ -2548,7 +2466,7 @@ check_aranges_structural (struct elf_file *file,
                          struct coverage *coverage)
 {
   struct read_ctx ctx;
-  read_ctx_init (&ctx, file, sec->data);
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
 
   bool retval = true;
 
@@ -2791,7 +2709,7 @@ check_pub_structural (struct elf_file *file,
                      struct cu *cu_chain)
 {
   struct read_ctx ctx;
-  read_ctx_init (&ctx, file, sec->data);
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
   bool retval = true;
 
   while (!read_ctx_eof (&ctx))
@@ -3129,7 +3047,7 @@ check_loc_or_range_ref (struct elf_file *file,
   assert (coverage != NULL);
 
   struct read_ctx ctx;
-  read_ctx_init (&ctx, parent_ctx->file, parent_ctx->data);
+  read_ctx_init (&ctx, parent_ctx->data, file->other_byte_order);
   if (!read_ctx_skip (&ctx, addr))
     {
       wr_error (wh, ": invalid reference outside the section "
@@ -3323,7 +3241,7 @@ check_loc_or_range_structural (struct elf_file *file,
   assert (cu_chain != NULL);
 
   struct read_ctx ctx;
-  read_ctx_init (&ctx, file, sec->data);
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
 
   bool retval = true;
 
@@ -3466,7 +3384,7 @@ read_rel (struct elf_file *file,
   bool is_rela = sec->rel.type == SHT_RELA;
 
   struct read_ctx ctx;
-  read_ctx_init (&ctx, file, sec->data);
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
 
   size_t entrysize
     = elf_64
@@ -3559,12 +3477,12 @@ read_rel (struct elf_file *file,
       uint64_t value;
       if (width == 4)
        value = dwarflint_read_4ubyte_unaligned
-         (file, sec->data->d_buf + cur->offset);
+         (sec->data->d_buf + cur->offset, file->other_byte_order);
       else
        {
          assert (width == 8);
          value = dwarflint_read_8ubyte_unaligned
-           (file, sec->data->d_buf + cur->offset);
+           (sec->data->d_buf + cur->offset, file->other_byte_order);
        }
 
       if (is_rela)
@@ -3598,7 +3516,7 @@ check_line_structural (struct elf_file *file,
                       struct cu *cu_chain)
 {
   struct read_ctx ctx;
-  read_ctx_init (&ctx, file, sec->data);
+  read_ctx_init (&ctx, sec->data, file->other_byte_order);
   bool retval = true;
 
   struct addr_record line_tables;
index 34e246f5c90d42daa828a00cfe085585f27af82a..3e60389a12a66bcb35bb609c468269bccc818c04 100644 (file)
@@ -94,7 +94,6 @@ extern "C"
     bool addr_64;      /* True if it's 64-bit Elf.  */
     bool other_byte_order; /* True if the file has a byte order
                              different from the host.  */
-    // xxx add CUs etc here?
   };
 
   /* Check that .debug_aranges and .debug_ranges match.  */
@@ -208,6 +207,85 @@ extern "C"
                                struct section_coverage *sco, void *data);
 
 
+  struct abbrev
+  {
+    uint64_t code;
+    struct where where;
+
+    /* Attributes.  */
+    struct abbrev_attrib
+    {
+      struct where where;
+      uint16_t name;
+      uint8_t form;
+    } *attribs;
+    size_t size;
+    size_t alloc;
+
+    /* While ULEB128 can hold numbers > 32bit, these are not legal
+       values of many enum types.  So just use as large type as
+       necessary to cover valid values.  */
+    uint16_t tag;
+    bool has_children;
+
+    /* Whether some DIE uses this abbrev.  */
+    bool used;
+  };
+
+  struct abbrev_table
+  {
+    struct abbrev_table *next;
+    struct abbrev *abbr;
+    uint64_t offset;
+    size_t size;
+    size_t alloc;
+    bool used;         /* There are CUs using this table.  */
+    bool skip_check;   /* There were errors during loading one of the
+                          CUs that use this table.  Check for unused
+                          abbrevs should be skipped.  */
+  };
+
+  struct ref
+  {
+    uint64_t addr; // Referree address
+    struct where who;  // Referrer
+  };
+
+  struct ref_record
+  {
+    size_t size;
+    size_t alloc;
+    struct ref *refs;
+  };
+
+  struct addr_record
+  {
+    size_t size;
+    size_t alloc;
+    uint64_t *addrs;
+  };
+
+  struct cu
+  {
+    struct cu *next;
+    uint64_t offset;
+    uint64_t cudie_offset;
+    uint64_t length;
+    uint64_t low_pc;              // DW_AT_low_pc value of CU DIE, -1 if not present.
+    struct addr_record die_addrs; // Addresses where DIEs begin in this CU.
+    struct ref_record die_refs;   // DIE references into other CUs from this CU.
+    struct ref_record loc_refs;   // references into .debug_loc from this CU.
+    struct ref_record range_refs; // references into .debug_ranges from this CU.
+    struct ref_record line_refs;       // references into .debug_line from this CU.
+    struct where where;           // Where was this section defined.
+    int address_size;             // Address size in bytes on the target machine.
+    int offset_size;           // Offset size in this CU.
+    int version;                       // CU version
+    bool has_arange;              // Whether we saw arange section pointing to this CU.
+    bool has_pubnames;            // Likewise for pubnames.
+    bool has_pubtypes;            // Likewise for pubtypes.
+  };
+
 #ifdef __cplusplus
 }
 #endif
index b9706cb6dfa9671464c0a6b4269732b287440289..131649387146f7e619ba14b969bdf1b7590b9f82 100644 (file)
@@ -40,6 +40,7 @@
 #include "dwarflint-main.hh"
 #include "dwarflint-readctx.h"
 #include "dwarflint-checks.hh"
+#include "dwarflint-checks-low.hh" // xxx
 
 /* Bug report address.  */
 const char *argp_program_bug_address = PACKAGE_BUGREPORT;
@@ -257,68 +258,32 @@ layout_rel_file (Elf *elf)
   return 0;
 }
 
-dwarflint::dwarflint (Elf *elf)
+dwarflint::dwarflint (Elf *a_elf)
+  : _m_elf (a_elf)
 {
   check_registrar::inst ()->enroll (*this);
 
   struct elf_file file;
-  if (!elf_file_init (&file, elf))
+  if (!elf_file_init (&file, a_elf))
     return;
 
-  struct abbrev_table *abbrev_chain = NULL;
-  struct cu *cu_chain = NULL;
-  struct read_ctx ctx;
+  check_debug_info *check_info = check (check_info);
+  // xxx check_expected_trees
+  cu *cu_chain = check_info->cu_chain;
+  read_ctx ctx;
 
   /* Don't attempt to do high-level checks if we couldn't initialize
      high-level context.  The wrapper takes care of printing out error
      messages if any.  */
-  struct hl_ctx *hlctx = do_high_level ? hl_ctx_new (elf) : NULL;
+  struct hl_ctx *hlctx = do_high_level ? hl_ctx_new (a_elf) : NULL;
 
 #define SEC(sec) (file.debugsec[sec_##sec])
 #define HAS_SEC(sec) (SEC(sec) != NULL && SEC(sec)->data != NULL)
 
-  if (likely (HAS_SEC(abbrev)))
-    {
-      read_ctx_init (&ctx, &file, SEC(abbrev)->data);
-      abbrev_chain = abbrev_table_load (&ctx);
-    }
-  else if (!tolerate_nodebug)
-    /* Hard error, not a message.  We can't debug without this.  */
-    wr_error (NULL, ".debug_abbrev data not found.\n");
-
-  Elf_Data *str_data = NULL;
-  if (SEC(str) != NULL)
-    {
-      str_data = SEC(str)->data;
-      if (str_data == NULL)
-       {
-         where wh = WHERE (sec_str, NULL);
-         wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf, &wh,
-                     ": the section is present but empty.\n");
-       }
-    }
-
-  struct cu_coverage *cu_coverage = NULL;
-  if (abbrev_chain != NULL)
-    {
-      if (likely (HAS_SEC(info)))
-       {
-         cu_coverage
-           = (struct cu_coverage *)calloc (1, sizeof (struct cu_coverage));
-         cu_chain = check_info_structural (&file, SEC(info), abbrev_chain,
-                                           str_data, cu_coverage);
-         if (cu_chain != NULL && hlctx != NULL)
-           check_expected_trees (hlctx);
-       }
-      else if (!tolerate_nodebug)
-       /* Hard error, not a message.  We can't debug without this.  */
-       wr_error (NULL, ".debug_info data not found.\n");
-    }
-
   bool ranges_sound;
   if (HAS_SEC(ranges) && cu_chain != NULL)
     ranges_sound = check_loc_or_range_structural (&file, SEC(ranges),
-                                                 cu_chain, cu_coverage);
+                                                 cu_chain, &check_info->cu_cov);
   else
     ranges_sound = false;
 
@@ -329,13 +294,13 @@ dwarflint::dwarflint (Elf *elf)
 
   if (HAS_SEC(aranges))
     {
-      read_ctx_init (&ctx, &file, SEC(aranges)->data);
+      read_ctx_init (&ctx, SEC(aranges)->data, file.other_byte_order);
 
       /* If ranges were needed and not loaded, don't pass them down
         for CU/aranges coverage analysis. */
       struct coverage *cov
-       = (cu_coverage != NULL
-          && cu_coverage->need_ranges) ? NULL : &cu_coverage->cov;
+       = check_info->cu_cov.need_ranges ? NULL
+       : &check_info->cu_cov.cov;
 
       if (check_aranges_structural (&file, SEC(aranges), cu_chain, cov)
          && ranges_sound && hlctx != NULL && !be_tolerant && !be_gnu)
@@ -370,7 +335,6 @@ dwarflint::dwarflint (Elf *elf)
     }
 
   cu_free (cu_chain);
-  abbrev_table_free (abbrev_chain);
   if (file.ebl != NULL)
     ebl_closebackend (file.ebl);
   free (file.sec);
index a6cd8b89ddfe9d1520fb0cf678176dd548854938..d5a80744c1c35632d82ce252aa07541e65deeae0 100644 (file)
@@ -4,11 +4,13 @@
 #include <map>
 #include <vector>
 #include <stdexcept>
+#include "../libelf/libelf.h"
 
 class dwarflint
 {
   typedef std::map <void const *, class check_base *> check_map;
   check_map _m_checks;
+  Elf * _m_elf;
 
 public:
   struct check_registrar
@@ -42,6 +44,7 @@ public:
   };
 
   dwarflint (Elf *elf);
+  Elf *elf () { return _m_elf; }
 
   template <class T>
   T *
@@ -63,7 +66,7 @@ public:
 
   template <class T>
   T *
-  check (T *fake)
+  check (__attribute__ ((unused)) T *fake)
   {
     return check<T> ();
   }
index 3133f0acbec530a92fb94ec300768ded9741e0fd..b1e3296d04fa4165f519950c445142c5a5ada262 100644 (file)
@@ -44,10 +44,10 @@ union unaligned
   } __attribute__ ((packed));
 
 static uint16_t
-read_2ubyte_unaligned (struct elf_file *file, const void *p)
+read_2ubyte_unaligned (const void *p, bool other_byte_order)
 {
   const union unaligned *up = p;
-  if (file->other_byte_order)
+  if (other_byte_order)
     return bswap_16 (up->u2);
   return up->u2;
 }
@@ -55,52 +55,52 @@ read_2ubyte_unaligned (struct elf_file *file, const void *p)
 /* Prefix with dwarflint_ for export, so that it doesn't get confused
    with functions and macros in memory-access.h.  */
 uint32_t
-dwarflint_read_4ubyte_unaligned (struct elf_file *file, const void *p)
+dwarflint_read_4ubyte_unaligned (const void *p, bool other_byte_order)
 {
   const union unaligned *up = p;
-  if (file->other_byte_order)
+  if (other_byte_order)
     return bswap_32 (up->u4);
   return up->u4;
 }
 
 uint64_t
-dwarflint_read_8ubyte_unaligned (struct elf_file *file, const void *p)
+dwarflint_read_8ubyte_unaligned (const void *p, bool other_byte_order)
 {
   const union unaligned *up = p;
-  if (file->other_byte_order)
+  if (other_byte_order)
     return bswap_64 (up->u8);
   return up->u8;
 }
 
 
-#define read_2ubyte_unaligned_inc(Dbg, Addr) \
-  ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr);                        \
-     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);                    \
-     t_; })
+#define read_2ubyte_unaligned_inc(Addr, OtherByteOrder)                        \
+  ({ uint16_t t_ = read_2ubyte_unaligned (Addr, OtherByteOrder);       \
+    Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);               \
+    t_; })
 
-#define read_4ubyte_unaligned_inc(Dbg, Addr) \
-  ({ uint32_t t_ = dwarflint_read_4ubyte_unaligned (Dbg, Addr);                      \
-     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);                    \
-     t_; })
+#define read_4ubyte_unaligned_inc(Addr, OtherByteOrder)                        \
+  ({ uint32_t t_ = dwarflint_read_4ubyte_unaligned (Addr, OtherByteOrder); \
+    Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);               \
+    t_; })
 
-#define read_8ubyte_unaligned_inc(Dbg, Addr) \
-  ({ uint64_t t_ = dwarflint_read_8ubyte_unaligned (Dbg, Addr);                      \
-     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);                    \
-     t_; })
+#define read_8ubyte_unaligned_inc(Addr, OtherByteOrder)                        \
+  ({ uint64_t t_ = dwarflint_read_8ubyte_unaligned (Addr, OtherByteOrder); \
+    Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);               \
+    t_; })
 
 
 
 void
-read_ctx_init (struct read_ctx *ctx, struct elf_file *file, Elf_Data *data)
+read_ctx_init (struct read_ctx *ctx, Elf_Data *data, bool other_byte_order)
 {
   if (data == NULL)
     abort ();
 
-  ctx->file = file;
   ctx->data = data;
   ctx->begin = data->d_buf;
   ctx->end = data->d_buf + data->d_size;
   ctx->ptr = data->d_buf;
+  ctx->other_byte_order = other_byte_order;
 }
 
 bool
@@ -114,11 +114,11 @@ read_ctx_init_sub (struct read_ctx *ctx, struct read_ctx *parent,
       || end > parent->end)
     return false;
 
-  ctx->file = parent->file;
   ctx->data = parent->data;
   ctx->begin = begin;
   ctx->end = end;
   ctx->ptr = begin;
+  ctx->other_byte_order = parent->other_byte_order;
   return true;
 }
 
@@ -217,7 +217,7 @@ read_ctx_read_2ubyte (struct read_ctx *ctx, uint16_t *ret)
 {
   if (!read_ctx_need_data (ctx, 2))
     return false;
-  uint16_t val = read_2ubyte_unaligned_inc (ctx->file, ctx->ptr);
+  uint16_t val = read_2ubyte_unaligned_inc (ctx->ptr, ctx->other_byte_order);
   if (ret != NULL)
     *ret = val;
   return true;
@@ -228,7 +228,7 @@ read_ctx_read_4ubyte (struct read_ctx *ctx, uint32_t *ret)
 {
   if (!read_ctx_need_data (ctx, 4))
     return false;
-  uint32_t val = read_4ubyte_unaligned_inc (ctx->file, ctx->ptr);
+  uint32_t val = read_4ubyte_unaligned_inc (ctx->ptr, ctx->other_byte_order);
   if (ret != NULL)
     *ret = val;
   return true;
@@ -239,7 +239,7 @@ read_ctx_read_8ubyte (struct read_ctx *ctx, uint64_t *ret)
 {
   if (!read_ctx_need_data (ctx, 8))
     return false;
-  uint64_t val = read_8ubyte_unaligned_inc (ctx->file, ctx->ptr);
+  uint64_t val = read_8ubyte_unaligned_inc (ctx->ptr, ctx->other_byte_order);
   if (ret != NULL)
     *ret = val;
   return true;
index 62112eb21bd91ba71f772e5a2a2c0d5b9cae8bc6..ab48398904c33a19f99c9aaa4d76ebeb40545b70 100644 (file)
@@ -14,22 +14,22 @@ extern "C"
 
 struct read_ctx
 {
-  struct elf_file *file;
   Elf_Data *data;
   const unsigned char *ptr;
   const unsigned char *begin;
   const unsigned char *end;
+  bool other_byte_order;
 };
 
-uint32_t dwarflint_read_4ubyte_unaligned (struct elf_file *file,
-                                         const void *p);
-uint64_t dwarflint_read_8ubyte_unaligned (struct elf_file *file,
-                                         const void *p);
+uint32_t dwarflint_read_4ubyte_unaligned (const void *p,
+                                         bool other_byte_order);
+uint64_t dwarflint_read_8ubyte_unaligned (const void *p,
+                                         bool other_byte_order);
 
 
 void read_ctx_init (struct read_ctx *ctx,
-                          struct elf_file *file,
-                          Elf_Data *data);
+                   Elf_Data *data,
+                   bool other_byte_order);
 bool read_ctx_init_sub (struct read_ctx *ctx,
                        struct read_ctx *parent,
                        const unsigned char *begin,