commit 312b05e01189aa907c6b96808726e12be2c810c7
parent bee0b0763782fe5e1ee206621fde904eb94f56b5
Author: Kyle Milz <kyle@0x30.net>
Date: Mon, 1 Aug 2016 11:30:16 -0600
src: add logging to citrun-inst
Diffstat:
M | src/inst_main.cc | | | 130 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------- |
1 file changed, 97 insertions(+), 33 deletions(-)
diff --git a/src/inst_main.cc b/src/inst_main.cc
@@ -15,6 +15,7 @@
*/
#include <sys/stat.h> // stat
#include <sys/time.h> // utimes
+#include <sys/utsname.h> // uname
#include <sys/wait.h> // waitpid
#include <clang/Frontend/TextDiagnosticPrinter.h>
@@ -25,10 +26,9 @@
#include <cstring> // strcmp
#include <err.h>
#include <fstream>
-#include <iostream>
#include <sstream>
#include <string>
-#include <unistd.h> // execvp, fork, unlink
+#include <unistd.h> // execvp, fork, getpid, unlink
#include "inst_action.h"
@@ -40,17 +40,26 @@ static llvm::cl::OptionCategory ToolingCategory("instrument options");
class CitrunInst {
public:
CitrunInst(int, char *argv[]);
- int instrument();
- void patch_link_command();
- int fork_compiler();
- void restore_original_src();
+ ~CitrunInst();
+
+ int instrument();
+ void patch_link_command();
+ int compile_modified();
private:
+ void clean_path();
+ int fork_compiler();
+ void restore_original_src();
+
std::vector<char *> m_args;
std::vector<std::string> m_source_files;
std::map<std::string, std::string> m_temp_file_map;
bool m_object_arg;
bool m_compile_arg;
+ std::error_code m_ec;
+ llvm::raw_fd_ostream m_log;
+ pid_t m_pid;
+ std::string m_pfx;
};
// Returns true if value ends with suffix, false otherwise.
@@ -95,11 +104,29 @@ copy_file(std::string const &dst_fn, std::string const &src_fn)
CitrunInst::CitrunInst(int argc, char *argv[]) :
m_args(argv, argv + argc),
m_object_arg(false),
- m_compile_arg(false)
+ m_compile_arg(false),
+ m_ec(),
+ m_log("citrun.log", m_ec, llvm::sys::fs::F_Append),
+ m_pid(getpid()),
+ m_pfx(std::to_string(m_pid) + ": ")
{
+ struct utsname utsname;
+ if (uname(&utsname) == -1)
+ err(1, "uname");
+
+ m_log << m_pfx << "citrun-inst v0.0 on " << utsname.sysname
+ << "-" << utsname.release << " " << utsname.machine << "\n";
+ m_log << m_pfx << "This program is called '" << m_args[0] << "'.\n";
+
+ setprogname("citrun-inst");
+ clean_path();
+
+ m_log << m_pfx << "Processing " << m_args.size() << " command line arguments.\n";
+
for (auto &arg : m_args) {
if (std::strcmp(arg, "-E") == 0) {
- // Preprocessing argument found, exec native command
+ m_log << m_pfx << "Preprocessor argument found\n";
+
m_args.push_back(NULL);
if (execvp(m_args[0], &m_args[0]))
err(1, "execvp");
@@ -113,8 +140,8 @@ CitrunInst::CitrunInst(int argc, char *argv[]) :
if (ends_with(arg, ".c") || ends_with(arg, ".cc") ||
ends_with(arg, ".cpp") || ends_with(arg, ".cxx")) {
- // Keep track of original source file names
m_source_files.push_back(arg);
+ m_log << m_pfx << "Found source file '" << arg << "'.\n";
char *dst_fn;
if ((dst_fn = std::tmpnam(NULL)) == NULL)
@@ -124,6 +151,14 @@ CitrunInst::CitrunInst(int argc, char *argv[]) :
m_temp_file_map[arg] = dst_fn;
}
}
+
+ m_log << m_pfx << "Object arg = " << m_object_arg << ", "
+ << "compile arg = " << m_compile_arg << "\n";
+}
+
+CitrunInst::~CitrunInst()
+{
+ m_log << m_pfx << "citrun-inst is done.\n";
}
int
@@ -131,12 +166,20 @@ CitrunInst::instrument()
{
std::vector<const char *> clang_argv;
- if (m_source_files.size() == 0)
+ if (m_source_files.size() == 0) {
+ m_log << m_pfx << "No source files to instrument.\n";
return 0;
+ }
+ // Construct a speical command line for ClangTool.
clang_argv.push_back(m_args[0]);
- for (auto s : m_source_files)
+ m_log << m_pfx << "Attempting instrumentation on";
+
+ for (auto s : m_source_files) {
+ m_log << " '" << s << "'";
clang_argv.push_back(s.c_str());
+ }
+ m_log << ".\n";
clang_argv.push_back("--");
@@ -149,34 +192,39 @@ CitrunInst::instrument()
#elif defined(__APPLE__)
clang_argv.push_back("-I/opt/local/libexec/llvm-3.7/lib/clang/3.7/include");
#endif
+ m_log << m_pfx << "Adding search path '" << clang_argv.back() << "'.\n";
// give clang it's <source files> -- <native command line> arg style
int clang_argc = clang_argv.size();
clang::tooling::CommonOptionsParser op(clang_argc, &clang_argv[0], ToolingCategory);
clang::tooling::ClangTool Tool(op.getCompilations(), op.getSourcePathList());
- std::error_code ec;
- llvm::raw_fd_ostream output("citrun.log", ec, llvm::sys::fs::F_None);
clang::DiagnosticOptions diags;
+ clang::TextDiagnosticPrinter *log;
+
+ log = new clang::TextDiagnosticPrinter(m_log, &diags, false);
+ log->setPrefix(std::to_string(m_pid));
+ Tool.setDiagnosticConsumer(log);
- Tool.setDiagnosticConsumer(new clang::TextDiagnosticPrinter(output, &diags, false));
int ret = Tool.run(&(*clang::tooling::newFrontendActionFactory<InstrumentAction>()));
- if (ret == 0)
+ if (ret == 0) {
+ m_log << m_pfx << "Instrumentation successful.\n";
return 0;
+ }
+
+ m_log << m_pfx << "Instrumentation failed.\n";
+ m_log << m_pfx << "Attempting compilation of unmodified source.\n";
- // Instrumentation failed, try compiling with native compiler.
restore_original_src();
ret = fork_compiler();
- // Native compiler succeeded. This is bad.
if (ret == 0) {
- warnx("citrun instrumentation failed, but the native "
- "compile succeeded!");
+ m_log << m_pfx << "Bad news, native compile succeeded.\n";
return 0;
}
- // Native compiler failed too. That's okay.
+ m_log << m_pfx << "Good, the native compiler also failed.\n";
return ret;
}
@@ -184,6 +232,7 @@ void
CitrunInst::restore_original_src()
{
for (auto &tmp_file : m_temp_file_map) {
+ m_log << m_pfx << "Restored '" << tmp_file.first << "'\n";
copy_file(tmp_file.first, tmp_file.second);
unlink(tmp_file.second.c_str());
}
@@ -212,6 +261,8 @@ CitrunInst::patch_link_command()
m_args.push_back(const_cast<char *>("-pthread"));
#endif
m_args.push_back(const_cast<char *>(STR(CITRUN_LIB)));
+
+ m_log << m_pfx << "Link detected, adding '" << m_args.back() << "'.\n";
}
int
@@ -230,24 +281,31 @@ CitrunInst::fork_compiler()
err(1, "execvp");
}
+ m_log << m_pfx << "Forked '" << m_args[0] << "' "
+ << "pid is " << child_pid << ".\n";
+
int status;
if (waitpid(child_pid, &status, 0) < 0)
err(1, "waitpid");
// Return the exit code of the native compiler.
+ int exit = -1;
if (WIFEXITED(status))
- return WEXITSTATUS(status);
+ exit = WEXITSTATUS(status);
- return -1;
+ m_log << m_pfx << "pid " << child_pid << " exited " << exit << "\n";
+ return exit;
}
void
-clean_path()
+CitrunInst::clean_path()
{
char *path;
- if ((path = std::getenv("PATH")) == NULL)
+ if ((path = std::getenv("PATH")) == NULL) {
+ m_log << m_pfx << "PATH is not set.\n";
errx(1, "PATH must be set");
+ }
// Filter CITRUN_PATH out of PATH
std::stringstream path_ss(path);
@@ -270,8 +328,10 @@ clean_path()
first_component = 0;
}
- if (!found_citrun_path)
+ if (!found_citrun_path) {
+ m_log << m_pfx << "'" << STR(CITRUN_PATH) << "' not in PATH.\n";
errx(1, "'%s' not in PATH", STR(CITRUN_PATH));
+ }
// Set new $PATH
if (setenv("PATH", new_path.str().c_str(), 1))
@@ -279,20 +339,24 @@ clean_path()
}
int
-main(int argc, char *argv[])
+CitrunInst::compile_modified()
{
- // We probably didn't call citrun-inst directly.
- setprogname("citrun-inst");
- clean_path();
+ m_log << m_pfx << "Running native compiler on modified source code.\n";
+
+ int ret = fork_compiler();
+ restore_original_src();
+ return ret;
+}
+
+int
+main(int argc, char *argv[])
+{
CitrunInst main(argc, argv);
if (main.instrument())
return 1;
main.patch_link_command();
-
- int ret = main.fork_compiler();
- main.restore_original_src();
- return ret;
+ return main.compile_modified();
}