Переглянути джерело

Initial commit (README)

Initial commit (Any Version)

Initial commit (Any Version)
Carl 8 місяців тому
батько
коміт
db6130b9c0
5 змінених файлів з 62 додано та 43 видалено
  1. 2 0
      README.md
  2. 13 6
      api/BPFTable.h
  3. 8 17
      config.m4
  4. 38 19
      ebpf.cpp
  5. 1 1
      php_ebpf.h

+ 2 - 0
README.md

@@ -69,6 +69,8 @@ sudo apt install bpfcc-tools libbpfcc libbpf-dev linux-headers-$(uname -r) clang
 
 ### 扩展安装
 ```bash
+git clone --recursive https://git.yunzhihui.ltd/root/phbpf.git
+cd phbpf
 phpize
 ./configure
 make && sudo make install

+ 13 - 6
api/BPFTable.h

@@ -554,9 +554,12 @@ template <class ValueType>
 class BPFInodeStorageTable : public BPFTableBase<int, ValueType> {
  public:
   BPFInodeStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
-    if (desc.type != BPF_MAP_TYPE_INODE_STORAGE)
-      throw std::invalid_argument("Table '" + desc.name +
-                                  "' is not a inode_storage table");
+#ifdef BPF_MAP_TYPE_INODE_STORAGE
+	  if (desc.type != BPF_MAP_TYPE_INODE_STORAGE)
+    throw std::invalid_argument("Table '" + desc.name + "' is not a inode_storage table");
+#else
+	  throw std::runtime_error("BPF_MAP_TYPE_INODE_STORAGE is not supported on this kernel");
+#endif
   }
 
   virtual StatusTuple get_value(const int& fd, ValueType& value) {
@@ -583,9 +586,13 @@ template <class ValueType>
 class BPFTaskStorageTable : public BPFTableBase<int, ValueType> {
  public:
   BPFTaskStorageTable(const TableDesc& desc) : BPFTableBase<int, ValueType>(desc) {
-    if (desc.type != BPF_MAP_TYPE_TASK_STORAGE)
-      throw std::invalid_argument("Table '" + desc.name +
-                                  "' is not a task_storage table");
+#ifdef BPF_MAP_TYPE_TASK_STORAGE
+	  if (desc.type != BPF_MAP_TYPE_TASK_STORAGE)
+    throw std::invalid_argument("Table '" + desc.name +
+                                "' is not a task_storage table");
+#else
+	  throw std::runtime_error("BPF_MAP_TYPE_TASK_STORAGE is not supported on this kernel");
+#endif
   }
 
   virtual StatusTuple get_value(const int& fd, ValueType& value) {

+ 8 - 17
config.m4

@@ -47,10 +47,10 @@ if test "$PHP_EBPF" != "no"; then
   AC_ARG_WITH([ebpf],
     [AS_HELP_STRING([--with-bcc=DIR], [Specify the path to bcc headers and libraries])],
     [LIB_BCC="$withval"],
-    [LIB_BCC="./deps/bcc"]
+    [LIB_BCC="deps/bcc"]
   )
-  PHP_ADD_INCLUDE($LIB_BCC/src/cc)
-
+  BCC_C_SOURCE="$LIB_BCC/src/cc"
+  PHP_ADD_INCLUDE($BCC_C_SOURCE)
   AC_ARG_WITH([ebpf],
       [AS_HELP_STRING([--with-llvm=DIR], [Specify the path to llvm headers and libraries])],
       [LIB_LLVM="$withval"],
@@ -65,19 +65,10 @@ if test "$PHP_EBPF" != "no"; then
   dnl )
   AC_DEFINE_UNQUOTED([KERNEL_MODULES_DIR], ["$LIB_KERNEL"], [Path to kernel modules])
 
-  PHP_ADD_INCLUDE(./api)
-
-  dnl PHP_ADD_LIBRARY_WITH_PATH(bcc, /usr/lib/x86_64-linux-gnu, EBPF_SHARED_LIBADD)
+  API_SOURCE="api"
+  PHP_ADD_INCLUDE($API_SOURCE)
 
-  PHP_CHECK_LIBRARY(bcc, bpf_prog_load,
-  [
-    PHP_ADD_LIBRARY_WITH_PATH(bcc, /usr/lib/x86_64-linux-gnu, EBPF_SHARED_LIBADD)
-    AC_DEFINE(HAVE_EBPFLIB, 1, [Define if libbcc is available])
-  ],[
-    AC_MSG_ERROR([libbcc not found or missing required symbols])
-  ],[
-    -L/usr/lib/x86_64-linux-gnu
-  ])
+  PHP_ADD_LIBRARY_WITH_PATH(bcc, /usr/lib/x86_64-linux-gnu, EBPF_SHARED_LIBADD)
 
   dnl # --with-ebpf -> check for lib and symbol presence
   dnl LIBNAME=ebpf # you may want to change this
@@ -105,8 +96,8 @@ if test "$PHP_EBPF" != "no"; then
 
 
   source_file="ebpf.cpp \
-        api/BPF.cc \
-        api/BPFTable.cc"
+        $API_SOURCE/BPF.cc \
+        $API_SOURCE/BPFTable.cc"
 
   PHP_NEW_EXTENSION(ebpf, $source_file, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
 

+ 38 - 19
ebpf.cpp

@@ -108,9 +108,9 @@ static inline sub_object *table_fetch_object(zend_object *obj) {
 }
 
 void EbpfExtension::_trace_autoload() {
-	size_t num_funcs = bpf.get_num_functions();
+	size_t num_funcs = bpf_num_functions(mod);
 	for (size_t i = 0; i < num_funcs; i++) {
-		const char *func_name = bpf.get_function_name(i);
+		const char *func_name = bpf_function_name(mod, i);
 		std::string fn_name(func_name);
 		if (fn_name.rfind("kprobe__", 0) == 0) {
 			std::string kernel_func = fix_syscall_fnname(fn_name.substr(8));
@@ -374,6 +374,7 @@ zval EbpfExtension::get_table_cls(const char *table_name, int from_attr) {
 			Z_ADDREF(retval);
 			break;
 		}
+#ifdef BPF_MAP_TYPE_RINGBUF
 		case BPF_MAP_TYPE_RINGBUF: {
 			if (!ring_buf_table_ce) {
 				zend_throw_error(NULL, "RingBufTable class not found");
@@ -386,6 +387,7 @@ zval EbpfExtension::get_table_cls(const char *table_name, int from_attr) {
 			Z_ADDREF(retval);
 			break;
 		}
+#endif
 		default:
 			if (from_attr) {
 				ZVAL_LONG(&retval, ttype);
@@ -495,6 +497,7 @@ std::unordered_set<std::string> EbpfExtension::get_kprobe_functions(const std::s
 	return fns;
 }
 
+#ifdef BPF_PROG_TYPE_TRACING
 ebpf::StatusTuple EbpfExtension::attach_kfunc(const std::string &kfn) {
 	int probe_fd;
 	auto fn = bpf.load_func(kfn, BPF_PROG_TYPE_TRACING, probe_fd);
@@ -503,11 +506,20 @@ ebpf::StatusTuple EbpfExtension::attach_kfunc(const std::string &kfn) {
 	if (res_fd < 0) {
 		TRY2(bpf.unload_func(kfn));
 		return ebpf::StatusTuple(-1, "Unable to attach kfunc using %s",
-		                         kfn.c_str());
+								 kfn.c_str());
 	}
 	return ebpf::StatusTuple::OK();
 }
+#else
 
+ebpf::StatusTuple EbpfExtension::attach_kfunc(const std::string &kfn) {
+	return ebpf::StatusTuple(-1,
+	                         "kfunc attachment requires BPF_PROG_TYPE_TRACING, which is not available on this kernel");
+}
+
+#endif
+
+#ifdef BPF_PROG_TYPE_LSM
 ebpf::StatusTuple EbpfExtension::attach_lsm(const std::string &lsm) {
 	int probe_fd;
 	auto fn = bpf.load_func(lsm, BPF_PROG_TYPE_LSM, probe_fd);
@@ -516,10 +528,17 @@ ebpf::StatusTuple EbpfExtension::attach_lsm(const std::string &lsm) {
 	if (res_fd < 0) {
 		TRY2(bpf.unload_func(lsm));
 		return ebpf::StatusTuple(-1, "Unable to attach lsm using %s",
-		                         lsm.c_str());
+								 lsm.c_str());
 	}
 	return ebpf::StatusTuple::OK();
 }
+#else
+
+ebpf::StatusTuple EbpfExtension::attach_lsm(const std::string &lsm) {
+	return ebpf::StatusTuple(-1, "BPF_PROG_TYPE_LSM is not supported by this kernel.");
+}
+
+#endif
 
 
 zend_object *bpf_create_object(zend_class_entry *ce) {
@@ -592,7 +611,7 @@ PHP_METHOD (Bpf, __construct) {
 		}
 
 		auto res = obj->ebpf_cpp_cls->init(source);
-		if (!res.ok()) {
+		if (res.code() != 0) {
 			zend_throw_error(NULL, "BPF init failed: %s", res.msg().c_str());
 			RETURN_FALSE;
 		}
@@ -664,7 +683,7 @@ PHP_METHOD (Bpf, attach_kprobe) {
 			std::string(probe_func, probe_func_len)
 	);
 
-	if (!attach_res.ok()) {
+	if (attach_res.code() != 0) {
 		zend_throw_error(NULL, "attach error: %s", attach_res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -692,7 +711,7 @@ PHP_METHOD (Bpf, attach_tracepoint) {
 			std::string(probe_func, probe_func_len)
 	);
 
-	if (!attach_res.ok()) {
+	if (attach_res.code() != 0) {
 		zend_throw_error(NULL, "attach error: %s", attach_res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -744,7 +763,7 @@ PHP_METHOD (Bpf, attach_kfunc) {
 
 	auto attach_res = obj->ebpf_cpp_cls->attach_kfunc(std::string(kfunc, kfunc_len));
 
-	if (!attach_res.ok()) {
+	if (attach_res.code() != 0) {
 		zend_throw_error(NULL, "attach error: %s", attach_res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -768,7 +787,7 @@ PHP_METHOD (Bpf, attach_lsm) {
 
 	auto attach_res = obj->ebpf_cpp_cls->attach_lsm(std::string(lsm, lsm_len));
 
-	if (!attach_res.ok()) {
+	if (attach_res.code() != 0) {
 		zend_throw_error(NULL, "attach error: %s", attach_res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -856,7 +875,7 @@ PHP_METHOD (Bpf, detach_kprobe) {
 
 	auto detach_res = obj->ebpf_cpp_cls->bpf.detach_kprobe(std::string(fn, fn_len));
 
-	if (!detach_res.ok()) {
+	if (detach_res.code() != 0) {
 		zend_throw_error(NULL, "detach_kprobe error: %s", detach_res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -913,7 +932,7 @@ PHP_METHOD (Bpf, detach_uprobe) {
 			symbol_offset
 	);
 
-	if (!detach_res.ok()) {
+	if (detach_res.code() != 0) {
 		zend_throw_error(NULL, "detach_uprobe error: %s", detach_res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -1116,7 +1135,7 @@ PHP_METHOD (Bpf, load_func) {
 			probe_fd
 	);
 
-	if (!res.ok()) {
+	if (res.code() != 0) {
 		zend_throw_error(NULL, "Failed to load function: %s", res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -1209,7 +1228,7 @@ PHP_METHOD (PerfEventArrayTable, open_perf_buffer) {
 	}
 
 	auto res = obj->bpf->open_perf_buffer(name, callbackfn);
-	if (!res.ok()) {
+	if (res.code() != 0) {
 		zend_throw_error(NULL, "open_perf_buffer error: %s", res.msg().c_str());
 		RETURN_NULL();
 	}
@@ -1278,20 +1297,20 @@ PHP_METHOD (HashTable, clear) {
 
 	if (!name_zv || Z_TYPE_P(name_zv) != IS_STRING) {
 		zend_throw_error(NULL, "Invalid or missing name property");
-		RETURN_NULL();
+		RETURN_NULL()
 	}
 	sub_object *obj = table_fetch_object(Z_OBJ_P(getThis()));
 	if (!obj || !obj->bpf) {
 		zend_throw_error(NULL, "Invalid object state");
-		RETURN_NULL();
+		RETURN_NULL()
 	}
 
 	auto table = obj->bpf->get_table(Z_STRVAL_P(name_zv));
 	auto res = table.clear_table_non_atomic();
 
-	if (!res.ok()) {
+	if (res.code() != 0) {
 		zend_throw_error(NULL, "Failed to clear table: %s", res.msg().c_str());
-		RETURN_NULL();
+		RETURN_NULL()
 	}
 
 	RETURN_TRUE;
@@ -1330,7 +1349,7 @@ PHP_METHOD (ArrayTable, get_value) {
 		auto table = obj->bpf->get_array_table<uint64_t>(Z_STRVAL_P(name_zv));
 		uint64_t val;
 		auto res = table.get_value(index, val);
-		if (!res.ok()) {
+		if (res.code() != 0) {
 			zend_throw_error(NULL, "Get value error in %s", Z_STRVAL_P(name_zv));
 			RETURN_NULL();
 		}
@@ -1540,7 +1559,7 @@ PHP_METHOD (PerCpuArrayTable, sum_value) {
 	try {
 		auto table = obj->bpf->get_percpu_array_table<uint64_t>(Z_STRVAL_P(name_zv));
 		auto res = table.get_value(index, val);
-		if (!res.ok()) {
+		if (res.code() != 0) {
 			zend_throw_error(NULL, "Get value error in %s", Z_STRVAL_P(name_zv));
 			RETURN_NULL();
 		}

+ 1 - 1
php_ebpf.h

@@ -95,7 +95,7 @@ public:
 
 	ebpf::StatusTuple init(const std::string &bpf_program) {
 		auto res = this->bpf.init(bpf_program);
-		if (res.ok())
+		if (res.code() == 0)
 			this->mod = (void *) this->bpf.get_mod();
 		return res;
 	}