Skip to content

Commit

Permalink
Add ARM64 Support (#53)
Browse files Browse the repository at this point in the history
* remove old issues templates dir

* Go 1.18 support

* fix grpc client instrumentation on go1.17

* Avoid detecting init process

* Add ARM64 support

* bug fixes

* arm64 support

* improved stability

* build arm64 docker image
  • Loading branch information
edeNFed authored Feb 11, 2023
1 parent a6842d3 commit 1d6c73b
Show file tree
Hide file tree
Showing 23 changed files with 2,550 additions and 1,572 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ jobs:
run: echo ::set-output name=tag::${GITHUB_REF#refs/*/}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Login to DockerHub
uses: docker/login-action@v1
with:
Expand All @@ -22,3 +24,4 @@ jobs:
with:
push: true
tags: keyval/otel-go-agent:${{ steps.vars.outputs.tag }}
platforms: linux/amd64,linux/arm64
7 changes: 4 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
FROM fedora:35 as builder
ARG TARGETARCH
RUN dnf install clang llvm make libbpf-devel -y
RUN curl -LO https://go.dev/dl/go1.18.linux-amd64.tar.gz && tar -C /usr/local -xzf go*.linux-amd64.tar.gz
RUN curl -LO https://go.dev/dl/go1.18.linux-$TARGETARCH.tar.gz && tar -C /usr/local -xzf go*.linux-$TARGETARCH.tar.gz
ENV PATH="/usr/local/go/bin:${PATH}"
WORKDIR /app
COPY . .
RUN make build
RUN TARGET=$TARGETARCH make build

FROM gcr.io/distroless/base-debian11
FROM registry.fedoraproject.org/fedora-minimal:35
COPY --from=builder /app/kv-go-instrumentation /
CMD ["/kv-go-instrumentation"]
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ REPODIR := $(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))

# Build the list of include directories to compile the bpf program
BPF_INCLUDE += -I${REPODIR}/include/libbpf
BPF_INCLUDE+= -I${REPODIR}/include
BPF_INCLUDE += -I${REPODIR}/include

.PHONY: generate
generate: export CFLAGS := $(BPF_INCLUDE)
Expand All @@ -14,7 +14,7 @@ generate:

.PHONY: build
build: generate
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o kv-go-instrumentation cli/main.go
GOOS=linux go build -o kv-go-instrumentation cli/main.go

.PHONY: docker-build
docker-build:
Expand Down
14 changes: 11 additions & 3 deletions include/alloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ static __always_inline u64 get_area_start() {
static __always_inline u64 get_area_end(u64 start) {
s64 partition_size = (end_addr - start_addr) / total_cpus;
s32 end_index = 1;
bpf_printk("total size: %d, partition size: %d, modulo: %d", end_addr - start_addr, partition_size, (end_addr - start_addr) % partition_size);
u64* end = (u64*)bpf_map_lookup_elem(&alloc_map, &end_index);
if (end == NULL || *end == 0) {
u64 current_end_addr = start + partition_size;
Expand All @@ -49,6 +50,7 @@ static __always_inline void* write_target_data(void* data, s32 size) {

u64 start = get_area_start();
u64 end = get_area_end(start);
s32 current_cpu = bpf_get_smp_processor_id();
if (end - start < size) {
bpf_printk("reached end of CPU memory block, going to the start again");
s32 start_index = 0;
Expand All @@ -61,10 +63,16 @@ static __always_inline void* write_target_data(void* data, s32 size) {
if (success == 0) {
s32 start_index = 0;
u64 updated_start = start + size;

// align updated_start to 8 bytes
if (updated_start % 8 != 0) {
updated_start += 8 - (updated_start % 8);
}

bpf_map_update_elem(&alloc_map, &start_index, &updated_start, BPF_ANY);
return target;
} else {
bpf_printk("failed to write to userspace, error code: %d, addr: %lx, size: %d", success, target, size);
return NULL;
}

bpf_printk("failed to write to userspace, error code: %d, addr: %lx", success, target);
return NULL;
}
21 changes: 11 additions & 10 deletions include/arguments.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "common.h"
#include "bpf_tracing.h"
#include "bpf_helpers.h"
#include <stdbool.h>

Expand All @@ -8,31 +9,31 @@ volatile const bool is_registers_abi;
void* get_argument_by_reg(struct pt_regs *ctx, int index) {
switch (index) {
case 1:
return (void *)(ctx->rax);
return (void*)GO_PARAM1(ctx);
case 2:
return (void *)(ctx->rbx);
return (void*)GO_PARAM2(ctx);
case 3:
return (void *)(ctx->rcx);
return (void*)GO_PARAM3(ctx);
case 4:
return (void *)(ctx->rdi);
return (void*)GO_PARAM4(ctx);
case 5:
return (void *)(ctx->rsi);
return (void*)GO_PARAM5(ctx);
case 6:
return (void *)(ctx->r8);
return (void*)GO_PARAM6(ctx);
case 7:
return (void *)(ctx->r9);
return (void*)GO_PARAM7(ctx);
case 8:
return (void *)(ctx->r10);
return (void*)GO_PARAM8(ctx);
case 9:
return (void *)(ctx->r11);
return (void*)GO_PARAM9(ctx);
default:
return NULL;
}
}

void* get_argument_by_stack(struct pt_regs *ctx, int index) {
void* ptr = 0;
bpf_probe_read(&ptr, sizeof(ptr), (void *)(ctx->rsp+(index*8)));
bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx)+(index*8)));
return ptr;
}

Expand Down
83 changes: 50 additions & 33 deletions include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,40 +70,57 @@ enum {
#define BPF_F_INDEX_MASK 0xffffffffULL
#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK

#define PT_REGS_RC(x) ((x)->rax)
#if defined(__TARGET_ARCH_x86)
struct pt_regs {
/*
* C ABI says these regs are callee-preserved. They aren't saved on kernel entry
* unless syscall needs a complete, fully filled "struct pt_regs".
*/
unsigned long r15;
unsigned long r14;
unsigned long r13;
unsigned long r12;
unsigned long rbp;
unsigned long rbx;
/* These regs are callee-clobbered. Always saved on kernel entry. */
unsigned long r11;
unsigned long r10;
unsigned long r9;
unsigned long r8;
unsigned long rax;
unsigned long rcx;
unsigned long rdx;
unsigned long rsi;
unsigned long rdi;
/*
* On syscall entry, this is syscall#. On CPU exception, this is error code.
* On hw interrupt, it's IRQ number:
*/
unsigned long orig_rax;
/* Return frame for iretq */
unsigned long rip;
unsigned long cs;
unsigned long eflags;
unsigned long rsp;
unsigned long ss;
/* top of stack page */
long unsigned int r15;
long unsigned int r14;
long unsigned int r13;
long unsigned int r12;
long unsigned int bp;
long unsigned int bx;
long unsigned int r11;
long unsigned int r10;
long unsigned int r9;
long unsigned int r8;
long unsigned int ax;
long unsigned int cx;
long unsigned int dx;
long unsigned int si;
long unsigned int di;
long unsigned int orig_ax;
long unsigned int ip;
long unsigned int cs;
long unsigned int flags;
long unsigned int sp;
long unsigned int ss;
};
#elif defined(__TARGET_ARCH_arm64)
struct user_pt_regs {
__u64 regs[31];
__u64 sp;
__u64 pc;
__u64 pstate;
};

struct pt_regs {
union {
struct user_pt_regs user_regs;
struct {
u64 regs[31];
u64 sp;
u64 pc;
u64 pstate;
};
};
u64 orig_x0;
s32 syscallno;
u32 unused2;
u64 orig_addr_limit;
u64 pmr_save;
u64 stackframe[2];
u64 lockdep_hardirqs;
u64 exit_rcu;
};
#endif

#endif /* __VMLINUX_H__ */
6 changes: 5 additions & 1 deletion include/go_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,11 @@ static __always_inline struct go_string write_user_go_string(char* str, u32 len)
new_string.len = len;

// Copy new string struct to userspace
write_target_data((void*)&new_string, sizeof(new_string));
void* res = write_target_data((void*)&new_string, sizeof(new_string));
if (res == NULL) {
new_string.len = 0;
}

return new_string;
}

Expand Down
55 changes: 55 additions & 0 deletions include/libbpf/bpf_tracing.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
#elif defined(__TARGET_ARCH_sparc)
#define bpf_target_sparc
#define bpf_target_defined
#elif defined(__TARGET_ARCH_riscv)
#define bpf_target_riscv
#define bpf_target_defined
#else

/* Fall back to what the compiler says */
Expand All @@ -48,6 +51,9 @@
#elif defined(__sparc__)
#define bpf_target_sparc
#define bpf_target_defined
#elif defined(__riscv) && __riscv_xlen == 64
#define bpf_target_riscv
#define bpf_target_defined
#endif /* no compiler target */

#endif
Expand All @@ -60,6 +66,17 @@

#if defined(__KERNEL__) || defined(__VMLINUX_H__)

#define GO_PARAM1(x) ((x)->ax)
#define GO_PARAM2(x) ((x)->bx)
#define GO_PARAM3(x) ((x)->cx)
#define GO_PARAM4(x) ((x)->di)
#define GO_PARAM5(x) ((x)->si)
#define GO_PARAM6(x) ((x)->r8)
#define GO_PARAM7(x) ((x)->r9)
#define GO_PARAM8(x) ((x)->r10)
#define GO_PARAM9(x) ((x)->r11)
#define GOROUTINE(x) ((x)->r14)

#define PT_REGS_PARM1(x) ((x)->di)
#define PT_REGS_PARM2(x) ((x)->si)
#define PT_REGS_PARM3(x) ((x)->dx)
Expand Down Expand Up @@ -192,6 +209,18 @@ struct pt_regs;
/* arm64 provides struct user_pt_regs instead of struct pt_regs to userspace */
struct pt_regs;
#define PT_REGS_ARM64 const volatile struct user_pt_regs

#define GO_PARAM1(x) (((PT_REGS_ARM64 *)(x))->regs[0])
#define GO_PARAM2(x) (((PT_REGS_ARM64 *)(x))->regs[1])
#define GO_PARAM3(x) (((PT_REGS_ARM64 *)(x))->regs[2])
#define GO_PARAM4(x) (((PT_REGS_ARM64 *)(x))->regs[3])
#define GO_PARAM5(x) (((PT_REGS_ARM64 *)(x))->regs[4])
#define GO_PARAM6(x) (((PT_REGS_ARM64 *)(x))->regs[5])
#define GO_PARAM7(x) (((PT_REGS_ARM64 *)(x))->regs[6])
#define GO_PARAM8(x) (((PT_REGS_ARM64 *)(x))->regs[7])
#define GO_PARAM9(x) (((PT_REGS_ARM64 *)(x))->regs[8])
#define GOROUTINE(x) (((PT_REGS_ARM64 *)(x))->regs[28])

#define PT_REGS_PARM1(x) (((PT_REGS_ARM64 *)(x))->regs[0])
#define PT_REGS_PARM2(x) (((PT_REGS_ARM64 *)(x))->regs[1])
#define PT_REGS_PARM3(x) (((PT_REGS_ARM64 *)(x))->regs[2])
Expand Down Expand Up @@ -288,6 +317,32 @@ struct pt_regs;
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((x), pc)
#endif

#elif defined(bpf_target_riscv)

struct pt_regs;
#define PT_REGS_RV const volatile struct user_regs_struct
#define PT_REGS_PARM1(x) (((PT_REGS_RV *)(x))->a0)
#define PT_REGS_PARM2(x) (((PT_REGS_RV *)(x))->a1)
#define PT_REGS_PARM3(x) (((PT_REGS_RV *)(x))->a2)
#define PT_REGS_PARM4(x) (((PT_REGS_RV *)(x))->a3)
#define PT_REGS_PARM5(x) (((PT_REGS_RV *)(x))->a4)
#define PT_REGS_RET(x) (((PT_REGS_RV *)(x))->ra)
#define PT_REGS_FP(x) (((PT_REGS_RV *)(x))->s5)
#define PT_REGS_RC(x) (((PT_REGS_RV *)(x))->a5)
#define PT_REGS_SP(x) (((PT_REGS_RV *)(x))->sp)
#define PT_REGS_IP(x) (((PT_REGS_RV *)(x))->epc)

#define PT_REGS_PARM1_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a0)
#define PT_REGS_PARM2_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a1)
#define PT_REGS_PARM3_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a2)
#define PT_REGS_PARM4_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a3)
#define PT_REGS_PARM5_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a4)
#define PT_REGS_RET_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), ra)
#define PT_REGS_FP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), fp)
#define PT_REGS_RC_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), a5)
#define PT_REGS_SP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), sp)
#define PT_REGS_IP_CORE(x) BPF_CORE_READ((PT_REGS_RV *)(x), epc)

#endif

#if defined(bpf_target_powerpc)
Expand Down
Loading

0 comments on commit 1d6c73b

Please sign in to comment.