Skip to content

Commit

Permalink
build bpftimetool
Browse files Browse the repository at this point in the history
  • Loading branch information
Littlefisher619 committed Oct 22, 2023
1 parent 72260ed commit aa07d92
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 152 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ set(SPDLOG_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/spdlog/include)
add_subdirectory(vm)
add_subdirectory(runtime)
add_subdirectory(daemon)
add_subdirectory(tools)

# benchmark that requires bpftime libraries
add_subdirectory(benchmark)
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ unit-test: ## run catch2 unit tests
cd build/runtime/test && ctest -VV

build: ## build the package
cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=1
cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=1
cmake --build build --config Debug
cd tools/cli-rs && cargo build

Expand Down
5 changes: 0 additions & 5 deletions daemon/main.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
// Copyright (c) 2019 Facebook
// Copyright (c) 2020 Netflix
//
// Based on bpf_mocker(8) from BCC by Brendan Gregg and others.
// 14-Feb-2020 Brendan Gregg Created this.
#include <argp.h>
#include <signal.h>
#include <stdio.h>
Expand Down
1 change: 1 addition & 0 deletions runtime/test/README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# unit tests for the bpftime

depreciated, use the unit-test instead. New tests should be added to the unit-test with catch2.
1 change: 1 addition & 0 deletions tools/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_subdirectory(bpftimetool)
14 changes: 3 additions & 11 deletions tools/bpftimetool/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,20 @@ add_executable(bpftimetool
main.cpp
)

find_package(Boost REQUIRED COMPONENTS program_options)

