Skip to content

Development Guide

Relevant source files

The following files were used as context for generating this wiki page:

This document provides comprehensive guidance for developers contributing to eCapture. It covers the build system, development workflow, testing procedures, and release process. For information about implementing new capture modules, see Adding New Modules. For eBPF program development details, see eBPF Program Development.


Development Environment Setup

Prerequisites

eCapture requires the following tools and libraries for development:

ComponentMinimum VersionPurpose
Go1.24User-space program compilation
Clang9+ (14 recommended)eBPF program compilation
LLVM9+ (14 recommended)eBPF bytecode generation
Linux Kernel4.18+eBPF support
libelf-dev-ELF file parsing
Linux headers-Kernel structure definitions

Environment Initialization Script

The project provides an automated environment setup script at builder/init_env.sh:1-106. This script:

  1. Detects the Ubuntu version and selects appropriate Clang version (builder/init_env.sh:16-39)
  2. Installs required packages via apt-get (builder/init_env.sh:72-74)
  3. Configures cross-compilation toolchain (builder/init_env.sh:43-61)
  4. Prepares Linux kernel sources for eBPF compilation (builder/init_env.sh:81-89)
  5. Downloads and installs Go (builder/init_env.sh:94-97)

Architecture Detection: The script automatically detects the host architecture and configures cross-compilation:

Manual Execution:

bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/gojue/ecapture/master/builder/init_env.sh)"

Sources: builder/init_env.sh:1-106


Build System Architecture

Makefile Structure

The build system consists of three primary files:

Build System Components:

Sources: Makefile:1-11, functions.mk:1-76, builder/Makefile.release:1-10

Build Targets Overview

TargetPurposeBytecode Included
allFull build with CO-RE and non-CO-REBoth
nocoreBuild with non-CO-RE onlyNon-CO-RE only
ebpfCompile CO-RE eBPF bytecodeCO-RE
ebpf_noncoreCompile non-CO-RE eBPF bytecodeNon-CO-RE
assetsGenerate Go embedded bytecodeBoth
buildCompile Go binary-
cleanRemove build artifacts-
test-raceRun unit tests with race detector-
e2eRun end-to-end tests-

Sources: Makefile:4-14, Makefile:106-245


Build Process Flow

Complete Build Pipeline

Sources: Makefile:6-11, Makefile:133-201

CO-RE vs Non-CO-RE Compilation

CO-RE (Compile Once, Run Everywhere):

bash
clang -D__TARGET_ARCH_x86 \
  -target bpfel \
  -c kern/openssl.c \
  -o user/bytecode/openssl_kern_core.o \
  -g -fno-ident
  • Produces kernel-agnostic bytecode (Makefile:122-127)
  • Requires kernel with BTF (BPF Type Format) support
  • Uses vmlinux.h generated by bpftool btf dump (Makefile:130-131)
  • Smaller file size, portable across kernel versions

Non-CO-RE (Kernel-Specific):

bash
clang -I /usr/src/linux-source/arch/x86/include \
  -c kern/openssl.c -o - | \
llc -march=bpf -filetype=obj \
  -o user/bytecode/openssl_kern_noncore.o
  • Requires kernel headers for target kernel (Makefile:144-159)
  • Works on older kernels without BTF support
  • Kernel-specific, must rebuild for different kernel versions
  • Larger file size due to kernel structure definitions

Build Variables:

Sources: Makefile:117-159

Asset Embedding Process

The build system uses go-bindata to embed all eBPF bytecode files into the Go binary:

  1. Compile eBPF Programs: Produces *.o files in user/bytecode/
  2. Generate Go Code: go-bindata reads all .o files (Makefile:164)
  3. Create Asset Package: Generates assets/ebpf_probe.go (Makefile:164)
  4. Embed in Binary: Go build includes embedded assets

This approach eliminates the need to distribute separate bytecode files alongside the binary.

Sources: Makefile:162-171


Building eCapture

Standard Build (Native Architecture)

Full build with both CO-RE and non-CO-RE:

bash
make clean
make env          # Display build environment
make all          # Build everything

Non-CO-RE only (for older kernels):

bash
make clean
make nocore

The nocore target is useful when:

  • Target system lacks BTF support
  • Deploying to specific kernel version
  • Reducing binary size by excluding CO-RE bytecode

Sources: Makefile:4-14

Cross-Compilation

Build for ARM64 on x86_64:

bash
make clean
CROSS_ARCH=arm64 make env
CROSS_ARCH=arm64 make all

Build for x86_64 on ARM64:

bash
make clean
CROSS_ARCH=amd64 make env
CROSS_ARCH=amd64 make all

Cross-Compilation Requirements:

libpcap Cross-Compilation: The build system automatically configures libpcap for cross-compilation:

