main.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. #include <iostream>
  2. #include <fstream>
  3. #include <csignal>
  4. #include <sstream>
  5. #include <utility>
  6. #include <vector>
  7. #include <unordered_set>
  8. #include <regex>
  9. #include <phpcpp.h>
  10. #include "bcc_common.h"
  11. #include "bpf_module.h"
  12. #include "libbpf.h"
  13. #include <BPF.h>
  14. #include "table.h"
  15. #define TRACE_PIPE_PATH "/sys/kernel/debug/tracing/trace_pipe"
  16. #define DEBUGFS "/sys/kernel/debug"
  17. const std::vector<std::string> syscall_prefixes = {
  18. "sys_",
  19. "__x64_sys_",
  20. "__x32_compat_sys_",
  21. "__ia32_compat_sys_",
  22. "__arm64_sys_",
  23. "__s390x_sys_",
  24. "__s390_sys_",
  25. "__riscv_sys_"
  26. };
  27. class EbpfExtension : public Php::Base {
  28. private:
  29. ebpf::BPF bpf;
  30. void *mod;
  31. Php::Object _perf_event;
  32. PerfEventArrayTable *_class_perf_event;
  33. static std::string add_prefix(const std::string &prefix, const std::string &name) {
  34. if (name.rfind(prefix, 0) != 0) {
  35. return prefix + name;
  36. }
  37. return name;
  38. }
  39. std::string fix_syscall_fnname(const std::string &name) {
  40. for (const auto &prefix: syscall_prefixes) {
  41. if (name.rfind(prefix, 0) == 0) {
  42. return bpf.get_syscall_fnname(name.substr(prefix.length()));
  43. }
  44. }
  45. return name;
  46. }
  47. void _trace_autoload() {
  48. size_t num_funcs = bpf.get_num_functions();
  49. for (size_t i = 0; i < num_funcs; i++) {
  50. const char *func_name = bpf.get_function_name(i);
  51. std::string fn_name(func_name);
  52. if (fn_name.rfind("kprobe__", 0) == 0) {
  53. std::string kernel_func = fix_syscall_fnname(fn_name.substr(8));
  54. bpf.attach_kprobe(kernel_func, fn_name);
  55. } else if (fn_name.rfind("kretprobe__", 0) == 0) {
  56. std::string kernel_func = fix_syscall_fnname(fn_name.substr(11));
  57. bpf.attach_kprobe(kernel_func, fn_name, 0, BPF_PROBE_RETURN);
  58. } else if (fn_name.rfind("tracepoint__", 0) == 0) {
  59. std::string tp_name = fn_name.substr(12);
  60. std::replace(tp_name.begin(), tp_name.end(), '_', ':');
  61. bpf.attach_tracepoint(tp_name, fn_name);
  62. } else if (fn_name.rfind("raw_tracepoint__", 0) == 0) {
  63. std::string tp_name = fn_name.substr(16);
  64. bpf.attach_raw_tracepoint(tp_name, fn_name);
  65. } else if (fn_name.rfind("kfunc__", 0) == 0) {
  66. fn_name = add_prefix("kfunc__", fn_name);
  67. attach_kfunc(fn_name);
  68. } else if (fn_name.rfind("kretfunc__", 0) == 0) {
  69. fn_name = add_prefix("kretfunc__", fn_name);
  70. attach_kfunc(fn_name);
  71. } else if (fn_name.rfind("lsm__", 0) == 0) {
  72. fn_name = add_prefix("lsm__", fn_name);
  73. attach_lsm(fn_name);
  74. }
  75. }
  76. }
  77. public:
  78. EbpfExtension() = default;
  79. virtual ~EbpfExtension() = default;
  80. Php::Value __get(const Php::Value &name) {
  81. int from_attr = 1;
  82. auto res = get_table_cls(name, from_attr);
  83. if (!res.isObject()) {
  84. return Php::Base::__get(name);
  85. } else {
  86. return res;
  87. }
  88. }
  89. std::unordered_set<std::string> get_kprobe_functions(const std::string &event_re) {
  90. std::unordered_set<std::string> blacklist;
  91. std::unordered_set<std::string> avail_filter;
  92. std::unordered_set<std::string> fns;
  93. std::string blacklist_file = std::string(DEBUGFS) + "/kprobes/blacklist";
  94. std::ifstream blacklist_f(blacklist_file);
  95. if (blacklist_f.is_open()) {
  96. std::string line;
  97. while (std::getline(blacklist_f, line)) {
  98. std::istringstream iss(line);
  99. std::string addr, func_name;
  100. if (iss >> addr >> func_name) {
  101. blacklist.insert(func_name);
  102. }
  103. }
  104. blacklist_f.close();
  105. }
  106. std::string avail_filter_file = std::string(DEBUGFS) + "/tracing/available_filter_functions";
  107. std::ifstream avail_filter_f(avail_filter_file);
  108. if (avail_filter_f.is_open()) {
  109. std::string line;
  110. while (std::getline(avail_filter_f, line)) {
  111. std::istringstream iss(line);
  112. std::string func_name;
  113. if (iss >> func_name) {
  114. avail_filter.insert(func_name);
  115. }
  116. }
  117. avail_filter_f.close();
  118. }
  119. std::ifstream kallsyms_f("/proc/kallsyms");
  120. if (!kallsyms_f.is_open()) {
  121. std::cerr << "Failed to open /proc/kallsyms\n";
  122. return fns;
  123. }
  124. std::string line;
  125. bool in_init_section = false;
  126. bool in_irq_section = false;
  127. std::regex cold_regex(".*\\.cold(\\.\\d+)?$");
  128. while (std::getline(kallsyms_f, line)) {
  129. std::istringstream iss(line);
  130. std::string addr, type, func_name;
  131. if (!(iss >> addr >> type >> func_name)) {
  132. continue;
  133. }
  134. if (!in_init_section) {
  135. if (func_name == "__init_begin") {
  136. in_init_section = true;
  137. continue;
  138. }
  139. } else if (func_name == "__init_end") {
  140. in_init_section = false;
  141. continue;
  142. }
  143. if (!in_irq_section) {
  144. if (func_name == "__irqentry_text_start") {
  145. in_irq_section = true;
  146. continue;
  147. } else if (func_name == "__irqentry_text_end") {
  148. in_irq_section = false;
  149. continue;
  150. }
  151. } else if (func_name == "__irqentry_text_end") {
  152. in_irq_section = false;
  153. continue;
  154. }
  155. // 过滤掉 NOKPROBE_SYMBOL() 定义的 _kbl_addr_*
  156. if (func_name.rfind("_kbl_addr_", 0) == 0) {
  157. continue;
  158. }
  159. // 过滤掉 perf 相关函数
  160. if (func_name.rfind("__perf", 0) == 0 || func_name.rfind("perf_", 0) == 0) {
  161. continue;
  162. }
  163. // 过滤掉 __SCT__ 前缀的静态函数
  164. if (func_name.rfind("__SCT__", 0) == 0) {
  165. continue;
  166. }
  167. // 过滤掉 GCC 8 编译生成的 .cold 函数
  168. if (std::regex_match(func_name, cold_regex)) {
  169. continue;
  170. }
  171. if ((type == "t" || type == "T" || type == "w" || type == "W") &&
  172. func_name == event_re &&
  173. blacklist.find(func_name) == blacklist.end() &&
  174. avail_filter.find(func_name) != avail_filter.end()) {
  175. fns.insert(func_name);
  176. }
  177. }
  178. return fns;
  179. }
  180. Php::Value php_get_kprobe_functions(Php::Parameters &params) {
  181. std::string fn = params[0].stringValue();
  182. auto res = get_kprobe_functions(fn);
  183. Php::Array result;
  184. for (const auto &item: res) {
  185. result[result.size()] = item; // 将每个匹配的函数名添加到 Php::Array
  186. }
  187. return result;
  188. }
  189. Php::Value php_test(Php::Parameters &params) {
  190. std::string fn = params[0].stringValue();
  191. Php::out << fn << std::endl;
  192. auto res = get_kprobe_functions(fn);
  193. Php::Array result;
  194. for (const auto &item : res) {
  195. result[result.size()] = item; // 将每个匹配的函数名添加到 Php::Array
  196. }
  197. return result;
  198. }
  199. void __construct(Php::Parameters &params) {
  200. std::string bpf_code = params[0].stringValue();
  201. auto init_res = bpf.init(bpf_code);
  202. if (!init_res.ok()) {
  203. throw Php::Exception("init error: " + init_res.msg());
  204. }
  205. this->mod = (void *) bpf.get_mod();
  206. _trace_autoload();
  207. }
  208. ebpf::StatusTuple attach_kfunc(const std::string &kfn) {
  209. int probe_fd;
  210. auto fn = bpf.load_func(kfn, BPF_PROG_TYPE_TRACING, probe_fd);
  211. int res_fd = bpf_attach_kfunc(probe_fd);
  212. if (res_fd < 0) {
  213. TRY2(bpf.unload_func(kfn));
  214. return ebpf::StatusTuple(-1, "Unable to attach kfunc using %s",
  215. kfn.c_str());
  216. }
  217. return ebpf::StatusTuple::OK();
  218. }
  219. ebpf::StatusTuple attach_lsm(const std::string &lsm) {
  220. int probe_fd;
  221. auto fn = bpf.load_func(lsm, BPF_PROG_TYPE_LSM, probe_fd);
  222. int res_fd = bpf_attach_lsm(probe_fd);
  223. if (res_fd < 0) {
  224. TRY2(bpf.unload_func(lsm));
  225. return ebpf::StatusTuple(-1, "Unable to attach lsm using %s",
  226. lsm.c_str());
  227. }
  228. return ebpf::StatusTuple::OK();
  229. }
  230. void php_attach_kprobe(Php::Parameters &params) {
  231. std::string kernel_func = params[0].stringValue();
  232. std::string probe_func = params[1].stringValue();
  233. auto attach_res = bpf.attach_kprobe(kernel_func, probe_func);
  234. if (!attach_res.ok()) {
  235. throw Php::Exception("attach error: " + attach_res.msg());
  236. }
  237. }
  238. void php_attach_tracepoint(Php::Parameters &params) {
  239. std::string tp_func = params[0].stringValue();
  240. std::string probe_func = params[1].stringValue();
  241. auto attach_res = bpf.attach_tracepoint(tp_func, probe_func);
  242. if (!attach_res.ok()) {
  243. throw Php::Exception("attach error: " + attach_res.msg());
  244. }
  245. }
  246. void php_attach_raw_tracepoint(Php::Parameters &params) {
  247. std::string tp_func = params[0].stringValue();
  248. std::string probe_func = params[1].stringValue();
  249. auto attach_res = bpf.attach_raw_tracepoint(tp_func, probe_func);
  250. if (!attach_res.ok()) {
  251. throw Php::Exception("attach error: " + attach_res.msg());
  252. }
  253. }
  254. void php_attach_kfunc(Php::Parameters &params) {
  255. std::string kfunc = params[0].stringValue();
  256. auto attach_res = attach_kfunc(kfunc);
  257. if (!attach_res.ok()) {
  258. throw Php::Exception("attach error: " + attach_res.msg());
  259. }
  260. }
  261. void php_attach_lsm(Php::Parameters &params) {
  262. std::string kfunc = params[0].stringValue();
  263. auto attach_res = attach_lsm(kfunc);
  264. if (!attach_res.ok()) {
  265. throw Php::Exception("attach error: " + attach_res.msg());
  266. }
  267. }
  268. void php_attach_uprobe(Php::Parameters &params) {
  269. std::string binary_path = params[0].stringValue();
  270. std::string symbol = params[1].stringValue();
  271. std::string probe_func = params[2].stringValue();
  272. int64_t symbol_addr = 0, symbol_offset = 0, pid_param;
  273. uint32_t ref_ctr_offset = 0;
  274. pid_t pid = -1;
  275. if (params.size() > 3) {
  276. Php::Value options = params[3];
  277. symbol_addr = options.get("symbol_addr").numericValue();
  278. symbol_offset = options.get("symbol_offset").numericValue();
  279. ref_ctr_offset = options.get("ref_ctr_offset").numericValue();
  280. pid_param = options.get("pid").numericValue();
  281. if (pid_param > 0) {
  282. pid = static_cast<pid_t>(pid_param);
  283. }
  284. }
  285. auto attach_res = bpf.attach_uprobe(binary_path, symbol, probe_func, symbol_addr, BPF_PROBE_ENTRY, pid,
  286. symbol_offset, ref_ctr_offset);
  287. if (!attach_res.ok()) {
  288. throw Php::Exception("attach error: " + attach_res.msg());
  289. }
  290. }
  291. void php_detach_kprobe(Php::Parameters &params) {
  292. std::string fn = params[0].stringValue();
  293. auto detach_res = bpf.detach_kprobe(fn);
  294. if (!detach_res.ok()) {
  295. throw Php::Exception("detach_kprobe error: " + detach_res.msg());
  296. }
  297. }
  298. void php_detach_uprobe(Php::Parameters &params) {
  299. std::string binary_path = params[0].stringValue();
  300. std::string symbol = params[1].stringValue();
  301. int64_t symbol_addr = 0, symbol_offset = 0, pid_param;
  302. pid_t pid = -1;
  303. if (params.size() > 2) {
  304. Php::Value options = params[2];
  305. symbol_addr = options.get("symbol_addr").numericValue();
  306. symbol_offset = options.get("symbol_offset").numericValue();
  307. pid_param = options.get("pid").numericValue();
  308. if (pid_param > 0) {
  309. pid = static_cast<pid_t>(pid_param);
  310. }
  311. }
  312. auto detach_res = bpf.detach_uprobe(binary_path, symbol, symbol_addr, BPF_PROBE_ENTRY, pid, symbol_offset);
  313. if (!detach_res.ok()) {
  314. throw Php::Exception("detach_kprobe error: " + detach_res.msg());
  315. }
  316. }
  317. [[noreturn]] static void php_trace_print() {
  318. std::ifstream pipe(TRACE_PIPE_PATH);
  319. std::string line;
  320. if (!pipe.is_open()) {
  321. throw Php::Exception("Failed to open trace_pipe");
  322. }
  323. std::cout << "Press Ctrl+C to stop..." << std::endl;
  324. while (true) {
  325. if (std::getline(pipe, line)) {
  326. std::cout << line << std::endl;
  327. }
  328. }
  329. }
  330. static Php::Value php_trace_fields(Php::Parameters &params) {
  331. std::ifstream traceFile(TRACE_PIPE_PATH);
  332. if (!traceFile.is_open()) {
  333. throw Php::Exception("Failed to open trace_pipe");
  334. }
  335. std::string line;
  336. while (std::getline(traceFile, line)) {
  337. if (line.empty()) {
  338. continue;
  339. }
  340. if (line.rfind("CPU:", 0) == 0) {
  341. continue;
  342. }
  343. std::string task = line.substr(0, 16);
  344. task.erase(0, task.find_first_not_of(" "));
  345. std::istringstream iss(line.substr(17));
  346. std::string pid, cpu, flags, ts, msg;
  347. char delim;
  348. if (!(iss >> pid >> delim >> cpu >> delim >> flags >> ts)) {
  349. continue;
  350. }
  351. size_t sym_end = iss.str().find(": ", iss.tellg());
  352. if (sym_end != std::string::npos) {
  353. msg = iss.str().substr(sym_end + 2);
  354. }
  355. Php::Array result;
  356. result[0] = task;
  357. result[1] = std::stoi(pid);
  358. result[2] = std::stoi(cpu.substr(1, cpu.size() - 2)); // 去掉方括号
  359. result[3] = flags;
  360. result[4] = std::stod(ts);
  361. result[5] = msg;
  362. return result;
  363. }
  364. return Php::Value();
  365. }
  366. Php::Value php_perf_event(Php::Parameters &params) {
  367. std::string event_name = params[0].stringValue(); // Get event_name from the parameters
  368. this->_class_perf_event = new PerfEventArrayTable(&this->bpf, event_name);
  369. return Php::Object("PerfEventArrayTable", this->_class_perf_event);
  370. }
  371. Php::Value get_table_cls(const char *table_name, int from_attr) {
  372. int ttype = bpf_table_type(this->mod, table_name);
  373. switch (ttype) {
  374. case BPF_MAP_TYPE_HASH:
  375. return Php::Object("HashTable", new HashTable(&this->bpf, table_name));
  376. case BPF_MAP_TYPE_ARRAY:
  377. return Php::Object("ArrayTable", new ArrayTable(&this->bpf, table_name));
  378. case BPF_MAP_TYPE_PROG_ARRAY:
  379. return Php::Object("ProgArrayTable", new ProgArrayTable(&this->bpf, table_name));
  380. case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
  381. this->_class_perf_event = new PerfEventArrayTable(&this->bpf, table_name);
  382. return Php::Object("PerfEventArrayTable", this->_class_perf_event);
  383. case BPF_MAP_TYPE_PERCPU_HASH:
  384. return Php::Object("PerCpuHashTable", new PerCpuHashTable(&this->bpf, table_name));
  385. case BPF_MAP_TYPE_PERCPU_ARRAY:
  386. return Php::Object("PerCpuArrayTable", new PerCpuArrayTable(&this->bpf, table_name));
  387. case BPF_MAP_TYPE_LPM_TRIE:
  388. return Php::Object("LpmTrieTable", new LpmTrieTable(&this->bpf, table_name));
  389. case BPF_MAP_TYPE_STACK_TRACE:
  390. return Php::Object("StackTraceTable", new StackTraceTable(&this->bpf, table_name));
  391. case BPF_MAP_TYPE_LRU_HASH:
  392. return Php::Object("LruHashTable", new LruHashTable(&this->bpf, table_name));
  393. case BPF_MAP_TYPE_LRU_PERCPU_HASH:
  394. return Php::Object("LruPerCpuHashTable", new LruPerCpuHashTable(&this->bpf, table_name));
  395. case BPF_MAP_TYPE_CGROUP_ARRAY:
  396. return Php::Object("CgroupArrayTable", new CgroupArrayTable(&this->bpf, table_name));
  397. case BPF_MAP_TYPE_DEVMAP:
  398. return Php::Object("DevMapTable", new DevMapTable(&this->bpf, table_name));
  399. case BPF_MAP_TYPE_CPUMAP:
  400. return Php::Object("CpuMapTable", new CpuMapTable(&this->bpf, table_name));
  401. case BPF_MAP_TYPE_XSKMAP:
  402. return Php::Object("XskMapTable", new XskMapTable(&this->bpf, table_name));
  403. case BPF_MAP_TYPE_ARRAY_OF_MAPS:
  404. return Php::Object("MapInMapArrayTable", new MapInMapArrayTable(&this->bpf, table_name));
  405. case BPF_MAP_TYPE_HASH_OF_MAPS:
  406. return Php::Object("MapInMapHashTable", new MapInMapHashTable(&this->bpf, table_name));
  407. case BPF_MAP_TYPE_QUEUE:
  408. case BPF_MAP_TYPE_STACK:
  409. return Php::Object("QueueStackTable", new QueueStackTable(&this->bpf, table_name));
  410. case BPF_MAP_TYPE_RINGBUF:
  411. return Php::Object("RingBufTable", new RingBufTable(&this->bpf, table_name));
  412. default:
  413. if (from_attr) {
  414. return ttype;
  415. }
  416. throw Php::Exception("Unknown table type " + std::to_string(ttype));
  417. }
  418. }
  419. Php::Value php_get_table(Php::Parameters &params) {
  420. std::string table_name = params[0].stringValue();
  421. int from_fn = 0;
  422. return get_table_cls(table_name.c_str(), from_fn);
  423. }
  424. void php_perf_buffer_poll(Php::Parameters &params) {
  425. if (!this->_class_perf_event) {
  426. throw Php::Exception("perf event is null.");
  427. }
  428. int timeout_ms = -1;
  429. int res = this->_class_perf_event->perf_buffer_poll(timeout_ms);
  430. if (res < 0) {
  431. throw Php::Exception("perf buffer poll error.");
  432. }
  433. }
  434. Php::Value php_get_syscall_fnname(Php::Parameters &params) {
  435. std::string name = params[0].stringValue();
  436. return bpf.get_syscall_fnname(name);
  437. }
  438. };
  439. std::string sanitize_str(std::string str, bool (*validator)(char),
  440. char replacement = '_') {
  441. for (size_t i = 0; i < str.length(); i++)
  442. if (!validator(str[i]))
  443. str[i] = replacement;
  444. return str;
  445. }
  446. std::string attach_type_prefix(bpf_probe_attach_type type) {
  447. switch (type) {
  448. case BPF_PROBE_ENTRY:
  449. return "p";
  450. case BPF_PROBE_RETURN:
  451. return "r";
  452. }
  453. return "ERROR";
  454. }
  455. static bool kprobe_event_validator(char c) {
  456. return (c != '+') && (c != '.');
  457. }
  458. std::string get_kprobe_event(const std::string &kernel_func,
  459. bpf_probe_attach_type type) {
  460. std::string res = attach_type_prefix(type) + "_";
  461. res += sanitize_str(kernel_func, &kprobe_event_validator);
  462. return res;
  463. }
  464. extern "C" {
  465. PHPCPP_EXPORT void *get_module() {
  466. static Php::Extension extension("ebpf", "1.0.0");
  467. Php::Class<EbpfExtension> ebpf_class("Ebpf");
  468. ebpf_class.method<&EbpfExtension::php_trace_print>("trace_print");
  469. ebpf_class.method<&EbpfExtension::php_trace_fields>("trace_fields");
  470. ebpf_class.method<&EbpfExtension::__construct>("__construct", {
  471. Php::ByVal("bpf_code", Php::Type::String)
  472. });
  473. ebpf_class.method<&EbpfExtension::php_attach_kprobe>("attach_kprobe", {
  474. Php::ByVal("kernel_func", Php::Type::String),
  475. Php::ByVal("probe_func", Php::Type::String)
  476. });
  477. ebpf_class.method<&EbpfExtension::php_attach_tracepoint>("attach_tracepoint", {
  478. Php::ByVal("tp", Php::Type::String),
  479. Php::ByVal("probe_func", Php::Type::String)
  480. });
  481. ebpf_class.method<&EbpfExtension::php_attach_raw_tracepoint>("attach_raw_tracepoint", {
  482. Php::ByVal("tp", Php::Type::String),
  483. Php::ByVal("probe_func", Php::Type::String)
  484. });
  485. ebpf_class.method<&EbpfExtension::php_attach_kfunc>("attach_kfunc", {
  486. Php::ByVal("kfn", Php::Type::String),
  487. });
  488. ebpf_class.method<&EbpfExtension::php_attach_lsm>("attach_lsm", {
  489. Php::ByVal("lsm", Php::Type::String),
  490. });
  491. ebpf_class.method<&EbpfExtension::php_attach_uprobe>("attach_uprobe", {
  492. Php::ByVal("binary_path", Php::Type::String),
  493. Php::ByVal("symbol", Php::Type::String),
  494. Php::ByVal("probe_func", Php::Type::String),
  495. Php::ByVal("options", Php::Type::Array, false),
  496. });
  497. // ebpf_class.method<&EbpfExtension::php_open_perf_buffer>("open_perf_buffer", {
  498. // Php::ByVal("callback", Php::Type::Callable),
  499. // });
  500. ebpf_class.method<&EbpfExtension::php_perf_event>("perf_event", {
  501. Php::ByVal("ev_name", Php::Type::String),
  502. });
  503. ebpf_class.method<&EbpfExtension::php_get_table>("get_table", {
  504. Php::ByVal("tb_name", Php::Type::String),
  505. });
  506. ebpf_class.method<&EbpfExtension::php_perf_buffer_poll>("perf_buffer_poll", {});
  507. ebpf_class.method<&EbpfExtension::php_get_syscall_fnname>("get_syscall_fnname", {
  508. Php::ByVal("name", Php::Type::String),
  509. });
  510. /*detach*/
  511. ebpf_class.method<&EbpfExtension::php_detach_kprobe>("detach_kprobe", {
  512. Php::ByVal("kernel_func", Php::Type::String),
  513. });
  514. ebpf_class.method<&EbpfExtension::php_detach_uprobe>("detach_uprobe", {
  515. Php::ByVal("binary_path", Php::Type::String),
  516. Php::ByVal("symbol", Php::Type::String),
  517. Php::ByVal("options", Php::Type::Array, false),
  518. });
  519. ebpf_class.method<&EbpfExtension::php_test>("test", {
  520. Php::ByVal("idx", Php::Type::String),
  521. });
  522. ebpf_class.method<&EbpfExtension::php_get_kprobe_functions>("get_kprobe_functions", {
  523. Php::ByVal("fn", Php::Type::String),
  524. });
  525. extension.add(std::move(ebpf_class));
  526. /*HashTable*/
  527. Php::Class<HashTable> ebpf_hashtable_cls("HashTable");
  528. ebpf_hashtable_cls.method<&HashTable::php_get_values>("values", {
  529. });
  530. /*ArrayTable*/
  531. Php::Class<ArrayTable> ebpf_array_table_cls("ArrayTable");
  532. ebpf_array_table_cls.method<&ArrayTable::php_get_value>("get_value", {
  533. Php::ByVal("idx", Php::Type::Numeric),
  534. });
  535. /*ProgArrayTable*/
  536. Php::Class<ProgArrayTable> ebpf_prog_array_table_cls("ProgArrayTable");
  537. /*PerfEventArrayTable*/
  538. Php::Class<PerfEventArrayTable> ebpf_perf_event_class("PerfEventArrayTable");
  539. ebpf_perf_event_class.method<&PerfEventArrayTable::php_open_perf_buffer>("open_perf_buffer", {
  540. Php::ByVal("fn", Php::Type::String),
  541. });
  542. /*PerCpuHashTable*/
  543. Php::Class<PerCpuHashTable> ebpf_percpuhash_table_cls("PerCpuHashTable");
  544. /*PerCpuArrayTable*/
  545. Php::Class<PerCpuArrayTable> ebpf_per_cpu_array_table_cls("PerCpuArrayTable");
  546. ebpf_per_cpu_array_table_cls.method<&PerCpuArrayTable::php_sum_value>("sum_value", {
  547. Php::ByVal("idx", Php::Type::Numeric),
  548. });
  549. /*LpmTrieTable*/
  550. Php::Class<LpmTrieTable> ebpf_lpmtrie_table_cls("LpmTrieTable");
  551. /*StackTraceTable*/
  552. Php::Class<StackTraceTable> ebpf_stack_trace_table_cls("StackTraceTable");
  553. ebpf_stack_trace_table_cls.method<&StackTraceTable::php_get_values>("values", {
  554. Php::ByVal("stack", Php::Type::Numeric),
  555. Php::ByVal("pid", Php::Type::Numeric),
  556. });
  557. /*LruHashTable*/
  558. Php::Class<LruHashTable> ebpf_lruhash_table_cls("LruHashTable");
  559. /*LruPerCpuHashTable*/
  560. Php::Class<LruPerCpuHashTable> ebpf_lruper_cpuhash_table_cls("LruPerCpuHashTable");
  561. /*CgroupArrayTable*/
  562. Php::Class<CgroupArrayTable> ebpf_cgroup_array_table_cls("CgroupArrayTable");
  563. /*DevMapTable*/
  564. Php::Class<DevMapTable> ebpf_devmap_table_cls("DevMapTable");
  565. /*CpuMapTable*/
  566. Php::Class<CpuMapTable> ebpf_cpumap_table_cls("CpuMapTable");
  567. /*XskMapTable*/
  568. Php::Class<XskMapTable> ebpf_xskmap_table_cls("XskMapTable");
  569. /*MapInMapArrayTable*/
  570. Php::Class<MapInMapArrayTable> ebpf_map_in_map_array_table_cls("MapInMapArrayTable");
  571. /*MapInMapHashTable*/
  572. Php::Class<MapInMapHashTable> ebpf_map_in_maphash_table_cls("MapInMapHashTable");
  573. /*QueueStackTable*/
  574. Php::Class<QueueStackTable> ebpf_queue_stack_table_cls("QueueStackTable");
  575. /*RingBufTable*/
  576. Php::Class<RingBufTable> ebpf_ringbuf_table_cls("RingBufTable");
  577. extension.add(std::move(ebpf_hashtable_cls));
  578. extension.add(std::move(ebpf_array_table_cls));
  579. extension.add(std::move(ebpf_prog_array_table_cls));
  580. extension.add(std::move(ebpf_perf_event_class));
  581. extension.add(std::move(ebpf_percpuhash_table_cls));
  582. extension.add(std::move(ebpf_per_cpu_array_table_cls));
  583. extension.add(std::move(ebpf_lpmtrie_table_cls));
  584. extension.add(std::move(ebpf_stack_trace_table_cls));
  585. extension.add(std::move(ebpf_lruhash_table_cls));
  586. extension.add(std::move(ebpf_lruper_cpuhash_table_cls));
  587. extension.add(std::move(ebpf_cgroup_array_table_cls));
  588. extension.add(std::move(ebpf_devmap_table_cls));
  589. extension.add(std::move(ebpf_cpumap_table_cls));
  590. extension.add(std::move(ebpf_xskmap_table_cls));
  591. extension.add(std::move(ebpf_map_in_map_array_table_cls));
  592. extension.add(std::move(ebpf_map_in_maphash_table_cls));
  593. extension.add(std::move(ebpf_queue_stack_table_cls));
  594. extension.add(std::move(ebpf_ringbuf_table_cls));
  595. return extension;
  596. }
  597. }