You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

编译eBPF代码报错:struct pt_regs无'si'成员

问题:x86_64架构下编译eBPF代码时PT_REGS_PARM2宏报错

环境与代码

我在x86_64架构下尝试编译以下eBPF代码:

#include "vmlinux.h"

#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

SEC("kprobe/do_sys_openat2")
int kprobe__do_sys_openat2(struct pt_regs *ctx)
{
    char file_name[256];
    bpf_probe_read(file_name, sizeof(file_name), PT_REGS_PARM2(ctx));

    char fmt[] = "open file %s\n.";
    bpf_trace_printk(fmt, sizeof(fmt), &file_name);

    return 0;
}

使用如下Makefile构建:

OUTPUT = ./output
LIBBPF = ../libbpf

LIBBPF_SRC = $(abspath $(LIBBPF)/src)
LIBBPF_OBJ = $(abspath $(OUTPUT)/libbpf.a)

CC = gcc
CLANG = clang

ARCH := $(shell uname -m)
# ARCH := $(subst x86_64,amd64,$(ARCH))
GOARCH := $(ARCH)

BPFTOOL = $(shell which bpftool || /bin/false)
BTFFILE = /sys/kernel/btf/vmlinux
DBGVMLINUX = /usr/lib/debug/boot/vmlinux-$(shell uname -r)
GIT = $(shell which git || /bin/false)
VMLINUXH = vmlinux.h

# libbpf

LIBBPF_OBJDIR = $(abspath ./$(OUTPUT)/libbpf)
LIBBPF_DESTDIR = $(abspath ./$(OUTPUT))

CFLAGS = -ggdb -gdwarf -O2 -Wall -fpie -Wno-unused-variable -Wno-unused-function
LDFLAGS =

BPF_CFLAGS_STATIC = "-I$(abspath $(OUTPUT))"
BPF_LDFLAGS_STATIC = "-lelf -lz $(LIBBPF_OBJ)"

CGO_CFLAGS_STATIC = "-I$(abspath $(OUTPUT))"
CGO_LDFLAGS_STATIC = "-lelf -lz $(LIBBPF_OBJ)"
CGO_EXTLDFLAGS_STATIC = '-w -extldflags "-static"'

CGO_CFGLAGS_DYN = "-I. -I/usr/include/"
CGO_LDFLAGS_DYN = "-lelf -lz -lbpf"
CGO_EXTLDFLAGS_DYN = '-w'

## program

.PHONY: $(PROGRAM)
.PHONY: $(PROGRAM).bpf.c

PROGRAM = main

all:
    $(MAKE) -C . $(PROGRAM)

# vmlinux header file

.PHONY: vmlinuxh
vmlinuxh: $(VMLINUXH)

$(VMLINUXH): $(OUTPUT)
ifeq ($(wildcard $(BPFTOOL)),)
    @echo "ERROR: could not find bpftool"
    @exit 1
endif
    @if [ -f $(DBGVMLINUX) ]; then \
        echo "INFO: found dbg kernel, generating $(VMLINUXH) from $(DBGVMLINUX)"; \
        $(BPFTOOL) btf dump file $(DBGVMLINUX) format c > $(VMLINUXH); \
    fi
    @if [ ! -f $(BTFFILE) ] && [ ! -f $(DBGVMLINUX) ]; then \
        echo "ERROR: kernel does not seem to support BTF"; \
        exit 1; \
    fi
    @if [ ! -f $(VMLINUXH) ]; then \
        echo "INFO: generating $(VMLINUXH) from $(BTFFILE)"; \
        $(BPFTOOL) btf dump file $(BTFFILE) format c > $(VMLINUXH); \
    fi

# static libbpf generation for the git submodule

.PHONY: libbpf
libbpf: $(LIBBPF_OBJ)