add_dependencies(bpftime FridaCore bpftime-object)
target_include_directories(bpftime PUBLIC

target_include_directories(bpftimetool PUBLIC
set(LIBBPF_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/../../runtime/object/libbpf)
${FRIDA_CORE_INSTALL_DIR}
../../runtime/object
../../third_party/
../../runtime/include
${LIBBPF_INCLUDE_DIRS}/uapi
${LIBBPF_INCLUDE_DIRS}
)

target_link_libraries(bpftime
${FRIDA_CORE_INSTALL_DIR}/libfrida-core.a
target_link_libraries(bpftimetool
-lpthread
-lm
-ldl
runtime
bpftime-object
Boost::program_options
)

install(TARGETS bpftime CONFIGURATIONS Release Debug DESTINATION ~/.bpftime)
install(TARGETS bpftimetool CONFIGURATIONS Release Debug DESTINATION ~/.bpftime)
157 changes: 22 additions & 135 deletions tools/bpftimetool/main.cpp
Original file line number Diff line number Diff line change
@@ -1,168 +1,55 @@
#include <boost/program_options/value_semantic.hpp>
#include <cerrno>
#include <cstdlib>
#include <frida-core.h>
#include <iostream>
#include <boost/program_options.hpp>
#include <cstdio>
#include <memory>
#include <bpftime_shm.hpp>
#include <ostream>
#include <string>
#include <filesystem>
extern "C" {
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include <sys/stat.h>
}

const char *DEFAULT_INSTALLATION_LOCATION = "~/.bpftime";

using namespace std;

const std::string version = "1.0.0";
const bpftime::shm_open_type bpftime::global_shm_open_type =
shm_open_type::SHM_NO_CREATE;

struct cli_config {
bool dry_run = false;
bool benchmark = false;
bool kernel_uprobe = false;
int pid = 0;
std::string input_file;
int target_pid;
std::string agent_dynlib_path;
std::string bpf_object_path;
bool inject_client = false;
bool inject_server = false;
};

using libbpf_object_ptr =
std::unique_ptr<struct bpf_object, decltype(&bpf_object__close)>;

// open, load and attach the
static libbpf_object_ptr open_and_attach_libbpf_object(const char *filename)
{
struct bpf_object *obj;
struct bpf_program *prog;
// struct bpf_link *link;
int err;

obj = bpf_object__open(filename);
if (libbpf_get_error(obj)) {
fprintf(stderr, "Error opening BPF object file: %s\n",
filename);
return { nullptr, bpf_object__close };
}
libbpf_object_ptr obj_ptr(obj, bpf_object__close);

err = bpf_object__load(obj);
if (err) {
fprintf(stderr, "Error loading BPF object file: %s\n",
filename);
return { nullptr, bpf_object__close };
}
bpf_object__for_each_program(prog, obj)
{
// Link hasn't been used
bpf_program__attach(prog);
if (err) {
fprintf(stderr, "Error attaching BPF program\n");
return { nullptr, bpf_object__close };
}
}
return obj_ptr;
}

int inject_agent(int target_pid, const char *agent_dynlib_path)
{
// check the args
frida_init();
FridaInjector *injector = frida_injector_new();
GError *error = NULL;
guint id = frida_injector_inject_library_file_sync(injector, target_pid,
agent_dynlib_path,
"bpftime_agent_main",
"", NULL, &error);

if (error != NULL) {
fprintf(stderr, "%s\n", error->message);
g_error_free(error);
frida_unref(injector);
frida_deinit();
exit(EXIT_FAILURE);
}

printf("Successfully injected. ID: %u\n", id);

frida_injector_close_sync(injector, NULL, NULL);
frida_unref(injector);
frida_deinit();
return 0;
}

std::string get_lib_path(const char *library_name)
{
struct stat st;
auto so_path =
std::string(DEFAULT_INSTALLATION_LOCATION) + library_name;
if (stat(so_path.c_str(), &st) != 0) {
cerr << "Error: necessary library " << so_path
<< " not found:" << errno << endl;
exit(1);
}
return so_path;
}

std::string get_agent_lib_path()
{
return get_lib_path("/libbpftime-agent.so");
}

std::string get_server_lib_path()
{
return get_lib_path("/libbpftime-syscall-server.so");
}
using namespace bpftime;

// Main program
int main(int argc, char *argv[])
{
if (argc == 1) {
cerr << "Usage: " << argv[0] << " [load|start|attach] ..."
<< endl;
cerr << "Usage: " << argv[0] << " [load|import|export] ..."
<< endl
<< "Command-line tool to inspect and manage userspace eBPF objects" << endl;
return 1;
}

auto cmd = std::string(argv[1]);
if (cmd == "load") {
if (argc != 3) {
cerr << "Usage: " << argv[0] << " load <EXECUTABLE>"
<< endl;
cerr << "Usage: " << argv[0] << " load <fd> <JSON>"
<< endl
<< "Load a JSON file containing eBPF objects into the global shared memory" << endl;
return 1;
}
auto so_path = get_server_lib_path();
auto command_to_run =
"LD_PRELOAD=" + so_path + " " + std::string(argv[2]);
return system(command_to_run.c_str());
} else if (cmd == "start") {
int fd = atoi(argv[2]);
auto json_str = std::string(argv[3]);
return bpftime_import_shm_handler_from_json(fd, json_str.c_str());
} else if (cmd == "export") {
if (argc != 3) {
cerr << "Usage: " << argv[0] << " start <EXECUTABLE>"
<< endl;
cerr << "Usage: " << argv[0] << " export <filename>"
<< endl
<< "Export the global shared memory to a JSON file" << endl;
return 1;
}
auto so_path = get_agent_lib_path();
auto command_to_run =
"LD_PRELOAD=" + so_path + " " + std::string(argv[2]);
return system(command_to_run.c_str());
} else if (cmd == "attach") {
auto filename = std::string(argv[2]);
return bpftime_export_global_shm_to_json(filename.c_str());
} else if (cmd == "import") {
if (argc != 3) {
cerr << "Usage: " << argv[0] << " attach <pid>" << endl;
cerr << "Usage: " << argv[0] << " import <filename>"
<< endl
<< "Import a JSON file containing eBPF objects into the global shared memory" << endl;
return 1;
}
// convert pid to int
int pid = atoi(argv[2]);
auto so_path = get_agent_lib_path();
return inject_agent(pid, so_path.c_str());
auto filename = std::string(argv[2]);
return bpftime_import_global_shm_from_json(filename.c_str());
} else {
cerr << "Invalid subcommand " << cmd << endl;
return 1;
Expand Down

0 comments on commit aa07d92

Please sign in to comment.