bash
CC=aarch64-linux-gnu-gcc AR=aarch64-linux-gnu-ar \
  ./configure --host=aarch64-linux-gnu

Sources: Makefile:56-65, Makefile:176-184, .github/workflows/go-c-cpp.yml:56-65

Android Builds

Build for Android (ARM64):

bash
make clean
CROSS_ARCH=arm64 make env
ANDROID=1 CROSS_ARCH=arm64 make nocore

Android-Specific Considerations:

Sources: Makefile:95, .github/workflows/go-c-cpp.yml:61-65

Build Environment Variables

VariableDescriptionExample
CROSS_ARCHTarget architecturearm64, amd64
ANDROIDAndroid build flag1 (enable)
DEBUGDebug build flag1 (enable debug symbols)
SNAPSHOT_VERSIONOverride version stringv0.8.0

Environment Display:

bash
make env

This command displays all build variables including:

  • Host architecture detection
  • Kernel version
  • Compiler versions
  • Target architecture settings
  • Version information

Sources: Makefile:19-63


Testing

Unit Tests

Run unit tests:

bash
go test -v ./...

Run with race detector:

bash
make test-race

The race detector build (Makefile:216-224):

  • Enables CGO_ENABLED=1 for C integration
  • Links with libpcap statically
  • Uses race detector to identify data races

Sources: Makefile:216-224

End-to-End Tests

The project includes E2E test scripts for each major module:

Run specific E2E test:

bash
make e2e-tls       # Test TLS/SSL capture
make e2e-gnutls    # Test GnuTLS capture
make e2e-gotls     # Test Go TLS capture

Run all E2E tests:

bash
make e2e

Sources: Makefile:226-244


CI/CD Pipeline

GitHub Actions Workflow Architecture

Sources: .github/workflows/go-c-cpp.yml:1-128, .github/workflows/release.yml:1-129

CI Build Matrix

The CI system builds and tests multiple configurations:

ArchitectureNative BuildCross-CompilationAndroid
x86_64✓ CO-RE + non-CO-RE✓ arm64 target✓ arm64
arm64✓ CO-RE + non-CO-RE✓ amd64 target✓ amd64

CI Build Steps:

  1. Setup Environment (.github/workflows/go-c-cpp.yml:16-33):

    • Install Go 1.24.6
    • Install Clang 14, LLVM tools
    • Extract and prepare Linux kernel sources
  2. Native CO-RE Build (.github/workflows/go-c-cpp.yml:38-44):

    bash
    make clean
    make env
    DEBUG=1 make -j8
  3. Code Quality Check (.github/workflows/go-c-cpp.yml:45-50):

    • Run golangci-lint on Go code
    • Version: v2.1
  4. Non-CO-RE Build (.github/workflows/go-c-cpp.yml:51-55):

    bash
    make clean
    make nocore
  5. Cross-Compilation (.github/workflows/go-c-cpp.yml:56-65):

    bash
    CROSS_ARCH=arm64 make env
    CROSS_ARCH=arm64 make -j8
    ANDROID=1 CROSS_ARCH=arm64 make nocore -j8
  6. Test Execution (.github/workflows/go-c-cpp.yml:66-67):

    bash
    go test -v -race ./...

Sources: .github/workflows/go-c-cpp.yml:9-127

Compiler Version Management

The CI system ensures consistent compiler versions:

Clang/LLVM Setup:

bash
for tool in "clang" "llc" "llvm-strip"
do
  sudo rm -f /usr/bin/$tool
  sudo ln -s /usr/bin/$tool-14 /usr/bin/$tool
done

This creates symlinks to enforce Clang 14 usage (.github/workflows/go-c-cpp.yml:20-24).

Kernel Source Preparation:

bash
cd /usr/src
source_file=$(find . -maxdepth 1 -name "*linux-source*.tar.bz2")
sudo tar -xf $source_file
cd $source_dir
sudo make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- prepare V=0

Prepares kernel headers for cross-compilation (.github/workflows/go-c-cpp.yml:25-32).

Sources: .github/workflows/go-c-cpp.yml:16-33


Release Process

Release Workflow

Sources: .github/workflows/release.yml:1-129, builder/Makefile.release:1-151

Release Targets

Create snapshot (development build):

bash
make -f builder/Makefile.release snapshot

Create release (specific version):

bash
SNAPSHOT_VERSION=v0.8.0 make -f builder/Makefile.release release

Publish to GitHub:

bash
SNAPSHOT_VERSION=v0.8.0 make -f builder/Makefile.release publish

The release target orchestrates (builder/Makefile.release:10):

  1. snapshot: Build Linux artifacts
  2. build_deb: Create DEB packages
  3. snapshot_android: Build Android artifacts

