|
|
@@ -1,20 +1,22 @@
|
|
|
#include <iostream>
|
|
|
-#include <phpcpp.h>
|
|
|
#include <fstream>
|
|
|
-#include "bcc_common.h"
|
|
|
-#include "bpf_module.h"
|
|
|
-#include "libbpf.h"
|
|
|
-#include "BPF.h"
|
|
|
#include <csignal>
|
|
|
-#include <atomic>
|
|
|
#include <sstream>
|
|
|
#include <utility>
|
|
|
#include <vector>
|
|
|
-#include "table.cpp"
|
|
|
+#include <unordered_set>
|
|
|
+#include <regex>
|
|
|
+#include <phpcpp.h>
|
|
|
+#include "bcc_common.h"
|
|
|
+#include "bpf_module.h"
|
|
|
+#include "libbpf.h"
|
|
|
+#include <BPF.h>
|
|
|
+#include "table.h"
|
|
|
|
|
|
-constexpr const char *TRACE_PIPE_PATH = "/sys/kernel/debug/tracing/trace_pipe";
|
|
|
+#define TRACE_PIPE_PATH "/sys/kernel/debug/tracing/trace_pipe"
|
|
|
+
|
|
|
+#define DEBUGFS "/sys/kernel/debug"
|
|
|
|
|
|
-// Php::out << "Value of fn: " << fnn << std::endl;
|
|
|
|
|
|
const std::vector<std::string> syscall_prefixes = {
|
|
|
"sys_",
|
|
|
@@ -88,35 +90,135 @@ public:
|
|
|
|
|
|
Php::Value __get(const Php::Value &name) {
|
|
|
int from_attr = 1;
|
|
|
- auto res = get_table_cls(name, from_attr); // 这里传递 std::vector<Php::Value>
|
|
|
+ auto res = get_table_cls(name, from_attr);
|
|
|
if (!res.isObject()) {
|
|
|
return Php::Base::__get(name);
|
|
|
} else {
|
|
|
return res;
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ std::unordered_set<std::string> get_kprobe_functions(const std::string &event_re) {
|
|
|
+ std::unordered_set<std::string> blacklist;
|
|
|
+ std::unordered_set<std::string> avail_filter;
|
|
|
+ std::unordered_set<std::string> fns;
|
|
|
+
|
|
|
+ std::string blacklist_file = std::string(DEBUGFS) + "/kprobes/blacklist";
|
|
|
+ std::ifstream blacklist_f(blacklist_file);
|
|
|
+ if (blacklist_f.is_open()) {
|
|
|
+ std::string line;
|
|
|
+ while (std::getline(blacklist_f, line)) {
|
|
|
+ std::istringstream iss(line);
|
|
|
+ std::string addr, func_name;
|
|
|
+ if (iss >> addr >> func_name) {
|
|
|
+ blacklist.insert(func_name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ blacklist_f.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string avail_filter_file = std::string(DEBUGFS) + "/tracing/available_filter_functions";
|
|
|
+ std::ifstream avail_filter_f(avail_filter_file);
|
|
|
+ if (avail_filter_f.is_open()) {
|
|
|
+ std::string line;
|
|
|
+ while (std::getline(avail_filter_f, line)) {
|
|
|
+ std::istringstream iss(line);
|
|
|
+ std::string func_name;
|
|
|
+ if (iss >> func_name) {
|
|
|
+ avail_filter.insert(func_name);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ avail_filter_f.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ std::ifstream kallsyms_f("/proc/kallsyms");
|
|
|
+ if (!kallsyms_f.is_open()) {
|
|
|
+ std::cerr << "Failed to open /proc/kallsyms\n";
|
|
|
+ return fns;
|
|
|
+ }
|
|
|
+
|
|
|
+ std::string line;
|
|
|
+ bool in_init_section = false;
|
|
|
+ bool in_irq_section = false;
|
|
|
+ std::regex cold_regex(".*\\.cold(\\.\\d+)?$");
|
|
|
+
|
|
|
+ while (std::getline(kallsyms_f, line)) {
|
|
|
+ std::istringstream iss(line);
|
|
|
+ std::string addr, type, func_name;
|
|
|
+ if (!(iss >> addr >> type >> func_name)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!in_init_section) {
|
|
|
+ if (func_name == "__init_begin") {
|
|
|
+ in_init_section = true;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } else if (func_name == "__init_end") {
|
|
|
+ in_init_section = false;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!in_irq_section) {
|
|
|
+ if (func_name == "__irqentry_text_start") {
|
|
|
+ in_irq_section = true;
|
|
|
+ continue;
|
|
|
+ } else if (func_name == "__irqentry_text_end") {
|
|
|
+ in_irq_section = false;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ } else if (func_name == "__irqentry_text_end") {
|
|
|
+ in_irq_section = false;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 过滤掉 NOKPROBE_SYMBOL() 定义的 _kbl_addr_*
|
|
|
+ if (func_name.rfind("_kbl_addr_", 0) == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 过滤掉 perf 相关函数
|
|
|
+ if (func_name.rfind("__perf", 0) == 0 || func_name.rfind("perf_", 0) == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 过滤掉 __SCT__ 前缀的静态函数
|
|
|
+ if (func_name.rfind("__SCT__", 0) == 0) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // 过滤掉 GCC 8 编译生成的 .cold 函数
|
|
|
+ if (std::regex_match(func_name, cold_regex)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((type == "t" || type == "T" || type == "w" || type == "W") &&
|
|
|
+ func_name == event_re &&
|
|
|
+ blacklist.find(func_name) == blacklist.end() &&
|
|
|
+ avail_filter.find(func_name) != avail_filter.end()) {
|
|
|
+ fns.insert(func_name);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
-// printf("111111111\n");
|
|
|
-// if (name == "events") return _perf_event;
|
|
|
-//
|
|
|
-// auto a = new PerfEventArrayTable;
|
|
|
-// a->getMessage();
|
|
|
-//
|
|
|
+ return fns;
|
|
|
}
|
|
|
|
|
|
- void php_test(Php::Parameters ¶ms) {
|
|
|
- int ty = bpf_table_type(this->mod, "counters");
|
|
|
- Php::out << "counters type]" << ty << std::endl;
|
|
|
- int ty2 = bpf_table_type(this->mod, "events");
|
|
|
- Php::out << "events type]" << ty2 << std::endl;
|
|
|
-// bpf.get_map_in_map_table<int>("").get_fd();
|
|
|
-// auto aaa = bpf.table<>()("counters");
|
|
|
-// aaa.get_value(0, reinterpret_cast<std::string &>(val));
|
|
|
-//
|
|
|
-// auto control_table_hdl = bpf.get_array_table<uint64_t>("counters");
|
|
|
-// auto res1 = control_table_hdl.get_value(1, val);
|
|
|
-// Php::out<< "ok]" <<res1.ok() <<std::endl;
|
|
|
-// Php::out<< "msg]" << res1.msg() <<std::endl;
|
|
|
-// Php::out <<"val]" << val <<std::endl;
|
|
|
+ Php::Value php_get_kprobe_functions(Php::Parameters ¶ms) {
|
|
|
+ std::string fn = params[0].stringValue();
|
|
|
+ auto res = get_kprobe_functions(fn);
|
|
|
+ Php::Array result;
|
|
|
+ for (const auto &item: res) {
|
|
|
+ result[result.size()] = item; // 将每个匹配的函数名添加到 Php::Array
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ Php::Value php_test(Php::Parameters ¶ms) {
|
|
|
+ std::string fn = params[0].stringValue();
|
|
|
+ Php::out << fn << std::endl;
|
|
|
+ auto res = get_kprobe_functions(fn);
|
|
|
+ Php::Array result;
|
|
|
+ for (const auto &item : res) {
|
|
|
+ result[result.size()] = item; // 将每个匹配的函数名添加到 Php::Array
|
|
|
+ }
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
void __construct(Php::Parameters ¶ms) {
|
|
|
@@ -371,13 +473,10 @@ public:
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- Php::Value php_table(Php::Parameters ¶ms) {
|
|
|
- std::string table_name = params[0].stringValue(); // Get event_name from the parameters
|
|
|
+ Php::Value php_get_table(Php::Parameters ¶ms) {
|
|
|
+ std::string table_name = params[0].stringValue();
|
|
|
int from_fn = 0;
|
|
|
return get_table_cls(table_name.c_str(), from_fn);
|
|
|
-
|
|
|
-// this->_class_perf_event = new PerfEventArrayTable(&this->bpf, table_name);
|
|
|
-// return Php::Object("PerfEventArrayTable", this->_class_perf_event);
|
|
|
}
|
|
|
|
|
|
void php_perf_buffer_poll(Php::Parameters ¶ms) {
|
|
|
@@ -470,7 +569,7 @@ PHPCPP_EXPORT void *get_module() {
|
|
|
Php::ByVal("ev_name", Php::Type::String),
|
|
|
});
|
|
|
|
|
|
- ebpf_class.method<&EbpfExtension::php_table>("table", {
|
|
|
+ ebpf_class.method<&EbpfExtension::php_get_table>("get_table", {
|
|
|
Php::ByVal("tb_name", Php::Type::String),
|
|
|
});
|
|
|
|
|
|
@@ -489,31 +588,47 @@ PHPCPP_EXPORT void *get_module() {
|
|
|
Php::ByVal("symbol", Php::Type::String),
|
|
|
Php::ByVal("options", Php::Type::Array, false),
|
|
|
});
|
|
|
- ebpf_class.method<&EbpfExtension::php_test>("test", {});
|
|
|
+ ebpf_class.method<&EbpfExtension::php_test>("test", {
|
|
|
+ Php::ByVal("idx", Php::Type::String),
|
|
|
+
|
|
|
+ });
|
|
|
+ ebpf_class.method<&EbpfExtension::php_get_kprobe_functions>("get_kprobe_functions", {
|
|
|
+ Php::ByVal("fn", Php::Type::String),
|
|
|
+ });
|
|
|
extension.add(std::move(ebpf_class));
|
|
|
|
|
|
/*HashTable*/
|
|
|
Php::Class<HashTable> ebpf_hashtable_cls("HashTable");
|
|
|
+ ebpf_hashtable_cls.method<&HashTable::php_get_values>("values", {
|
|
|
+ });
|
|
|
/*ArrayTable*/
|
|
|
Php::Class<ArrayTable> ebpf_array_table_cls("ArrayTable");
|
|
|
- ebpf_array_table_cls.method<&ArrayTable::Value>("value", {
|
|
|
- Php::ByVal("i", Php::Type::Numeric),
|
|
|
+ ebpf_array_table_cls.method<&ArrayTable::php_get_value>("get_value", {
|
|
|
+ Php::ByVal("idx", Php::Type::Numeric),
|
|
|
});
|
|
|
/*ProgArrayTable*/
|
|
|
Php::Class<ProgArrayTable> ebpf_prog_array_table_cls("ProgArrayTable");
|
|
|
/*PerfEventArrayTable*/
|
|
|
Php::Class<PerfEventArrayTable> ebpf_perf_event_class("PerfEventArrayTable");
|
|
|
ebpf_perf_event_class.method<&PerfEventArrayTable::php_open_perf_buffer>("open_perf_buffer", {
|
|
|
- Php::ByVal("callback", Php::Type::Callable),
|
|
|
+ Php::ByVal("fn", Php::Type::String),
|
|
|
});
|
|
|
/*PerCpuHashTable*/
|
|
|
Php::Class<PerCpuHashTable> ebpf_percpuhash_table_cls("PerCpuHashTable");
|
|
|
/*PerCpuArrayTable*/
|
|
|
- Php::Class<PerCpuArrayTable> ebpf_percpuarray_table_cls("PerCpuArrayTable");
|
|
|
+ Php::Class<PerCpuArrayTable> ebpf_per_cpu_array_table_cls("PerCpuArrayTable");
|
|
|
+ ebpf_per_cpu_array_table_cls.method<&PerCpuArrayTable::php_sum_value>("sum_value", {
|
|
|
+ Php::ByVal("idx", Php::Type::Numeric),
|
|
|
+ });
|
|
|
/*LpmTrieTable*/
|
|
|
Php::Class<LpmTrieTable> ebpf_lpmtrie_table_cls("LpmTrieTable");
|
|
|
/*StackTraceTable*/
|
|
|
Php::Class<StackTraceTable> ebpf_stack_trace_table_cls("StackTraceTable");
|
|
|
+ ebpf_stack_trace_table_cls.method<&StackTraceTable::php_get_values>("values", {
|
|
|
+ Php::ByVal("stack", Php::Type::Numeric),
|
|
|
+ Php::ByVal("pid", Php::Type::Numeric),
|
|
|
+ });
|
|
|
+
|
|
|
/*LruHashTable*/
|
|
|
Php::Class<LruHashTable> ebpf_lruhash_table_cls("LruHashTable");
|
|
|
/*LruPerCpuHashTable*/
|
|
|
@@ -540,7 +655,7 @@ PHPCPP_EXPORT void *get_module() {
|
|
|
extension.add(std::move(ebpf_prog_array_table_cls));
|
|
|
extension.add(std::move(ebpf_perf_event_class));
|
|
|
extension.add(std::move(ebpf_percpuhash_table_cls));
|
|
|
- extension.add(std::move(ebpf_percpuarray_table_cls));
|
|
|
+ extension.add(std::move(ebpf_per_cpu_array_table_cls));
|
|
|
extension.add(std::move(ebpf_lpmtrie_table_cls));
|
|
|
extension.add(std::move(ebpf_stack_trace_table_cls));
|
|
|
extension.add(std::move(ebpf_lruhash_table_cls));
|