$(LIBBPF_OBJ): $(LIBBPF_SRC) $(wildcard $(LIBBPF_SRC)/*.[ch]) | $(OUTPUT)/libbpf
    CC="$(CC)" CFLAGS="$(CFLAGS)" LD_FLAGS="$(LDFLAGS)" \
       $(MAKE) -C $(LIBBPF_SRC) \
        BUILD_STATIC_ONLY=1 \
        OBJDIR=$(LIBBPF_OBJDIR) \
        DESTDIR=$(LIBBPF_DESTDIR) \
        INCLUDEDIR= LIBDIR= UAPIDIR= prefix= libdir= install

$(LIBBPF_SRC):
ifeq ($(wildcard $@), )
    echo "INFO: updating submodule 'libbpf'"
    $(GIT) submodule update --init --recursive
endif

# output dir

$(OUTPUT):
    mkdir -p $(OUTPUT)

$(OUTPUT)/libbpf:
    mkdir -p $(OUTPUT)/libbpf

## program bpf dependency

$(PROGRAM).bpf.o: $(PROGRAM).bpf.c | vmlinuxh
    $(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_x86 -I. -I$(OUTPUT) -c $< -o $@

## GO example

.PHONY: $(PROGRAM)

$(PROGRAM): libbpf | $(PROGRAM).bpf.o
    CC=$(CLANG) \
        CGO_CFLAGS=$(CGO_CFLAGS_STATIC) \
        CGO_LDFLAGS=$(CGO_LDFLAGS_STATIC) \
                GOARCH=$(GOARCH) \
                go build \
                -tags netgo -ldflags $(CGO_EXTLDFLAGS_STATIC) \
                -o $(PROGRAM) ./$(PROGRAM).go

## clean

clean:
    $(MAKE) -C $(LIBBPF_SRC) clean
    rm -rf $(OUTPUT)
    rm -rf $(VMLINUXH)
    rm -rf $(PROGRAM) $(PROGRAM)-*static $(PROGRAM)-*dynamic
    rm -rf $(PROGRAM).bpf.o $(PROGRAM).o

编译错误

编译时出现如下错误:

error: no member named 'si' in 'struct pt_regs'
    bpf_probe_read(file_name, sizeof(file_name), PT_REGS_PARM2(ctx));
                                                 ^~~~~~~~~~~~~~~~~~
./output/bpf/bpf_tracing.h:273:46: note: expanded from macro 'PT_REGS_PARM2'
#define PT_REGS_PARM2(x) (__PT_REGS_CAST(x)->__PT_PARM2_REG)
                          ~~~~~~~~~~~~~~~~~  ^
./output/bpf/bpf_tracing.h:78:24: note: expanded from macro '__PT_PARM2_REG'
#define __PT_PARM2_REG si
                       ^

经排查,错误源于bpf_tracing.h中PT_REGS_PARM2宏的定义,该宏展开后会访问struct pt_regs的si成员,但x86_64架构对应的struct pt_regs中并无此成员。想请教是Makefile中的架构指定有误,还是bpf_tracing.h的代码存在问题?


解答

问题出在Makefile中编译eBPF目标文件时的架构定义错误:

在编译$(PROGRAM).bpf.o的规则里,你使用了-D__TARGET_ARCH_x86,但x86_64架构对应的正确宏应该是__TARGET_ARCH_x86_64。

bpf_tracing.h中的__PT_PARM2_REG宏会根据目标架构选择对应的寄存器:

  • 32位x86架构下,第二个参数存在si寄存器中
  • 64位x86_64架构下,第二个参数存在rdi寄存器中

由于你错误定义了32位x86的架构宏,导致宏展开后访问了不存在的si成员。

修复步骤

修改Makefile中编译$(PROGRAM).bpf.o的规则:

$(PROGRAM).bpf.o: $(PROGRAM).bpf.c | vmlinuxh
    $(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_x86_64 -I. -I$(OUTPUT) -c $< -o $@

或者更通用的写法,根据系统架构自动设置:

$(PROGRAM).bpf.o: $(PROGRAM).bpf.c | vmlinuxh
    $(CLANG) $(CFLAGS) -target bpf -D__TARGET_ARCH_$(ARCH) -I. -I$(OUTPUT) -c $< -o $@

这样编译时会正确匹配x86_64架构的寄存器定义,PT_REGS_PARM2宏会展开为访问rdi成员,与struct pt_regs的定义一致,解决编译错误。

另外,还可以检查下libbpf子模块是否为最新版本,确保bpf_tracing.h中的架构相关宏定义是正确的,但核心问题还是架构宏的错误定义。


内容的提问来源于stack exchange,提问作者imawful

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:31:44