From 4419cc8e9d2c8d08991f374c4b5fcc0c2ea5641c Mon Sep 17 00:00:00 2001 From: Eden Federman Date: Sat, 11 Feb 2023 11:01:47 -0800 Subject: [PATCH 01/46] Add ARM64 Support Ported from https://github.com/keyval-dev/opentelemetry-go-instrumentation/pull/53 Co-authored-by: Eden Federman --- .github/workflows/release.yaml | 2 +- Dockerfile | 5 +- Makefile | 4 +- include/alloc.h | 8 +- include/arguments.h | 23 ++-- include/common.h | 86 ++++++++----- include/go_types.h | 6 +- include/libbpf/bpf_tracing.h | 55 ++++++++ .../bpf/github.com/gorilla/mux/probe.go | 2 +- .../google/golang/org/grpc/bpf/probe.bpf.c | 28 ++-- .../bpf/google/golang/org/grpc/probe.go | 2 +- .../golang/org/grpc/server/bpf/probe.bpf.c | 45 +------ .../google/golang/org/grpc/server/probe.go | 15 +-- .../bpf/net/http/server/probe.go | 2 +- pkg/instrumentors/manager.go | 17 ++- pkg/process/analyze.go | 121 +++++++++--------- pkg/process/ret_linux_amd64.go | 25 ++++ pkg/process/ret_linux_arm64.go | 25 ++++ 18 files changed, 283 insertions(+), 188 deletions(-) create mode 100644 pkg/process/ret_linux_amd64.go create mode 100644 pkg/process/ret_linux_arm64.go diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index 82f7e03f5..a3751f96b 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -42,4 +42,4 @@ jobs: push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - platforms: linux/amd64 + platforms: linux/amd64,linux/arm64 diff --git a/Dockerfile b/Dockerfile index 0f1ed7dae..8649cfe50 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,11 @@ FROM fedora:37 as builder +ARG TARGETARCH RUN dnf install clang llvm make libbpf-devel -y -RUN curl -LO https://go.dev/dl/go1.20.linux-amd64.tar.gz && tar -C /usr/local -xzf go*.linux-amd64.tar.gz +RUN curl -LO https://go.dev/dl/go1.20.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 registry.fedoraproject.org/fedora-minimal:37 COPY --from=builder /app/otel-go-instrumentation / diff --git a/Makefile b/Makefile index dfec3a943..7e5ecbddc 100644 --- a/Makefile +++ b/Makefile @@ -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 # Tools TOOLS_MOD_DIR := ./internal/tools @@ -30,7 +30,7 @@ generate: .PHONY: build build: generate - GOOS=linux GOARCH=amd64 go build -o otel-go-instrumentation cli/main.go + GOOS=linux go build -o otel-go-instrumentation cli/main.go .PHONY: docker-build docker-build: diff --git a/include/alloc.h b/include/alloc.h index 3fff24d8c..11e1d66ca 100644 --- a/include/alloc.h +++ b/include/alloc.h @@ -52,7 +52,7 @@ static __always_inline u64 get_area_end(u64 start) { s64 partition_size = (end_addr - start_addr) / total_cpus; s32 end_index = 1; - u64 *end = (u64 *)bpf_map_lookup_elem(&alloc_map, &end_index); + u64* end = (u64*)bpf_map_lookup_elem(&alloc_map, &end_index); if (end == NULL || *end == 0) { u64 current_end_addr = start + partition_size; @@ -88,6 +88,12 @@ static __always_inline void *write_target_data(void *data, s32 size) { 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; } diff --git a/include/arguments.h b/include/arguments.h index e75937fd2..b66a90a87 100644 --- a/include/arguments.h +++ b/include/arguments.h @@ -13,6 +13,7 @@ // limitations under the License. #include "common.h" +#include "bpf_tracing.h" #include "bpf_helpers.h" #include @@ -24,23 +25,23 @@ 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; } @@ -48,8 +49,8 @@ void *get_argument_by_reg(struct pt_regs *ctx, int index) 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))); + void* ptr = 0; + bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx)+(index*8))); return ptr; } diff --git a/include/common.h b/include/common.h index 7316a0459..19f1fba55 100644 --- a/include/common.h +++ b/include/common.h @@ -84,41 +84,57 @@ enum #define BPF_F_INDEX_MASK 0xffffffffULL #define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK -#define PT_REGS_RC(x) ((x)->rax) -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 */ +#if defined(__TARGET_ARCH_x86) +struct pt_regs { + 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__ */ diff --git a/include/go_types.h b/include/go_types.h index 622f9c626..6ad2f6474 100644 --- a/include/go_types.h +++ b/include/go_types.h @@ -54,7 +54,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; } diff --git a/include/libbpf/bpf_tracing.h b/include/libbpf/bpf_tracing.h index d6bfbe009..46a57a02f 100644 --- a/include/libbpf/bpf_tracing.h +++ b/include/libbpf/bpf_tracing.h @@ -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 */ @@ -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 @@ -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) @@ -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]) @@ -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) diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go index 3b6c5e629..3f5c5a03d 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c index 822da38e6..3617338fa 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c @@ -132,12 +132,12 @@ int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) struct go_slice_user_ptr slice_user_ptr = {}; if (is_registers_abi) { - slice.array = (void *)ctx->rax; - slice.len = (s32)ctx->rbx; - slice.cap = (s32)ctx->rcx; - slice_user_ptr.array = &ctx->rax; - slice_user_ptr.len = &ctx->rbx; - slice_user_ptr.cap = &ctx->rcx; + slice.array = (void*) GO_PARAM1(ctx); + slice.len = (s32) GO_PARAM2(ctx); + slice.cap = (s32) GO_PARAM3(ctx); + slice_user_ptr.array = (void*) &GO_PARAM1(ctx); + slice_user_ptr.len = (void*) &GO_PARAM2(ctx); + slice_user_ptr.cap = (void*) &GO_PARAM3(ctx); } else { @@ -145,18 +145,22 @@ int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) s32 slice_len_pos = 6; s32 slice_cap_pos = 7; slice.array = get_argument(ctx, slice_pointer_pos); - slice.len = (s32)get_argument(ctx, slice_len_pos); - slice.cap = (s32)get_argument(ctx, slice_cap_pos); - slice_user_ptr.array = (void *)ctx->rsp + (slice_pointer_pos * 8); - slice_user_ptr.len = (void *)ctx->rsp + (slice_len_pos * 8); - slice_user_ptr.cap = (void *)ctx->rsp + (slice_cap_pos * 8); + slice.len = (long)get_argument(ctx, slice_len_pos); + slice.cap = (long)get_argument(ctx, slice_cap_pos); + slice_user_ptr.array = (void *)(PT_REGS_SP(ctx)+(slice_pointer_pos*8)); + slice_user_ptr.len = (void *)(PT_REGS_SP(ctx)+(slice_len_pos*8)); + slice_user_ptr.cap = (void *)(PT_REGS_SP(ctx)+(slice_cap_pos*8)); } char key[11] = "traceparent"; struct go_string key_str = write_user_go_string(key, sizeof(key)); + if (key_str.len == 0) { + bpf_printk("write failed, aborting ebpf probe"); + return 0; + } // Get grpc request struct void *context_ptr = 0; - bpf_probe_read(&context_ptr, sizeof(context_ptr), (void *)(ctx->rsp + (context_pointer_pos * 8))); + bpf_probe_read(&context_ptr, sizeof(context_ptr), (void *)(PT_REGS_SP(ctx)+(context_pointer_pos*8))); void *parent_ctx = find_context_in_map(context_ptr, &context_to_grpc_events); void *grpcReq_ptr = bpf_map_lookup_elem(&context_to_grpc_events, &parent_ctx); struct grpc_request_t grpcReq = {}; diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index 6fc2b0536..fefa540f0 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -36,7 +36,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c index ce257e61e..424b7b53f 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf/probe.bpf.c @@ -115,50 +115,7 @@ int uprobe_server_handleStream(struct pt_regs *ctx) } SEC("uprobe/server_handleStream") -int uprobe_server_handleStream_ByRegisters(struct pt_regs *ctx) -{ - void *stream_ptr = (void *)(ctx->rdi); - - // Get parent context if exists - u32 stream_id = 0; - bpf_probe_read(&stream_id, sizeof(stream_id), (void *)(stream_ptr + stream_id_pos)); - void *grpcReq_ptr = bpf_map_lookup_elem(&streamid_to_grpc_events, &stream_id); - struct grpc_request_t grpcReq = {}; - if (grpcReq_ptr != NULL) - { - bpf_probe_read(&grpcReq, sizeof(grpcReq), grpcReq_ptr); - bpf_map_delete_elem(&streamid_to_grpc_events, &stream_id); - copy_byte_arrays(grpcReq.psc.TraceID, grpcReq.sc.TraceID, TRACE_ID_SIZE); - generate_random_bytes(grpcReq.sc.SpanID, SPAN_ID_SIZE); - } - else - { - grpcReq.sc = generate_span_context(); - } - - // Set attributes - grpcReq.start_time = bpf_ktime_get_ns(); - void *method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(stream_ptr + stream_method_ptr_pos)); - u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(stream_ptr + (stream_method_ptr_pos + 8))); - u64 method_size = sizeof(grpcReq.method); - method_size = method_size < method_len ? method_size : method_len; - bpf_probe_read(&grpcReq.method, method_size, method_ptr); - - // Write event - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(stream_ptr + stream_ctx_pos)); - void *ctx_instance = 0; - bpf_probe_read(&ctx_instance, sizeof(ctx_instance), (void *)(ctx_iface + 8)); - bpf_map_update_elem(&context_to_grpc_events, &ctx_instance, &grpcReq, 0); - bpf_map_update_elem(&spans_in_progress, &ctx_instance, &grpcReq.sc, 0); - return 0; -} - -SEC("uprobe/server_handleStream") -int uprobe_server_handleStream_Returns(struct pt_regs *ctx) -{ +int uprobe_server_handleStream_Returns(struct pt_regs *ctx) { u64 stream_pos = 4; void *stream_ptr = get_argument(ctx, stream_pos); void *ctx_iface = 0; diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go index 7b4e212eb..225416d55 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 @@ -63,7 +63,7 @@ func (g *grpcServerInstrumentor) LibraryName() string { func (g *grpcServerInstrumentor) FuncNames() []string { return []string{"google.golang.org/grpc.(*Server).handleStream", - "google.golang.org/grpc/internal/transport.(*decodeState).decodeHeader"} + "google.golang.org/grpc/internal/transport.(*http2Server).operateHeaders"} } func (g *grpcServerInstrumentor) Load(ctx *context.InstrumentorContext) error { @@ -119,15 +119,8 @@ func (g *grpcServerInstrumentor) Load(ctx *context.InstrumentorContext) error { return err } - var uprobeObj *ebpf.Program - if ctx.TargetDetails.IsRegistersABI() { - uprobeObj = g.bpfObjects.UprobeServerHandleStreamByRegisters - } else { - uprobeObj = g.bpfObjects.UprobeServerHandleStream - } - - up, err := ctx.Executable.Uprobe("", uprobeObj, &link.UprobeOptions{ - Address: offset, + up, err := ctx.Executable.Uprobe("", g.bpfObjects.UprobeServerHandleStream, &link.UprobeOptions{ + Offset: offset, }) if err != nil { return err diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index d6f6cfa45..70ee01f84 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/manager.go b/pkg/instrumentors/manager.go index 956c71c26..987bd8725 100644 --- a/pkg/instrumentors/manager.go +++ b/pkg/instrumentors/manager.go @@ -28,6 +28,10 @@ import ( "github.com/open-telemetry/opentelemetry-go-instrumentation/pkg/process" ) +var ( + ErrNotAllFuncsFound = fmt.Errorf("not all functions found for instrumentation") +) + type instrumentorsManager struct { instrumentors map[string]Instrumentor done chan bool @@ -80,16 +84,17 @@ func (m *instrumentorsManager) FilterUnusedInstrumentors(target *process.TargetD } for name, inst := range m.instrumentors { - allFuncExists := true + funcsFound := 0 for _, instF := range inst.FuncNames() { - if _, exists := existingFuncMap[instF]; !exists { - allFuncExists = false - break + if _, exists := existingFuncMap[instF]; exists { + funcsFound++ } } - if !allFuncExists { - log.Logger.V(1).Info("filtering unused instrumentation", "name", name) + if funcsFound != len(inst.FuncNames()) { + if funcsFound > 0 { + log.Logger.Error(ErrNotAllFuncsFound, "some of expected functions not found - check instrumented functions", "instrumentation_name", name, "funcs_found", funcsFound, "funcs_expected", len(inst.FuncNames())) + } delete(m.instrumentors, name) } } diff --git a/pkg/process/analyze.go b/pkg/process/analyze.go index 75d263ff1..9b9e29e8c 100644 --- a/pkg/process/analyze.go +++ b/pkg/process/analyze.go @@ -16,20 +16,17 @@ package process import ( "debug/elf" - "debug/gosym" "errors" "fmt" "os" - "strings" "github.com/hashicorp/go-version" "github.com/open-telemetry/opentelemetry-go-instrumentation/pkg/log" "github.com/open-telemetry/opentelemetry-go-instrumentation/pkg/process/ptrace" - "golang.org/x/arch/x86/x86asm" ) const ( - mapSize = 15 * 1024 * 1024 + mapSize = 4096 * 6 * 1024 ) type TargetDetails struct { @@ -136,34 +133,22 @@ func (a *processAnalyzer) Analyze(pid int, relevantFuncs map[string]interface{}) EndAddr: addr + mapSize, } - var pclndat []byte - if sec := elfF.Section(".gopclntab"); sec != nil { - pclndat, err = sec.Data() - if err != nil { - return nil, err - } - } - - sec := elfF.Section(".gosymtab") - if sec == nil { - return nil, fmt.Errorf("%s section not found in target binary, make sure this is a Go application", ".gosymtab") + if err != nil { + return nil, err } - symTabRaw, err := sec.Data() - pcln := gosym.NewLineTable(pclndat, elfF.Section(".text").Addr) - symTab, err := gosym.NewTable(symTabRaw, pcln) + symbols, err := elfF.Symbols() if err != nil { return nil, err } - for _, f := range symTab.Funcs { - fName := f.Name - // fetch short path of function for vendor scene - if paths := strings.Split(fName, "/vendor/"); len(paths) > 1 { - fName = paths[1] - } + for _, f := range symbols { + if _, exists := relevantFuncs[f.Name]; exists { + offset, err := getFuncOffset(elfF, f) + if err != nil { + return nil, err + } - if _, exists := relevantFuncs[fName]; exists { - start, returns, err := a.findFuncOffset(&f, elfF) + returns, err := findFuncReturns(elfF, f, offset) if err != nil { log.Logger.V(1).Info("can't find function offset. Skipping", "function", f.Name) continue @@ -171,11 +156,11 @@ func (a *processAnalyzer) Analyze(pid int, relevantFuncs map[string]interface{}) log.Logger.V(0).Info("found relevant function for instrumentation", "function", f.Name, - "start", start, + "start", offset, "returns", returns) function := &Func{ - Name: fName, - Offset: start, + Name: f.Name, + Offset: offset, ReturnOffsets: returns, } @@ -189,44 +174,62 @@ func (a *processAnalyzer) Analyze(pid int, relevantFuncs map[string]interface{}) return result, nil } -func (a *processAnalyzer) findFuncOffset(f *gosym.Func, elfF *elf.File) (uint64, []uint64, error) { - off := f.Value - for _, prog := range elfF.Progs { - if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 { - continue +func getFuncOffset(f *elf.File, symbol elf.Symbol) (uint64, error) { + var sections []*elf.Section + + for i := range f.Sections { + if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { + sections = append(sections, f.Sections[i]) } + } - // For more info on this calculation: stackoverflow.com/a/40249502 - if prog.Vaddr <= f.Value && f.Value < (prog.Vaddr+prog.Memsz) { - off = f.Value - prog.Vaddr + prog.Off + if len(sections) == 0 { + return 0, fmt.Errorf("function %q not found in file", symbol) + } - funcLen := f.End - f.Entry - data := make([]byte, funcLen) - _, err := prog.ReadAt(data, int64(f.Value-prog.Vaddr)) - if err != nil { - log.Logger.Error(err, "error while finding function return") - return 0, nil, err - } + var execSection *elf.Section + for m := range sections { + sectionStart := sections[m].Addr + sectionEnd := sectionStart + sections[m].Size + if symbol.Value >= sectionStart && symbol.Value < sectionEnd { + execSection = sections[m] + break + } + } - var returns []uint64 - for i := 0; i < int(funcLen); { - inst, err := x86asm.Decode(data[i:], 64) - if err != nil { - log.Logger.Error(err, "error while finding function return") - return 0, nil, err - } + if execSection == nil { + return 0, errors.New("could not find symbol in executable sections of binary") + } - if inst.Op == x86asm.RET { - returns = append(returns, off+uint64(i)) - } + return uint64(symbol.Value - execSection.Addr + execSection.Offset), nil +} - i += inst.Len - } +func findFuncReturns(elfFile *elf.File, sym elf.Symbol, functionOffset uint64) ([]uint64, error) { + textSection := elfFile.Section(".text") + if textSection == nil { + return nil, errors.New("could not find .text section in binary") + } - return off, returns, nil - } + lowPC := sym.Value + highPC := lowPC + sym.Size + offset := lowPC - textSection.Addr + buf := make([]byte, int(highPC-lowPC)) + + readBytes, err := textSection.ReadAt(buf, int64(offset)) + if err != nil { + return nil, fmt.Errorf("could not read text section: %w", err) + } + data := buf[:readBytes] + instructionIndices, err := findRetInstructions(data) + if err != nil { + return nil, fmt.Errorf("error while scanning instructions: %w", err) + } + // Add the function lowPC to each index to obtain the actual locations + newLocations := make([]uint64, len(instructionIndices)) + for i, instructionIndex := range instructionIndices { + newLocations[i] = instructionIndex + functionOffset } - return 0, nil, fmt.Errorf("prog not found") + return newLocations, nil } diff --git a/pkg/process/ret_linux_amd64.go b/pkg/process/ret_linux_amd64.go new file mode 100644 index 000000000..2c730c6d1 --- /dev/null +++ b/pkg/process/ret_linux_amd64.go @@ -0,0 +1,25 @@ +package process + +import ( + "fmt" + "golang.org/x/arch/x86/x86asm" +) + +func findRetInstructions(data []byte) ([]uint64, error) { + var returnOffsets []uint64 + index := 0 + for index < len(data) { + instruction, err := x86asm.Decode(data[index:], 64) + if err != nil { + return nil, fmt.Errorf("failed to decode x64 instruction at offset %d: %w", index, err) + } + + if instruction.Op == x86asm.RET { + returnOffsets = append(returnOffsets, uint64(index)) + } + + index += instruction.Len + } + + return returnOffsets, nil +} diff --git a/pkg/process/ret_linux_arm64.go b/pkg/process/ret_linux_arm64.go new file mode 100644 index 000000000..a29a10789 --- /dev/null +++ b/pkg/process/ret_linux_arm64.go @@ -0,0 +1,25 @@ +package process + +import ( + "golang.org/x/arch/arm64/arm64asm" +) + +const ( + // In ARM64 each instruction is 4 bytes in length + armInstructionSize = 4 +) + +func findRetInstructions(data []byte) ([]uint64, error) { + var returnOffsets []uint64 + index := 0 + for index < len(data) { + instruction, err := arm64asm.Decode(data[index:]) + if err == nil && instruction.Op == arm64asm.RET { + returnOffsets = append(returnOffsets, uint64(index)) + } + + index += armInstructionSize + } + + return returnOffsets, nil +} From 7c076e861d04a1625b019064293339e6a474a5f4 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Wed, 19 Apr 2023 14:09:55 +0100 Subject: [PATCH 02/46] update net/http probe to get args from ctx instead of goroutine --- include/arguments.h | 6 ------ .../bpf/net/http/server/bpf/probe.bpf.c | 20 ++++++++++--------- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/include/arguments.h b/include/arguments.h index b66a90a87..a01ac9c68 100644 --- a/include/arguments.h +++ b/include/arguments.h @@ -63,9 +63,3 @@ void *get_argument(struct pt_regs *ctx, int index) return get_argument_by_stack(ctx, index); } - -// In x86, current goroutine is pointed by r14, according to -// https://go.googlesource.com/go/+/refs/heads/dev.regabi/src/cmd/compile/internal-abi.md#amd64-architecture -inline void *get_goroutine_address(struct pt_regs *ctx) { - return (void *)(ctx->r14); -} diff --git a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index b49802cfe..377948f56 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -82,13 +82,14 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) path_size = path_size < path_len ? path_size : path_len; bpf_probe_read(&httpReq.path, path_size, path_ptr); - // Get goroutine pointer - void *goroutine = get_goroutine_address(ctx); + // Get Request.ctx + void *ctx_iface = 0; + bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(req_ptr + ctx_ptr_pos + 8)); // Write event httpReq.sc = generate_span_context(); - bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); - long res = bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); + bpf_map_update_elem(&context_to_http_events, &ctx_iface, &httpReq, 0); + long res = bpf_map_update_elem(&spans_in_progress, &ctx_iface, &httpReq.sc, 0); return 0; } @@ -96,15 +97,16 @@ SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP_Returns(struct pt_regs *ctx) { u64 request_pos = 4; - void *req_ptr = get_argument(ctx, request_pos); - void *goroutine = get_goroutine_address(ctx); + void *req_ptr = get_argument_by_stack(ctx, request_pos); + void *ctx_iface = 0; + bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(req_ptr + ctx_ptr_pos + 8)); - void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); + void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &ctx_iface); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - bpf_map_delete_elem(&context_to_http_events, &goroutine); - bpf_map_delete_elem(&spans_in_progress, &goroutine); + bpf_map_delete_elem(&context_to_http_events, &ctx_iface); + bpf_map_delete_elem(&spans_in_progress, &ctx_iface); return 0; } \ No newline at end of file From 7ba89cde3e41a6c084edc884ca19f00a1c566376 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Wed, 19 Apr 2023 14:25:04 +0100 Subject: [PATCH 03/46] fix c file formatting --- include/alloc.h | 2 +- include/arguments.h | 4 ++-- include/go_types.h | 2 +- .../bpf/google/golang/org/grpc/bpf/probe.bpf.c | 16 ++++++++-------- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/alloc.h b/include/alloc.h index 11e1d66ca..c494ed4d1 100644 --- a/include/alloc.h +++ b/include/alloc.h @@ -52,7 +52,7 @@ static __always_inline u64 get_area_end(u64 start) { s64 partition_size = (end_addr - start_addr) / total_cpus; s32 end_index = 1; - u64* end = (u64*)bpf_map_lookup_elem(&alloc_map, &end_index); + u64 *end = (u64 *)bpf_map_lookup_elem(&alloc_map, &end_index); if (end == NULL || *end == 0) { u64 current_end_addr = start + partition_size; diff --git a/include/arguments.h b/include/arguments.h index a01ac9c68..f5fac0f92 100644 --- a/include/arguments.h +++ b/include/arguments.h @@ -49,8 +49,8 @@ void *get_argument_by_reg(struct pt_regs *ctx, int index) void *get_argument_by_stack(struct pt_regs *ctx, int index) { - void* ptr = 0; - bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx)+(index*8))); + void *ptr = 0; + bpf_probe_read(&ptr, sizeof(ptr), (void *)(PT_REGS_SP(ctx) + (index * 8))); return ptr; } diff --git a/include/go_types.h b/include/go_types.h index 6ad2f6474..477ef6f3d 100644 --- a/include/go_types.h +++ b/include/go_types.h @@ -54,7 +54,7 @@ static __always_inline struct go_string write_user_go_string(char *str, u32 len) new_string.len = len; // Copy new string struct to userspace - void* res = 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; } diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c index 3617338fa..27f555a92 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c @@ -132,12 +132,12 @@ int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) struct go_slice_user_ptr slice_user_ptr = {}; if (is_registers_abi) { - slice.array = (void*) GO_PARAM1(ctx); + slice.array = (void *)GO_PARAM1(ctx); slice.len = (s32) GO_PARAM2(ctx); slice.cap = (s32) GO_PARAM3(ctx); - slice_user_ptr.array = (void*) &GO_PARAM1(ctx); - slice_user_ptr.len = (void*) &GO_PARAM2(ctx); - slice_user_ptr.cap = (void*) &GO_PARAM3(ctx); + slice_user_ptr.array = (void *)&GO_PARAM1(ctx); + slice_user_ptr.len = (void *)&GO_PARAM2(ctx); + slice_user_ptr.cap = (void *)&GO_PARAM3(ctx); } else { @@ -147,9 +147,9 @@ int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) slice.array = get_argument(ctx, slice_pointer_pos); slice.len = (long)get_argument(ctx, slice_len_pos); slice.cap = (long)get_argument(ctx, slice_cap_pos); - slice_user_ptr.array = (void *)(PT_REGS_SP(ctx)+(slice_pointer_pos*8)); - slice_user_ptr.len = (void *)(PT_REGS_SP(ctx)+(slice_len_pos*8)); - slice_user_ptr.cap = (void *)(PT_REGS_SP(ctx)+(slice_cap_pos*8)); + slice_user_ptr.array = (void *)(PT_REGS_SP(ctx) + (slice_pointer_pos * 8)); + slice_user_ptr.len = (void *)(PT_REGS_SP(ctx) + (slice_len_pos * 8)); + slice_user_ptr.cap = (void *)(PT_REGS_SP(ctx) + (slice_cap_pos * 8)); } char key[11] = "traceparent"; struct go_string key_str = write_user_go_string(key, sizeof(key)); @@ -160,7 +160,7 @@ int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) // Get grpc request struct void *context_ptr = 0; - bpf_probe_read(&context_ptr, sizeof(context_ptr), (void *)(PT_REGS_SP(ctx)+(context_pointer_pos*8))); + bpf_probe_read(&context_ptr, sizeof(context_ptr), (void *)(PT_REGS_SP(ctx) + (context_pointer_pos * 8))); void *parent_ctx = find_context_in_map(context_ptr, &context_to_grpc_events); void *grpcReq_ptr = bpf_map_lookup_elem(&context_to_grpc_events, &parent_ctx); struct grpc_request_t grpcReq = {}; From 0e83fa516cfa93990dd991bc7a8bd23bcb1bb099 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Wed, 19 Apr 2023 14:37:13 +0100 Subject: [PATCH 04/46] more c file formatting tidy --- pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c index 27f555a92..e56880266 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf/probe.bpf.c @@ -133,8 +133,8 @@ int uprobe_Http2Client_CreateHeaderFields(struct pt_regs *ctx) if (is_registers_abi) { slice.array = (void *)GO_PARAM1(ctx); - slice.len = (s32) GO_PARAM2(ctx); - slice.cap = (s32) GO_PARAM3(ctx); + slice.len = (s32)GO_PARAM2(ctx); + slice.cap = (s32)GO_PARAM3(ctx); slice_user_ptr.array = (void *)&GO_PARAM1(ctx); slice_user_ptr.len = (void *)&GO_PARAM2(ctx); slice_user_ptr.cap = (void *)&GO_PARAM3(ctx); From ace323327788ecd89c78c17c3079410e752ba726 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Wed, 19 Apr 2023 14:38:08 +0100 Subject: [PATCH 05/46] get http header ctx pointer for net/http instrumentation --- pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c | 1 + pkg/instrumentors/bpf/net/http/server/probe.go | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 377948f56..e362732d0 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -49,6 +49,7 @@ struct volatile const u64 method_ptr_pos; volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; +volatile const u64 ctx_ptr_pos; // This instrumentation attaches uprobe to the following function: // func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index 9579c2ff0..f156949f3 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -76,6 +76,11 @@ func (h *httpServerInstrumentor) Load(ctx *context.InstrumentorContext) error { StructName: "net/http.Request", Field: "URL", }, + { + VarName: "ctx_ptr_pos", + StructName: "net/http.Request", + Field: "ctx", + }, { VarName: "path_ptr_pos", StructName: "net/url.URL", From 3786f5c11d62af152848db371e5b14cc4bd082d8 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Wed, 19 Apr 2023 20:39:50 +0100 Subject: [PATCH 06/46] switch back to goroutine --- include/arguments.h | 5 +++++ .../bpf/net/http/server/bpf/probe.bpf.c | 22 +++++++------------ 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/include/arguments.h b/include/arguments.h index f5fac0f92..5e57a1595 100644 --- a/include/arguments.h +++ b/include/arguments.h @@ -63,3 +63,8 @@ void *get_argument(struct pt_regs *ctx, int index) return get_argument_by_stack(ctx, index); } + +inline void *get_goroutine_address(struct pt_regs *ctx) +{ + return (void *)GOROUTINE(ctx); +} \ No newline at end of file diff --git a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index e362732d0..02f88b16e 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -49,7 +49,6 @@ struct volatile const u64 method_ptr_pos; volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; -volatile const u64 ctx_ptr_pos; // This instrumentation attaches uprobe to the following function: // func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) @@ -83,31 +82,26 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) path_size = path_size < path_len ? path_size : path_len; bpf_probe_read(&httpReq.path, path_size, path_ptr); - // Get Request.ctx - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(req_ptr + ctx_ptr_pos + 8)); + // Get goroutine pointer + void *goroutine = get_goroutine_address(ctx); // Write event httpReq.sc = generate_span_context(); - bpf_map_update_elem(&context_to_http_events, &ctx_iface, &httpReq, 0); - long res = bpf_map_update_elem(&spans_in_progress, &ctx_iface, &httpReq.sc, 0); + bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); + bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); return 0; } SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP_Returns(struct pt_regs *ctx) { - u64 request_pos = 4; - void *req_ptr = get_argument_by_stack(ctx, request_pos); - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(req_ptr + ctx_ptr_pos + 8)); - - void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &ctx_iface); + void *goroutine = get_goroutine_address(ctx); + void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - bpf_map_delete_elem(&context_to_http_events, &ctx_iface); - bpf_map_delete_elem(&spans_in_progress, &ctx_iface); + bpf_map_delete_elem(&context_to_http_events, &goroutine); + bpf_map_delete_elem(&spans_in_progress, &goroutine); return 0; } \ No newline at end of file From aac8000480fe2c24d4eb87d785d956f2fb841002 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 13:59:54 +0100 Subject: [PATCH 07/46] set bpf2go target as bpfel --- pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go | 2 +- pkg/instrumentors/bpf/net/http/server/probe.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go index 47f79efe2..d10126f33 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index 9feaf373d..5b85c7a96 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -36,7 +36,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go index ae4031239..85c60b1f7 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index f156949f3..3ee366acd 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 From e5f3d1067d6d8ecebb475e42c18b8ef740d267ab Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 14:10:00 +0100 Subject: [PATCH 08/46] revert bpf2go target to $TARGET --- pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go | 2 +- pkg/instrumentors/bpf/net/http/server/probe.go | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go index d10126f33..47f79efe2 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index 5b85c7a96..9feaf373d 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -36,7 +36,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go index 85c60b1f7..ae4031239 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index 3ee366acd..f156949f3 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 From e383822030f45d582fce7ddbdaf011346a393b5c Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 14:14:20 +0100 Subject: [PATCH 09/46] remove generated probe go files --- .../bpf/github.com/gorilla/mux/bpf_bpfel.go | 142 ---------------- .../bpf/google/golang/org/grpc/bpf_bpfel.go | 155 ------------------ .../golang/org/grpc/server/bpf_bpfel.go | 155 ------------------ .../bpf/net/http/server/bpf_bpfel.go | 143 ---------------- 4 files changed, 595 deletions(-) delete mode 100644 pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel.go delete mode 100644 pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel.go delete mode 100644 pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel.go delete mode 100644 pkg/instrumentors/bpf/net/http/server/bpf_bpfel.go diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel.go deleted file mode 100644 index 56b9a71ee..000000000 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel.go +++ /dev/null @@ -1,142 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64 -// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64 - -package mux - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Method [100]int8 - Path [100]int8 - Sc bpfSpanContext -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeGorillaMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP"` - UprobeGorillaMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.ContextToHttpEvents, - m.Events, - m.SpansInProgress, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeGorillaMuxServeHTTP *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP"` - UprobeGorillaMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeGorillaMuxServeHTTP, - p.UprobeGorillaMuxServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel.go deleted file mode 100644 index dd9bd7f22..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64 -// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64 - -package grpc - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfGrpcRequestT struct { - StartTime uint64 - EndTime uint64 - Method [50]int8 - Target [50]int8 - Sc bpfSpanContext - Psc bpfSpanContext - _ [4]byte -} - -type bpfHeadersBuff struct{ Buff [500]uint8 } - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeHttp2ClientCreateHeaderFields *ebpf.ProgramSpec `ebpf:"uprobe_Http2Client_CreateHeaderFields"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` - Events *ebpf.MapSpec `ebpf:"events"` - HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` - Events *ebpf.Map `ebpf:"events"` - HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.ContextToGrpcEvents, - m.Events, - m.HeadersBuffMap, - m.SpansInProgress, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` - UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` - UprobeHttp2ClientCreateHeaderFields *ebpf.Program `ebpf:"uprobe_Http2Client_CreateHeaderFields"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeClientConnInvoke, - p.UprobeClientConnInvokeReturns, - p.UprobeHttp2ClientCreateHeaderFields, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel.go deleted file mode 100644 index 839c506ff..000000000 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel.go +++ /dev/null @@ -1,155 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64 -// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64 - -package server - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfGrpcRequestT struct { - StartTime uint64 - EndTime uint64 - Method [100]int8 - Sc bpfSpanContext - Psc bpfSpanContext - _ [4]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeDecodeStateDecodeHeader *ebpf.ProgramSpec `ebpf:"uprobe_decodeState_decodeHeader"` - UprobeServerHandleStream *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream"` - UprobeServerHandleStreamByRegisters *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream_ByRegisters"` - UprobeServerHandleStreamReturns *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` - StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - AllocMap *ebpf.Map `ebpf:"alloc_map"` - ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` - StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.AllocMap, - m.ContextToGrpcEvents, - m.Events, - m.SpansInProgress, - m.StreamidToGrpcEvents, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeDecodeStateDecodeHeader *ebpf.Program `ebpf:"uprobe_decodeState_decodeHeader"` - UprobeServerHandleStream *ebpf.Program `ebpf:"uprobe_server_handleStream"` - UprobeServerHandleStreamByRegisters *ebpf.Program `ebpf:"uprobe_server_handleStream_ByRegisters"` - UprobeServerHandleStreamReturns *ebpf.Program `ebpf:"uprobe_server_handleStream_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeDecodeStateDecodeHeader, - p.UprobeServerHandleStream, - p.UprobeServerHandleStreamByRegisters, - p.UprobeServerHandleStreamReturns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel.o -var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel.go deleted file mode 100644 index 9b5d9f9af..000000000 --- a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel.go +++ /dev/null @@ -1,143 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64 -// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64 - -package server - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Method [6]int8 - Path [100]int8 - Sc bpfSpanContext - _ [6]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.ContextToHttpEvents, - m.Events, - m.SpansInProgress, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` - UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeServerMuxServeHTTP, - p.UprobeServerMuxServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel.o -var _BpfBytes []byte From 318de9f7e78801ba6cf1d7f054142bb5293b2e32 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 14:46:52 +0100 Subject: [PATCH 10/46] set TARGET in build workflow to amd64 --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bfee4c0b6..bca007f4f 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,7 +20,7 @@ jobs: sudo apt-get update && sudo apt-get install -y clang llvm libbpf-dev - name: make generate run: | - make generate + TARGET=amd64 make generate - name: verify output run: | git diff --exit-code || (echo 'generated diff, please run "make generate"' && exit 1) @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v3 - name: Build auto-instrumentation run: | - IMG=otel-go-instrumentation make docker-build + TARGET=amd64 IMG=otel-go-instrumentation make docker-build offsets: runs-on: ubuntu-latest steps: From 1c4180a40ca33e29905a556cf19dfbe3ad8f0edb Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 15:16:08 +0100 Subject: [PATCH 11/46] add default docker image name to makefile --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 7e5ecbddc..73293cc1e 100644 --- a/Makefile +++ b/Makefile @@ -19,6 +19,8 @@ $(TOOLS)/%: | $(TOOLS) GOLICENSES = $(TOOLS)/go-licenses $(TOOLS)/go-licenses: PACKAGE=github.com/google/go-licenses +IMG?=otel-go-instrumentation + .PHONY: tools tools: $(GOLICENSES) From 2e7b9a9fccbe9cb7360d4c8febb9b9ca7dc61646 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 15:21:18 +0100 Subject: [PATCH 12/46] remove TARGET and IMG env vars in build workflow --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index bca007f4f..c6246fd0c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -20,7 +20,7 @@ jobs: sudo apt-get update && sudo apt-get install -y clang llvm libbpf-dev - name: make generate run: | - TARGET=amd64 make generate + make generate - name: verify output run: | git diff --exit-code || (echo 'generated diff, please run "make generate"' && exit 1) @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v3 - name: Build auto-instrumentation run: | - TARGET=amd64 IMG=otel-go-instrumentation make docker-build + make docker-build offsets: runs-on: ubuntu-latest steps: From 1d2c1174c3135edbdad519ef4dcaa8dc665dba4f Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 15:30:08 +0100 Subject: [PATCH 13/46] set TARGETARCH in build workflow --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c6246fd0c..deb3610ef 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v3 - name: Build auto-instrumentation run: | - make docker-build + TARGETARCH=amd64 make docker-build offsets: runs-on: ubuntu-latest steps: From ad676be092378e0f0188d1b59ac76747e171d521 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 16:29:15 +0100 Subject: [PATCH 14/46] tidy up build workflow --- .github/workflows/build.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index deb3610ef..c6246fd0c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -31,7 +31,7 @@ jobs: uses: actions/checkout@v3 - name: Build auto-instrumentation run: | - TARGETARCH=amd64 make docker-build + make docker-build offsets: runs-on: ubuntu-latest steps: From 6777738be597a7b7cc56c049f945bcb244c37201 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Mon, 24 Apr 2023 18:02:51 +0100 Subject: [PATCH 15/46] update go generate to use set targets directly --- Dockerfile | 3 ++- pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go | 2 +- pkg/instrumentors/bpf/net/http/server/probe.go | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 03cd546b0..27af4453d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,12 @@ FROM fedora:38 as builder ARG TARGETARCH +RUN echo "arch: $TARGETARCH" RUN dnf install clang llvm make libbpf-devel -y RUN curl -LO https://go.dev/dl/go1.20.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 TARGET=$TARGETARCH make build +RUN make build FROM registry.fedoraproject.org/fedora-minimal:38 COPY --from=builder /app/otel-go-instrumentation / diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go index 47f79efe2..63563d05d 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index 9feaf373d..fd846ae11 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -36,7 +36,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go index ae4031239..4d117b926 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index f156949f3..d9210844f 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 From 3f9010067b1773395cec2ec1ae4ce7ff093b7dd6 Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Mon, 24 Apr 2023 15:22:45 -0400 Subject: [PATCH 16/46] add qemu --- .github/workflows/build.yaml | 5 +++++ Dockerfile | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index c6246fd0c..de37be306 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,6 +29,11 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v3 + - + # Add support for more platforms with QEMU (optional) + # https://github.com/docker/setup-qemu-action + name: Set up QEMU + uses: docker/setup-qemu-action@v2 - name: Build auto-instrumentation run: | make docker-build diff --git a/Dockerfile b/Dockerfile index 27af4453d..27556185a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM fedora:38 as builder ARG TARGETARCH RUN echo "arch: $TARGETARCH" RUN dnf install clang llvm make libbpf-devel -y -RUN curl -LO https://go.dev/dl/go1.20.linux-$TARGETARCH.tar.gz && tar -C /usr/local -xzf go*.linux-$TARGETARCH.tar.gz +RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}.tar.gz && tar -C /usr/local -xzf go*.linux-$TARGETARCH.tar.gz ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /app COPY . . From 37ecf3cd8f10dcad0f2b704e2670a1d0f2e9e9d4 Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Mon, 24 Apr 2023 15:40:25 -0400 Subject: [PATCH 17/46] lets see what happens with buildarch --- Dockerfile | 6 +++--- Makefile | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 27556185a..d421126a9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM fedora:38 as builder -ARG TARGETARCH -RUN echo "arch: $TARGETARCH" +ARG BUILDARCH +RUN echo "arch: $BUILDARCH" RUN dnf install clang llvm make libbpf-devel -y -RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}.tar.gz && tar -C /usr/local -xzf go*.linux-$TARGETARCH.tar.gz +RUN curl -LO https://go.dev/dl/go1.20.linux-${BUILDARCH}.tar.gz && tar -C /usr/local -xzf go*.linux-${BUILDARCH}.tar.gz ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /app COPY . . diff --git a/Makefile b/Makefile index 73293cc1e..c4695e2b6 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ build: generate .PHONY: docker-build docker-build: - docker build -t $(IMG) . + docker build --no-cache -t $(IMG) . .PHONY: offsets offsets: From 3f7f1b1a8c0a203eb2e12f8d06088977443f6ada Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Mon, 24 Apr 2023 15:50:46 -0400 Subject: [PATCH 18/46] try buildx --- .github/workflows/build.yaml | 8 ++++---- Dockerfile | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index de37be306..93742e5af 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -30,10 +30,10 @@ jobs: - name: Checkout Repo uses: actions/checkout@v3 - - # Add support for more platforms with QEMU (optional) - # https://github.com/docker/setup-qemu-action - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + with: + platforms: linux/amd64,linux/arm64 - name: Build auto-instrumentation run: | make docker-build diff --git a/Dockerfile b/Dockerfile index d421126a9..6bf78f82b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ FROM fedora:38 as builder -ARG BUILDARCH -RUN echo "arch: $BUILDARCH" +ARG TARGETARCH +RUN echo "arch: $TARGETARCH" RUN dnf install clang llvm make libbpf-devel -y -RUN curl -LO https://go.dev/dl/go1.20.linux-${BUILDARCH}.tar.gz && tar -C /usr/local -xzf go*.linux-${BUILDARCH}.tar.gz +RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}}.tar.gz && tar -C /usr/local -xzf go*.linux-${TARGETARCH}.tar.gz ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /app COPY . . From fd741f1d4fa7f2622c12e51a66be9d4b703edd7f Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Mon, 24 Apr 2023 15:53:35 -0400 Subject: [PATCH 19/46] try buildx --- Dockerfile | 2 +- Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6bf78f82b..05980c380 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM fedora:38 as builder ARG TARGETARCH RUN echo "arch: $TARGETARCH" RUN dnf install clang llvm make libbpf-devel -y -RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}}.tar.gz && tar -C /usr/local -xzf go*.linux-${TARGETARCH}.tar.gz +RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}.tar.gz && tar -C /usr/local -xzf go*.linux-${TARGETARCH}.tar.gz ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /app COPY . . diff --git a/Makefile b/Makefile index c4695e2b6..23891a22c 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ build: generate .PHONY: docker-build docker-build: - docker build --no-cache -t $(IMG) . + docker buildx build --no-cache -t $(IMG) . .PHONY: offsets offsets: From a538ef0f1d5d19a2d9db830cea021fd0370dcd6d Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Mon, 24 Apr 2023 15:56:44 -0400 Subject: [PATCH 20/46] testing if we need buildx setup step --- .github/workflows/build.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 93742e5af..c6246fd0c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -29,11 +29,6 @@ jobs: steps: - name: Checkout Repo uses: actions/checkout@v3 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 - with: - platforms: linux/amd64,linux/arm64 - name: Build auto-instrumentation run: | make docker-build From 068af9b81efeefbf30f19c8acc3bd0e1d0f18bed Mon Sep 17 00:00:00 2001 From: Purvi Kanal Date: Mon, 24 Apr 2023 16:07:15 -0400 Subject: [PATCH 21/46] remove --no-cache option --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 23891a22c..795bbf32b 100644 --- a/Makefile +++ b/Makefile @@ -36,7 +36,7 @@ build: generate .PHONY: docker-build docker-build: - docker buildx build --no-cache -t $(IMG) . + docker buildx build -t $(IMG) . .PHONY: offsets offsets: From 58df81b4fc43c382326b6d33b43e079938d57c12 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 11:45:58 +0100 Subject: [PATCH 22/46] switch back to specific eBPF arch targets --- Dockerfile | 2 +- pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/probe.go | 2 +- pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go | 2 +- pkg/instrumentors/bpf/net/http/server/probe.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 05980c380..01d4d8582 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,7 +6,7 @@ RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}.tar.gz && tar -C /usr/ ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /app COPY . . -RUN make build +RUN TARGET=${TARGETARCH} make build FROM registry.fedoraproject.org/fedora-minimal:38 COPY --from=builder /app/otel-go-instrumentation / diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go index 63563d05d..47f79efe2 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index fd846ae11..9feaf373d 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -36,7 +36,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go index 4d117b926..ae4031239 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type GrpcEvent struct { StartTime uint64 diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index d9210844f..f156949f3 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c type HttpEvent struct { StartTime uint64 From 926fdb7ed60363d96c8b234cd517075bd646da15 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:21:36 +0100 Subject: [PATCH 23/46] tidy up docker/make files --- Dockerfile | 1 - Makefile | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 01d4d8582..d2733c999 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,5 @@ FROM fedora:38 as builder ARG TARGETARCH -RUN echo "arch: $TARGETARCH" RUN dnf install clang llvm make libbpf-devel -y RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}.tar.gz && tar -C /usr/local -xzf go*.linux-${TARGETARCH}.tar.gz ENV PATH="/usr/local/go/bin:${PATH}" diff --git a/Makefile b/Makefile index 795bbf32b..03e76bd67 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ $(TOOLS)/%: | $(TOOLS) GOLICENSES = $(TOOLS)/go-licenses $(TOOLS)/go-licenses: PACKAGE=github.com/google/go-licenses -IMG?=otel-go-instrumentation +IMG_NAME ?= otel-go-instrumentation:local .PHONY: tools tools: $(GOLICENSES) @@ -36,7 +36,7 @@ build: generate .PHONY: docker-build docker-build: - docker buildx build -t $(IMG) . + docker build -t $(IMG_NAME) . .PHONY: offsets offsets: @@ -70,7 +70,7 @@ fixture-nethttp: fixtures/nethttp fixture-gorillamux: fixtures/gorillamux fixtures/%: LIBRARY=$* fixtures/%: - IMG=otel-go-instrumentation $(MAKE) docker-build + $(MAKE) docker-build cd test/e2e/$(LIBRARY) && docker build -t sample-app . kind create cluster kind load docker-image otel-go-instrumentation sample-app From 63bba9eb53849bb960ccd8c0602d7cf4b6b8ddf7 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:25:00 +0100 Subject: [PATCH 24/46] set default target as amd64 --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 03e76bd67..783e0ef42 100644 --- a/Makefile +++ b/Makefile @@ -20,6 +20,7 @@ GOLICENSES = $(TOOLS)/go-licenses $(TOOLS)/go-licenses: PACKAGE=github.com/google/go-licenses IMG_NAME ?= otel-go-instrumentation:local +TARGET ?= amd64 .PHONY: tools tools: $(GOLICENSES) @@ -28,7 +29,7 @@ tools: $(GOLICENSES) generate: export CFLAGS := $(BPF_INCLUDE) generate: go mod tidy - go generate ./... + TARGET=$(TARGET) go generate ./... .PHONY: build build: generate From a5956d245fcc3e74771333a3b5217642971dfc12 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:30:19 +0100 Subject: [PATCH 25/46] readd buildx --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 783e0ef42..b06b69c77 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ build: generate .PHONY: docker-build docker-build: - docker build -t $(IMG_NAME) . + docker buildx -t $(IMG_NAME) . .PHONY: offsets offsets: From e22a0a5e340aa7692330133aacbb7f00fbd0f0dd Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:31:25 +0100 Subject: [PATCH 26/46] fix buildx arg --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b06b69c77..f3c8675cb 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ build: generate .PHONY: docker-build docker-build: - docker buildx -t $(IMG_NAME) . + docker buildx build -t $(IMG_NAME) . .PHONY: offsets offsets: From 0d83da20c6051dccd1a822c7482aa5a3f9a05613 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:42:45 +0100 Subject: [PATCH 27/46] fix image name --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f3c8675cb..c43640314 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ $(TOOLS)/%: | $(TOOLS) GOLICENSES = $(TOOLS)/go-licenses $(TOOLS)/go-licenses: PACKAGE=github.com/google/go-licenses -IMG_NAME ?= otel-go-instrumentation:local +IMG_NAME ?= otel-go-instrumentation TARGET ?= amd64 .PHONY: tools From 2ef3b6ebe8b02133494cde124c14002e8266a552 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:51:36 +0100 Subject: [PATCH 28/46] wait for longer for e2e pods --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c43640314..5e12e8b4f 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ fixtures/%: helm install test -f .github/workflows/e2e/k8s/collector-helm-values.yml opentelemetry-helm-charts/charts/opentelemetry-collector kubectl wait --for=condition=Ready --timeout=60s pod/test-opentelemetry-collector-0 kubectl -n default create -f .github/workflows/e2e/k8s/sample-job.yml - kubectl wait --for=condition=Complete --timeout=60s job/sample-job + kubectl wait --for=condition=Complete --timeout=90s job/sample-job kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces.json.tmp jq 'del(.resourceSpans[].scopeSpans[].spans[].endTimeUnixNano, .resourceSpans[].scopeSpans[].spans[].startTimeUnixNano) | .resourceSpans[].scopeSpans[].spans[].spanId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans[].spans[].traceId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans|=sort_by(.scope.name)' ./test/e2e/$(LIBRARY)/traces.json.tmp | jq --sort-keys . > ./test/e2e/$(LIBRARY)/traces.json rm ./test/e2e/$(LIBRARY)/traces.json.tmp From 121b6df7a3104dfe1d2d53a056cda610e819d8cf Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 12:55:15 +0100 Subject: [PATCH 29/46] Revert "wait for longer for e2e pods" This reverts commit 2ef3b6ebe8b02133494cde124c14002e8266a552. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5e12e8b4f..c43640314 100644 --- a/Makefile +++ b/Makefile @@ -82,7 +82,7 @@ fixtures/%: helm install test -f .github/workflows/e2e/k8s/collector-helm-values.yml opentelemetry-helm-charts/charts/opentelemetry-collector kubectl wait --for=condition=Ready --timeout=60s pod/test-opentelemetry-collector-0 kubectl -n default create -f .github/workflows/e2e/k8s/sample-job.yml - kubectl wait --for=condition=Complete --timeout=90s job/sample-job + kubectl wait --for=condition=Complete --timeout=60s job/sample-job kubectl cp -c filecp default/test-opentelemetry-collector-0:tmp/trace.json ./test/e2e/$(LIBRARY)/traces.json.tmp jq 'del(.resourceSpans[].scopeSpans[].spans[].endTimeUnixNano, .resourceSpans[].scopeSpans[].spans[].startTimeUnixNano) | .resourceSpans[].scopeSpans[].spans[].spanId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans[].spans[].traceId|= (if . != "" then "xxxxx" else . end) | .resourceSpans[].scopeSpans|=sort_by(.scope.name)' ./test/e2e/$(LIBRARY)/traces.json.tmp | jq --sort-keys . > ./test/e2e/$(LIBRARY)/traces.json rm ./test/e2e/$(LIBRARY)/traces.json.tmp From 5d5821668d93d4f28d025501daa591a24ce5acca Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 14:44:34 +0100 Subject: [PATCH 30/46] apply fix for instrumenting stripped binaries ported from: https://github.com/keyval-dev/opentelemetry-go-instrumentation/pull/56 --- pkg/process/analyze.go | 100 ++++---------------------- pkg/process/funcs_nonstripped.go | 116 +++++++++++++++++++++++++++++++ pkg/process/funcs_stripped.go | 104 +++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 87 deletions(-) create mode 100644 pkg/process/funcs_nonstripped.go create mode 100644 pkg/process/funcs_stripped.go diff --git a/pkg/process/analyze.go b/pkg/process/analyze.go index 51509da08..283bb9ed9 100644 --- a/pkg/process/analyze.go +++ b/pkg/process/analyze.go @@ -136,100 +136,26 @@ func (a *processAnalyzer) Analyze(pid int, relevantFuncs map[string]interface{}) if err != nil { return nil, err } - symbols, err := elfF.Symbols() + + funcs, err := findFunctions(elfF, relevantFuncs) if err != nil { + log.Logger.Error(err, "Failed to find functions") return nil, err } - for _, f := range symbols { - if _, exists := relevantFuncs[f.Name]; exists { - offset, err := getFuncOffset(elfF, f) - if err != nil { - return nil, err - } - - returns, err := findFuncReturns(elfF, f, offset) - if err != nil { - log.Logger.V(1).Info("can't find function offset. Skipping", "function", f.Name) - continue - } - - log.Logger.V(0).Info("found relevant function for instrumentation", - "function", f.Name, - "start", offset, - "returns", returns) - function := &Func{ - Name: f.Name, - Offset: offset, - ReturnOffsets: returns, - } - - result.Functions = append(result.Functions, function) - } - } - if len(result.Functions) == 0 { - return nil, errors.New("could not find function offsets for instrumenter") - } - + result.Functions = funcs return result, nil } -func getFuncOffset(f *elf.File, symbol elf.Symbol) (uint64, error) { - var sections []*elf.Section - - for i := range f.Sections { - if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { - sections = append(sections, f.Sections[i]) - } - } - - if len(sections) == 0 { - return 0, fmt.Errorf("function %q not found in file", symbol) - } - - var execSection *elf.Section - for m := range sections { - sectionStart := sections[m].Addr - sectionEnd := sectionStart + sections[m].Size - if symbol.Value >= sectionStart && symbol.Value < sectionEnd { - execSection = sections[m] - break - } - } - - if execSection == nil { - return 0, errors.New("could not find symbol in executable sections of binary") - } - - return uint64(symbol.Value - execSection.Addr + execSection.Offset), nil -} - -func findFuncReturns(elfFile *elf.File, sym elf.Symbol, functionOffset uint64) ([]uint64, error) { - textSection := elfFile.Section(".text") - if textSection == nil { - return nil, errors.New("could not find .text section in binary") - } - - lowPC := sym.Value - highPC := lowPC + sym.Size - offset := lowPC - textSection.Addr - buf := make([]byte, int(highPC-lowPC)) - - readBytes, err := textSection.ReadAt(buf, int64(offset)) - if err != nil { - return nil, fmt.Errorf("could not read text section: %w", err) - } - data := buf[:readBytes] - instructionIndices, err := findRetInstructions(data) +func findFunctions(elfF *elf.File, relevantFuncs map[string]interface{}) ([]*Func, error) { + result, err := FindFunctionsUnStripped(elfF, relevantFuncs) if err != nil { - return nil, fmt.Errorf("error while scanning instructions: %w", err) - } - - // Add the function lowPC to each index to obtain the actual locations - newLocations := make([]uint64, len(instructionIndices)) - for i, instructionIndex := range instructionIndices { - newLocations[i] = instructionIndex + functionOffset + if errors.Is(err, elf.ErrNoSymbols) { + log.Logger.V(0).Info("No symbols found in binary, trying to find functions using .gosymtab") + return FindFunctionsStripped(elfF, relevantFuncs) + } + return nil, err } - return newLocations, nil -} + return result, nil +} \ No newline at end of file diff --git a/pkg/process/funcs_nonstripped.go b/pkg/process/funcs_nonstripped.go new file mode 100644 index 000000000..d28bdd38b --- /dev/null +++ b/pkg/process/funcs_nonstripped.go @@ -0,0 +1,116 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package process + +import ( + "debug/elf" + "errors" + "fmt" + + "go.opentelemetry.io/auto/pkg/log" +) + +func FindFunctionsUnStripped(elfF *elf.File, relevantFuncs map[string]interface{}) ([]*Func, error) { + symbols, err := elfF.Symbols() + if err != nil { + return nil, err + } + + var result []*Func + for _, f := range symbols { + if _, exists := relevantFuncs[f.Name]; exists { + offset, err := getFuncOffsetUnstripped(elfF, f) + if err != nil { + return nil, err + } + + returns, err := findFuncReturnsUnstripped(elfF, f, offset) + if err != nil { + return nil, err + } + + log.Logger.V(0).Info("found relevant function for instrumentation", "function", f.Name, "returns", len(returns)) + function := &Func{ + Name: f.Name, + Offset: offset, + ReturnOffsets: returns, + } + + result = append(result, function) + } + } + + return result, nil +} + +func getFuncOffsetUnstripped(f *elf.File, symbol elf.Symbol) (uint64, error) { + var sections []*elf.Section + + for i := range f.Sections { + if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { + sections = append(sections, f.Sections[i]) + } + } + + if len(sections) == 0 { + return 0, fmt.Errorf("function %q not found in file", symbol) + } + + var execSection *elf.Section + for m := range sections { + sectionStart := sections[m].Addr + sectionEnd := sectionStart + sections[m].Size + if symbol.Value >= sectionStart && symbol.Value < sectionEnd { + execSection = sections[m] + break + } + } + + if execSection == nil { + return 0, errors.New("could not find symbol in executable sections of binary") + } + + return uint64(symbol.Value - execSection.Addr + execSection.Offset), nil +} + +func findFuncReturnsUnstripped(elfFile *elf.File, sym elf.Symbol, functionOffset uint64) ([]uint64, error) { + textSection := elfFile.Section(".text") + if textSection == nil { + return nil, errors.New("could not find .text section in binary") + } + + lowPC := sym.Value + highPC := lowPC + sym.Size + offset := lowPC - textSection.Addr + buf := make([]byte, int(highPC-lowPC)) + + readBytes, err := textSection.ReadAt(buf, int64(offset)) + if err != nil { + return nil, fmt.Errorf("could not read text section: %w", err) + } + data := buf[:readBytes] + instructionIndices, err := findRetInstructions(data) + if err != nil { + return nil, fmt.Errorf("error while scanning instructions: %w", err) + } + + // Add the function lowPC to each index to obtain the actual locations + newLocations := make([]uint64, len(instructionIndices)) + for i, instructionIndex := range instructionIndices { + newLocations[i] = instructionIndex + functionOffset + } + + return newLocations, nil +} \ No newline at end of file diff --git a/pkg/process/funcs_stripped.go b/pkg/process/funcs_stripped.go new file mode 100644 index 000000000..dfaf65018 --- /dev/null +++ b/pkg/process/funcs_stripped.go @@ -0,0 +1,104 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package process + +import ( + "debug/elf" + "debug/gosym" + "fmt" + + "go.opentelemetry.io/auto/pkg/log" +) + +func FindFunctionsStripped(elfF *elf.File, relevantFuncs map[string]interface{}) ([]*Func, error) { + var pclndat []byte + if sec := elfF.Section(".gopclntab"); sec != nil { + var err error + pclndat, err = sec.Data() + if err != nil { + return nil, err + } + } + + sec := elfF.Section(".gosymtab") + if sec == nil { + return nil, fmt.Errorf("%s section not found in target binary, make sure this is a Go application", ".gosymtab") + } + symTabRaw, err := sec.Data() + pcln := gosym.NewLineTable(pclndat, elfF.Section(".text").Addr) + symTab, err := gosym.NewTable(symTabRaw, pcln) + if err != nil { + return nil, err + } + + var result []*Func + for _, f := range symTab.Funcs { + if _, exists := relevantFuncs[f.Name]; exists { + start, returns, err := findFuncOffsetStripped(&f, elfF) + if err != nil { + return nil, err + } + + log.Logger.V(0).Info("found relevant function for instrumentation", "function", f.Name, "returns", len(returns)) + function := &Func{ + Name: f.Name, + Offset: start, + ReturnOffsets: returns, + } + + result = append(result, function) + } + } + + return result, nil +} + +func findFuncOffsetStripped(f *gosym.Func, elfF *elf.File) (uint64, []uint64, error) { + off := f.Value + for _, prog := range elfF.Progs { + if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 { + continue + } + + // For more info on this calculation: stackoverflow.com/a/40249502 + if prog.Vaddr <= f.Value && f.Value < (prog.Vaddr+prog.Memsz) { + off = f.Value - prog.Vaddr + prog.Off + + funcLen := f.End - f.Entry + data := make([]byte, funcLen) + _, err := prog.ReadAt(data, int64(f.Value-prog.Vaddr)) + if err != nil { + log.Logger.Error(err, "error while finding function return") + return 0, nil, err + } + + instructionIndices, err := findRetInstructions(data) + if err != nil { + log.Logger.Error(err, "error while finding function returns") + return 0, nil, err + } + + newLocations := make([]uint64, len(instructionIndices)) + for i, instructionIndex := range instructionIndices { + newLocations[i] = instructionIndex + off + } + + return off, newLocations, nil + } + + } + + return 0, nil, fmt.Errorf("prog not found") +} \ No newline at end of file From 11af7d21d2a84061ea58d6b2eb4f8f27ef2217ce Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 25 Apr 2023 16:36:46 +0100 Subject: [PATCH 31/46] Revert "apply fix for instrumenting stripped binaries" This reverts commit 5d5821668d93d4f28d025501daa591a24ce5acca. --- pkg/process/analyze.go | 100 ++++++++++++++++++++++---- pkg/process/funcs_nonstripped.go | 116 ------------------------------- pkg/process/funcs_stripped.go | 104 --------------------------- 3 files changed, 87 insertions(+), 233 deletions(-) delete mode 100644 pkg/process/funcs_nonstripped.go delete mode 100644 pkg/process/funcs_stripped.go diff --git a/pkg/process/analyze.go b/pkg/process/analyze.go index 283bb9ed9..51509da08 100644 --- a/pkg/process/analyze.go +++ b/pkg/process/analyze.go @@ -136,26 +136,100 @@ func (a *processAnalyzer) Analyze(pid int, relevantFuncs map[string]interface{}) if err != nil { return nil, err } - - funcs, err := findFunctions(elfF, relevantFuncs) + symbols, err := elfF.Symbols() if err != nil { - log.Logger.Error(err, "Failed to find functions") return nil, err } - result.Functions = funcs + for _, f := range symbols { + if _, exists := relevantFuncs[f.Name]; exists { + offset, err := getFuncOffset(elfF, f) + if err != nil { + return nil, err + } + + returns, err := findFuncReturns(elfF, f, offset) + if err != nil { + log.Logger.V(1).Info("can't find function offset. Skipping", "function", f.Name) + continue + } + + log.Logger.V(0).Info("found relevant function for instrumentation", + "function", f.Name, + "start", offset, + "returns", returns) + function := &Func{ + Name: f.Name, + Offset: offset, + ReturnOffsets: returns, + } + + result.Functions = append(result.Functions, function) + } + } + if len(result.Functions) == 0 { + return nil, errors.New("could not find function offsets for instrumenter") + } + return result, nil } -func findFunctions(elfF *elf.File, relevantFuncs map[string]interface{}) ([]*Func, error) { - result, err := FindFunctionsUnStripped(elfF, relevantFuncs) - if err != nil { - if errors.Is(err, elf.ErrNoSymbols) { - log.Logger.V(0).Info("No symbols found in binary, trying to find functions using .gosymtab") - return FindFunctionsStripped(elfF, relevantFuncs) +func getFuncOffset(f *elf.File, symbol elf.Symbol) (uint64, error) { + var sections []*elf.Section + + for i := range f.Sections { + if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { + sections = append(sections, f.Sections[i]) } - return nil, err } - return result, nil -} \ No newline at end of file + if len(sections) == 0 { + return 0, fmt.Errorf("function %q not found in file", symbol) + } + + var execSection *elf.Section + for m := range sections { + sectionStart := sections[m].Addr + sectionEnd := sectionStart + sections[m].Size + if symbol.Value >= sectionStart && symbol.Value < sectionEnd { + execSection = sections[m] + break + } + } + + if execSection == nil { + return 0, errors.New("could not find symbol in executable sections of binary") + } + + return uint64(symbol.Value - execSection.Addr + execSection.Offset), nil +} + +func findFuncReturns(elfFile *elf.File, sym elf.Symbol, functionOffset uint64) ([]uint64, error) { + textSection := elfFile.Section(".text") + if textSection == nil { + return nil, errors.New("could not find .text section in binary") + } + + lowPC := sym.Value + highPC := lowPC + sym.Size + offset := lowPC - textSection.Addr + buf := make([]byte, int(highPC-lowPC)) + + readBytes, err := textSection.ReadAt(buf, int64(offset)) + if err != nil { + return nil, fmt.Errorf("could not read text section: %w", err) + } + data := buf[:readBytes] + instructionIndices, err := findRetInstructions(data) + if err != nil { + return nil, fmt.Errorf("error while scanning instructions: %w", err) + } + + // Add the function lowPC to each index to obtain the actual locations + newLocations := make([]uint64, len(instructionIndices)) + for i, instructionIndex := range instructionIndices { + newLocations[i] = instructionIndex + functionOffset + } + + return newLocations, nil +} diff --git a/pkg/process/funcs_nonstripped.go b/pkg/process/funcs_nonstripped.go deleted file mode 100644 index d28bdd38b..000000000 --- a/pkg/process/funcs_nonstripped.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package process - -import ( - "debug/elf" - "errors" - "fmt" - - "go.opentelemetry.io/auto/pkg/log" -) - -func FindFunctionsUnStripped(elfF *elf.File, relevantFuncs map[string]interface{}) ([]*Func, error) { - symbols, err := elfF.Symbols() - if err != nil { - return nil, err - } - - var result []*Func - for _, f := range symbols { - if _, exists := relevantFuncs[f.Name]; exists { - offset, err := getFuncOffsetUnstripped(elfF, f) - if err != nil { - return nil, err - } - - returns, err := findFuncReturnsUnstripped(elfF, f, offset) - if err != nil { - return nil, err - } - - log.Logger.V(0).Info("found relevant function for instrumentation", "function", f.Name, "returns", len(returns)) - function := &Func{ - Name: f.Name, - Offset: offset, - ReturnOffsets: returns, - } - - result = append(result, function) - } - } - - return result, nil -} - -func getFuncOffsetUnstripped(f *elf.File, symbol elf.Symbol) (uint64, error) { - var sections []*elf.Section - - for i := range f.Sections { - if f.Sections[i].Flags == elf.SHF_ALLOC+elf.SHF_EXECINSTR { - sections = append(sections, f.Sections[i]) - } - } - - if len(sections) == 0 { - return 0, fmt.Errorf("function %q not found in file", symbol) - } - - var execSection *elf.Section - for m := range sections { - sectionStart := sections[m].Addr - sectionEnd := sectionStart + sections[m].Size - if symbol.Value >= sectionStart && symbol.Value < sectionEnd { - execSection = sections[m] - break - } - } - - if execSection == nil { - return 0, errors.New("could not find symbol in executable sections of binary") - } - - return uint64(symbol.Value - execSection.Addr + execSection.Offset), nil -} - -func findFuncReturnsUnstripped(elfFile *elf.File, sym elf.Symbol, functionOffset uint64) ([]uint64, error) { - textSection := elfFile.Section(".text") - if textSection == nil { - return nil, errors.New("could not find .text section in binary") - } - - lowPC := sym.Value - highPC := lowPC + sym.Size - offset := lowPC - textSection.Addr - buf := make([]byte, int(highPC-lowPC)) - - readBytes, err := textSection.ReadAt(buf, int64(offset)) - if err != nil { - return nil, fmt.Errorf("could not read text section: %w", err) - } - data := buf[:readBytes] - instructionIndices, err := findRetInstructions(data) - if err != nil { - return nil, fmt.Errorf("error while scanning instructions: %w", err) - } - - // Add the function lowPC to each index to obtain the actual locations - newLocations := make([]uint64, len(instructionIndices)) - for i, instructionIndex := range instructionIndices { - newLocations[i] = instructionIndex + functionOffset - } - - return newLocations, nil -} \ No newline at end of file diff --git a/pkg/process/funcs_stripped.go b/pkg/process/funcs_stripped.go deleted file mode 100644 index dfaf65018..000000000 --- a/pkg/process/funcs_stripped.go +++ /dev/null @@ -1,104 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package process - -import ( - "debug/elf" - "debug/gosym" - "fmt" - - "go.opentelemetry.io/auto/pkg/log" -) - -func FindFunctionsStripped(elfF *elf.File, relevantFuncs map[string]interface{}) ([]*Func, error) { - var pclndat []byte - if sec := elfF.Section(".gopclntab"); sec != nil { - var err error - pclndat, err = sec.Data() - if err != nil { - return nil, err - } - } - - sec := elfF.Section(".gosymtab") - if sec == nil { - return nil, fmt.Errorf("%s section not found in target binary, make sure this is a Go application", ".gosymtab") - } - symTabRaw, err := sec.Data() - pcln := gosym.NewLineTable(pclndat, elfF.Section(".text").Addr) - symTab, err := gosym.NewTable(symTabRaw, pcln) - if err != nil { - return nil, err - } - - var result []*Func - for _, f := range symTab.Funcs { - if _, exists := relevantFuncs[f.Name]; exists { - start, returns, err := findFuncOffsetStripped(&f, elfF) - if err != nil { - return nil, err - } - - log.Logger.V(0).Info("found relevant function for instrumentation", "function", f.Name, "returns", len(returns)) - function := &Func{ - Name: f.Name, - Offset: start, - ReturnOffsets: returns, - } - - result = append(result, function) - } - } - - return result, nil -} - -func findFuncOffsetStripped(f *gosym.Func, elfF *elf.File) (uint64, []uint64, error) { - off := f.Value - for _, prog := range elfF.Progs { - if prog.Type != elf.PT_LOAD || (prog.Flags&elf.PF_X) == 0 { - continue - } - - // For more info on this calculation: stackoverflow.com/a/40249502 - if prog.Vaddr <= f.Value && f.Value < (prog.Vaddr+prog.Memsz) { - off = f.Value - prog.Vaddr + prog.Off - - funcLen := f.End - f.Entry - data := make([]byte, funcLen) - _, err := prog.ReadAt(data, int64(f.Value-prog.Vaddr)) - if err != nil { - log.Logger.Error(err, "error while finding function return") - return 0, nil, err - } - - instructionIndices, err := findRetInstructions(data) - if err != nil { - log.Logger.Error(err, "error while finding function returns") - return 0, nil, err - } - - newLocations := make([]uint64, len(instructionIndices)) - for i, instructionIndex := range instructionIndices { - newLocations[i] = instructionIndex + off - } - - return off, newLocations, nil - } - - } - - return 0, nil, fmt.Errorf("prog not found") -} \ No newline at end of file From 9b358df0b07ba2c54543ab7cdcca3d5fd40ca25d Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 15:29:53 +0100 Subject: [PATCH 32/46] use $TARGET for gin bpf2cmd --- pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go index 347190ff9..97f7b68ab 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go @@ -35,7 +35,7 @@ import ( "golang.org/x/sys/unix" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target bpfel -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c // Event represents an event in the gin-gonic/gin server during an HTTP // request-response. From ef84926551fd04fb38ca861a2f8a2501c25f3ada Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 15:48:17 +0100 Subject: [PATCH 33/46] update ptrace_linux_arm --- .../bpf/github.com/gin-gonic/gin/bpf_bpfel.go | 143 ------------------ pkg/process/ptrace/ptrace_linux_arm64.go | 4 +- 2 files changed, 2 insertions(+), 145 deletions(-) delete mode 100644 pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel.go diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel.go deleted file mode 100644 index 2a54a5515..000000000 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel.go +++ /dev/null @@ -1,143 +0,0 @@ -// Code generated by bpf2go; DO NOT EDIT. -//go:build 386 || amd64 || amd64p32 || arm || arm64 || mips64le || mips64p32le || mipsle || ppc64le || riscv64 -// +build 386 amd64 amd64p32 arm arm64 mips64le mips64p32le mipsle ppc64le riscv64 - -package gin - -import ( - "bytes" - _ "embed" - "fmt" - "io" - - "github.com/cilium/ebpf" -) - -type bpfHttpRequestT struct { - StartTime uint64 - EndTime uint64 - Method [6]int8 - Path [100]int8 - Sc bpfSpanContext - _ [6]byte -} - -type bpfSpanContext struct { - TraceID [16]uint8 - SpanID [8]uint8 -} - -// loadBpf returns the embedded CollectionSpec for bpf. -func loadBpf() (*ebpf.CollectionSpec, error) { - reader := bytes.NewReader(_BpfBytes) - spec, err := ebpf.LoadCollectionSpecFromReader(reader) - if err != nil { - return nil, fmt.Errorf("can't load bpf: %w", err) - } - - return spec, err -} - -// loadBpfObjects loads bpf and converts it into a struct. -// -// The following types are suitable as obj argument: -// -// *bpfObjects -// *bpfPrograms -// *bpfMaps -// -// See ebpf.CollectionSpec.LoadAndAssign documentation for details. -func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { - spec, err := loadBpf() - if err != nil { - return err - } - - return spec.LoadAndAssign(obj, opts) -} - -// bpfSpecs contains maps and programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfSpecs struct { - bpfProgramSpecs - bpfMapSpecs -} - -// bpfSpecs contains programs before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfProgramSpecs struct { - UprobeGinEngineServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP"` - UprobeGinEngineServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` -} - -// bpfMapSpecs contains maps before they are loaded into the kernel. -// -// It can be passed ebpf.CollectionSpec.Assign. -type bpfMapSpecs struct { - ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` - Events *ebpf.MapSpec `ebpf:"events"` - SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` -} - -// bpfObjects contains all objects after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfObjects struct { - bpfPrograms - bpfMaps -} - -func (o *bpfObjects) Close() error { - return _BpfClose( - &o.bpfPrograms, - &o.bpfMaps, - ) -} - -// bpfMaps contains all maps after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfMaps struct { - ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` - Events *ebpf.Map `ebpf:"events"` - SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` -} - -func (m *bpfMaps) Close() error { - return _BpfClose( - m.ContextToHttpEvents, - m.Events, - m.SpansInProgress, - ) -} - -// bpfPrograms contains all programs after they have been loaded into the kernel. -// -// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. -type bpfPrograms struct { - UprobeGinEngineServeHTTP *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP"` - UprobeGinEngineServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` -} - -func (p *bpfPrograms) Close() error { - return _BpfClose( - p.UprobeGinEngineServeHTTP, - p.UprobeGinEngineServeHTTP_Returns, - ) -} - -func _BpfClose(closers ...io.Closer) error { - for _, closer := range closers { - if err := closer.Close(); err != nil { - return err - } - } - return nil -} - -// Do not access this directly. -// -//go:embed bpf_bpfel.o -var _BpfBytes []byte diff --git a/pkg/process/ptrace/ptrace_linux_arm64.go b/pkg/process/ptrace/ptrace_linux_arm64.go index 6bef2033d..7c523e8e1 100644 --- a/pkg/process/ptrace/ptrace_linux_arm64.go +++ b/pkg/process/ptrace/ptrace_linux_arm64.go @@ -29,7 +29,7 @@ const syscallInstrSize = 4 // see kernel source /include/uapi/linux/elf.h const nrPRStatus = 1 -func getIp(regs *syscall.PtraceRegs) uintptr { +func getIP(regs *syscall.PtraceRegs) uintptr { return uintptr(regs.Pc) } @@ -81,7 +81,7 @@ func (p *TracedProgram) Syscall(number uint64, args ...uint64) (uint64, error) { } instruction := make([]byte, syscallInstrSize) - ip := getIp(p.backupRegs) + ip := getIP(p.backupRegs) // most aarch64 devices are little endian // 0xd4000001 is `svc #0` to call the system call From cf07836995af74b23fdabafdd153d574f8847a12 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 15:55:09 +0100 Subject: [PATCH 34/46] add changelog entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d875776f..580fee2ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ### Added - Add [gin-gonic/gin](https://github.com/gin-gonic/gin) instrumentation. ([#100](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/100)) +- Add ARMM64 support. ([#82](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/82)) ### Changed - Change `OTEL_TARGET_EXE` environment variable to `OTEL_GO_AUTO_TARGET_EXE`. From 2e4948dec19584d3514340d05060c2ab9f370c51 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 18:53:09 +0100 Subject: [PATCH 35/46] extend get_goroutine to work with go <1.17 --- include/arguments.h | 11 +++- .../github.com/gin-gonic/gin/bpf/probe.bpf.c | 10 ++-- .../bpf/github.com/gin-gonic/gin/probe.go | 5 ++ .../github.com/gorilla/mux/bpf/probe.bpf.c | 55 +++++++++---------- .../bpf/net/http/server/bpf/probe.bpf.c | 5 +- test/e2e/gorillamux/traces.json | 28 ---------- 6 files changed, 46 insertions(+), 68 deletions(-) diff --git a/include/arguments.h b/include/arguments.h index 5e57a1595..8d5307b04 100644 --- a/include/arguments.h +++ b/include/arguments.h @@ -64,7 +64,12 @@ void *get_argument(struct pt_regs *ctx, int index) return get_argument_by_stack(ctx, index); } -inline void *get_goroutine_address(struct pt_regs *ctx) +inline void *get_goroutine_address(struct pt_regs *ctx, int go_ctx_index) { - return (void *)GOROUTINE(ctx); -} \ No newline at end of file + if (is_registers_abi) + { + return (void *)GOROUTINE(ctx); + } + + return get_argument_by_stack(ctx, go_ctx_index); +} diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c index 9ee1fe7b6..0c595e789 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf/probe.bpf.c @@ -46,6 +46,7 @@ struct { volatile const u64 method_ptr_pos; volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; +volatile const u64 ctx_ptr_pos; // This instrumentation attaches uprobe to the following function: // func (engine *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) @@ -79,21 +80,18 @@ int uprobe_GinEngine_ServeHTTP(struct pt_regs *ctx) { bpf_probe_read(&httpReq.path, path_size, path_ptr); // Get goroutine pointer - void *goroutine = get_goroutine_address(ctx); + void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); // Write event httpReq.sc = generate_span_context(); bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); - long res = bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); + bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); return 0; } SEC("uprobe/GinEngine_ServeHTTP") int uprobe_GinEngine_ServeHTTP_Returns(struct pt_regs *ctx) { - u64 request_pos = 4; - void *req_ptr = get_argument(ctx, request_pos); - void *goroutine = get_goroutine_address(ctx); - + void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go index 440d410c6..5890674f2 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go @@ -84,6 +84,11 @@ func (h *Instrumentor) Load(ctx *context.InstrumentorContext) error { StructName: "net/http.Request", Field: "URL", }, + { + VarName: "ctx_ptr_pos", + StructName: "net/http.Request", + Field: "ctx", + }, { VarName: "path_ptr_pos", StructName: "net/url.URL", diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c index 275510684..f4a1d4c16 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf/probe.bpf.c @@ -18,26 +18,28 @@ char __license[] SEC("license") = "Dual MIT/GPL"; -#define MAX_SIZE 100 +#define PATH_MAX_LEN 100 +#define METHOD_MAX_LEN 6 // Longer method: DELETE #define MAX_CONCURRENT 50 struct http_request_t { u64 start_time; u64 end_time; - char method[MAX_SIZE]; - char path[MAX_SIZE]; + char method[METHOD_MAX_LEN]; + char path[PATH_MAX_LEN]; struct span_context sc; }; +// map key: pointer to the goroutine that handles the request struct { - __uint(type, BPF_MAP_TYPE_HASH); - __type(key, void*); - __type(value, struct http_request_t); - __uint(max_entries, MAX_CONCURRENT); + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, void *); + __type(value, struct http_request_t); + __uint(max_entries, MAX_CONCURRENT); } context_to_http_events SEC(".maps"); struct { - __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); } events SEC(".maps"); // Injected in init @@ -55,52 +57,47 @@ int uprobe_GorillaMux_ServeHTTP(struct pt_regs *ctx) { httpReq.start_time = bpf_ktime_get_ns(); // Get request struct - void* req_ptr = get_argument(ctx, request_pos); + void *req_ptr = get_argument(ctx, request_pos); // Get method from request - void* method_ptr = 0; - bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr+method_ptr_pos)); + void *method_ptr = 0; + bpf_probe_read(&method_ptr, sizeof(method_ptr), (void *)(req_ptr + method_ptr_pos)); u64 method_len = 0; - bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr+(method_ptr_pos+8))); + bpf_probe_read(&method_len, sizeof(method_len), (void *)(req_ptr + (method_ptr_pos + 8))); u64 method_size = sizeof(httpReq.method); method_size = method_size < method_len ? method_size : method_len; bpf_probe_read(&httpReq.method, method_size, method_ptr); // get path from Request.URL void *url_ptr = 0; - bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr+url_ptr_pos)); - void* path_ptr = 0; - bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr+path_ptr_pos)); + bpf_probe_read(&url_ptr, sizeof(url_ptr), (void *)(req_ptr + url_ptr_pos)); + void *path_ptr = 0; + bpf_probe_read(&path_ptr, sizeof(path_ptr), (void *)(url_ptr + path_ptr_pos)); u64 path_len = 0; - bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr+(path_ptr_pos+8))); + bpf_probe_read(&path_len, sizeof(path_len), (void *)(url_ptr + (path_ptr_pos + 8))); u64 path_size = sizeof(httpReq.path); path_size = path_size < path_len ? path_size : path_len; bpf_probe_read(&httpReq.path, path_size, path_ptr); - // Get Request.ctx - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(req_ptr+ctx_ptr_pos+8)); + // Get goroutine pointer + void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); // Write event httpReq.sc = generate_span_context(); - bpf_map_update_elem(&context_to_http_events, &ctx_iface, &httpReq, 0); - long res = bpf_map_update_elem(&spans_in_progress, &ctx_iface, &httpReq.sc, 0); + bpf_map_update_elem(&context_to_http_events, &goroutine, &httpReq, 0); + bpf_map_update_elem(&spans_in_progress, &goroutine, &httpReq.sc, 0); return 0; } SEC("uprobe/GorillaMux_ServeHTTP") int uprobe_GorillaMux_ServeHTTP_Returns(struct pt_regs *ctx) { - u64 request_pos = 4; - void* req_ptr = get_argument(ctx, request_pos); - void *ctx_iface = 0; - bpf_probe_read(&ctx_iface, sizeof(ctx_iface), (void *)(req_ptr+ctx_ptr_pos+8)); - - void* httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &ctx_iface); + void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); + void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); httpReq.end_time = bpf_ktime_get_ns(); bpf_perf_event_output(ctx, &events, BPF_F_CURRENT_CPU, &httpReq, sizeof(httpReq)); - bpf_map_delete_elem(&context_to_http_events, &ctx_iface); - bpf_map_delete_elem(&spans_in_progress, &ctx_iface); + bpf_map_delete_elem(&context_to_http_events, &goroutine); + bpf_map_delete_elem(&spans_in_progress, &goroutine); return 0; } \ No newline at end of file diff --git a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c index 02f88b16e..bb724666b 100644 --- a/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c +++ b/pkg/instrumentors/bpf/net/http/server/bpf/probe.bpf.c @@ -49,6 +49,7 @@ struct volatile const u64 method_ptr_pos; volatile const u64 url_ptr_pos; volatile const u64 path_ptr_pos; +volatile const u64 ctx_ptr_pos; // This instrumentation attaches uprobe to the following function: // func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) @@ -83,7 +84,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) bpf_probe_read(&httpReq.path, path_size, path_ptr); // Get goroutine pointer - void *goroutine = get_goroutine_address(ctx); + void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); // Write event httpReq.sc = generate_span_context(); @@ -95,7 +96,7 @@ int uprobe_ServerMux_ServeHTTP(struct pt_regs *ctx) SEC("uprobe/ServerMux_ServeHTTP") int uprobe_ServerMux_ServeHTTP_Returns(struct pt_regs *ctx) { - void *goroutine = get_goroutine_address(ctx); + void *goroutine = get_goroutine_address(ctx, ctx_ptr_pos); void *httpReq_ptr = bpf_map_lookup_elem(&context_to_http_events, &goroutine); struct http_request_t httpReq = {}; bpf_probe_read(&httpReq, sizeof(httpReq), httpReq_ptr); diff --git a/test/e2e/gorillamux/traces.json b/test/e2e/gorillamux/traces.json index ba6adfbc6..821041bcc 100644 --- a/test/e2e/gorillamux/traces.json +++ b/test/e2e/gorillamux/traces.json @@ -24,34 +24,6 @@ ] }, "scopeSpans": [ - { - "scope": { - "name": "github.com/gorilla/mux" - }, - "spans": [ - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "" - } - } - ], - "kind": 2, - "parentSpanId": "", - "spanId": "", - "status": {}, - "traceId": "" - } - ] - }, { "scope": { "name": "net/http" From d4451a1a4410526caf78af4ba9713a90d5b80ce5 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 18:54:58 +0100 Subject: [PATCH 36/46] add missing licese files --- pkg/process/ret_linux_amd64.go | 14 ++++++++++++++ pkg/process/ret_linux_arm64.go | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/pkg/process/ret_linux_amd64.go b/pkg/process/ret_linux_amd64.go index 2c730c6d1..ce9a513d6 100644 --- a/pkg/process/ret_linux_amd64.go +++ b/pkg/process/ret_linux_amd64.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package process import ( diff --git a/pkg/process/ret_linux_arm64.go b/pkg/process/ret_linux_arm64.go index a29a10789..ec503a72d 100644 --- a/pkg/process/ret_linux_arm64.go +++ b/pkg/process/ret_linux_arm64.go @@ -1,3 +1,17 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + package process import ( From f54f447aa82796794327c6d62c1d59ee338c6a48 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 19:09:47 +0100 Subject: [PATCH 37/46] fix bad merge in Makefile --- Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/Makefile b/Makefile index 2ce25d6b5..3f7499377 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,6 @@ test/%: generate: export CFLAGS := $(BPF_INCLUDE) generate: go-mod-tidy generate: - go mod tidy TARGET=$(TARGET) go generate ./... .PHONY: go-mod-tidy From c507a1ea8094f05c11344a297297184cc3a0a4b8 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Fri, 28 Apr 2023 19:15:31 +0100 Subject: [PATCH 38/46] remove unnessary additional funcname for net/http instrumentor --- .../bpf/net/http/server/probe.go | 2 +- test/e2e/nethttp/traces.json | 21 ------------------- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index 7f93269ea..d31548249 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -61,7 +61,7 @@ func (h *httpServerInstrumentor) LibraryName() string { } func (h *httpServerInstrumentor) FuncNames() []string { - return []string{"net/http.(*ServeMux).ServeHTTP", "net/http.HandlerFunc.ServeHTTP"} + return []string{"net/http.HandlerFunc.ServeHTTP"} } func (h *httpServerInstrumentor) Load(ctx *context.InstrumentorContext) error { diff --git a/test/e2e/nethttp/traces.json b/test/e2e/nethttp/traces.json index a11b52ea0..4c85eab41 100644 --- a/test/e2e/nethttp/traces.json +++ b/test/e2e/nethttp/traces.json @@ -50,27 +50,6 @@ "spanId": "xxxxx", "status": {}, "traceId": "xxxxx" - }, - { - "attributes": [ - { - "key": "http.method", - "value": { - "stringValue": "" - } - }, - { - "key": "http.target", - "value": { - "stringValue": "" - } - } - ], - "kind": 2, - "parentSpanId": "", - "spanId": "", - "status": {}, - "traceId": "" } ] } From 8a00211280a1312083477cc5d5e3b490b3152aa6 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 2 May 2023 11:18:49 +0100 Subject: [PATCH 39/46] update bpf2go generate commands to use both arm and amd --- Dockerfile | 2 +- Makefile | 3 +- .../gin-gonic/gin/bpf_bpfel_arm64.go | 143 ++++++++++++++++ .../github.com/gin-gonic/gin/bpf_bpfel_x86.go | 143 ++++++++++++++++ .../bpf/github.com/gin-gonic/gin/probe.go | 2 +- .../github.com/gorilla/mux/bpf_bpfel_arm64.go | 143 ++++++++++++++++ .../github.com/gorilla/mux/bpf_bpfel_x86.go | 143 ++++++++++++++++ .../bpf/github.com/gorilla/mux/probe.go | 2 +- .../google/golang/org/grpc/bpf_bpfel_arm64.go | 155 ++++++++++++++++++ .../google/golang/org/grpc/bpf_bpfel_x86.go | 155 ++++++++++++++++++ .../bpf/google/golang/org/grpc/probe.go | 2 +- .../golang/org/grpc/server/bpf_bpfel_arm64.go | 152 +++++++++++++++++ .../golang/org/grpc/server/bpf_bpfel_x86.go | 152 +++++++++++++++++ .../google/golang/org/grpc/server/probe.go | 2 +- .../bpf/net/http/server/bpf_bpfel_arm64.go | 143 ++++++++++++++++ .../bpf/net/http/server/bpf_bpfel_x86.go | 143 ++++++++++++++++ .../bpf/net/http/server/probe.go | 2 +- 17 files changed, 1479 insertions(+), 8 deletions(-) create mode 100644 pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go create mode 100644 pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go create mode 100644 pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go create mode 100644 pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go create mode 100644 pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go create mode 100644 pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go create mode 100644 pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go create mode 100644 pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go create mode 100644 pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go create mode 100644 pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go diff --git a/Dockerfile b/Dockerfile index d2733c999..6dbab74db 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ RUN curl -LO https://go.dev/dl/go1.20.linux-${TARGETARCH}.tar.gz && tar -C /usr/ ENV PATH="/usr/local/go/bin:${PATH}" WORKDIR /app COPY . . -RUN TARGET=${TARGETARCH} make build +RUN make build FROM registry.fedoraproject.org/fedora-minimal:38 COPY --from=builder /app/otel-go-instrumentation / diff --git a/Makefile b/Makefile index 3f7499377..d94318f8a 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,6 @@ GOLICENSES = $(TOOLS)/go-licenses $(TOOLS)/go-licenses: PACKAGE=github.com/google/go-licenses IMG_NAME ?= otel-go-instrumentation -TARGET ?= amd64 GOLANGCI_LINT = $(TOOLS)/golangci-lint $(TOOLS)/golangci-lint: PACKAGE=github.com/golangci/golangci-lint/cmd/golangci-lint @@ -49,7 +48,7 @@ test/%: generate: export CFLAGS := $(BPF_INCLUDE) generate: go-mod-tidy generate: - TARGET=$(TARGET) go generate ./... + go generate ./... .PHONY: go-mod-tidy go-mod-tidy: $(ALL_GO_MOD_DIRS:%=go-mod-tidy/%) diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go new file mode 100644 index 000000000..be4cd2a39 --- /dev/null +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_arm64.go @@ -0,0 +1,143 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 +// +build arm64 + +package gin + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfHttpRequestT struct { + StartTime uint64 + EndTime uint64 + Method [6]int8 + Path [100]int8 + Sc bpfSpanContext + _ [6]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeGinEngineServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP"` + UprobeGinEngineServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.ContextToHttpEvents, + m.Events, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeGinEngineServeHTTP *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP"` + UprobeGinEngineServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeGinEngineServeHTTP, + p.UprobeGinEngineServeHTTP_Returns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_arm64.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go new file mode 100644 index 000000000..d57a435b0 --- /dev/null +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/bpf_bpfel_x86.go @@ -0,0 +1,143 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 +// +build 386 amd64 + +package gin + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfHttpRequestT struct { + StartTime uint64 + EndTime uint64 + Method [6]int8 + Path [100]int8 + Sc bpfSpanContext + _ [6]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeGinEngineServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP"` + UprobeGinEngineServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.ContextToHttpEvents, + m.Events, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeGinEngineServeHTTP *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP"` + UprobeGinEngineServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GinEngine_ServeHTTP_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeGinEngineServeHTTP, + p.UprobeGinEngineServeHTTP_Returns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_x86.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go index 84b507763..301a77af3 100644 --- a/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go +++ b/pkg/instrumentors/bpf/github.com/gin-gonic/gin/probe.go @@ -36,7 +36,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c // Event represents an event in the gin-gonic/gin server during an HTTP // request-response. diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go new file mode 100644 index 000000000..3d8c80d1d --- /dev/null +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_arm64.go @@ -0,0 +1,143 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 +// +build arm64 + +package mux + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfHttpRequestT struct { + StartTime uint64 + EndTime uint64 + Method [6]int8 + Path [100]int8 + Sc bpfSpanContext + _ [6]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeGorillaMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP"` + UprobeGorillaMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.ContextToHttpEvents, + m.Events, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeGorillaMuxServeHTTP *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP"` + UprobeGorillaMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeGorillaMuxServeHTTP, + p.UprobeGorillaMuxServeHTTP_Returns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_arm64.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go new file mode 100644 index 000000000..50f832a31 --- /dev/null +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/bpf_bpfel_x86.go @@ -0,0 +1,143 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 +// +build 386 amd64 + +package mux + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfHttpRequestT struct { + StartTime uint64 + EndTime uint64 + Method [6]int8 + Path [100]int8 + Sc bpfSpanContext + _ [6]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeGorillaMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP"` + UprobeGorillaMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.ContextToHttpEvents, + m.Events, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeGorillaMuxServeHTTP *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP"` + UprobeGorillaMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_GorillaMux_ServeHTTP_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeGorillaMuxServeHTTP, + p.UprobeGorillaMuxServeHTTP_Returns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_x86.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go index 085d8970e..249934adc 100644 --- a/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go +++ b/pkg/instrumentors/bpf/github.com/gorilla/mux/probe.go @@ -36,7 +36,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c // Event represents an event in the gorilla/mux server during an HTTP // request-response. diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go new file mode 100644 index 000000000..5a120d29a --- /dev/null +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_arm64.go @@ -0,0 +1,155 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 +// +build arm64 + +package grpc + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfGrpcRequestT struct { + StartTime uint64 + EndTime uint64 + Method [50]int8 + Target [50]int8 + Sc bpfSpanContext + Psc bpfSpanContext + _ [4]byte +} + +type bpfHeadersBuff struct{ Buff [500]uint8 } + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeHttp2ClientCreateHeaderFields *ebpf.ProgramSpec `ebpf:"uprobe_Http2Client_CreateHeaderFields"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` + Events *ebpf.MapSpec `ebpf:"events"` + HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + AllocMap *ebpf.Map `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` + Events *ebpf.Map `ebpf:"events"` + HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.AllocMap, + m.ContextToGrpcEvents, + m.Events, + m.HeadersBuffMap, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeHttp2ClientCreateHeaderFields *ebpf.Program `ebpf:"uprobe_Http2Client_CreateHeaderFields"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeClientConnInvoke, + p.UprobeClientConnInvokeReturns, + p.UprobeHttp2ClientCreateHeaderFields, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_arm64.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go new file mode 100644 index 000000000..3e4760666 --- /dev/null +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/bpf_bpfel_x86.go @@ -0,0 +1,155 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 +// +build 386 amd64 + +package grpc + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfGrpcRequestT struct { + StartTime uint64 + EndTime uint64 + Method [50]int8 + Target [50]int8 + Sc bpfSpanContext + Psc bpfSpanContext + _ [4]byte +} + +type bpfHeadersBuff struct{ Buff [500]uint8 } + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeClientConnInvoke *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.ProgramSpec `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeHttp2ClientCreateHeaderFields *ebpf.ProgramSpec `ebpf:"uprobe_Http2Client_CreateHeaderFields"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` + Events *ebpf.MapSpec `ebpf:"events"` + HeadersBuffMap *ebpf.MapSpec `ebpf:"headers_buff_map"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + AllocMap *ebpf.Map `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` + Events *ebpf.Map `ebpf:"events"` + HeadersBuffMap *ebpf.Map `ebpf:"headers_buff_map"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.AllocMap, + m.ContextToGrpcEvents, + m.Events, + m.HeadersBuffMap, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeClientConnInvoke *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke"` + UprobeClientConnInvokeReturns *ebpf.Program `ebpf:"uprobe_ClientConn_Invoke_Returns"` + UprobeHttp2ClientCreateHeaderFields *ebpf.Program `ebpf:"uprobe_Http2Client_CreateHeaderFields"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeClientConnInvoke, + p.UprobeClientConnInvokeReturns, + p.UprobeHttp2ClientCreateHeaderFields, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_x86.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go index 031b24245..fa13540fe 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/probe.go @@ -38,7 +38,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c // Event represents an event in the gRPC client during a gRPC request. type Event struct { diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go new file mode 100644 index 000000000..dd91b8731 --- /dev/null +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_arm64.go @@ -0,0 +1,152 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 +// +build arm64 + +package server + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfGrpcRequestT struct { + StartTime uint64 + EndTime uint64 + Method [100]int8 + Sc bpfSpanContext + Psc bpfSpanContext + _ [4]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeDecodeStateDecodeHeader *ebpf.ProgramSpec `ebpf:"uprobe_decodeState_decodeHeader"` + UprobeServerHandleStream *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream"` + UprobeServerHandleStreamReturns *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + AllocMap *ebpf.Map `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.AllocMap, + m.ContextToGrpcEvents, + m.Events, + m.SpansInProgress, + m.StreamidToGrpcEvents, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeDecodeStateDecodeHeader *ebpf.Program `ebpf:"uprobe_decodeState_decodeHeader"` + UprobeServerHandleStream *ebpf.Program `ebpf:"uprobe_server_handleStream"` + UprobeServerHandleStreamReturns *ebpf.Program `ebpf:"uprobe_server_handleStream_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeDecodeStateDecodeHeader, + p.UprobeServerHandleStream, + p.UprobeServerHandleStreamReturns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_arm64.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go new file mode 100644 index 000000000..3c8e878fb --- /dev/null +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/bpf_bpfel_x86.go @@ -0,0 +1,152 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 +// +build 386 amd64 + +package server + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfGrpcRequestT struct { + StartTime uint64 + EndTime uint64 + Method [100]int8 + Sc bpfSpanContext + Psc bpfSpanContext + _ [4]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeDecodeStateDecodeHeader *ebpf.ProgramSpec `ebpf:"uprobe_decodeState_decodeHeader"` + UprobeServerHandleStream *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream"` + UprobeServerHandleStreamReturns *ebpf.ProgramSpec `ebpf:"uprobe_server_handleStream_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + AllocMap *ebpf.MapSpec `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.MapSpec `ebpf:"context_to_grpc_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` + StreamidToGrpcEvents *ebpf.MapSpec `ebpf:"streamid_to_grpc_events"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + AllocMap *ebpf.Map `ebpf:"alloc_map"` + ContextToGrpcEvents *ebpf.Map `ebpf:"context_to_grpc_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` + StreamidToGrpcEvents *ebpf.Map `ebpf:"streamid_to_grpc_events"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.AllocMap, + m.ContextToGrpcEvents, + m.Events, + m.SpansInProgress, + m.StreamidToGrpcEvents, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeDecodeStateDecodeHeader *ebpf.Program `ebpf:"uprobe_decodeState_decodeHeader"` + UprobeServerHandleStream *ebpf.Program `ebpf:"uprobe_server_handleStream"` + UprobeServerHandleStreamReturns *ebpf.Program `ebpf:"uprobe_server_handleStream_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeDecodeStateDecodeHeader, + p.UprobeServerHandleStream, + p.UprobeServerHandleStreamReturns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_x86.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go index 2a0117e4d..78f1491b5 100644 --- a/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go +++ b/pkg/instrumentors/bpf/google/golang/org/grpc/server/probe.go @@ -36,7 +36,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c // Event represents an event in the gRPC server during a gRPC request. type Event struct { diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go new file mode 100644 index 000000000..8b017c446 --- /dev/null +++ b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_arm64.go @@ -0,0 +1,143 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build arm64 +// +build arm64 + +package server + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfHttpRequestT struct { + StartTime uint64 + EndTime uint64 + Method [6]int8 + Path [100]int8 + Sc bpfSpanContext + _ [6]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` + UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.ContextToHttpEvents, + m.Events, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` + UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeServerMuxServeHTTP, + p.UprobeServerMuxServeHTTP_Returns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_arm64.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go new file mode 100644 index 000000000..8d70f5d5e --- /dev/null +++ b/pkg/instrumentors/bpf/net/http/server/bpf_bpfel_x86.go @@ -0,0 +1,143 @@ +// Code generated by bpf2go; DO NOT EDIT. +//go:build 386 || amd64 +// +build 386 amd64 + +package server + +import ( + "bytes" + _ "embed" + "fmt" + "io" + + "github.com/cilium/ebpf" +) + +type bpfHttpRequestT struct { + StartTime uint64 + EndTime uint64 + Method [6]int8 + Path [100]int8 + Sc bpfSpanContext + _ [6]byte +} + +type bpfSpanContext struct { + TraceID [16]uint8 + SpanID [8]uint8 +} + +// loadBpf returns the embedded CollectionSpec for bpf. +func loadBpf() (*ebpf.CollectionSpec, error) { + reader := bytes.NewReader(_BpfBytes) + spec, err := ebpf.LoadCollectionSpecFromReader(reader) + if err != nil { + return nil, fmt.Errorf("can't load bpf: %w", err) + } + + return spec, err +} + +// loadBpfObjects loads bpf and converts it into a struct. +// +// The following types are suitable as obj argument: +// +// *bpfObjects +// *bpfPrograms +// *bpfMaps +// +// See ebpf.CollectionSpec.LoadAndAssign documentation for details. +func loadBpfObjects(obj interface{}, opts *ebpf.CollectionOptions) error { + spec, err := loadBpf() + if err != nil { + return err + } + + return spec.LoadAndAssign(obj, opts) +} + +// bpfSpecs contains maps and programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfSpecs struct { + bpfProgramSpecs + bpfMapSpecs +} + +// bpfSpecs contains programs before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfProgramSpecs struct { + UprobeServerMuxServeHTTP *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP"` + UprobeServerMuxServeHTTP_Returns *ebpf.ProgramSpec `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` +} + +// bpfMapSpecs contains maps before they are loaded into the kernel. +// +// It can be passed ebpf.CollectionSpec.Assign. +type bpfMapSpecs struct { + ContextToHttpEvents *ebpf.MapSpec `ebpf:"context_to_http_events"` + Events *ebpf.MapSpec `ebpf:"events"` + SpansInProgress *ebpf.MapSpec `ebpf:"spans_in_progress"` +} + +// bpfObjects contains all objects after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfObjects struct { + bpfPrograms + bpfMaps +} + +func (o *bpfObjects) Close() error { + return _BpfClose( + &o.bpfPrograms, + &o.bpfMaps, + ) +} + +// bpfMaps contains all maps after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfMaps struct { + ContextToHttpEvents *ebpf.Map `ebpf:"context_to_http_events"` + Events *ebpf.Map `ebpf:"events"` + SpansInProgress *ebpf.Map `ebpf:"spans_in_progress"` +} + +func (m *bpfMaps) Close() error { + return _BpfClose( + m.ContextToHttpEvents, + m.Events, + m.SpansInProgress, + ) +} + +// bpfPrograms contains all programs after they have been loaded into the kernel. +// +// It can be passed to loadBpfObjects or ebpf.CollectionSpec.LoadAndAssign. +type bpfPrograms struct { + UprobeServerMuxServeHTTP *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP"` + UprobeServerMuxServeHTTP_Returns *ebpf.Program `ebpf:"uprobe_ServerMux_ServeHTTP_Returns"` +} + +func (p *bpfPrograms) Close() error { + return _BpfClose( + p.UprobeServerMuxServeHTTP, + p.UprobeServerMuxServeHTTP_Returns, + ) +} + +func _BpfClose(closers ...io.Closer) error { + for _, closer := range closers { + if err := closer.Close(); err != nil { + return err + } + } + return nil +} + +// Do not access this directly. +// +//go:embed bpf_bpfel_x86.o +var _BpfBytes []byte diff --git a/pkg/instrumentors/bpf/net/http/server/probe.go b/pkg/instrumentors/bpf/net/http/server/probe.go index 50a46c071..41d825708 100644 --- a/pkg/instrumentors/bpf/net/http/server/probe.go +++ b/pkg/instrumentors/bpf/net/http/server/probe.go @@ -36,7 +36,7 @@ import ( "go.opentelemetry.io/otel/trace" ) -//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target $TARGET -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c +//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf ./bpf/probe.bpf.c // Event represents an event in an HTTP server during an HTTP // request-response. From 7d7392a8856d971e82e1e4f3fe4d32aad6db37cd Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Tue, 2 May 2023 11:20:46 +0100 Subject: [PATCH 40/46] Update changelog entry Co-authored-by: Tyler Yahn --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0a72be21..149eaf635 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http - Add [gin-gonic/gin](https://github.com/gin-gonic/gin) instrumentation. ([#100](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/100)) - Add ARMM64 support. ([#82](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/82)) + ### Changed - Use verion spans in `offsets_results.json` instead of storing each version. ([#45](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/45)) From eed05ee9d57e5b3da0f1888dcdf0d624701f4c8b Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 2 May 2023 11:29:32 +0100 Subject: [PATCH 41/46] re-add comments to pt_regs struct --- include/common.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/common.h b/include/common.h index 19f1fba55..0eeb5ed59 100644 --- a/include/common.h +++ b/include/common.h @@ -86,12 +86,17 @@ enum #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". + */ long unsigned int r15; long unsigned int r14; long unsigned int r13; long unsigned int r12; long unsigned int bp; long unsigned int bx; + /* These regs are callee-clobbered. Always saved on kernel entry. */ long unsigned int r11; long unsigned int r10; long unsigned int r9; @@ -101,12 +106,18 @@ struct pt_regs { long unsigned int dx; long unsigned int si; long unsigned int di; + /* + * On syscall entry, this is syscall#. On CPU exception, this is error code. + * On hw interrupt, it's IRQ number: + */ long unsigned int orig_ax; + /* Return frame for iretq */ long unsigned int ip; long unsigned int cs; long unsigned int flags; long unsigned int sp; long unsigned int ss; + /* top of stack page */ }; #elif defined(__TARGET_ARCH_arm64) struct user_pt_regs { From 7663e44f9807b38d9e6f7d999457e3ca1f736888 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 2 May 2023 11:51:08 +0100 Subject: [PATCH 42/46] add build guards to findReturnInstructions arch files --- pkg/process/ret_linux_amd64.go | 2 ++ pkg/process/ret_linux_arm64.go | 2 ++ 2 files changed, 4 insertions(+) diff --git a/pkg/process/ret_linux_amd64.go b/pkg/process/ret_linux_amd64.go index ce9a513d6..db14e1916 100644 --- a/pkg/process/ret_linux_amd64.go +++ b/pkg/process/ret_linux_amd64.go @@ -11,6 +11,8 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +//go:build 386 || amd64 +// +build 386 amd64 package process diff --git a/pkg/process/ret_linux_arm64.go b/pkg/process/ret_linux_arm64.go index ec503a72d..9448f14d2 100644 --- a/pkg/process/ret_linux_arm64.go +++ b/pkg/process/ret_linux_arm64.go @@ -11,6 +11,8 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. +//go:build arm64 +// +build arm64 package process From 9afe789733108a536b92402aef6da7bcb6ec0436 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 2 May 2023 12:19:01 +0100 Subject: [PATCH 43/46] unexport error const --- pkg/instrumentors/manager.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/instrumentors/manager.go b/pkg/instrumentors/manager.go index 115f82732..0d4e61608 100644 --- a/pkg/instrumentors/manager.go +++ b/pkg/instrumentors/manager.go @@ -30,7 +30,8 @@ import ( ) var ( - ErrNotAllFuncsFound = fmt.Errorf("not all functions found for instrumentation") + // Error message returned when unable to find all instrumentation functions. + errNotAllFuncsFound = fmt.Errorf("not all functions found for instrumentation") ) // Manager handles the management of [Instrumentor] instances. @@ -100,7 +101,7 @@ func (m *Manager) FilterUnusedInstrumentors(target *process.TargetDetails) { if funcsFound != len(inst.FuncNames()) { if funcsFound > 0 { - log.Logger.Error(ErrNotAllFuncsFound, "some of expected functions not found - check instrumented functions", "instrumentation_name", name, "funcs_found", funcsFound, "funcs_expected", len(inst.FuncNames())) + log.Logger.Error(errNotAllFuncsFound, "some of expected functions not found - check instrumented functions", "instrumentation_name", name, "funcs_found", funcsFound, "funcs_expected", len(inst.FuncNames())) } delete(m.instrumentors, name) } From 12a4b75b9a0a7d48655485dd5e2165e4f31e5535 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 2 May 2023 12:38:10 +0100 Subject: [PATCH 44/46] separate imports --- pkg/process/ret_linux_amd64.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/process/ret_linux_amd64.go b/pkg/process/ret_linux_amd64.go index db14e1916..ccbddb094 100644 --- a/pkg/process/ret_linux_amd64.go +++ b/pkg/process/ret_linux_amd64.go @@ -18,6 +18,7 @@ package process import ( "fmt" + "golang.org/x/arch/x86/x86asm" ) From 6e8943372b1914277c311e4a6ef281ad48913528 Mon Sep 17 00:00:00 2001 From: Mike Goldsmth Date: Tue, 2 May 2023 13:27:45 +0100 Subject: [PATCH 45/46] update mapSize description --- pkg/process/analyze.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/process/analyze.go b/pkg/process/analyze.go index 41249218c..b2aad2d13 100644 --- a/pkg/process/analyze.go +++ b/pkg/process/analyze.go @@ -27,7 +27,9 @@ import ( ) const ( - mapSize = 4096 * 6 * 1024 + // The concurrent trace & span ID pairs lookup size in bytes. Currently set to 24mb. + // TODO: Review map size. + mapSize = 25165824 ) // TargetDetails are the details about a target function. From c395a5cdbaea4462ce98130cb9a25af9df4e0a19 Mon Sep 17 00:00:00 2001 From: Mike Goldsmith Date: Tue, 2 May 2023 15:35:16 +0100 Subject: [PATCH 46/46] Fix changelog entry Co-authored-by: Tyler Yahn --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 149eaf635..677f6e38f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ OpenTelemetry Go Automatic Instrumentation adheres to [Semantic Versioning](http ### Added - Add [gin-gonic/gin](https://github.com/gin-gonic/gin) instrumentation. ([#100](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/100)) -- Add ARMM64 support. ([#82](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/82)) +- Add ARM64 support. ([#82](https://github.com/open-telemetry/opentelemetry-go-instrumentation/pull/82)) ### Changed