Commit 40b0e3ca authored by Brendan Gregg's avatar Brendan Gregg Committed by GitHub

Merge pull request #109 from iovisor/debug-unoptimized-code

add verbose debug output with -dd
parents 35bd1134 d741c913
......@@ -103,6 +103,7 @@ OPTIONS:
-p PID PID for enabling USDT probes
-v verbose messages
-d debug info dry run
-dd verbose debug info dry run
EXAMPLES:
bpftrace -l '*sleep*'
......@@ -201,6 +202,7 @@ kprobe:hrtimer_nanosleep
## 5. `-d`: Debug Output
The `-d` option produces debug output, and does not run the program. This is mostly useful for debugging issues with bpftrace itself.
You can also use `-dd` to produce a more verbose debug output, which will also print unoptimized IR.
**If you are an end-user of bpftrace, you should not normally need the `-d` or `-v` options, and you can skip to the [Language](#language) section.**
......
......@@ -1317,7 +1317,7 @@ void CodegenLLVM::createStrcmpFunction()
b_.CreateRet(b_.getInt1(0));
}
std::unique_ptr<BpfOrc> CodegenLLVM::compile(bool debug, std::ostream &out)
std::unique_ptr<BpfOrc> CodegenLLVM::compile(DebugLevel debug, std::ostream &out)
{
createLog2Function();
createLinearFunction();
......@@ -1355,11 +1355,23 @@ std::unique_ptr<BpfOrc> CodegenLLVM::compile(bool debug, std::ostream &out)
*/
LLVMAddAlwaysInlinerPass(reinterpret_cast<LLVMPassManagerRef>(&PM));
PMB.populateModulePassManager(PM);
if (debug == DebugLevel::kFullDebug)
{
raw_os_ostream llvm_ostream(out);
llvm_ostream << "Before optimization\n";
llvm_ostream << "-------------------\n\n";
module_->print(llvm_ostream, nullptr, false, true);
}
PM.run(*module_.get());
if (debug)
if (debug != DebugLevel::kNone)
{
raw_os_ostream llvm_ostream(out);
if (debug == DebugLevel::kFullDebug) {
llvm_ostream << "\nAfter optimization\n";
llvm_ostream << "------------------\n\n";
}
module_->print(llvm_ostream, nullptr, false, true);
}
......
......@@ -55,7 +55,7 @@ public:
void createLog2Function();
void createLinearFunction();
void createStrcmpFunction();
std::unique_ptr<BpfOrc> compile(bool debug=false, std::ostream &out=std::cerr);
std::unique_ptr<BpfOrc> compile(DebugLevel debug=DebugLevel::kNone, std::ostream &out=std::cerr);
private:
Node *root_;
......
......@@ -236,7 +236,7 @@ void AttachedProbe::load_prog()
// Redirect stderr, so we don't get error messages from BCC
int old_stderr, new_stderr;
fflush(stderr);
if (bt_debug)
if (bt_debug != DebugLevel::kNone)
log_level = 15;
else
{
......@@ -265,7 +265,7 @@ void AttachedProbe::load_prog()
}
// Restore stderr
if (bt_debug == false)
if (bt_debug == DebugLevel::kNone)
{
fflush(stderr);
dup2(old_stderr, 2);
......
......@@ -17,7 +17,7 @@
namespace bpftrace {
bool bt_debug = false;
DebugLevel bt_debug = DebugLevel::kNone;
bool bt_verbose = false;
int BPFtrace::add_probe(ast::Probe &p)
......@@ -89,7 +89,7 @@ int BPFtrace::add_probe(ast::Probe &p)
probe.name = attach_point->name(func);
probe.freq = attach_point->freq;
probe.loc = 0;
probe.index = attach_point->index(func) > 0 ?
probe.index = attach_point->index(func) > 0 ?
attach_point->index(func) : p.index();
probes_.push_back(probe);
}
......
......@@ -17,11 +17,35 @@
namespace bpftrace {
class BpfOrc;
enum class DebugLevel;
// globals
extern bool bt_debug;
extern DebugLevel bt_debug;
extern bool bt_verbose;
enum class DebugLevel {
kNone,
kDebug,
kFullDebug
};
inline DebugLevel operator++(DebugLevel& level, int)
{
switch (level) {
case DebugLevel::kNone:
level = DebugLevel::kDebug;
break;
case DebugLevel::kDebug:
level = DebugLevel::kFullDebug;
break;
case DebugLevel::kFullDebug:
// NOTE (mmarchini): should be handled by the caller
level = DebugLevel::kNone;
break;
}
return level;
}
class BPFtrace
{
public:
......
......@@ -23,6 +23,7 @@ void usage()
std::cerr << " -p PID PID for enabling USDT probes" << std::endl;
std::cerr << " -v verbose messages" << std::endl;
std::cerr << " -d debug info dry run" << std::endl << std::endl;
std::cerr << " -dd verbose debug info dry run" << std::endl << std::endl;
std::cerr << "EXAMPLES:" << std::endl;
std::cerr << "bpftrace -l '*sleep*'" << std::endl;
std::cerr << " list probes containing \"sleep\"" << std::endl;
......@@ -46,7 +47,11 @@ int main(int argc, char *argv[])
switch (c)
{
case 'd':
bt_debug = true;
bt_debug++;
if (bt_debug == DebugLevel::kNone) {
usage();
return 1;
}
break;
case 'v':
bt_verbose = true;
......@@ -66,7 +71,7 @@ int main(int argc, char *argv[])
}
}
if (bt_verbose && bt_debug)
if (bt_verbose && (bt_debug != DebugLevel::kNone))
{
// TODO: allow both
std::cerr << "USAGE: Use either -v or -d." << std::endl;
......@@ -125,7 +130,7 @@ int main(int argc, char *argv[])
if (pid_str)
bpftrace.pid_ = atoi(pid_str);
if (bt_debug)
if (bt_debug != DebugLevel::kNone)
{
ast::Printer p(std::cout);
driver.root_->accept(p);
......@@ -140,14 +145,14 @@ int main(int argc, char *argv[])
if (err)
return err;
err = semantics.create_maps(bt_debug);
err = semantics.create_maps(bt_debug != DebugLevel::kNone);
if (err)
return err;
ast::CodegenLLVM llvm(driver.root_, bpftrace);
auto bpforc = llvm.compile(bt_debug);
if (bt_debug)
if (bt_debug != DebugLevel::kNone)
return 0;
// Empty signal handler for cleanly terminating the program
......
......@@ -93,7 +93,7 @@ void test(const std::string &input, const std::string expected_output)
std::stringstream out;
ast::CodegenLLVM codegen(driver.root_, bpftrace);
codegen.compile(true, out);
codegen.compile(DebugLevel::kDebug, out);
std::string full_expected_output = header + expected_output;
EXPECT_EQ(full_expected_output, out.str());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment