Skip to content

Commit

Permalink
improve probes lookup by dropping use of regex
Browse files Browse the repository at this point in the history
Ref: #526
  • Loading branch information
mmarchini committed Apr 25, 2019
1 parent ee449b7 commit 5ed8717
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 25 deletions.
43 changes: 19 additions & 24 deletions src/bpftrace.cpp
Expand Up @@ -153,25 +153,31 @@ std::set<std::string> BPFtrace::find_wildcard_matches(const std::string &prefix,
{
if (!has_wildcard(func))
return std::set<std::string>({func});
// Turn glob into a regex
auto regex_str = "(" + std::regex_replace(func, std::regex("\\*"), "[^\\s]*") + ")";
if (prefix != "")
regex_str = prefix + ":" + regex_str;
regex_str = "^" + regex_str;
std::regex func_regex(regex_str);
std::smatch match;
bool start_wildcard = func[0] == '*';
bool end_wildcard = func[func.length() - 1] == '*';

std::vector<std::string> tokens = split_string(func, '*');
tokens.erase(std::remove(tokens.begin(), tokens.end(), ""), tokens.end());

std::string line;
std::set<std::string> matches;
std::string full_prefix = prefix.empty() ? "" : (prefix + ":");
while (std::getline(symbol_name_stream, line))
{
if (std::regex_search(line, match, func_regex))
{
assert(match.size() == 2);
// skip the ".part.N" kprobe variants, as they can't be traced:
if (std::strstr(match.str(1).c_str(), ".part.") == NULL)
matches.insert(match[1]);
if (!full_prefix.empty()) {
if (line.find(full_prefix, 0) != 0)
continue;
line = line.substr(full_prefix.length());
}

if (!wildcard_match(line, tokens, start_wildcard, end_wildcard))
continue;

// skip the ".part.N" kprobe variants, as they can't be traced:
if (line.find(".part.") != std::string::npos)
continue;

matches.insert(line);
}
return matches;
}
Expand Down Expand Up @@ -1499,17 +1505,6 @@ std::string BPFtrace::resolve_uid(uintptr_t addr)
return username;
}

std::vector<std::string> BPFtrace::split_string(std::string &str, char split_by)
{
std::vector<std::string> elems;
std::stringstream ss(str);
std::string value;
while(std::getline(ss, value, split_by)) {
elems.push_back(value);
}
return elems;
}

std::string BPFtrace::resolve_ksym(uintptr_t addr, bool show_offset)
{
struct bcc_symbol ksym;
Expand Down
1 change: 0 additions & 1 deletion src/bpftrace.h
Expand Up @@ -136,7 +136,6 @@ class BPFtrace
static uint64_t read_address_from_output(std::string output);
static std::string hist_index_label(int power);
static std::string lhist_index_label(int number);
static std::vector<std::string> split_string(std::string &str, char split_by);
std::vector<uint8_t> find_empty_key(IMap &map, size_t size) const;
static int spawn_child(const std::vector<std::string>& args);
static bool is_pid_alive(int pid);
Expand Down
33 changes: 33 additions & 0 deletions src/utils.cpp
Expand Up @@ -4,6 +4,7 @@
#include <map>
#include <string>
#include <tuple>
#include <sstream>
#include <fstream>
#include <memory>

Expand Down Expand Up @@ -76,6 +77,38 @@ bool has_wildcard(const std::string &str)
str.find("]") != std::string::npos);
}

std::vector<std::string> split_string(const std::string &str, char delimiter) {
std::vector<std::string> elems;
std::stringstream ss(str);
std::string value;
while(std::getline(ss, value, delimiter)) {
elems.push_back(value);
}
return elems;
}

bool wildcard_match(const std::string &str, std::vector<std::string> &tokens, bool start_wildcard, bool end_wildcard) {
size_t next = 0;

if (!start_wildcard)
if (str.find(tokens[0], next) != next)
return false;

for (std::string token : tokens) {
size_t found = str.find(token, next);
if (found == std::string::npos)
return false;

next = found + token.length();
}

if (!end_wildcard)
if (str.length() != next)
return false;

return true;
}

