Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve probes lookup by dropping use of regex #557

Merged
merged 1 commit into from
Apr 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 19 additions & 24 deletions src/bpftrace.cpp
Original file line number Diff line number Diff line change
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)
mmarchini marked this conversation as resolved.
Show resolved Hide resolved
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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