Sources: builder/Makefile.release:10-151

Packaging Formats

TAR.GZ Archives

Archive Contents:

  • ecapture binary
  • LICENSE
  • CHANGELOG.md
  • README.md and README_CN.md

Naming Convention:

ecapture-{VERSION}-{OS}-{ARCH}[-nocore].tar.gz

Examples:

  • ecapture-v0.8.0-linux-amd64.tar.gz (CO-RE + non-CO-RE)
  • ecapture-v0.8.0-android-arm64-nocore.tar.gz (non-CO-RE only)

Archive Creation (builder/Makefile.release:62-76):

bash
$(CMD_MKDIR) -p $(TAR_DIR)
$(CMD_CP) LICENSE $(TAR_DIR)/LICENSE
$(CMD_CP) bin/ecapture $(TAR_DIR)/ecapture
$(CMD_TAR) -czf $(OUT_ARCHIVE) $(TAR_DIR)

Sources: builder/Makefile.release:62-76, functions.mk:62-76

DEB Packages

Package Structure:

ecapture-v0.8.0-amd64.deb
├── DEBIAN/
│   └── control
└── usr/
    └── local/
        └── bin/
            └── ecapture

Control File Fields (builder/Makefile.release:143-149):

  • Package: ecapture
  • Version: Extracted from git tag
  • Architecture: amd64 or arm64
  • Maintainer: CFC4N cfc4ncs@gmail.com
  • Description: capture SSL/TLS text content without CA cert by eBPF

Build Process:

bash
make -f builder/Makefile.release deb

Creates DEB package using dpkg-deb --build (builder/Makefile.release:151).

Sources: builder/Makefile.release:132-151

Docker Images

Multi-Architecture Build:

bash
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  --build-arg VERSION=v0.8.0 \
  -t ecapture:v0.8.0 \
  -t ecapture:latest \
  --push .

Dockerfile Stages (builder/Dockerfile:1-39):

  1. Builder Stage: Ubuntu 22.04 base

    • Install compilers (Clang 14, Go 1.24.6)
    • Build eCapture with make all
  2. Runtime Stage: Alpine Linux

    • Copy only the ecapture binary
    • Set ENTRYPOINT to /ecapture

Image Tags:

  • {username}/ecapture:v{VERSION} (version-specific)
  • {username}/ecapture:latest (latest release)

Sources: .github/workflows/release.yml:101-129, builder/Dockerfile:1-39

Release Notes Generation

The release workflow automatically generates release notes:

  1. Get Previous Tag (.github/workflows/release.yml:63-67):

    bash
    PREVIOUS=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
  2. Generate Notes via GitHub API (.github/workflows/release.yml:68-80):

    bash
    gh api --method POST \
      /repos/$REPO/releases/generate-notes \
      -f tag_name=$TAG \
      -f previous_tag_name=$PREVIOUS_TAG
  3. Create Release (builder/Makefile.release:124):

    bash
    gh release create $(VERSION) $$FILES \
      --title "eCapture $(VERSION)" \
      --notes-file $(RELEASE_NOTES)

Sources: .github/workflows/release.yml:63-87, builder/Makefile.release:114-124


Development Workflow Summary

Typical Development Cycle

  1. Setup Environment:

    bash
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/gojue/ecapture/master/builder/init_env.sh)"
  2. Clone and Build:

    bash
    git clone https://github.com/gojue/ecapture.git
    cd ecapture
    make env          # Verify environment
    make all          # Build everything
  3. Make Changes:

    • Modify eBPF programs in kern/
    • Modify Go code in cli/, user/, or other packages
  4. Test:

    bash
    make clean
    make all
    go test -v ./...
    make e2e          # If testing modules
  5. Format Code:

    bash
    make format       # Format C code with clang-format
  6. Commit and Push:

    bash
    git add .
    git commit -m "Your change description"
    git push origin your-branch
  7. Create Pull Request:

    • CI automatically runs on x86_64 and arm64
    • Both native and cross-compilation builds tested
    • Code quality checked with golangci-lint

Key Build Commands Reference

CommandPurposeUse Case
make envShow build environmentVerify configuration
make allFull build (CO-RE + non-CO-RE)Development
make nocoreNon-CO-RE only buildOlder kernels
make cleanRemove build artifactsClean rebuild
make test-raceRun tests with race detectorFind concurrency issues
make e2eRun E2E testsIntegration testing
make formatFormat C codeCode style
CROSS_ARCH=arm64 makeCross-compile for ARM64ARM target
ANDROID=1 make nocoreBuild for AndroidMobile deployment

Sources: Makefile:1-245, builder/Makefile.release:1-151

Development Guide has loaded