Skip to content

Commit

Permalink
elfparser: Add method to load BPF from an io.ReaderAt
Browse files Browse the repository at this point in the history
- Introduce the `LoadBpfFromReader` method in the `bpfSDKClient`.
- This method enables loading ELF files directly from an io.ReaderAt.

Signed-off-by: shun159 <dreamdiagnosis@gmail.com>
  • Loading branch information
shun159 committed Sep 22, 2023
1 parent 9148455 commit c9a6296
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 9 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ test-data/*.elf
test/c/vmlinux.h
test/c/*.elf
test/main
pkg/**/*.elf
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export GOPROXY = direct

CURDIR := $(abspath .)
TESTDATADIR := $(CURDIR)/test-data
ELFPARSERDIR := $(CURDIR)/pkg/elfparser
BPFTOOL := bpftool
CLANG := clang
LOGFILE_PATH ?= stdout
Expand Down Expand Up @@ -48,7 +49,8 @@ TARGETS := \
$(TESTDATADIR)/recoverydata \
$(TESTDATADIR)/test-kprobe \
$(TESTDATADIR)/xdp \
$(TESTDATADIR)/ring_buffer
$(TESTDATADIR)/ring_buffer \
$(ELFPARSERDIR)/test-data/test

%.bpf.elf: %.bpf.c
$(CLANG) $(CLANG_INCLUDE) $(BPF_CFLAGS) -c $< -o $@
Expand All @@ -74,3 +76,4 @@ unit-test: ## Run unit tests
clean:
-@rm -f $(TESTDATADIR)/vmlinux.h
-@rm -f $(TESTDATADIR)/*.elf
-@rm -f $(ELFPARSERDIR)/test-data/*.elf
26 changes: 18 additions & 8 deletions pkg/elfparser/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ var sdkCache = cache.Get()
type BpfSDKClient interface {
IncreaseRlimit() error
LoadBpfFile(path, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error)
LoadBpfFromReader(r io.ReaderAt, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error)
RecoverGlobalMaps() (map[string]ebpf_maps.BpfMap, error)
RecoverAllBpfProgramsAndMaps() (map[string]BpfData, error)
}
Expand Down Expand Up @@ -122,26 +123,35 @@ func newElfLoader(elfFile *elf.File, bpfmapapi ebpf_maps.BpfMapAPIs, bpfprogapi
return elfloader
}

func (b *bpfSDKClient) LoadBpfFile(path, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error) {
bpfFile, err := os.Open(path)
// LoadBpfFromReader loads ELF file from io.ReaderAt and parses an ELF file into BPF objects
func (b *bpfSDKClient) LoadBpfFromReader(r io.ReaderAt, customizedPinPath string) (
map[string]BpfData,
map[string]ebpf_maps.BpfMap,
error,
) {
elfFile, err := elf.NewFile(r)
if err != nil {
log.Infof("LoadBpfFile failed to open")
return nil, nil, err
}
defer bpfFile.Close()

elfFile, err := elf.NewFile(bpfFile)
elfLoader := newElfLoader(elfFile, b.mapApi, b.progApi, customizedPinPath)
bpfLoadedProg, bpfLoadedMaps, err := elfLoader.doLoadELF()
if err != nil {
return nil, nil, err
}

elfLoader := newElfLoader(elfFile, b.mapApi, b.progApi, customizedPinPath)
return bpfLoadedProg, bpfLoadedMaps, nil
}

bpfLoadedProg, bpfLoadedMaps, err := elfLoader.doLoadELF()
func (b *bpfSDKClient) LoadBpfFile(path, customizedPinPath string) (map[string]BpfData, map[string]ebpf_maps.BpfMap, error) {
bpfFile, err := os.Open(path)
if err != nil {
log.Infof("LoadBpfFile failed to open")
return nil, nil, err
}
return bpfLoadedProg, bpfLoadedMaps, nil
defer bpfFile.Close()

return b.LoadBpfFromReader(bpfFile, customizedPinPath)
}

func (e *elfLoader) loadMap(parsedMapData []ebpf_maps.CreateEBPFMapInput) (map[string]ebpf_maps.BpfMap, error) {
Expand Down
16 changes: 16 additions & 0 deletions pkg/elfparser/elf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@
package elfparser

import (
"bytes"
"debug/elf"
_ "embed"
"errors"
"os"
"sort"
Expand Down Expand Up @@ -668,3 +670,17 @@ func TestProgType(t *testing.T) {
})
}
}

//go:embed test-data/test.bpf.elf

Check failure on line 674 in pkg/elfparser/elf_test.go

View workflow job for this annotation

GitHub Actions / Unit test

pattern test-data/test.bpf.elf: no matching files found
var elfBytes []byte

func TestLoadBpfFromEmbeddedElf(t *testing.T) {
if os.Getuid() != 0 {
t.Skip("Test requires root privileges.")
}

bpfSDKclient := New()
r := bytes.NewReader(elfBytes)
_, _, err := bpfSDKclient.LoadBpfFromReader(r, "")
assert.NoError(t, err)
}
9 changes: 9 additions & 0 deletions pkg/elfparser/test-data/test.bpf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#include <linux/types.h>

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

SEC("kprobe")
int test_kprobe(struct pt_regs *ctx) { return 0; }

char _license[] SEC("license") = "GPL";

0 comments on commit c9a6296

Please sign in to comment.