summaryrefslogtreecommitdiffstats
path: root/coveragedb.cxx
diff options
context:
space:
mode:
authorwcohen <wcohen>2007-06-26 19:36:25 +0000
committerwcohen <wcohen>2007-06-26 19:36:25 +0000
commitc3a3c0c99c32c0969e6450d60aae1a2b1798ca17 (patch)
tree536bc183503bbcb0fbfa4ce419175e59a0855983 /coveragedb.cxx
parent23944d00d55ecc08acbb0e2f39f7fb5cd7a0580e (diff)
downloadsystemtap-steved-c3a3c0c99c32c0969e6450d60aae1a2b1798ca17.tar.gz
systemtap-steved-c3a3c0c99c32c0969e6450d60aae1a2b1798ca17.tar.xz
systemtap-steved-c3a3c0c99c32c0969e6450d60aae1a2b1798ca17.zip
2007-06-26 William Cohen <wcohen@redhat.com>
PR 4529 * coveragedb.cxx: New. * coveragedb.h: New. * Makefile.am: Add coveragedb.cxx and sqlite3 to build. * Makefile.in: Regenerated. * configure.ac: Add test for sqlite3 * configure: Regenerated. * systemtap.spec.in: Add dependencies for sqlite3/sqlite3-devel. * elaborate.h, elaborate.cxx (derived_probe::collect_derivation_chain): New. (alias_expansion_builder::build): Correct token location. (semantic_pass_opt[12): Track used and unused variables/functions. * session.h (tapset_compile_coverage, unused_globals, unused_probes, unused_functions): New fields. * staptree.h (unused_locals, probe_point::str): New member. * staptree.cxx: Ditto. * main.cxx: Add "-q" tapset coverage option and SYSTEMTAP_COVERAGE env.
Diffstat (limited to 'coveragedb.cxx')
-rw-r--r--coveragedb.cxx322
1 files changed, 322 insertions, 0 deletions
diff --git a/coveragedb.cxx b/coveragedb.cxx
new file mode 100644
index 00000000..69eb95b4
--- /dev/null
+++ b/coveragedb.cxx
@@ -0,0 +1,322 @@
+// coveragedb.cxx
+// Copyright (C) 2007 Red Hat Inc.
+//
+// This file is part of systemtap, and is free software. You can
+// redistribute it and/or modify it under the terms of the GNU General
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+#include "parse.h"
+#include "coveragedb.h"
+#include "config.h"
+#include "elaborate.h"
+#include "tapsets.h"
+#include "session.h"
+#include "util.h"
+
+#include <iostream>
+#include <sqlite3.h>
+
+using namespace std;
+
+void print_coverage_info(systemtap_session &s)
+{
+ vector<derived_probe*> used_probe_list;
+ vector<derived_probe*> unused_probe_list;
+ // print out used probes
+ clog << "---- used probes-----" << endl;
+ for (unsigned i=0; i<s.probes.size(); i++) {
+ // walk through the chain of probes
+ s.probes[i]->collect_derivation_chain(used_probe_list);
+ for (unsigned j=0; j<used_probe_list.size(); ++j) {
+ for (unsigned k=0; k< used_probe_list[j]->locations.size(); ++k)
+ clog << "probe: "
+ << used_probe_list[j]->locations[k]->tok->location << endl;
+ }
+
+ clog << "----" << endl;
+ // for each probe print used and unused variables
+ for (unsigned j=0; j<s.probes[i]->locals.size(); ++j) {
+ clog << "local: " << s.probes[i]->locals[j]->tok->location << endl;
+ }
+ for (unsigned j=0; j<s.probes[i]->unused_locals.size(); ++j) {
+ clog << "unused_local: "
+ << s.probes[i]->unused_locals[j]->tok->location
+ << endl;
+ }
+ }
+ // print out unused probes
+ clog << "---- unused probes----- " << endl;
+ for (unsigned i=0; i<s.unused_probes.size(); i++) {
+ // walk through the chain of probes
+ s.probes[i]->collect_derivation_chain(unused_probe_list);
+ for (unsigned j=0; j<unused_probe_list.size(); ++j) {
+ for (unsigned k=0; k< unused_probe_list[j]->locations.size(); ++k)
+ clog << "probe: "
+ << unused_probe_list[j]->locations[k]->tok->location << endl;
+ }
+
+ }
+ // print out used functions
+ clog << "---- used functions----- " << endl;
+ for (unsigned i=0; i<s.functions.size(); i++) {
+ clog << "function: " << s.functions[i]->tok->location
+ << " " << s.functions[i]->name
+ << endl;
+ }
+ // print out unused functions
+ clog << "---- unused functions----- " << endl;
+ for (unsigned i=0; i<s.unused_functions.size(); i++) {
+ clog << "unused_function: " << s.unused_functions[i]->tok->location
+ << " " << s.unused_functions[i]->name
+ << endl;
+ }
+ // print out used globals
+ clog << "---- used globals----- " << endl;
+ for (unsigned i=0; i<s.globals.size(); i++) {
+ clog << "globals: " << s.globals[i]->tok->location
+ << " " << s.globals[i]->name
+ << endl;
+ }
+ // print out unused globals
+ clog << "---- unused globals----- " << endl;
+ for (unsigned i=0; i<s.unused_globals.size(); i++) {
+ clog << "globals: " << s.unused_globals[i]->tok->location
+ << " " << s.unused_globals[i]->name
+ << endl;
+ }
+}
+
+
+void sql_stmt(sqlite3 *db, const char* stmt)
+{
+ char *errmsg;
+ int ret;
+
+ // cerr << "sqlite: " << stmt << endl;
+
+ ret = sqlite3_exec(db, stmt, 0, 0, &errmsg);
+
+ if(ret != SQLITE_OK) {
+ cerr << "Error in statement: " << stmt << " [" << errmsg << "]."
+ << endl;
+ }
+}
+
+void enter_element(sqlite3 *db, coverage_element &x)
+{
+ ostringstream command;
+ command << "insert or ignore into counts values ('"
+ << x.file << "', '"
+ << x.line << "', '"
+ << x.col << "', '"
+ << x.type << "','"
+ << x.name << "', '"
+ << x.parent <<"',"
+ << "'0', '0', '0')";
+ sql_stmt(db, command.str().c_str());
+}
+
+void increment_element(sqlite3 *db, coverage_element &x)
+{
+ // make sure value in table
+ enter_element(db, x);
+ // increment appropriate value
+ if (x.compiled) {
+ ostringstream command;
+ command << "update counts set compiled = compiled + "
+ << x.compiled << " where ("
+ << "file == '" << x.file << "' and "
+ << "line == '" << x.line << "' and "
+ << "col == '" << x.col << "')";
+ sql_stmt(db, command.str().c_str());
+ }
+ if (x.removed) {
+ ostringstream command;
+ command << "update counts set removed = removed + "
+ << x.removed << " where ("
+ << "file == '" << x.file << "' and "
+ << "line == '" << x.line << "' and "
+ << "col == '" << x.col << "')";
+ sql_stmt(db, command.str().c_str());
+ }
+}
+
+
+void
+sql_update_used_probes(sqlite3 *db, systemtap_session &s)
+{
+ vector<derived_probe*> used_probe_list;
+
+ // update database used probes
+ for (unsigned i=0; i<s.probes.size(); i++) {
+ // walk through the chain of probes
+ s.probes[i]->collect_derivation_chain(used_probe_list);
+ for (unsigned j=0; j<used_probe_list.size(); ++j) {
+ for (unsigned k=0; k< used_probe_list[j]->locations.size(); ++k){
+ struct source_loc place = used_probe_list[j]->locations[k]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("p");
+ x.name = used_probe_list[j]->locations[k]->str();
+ x.compiled = 1;
+ increment_element(db, x);
+ }
+ }
+
+ // for each probe update used and unused variables
+ for (unsigned j=0; j<s.probes[i]->locals.size(); ++j) {
+ struct source_loc place = s.probes[i]->locals[j]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("l");
+ x.name = s.probes[i]->locals[j]->tok->content;
+ x.compiled = 1;
+ increment_element(db, x);
+ }
+ for (unsigned j=0; j<s.probes[i]->unused_locals.size(); ++j) {
+ struct source_loc place = s.probes[i]->unused_locals[j]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("l");
+ x.name = s.probes[i]->unused_locals[j]->tok->content;
+ x.removed = 1;
+ increment_element(db, x);
+ }
+ }
+}
+
+
+void
+sql_update_unused_probes(sqlite3 *db, systemtap_session &s)
+{
+ vector<derived_probe*> unused_probe_list;
+
+ // update database unused probes
+ for (unsigned i=0; i<s.unused_probes.size(); i++) {
+ // walk through the chain of probes
+ s.probes[i]->collect_derivation_chain(unused_probe_list);
+ for (unsigned j=0; j<unused_probe_list.size(); ++j) {
+ for (unsigned k=0; k< unused_probe_list[j]->locations.size(); ++k) {
+
+ struct source_loc place = unused_probe_list[j]->locations[k]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("p");
+ x.name = unused_probe_list[j]->locations[k]->str();
+ x.removed = 1;
+ increment_element(db, x);
+ }
+ }
+ }
+}
+
+
+void
+sql_update_used_functions(sqlite3 *db, systemtap_session &s)
+{
+ // update db used functions
+ for (unsigned i=0; i<s.functions.size(); i++) {
+ struct source_loc place = s.functions[i]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("f");
+ x.name = s.functions[i]->name;
+ x.compiled = 1;
+ increment_element(db, x);
+ }
+}
+
+
+void
+sql_update_unused_functions(sqlite3 *db, systemtap_session &s)
+{
+ // update db unused functions
+ for (unsigned i=0; i<s.unused_functions.size(); i++) {
+ struct source_loc place = s.unused_functions[i]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("f");
+ x.name = s.unused_functions[i]->name;
+ x.removed = 1;
+ increment_element(db, x);
+ }
+}
+
+
+void
+sql_update_used_globals(sqlite3 *db, systemtap_session &s)
+{
+ // update db used globals
+ for (unsigned i=0; i<s.globals.size(); i++) {
+ sql_stmt(db, "--");
+ struct source_loc place = s.globals[i]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("g");
+ x.name = s.globals[i]->name;
+ x.compiled = 1;
+ increment_element(db, x);
+ }
+}
+
+
+void
+sql_update_unused_globals(sqlite3 *db, systemtap_session &s)
+{
+ // update db unused globals
+ for (unsigned i=0; i<s.unused_globals.size(); i++) {
+ struct source_loc place = s.unused_globals[i]->tok->location;
+ coverage_element x(place);
+
+ x.type = string("g");
+ x.name = s.unused_globals[i]->name;
+ x.removed = 1;
+ increment_element(db, x);
+ }
+}
+
+
+
+void update_coverage_db(systemtap_session &s)
+{
+ sqlite3 *db;
+ int rc;
+
+ string filename(s.data_path + "/" + s.kernel_release + ".db");
+
+ rc = sqlite3_open(filename.c_str(), &db);
+ if( rc ){
+ cerr << "Can't open database: " << sqlite3_errmsg(db) << endl;
+ sqlite3_close(db);
+ exit(EXIT_FAILURE);
+ }
+
+ string create_table("create table if not exists counts ("
+ "file text, line integer, col integer, "
+ "type text, name text, parent text, "
+ "compiled integer, removed integer, executed integer, "
+ "primary key (file, line, col))"
+ );
+
+ // lock the database
+ sql_stmt(db, "begin");
+
+ // update the number counts on things
+ sql_stmt(db, create_table.c_str());
+
+ if (s.verbose >2)
+ print_coverage_info(s);
+
+ sql_update_used_probes(db, s);
+ sql_update_unused_probes(db, s);
+ sql_update_used_functions(db, s);
+ sql_update_unused_functions(db, s);
+ sql_update_used_globals(db, s);
+ sql_update_unused_globals(db, s);
+
+ // unlock the database and close database
+ sql_stmt(db, "commit");
+
+ sqlite3_close(db);
+}