]> git.ipfire.org Git - thirdparty/elfutils.git/commitdiff
dwarflint: Move Elf* out of dwarflint class
authorPetr Machata <pmachata@redhat.com>
Fri, 27 Nov 2009 15:41:10 +0000 (16:41 +0100)
committerPetr Machata <pmachata@redhat.com>
Wed, 18 Aug 2010 12:55:14 +0000 (14:55 +0200)
* instead implement opening in highlevel_check and lowlevel_check
  separately.  We need to open highlevel check through dwfl,
  which does its own Elf opening.

src/Makefile.am
src/dwarflint/check_highlevel.cc [new file with mode: 0644]
src/dwarflint/checks-high.hh
src/dwarflint/checks-low.cc
src/dwarflint/dwarflint.cc
src/dwarflint/dwarflint.hh
src/dwarflint/main.cc

index 4a1c07eb1caf5b1e9aace0f84c4897d8ddfcd238..976af4948b3dda1074c0311197383867621ab060 100644 (file)
@@ -95,7 +95,7 @@ dwarflint_SOURCES = dwarfstrings.c \
                    dwarflint/reloc.cc dwarflint/reloc.h \
                    dwarflint/tables.cc dwarflint/tables.hh dwarflint/tables.h \
                    dwarflint/all-dies-it.hh \
-                   dwarflint/checks-high.hh \
+                   dwarflint/check_highlevel.cc dwarflint/checks-high.hh \
                    dwarflint/check_debug_abbrev.cc \
                    dwarflint/check_debug_info.cc \
                    dwarflint/check_debug_line.cc \
diff --git a/src/dwarflint/check_highlevel.cc b/src/dwarflint/check_highlevel.cc
new file mode 100644 (file)
index 0000000..68309d4
--- /dev/null
@@ -0,0 +1,47 @@
+/* Initialization of high-level check context
+   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>.  */
+
+  // xxx this will throw an exception on <c++/dwarf> or <libdw.h>
+  // failure.  We need to catch it and convert to check_base::failed.
+
+#include "checks-high.hh" // xxx rename
+#include "../libdwfl/libdwfl.h"
+
+Dwarf *
+dwarf_handle_loader::get_dwarf_handle (int fd)
+{
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  /*
+    static const Dwfl_Callbacks callbacks =
+    {
+    .section_address = dwfl_offline_section_address,
+    .find_debuginfo = find_no_debuginfo
+    };
+    Dwfl *dwfl = dwfl_begin (&callbacks);
+    if (unlikely (dwfl == NULL))
+      throw check_base::failed ();
+    */
+  return dwarf_begin_elf (elf, DWARF_C_READ, NULL);
+}
index 6e1a63ec989fe21dcd0936d015dd2e306d36a1b5..5361e5e8a569ad3a84dc5afc99776acb1eb5c639 100644 (file)
    Network licensing program, please visit www.openinventionnetwork.com
    <http://www.openinventionnetwork.com>.  */
 
+#ifndef DWARFLINT_CHECKS_HIGH_HH
+#define DWARFLINT_CHECKS_HIGH_HH
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
 #include "checks-low.hh"
 #include "config.h"
 #include "c++/dwarf"
 
+struct dwarf_handle_loader
+{
+  Dwarf *get_dwarf_handle (int fd);
+};
+
 template<class T>
 class highlevel_check
   : public check<highlevel_check<T> >
+  , private dwarf_handle_loader
 {
   ::Dwarf *_m_handle;
 
@@ -39,7 +52,7 @@ public:
   // xxx this will throw an exception on <c++/dwarf> or <libdw.h>
   // failure.  We need to catch it and convert to check_base::failed.
   explicit highlevel_check (dwarflint &lint)
-    : _m_handle (dwarf_begin_elf (lint.elf (), DWARF_C_READ, NULL))
+    : _m_handle (get_dwarf_handle (lint.fd ()))
     , dw (_m_handle)
   {
     if (!do_high_level)
@@ -61,3 +74,5 @@ to_where (T const &die)
   where_reset_2 (&ret, die.offset ());
   return ret;
 }
+
+#endif//DWARFLINT_CHECKS_HIGH_HH
index 9350d92b44ad15be2557f4e67fe6c221a6490b4e..a4247db2e434027bd3431a87bbcf61ca02c8d291 100644 (file)
@@ -67,9 +67,136 @@ struct secinfo_map
   }
 };
 
