no_mudflap.os = -fmudflap
-bin_PROGRAMS = dwarflint
+bin_PROGRAMS = dwarflint locstats
noinst_PROGRAMS = tests/test-coverage tests/test-wrap tests/test-all-dies-it
dwarflint_SOURCES = \
dwarflint.cc dwarflint.hh dwarflint.ii \
elf_file.hh elf_file.ii \
expected-at.cc expected.hh \
+ files.cc files.hh \
highlevel_check.cc highlevel_check.hh \
main.cc \
messages.cc messages.hh \
check_range_out_of_scope.cc \
check_self_referential_die.cc \
check_linkage_external_die.cc \
- locstats.cc \
lowlevel_checks.cc lowlevel_checks.hh \
\
../src/dwarfstrings.c
+locstats_SOURCES = \
+ locstats.cc \
+ files.cc files.hh \
+ option.cc option.hh option.ii \
+ pri.cc pri.hh \
+ where.c where.h
+
tests_test_coverage_SOURCES = tests/test-coverage.cc coverage.cc pri.cc \
../src/dwarfstrings.c
libdwpp = ../libdw/libdwpp.a $(libdw)
dwarflint_LDADD = $(libebl) $(libelf) $(libdwpp) $(libeu) $(libmudflap) -ldl
+locstats_LDADD = $(libebl) $(libelf) $(libdwpp) $(libeu) $(libmudflap) -ldl
tests_test_coverage_LDADD = $(libebl) $(libelf) $(libdwpp) $(libeu) $(libmudflap) -ldl
tests_test_all_dies_it_LDADD = $(libdwpp)
/* Pedantic checking of DWARF files
- Copyright (C) 2008,2009,2010 Red Hat, Inc.
+ Copyright (C) 2008,2009,2010,2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include "dwarflint.hh"
#include "messages.hh"
#include "checks.hh"
#include "check_registrar.hh"
+#include "files.hh"
#include <fcntl.h>
#include <cstring>
#include <cerrno>
#include <stdexcept>
-#include <sstream>
std::ostream &
operator << (std::ostream &o, checkstack const &stack)
return o;
}
-namespace
-{
- int
- get_fd (char const *fname)
- {
- /* Open the file. */
- int fd = open (fname, O_RDONLY);
- if (fd == -1)
- {
- std::stringstream ss;
- ss << "Cannot open input file: " << strerror (errno) << ".";
- throw std::runtime_error (ss.str ());
- }
-
- return fd;
- }
-}
-
void
main_check_registrar::run (dwarflint &lint)
{
dwarflint::dwarflint (char const *a_fname, checkrules const &a_rules)
: _m_fname (a_fname)
- , _m_fd (get_fd (_m_fname))
+ , _m_fd (files::open (_m_fname))
, _m_rules (a_rules)
{
main_registrar ()->run (*this);
--- /dev/null
+/* Pedantic checking of DWARF files.
+ Copyright (C) 2011 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 "files.hh"
+#include "messages.hh"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sstream>
+#include <cstring>
+#include <cerrno>
+#include <stdexcept>
+
+namespace
+{
+ inline bool failed (void *ptr) { return ptr == NULL; }
+ inline bool failed (int i) { return i < 0; }
+
+ template <class T>
+ inline T
+ throw_if_failed (T x, char const *msg,
+ char const *(*errmsgcb) (int) = NULL)
+ {
+ if (unlikely (failed (x)))
+ {
+ std::stringstream ss;
+ ss << msg;
+ if (errmsgcb != NULL)
+ ss << ": " << errmsgcb (-1);
+ throw std::runtime_error (ss.str ());
+ }
+ return x;
+ }
+
+ char const *
+ mystrerror (int i)
+ {
+ if (i == -1)
+ i = errno;
+ return strerror (i);
+ }
+}
+
+int
+files::open (char const *fname)
+{
+ int fd = ::open (fname, O_RDONLY);
+ if (fd == -1)
+ {
+ std::stringstream ss;
+ ss << "Cannot open input file: " << strerror (errno) << ".";
+ throw std::runtime_error (ss.str ());
+ }
+
+ return fd;
+}
+
+Dwfl *
+files::open_dwfl ()
+{
+ static class my_callbacks
+ : public Dwfl_Callbacks
+ {
+ // Stub libdwfl callback, only the ELF handle already open is ever used.
+ static int
+ find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
+ void **userdata __attribute__ ((unused)),
+ const char *modname __attribute__ ((unused)),
+ Dwarf_Addr base __attribute__ ((unused)),
+ const char *file_name __attribute__ ((unused)),
+ const char *debuglink_file __attribute__ ((unused)),
+ GElf_Word debuglink_crc __attribute__ ((unused)),
+ char **debuginfo_file_name __attribute__ ((unused)))
+ {
+ return -1;
+ }
+
+ public:
+ my_callbacks ()
+ {
+ section_address = dwfl_offline_section_address;
+ find_debuginfo = find_no_debuginfo;
+ }
+ } cbs;
+
+ return throw_if_failed (dwfl_begin (&cbs),
+ "Couldn't initialize DWFL");
+}
+
+Dwarf *
+files::open_dwarf (Dwfl *dwfl, char const *fname, int fd)
+{
+ dwfl_report_begin (dwfl);
+
+ // Dup FD for dwfl to consume.
+ int dwfl_fd
+ = throw_if_failed (dup (fd), "Error: dup", mystrerror);
+
+ Dwfl_Module *mod
+ = throw_if_failed (dwfl_report_offline (dwfl, fname, fname, dwfl_fd),
+ "Couldn't add DWFL module", dwfl_errmsg);
+ dwfl_report_end (dwfl, NULL, NULL);
+ Dwarf_Addr bias;
+ throw_if_failed (dwfl_module_getelf (mod, &bias),
+ "Couldn't open ELF.", dwfl_errmsg);
+ return throw_if_failed (dwfl_module_getdwarf (mod, &bias),
+ "Couldn't obtain DWARF descriptor", dwfl_errmsg);
+}
+
+elfutils::dwarf
+files::open_dwarf (Dwarf *dw)
+ try
+ {
+ return dw;
+ }
+ catch (...)
+ {
+ throw std::runtime_error
+ ("Couldn't initialize high-level DWARF descriptor");
+ }
--- /dev/null
+/* Pedantic checking of DWARF files.
+ Copyright (C) 2011 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>. */
+
+#ifndef _DWARFLINT_FILES_H_
+#define _DWARFLINT_FILES_H_
+
+#include "../libdwfl/libdwfl.h"
+#include "../libdw/c++/dwarf"
+
+// The functions in this module do their own error handling, and throw
+// std::runtime_error with descriptive error message on error.
+namespace files
+{
+ int open (char const *fname);
+
+ Dwfl *open_dwfl ()
+ __attribute__ ((nonnull, malloc));
+
+ Dwarf *open_dwarf (Dwfl *dwfl, char const *fname, int fd)
+ __attribute__ ((nonnull, malloc));
+
+ elfutils::dwarf open_dwarf (Dwarf *dw);
+}
+
+#endif /* _DWARFLINT_FILES_H_ */
/* Initialization of high-level check context
- Copyright (C) 2009, 2010 Red Hat, Inc.
+ Copyright (C) 2009, 2010, 2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
<http://www.openinventionnetwork.com>. */
#include "highlevel_check.hh"
-#include "messages.hh"
-
-#include "sections.hh"
#include "lowlevel_checks.hh"
-
-namespace
-{
- inline bool failed (void *ptr) { return ptr == NULL; }
- inline bool failed (int i) { return i < 0; }
-
- template <class T>
- inline T
- throw_if_failed (T x, char const *msg,
- char const *(*errmsgcb) (int) = NULL)
- {
- if (unlikely (failed (x)))
- {
- std::stringstream ss;
- ss << msg;
- if (errmsgcb != NULL)
- ss << ": " << errmsgcb (-1);
- ss << '.';
- wr_error () << ss.str () << std::endl;
- throw check_base::failed ();
- }
- return x;
- }
-
- Dwfl *open_dwfl () __attribute__ ((nonnull, malloc));
- Dwarf *open_dwarf (Dwfl *dwfl, int fd) __attribute__ ((nonnull, malloc));
-
- Dwfl *
- open_dwfl ()
- {
- static class my_callbacks
- : public Dwfl_Callbacks
- {
- // Stub libdwfl callback, only the ELF handle already open is ever used.
- static int
- find_no_debuginfo (Dwfl_Module *mod __attribute__ ((unused)),
- void **userdata __attribute__ ((unused)),
- const char *modname __attribute__ ((unused)),
- Dwarf_Addr base __attribute__ ((unused)),
- const char *file_name __attribute__ ((unused)),
- const char *debuglink_file __attribute__ ((unused)),
- GElf_Word debuglink_crc __attribute__ ((unused)),
- char **debuginfo_file_name __attribute__ ((unused)))
- {
- return -1;
- }
-
- public:
- my_callbacks ()
- {
- section_address = dwfl_offline_section_address;
- find_debuginfo = find_no_debuginfo;
- }
- } cbs;
-
- return throw_if_failed (dwfl_begin (&cbs),
- "Couldn't initialize DWFL");
- }
-
- char const *
- mystrerror (int i)
- {
- if (i == -1)
- i = errno;
- return strerror (i);
- }
-
- Dwarf *
- open_dwarf (Dwfl *dwfl, char const *fname, int fd)
- {
- dwfl_report_begin (dwfl);
-
- // Dup FD for dwfl to consume.
- int dwfl_fd
- = throw_if_failed (dup (fd), "Error: dup", mystrerror);
-
- Dwfl_Module *mod
- = throw_if_failed (dwfl_report_offline (dwfl, fname, fname, dwfl_fd),
- "Couldn't add DWFL module", dwfl_errmsg);
- dwfl_report_end (dwfl, NULL, NULL);
- Dwarf_Addr bias;
- throw_if_failed (dwfl_module_getelf (mod, &bias),
- "Couldn't open ELF.", dwfl_errmsg);
- return throw_if_failed (dwfl_module_getdwarf (mod, &bias),
- "Couldn't obtain DWARF descriptor", dwfl_errmsg);
- }
-
- elfutils::dwarf
- open_hl_dwarf (Dwarf *dw)
- try
- {
- return dw;
- }
- catch (...)
- {
- wr_error ()
- << "Couldn't initialize high-level DWARF descriptor." << std::endl;
- throw check_base::failed ();
- }
-}
+#include "files.hh"
open_highlevel_dwarf::open_highlevel_dwarf (checkstack &stack, dwarflint &lint)
: _m_dwfl ((lint.check<lowlevel_checks> (stack),
- open_dwfl ()))
- , c_dw (open_dwarf (_m_dwfl, lint.fname (), lint.fd ()))
- , dw (open_hl_dwarf (c_dw))
+ files::open_dwfl ()))
+ , c_dw (files::open_dwarf (_m_dwfl, lint.fname (), lint.fd ()))
+ , dw (files::open_dwarf (c_dw))
{}
open_highlevel_dwarf::~open_highlevel_dwarf ()
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
#include "highlevel_check.hh"
#include "all-dies-it.hh"
#include "option.hh"
-#include "messages.hh"
#include "pri.hh"
+#include "files.hh"
+
+#include <libintl.h>
#include <sstream>
#include <bitset>
using elfutils::dwarf;
-namespace
-{
-
-#define DIE_OPTSTRING \
+#define DIE_OPTSTRING \
"}[,...]"
- string_option opt_ignore
+global_opt<string_option> opt_ignore
("Skip certain DIEs. class may be one of single_addr, artificial, inlined, \
inlined_subroutine, no_coverage, mutable, or immutable.",
- "class[,...]", "locstats:ignore");
+ "class[,...]", "ignore");
- string_option opt_dump
+global_opt<string_option> opt_dump
("Dump certain DIEs. For classes, see option 'ignore'.",
- "class[,...]", "locstats:dump");
+ "class[,...]", "dump");
- string_option opt_tabulation_rule
+global_opt<string_option> opt_tabulation_rule
("Rule for sorting results into buckets. start is either integer 0..100, \
or special value 0.0 indicating cases with no coverage whatsoever \
(i.e. not those that happen to round to 0%).",
- "start[:step][,...]", "locstats:tabulate");
-
- class locstats
- : public highlevel_check<locstats>
- {
- public:
- static checkdescriptor const *descriptor () {
- static checkdescriptor cd
- (checkdescriptor::create ("locstats")
- .groups ("@nodefault")
- .option (opt_ignore)
- .option (opt_dump)
- .option (opt_tabulation_rule)
- .description (
-"Computes a location info coverage statistics. Goes through the whole "
-"DIE graph, looking at each variable and formal parameter, and "
-"determining scope coverage of its location information. In other "
-"words for how big a part of scope we know, where the variable "
-"\"lives\".\n"
-" - https://fedorahosted.org/pipermail/elfutils-devel/2010-July/001498.html\n"
-" - https://fedorahosted.org/pipermail/elfutils-devel/2010-September/001602.html\n"));
- return &cd;
- }
-
- locstats (checkstack &stack, dwarflint &lint);
- };
+ "start[:step][,...]", "tabulate");
- reg<locstats> reg_locstats;
+// where.c needs to know how to format certain wheres. The module
+// doesn't know that we don't use these :)
+extern "C"
+bool
+show_refs ()
+{
+ return false;
+}
#define DIE_TYPES \
TYPE(single_addr) \
TYPE(mutable) \
TYPE(immutable)
- struct tabrule
- {
- int start;
- int step;
- tabrule (int a_start, int a_step)
- : start (a_start), step (a_step)
- {}
- bool operator < (tabrule const &other) const {
- return start < other.start;
- }
- };
+struct tabrule
+{
+ int start;
+ int step;
+ tabrule (int a_start, int a_step)
+ : start (a_start), step (a_step)
+ {}
+ bool operator < (tabrule const &other) const {
+ return start < other.start;
+ }
+};
- // Sharp 0.0% coverage (i.e. not a single address byte is covered)
- const int cov_00 = -1;
+// Sharp 0.0% coverage (i.e. not a single address byte is covered)
+const int cov_00 = -1;
- struct tabrules_t
- : public std::vector<tabrule>
+struct tabrules_t
+ : public std::vector<tabrule>
+{
+ tabrules_t (std::string const &rule)
{
- tabrules_t (std::string const &rule)
- {
- std::stringstream ss;
- ss << rule;
+ std::stringstream ss;
+ ss << rule;
- std::string item;
- while (std::getline (ss, item, ','))
- {
- if (item.empty ())
- continue;
- int start;
- int step;
- char const *ptr = item.c_str ();
-
- if (item.length () >= 3
- && std::strncmp (ptr, "0.0", 3) == 0)
- {
- start = cov_00;
- ptr += 3;
- }
- else
- start = std::strtol (ptr, const_cast<char **> (&ptr), 10);
+ std::string item;
+ while (std::getline (ss, item, ','))
+ {
+ if (item.empty ())
+ continue;
+ int start;
+ int step;
+ char const *ptr = item.c_str ();
- if (*ptr == 0)
- step = 0;
- else
- {
- if (*ptr != ':')
- {
- step = 0;
- goto garbage;
- }
- else
- ptr++;
+ if (item.length () >= 3
+ && std::strncmp (ptr, "0.0", 3) == 0)
+ {
+ start = cov_00;
+ ptr += 3;
+ }
+ else
+ start = std::strtol (ptr, const_cast<char **> (&ptr), 10);
- step = std::strtol (ptr, const_cast<char **> (&ptr), 10);
- if (*ptr != 0)
- garbage:
- std::cerr << "Ignoring garbage at the end of the rule item: '"
- << ptr << '\'' << std::endl;
- }
+ if (*ptr == 0)
+ step = 0;
+ else
+ {
+ if (*ptr != ':')
+ {
+ step = 0;
+ goto garbage;
+ }
+ else
+ ptr++;
+
+ step = std::strtol (ptr, const_cast<char **> (&ptr), 10);
+ if (*ptr != 0)
+ garbage:
+ std::cerr << "Ignoring garbage at the end of the rule item: '"
+ << ptr << '\'' << std::endl;
+ }
- push_back (tabrule (start, step));
- }
+ push_back (tabrule (start, step));
+ }
- push_back (tabrule (100, 0));
- std::sort (begin (), end ());
- }
+ push_back (tabrule (100, 0));
+ std::sort (begin (), end ());
+ }
- void next ()
- {
- if (at (0).step == 0)
- erase (begin ());
- else
- {
- if (at (0).start == cov_00)
- at (0).start = 0;
- at (0).start += at (0).step;
- if (size () > 1)
- {
- if (at (0).start > at (1).start)
- erase (begin ());
- while (size () > 1
- && at (0).start == at (1).start)
- erase (begin ());
- }
- }
- }
+ void next ()
+ {
+ if (at (0).step == 0)
+ erase (begin ());
+ else
+ {
+ if (at (0).start == cov_00)
+ at (0).start = 0;
+ at (0).start += at (0).step;
+ if (size () > 1)
+ {
+ if (at (0).start > at (1).start)
+ erase (begin ());
+ while (size () > 1
+ && at (0).start == at (1).start)
+ erase (begin ());
+ }
+ }
+ }
- bool match (int value) const
- {
- return at (0).start == value;
- }
- };
+ bool match (int value) const
+ {
+ return at (0).start == value;
+ }
+};
#define TYPE(T) dt_##T,
enum die_type_e
};
#undef TYPE
- class die_type_matcher
- : public std::bitset<dt__count>
+class die_type_matcher
+ : public std::bitset<dt__count>
+{
+ class invalid {};
+ std::pair<die_type_e, bool>
+ parse (std::string &desc)
{
- class invalid {};
- std::pair<die_type_e, bool>
- parse (std::string &desc)
- {
- bool val = true;
- if (desc == "")
- throw invalid ();
+ bool val = true;
+ if (desc == "")
+ throw invalid ();
#define TYPE(T) \
- if (desc == #T) \
- return std::make_pair (dt_##T, val);
- DIE_TYPES
+ if (desc == #T) \
+ return std::make_pair (dt_##T, val);
+ DIE_TYPES
#undef TYPE
throw invalid ();
- }
-
- public:
- die_type_matcher (std::string const &rule)
- {
- std::stringstream ss;
- ss << rule;
-
- std::string item;
- while (std::getline (ss, item, ','))
- try
- {
- std::pair<die_type_e, bool> const &ig = parse (item);
- set (ig.first, ig.second);
- }
- catch (invalid &i)
- {
- std::cerr << "Invalid die type: " << item << std::endl;
- }
- }
- };
+ }
- class mutability_t
+public:
+ die_type_matcher (std::string const &rule)
{
- bool _m_is_mutable;
- bool _m_is_immutable;
-
- public:
- mutability_t ()
- : _m_is_mutable (false)
- , _m_is_immutable (false)
- {
- }
-
- void set (bool what)
- {
- if (what)
- _m_is_mutable = true;
- else
- _m_is_immutable = true;
- }
+ std::stringstream ss;
+ ss << rule;
- void set_both ()
- {
- set (true);
- set (false);
- }
+ std::string item;
+ while (std::getline (ss, item, ','))
+ try
+ {
+ std::pair<die_type_e, bool> const &ig = parse (item);
+ set (ig.first, ig.second);
+ }
+ catch (invalid &i)
+ {
+ std::cerr << "Invalid die type: " << item << std::endl;
+ }
+ }
+};
- void locexpr (Dwarf_Op *expr, size_t len)
- {
- // We scan the expression looking for DW_OP_{bit_,}piece
- // operators which mark ends of sub-expressions to us.
- bool m = false;
- for (size_t i = 0; i < len; ++i)
- switch (expr[i].atom)
- {
- case DW_OP_implicit_value:
- case DW_OP_stack_value:
- m = true;
- break;
-
- case DW_OP_bit_piece:
- case DW_OP_piece:
- set (m);
- m = false;
- break;
- };
- set (m);
- }
+class mutability_t
+{
+ bool _m_is_mutable;
+ bool _m_is_immutable;
- bool is_mutable () const { return _m_is_mutable; }
- bool is_immutable () const { return _m_is_immutable; }
- };
+public:
+ mutability_t ()
+ : _m_is_mutable (false)
+ , _m_is_immutable (false)
+ {
+ }
- struct error
- : public std::runtime_error
+ void set (bool what)
{
- explicit error (std::string const &what_arg)
- : std::runtime_error (what_arg)
- {}
- };
-
- // Look through the stack of parental dies and return the non-empty
- // ranges instance closest to the stack top (i.e. die_stack.end ()).
- dwarf::ranges
- find_ranges (std::vector<dwarf::debug_info_entry> const &die_stack)
+ if (what)
+ _m_is_mutable = true;
+ else
+ _m_is_immutable = true;
+ }
+
+ void set_both ()
{
- for (auto it = die_stack.rbegin (); it != die_stack.rend (); ++it)
- if (!it->ranges ().empty ())
- return it->ranges ();
- throw error ("no ranges for this DIE");
+ set (true);
+ set (false);
}
- bool
- is_inlined (dwarf::debug_info_entry const &die)
+ void locexpr (Dwarf_Op *expr, size_t len)
{
- dwarf::debug_info_entry::attributes_type::const_iterator it
- = die.attributes ().find (DW_AT_inline);
- if (it != die.attributes ().end ())
- {
- char const *name = (*it).second.dwarf_constant ().name ();
- return std::strcmp (name, "declared_inlined") == 0
- || std::strcmp (name, "inlined") == 0;
- }
- return false;
+ // We scan the expression looking for DW_OP_{bit_,}piece
+ // operators which mark ends of sub-expressions to us.
+ bool m = false;
+ for (size_t i = 0; i < len; ++i)
+ switch (expr[i].atom)
+ {
+ case DW_OP_implicit_value:
+ case DW_OP_stack_value:
+ m = true;
+ break;
+
+ case DW_OP_bit_piece:
+ case DW_OP_piece:
+ set (m);
+ m = false;
+ break;
+ };
+ set (m);
}
+
+ bool is_mutable () const { return _m_is_mutable; }
+ bool is_immutable () const { return _m_is_immutable; }
+};
+
+struct error
+ : public std::runtime_error
+{
+ explicit error (std::string const &what_arg)
+ : std::runtime_error (what_arg)
+ {}
+};
+
+// Look through the stack of parental dies and return the non-empty
+// ranges instance closest to the stack top (i.e. die_stack.end ()).
+dwarf::ranges
+find_ranges (std::vector<dwarf::debug_info_entry> const &die_stack)
+{
+ for (auto it = die_stack.rbegin (); it != die_stack.rend (); ++it)
+ if (!it->ranges ().empty ())
+ return it->ranges ();
+ throw error ("no ranges for this DIE");
+}
+
+bool
+is_inlined (dwarf::debug_info_entry const &die)
+{
+ dwarf::debug_info_entry::attributes_type::const_iterator it
+ = die.attributes ().find (DW_AT_inline);
+ if (it != die.attributes ().end ())
+ {
+ char const *name = (*it).second.dwarf_constant ().name ();
+ return std::strcmp (name, "declared_inlined") == 0
+ || std::strcmp (name, "inlined") == 0;
+ }
+ return false;
}
-locstats::locstats (checkstack &stack, dwarflint &lint)
- : highlevel_check<locstats> (stack, lint)
+void
+process(Dwarf *c_dw, dwarf const &dw)
{
// map percentage->occurrences. Percentage is cov_00..100, where
// 0..100 is rounded-down integer division.
for (int i = 0; i <= 100; ++i)
tally[i] = 0;
- tabrules_t tabrules (/*opt_tabulation_rule.seen ()
- ? opt_tabulation_rule.value () :*/ "10:10");
- die_type_matcher ignore (/*opt_ignore.seen () ? opt_ignore.value () :*/ "");
- die_type_matcher dump (/*opt_dump.seen () ? opt_dump.value () :*/ "");
+ tabrules_t tabrules (opt_tabulation_rule.seen ()
+ ? opt_tabulation_rule.value () : "10:10");
+ die_type_matcher ignore (opt_ignore.seen () ? opt_ignore.value () : "");
+ die_type_matcher dump (opt_dump.seen () ? opt_dump.value () : "");
std::bitset<dt__count> interested = ignore | dump;
bool interested_mutability
= interested.test (dt_mutable) || interested.test (dt_immutable);
-
for (all_dies_iterator<dwarf> it = all_dies_iterator<dwarf> (dw);
it != all_dies_iterator<dwarf> (); ++it)
{
// Unfortunately the location expression is not yet wrapped
// in c++, so we need to revert back to C code.
Dwarf_Die die_c_mem,
- *die_c = dwarf_offdie (this->c_dw, die.offset (), &die_c_mem);
+ *die_c = dwarf_offdie (c_dw, die.offset (), &die_c_mem);
assert (die_c != NULL);
Dwarf_Attribute locattr_mem,
struct where where = WHERE (sec_info, NULL);
where_reset_1 (&where, it.cu ().offset ());
where_reset_2 (&where, die.offset ());
- wr_error (where) << e.what () << '.' << std::endl;
+ std::cerr << "error: " << where << ": "
+ << e.what () << '.' << std::endl;
continue;
}
}
unsigned long cumulative = 0;
unsigned long last = 0;
int last_pct = cov_00;
+ if (total == 0)
+ {
+ std::cout << "No coverage recorded." << std::endl;
+ return;
+ }
+
std::cout << "cov%\tsamples\tcumul" << std::endl;
for (int i = cov_00; i <= 100; ++i)
{
}
}
}
+
+int
+main(int argc, char *argv[])
+{
+ /* Set locale. */
+ setlocale (LC_ALL, "");
+
+ /* Initialize the message catalog. */
+ textdomain (PACKAGE_TARNAME);
+
+ /* Parse and process arguments. */
+ argppp argp (global_opts ());
+ int remaining;
+ argp.parse (argc, argv, 0, &remaining);
+
+ if (remaining == argc)
+ {
+ fputs (gettext ("Missing file name.\n"), stderr);
+ argp.help (stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
+ program_invocation_short_name);
+ std::exit (1);
+ }
+
+ bool only_one = remaining + 1 == argc;
+ do
+ {
+ try
+ {
+ char const *fname = argv[remaining];
+ if (!only_one)
+ std::cout << std::endl << fname << ":" << std::endl;
+
+ int fd = files::open (fname);
+ Dwfl *dwfl = files::open_dwfl ();
+ Dwarf *c_dw = files::open_dwarf (dwfl, fname, fd);
+ dwarf dw = files::open_dwarf (c_dw);
+
+ process (c_dw, dw);
+
+ close (fd);
+ dwfl_end (dwfl);
+ }
+ catch (std::runtime_error &e)
+ {
+ std::cerr << "error: "
+ << e.what () << '.' << std::endl;
+ continue;
+ }
+ }
+ while (++remaining < argc);
+}
/* Main entry point for dwarflint, a pedantic checker for DWARF files.
- Copyright (C) 2008,2009,2010 Red Hat, Inc.
+ Copyright (C) 2008,2009,2010,2011 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
textdomain (PACKAGE_TARNAME);
/* Parse and process arguments. */
- argppp &argp = argppp::inst ();
+ argppp argp (global_opts (),
+ dwarflint::main_registrar ()->get_descriptors ());
int remaining;
argp.parse (argc, argv, 0, &remaining);
#include <cstring>
#include <iostream>
+argppp *argppp::instance = NULL;
+
option_i *
options::find_opt (int key) const
{
return a;
}
-argppp &
-argppp::inst ()
+argppp::argppp (options const &global)
+ : _m_inited (false)
{
- static argppp my
- (global_opts (), dwarflint::main_registrar ()->get_descriptors ());
- return my;
+ argp main = global.build_argp (true);
+ main.parser = &parse_opt;
+ _m_argp = main;
+
+ // Only one instance is allowed per program.
+ assert (instance == NULL);
+ instance = this;
}
argppp::argppp (options const &global,
main.parser = &parse_opt;
_m_argp = main;
+
+ // Only one instance is allowed per program.
+ assert (instance == NULL);
+ instance = this;
}
error_t
argppp::parse_opt (int key, char *arg, argp_state *state)
{
- if (key == ARGP_KEY_INIT && !inst ()._m_inited)
+ assert (instance != NULL);
+ if (key == ARGP_KEY_INIT && !instance->_m_inited)
{
- inst ()._m_inited = true;
+ instance->_m_inited = true;
unsigned i = 0;
for (std::vector<options const *>::const_iterator it
- = inst ()._m_children_inputs.begin ();
- it != inst ()._m_children_inputs.end (); ++it)
+ = instance->_m_children_inputs.begin ();
+ it != instance->_m_children_inputs.end (); ++it)
state->child_inputs[i++] = const_cast<options *> (*it);
return 0;
}
std::vector<options const *> _m_children_inputs;
argp _m_argp;
bool _m_inited;
- argppp (options const &global,
- std::vector<checkdescriptor const *> checkdescriptors);
static error_t parse_opt (int key, char *arg, argp_state *state);
+ static argppp *instance;
public:
- static argppp &inst ();
+ argppp (options const &global);
+ argppp (options const &global,
+ std::vector<checkdescriptor const *> checkdescriptors);
+
void parse (int argc, char **argv, unsigned flags, int *remaining);
void help (FILE *stream, unsigned flags, char *name);
};