MCPcopy
hub / github.com/cilium/ebpf / populateStructOps

Method populateStructOps

collection.go:623–710  ·  view source on GitHub ↗

populateStructOps translates the user struct bytes into the kernel value struct layout for a struct_ops map and writes the result back to mapSpec.Contents[0].

(m *Map, mapSpec *MapSpec)

Source from the content-addressed store, hash-verified

621// populateStructOps translates the user struct bytes into the kernel value struct
622// layout for a struct_ops map and writes the result back to mapSpec.Contents[0].
623func (cl *collectionLoader) populateStructOps(m *Map, mapSpec *MapSpec) error {
624 userType, ok := btf.As[*btf.Struct](mapSpec.Value)
625 if !ok {
626 return fmt.Errorf("value should be a *Struct")
627 }
628
629 userData, err := mapSpec.dataSection()
630 if err != nil {
631 return fmt.Errorf("getting data section: %w", err)
632 }
633 if len(userData) < int(userType.Size) {
634 return fmt.Errorf("user data too short: have %d, need at least %d", len(userData), userType.Size)
635 }
636
637 vType, _, module, err := structOpsFindTarget(userType, cl.types)
638 if err != nil {
639 return fmt.Errorf("struct_ops value type %q: %w", userType.Name, err)
640 }
641 defer module.Close()
642
643 // Find the inner ops struct embedded in the value struct.
644 kType, kTypeOff, err := structOpsFindInnerType(vType)
645 if err != nil {
646 return err
647 }
648
649 kernVData := make([]byte, int(vType.Size))
650 for _, m := range userType.Members {
651 i := slices.IndexFunc(kType.Members, func(km btf.Member) bool {
652 return km.Name == m.Name
653 })
654
655 // Allow field to not exist in target as long as the source is zero.
656 if i == -1 {
657 mSize, err := btf.Sizeof(m.Type)
658 if err != nil {
659 return fmt.Errorf("sizeof(user.%s): %w", m.Name, err)
660 }
661 srcOff := int(m.Offset.Bytes())
662 if srcOff < 0 || srcOff+mSize > len(userData) {
663 return fmt.Errorf("member %q: userdata is too small", m.Name)
664 }
665
666 // let fail if the field in type user type is missing in type kern type
667 if !structOpsIsMemZeroed(userData[srcOff : srcOff+mSize]) {
668 return fmt.Errorf("%s doesn't exist in %s, but it has non-zero value", m.Name, kType.Name)
669 }
670
671 continue
672 }
673
674 km := kType.Members[i]
675
676 switch btf.UnderlyingType(m.Type).(type) {
677 case *btf.Pointer:
678 // If this is a pointer → resolve struct_ops program.
679 psKey := kType.Name + ":" + m.Name
680 for k, ps := range cl.coll.Programs {

Callers 1

populateDeferredMapsMethod · 0.95

Calls 11

SizeofFunction · 0.92
UnderlyingTypeFunction · 0.92
structOpsFindTargetFunction · 0.85
structOpsFindInnerTypeFunction · 0.85
structOpsIsMemZeroedFunction · 0.85
structOpsPopulateValueFunction · 0.85
structOpsCopyMemberFunction · 0.85
dataSectionMethod · 0.80
PutMethod · 0.80
CloseMethod · 0.65
BytesMethod · 0.45

Tested by

no test coverage detected