From ee78050ea77167d688d44f35100b367da06f28e2 Mon Sep 17 00:00:00 2001 From: yihong0618 Date: Tue, 13 Jun 2023 21:03:46 +0800 Subject: [PATCH 1/2] feat: support aarch64 Signed-off-by: yihong0618 --- src/pgtracer/ebpf/code/perf.c | 2 +- src/pgtracer/ebpf/code/stack.h | 96 +++++++++++++++++++++++++++++++++- src/pgtracer/ebpf/unwind.py | 82 +++++++++++++++++++++++++++++ 3 files changed, 178 insertions(+), 2 deletions(-) diff --git a/src/pgtracer/ebpf/code/perf.c b/src/pgtracer/ebpf/code/perf.c index 964b05b..6b0486d 100644 --- a/src/pgtracer/ebpf/code/perf.c +++ b/src/pgtracer/ebpf/code/perf.c @@ -93,7 +93,7 @@ int perf_event(struct bpf_perf_event_data *ctx) } if (need_node) { - capture_stack(&(ctx->regs), &(stack_sample->stack_data), MAX_STACK_READ); + capture_stack((struct pt_regs *)&(ctx->regs), &(stack_sample->stack_data), MAX_STACK_READ); } event_ring.ringbuf_submit(stack_sample, 0); } diff --git a/src/pgtracer/ebpf/code/stack.h b/src/pgtracer/ebpf/code/stack.h index 75d2afc..7a14083 100644 --- a/src/pgtracer/ebpf/code/stack.h +++ b/src/pgtracer/ebpf/code/stack.h @@ -2,6 +2,7 @@ #define STACK_H #include +#if defined(__x86_64__) struct stack_data_t { u64 rax; u64 rdx; @@ -61,5 +62,98 @@ static inline int capture_stack(struct pt_regs *ctx, struct stack_data_t *stack_ } return ret; } +#elif defined(__aarch64__) +struct stack_data_t { + u64 x0; + u64 x1; + u64 x2; + u64 x3; + u64 x4; + u64 x5; + u64 x6; + u64 x7; + u64 x8; + u64 x9; + u64 x10; + u64 x11; + u64 x12; + u64 x13; + u64 x14; + u64 x15; + u64 x16; + u64 x17; + u64 x18; + u64 x19; + u64 x20; + u64 x21; + u64 x22; + u64 x23; + u64 x24; + u64 x25; + u64 x26; + u64 x27; + u64 x28; + u64 x29; // frame pointer + u64 x30; // link register + u64 sp; // stack pointer + u64 pc; // program counter + u64 size; + u64 start_addr; + char stack[MAX_STACK_READ]; // Dynamically injected using defines +}; + +/* + * Capture the current stack and register values. + */ +static inline int capture_stack(struct pt_regs *ctx, struct stack_data_t *stack_data, u64 max_read) +{ + int ret = 0; + stack_data->x0 = ctx->regs[0]; + stack_data->x1 = ctx->regs[1]; + stack_data->x2 = ctx->regs[2]; + stack_data->x3 = ctx->regs[3]; + stack_data->x4 = ctx->regs[4]; + stack_data->x5 = ctx->regs[5]; + stack_data->x6 = ctx->regs[6]; + stack_data->x7 = ctx->regs[7]; + stack_data->x8 = ctx->regs[8]; + stack_data->x9 = ctx->regs[9]; + stack_data->x10 = ctx->regs[10]; + stack_data->x11 = ctx->regs[11]; + stack_data->x12 = ctx->regs[12]; + stack_data->x13 = ctx->regs[13]; + stack_data->x14 = ctx->regs[14]; + stack_data->x15 = ctx->regs[15]; + stack_data->x16 = ctx->regs[16]; + stack_data->x17 = ctx->regs[17]; + stack_data->x18 = ctx->regs[18]; + stack_data->x19 = ctx->regs[19]; + stack_data->x20 = ctx->regs[20]; + stack_data->x21 = ctx->regs[21]; + stack_data->x22 = ctx->regs[22]; + stack_data->x23 = ctx->regs[23]; + stack_data->x24 = ctx->regs[24]; + stack_data->x25 = ctx->regs[25]; + stack_data->x26 = ctx->regs[26]; + stack_data->x27 = ctx->regs[27]; + stack_data->x28 = ctx->regs[28]; + stack_data->x29 = ctx->regs[29]; + stack_data->x30 = ctx->regs[30]; + stack_data->sp = ctx->sp; + stack_data->pc = ctx->pc; + stack_data->start_addr = stack_data->sp; + stack_data->size = (STACK_TOP_ADDR - stack_data->sp); + if (stack_data->size > max_read) + stack_data->size = max_read; + ret = bpf_probe_read_user(&stack_data->stack, + stack_data->size, + (void *) (stack_data->sp)); + if (ret != 0) + { + stack_data->size = 0; + } + return ret; +} +#endif // Arch -#endif +#endif // STACK_H diff --git a/src/pgtracer/ebpf/unwind.py b/src/pgtracer/ebpf/unwind.py index 769a44d..c2d0f16 100644 --- a/src/pgtracer/ebpf/unwind.py +++ b/src/pgtracer/ebpf/unwind.py @@ -149,6 +149,88 @@ class unw_tdep_proc_info_t(ct.Structure): _fields_ = [("unused", ct.c_char)] + class unw_proc_info_t(ct.Structure): + """ + Mapping of unw_proc_info_t type + """ + + _fields_ = [ + ("start_ip", unw_word_t), + ("end_ip", unw_word_t), + ("lsda", unw_word_t), + ("handler", unw_word_t), + ("gp", unw_word_t), + ("flags", unw_word_t), + ("format", ct.c_int), + ("unwind_info_size", ct.c_int), + ("unwind_info", ct.c_void_p), + ("extra", unw_tdep_proc_info_t), + ] + +elif ARCH == "aarch64": + UNW_TDEP_CURSOR_LEN = 256 # Placeholder value, adapt as needed + unw_word_t = ct.c_ulonglong + UNW_WORD_T_FORMAT = " Date: Tue, 13 Jun 2023 21:31:47 +0800 Subject: [PATCH 2/2] fix: refactor logic make ci happy --- src/pgtracer/ebpf/unwind.py | 205 +++++++++++++++++++----------------- 1 file changed, 107 insertions(+), 98 deletions(-) diff --git a/src/pgtracer/ebpf/unwind.py b/src/pgtracer/ebpf/unwind.py index c2d0f16..7cf21a0 100644 --- a/src/pgtracer/ebpf/unwind.py +++ b/src/pgtracer/ebpf/unwind.py @@ -84,13 +84,19 @@ def find_libunwind_version() -> Tuple[int, int]: if libname is None: raise ImportError(f"Cannot load libunwind-{ARCH}") libunwind = ct.cdll.LoadLibrary(libname) + +if ARCH not in ["x86_64", "aarch64"]: + raise NotImplementedError(f"Stack unwinding is not supporte for {ARCH} arch") + +# same value for x86_64 and aarch64 +unw_word_t = ct.c_ulonglong +UNW_WORD_T_FORMAT = " Tuple[int, int]: "rip", ] UNW_REG_IP = REG_NAMES.index("rip") + stack_data_fields_list = [ + ("rax", ct.c_ulong), + ("rdx", ct.c_ulong), + ("rcx", ct.c_ulong), + ("rbx", ct.c_ulong), + ("rsi", ct.c_ulong), + ("rdi", ct.c_ulong), + ("rbp", ct.c_ulong), + ("rsp", ct.c_ulong), + ("r8", ct.c_ulong), + ("r9", ct.c_ulong), + ("r10", ct.c_ulong), + ("r11", ct.c_ulong), + ("r12", ct.c_ulong), + ("r13", ct.c_ulong), + ("r14", ct.c_ulong), + ("r15", ct.c_ulong), + ("rip", ct.c_ulong), + ("size", ct.c_ulong), + ("start_addr", ct.c_ulong), + ("stack", stack_array), + ] - # This corresponds to the stack and registers captured from ebpf, - # and is architecture specific - class stack_data_t(ct.Structure): - """ - Mapping of stack_data_t type, defined in ebpf code. - """ - - _fields_ = [ - ("rax", ct.c_ulong), - ("rdx", ct.c_ulong), - ("rcx", ct.c_ulong), - ("rbx", ct.c_ulong), - ("rsi", ct.c_ulong), - ("rdi", ct.c_ulong), - ("rbp", ct.c_ulong), - ("rsp", ct.c_ulong), - ("r8", ct.c_ulong), - ("r9", ct.c_ulong), - ("r10", ct.c_ulong), - ("r11", ct.c_ulong), - ("r12", ct.c_ulong), - ("r13", ct.c_ulong), - ("r14", ct.c_ulong), - ("r15", ct.c_ulong), - ("rip", ct.c_ulong), - ("size", ct.c_ulong), - ("start_addr", ct.c_ulong), - ("stack", stack_array), - ] - - class unw_tdep_proc_info_t(ct.Structure): - """ - Mapping of unw_tdep_proc_info_t - """ - - _fields_ = [("unused", ct.c_char)] - - class unw_proc_info_t(ct.Structure): - """ - Mapping of unw_proc_info_t type - """ - - _fields_ = [ - ("start_ip", unw_word_t), - ("end_ip", unw_word_t), - ("lsda", unw_word_t), - ("handler", unw_word_t), - ("gp", unw_word_t), - ("flags", unw_word_t), - ("format", ct.c_int), - ("unwind_info_size", ct.c_int), - ("unwind_info", ct.c_void_p), - ("extra", unw_tdep_proc_info_t), - ] +elif ARCH == "aarch64": + UNW_TDEP_CURSOR_LEN = 256 # Placeholder value, adapt as needed + REG_NAMES = [ + "x0", + "x1", + "x2", + "x3", + "x4", + "x5", + "x6", + "x7", + "x8", + "x9", + "x10", + "x11", + "x12", + "x13", + "x14", + "x15", + "x16", + "x17", + "x18", + "x19", + "x20", + "x21", + "x22", + "x23", + "x24", + "x25", + "x26", + "x27", + "x28", + "x29", + "x30", + "sp", + "pc", + ] + UNW_REG_IP = REG_NAMES.index("pc") + stack_data_fields_list = [(reg, ct.c_ulong) for reg in REG_NAMES] + [ + ("size", ct.c_ulong), + ("start_addr", ct.c_ulong), + ("stack", stack_array), + ] elif ARCH == "aarch64": UNW_TDEP_CURSOR_LEN = 256 # Placeholder value, adapt as needed - unw_word_t = ct.c_ulonglong - UNW_WORD_T_FORMAT = "