-bool
-elf_file_init (struct elf_file *file, Elf *elf)
+namespace
+{
+int
+layout_rel_file (Elf *elf)
+{
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    return 1;
+
+  if (ehdr.e_type != ET_REL)
+    return 0;
+
+  /* Taken from libdwfl. */
+  GElf_Addr base = 0;
+  GElf_Addr start = 0, end = 0, bias = 0;
+
+  bool first = true;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (shdr == NULL))
+       return 1;
+
+      if (shdr->sh_flags & SHF_ALLOC)
+       {
+         const GElf_Xword align = shdr->sh_addralign ?: 1;
+         const GElf_Addr next = (end + align - 1) & -align;
+         if (shdr->sh_addr == 0
+             /* Once we've started doing layout we have to do it all,
+                unless we just layed out the first section at 0 when
+                it already was at 0.  */
+             || (bias == 0 && end > start && end != next))
+           {
+             shdr->sh_addr = next;
+             if (end == base)
+               /* This is the first section assigned a location.
+                  Use its aligned address as the module's base.  */
+               start = base = shdr->sh_addr;
+             else if (unlikely (base & (align - 1)))
+               {
+                 /* If BASE has less than the maximum alignment of
+                    any section, we eat more than the optimal amount
+                    of padding and so make the module's apparent
+                    size come out larger than it would when placed
+                    at zero.  So reset the layout with a better base.  */
+
+                 start = end = base = (base + align - 1) & -align;
+                 Elf_Scn *prev_scn = NULL;
+                 do
+                   {
+                     prev_scn = elf_nextscn (elf, prev_scn);
+                     GElf_Shdr prev_shdr_mem;
+                     GElf_Shdr *prev_shdr = gelf_getshdr (prev_scn,
+                                                          &prev_shdr_mem);
+                     if (unlikely (prev_shdr == NULL))
+                       return 1;
+                     if (prev_shdr->sh_flags & SHF_ALLOC)
+                       {
+                         const GElf_Xword prev_align
+                           = prev_shdr->sh_addralign ?: 1;
+
+                         prev_shdr->sh_addr
+                           = (end + prev_align - 1) & -prev_align;
+                         end = prev_shdr->sh_addr + prev_shdr->sh_size;
+
+                         if (unlikely (! gelf_update_shdr (prev_scn,
+                                                           prev_shdr)))
+                           return 1;
+                       }
+                   }
+                 while (prev_scn != scn);
+                 continue;
+               }
+
+             end = shdr->sh_addr + shdr->sh_size;
+             if (likely (shdr->sh_addr != 0)
+                 && unlikely (! gelf_update_shdr (scn, shdr)))
+               return 1;
+           }
+         else
+           {
+             /* The address is already assigned.  Just track it.  */
+             if (first || end < shdr->sh_addr + shdr->sh_size)
+               end = shdr->sh_addr + shdr->sh_size;
+             if (first || bias > shdr->sh_addr)
+               /* This is the lowest address in the module.  */
+               bias = shdr->sh_addr;
+
+             if ((shdr->sh_addr - bias + base) & (align - 1))
+               /* This section winds up misaligned using BASE.
+                  Adjust BASE upwards to make it congruent to
+                  the lowest section address in the file modulo ALIGN.  */
+               base = (((base + align - 1) & -align)
+                       + (bias & (align - 1)));
+           }
+
+         first = false;
+       }
+    }
+  return 0;
+}
+
+  Elf *
+  open_elf (int fd)
+  {
+    Elf *elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+    if (unlikely (elf == NULL))
+      {
+       wr_error ()
+         << "Error opening file: " << elf_errmsg (-1) << std::endl;
+       throw check_base::failed ();
+      }
+
+    if (layout_rel_file (elf))
+      {
+       wr_error ()
+         << "Couldn't layout ET_REL file." << std::endl;
+       throw check_base::failed ();
+      }
+
+    return elf;
+  }
+
+Elf *
+elf_file_init (struct elf_file *file, int fd)
 {
+  Elf *elf = open_elf (fd);
+  assert (elf != NULL);
   memset (file, 0, sizeof (*file));
 
   file->elf = elf;
@@ -115,7 +242,7 @@ elf_file_init (struct elf_file *file, Elf *elf)
        {
        invalid_elf:
          wr_error () << "Broken ELF." << std::endl;
-         return false;
+         goto close_and_out;
        }
 
       const char *scnname = elf_strptr (elf, file->ehdr.e_shstrndx,
@@ -245,12 +372,26 @@ elf_file_init (struct elf_file *file, Elf *elf)
            << std::endl;
     }
 
-  return true;
+  return elf;
+
+ close_and_out:
+  if (elf != NULL)
+    {
+      elf_errno (); // clear errno
+      elf_end (elf);
+      int err = elf_errno ();
+      if (err != 0)
+       wr_error ()
+         << "error while closing Elf descriptor: "
+         << elf_errmsg (err) << std::endl;
+    }
+  return NULL;
+}
 }
 
 load_sections::load_sections (dwarflint &lint)
 {
-  elf_file_init (&file, lint.elf ());
+  elf_file_init (&file, lint.fd ());
 }
 
 load_sections::~load_sections ()
index 72f23c89ba0fdd2de0e9cd2b65307565cb7e34e2..27f51f18151294862213b20cd9b827e334a50200 100644 (file)
@@ -1,7 +1,7 @@
 #include "dwarflint.hh"
 
-dwarflint::dwarflint (Elf *a_elf)
-  : _m_elf (a_elf)
+dwarflint::dwarflint (int a_fd)
+  : _m_fd (a_fd)
 {
   check_registrar::inst ()->enroll (*this);
 }
index f1684ecafd94e161685efbc9584fc78eed942681..6d256a7e8473fa1c59ac64ad2c2bcd9ecaff7462 100644 (file)
@@ -10,7 +10,7 @@ class dwarflint
 {
   typedef std::map <void const *, class check_base *> check_map;
   check_map _m_checks;
-  Elf * _m_elf;
+  int _m_fd;
 
 public:
   struct check_registrar
@@ -43,8 +43,8 @@ public:
     std::vector <item *> _m_items;
   };
 
-  dwarflint (Elf *elf);
-  Elf *elf () { return _m_elf; }
+  explicit dwarflint (int fd);
+  int fd () { return _m_fd; }
 
   template <class T> T *check ();
 
index 38fd1b2c7b660e82d5688dba26c1c6300d50e6c5..f544635a944a057f29d1fc8e299ff3b621a4d414 100644 (file)
@@ -156,108 +156,6 @@ parse_opt (int key, char *arg __attribute__ ((unused)),
   return 0;
 }
 
