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 \
--- /dev/null
+/* 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);
+}
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;
// 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)
where_reset_2 (&ret, die.offset ());
return ret;
}
+
+#endif//DWARFLINT_CHECKS_HIGH_HH
}
};
-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;
{
invalid_elf:
wr_error () << "Broken ELF." << std::endl;
- return false;
+ goto close_and_out;
}
const char *scnname = elf_strptr (elf, file->ehdr.e_shstrndx,
<< 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 ()
#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);
}
{
typedef std::map <void const *, class check_base *> check_map;
check_map _m_checks;
- Elf * _m_elf;
+ int _m_fd;
public:
struct check_registrar
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 ();
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[])
{
}
/* 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);
}