Commit e5a497ce authored by Brendan Gregg's avatar Brendan Gregg

add -l to list probes

parent 0746ff9c
...@@ -12,6 +12,7 @@ add_executable(bpftrace ...@@ -12,6 +12,7 @@ add_executable(bpftrace
mapkey.cpp mapkey.cpp
printf.cpp printf.cpp
types.cpp types.cpp
list.cpp
) )
target_link_libraries(bpftrace arch ast parser) target_link_libraries(bpftrace arch ast parser)
......
#include <sys/types.h>
#include <dirent.h>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <regex>
#include <vector>
#include <string>
#include "list.h"
#include "bpftrace.h"
namespace bpftrace {
const std::string kprobe_path = "/sys/kernel/debug/tracing/available_filter_functions";
const std::string tp_path = "/sys/kernel/debug/tracing/events";
bool search_probe(const std::string &probe, const std::string search)
{
std::string s = search;
char remove[] = "*.?";
unsigned int i;
// TODO: glob searching instead of discarding wildcards
for (i = 0; i < strlen(remove); ++i)
{
s.erase(std::remove(s.begin(), s.end(), remove[i]), s.end());
}
if (probe.find(s) == std::string::npos)
return true;
return false;
}
void list_dir(const std::string path, std::vector<std::string> &files)
{
// yes, I know about std::filesystem::directory_iterator, but no, it wasn't available
DIR *dp;
struct dirent *dep;
if ((dp = opendir(path.c_str())) == NULL)
return;
while ((dep = readdir(dp)) != NULL)
files.push_back(std::string(dep->d_name));
}
void list_probes(const std::string &search)
{
unsigned int i, j;
std::string line, probe;
// software
// TODO: add here
// hardware
// TODO: add here
// tracepoints
std::vector<std::string> cats = std::vector<std::string>();
list_dir(tp_path, cats);
for (i = 0; i < cats.size(); i++)
{
if (cats[i] == "." || cats[i] == ".." || cats[i] == "enable" || cats[i] == "filter")
continue;
std::vector<std::string> events = std::vector<std::string>();
list_dir(tp_path + "/" + cats[i], events);
for (j = 0; j < events.size(); j++)
{
if (events[j] == "." || events[j] == ".." || events[j] == "enable" || events[j] == "filter")
continue;
probe = "tracepoint:" + cats[i] + ":" + events[j];
if (search_probe(probe, search))
continue;
std::cout << probe << std::endl;
}
}
// kprobes
std::cout << std::endl;
std::ifstream file(kprobe_path);
if (file.fail())
{
std::cerr << strerror(errno) << ": " << kprobe_path << std::endl;
return;
}
std::set<std::string> matches;
size_t loc;
while (std::getline(file, line))
{
loc = line.find_first_of(" ");
if (loc == std::string::npos)
probe = "kprobe:" + line;
else
probe = "kprobe:" + line.substr(0, loc);
if (!search.empty())
{
if (search_probe(probe, search))
continue;
}
std::cout << probe << std::endl;
}
}
void list_probes()
{
const std::string search = "";
list_probes(search);
}
} // namespace bpftrace
#include <sstream>
namespace bpftrace {
void list_probes(const std::string &search);
void list_probes();
} // namespace bpftrace
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "driver.h" #include "driver.h"
#include "printer.h" #include "printer.h"
#include "semantic_analyser.h" #include "semantic_analyser.h"
#include "list.h"
using namespace bpftrace; using namespace bpftrace;
...@@ -16,11 +17,14 @@ void usage() ...@@ -16,11 +17,14 @@ void usage()
std::cerr << " bpftrace [options] filename" << std::endl; std::cerr << " bpftrace [options] filename" << std::endl;
std::cerr << " bpftrace [options] -e 'program'" << std::endl << std::endl; std::cerr << " bpftrace [options] -e 'program'" << std::endl << std::endl;
std::cerr << "OPTIONS:" << std::endl; std::cerr << "OPTIONS:" << std::endl;
std::cerr << " -l [search] list probes" << std::endl;
std::cerr << " -e 'program' execute this program" << std::endl; std::cerr << " -e 'program' execute this program" << std::endl;
std::cerr << " -v verbose messages" << std::endl; std::cerr << " -v verbose messages" << std::endl;
std::cerr << " -d debug info dry run" << std::endl << std::endl; std::cerr << " -d debug info dry run" << std::endl << std::endl;
std::cerr << "EXAMPLES:" << std::endl; std::cerr << "EXAMPLES:" << std::endl;
std::cerr << "bpftrace -e 'kprobe:sys_nanosleep { printf(\"PID %d sleeping...\\n\", pid); }'" << std::endl; std::cerr << "bpftrace -l '*sleep*'" << std::endl;
std::cerr << " list probes containing \"sleep\"" << std::endl;
std::cerr << "bpftrace -e 'kprobe:do_nanosleep { printf(\"PID %d sleeping...\\n\", pid); }'" << std::endl;
std::cerr << " trace processes calling sleep" << std::endl; std::cerr << " trace processes calling sleep" << std::endl;
std::cerr << "bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'" << std::endl; std::cerr << "bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'" << std::endl;
std::cerr << " count syscalls by process name" << std::endl; std::cerr << " count syscalls by process name" << std::endl;
...@@ -30,10 +34,11 @@ int main(int argc, char *argv[]) ...@@ -30,10 +34,11 @@ int main(int argc, char *argv[])
{ {
int err; int err;
Driver driver; Driver driver;
bool listing = false;
std::string script; std::string script, search;
int c; int c;
while ((c = getopt(argc, argv, "de:v")) != -1) while ((c = getopt(argc, argv, "de:lv")) != -1)
{ {
switch (c) switch (c)
{ {
...@@ -46,6 +51,9 @@ int main(int argc, char *argv[]) ...@@ -46,6 +51,9 @@ int main(int argc, char *argv[])
case 'e': case 'e':
script = optarg; script = optarg;
break; break;
case 'l':
listing = true;
break;
default: default:
usage(); usage();
return 1; return 1;
...@@ -59,6 +67,20 @@ int main(int argc, char *argv[]) ...@@ -59,6 +67,20 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
// Listing probes
if (listing)
{
if (optind == argc-1)
list_probes(argv[optind]);
else if (optind == argc)
list_probes();
else
{
usage();
}
return 0;
}
if (script.empty()) if (script.empty())
{ {
// There should only be 1 non-option argument (the script file) // There should only be 1 non-option argument (the script file)
......
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