-static int
-layout_rel_file (Elf *elf)
-{
-  GElf_Ehdr ehdr;
-  if (gelf_getehdr (elf, &ehdr) == NULL)
-    return 1;
-
-  if (ehdr.e_type != ET_REL)
-    return 0;
-
-  /* Taken from libdwfl. */
-  GElf_Addr base = 0;
-  GElf_Addr start = 0, end = 0, bias = 0;
-
-  bool first = true;
-  Elf_Scn *scn = NULL;
-  while ((scn = elf_nextscn (elf, scn)) != NULL)
-    {
-      GElf_Shdr shdr_mem;
-      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
-      if (unlikely (shdr == NULL))
-       return 1;
-
-      if (shdr->sh_flags & SHF_ALLOC)
-       {
-         const GElf_Xword align = shdr->sh_addralign ?: 1;
-         const GElf_Addr next = (end + align - 1) & -align;
-         if (shdr->sh_addr == 0
-             /* Once we've started doing layout we have to do it all,
-                unless we just layed out the first section at 0 when
-                it already was at 0.  */
-             || (bias == 0 && end > start && end != next))
-           {
-             shdr->sh_addr = next;
-             if (end == base)
-               /* This is the first section assigned a location.
-                  Use its aligned address as the module's base.  */
-               start = base = shdr->sh_addr;
-             else if (unlikely (base & (align - 1)))
-               {
-                 /* If BASE has less than the maximum alignment of
-                    any section, we eat more than the optimal amount
-                    of padding and so make the module's apparent
-                    size come out larger than it would when placed
-                    at zero.  So reset the layout with a better base.  */
-
-                 start = end = base = (base + align - 1) & -align;
-                 Elf_Scn *prev_scn = NULL;
-                 do
-                   {
-                     prev_scn = elf_nextscn (elf, prev_scn);
-                     GElf_Shdr prev_shdr_mem;
-                     GElf_Shdr *prev_shdr = gelf_getshdr (prev_scn,
-                                                          &prev_shdr_mem);
-                     if (unlikely (prev_shdr == NULL))
-                       return 1;
-                     if (prev_shdr->sh_flags & SHF_ALLOC)
-                       {
-                         const GElf_Xword prev_align
-                           = prev_shdr->sh_addralign ?: 1;
-
-                         prev_shdr->sh_addr
-                           = (end + prev_align - 1) & -prev_align;
-                         end = prev_shdr->sh_addr + prev_shdr->sh_size;
-
-                         if (unlikely (! gelf_update_shdr (prev_scn,
-                                                           prev_shdr)))
-                           return 1;
-                       }
-                   }
-                 while (prev_scn != scn);
-                 continue;
-               }
-
-             end = shdr->sh_addr + shdr->sh_size;
-             if (likely (shdr->sh_addr != 0)
-                 && unlikely (! gelf_update_shdr (scn, shdr)))
-               return 1;
-           }
-         else
-           {
-             /* The address is already assigned.  Just track it.  */
-             if (first || end < shdr->sh_addr + shdr->sh_size)
-               end = shdr->sh_addr + shdr->sh_size;
-             if (first || bias > shdr->sh_addr)
-               /* This is the lowest address in the module.  */
-               bias = shdr->sh_addr;
-
-             if ((shdr->sh_addr - bias + base) & (align - 1))
-               /* This section winds up misaligned using BASE.
-                  Adjust BASE upwards to make it congruent to
-                  the lowest section address in the file modulo ALIGN.  */
-               base = (((base + align - 1) & -align)
-                       + (bias & (align - 1)));
-           }
-
-         first = false;
-       }
-    }
-  return 0;
-}
-
 int
 main (int argc, char *argv[])
 {
@@ -320,33 +218,13 @@ main (int argc, char *argv[])
        }
 
       /* Create an `Elf' descriptor.  */
-      Elf *elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
-      if (elf == NULL)
-      invalid_elf:
-       wr_error (NULL,
-                 gettext ("Error processing ELF file: %s\n"),
-                 elf_errmsg (-1));
-      else
-       {
-         unsigned int prev_error_count = error_count;
-         if (layout_rel_file (elf))
-           goto invalid_elf;
-
-         if (!only_one)
-           std::cout << std::endl << argv[remaining] << ":" << std::endl;
-         dwarflint lint (elf);
-
-         elf_errno (); /* Clear errno.  */
-         elf_end (elf);
-         int err = elf_errno ();
-         if (err != 0)
-           wr_error (NULL,
-                     gettext ("error while closing Elf descriptor: %s\n"),
-                     elf_errmsg (err));
-
-         if (prev_error_count == error_count && !be_quiet)
-           puts (gettext ("No errors"));
-       }
+      unsigned int prev_error_count = error_count;
+      if (!only_one)
+       std::cout << std::endl << argv[remaining] << ":" << std::endl;
+      dwarflint lint (fd);
+
+      if (prev_error_count == error_count && !be_quiet)
+       puts (gettext ("No errors"));
 
       close (fd);
     }