summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Machata <pmachata@redhat.com>2010-09-14 23:05:58 +0200
committerPetr Machata <pmachata@redhat.com>2010-09-14 23:05:58 +0200
commit88f3d38340abb592f7e8bf9991a4479d447f631c (patch)
tree8892d2050cc137b3fc981662d79b69603c13b2fb
parentedf32c0a403522d261663e2ab47b39df2a56582f (diff)
downloadelfutils-88f3d38340abb592f7e8bf9991a4479d447f631c.tar.gz
dwarflint: Make it possible to define relevant options directly at checks
-rw-r--r--dwarflint/Makefile.am2
-rw-r--r--dwarflint/TODO3
-rw-r--r--dwarflint/check_debug_info.cc8
-rw-r--r--dwarflint/check_debug_loc_range.cc5
-rw-r--r--dwarflint/check_matching_ranges.cc3
-rw-r--r--dwarflint/check_nodebug.cc7
-rw-r--r--dwarflint/checks.cc8
-rw-r--r--dwarflint/dwarflint.cc10
-rw-r--r--dwarflint/highlevel_check.hh8
-rw-r--r--dwarflint/low.c6
-rw-r--r--dwarflint/main.cc270
-rw-r--r--dwarflint/main.hh (renamed from dwarflint/options.h)30
-rw-r--r--dwarflint/option.cc133
-rw-r--r--dwarflint/option.hh147
-rw-r--r--dwarflint/options.cc43
-rw-r--r--dwarflint/sections.cc3
-rwxr-xr-xdwarflint/tests/run-nodebug.sh7
-rw-r--r--dwarflint/where.c5
18 files changed, 421 insertions, 277 deletions
diff --git a/dwarflint/Makefile.am b/dwarflint/Makefile.am
index a44751f7..faaedb62 100644
--- a/dwarflint/Makefile.am
+++ b/dwarflint/Makefile.am
@@ -49,7 +49,7 @@ dwarflint_SOURCES = \
messages.cc messages.h \
section_id.cc section_id.h \
where.c where.h \
- options.cc options.h \
+ option.cc option.hh \
addr-record.cc addr-record.h \
reloc.cc reloc.h \
tables.cc tables.hh tables.h \
diff --git a/dwarflint/TODO b/dwarflint/TODO
index e47c6122..99069b67 100644
--- a/dwarflint/TODO
+++ b/dwarflint/TODO
@@ -110,6 +110,9 @@
there to be frequent additions to this "quirks table", so it should
be fairly easy to extend this.
+ The current option --tolerant will go away when this is implemented.
+ I don't think it even works anyway.
+
* multi-file mode
While dwarflint manages checking several files (meaning you can put
diff --git a/dwarflint/check_debug_info.cc b/dwarflint/check_debug_info.cc
index 8e8a36f0..d99fdadb 100644
--- a/dwarflint/check_debug_info.cc
+++ b/dwarflint/check_debug_info.cc
@@ -1,6 +1,6 @@
/* Routines related to .debug_info.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009, 2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -34,7 +34,7 @@
#include "messages.h"
#include "pri.hh"
-#include "options.h"
+#include "option.hh"
#include "sections.hh"
#include "check_debug_loc_range.hh"
#include "check_debug_abbrev.hh"
@@ -93,6 +93,10 @@ check_debug_info::descriptor ()
return &cd;
}
+static void_option
+ dump_die_offsets ("Dump DIE offsets to stderr as the tree is iterated.",
+ "dump-offsets");
+
namespace
{
bool
diff --git a/dwarflint/check_debug_loc_range.cc b/dwarflint/check_debug_loc_range.cc
index d664122e..5a3f1268 100644
--- a/dwarflint/check_debug_loc_range.cc
+++ b/dwarflint/check_debug_loc_range.cc
@@ -1,6 +1,6 @@
/* Routines related to .debug_loc and .debug_range.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009, 2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -38,13 +38,14 @@
#include "../libdw/dwarf.h"
#include "low.h"
-#include "options.h"
#include "check_debug_loc_range.hh"
#include "check_debug_info.hh"
#include "sections.hh"
#include "../src/dwarf-opcodes.h"
#include "pri.hh"
+bool do_range_coverage = false; // currently no option
+
checkdescriptor const *
check_debug_ranges::descriptor ()
{
diff --git a/dwarflint/check_matching_ranges.cc b/dwarflint/check_matching_ranges.cc
index 0afdc078..f9c05962 100644
--- a/dwarflint/check_matching_ranges.cc
+++ b/dwarflint/check_matching_ranges.cc
@@ -59,9 +59,6 @@ check_matching_ranges::check_matching_ranges (checkstack &stack,
dwarflint &lint)
: highlevel_check<check_matching_ranges> (stack, lint)
{
- if (be_tolerant || be_gnu)
- throw check_base::unscheduled ();
-
lint.check<check_debug_ranges> (stack);
lint.check<check_debug_aranges> (stack);
diff --git a/dwarflint/check_nodebug.cc b/dwarflint/check_nodebug.cc
index e26d3dfb..fe9fbb0e 100644
--- a/dwarflint/check_nodebug.cc
+++ b/dwarflint/check_nodebug.cc
@@ -24,9 +24,9 @@
<http://www.openinventionnetwork.com>. */
#include "checks.hh"
-#include "options.h"
#include "messages.h"
#include "sections.hh"
+#include "option.hh"
class check_nodebug
: public check<check_nodebug>
@@ -62,10 +62,13 @@ private:
};
static reg<check_nodebug> reg_nodebug;
+static void_option ignore_missing
+ ("Don't complain if files have no DWARF at all",
+ "ignore-missing", 'i');
check_nodebug::check_nodebug (checkstack &stack, dwarflint &lint)
{
- if (tolerate_nodebug)
+ if (ignore_missing)
return;
// We demand .debug_info and .debug_abbrev, the rest is optional.
diff --git a/dwarflint/checks.cc b/dwarflint/checks.cc
index 16b7abe1..76ca27ae 100644
--- a/dwarflint/checks.cc
+++ b/dwarflint/checks.cc
@@ -24,7 +24,11 @@
<http://www.openinventionnetwork.com>. */
#include "checks.hh"
-#include "options.h"
+#include "option.hh"
+
+static void_option show_progress
+ ("Print out checks as they are performed, their context and result.",
+ "show-progress");
reporter::reporter (checkstack const &s, checkdescriptor const &a_cd)
: stack (s)
@@ -36,7 +40,7 @@ reporter::reporter (checkstack const &s, checkdescriptor const &a_cd)
void
reporter::operator () (char const *what, bool ext)
{
- if (!be_verbose)
+ if (!show_progress)
return;
if (false)
diff --git a/dwarflint/dwarflint.cc b/dwarflint/dwarflint.cc
index bbd17b5f..9c21dbcc 100644
--- a/dwarflint/dwarflint.cc
+++ b/dwarflint/dwarflint.cc
@@ -1,5 +1,5 @@
/* Dwarflint check scheduler.
- Copyright (C) 2008,2009 Red Hat, Inc.
+ Copyright (C) 2008,2009,2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#include "dwarflint.hh"
#include "messages.h"
#include "checks.hh"
-#include "options.h"
+#include "main.hh"
#include <fcntl.h>
#include <cstring>
@@ -122,6 +122,7 @@ namespace
void
dwarflint::check_registrar::list_checks () const
{
+ bool be_verbose = opt_list_checks.value () == "full";
typedef std::set<checkdescriptor const *> descset;
descset descriptors;
for (std::vector <item *>::const_iterator it = _m_items.begin ();
@@ -160,8 +161,9 @@ dwarflint::check_registrar::list_checks () const
}
}
if (!be_verbose)
- std::cout << "Use --list-checks --verbose "
- "to get detailed description of each check." << std::endl;
+ std::cout
+ << "Use --list-checks=full to get more detailed description."
+ << std::endl;
}
namespace
diff --git a/dwarflint/highlevel_check.hh b/dwarflint/highlevel_check.hh
index 5505ae15..7fb7b128 100644
--- a/dwarflint/highlevel_check.hh
+++ b/dwarflint/highlevel_check.hh
@@ -1,5 +1,5 @@
/* Pedantic checking of DWARF files.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009, 2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -31,7 +31,6 @@
#endif
#include "checks.hh"
-#include "options.h"
#include "c++/dwarf"
#include "../libdwfl/libdwfl.h"
@@ -69,10 +68,7 @@ public:
explicit highlevel_check (checkstack &stack, dwarflint &lint)
: _m_loader (lint.check (stack, _m_loader))
, dw (_m_loader->dw)
- {
- if (!do_high_level)
- throw check_base::unscheduled ();
- }
+ {}
};
template <class T>
diff --git a/dwarflint/low.c b/dwarflint/low.c
index d5950e14..9872d4ae 100644
--- a/dwarflint/low.c
+++ b/dwarflint/low.c
@@ -1,5 +1,5 @@
/* Pedantic checking of DWARF files
- Copyright (C) 2008,2009 Red Hat, Inc.
+ Copyright (C) 2008,2009,2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -46,7 +46,6 @@
#include "../src/dwarfstrings.h"
#include "low.h"
#include "readctx.h"
-#include "options.h"
#include "tables.h"
#define PRI_CU "CU 0x%" PRIx64
@@ -331,8 +330,7 @@ check_aranges_structural (struct elf_file *file,
inline void aranges_coverage_add (uint64_t begin, uint64_t length)
{
- if (coverage_is_overlap (aranges_coverage, begin, length)
- && !be_gnu && !be_tolerant)
+ if (coverage_is_overlap (aranges_coverage, begin, length))
{
char buf[128];
/* Not a show stopper, this shouldn't derail high-level. */
diff --git a/dwarflint/main.cc b/dwarflint/main.cc
index 05070d23..61a080be 100644
--- a/dwarflint/main.cc
+++ b/dwarflint/main.cc
@@ -1,5 +1,5 @@
/* Main entry point for dwarflint, a pedantic checker for DWARF files.
- Copyright (C) 2008,2009 Red Hat, Inc.
+ Copyright (C) 2008,2009,2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -26,7 +26,6 @@
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
-#include <argp.h>
#include <libintl.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -35,58 +34,10 @@
#include <sstream>
#include "low.h"
-#include "options.h"
#include "dwarflint.hh"
#include "readctx.h"
#include "checks.hh"
-
-/* Bug report address. */
-const char *argp_program_bug_address = PACKAGE_BUGREPORT;
-
-#define ARGP_strict 300
-#define ARGP_gnu 301
-#define ARGP_tolerant 302
-#define ARGP_ref 303
-#define ARGP_nohl 304
-#define ARGP_dump_off 305
-#define ARGP_check 306
-#define ARGP_list_checks 307
-
-/* Definitions of arguments for argp functions. */
-static const struct argp_option options[] =
-{
- { "strict", ARGP_strict, NULL, 0,
- N_("Be extremely strict, flag level 2 features."), 0 },
- { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
- { "ignore-missing", 'i', NULL, 0,
- N_("Don't complain if files have no DWARF at all"), 0 },
- { "gnu", ARGP_gnu, NULL, 0,
- N_("Binary has been created with GNU toolchain and is therefore known to be \
-broken in certain ways"), 0 },
- { "tolerant", ARGP_tolerant, NULL, 0,
- N_("Don't output certain common error messages"), 0 },
- { "ref", ARGP_ref, NULL, 0,
- N_("When validating .debug_loc and .debug_ranges, display information about \
-the DIE referring to the entry in consideration"), 0 },
- { "nohl", ARGP_nohl, NULL, 0,
- N_("Don't run high-level tests"), 0 },
- { "verbose", 'v', NULL, 0,
- N_("Be verbose"), 0 },
- { "dump-offsets", ARGP_dump_off, NULL, 0,
- N_("Dump DIE offsets to stderr as the tree is iterated."), 0 },
- { "check", ARGP_check, "[+-][@]name,...", 0,
- N_("Only run selected checks."), 0 },
- { "list-checks", ARGP_list_checks, NULL, 0,
- N_("List all the available checks."), 0 },
- { NULL, 0, NULL, 0, NULL, 0 }
-};
-
-/* Short description of program. */
-static const char doc[] = N_("\
-Pedantic checking of DWARF stored in ELF files.");
-
-/* Strings for arguments in help texts. */
-static const char args_doc[] = N_("FILE...");
+#include "option.hh"
/* Messages that are accepted (and made into warning). */
struct message_criteria warning_criteria;
@@ -94,142 +45,94 @@ struct message_criteria warning_criteria;
/* Accepted (warning) messages, that are turned into errors. */
struct message_criteria error_criteria;
-/* Whether to list available checks and exit. */
-static bool just_list_checks = false;
-
-
-static error_t parse_opt (int key, char *arg, struct argp_state *state);
-
-/* Data structure to communicate with argp functions. */
-static struct argp argp =
-{
- options, parse_opt, args_doc, doc, NULL, NULL, NULL
-};
-
-struct initial_check_rules
- : public check_rules
-{
- initial_check_rules () {
- push_back (check_rule ("@all", check_rule::request));
- push_back (check_rule ("@nodefault", check_rule::forbid));
- }
-} rules;
-
-/* Handle program arguments. */
-static error_t
-parse_opt (int key, char *arg __attribute__ ((unused)),
- struct argp_state *state __attribute__ ((unused)))
+struct check_option_t
+ : public option_common
{
- switch (key)
- {
- case ARGP_strict:
- be_strict = true;
- break;
-
- case ARGP_gnu:
- be_gnu = true;
- break;
-
- case ARGP_tolerant:
- be_tolerant = true;
- break;
-
- case ARGP_ref:
- show_refs = true;
- break;
+ struct initial_check_rules
+ : public check_rules
+ {
+ initial_check_rules () {
+ push_back (check_rule ("@all", check_rule::request));
+ push_back (check_rule ("@nodefault", check_rule::forbid));
+ }
+ } rules;
- case ARGP_nohl:
- do_high_level = false;
- break;
+ check_option_t ()
+ : option_common ("Only run selected checks.",
+ "[+-][@]name,...", "check", 0)
+ {}
- case ARGP_dump_off:
- dump_die_offsets = true;
- break;
+ error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
+ {
+ static bool first = true;
+ std::stringstream ss (arg);
+ std::string item;
- case ARGP_check:
+ while (std::getline (ss, item, ','))
{
- static bool first = true;
- std::stringstream ss (arg);
- std::string item;
+ if (item.empty ())
+ continue;
- while (std::getline (ss, item, ','))
+ enum {
+ forbid,
+ request,
+ replace
+ } act;
+
+ // If the first rule has no operator, we assume the user
+ // wants to replace the implicit set of checks.
+ if (first)
{
- if (item.empty ())
- continue;
-
- enum {
- forbid,
- request,
- replace
- } act;
-
- // If the first rule has no operator, we assume the user
- // wants to replace the implicit set of checks.
- if (first)
- {
- act = replace;
- first = false;
- }
- else
- // Otherwise the rules are implicitly requesting, even
- // without the '+' operator.
- act = request;
-
- bool minus = item[0] == '-';
- bool plus = item[0] == '+';
- if (plus || minus)
- item = item.substr (1);
- if (plus)
- act = request;
- if (minus)
- act = forbid;
-
- if (act == replace)
- {
- rules.clear ();
- act = request;
- }
-
- check_rule::action_t action
- = act == request ? check_rule::request : check_rule::forbid;
- rules.push_back (check_rule (item, action));
+ act = replace;
+ first = false;
+ }
+ else
+ // Otherwise the rules are implicitly requesting, even
+ // without the '+' operator.
+ act = request;
+
+ bool minus = item[0] == '-';
+ bool plus = item[0] == '+';
+ if (plus || minus)
+ item = item.substr (1);
+ if (plus)
+ act = request;
+ if (minus)
+ act = forbid;
+
+ if (act == replace)
+ {
+ rules.clear ();
+ act = request;
}
- }
- break;
-
- case ARGP_list_checks:
- just_list_checks = true;
- break;
- case 'i':
- tolerate_nodebug = true;
- break;
+ check_rule::action_t action
+ = act == request ? check_rule::request : check_rule::forbid;
+ rules.push_back (check_rule (item, action));
+ }
+ return 0;
+ }
+} check_option;
- case 'q':
- be_quiet = true;
- be_verbose = false;
- break;
+void_option be_quiet ("Do not print anything if successful",
+ "quiet", 'q');
- case 'v':
- be_quiet = false;
- be_verbose = true;
- break;
+string_option opt_list_checks ("List all the available checks.",
+ "full", "list-checks", 0,
+ OPTION_ARG_OPTIONAL);
- case ARGP_KEY_NO_ARGS:
- if (!just_list_checks)
- {
- fputs (gettext ("Missing file name.\n"), stderr);
- argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
- program_invocation_short_name);
- exit (1);
- }
- break;
+// xxx The following three should go away when we introduce the
+// message filtering. Or should be preserved, but in a way that makes
+// more sense, right now they are simply a misnomer.
+void_option ignore_bloat ("Ignore messages related to bloat.", "ignore-bloat");
+void_option be_strict ("Be somewhat stricter.", "strict");
+void_option be_tolerant ("Be somewhat more tolerant.", "tolerant");
- default:
- return ARGP_ERR_UNKNOWN;
- }
- return 0;
-}
+// xxx as soon as where is in c++, this can move there
+void_option opt_show_refs = void_option (
+"When validating .debug_loc and .debug_ranges, display information about \
+the DIE referring to the entry in consideration", "ref");
+extern "C" bool show_refs () { return (bool)opt_show_refs; }
int
main (int argc, char *argv[])
@@ -241,14 +144,22 @@ main (int argc, char *argv[])
textdomain (PACKAGE_TARNAME);
/* Parse and process arguments. */
+ struct argp argp = options::registered ().build_argp ();
int remaining;
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
- if (just_list_checks)
+ if (opt_list_checks.seen ())
{
dwarflint::check_registrar::inst ()->list_checks ();
std::exit (0);
}
+ else if (remaining == argc)
+ {
+ fputs (gettext ("Missing file name.\n"), stderr);
+ argp_help (&argp, stderr, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
+ program_invocation_short_name);
+ std::exit (1);
+ }
/* Initialize warning & error criteria. */
warning_criteria |= message_term (mc_none, mc_none);
@@ -257,10 +168,7 @@ main (int argc, char *argv[])
error_criteria |= message_term (mc_error, mc_none);
/* Configure warning & error criteria according to configuration. */
- if (tolerate_nodebug)
- warning_criteria &= message_term (mc_none, mc_elf);
-
- if (be_gnu)
+ if (ignore_bloat)
warning_criteria &= message_term (mc_none, mc_acc_bloat);
if (!be_strict)
@@ -277,7 +185,7 @@ main (int argc, char *argv[])
warning_criteria &= message_term (mc_none, mc_ranges);
}
- if (be_verbose)
+ if (false) // for debugging
{
std::cout << "warning criteria: " << warning_criteria.str () << std::endl;
std::cout << "error criteria: " << error_criteria.str () << std::endl;
@@ -297,7 +205,7 @@ main (int argc, char *argv[])
unsigned int prev_error_count = error_count;
if (!only_one)
std::cout << std::endl << fname << ":" << std::endl;
- dwarflint lint (fname, rules);
+ dwarflint lint (fname, check_option.rules);
if (prev_error_count == error_count && !be_quiet)
puts (gettext ("No errors"));
diff --git a/dwarflint/options.h b/dwarflint/main.hh
index 157d56f5..0651895d 100644
--- a/dwarflint/options.h
+++ b/dwarflint/main.hh
@@ -1,5 +1,5 @@
-/*
- Copyright (C) 2008,2009 Red Hat, Inc.
+/* Pedantic checker for DWARF files
+ Copyright (C) 2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -23,26 +23,10 @@
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
-#ifdef __cplusplus
-extern "C"
-{
-#else
-#include <stdbool.h>
-#endif
+#ifndef DWARFLINT_MAIN_HH
+#define DWARFLINT_MAIN_HH
- /* Whole-program options. */
- extern bool tolerate_nodebug;
- extern bool be_quiet; /* -q */
- extern bool be_verbose; /* -v */
- extern bool be_strict; /* --strict */
- extern bool be_gnu; /* --gnu */
- extern bool be_tolerant; /* --tolerant */
- extern bool show_refs; /* --ref */
- extern bool do_high_level; /* ! --nohl */
- extern bool dump_die_offsets; /* --dump-offsets */
+#include "option.hh"
+extern string_option opt_list_checks;
- extern bool do_range_coverage;
-
-#ifdef __cplusplus
-}
-#endif
+#endif//DWARFLINT_MAIN_HH
diff --git a/dwarflint/option.cc b/dwarflint/option.cc
new file mode 100644
index 00000000..6fadf9ab
--- /dev/null
+++ b/dwarflint/option.cc
@@ -0,0 +1,133 @@
+/* Pedantic checking of DWARF files
+ Copyright (C) 2009,2010 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 "option.hh"
+#include <cassert>
+#include <cstring>
+#include <iostream>
+
+option_common *
+options::opt (int key) const
+{
+ const_iterator it = find (key);
+ if (it == end ())
+ return NULL;
+ return it->second;
+}
+
+option_common const *
+options::getopt (int key) const
+{
+ return opt (key);
+}
+
+error_t
+options::parse_opt (int key, char *arg,
+ __attribute__ ((unused)) argp_state *state)
+{
+ option_common *o = registered ().opt (key);
+ if (o == NULL)
+ return ARGP_ERR_UNKNOWN;
+ return o->parse_opt (arg, state);
+}
+
+struct last_option
+ : public argp_option
+{
+ last_option () {
+ std::memset (this, 0, sizeof (*this));
+ }
+};
+
+/* Bug report address. */
+const char *argp_program_bug_address = PACKAGE_BUGREPORT;
+
+argp
+options::build_argp ()
+{
+ _m_opts.clear ();
+ for (const_iterator it = begin (); it != end (); ++it)
+ _m_opts.push_back (it->second->build_option ());
+ _m_opts.push_back (last_option ());
+ argp a = {
+ &_m_opts.front (),
+ &options::parse_opt,
+ "FILE...",
+ "\
+Pedantic checking of DWARF stored in ELF files.",
+ NULL, NULL, NULL
+ };
+ return a;
+}
+
+
+int option_common::_m_last_opt = 300;
+
+options &
+options::registered ()
+{
+ static options opts;
+ return opts;
+}
+
+int
+option_common::get_short_option (char opt_short)
+{
+ if (opt_short)
+ return opt_short;
+ return _m_last_opt++;
+}
+
+namespace
+{
+ argp_option argp_option_ctor (char const *name, int key,
+ char const *arg, int flags,
+ char const *doc, int group)
+ {
+ assert (name != NULL);
+ assert (doc != NULL);
+ argp_option opt = {
+ name, key, arg, flags, doc, group
+ };
+ return opt;
+ }
+}
+
+option_common::option_common (char const *description,
+ char const *arg_description,
+ char const *opt_long, char opt_short,
+ int flags)
+ : _m_opt (argp_option_ctor (opt_long, get_short_option (opt_short),
+ arg_description, flags,
+ description, 0))
+ , _m_seen (false)
+{
+ assert (options::registered ().getopt (_m_opt.key) == NULL);
+ options::registered ()[_m_opt.key] = this;
+}
diff --git a/dwarflint/option.hh b/dwarflint/option.hh
new file mode 100644
index 00000000..aa256d62
--- /dev/null
+++ b/dwarflint/option.hh
@@ -0,0 +1,147 @@
+/* Pedantic checker for DWARF files
+ Copyright (C) 2010 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_OPTION_HH
+#define DWARFLINT_OPTION_HH
+
+#include <string>
+#include <argp.h>
+#include <map>
+#include <vector>
+#include <cassert>
+
+#include <iostream>
+
+class option_common;
+
+class options
+ : private std::map<int, option_common *>
+{
+ friend class option_common;
+ std::vector<argp_option> _m_opts;
+
+ option_common *opt (int key) const;
+ static error_t parse_opt (int key, char *arg, argp_state *state);
+
+public:
+ static options &registered ();
+ option_common const *getopt (int key) const;
+ argp build_argp ();
+};
+
+class option_common
+{
+ argp_option _m_opt;
+
+ static int _m_last_opt;
+ static int get_short_option (char opt_short);
+
+protected:
+ bool _m_seen;
+
+ option_common (char const *description,
+ char const *arg_description,
+ char const *opt_long, char opt_short,
+ int flags = 0);
+
+public: // consumer interface
+ bool seen () const { return _m_seen; }
+
+public: // option handler interface
+ argp_option const &build_option () const { return _m_opt; }
+ virtual error_t parse_opt (char *arg, argp_state *state) = 0;
+};
+
+template<class arg_type>
+class value_converter;
+
+template<class arg_type>
+class xoption
+ : public option_common
+{
+ arg_type _m_arg;
+
+public:
+ xoption (char const *description,
+ char const *arg_description,
+ char const *opt_long, char opt_short = 0,
+ int flags = 0)
+ : option_common (description, arg_description, opt_long, opt_short, flags)
+ {
+ }
+
+ arg_type const &value () const
+ {
+ return _m_arg;
+ }
+
+ error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
+ {
+ _m_seen = true;
+ _m_arg = value_converter<arg_type>::convert (arg);
+ return 0;
+ }
+};
+
+template<>
+class xoption<void>
+ : public option_common
+{
+public:
+ xoption (char const *description,
+ char const *opt_long, char opt_short = 0, int flags = 0)
+ : option_common (description, NULL, opt_long, opt_short, flags)
+ {
+ }
+
+ error_t parse_opt (char *arg, __attribute__ ((unused)) argp_state *state)
+ {
+ assert (arg == NULL);
+ _m_seen = true;
+ return 0;
+ }
+
+ // This shouldn't be promoted to option_common, as
+ // e.g. xoption<bool> will naturally have a different
+ // implementation.
+ operator bool () { return seen (); }
+};
+
+template<>
+struct value_converter<std::string>
+{
+ static std::string convert (char const *arg)
+ {
+ if (arg == NULL)
+ return "";
+ else
+ return arg;
+ }
+};
+
+typedef xoption<void> void_option;
+typedef xoption<std::string> string_option;
+
+#endif//DWARFLINT_OPTION_HH
diff --git a/dwarflint/options.cc b/dwarflint/options.cc
deleted file mode 100644
index ff3b5e2c..00000000
--- a/dwarflint/options.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- Copyright (C) 2008,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>. */
-
-#include "options.h"
-
-/* If true, we accept silently files without debuginfo. */
-bool tolerate_nodebug = false;
-
-/* True if no message is to be printed if the run is succesful. */
-bool be_quiet = false; /* -q */
-bool be_verbose = false; /* -v */
-bool be_strict = false; /* --strict */
-bool be_gnu = false; /* --gnu */
-bool be_tolerant = false; /* --tolerant */
-bool show_refs = false; /* --ref */
-bool do_high_level = true; /* ! --nohl */
-bool dump_die_offsets = false; /* --dump-offsets */
-
-/* True if coverage analysis of .debug_ranges vs. ELF sections should
- be done. */
-bool do_range_coverage = false; // currently no option
diff --git a/dwarflint/sections.cc b/dwarflint/sections.cc
index a8932334..1e07987e 100644
--- a/dwarflint/sections.cc
+++ b/dwarflint/sections.cc
@@ -1,5 +1,5 @@
/* Low-level section handling.
- Copyright (C) 2009 Red Hat, Inc.
+ Copyright (C) 2009, 2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
@@ -34,7 +34,6 @@
#include "sections.hh"
#include "messages.h"
#include "pri.hh"
-#include "options.h"
checkdescriptor const *
load_sections::descriptor ()
diff --git a/dwarflint/tests/run-nodebug.sh b/dwarflint/tests/run-nodebug.sh
index f853e13c..a595433c 100755
--- a/dwarflint/tests/run-nodebug.sh
+++ b/dwarflint/tests/run-nodebug.sh
@@ -33,3 +33,10 @@ testrun_compare ./dwarflint nodebug <<EOF
error: .debug_abbrev: data not found.
error: .debug_info: data not found.
EOF
+
+testrun_compare ./dwarflint -i nodebug <<EOF
+No errors
+EOF
+
+testrun_compare ./dwarflint -q -i nodebug <<EOF
+EOF
diff --git a/dwarflint/where.c b/dwarflint/where.c
index 3e284565..ca9f0cd5 100644
--- a/dwarflint/where.c
+++ b/dwarflint/where.c
@@ -24,7 +24,6 @@
<http://www.openinventionnetwork.com>. */
#include "where.h"
-#include "options.h"
#include <inttypes.h>
#include <assert.h>
@@ -32,6 +31,8 @@
#include <stdio.h>
#include <string.h>
+extern bool show_refs (void);
+
const char *
where_fmt (const struct where *wh, char *ptr)
{
@@ -189,7 +190,7 @@ where_fmt (const struct where *wh, char *ptr)
void
where_fmt_chain (const struct where *wh, const char *severity)
{
- if (wh != NULL && show_refs)
+ if (wh != NULL && show_refs ())
for (struct where const *it = wh->next; it != NULL; it = it->next)
printf ("%s: %s: caused by this reference.\n",
severity, where_fmt (it, NULL));