From 1c32cfee4365ad2f62cc92b7fdd59be82bb0b798 Mon Sep 17 00:00:00 2001 From: Timo Beckers Date: Wed, 23 Feb 2022 16:19:07 +0100 Subject: [PATCH] collection: don't copy btf.Spec in CollectionSpec.Copy() Copying btf.Spec requires updating Map/Program.BTF.(S,s)pec, which gets complicated due to btf.Map/Program being pointers. Instead of implementing a full deep-copy, avoid copying btf.Spec for now, since it's considered read-only. Since we're planning to get rid of btf.Program/Map anyway, this would not be worth the investment. Add a test that loads both a copy and an original CollectionSpec. Signed-off-by: Timo Beckers --- collection.go | 3 ++- collection_test.go | 29 +++++++++++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/collection.go b/collection.go index 9bb0a2d65..8d27828c9 100644 --- a/collection.go +++ b/collection.go @@ -28,6 +28,7 @@ type CollectionSpec struct { Programs map[string]*ProgramSpec // Types holds type information about Maps and Programs. + // Modifications to Types are currently undefined behaviour. Types *btf.Spec // ByteOrder specifies whether the ELF was compiled for @@ -45,7 +46,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec { Maps: make(map[string]*MapSpec, len(cs.Maps)), Programs: make(map[string]*ProgramSpec, len(cs.Programs)), ByteOrder: cs.ByteOrder, - Types: cs.Types.Copy(), + Types: cs.Types, } for name, spec := range cs.Maps { diff --git a/collection_test.go b/collection_test.go index 714e74ac4..e40a749da 100644 --- a/collection_test.go +++ b/collection_test.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/cilium/ebpf/asm" + "github.com/cilium/ebpf/internal" "github.com/cilium/ebpf/internal/btf" "github.com/cilium/ebpf/internal/testutils" ) @@ -83,8 +84,32 @@ func TestCollectionSpecCopy(t *testing.T) { t.Error("Copy returned same Programs") } - if cpy.Types == cs.Types { - t.Error("Copy returned same Types") + if cpy.Types != cs.Types { + t.Error("Copy returned different Types") + } +} + +func TestCollectionSpecLoadCopy(t *testing.T) { + file := fmt.Sprintf("testdata/loader-%s.elf", internal.ClangEndian) + spec, err := LoadCollectionSpec(file) + if err != nil { + t.Fatal(err) + } + + spec2 := spec.Copy() + + var objs struct { + Prog *Program `ebpf:"xdp_prog"` + } + + err = spec.LoadAndAssign(&objs, nil) + testutils.SkipIfNotSupported(t, err) + if err != nil { + t.Fatal("Loading original spec:", err) + } + + if err := spec2.LoadAndAssign(&objs, nil); err != nil { + t.Fatal("Loading copied spec:", err) } }