std::vector<int> get_online_cpus()
{
return read_cpu_range("/sys/devices/system/cpu/online");
Expand Down
2 changes: 2 additions & 0 deletions src/utils.h
Expand Up @@ -30,6 +30,8 @@ static std::vector<DeprecatedName> DEPRECATED_LIST =


bool has_wildcard(const std::string &str);
std::vector<std::string> split_string(const std::string &str, char delimiter);
bool wildcard_match(const std::string &str, std::vector<std::string> &tokens, bool start_wildcard, bool end_wildcard);
std::vector<int> get_online_cpus();
std::vector<int> get_possible_cpus();
std::vector<std::string> get_kernel_cflags(
Expand Down
1 change: 1 addition & 0 deletions tests/CMakeLists.txt
Expand Up @@ -12,6 +12,7 @@ add_executable(bpftrace_test
probe.cpp
semantic_analyser.cpp
tracepoint_format_parser.cpp
utils.cpp

${CMAKE_SOURCE_DIR}/src/attached_probe.cpp
${CMAKE_SOURCE_DIR}/src/bpftrace.cpp
Expand Down
77 changes: 77 additions & 0 deletions tests/utils.cpp
@@ -0,0 +1,77 @@
#include "gtest/gtest.h"
#include "utils.h"

namespace bpftrace {
namespace test {
namespace utils {

TEST(utils, split_string)
{
std::vector<std::string> tokens_empty = {};
std::vector<std::string> tokens_one_empty = {""};
std::vector<std::string> tokens_two_empty = {"", ""};
std::vector<std::string> tokens_f = {"", "f"};
std::vector<std::string> tokens_foo_bar = {"foo", "bar"};
std::vector<std::string> tokens_empty_foo_bar = {"", "foo", "bar"};
std::vector<std::string> tokens_empty_foo_empty_bar = {"", "foo", "", "bar"};
std::vector<std::string> tokens_empty_foo_bar_biz = {"", "foo", "bar", "biz"};

EXPECT_EQ(split_string("", '-'), tokens_empty);
EXPECT_EQ(split_string("-", '-'), tokens_one_empty);
EXPECT_EQ(split_string("--", '-'), tokens_two_empty);
EXPECT_EQ(split_string("-f-", '-'), tokens_f);
EXPECT_EQ(split_string("-foo-bar-", '-'), tokens_empty_foo_bar);
EXPECT_EQ(split_string("-foo--bar-", '-'), tokens_empty_foo_empty_bar);
EXPECT_EQ(split_string("-foo-bar-biz-", '-'), tokens_empty_foo_bar_biz);
EXPECT_EQ(split_string("-foo-bar", '-'), tokens_empty_foo_bar);
EXPECT_EQ(split_string("foo-bar-", '-'), tokens_foo_bar);
EXPECT_EQ(split_string("foo-bar", '-'), tokens_foo_bar);
}

TEST(utils, wildcard_match)
{
std::vector<std::string> tokens_not = {"not"};
std::vector<std::string> tokens_bar = {"bar"};
std::vector<std::string> tokens_bar_not = {"bar", "not"};
std::vector<std::string> tokens_foo = {"foo"};
std::vector<std::string> tokens_biz = {"biz"};
std::vector<std::string> tokens_foo_biz = {"foo", "biz"};


// start: true, end: true
EXPECT_EQ(wildcard_match("foobarbiz", tokens_not, true, true), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar, true, true), true);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar_not, true, true), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo, true, true), true);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_biz, true, true), true);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo_biz, true, true), true);

// start: false, end: true
EXPECT_EQ(wildcard_match("foobarbiz", tokens_not, false, true), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar, false, true), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar_not, false, true), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo, false, true), true);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_biz, false, true), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo_biz, false, true), true);

// start: true, end: false
EXPECT_EQ(wildcard_match("foobarbiz", tokens_not, true, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar, true, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar_not, true, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo, true, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_biz, true, false), true);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo_biz, true, false), true);

// start: false, end: false
EXPECT_EQ(wildcard_match("foobarbiz", tokens_not, false, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar, false, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_bar_not, false, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo, false, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_biz, false, false), false);
EXPECT_EQ(wildcard_match("foobarbiz", tokens_foo_biz, false, false), true);
}

} // namespace ast
} // namespace test
} // namespace bpftrace

0 comments on commit 5ed8717

Please sign in to comment.