Skip to content

Commit

Permalink
collection: define MissingConstantsError
Browse files Browse the repository at this point in the history
RewriteConstants can return the error "spec is missing one or more
constants" if the constant given as parameter does not exist. This patch
defines the error as a specific type so it can be tested with:

    var mErr *MissingConstantsError
    if !errors.As(err, &mErr) { ... }

New unit tests are added, for both the success and failure cases.

Signed-off-by: Alban Crequy <albancrequy@linux.microsoft.com>
Co-developed-by: Lorenz Bauer <oss@lmb.io>
  • Loading branch information
alban authored and lmb committed Jan 17, 2023
1 parent 3cd2cb3 commit 63a3cae
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 2 deletions.
14 changes: 12 additions & 2 deletions collection.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,16 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error {
return nil
}

// MissingConstantsError is returned by [CollectionSpec.RewriteConstants].
type MissingConstantsError struct {
// The constants missing from .rodata.
Constants []string
}

func (m *MissingConstantsError) Error() string {
return fmt.Sprintf("some constants are missing from .rodata: %s", strings.Join(m.Constants, ", "))
}

// RewriteConstants replaces the value of multiple constants.
//
// The constant must be defined like so in the C program:
Expand All @@ -120,7 +130,7 @@ func (cs *CollectionSpec) RewriteMaps(maps map[string]*Map) error {
//
// From Linux 5.5 the verifier will use constants to eliminate dead code.
//
// Returns an error if a constant doesn't exist.
// Returns an error wrapping [MissingConstantsError] if a constant doesn't exist.
func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error {
replaced := make(map[string]bool)

Expand Down Expand Up @@ -184,7 +194,7 @@ func (cs *CollectionSpec) RewriteConstants(consts map[string]interface{}) error
}

if len(missing) != 0 {
return fmt.Errorf("spec is missing one or more constants: %s", strings.Join(missing, ","))
return fmt.Errorf("rewrite constants: %w", &MissingConstantsError{Constants: missing})
}

return nil
Expand Down
47 changes: 47 additions & 0 deletions collection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/cilium/ebpf/btf"
"github.com/cilium/ebpf/internal"
"github.com/cilium/ebpf/internal/testutils"
qt "github.com/frankban/quicktest"
)

func TestCollectionSpecNotModified(t *testing.T) {
Expand Down Expand Up @@ -328,6 +329,52 @@ func TestCollectionSpecMapReplacements_SpecMismatch(t *testing.T) {
}
}

func TestCollectionRewriteConstants(t *testing.T) {
cs := &CollectionSpec{
Maps: map[string]*MapSpec{
".rodata": {
Type: Array,
KeySize: 4,
ValueSize: 4,
MaxEntries: 1,
Value: &btf.Datasec{
Vars: []btf.VarSecinfo{
{
Type: &btf.Var{
Name: "the_constant",
Type: &btf.Int{Size: 4},
},
Offset: 0,
Size: 4,
},
},
},
Contents: []MapKV{
{Key: uint32(0), Value: []byte{1, 1, 1, 1}},
},
},
},
}

err := cs.RewriteConstants(map[string]interface{}{
"fake_constant_one": uint32(1),
"fake_constant_two": uint32(2),
})
qt.Assert(t, err, qt.IsNotNil, qt.Commentf("RewriteConstants did not fail"))

var mErr *MissingConstantsError
if !errors.As(err, &mErr) {
t.Fatal("Error doesn't wrap MissingConstantsError:", err)
}
qt.Assert(t, mErr.Constants, qt.ContentEquals, []string{"fake_constant_one", "fake_constant_two"})

err = cs.RewriteConstants(map[string]interface{}{
"the_constant": uint32(0x42424242),
})
qt.Assert(t, err, qt.IsNil)
qt.Assert(t, cs.Maps[".rodata"].Contents[0].Value, qt.ContentEquals, []byte{0x42, 0x42, 0x42, 0x42})
}

func TestCollectionSpec_LoadAndAssign_LazyLoading(t *testing.T) {
spec := &CollectionSpec{
Maps: map[string]*MapSpec{
Expand Down

0 comments on commit 63a3cae

Please sign in to comment.