diff --git a/CMakeLists.txt b/CMakeLists.txt index 49253fb7..7304e380 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ endif() if(${CMAKE_BUILD_TYPE} STREQUAL "Debug") message(STATUS "Enabling ubsan for Debug builds; Processor=${CMAKE_SYSTEM_PROCESSOR}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm((32.*)|(v6.*)|(v7.*))") message(STATUS "Linking libatomic on arm32 machines..") diff --git a/Makefile b/Makefile index f3066062..21b1aaa1 100644 --- a/Makefile +++ b/Makefile @@ -34,8 +34,10 @@ build-unit-test: cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=1 -DCMAKE_BUILD_TYPE:STRING=Debug cmake --build build --config Debug --target bpftime_runtime_tests -unit-test: +unit-test: ## run catch2 unit tests + make -C runtime/test/bpf ./build/runtime/unit-test/bpftime_runtime_tests + cd build/runtime && ctest -VV build: ## build the package cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=1 diff --git a/cmake/StandardSettings.cmake b/cmake/StandardSettings.cmake index 6bceceb9..8020a70a 100644 --- a/cmake/StandardSettings.cmake +++ b/cmake/StandardSettings.cmake @@ -60,6 +60,6 @@ endif() option(BPFTIME_ENABLE_ASAN "Enable Address Sanitize to detect memory error." OFF) if(BPFTIME_ENABLE_ASAN) - add_compile_options(-fsanitize=address) - add_link_options(-fsanitize=address) + add_compile_options(-fsanitize=address,undefined) + add_link_options(-fsanitize=address,undefined) endif() diff --git a/runtime/include/bpftime_shm.hpp b/runtime/include/bpftime_shm.hpp index 485236ba..ca73626f 100644 --- a/runtime/include/bpftime_shm.hpp +++ b/runtime/include/bpftime_shm.hpp @@ -51,6 +51,8 @@ void bpftime_destroy_global_shm(); int bpftime_import_global_shm_from_json(const char *filename); // export the global shared memory to json file int bpftime_export_global_shm_to_json(const char *filename); +// import a hander to global shared memory from json string +int bpftime_import_shm_handler_from_json(int fd, const char *json_string); // create a bpf link in the global shared memory // diff --git a/runtime/src/bpftime_shm_json.cpp b/runtime/src/bpftime_shm_json.cpp index c5fe0a45..0a003ced 100644 --- a/runtime/src/bpftime_shm_json.cpp +++ b/runtime/src/bpftime_shm_json.cpp @@ -64,19 +64,96 @@ bpf_perf_event_handler_to_json(const bpf_perf_event_handler &handler) extern "C" int bpftime_import_global_shm_from_json(const char *filename) { - assert(false && "Not implemented"); - return -1; + return bpftime_import_shm_from_json(shm_holder.global_shared_memory, + filename); } -int bpftime::bpftime_import_shm_from_json(const bpftime_shm &shm, +static int import_shm_handler_from_json(bpftime_shm &shm, json value, int fd) +{ + std::string handler_type = value["type"]; + if (handler_type == "bpf_prog_handler") { + std::string insns_str = value["attr"]["insns"]; + std::string name = value["attr"]["name"]; + int type = value["attr"]["type"]; + int cnt = value["attr"]["cnt"]; + std::vector insns; + insns.resize(cnt); + int res = hex_string_to_buffer(insns_str, + (unsigned char *)insns.data(), + insns_str.size()); + if (res < 0) { + spdlog::error("Failed to parse insns in json"); + return -1; + } + + shm.add_bpf_prog(fd, insns.data(), cnt, name.c_str(), type); + } else if (handler_type == "bpf_map_handler") { + std::string name = value["name"]; + bpf_map_attr attr = json_to_bpf_map_attr(value["attr"]); + shm.add_bpf_map(fd, name.c_str(), attr); + } else if (handler_type == "bpf_perf_event_handler") { + int type = value["attr"]["type"]; + int offset = value["attr"]["offset"]; + int pid = value["attr"]["pid"]; + int ref_ctr_off = value["attr"]["ref_ctr_off"]; + std::string _module_name = value["attr"]["_module_name"]; + int tracepoint_id = value["attr"]["tracepoint_id"]; + switch ((bpf_perf_event_handler::bpf_event_type)type) { + case bpf_perf_event_handler::bpf_event_type::BPF_TYPE_UPROBE: + shm.add_uprobe(fd, pid, _module_name.c_str(), offset, + false, ref_ctr_off); + break; + case bpf_perf_event_handler::bpf_event_type::BPF_TYPE_URETPROBE: + shm.add_uprobe(fd, pid, _module_name.c_str(), offset, + true, ref_ctr_off); + break; + case bpf_perf_event_handler::bpf_event_type::PERF_TYPE_TRACEPOINT: + shm.add_tracepoint(fd, pid, tracepoint_id); + break; + default: + spdlog::error("Unsupported perf event type {}", type); + return -1; + } + } else if (handler_type == "bpf_link_handler") { + int prog_fd = value["attr"]["prog_fd"]; + int target_fd = value["attr"]["target_fd"]; + shm.add_bpf_link(fd, prog_fd, target_fd); + } else { + spdlog::error("Unsupported handler type {}", handler_type); + return -1; + } + return 0; +} + +int bpftime::bpftime_import_shm_handler_from_json(bpftime_shm &shm, int fd, + const char *json_string) +{ + json j = json::parse(json_string); + return import_shm_handler_from_json(shm, fd, j); +} + +int bpftime::bpftime_import_shm_from_json(bpftime_shm &shm, const char *filename) { - return -1; + ifstream file(filename); + json j; + file >> j; + file.close(); + for (auto &[key, value] : j.items()) { + int fd = std::stoi(key); + int res = import_shm_handler_from_json(shm, value, fd); + if (res < 0) { + spdlog::error("Failed to import handler from json"); + return -1; + } + } + return 0; } extern "C" int bpftime_export_global_shm_to_json(const char *filename) { - return bpftime_export_shm_to_json(shm_holder.global_shared_memory, filename); + return bpftime_export_shm_to_json(shm_holder.global_shared_memory, + filename); } int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, @@ -107,12 +184,20 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, // prog j[std::to_string(i)] = { { "type", "bpf_prog_handler" }, - { "insns", buffer_to_hex_string( - (const unsigned char *)insns, - sizeof(ebpf_inst) * cnt) }, - { "cnt", cnt }, - { "name", name } + { "attr", + { "type", prog_handler.type }, + { "insns", + buffer_to_hex_string( + (const unsigned char *)insns, + sizeof(ebpf_inst) * cnt) }, + { "cnt", cnt }, + { "name", name } } }; + // append attach fds to the json + for (auto &fd : prog_handler.attach_fds) { + j[std::to_string(i)]["attr"]["attach_fds"] + .push_back(fd); + } spdlog::info("find prog fd={} name={}", i, prog_handler.name); } else if (std::holds_alternative(handler)) { @@ -131,7 +216,7 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, std::get(handler); j[std::to_string(i)] = { { "type", "bpf_perf_event_handler" }, - { "data", + { "attr", bpf_perf_event_handler_to_json(perf_handler) } }; spdlog::info("bpf_perf_event_handler found at {}", i); @@ -142,8 +227,10 @@ int bpftime::bpftime_export_shm_to_json(const bpftime_shm &shm, } else if (std::holds_alternative(handler)) { auto &h = std::get(handler); j[std::to_string(i)] = { { "type", "bpf_link_handler" }, - { "prog_fd", h.prog_fd }, - { "target_fd", h.target_fd } }; + { "attr", + { "prog_fd", h.prog_fd }, + { "target_fd", + h.target_fd } } }; spdlog::info( "bpf_link_handler found at {},link {} -> {}", i, h.prog_fd, h.target_fd); diff --git a/runtime/src/bpftime_shm_json.hpp b/runtime/src/bpftime_shm_json.hpp index 977c39cd..a1040a18 100644 --- a/runtime/src/bpftime_shm_json.hpp +++ b/runtime/src/bpftime_shm_json.hpp @@ -36,7 +36,8 @@ static inline int hex_string_to_buffer(const std::string &hexString, } int bpftime_export_shm_to_json(const bpftime_shm& shm, const char *filename); -int bpftime_import_shm_from_json(const bpftime_shm& shm, const char *filename); - +int bpftime_import_shm_from_json(bpftime_shm& shm, const char *filename); +int bpftime_import_shm_handler_from_json(bpftime_shm &shm, int fd, + const char *json_string); } // namespace bpftime #endif // BPFTIME_JSON_EXPORTER_HPP diff --git a/runtime/src/handler/perf_event_handler.cpp b/runtime/src/handler/perf_event_handler.cpp index d886784e..e33beaf5 100644 --- a/runtime/src/handler/perf_event_handler.cpp +++ b/runtime/src/handler/perf_event_handler.cpp @@ -46,6 +46,7 @@ bpf_perf_event_handler::bpf_perf_event_handler( { this->_module_name = module_name; } + // create uprobe/uretprobe with new perf event attr bpf_perf_event_handler::bpf_perf_event_handler( bool is_retprobe, uint64_t offset, int pid, const char *module_name, diff --git a/runtime/unit-test/test_bpftime_shm_json.cpp b/runtime/unit-test/test_bpftime_shm_json.cpp index 4477225d..2b89e570 100644 --- a/runtime/unit-test/test_bpftime_shm_json.cpp +++ b/runtime/unit-test/test_bpftime_shm_json.cpp @@ -86,13 +86,13 @@ TEST_CASE("Test bpftime shm json import/export") SECTION("Test shm json import") { - // bpftime_shm shm2(SHM_NAME, shm_open_type::SHM_CLIENT); - // bpftime_import_shm_from_json(shm2, - // "/tmp/bpftime_test_shm_json.json"); - // REQUIRE(shm2.get_bpf_prog(4) != nullptr); - // REQUIRE(shm2.get_tracepoint(5) != nullptr); - // REQUIRE(shm2.get_bpf_link(7) != nullptr); - // REQUIRE(shm2.get_bpf_map(8) != nullptr); - // REQUIRE(shm2.get_bpf_map(9) != nullptr); + bpftime_shm shm2(SHM_NAME, shm_open_type::SHM_CLIENT); + bpftime_import_shm_from_json(shm2, + "/tmp/bpftime_test_shm_json.json"); + REQUIRE(shm2.is_prog_fd(4)); + REQUIRE(shm2.is_perf_fd(5)); + REQUIRE(shm2.is_exist_fake_fd(7)); + REQUIRE(shm2.is_map_fd(8)); + REQUIRE(shm2.is_map_fd(9)); } }