Skip to content

Commit

Permalink
docs: add documents of how to use JIT (#98)
Browse files Browse the repository at this point in the history
* fix lock for array

* add spinlock

* use pthread spinlock
  • Loading branch information
yunwei37 authored Nov 21, 2023
1 parent a7ec9af commit 722411c
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 30 deletions.
6 changes: 4 additions & 2 deletions daemon/kernel/bpf_tracer.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -398,11 +398,13 @@ process_perf_event_open_enter(struct trace_event_raw_sys_enter *ctx)
return 0;
}
bpf_probe_read_user(&new_attr_buffer, sizeof(new_attr_buffer), attr);
struct perf_event_attr* new_attr_pointer = &new_attr_buffer;
struct perf_event_attr *new_attr_pointer =
(struct perf_event_attr *)&new_attr_buffer;
if (new_attr_pointer->type == uprobe_perf_type) {
// found uprobe
if (enable_replace_uprobe) {
if (can_hook_uprobe_at(new_attr_pointer->probe_offset)) {
if (can_hook_uprobe_at(
new_attr_pointer->probe_offset)) {
u64 old_offset = new_attr_pointer->probe_offset;
new_attr_pointer->probe_offset = 0;
long size = bpf_probe_read_user_str(
Expand Down
2 changes: 1 addition & 1 deletion daemon/user/handle_bpf_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ int bpf_event_handler::handle_perf_event_open(const struct event *e)
spdlog::debug("handle_perf_event");
const char *type_id_str = "UNKNOWN TYPE";
unsigned int perf_type = e->perf_event_data.attr.type;
if (perf_type >= 0 && perf_type < (sizeof(perf_type_id_strings) /
if (perf_type < (sizeof(perf_type_id_strings) /
sizeof(perf_type_id_strings[0]))) {
type_id_str = perf_type_id_strings[perf_type];
}
Expand Down
8 changes: 8 additions & 0 deletions documents/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@

It's at a very early stage and may contain bugs on more platforms and eBPF programs.

## Run with JIT enabled

Set `BPFTIME_USE_JIT=true` in the server to enable JIT, for example, when running the server:

```sh
LD_PRELOAD=~/.bpftime/libbpftime-syscall-server.so BPFTIME_USE_JIT=true example/malloc/malloc
```

## Uprobe and uretprobe

With `bpftime`, you can build eBPF applications using familiar tools like clang and libbpf, and execute them in userspace. For instance, the `malloc` eBPF program traces malloc calls using uprobe and aggregates the counts using a hash map.
Expand Down
31 changes: 29 additions & 2 deletions example/sslsniff/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# sslsniff

Not working because we refactored the runtime.
## Run the probe

TODO: make the ring buffer work again.
```sh
sudo LD_PRELOAD=build/runtime/syscall-server/libbpftime-syscal
l-server.so example/sslsniff/sslsniff
```

## run the example

```sh
sudo LD_PRELOAD=build/runtime/agent/libbpftime-agent.so wget https://www.google.com
```

## Output

```txt
----- DATA -----
gle.erd={jsr:1,bv:1904,de:true};
var h=this||self;var k,l=null!=(k=h.mei)?k:1,n,p=null!=(n=h.sdo)?n:!0,q=0,r,t=google.erd,v=t.jsr;google.ml=function(a,b,d,m,e){e=void 0===e?2:e;b&&(r=a&&a.message);void 0===d&&(d={});d.cad="ple_"+google.ple+".aple_"+google.aple;if(google.dl)return google.dl(a,e,d),null;if(0>v){window.console&&console.error(a,d);if(-2===v)throw a;b=!1}else b=!a||!a.message||"Error loading script"===a.message||q>=l&&!m?!1:!0;if(!b)return null;q++;d=d||{};b=encodeURIComponent;var c="/gen_204?atyp=i&ei="+b(google.kEI);google.kEXPI&&(c+="&jexpid="+b(google.kEXPI));c+="&srcpg="+b(google.sn)+"&jsr="+b(t.jsr)+"&bver="+
b(t.bv);var f=a.lineNumber;void 0!==f&&(c+="&line="+f);var g=a.fileName;g&&(0<g.indexOf("-extension:/")&&(e=3),c+="&script="+b(g),f&&g===window.location.href&&(f=document.documentElement.outerHTML.split("\n")[f],c+="&cad="+b(f?f.substring(0,300):"No script found.")));google.ple&&1===google.ple&&(e=2);c+="&jsel="+e;for(var u in d)c+="&",c+=b(u),c+="=",c+=b(d[u]);c=c+"&emsg="+b(a.name+": "+a.message);c=c+"&jsst="+b(a.stack||"N/A");12288<=c.length&&(c=c.substr(0,12288));a=c;m||google.log(0,"",a);return a};window.onerror=function(a,b,d,m,e){r!==a&&(a=e instanceof Error?e:Error(a),void 0===d
----- END DATA -----
READ/RECV 0.127135326 wget 165620 1228
----- DATA -----
||"lineNumber"in a||(a.lineNumber=d),void 0===b||"fileName"in a||(a.fileName=b),google.ml(a,!1,void 0,!1,"SyntaxError"===a.name||"SyntaxError"===a.message.substring(0,11)||-1!==a.message.indexOf("Script error")?3:0));r=null;p&&q>=l&&(window.onerror=null)};})();</script></head><body bgcolor="#fff"><script nonce="CI2JfUFPMIVEYcnuixggow">(function(){var src='/images/nav_logo229.png';var iesg=false;document.body.onload = function(){window.n && window.n();if (document.images){new Image().src=src;}
if (!iesg){document.f&&document.f.q.focus();document.gbqf&&document.gbqf.q.focus();}
}
})();</script><div id="mngb"><div id=gbar><nobr><b class=gb1>Search</b> <a class=gb1 href="https://www.google.com/imghp?hl=en&tab=wi">Images</a> <a class=gb1 href="https://maps.google.com/maps?hl=en&tab=wl">Maps</a> <a class=gb1 href="https://play.google.com/?hl=en&tab=w8">Play</a> <a class=gb1 href="https://www.youtube.com/?tab=w1">YouTube</a> <a class=gb1 href="https://news.google.com/?tab=wn">News</a> <a class=gb1 href="https://mail.google.com/mail/?tab=wm">Gmail</a> <a class=gb1 href="https://drive.google.com/?tab=wo">Drive</a> <a class=gb1 style="text-decoration:none" href="https://www.google.com/intl/en/about/products?tab=wh"><u>
----- END DATA -----
```
2 changes: 1 addition & 1 deletion runtime/src/bpf_map/userspace/array_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class array_map_impl {
uint32_t _max_entries;

public:
const static bool should_lock = true;
const static bool should_lock = false;
array_map_impl(boost::interprocess::managed_shared_memory &memory,
uint32_t value_size, uint32_t max_entries);

Expand Down
2 changes: 2 additions & 0 deletions runtime/src/bpf_map/userspace/hash_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

namespace bpftime
{

hash_map_impl::hash_map_impl(managed_shared_memory &memory, uint32_t key_size,
uint32_t value_size)
: map_impl(10, bytes_vec_hasher(), std::equal_to<bytes_vec>(),
Expand All @@ -20,6 +21,7 @@ hash_map_impl::hash_map_impl(managed_shared_memory &memory, uint32_t key_size,
value_vec(value_size, memory.get_segment_manager())
{
}

void *hash_map_impl::elem_lookup(const void *key)
{
spdlog::trace("Peform elem lookup of hash map");
Expand Down
7 changes: 3 additions & 4 deletions runtime/src/bpf_map/userspace/hash_map.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,15 @@ namespace bpftime

using namespace boost::interprocess;


// implementation of hash map
class hash_map_impl {
using bi_map_value_ty = std::pair<const bytes_vec, bytes_vec>;
using bi_map_allocator =
allocator<bi_map_value_ty,
managed_shared_memory::segment_manager>;
using shm_hash_map = boost::unordered_map<
bytes_vec, bytes_vec, bytes_vec_hasher,
std::equal_to<bytes_vec>, bi_map_allocator>;
using shm_hash_map =
boost::unordered_map<bytes_vec, bytes_vec, bytes_vec_hasher,
std::equal_to<bytes_vec>, bi_map_allocator>;
shm_hash_map map_impl;
uint32_t _key_size;
uint32_t _value_size;
Expand Down
1 change: 1 addition & 0 deletions runtime/src/bpftime_shm_internal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "bpftime_config.hpp"
#include <handler/handler_manager.hpp>
#include <optional>

namespace bpftime
{

Expand Down
21 changes: 7 additions & 14 deletions runtime/src/handler/map_handler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,15 @@ const void *bpf_map_handler::map_lookup_elem(const void *key,
{
const auto do_lookup = [&](auto *impl) -> const void * {
if (impl->should_lock) {
sharable_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->elem_lookup(key);
} else {
return impl->elem_lookup(key);
}
};
const auto do_lookup_userspace = [&](auto *impl) -> const void * {
if (impl->should_lock) {
sharable_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->elem_lookup_userspace(key);
} else {
return impl->elem_lookup_userspace(key);
Expand Down Expand Up @@ -133,8 +131,7 @@ long bpf_map_handler::map_update_elem(const void *key, const void *value,
{
const auto do_update = [&](auto *impl) -> long {
if (impl->should_lock) {
scoped_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->elem_update(key, value, flags);
} else {
return impl->elem_update(key, value, flags);
Expand All @@ -143,8 +140,7 @@ long bpf_map_handler::map_update_elem(const void *key, const void *value,

const auto do_update_userspace = [&](auto *impl) -> long {
if (impl->should_lock) {
scoped_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->elem_update_userspace(key, value, flags);
} else {
return impl->elem_update_userspace(key, value, flags);
Expand Down Expand Up @@ -211,8 +207,7 @@ int bpf_map_handler::bpf_map_get_next_key(const void *key, void *next_key,
{
const auto do_get_next_key = [&](auto *impl) -> int {
if (impl->should_lock) {
sharable_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->map_get_next_key(key, next_key);
} else {
return impl->map_get_next_key(key, next_key);
Expand Down Expand Up @@ -277,17 +272,15 @@ long bpf_map_handler::map_delete_elem(const void *key,
{
const auto do_delete = [&](auto *impl) -> long {
if (impl->should_lock) {
scoped_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->elem_delete(key);
} else {
return impl->elem_delete(key);
}
};
const auto do_delete_userspace = [&](auto *impl) -> long {
if (impl->should_lock) {
scoped_lock<interprocess_sharable_mutex> guard(
*map_mutex);
bpftime_lock_guard guard(map_lock);
return impl->elem_delete_userspace(key);
} else {
return impl->elem_delete_userspace(key);
Expand Down
30 changes: 24 additions & 6 deletions runtime/src/handler/map_handler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,28 @@ using boost_shm_string =
using sharable_mutex_ptr = boost::interprocess::managed_unique_ptr<
boost::interprocess::interprocess_sharable_mutex,
boost::interprocess::managed_shared_memory>::type;

// lock guad for RAII
class bpftime_lock_guard {
private:
volatile pthread_spinlock_t &spinlock;

public:
explicit bpftime_lock_guard(volatile pthread_spinlock_t &spinlock)
: spinlock(spinlock)
{
pthread_spin_lock(&spinlock);
}
~bpftime_lock_guard()
{
pthread_spin_unlock(&spinlock);
}

// Delete copy constructor and assignment operator
bpftime_lock_guard(const bpftime_lock_guard &) = delete;
bpftime_lock_guard &operator=(const bpftime_lock_guard &) = delete;
};

// bpf map handler
// all map data will be put on shared memory, so it can be accessed by
// different processes
Expand All @@ -52,16 +74,12 @@ class bpf_map_handler {
boost::interprocess::managed_shared_memory &mem)
: type((bpf_map_type)type),
name(char_allocator(mem.get_segment_manager())),
map_mutex(boost::interprocess::make_managed_unique_ptr(
mem.construct<boost::interprocess::
interprocess_sharable_mutex>(
boost::interprocess::anonymous_instance)(),
mem)),
map_impl_ptr(nullptr), max_entries(max_ents), flags(flags),
key_size(key_size), value_size(value_size)

{
spdlog::debug("Create map with type {}", type);
pthread_spin_init(&map_lock, 0);
this->name = name;
}
bpf_map_handler(const bpf_map_handler &) = delete;
Expand Down Expand Up @@ -171,7 +189,7 @@ class bpf_map_handler {

private:
std::string get_container_name();
mutable sharable_mutex_ptr map_mutex;
mutable pthread_spinlock_t map_lock;
// The underlying data structure of the map
general_map_impl_ptr map_impl_ptr;
uint32_t max_entries = 0;
Expand Down

0 comments on commit 722411c

Please sign in to comment.