Skip to content

Commit b979ab8

Browse files
committed
chore: wip [skip ci]
1 parent 4f99856 commit b979ab8

10 files changed

Lines changed: 362 additions & 107 deletions

File tree

crates/memtrack/src/ebpf/c/event.h

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,42 @@
1010
#define EVENT_TYPE_MUNMAP 7
1111
#define EVENT_TYPE_BRK 8
1212

13-
/* Event structure - shared between BPF and userspace */
14-
struct event {
13+
/* Common header shared by all event types */
14+
struct event_header {
1515
uint8_t event_type; /* See EVENT_TYPE_* constants above */
1616
uint64_t timestamp; /* monotonic time in nanoseconds (CLOCK_MONOTONIC) */
1717
uint32_t pid;
1818
uint32_t tid;
19-
uint64_t addr; /* address returned/freed */
20-
uint64_t size; /* size requested */
19+
};
20+
21+
/* Tagged union event structure */
22+
struct event {
23+
struct event_header header;
24+
union {
25+
/* Allocation events (malloc, calloc, aligned_alloc) */
26+
struct {
27+
uint64_t addr; /* address returned */
28+
uint64_t size; /* size requested */
29+
} alloc;
30+
31+
/* Deallocation event (free) */
32+
struct {
33+
uint64_t addr; /* address to free */
34+
} free;
35+
36+
/* Reallocation event - includes both old and new addresses */
37+
struct {
38+
uint64_t old_addr; /* previous address (can be NULL) */
39+
uint64_t new_addr; /* new address returned */
40+
uint64_t size; /* new size requested */
41+
} realloc;
42+
43+
/* Memory mapping events (mmap, munmap, brk) */
44+
struct {
45+
uint64_t addr; /* address of mapping */
46+
uint64_t size; /* size of mapping */
47+
} mmap;
48+
} data;
2149
};
2250

2351
#endif /* __EVENT_H__ */

crates/memtrack/src/ebpf/c/memtrack.bpf.c

Lines changed: 102 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -123,29 +123,64 @@ static __always_inline __u64* take_param(void* map) {
123123
return value;
124124
}
125125

126-
/* Helper to submit an event to the ring buffer */
127-
static __always_inline int submit_event(__u64 addr, __u64 size, __u8 event_type) {
128-
__u64 tid = bpf_get_current_pid_tgid();
129-
__u32 pid = tid >> 32;
130-
131-
if (!is_tracked(pid) || !is_enabled()) {
132-
return 0;
126+
/* Macro to handle common event submission boilerplate
127+
* Usage: SUBMIT_EVENT(event_type, { e->data.foo = bar; })
128+
*/
129+
#define SUBMIT_EVENT(evt_type, fill_data) \
130+
{ \
131+
__u64 tid = bpf_get_current_pid_tgid(); \
132+
__u32 pid = tid >> 32; \
133+
\
134+
if (!is_tracked(pid) || !is_enabled()) { \
135+
return 0; \
136+
} \
137+
\
138+
struct event* e = bpf_ringbuf_reserve(&events, sizeof(*e), 0); \
139+
if (!e) { \
140+
return 0; \
141+
} \
142+
\
143+
e->header.timestamp = bpf_ktime_get_ns(); \
144+
e->header.pid = pid; \
145+
e->header.tid = tid & 0xFFFFFFFF; \
146+
e->header.event_type = evt_type; \
147+
\
148+
fill_data; \
149+
\
150+
bpf_ringbuf_submit(e, 0); \
151+
return 0; \
133152
}
134153

135-
struct event* e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
136-
if (!e) {
137-
return 0;
138-
}
154+
/* Helper to submit an allocation event (malloc, calloc, aligned_alloc) */
155+
static __always_inline int submit_alloc_event(__u64 addr, __u64 size, __u8 event_type) {
156+
SUBMIT_EVENT(event_type, {
157+
e->data.alloc.addr = addr;
158+
e->data.alloc.size = size;
159+
});
160+
}
139161

140-
e->timestamp = bpf_ktime_get_ns();
141-
e->pid = pid;
142-
e->tid = tid & 0xFFFFFFFF;
143-
e->event_type = event_type;
144-
e->addr = addr;
145-
e->size = size;
146-
bpf_ringbuf_submit(e, 0);
162+
/* Helper to submit a free event */
163+
static __always_inline int submit_free_event(__u64 addr, __u8 event_type) {
164+
SUBMIT_EVENT(event_type, {
165+
e->data.free.addr = addr;
166+
});
167+
}
147168

148-
return 0;
169+
/* Helper to submit a realloc event with both old and new addresses */
170+
static __always_inline int submit_realloc_event(__u64 old_addr, __u64 new_addr, __u64 size) {
171+
SUBMIT_EVENT(EVENT_TYPE_REALLOC, {
172+
e->data.realloc.old_addr = old_addr;
173+
e->data.realloc.new_addr = new_addr;
174+
e->data.realloc.size = size;
175+
});
176+
}
177+
178+
/* Helper to submit a memory mapping event (mmap, munmap, brk) */
179+
static __always_inline int submit_mmap_event(__u64 addr, __u64 size, __u8 event_type) {
180+
SUBMIT_EVENT(event_type, {
181+
e->data.mmap.addr = addr;
182+
e->data.mmap.size = size;
183+
});
149184
}
150185

151186
/* Macro to generate uprobe/uretprobe pairs for allocation functions */
@@ -163,7 +198,7 @@ static __always_inline int submit_event(__u64 addr, __u64 size, __u8 event_type)
163198
if (addr == 0) { \
164199
return 0; \
165200
} \
166-
return submit_event(addr, *size_ptr, event_type); \
201+
return submit_alloc_event(addr, *size_ptr, event_type); \
167202
}
168203

169204
/* Macro for simple address-only functions like free */
@@ -174,7 +209,7 @@ static __always_inline int submit_event(__u64 addr, __u64 size, __u8 event_type)
174209
if (addr == 0) { \
175210
return 0; \
176211
} \
177-
return submit_event(addr, 0, event_type); \
212+
return submit_free_event(addr, event_type); \
178213
}
179214

180215
/* malloc: allocates with size parameter */
@@ -186,8 +221,49 @@ UPROBE_ADDR_ONLY(free, PT_REGS_PARM1(ctx), EVENT_TYPE_FREE)
186221
/* calloc: allocates with nmemb * size */
187222
UPROBE_WITH_ARGS(calloc, PT_REGS_PARM1(ctx) * PT_REGS_PARM2(ctx), PT_REGS_RC(ctx), EVENT_TYPE_CALLOC)
188223

189-
/* realloc: reallocates with new size */
190-
UPROBE_WITH_ARGS(realloc, PT_REGS_PARM2(ctx), PT_REGS_RC(ctx), EVENT_TYPE_REALLOC)
224+
/* realloc: reallocates with new size (custom implementation to capture old_addr) */
225+
struct realloc_params {
226+
__u64 old_addr;
227+
__u64 size;
228+
};
229+
BPF_HASH_MAP(realloc_params, __u64, struct realloc_params, 10000);
230+
231+
SEC("uprobe")
232+
int uprobe_realloc(struct pt_regs* ctx) {
233+
__u64 tid = bpf_get_current_pid_tgid();
234+
__u32 pid = tid >> 32;
235+
236+
if (!is_tracked(pid)) {
237+
return 0;
238+
}
239+
240+
struct realloc_params params = {
241+
.old_addr = PT_REGS_PARM1(ctx),
242+
.size = PT_REGS_PARM2(ctx),
243+
};
244+
bpf_map_update_elem(&realloc_params, &tid, &params, BPF_ANY);
245+
return 0;
246+
}
247+
248+
SEC("uretprobe")
249+
int uretprobe_realloc(struct pt_regs* ctx) {
250+
__u64 tid = bpf_get_current_pid_tgid();
251+
struct realloc_params* params = bpf_map_lookup_elem(&realloc_params, &tid);
252+
if (!params) {
253+
return 0;
254+
}
255+
256+
/* Take params and delete from map */
257+
struct realloc_params p = *params;
258+
bpf_map_delete_elem(&realloc_params, &tid);
259+
260+
__u64 new_addr = PT_REGS_RC(ctx);
261+
if (new_addr == 0) {
262+
return 0;
263+
}
264+
265+
return submit_realloc_event(p.old_addr, new_addr, p.size);
266+
}
191267

192268
/* aligned_alloc: allocates with alignment and size */
193269
UPROBE_WITH_ARGS(aligned_alloc, PT_REGS_PARM2(ctx), PT_REGS_RC(ctx), EVENT_TYPE_ALIGNED_ALLOC)
@@ -234,7 +310,7 @@ int tracepoint_sys_exit_mmap(struct trace_event_raw_sys_exit* ctx) {
234310
return 0;
235311
}
236312

237-
return submit_event((__u64)ret, args->len, EVENT_TYPE_MMAP);
313+
return submit_mmap_event((__u64)ret, args->len, EVENT_TYPE_MMAP);
238314
}
239315

240316
/* munmap tracking */
@@ -247,7 +323,7 @@ int tracepoint_sys_enter_munmap(struct trace_event_raw_sys_enter* ctx) {
247323
return 0;
248324
}
249325

250-
return submit_event(addr, len, EVENT_TYPE_MUNMAP);
326+
return submit_mmap_event(addr, len, EVENT_TYPE_MUNMAP);
251327
}
252328

253329
/* brk tracking - adjusts the program break (heap boundary) */
@@ -281,5 +357,5 @@ int tracepoint_sys_exit_brk(struct trace_event_raw_sys_exit* ctx) {
281357
return 0;
282358
}
283359

284-
return submit_event(new_brk, 0, EVENT_TYPE_BRK);
360+
return submit_mmap_event(new_brk, 0, EVENT_TYPE_BRK);
285361
}

0 commit comments

Comments
 (0)