gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

map.go (37505B)


      1 package ebpf
      2 
      3 import (
      4 	"bytes"
      5 	"errors"
      6 	"fmt"
      7 	"io"
      8 	"math/rand"
      9 	"path/filepath"
     10 	"reflect"
     11 	"time"
     12 	"unsafe"
     13 
     14 	"github.com/cilium/ebpf/btf"
     15 	"github.com/cilium/ebpf/internal"
     16 	"github.com/cilium/ebpf/internal/sys"
     17 	"github.com/cilium/ebpf/internal/unix"
     18 )
     19 
     20 // Errors returned by Map and MapIterator methods.
     21 var (
     22 	ErrKeyNotExist      = errors.New("key does not exist")
     23 	ErrKeyExist         = errors.New("key already exists")
     24 	ErrIterationAborted = errors.New("iteration aborted")
     25 	ErrMapIncompatible  = errors.New("map spec is incompatible with existing map")
     26 	errMapNoBTFValue    = errors.New("map spec does not contain a BTF Value")
     27 )
     28 
     29 // MapOptions control loading a map into the kernel.
     30 type MapOptions struct {
     31 	// The base path to pin maps in if requested via PinByName.
     32 	// Existing maps will be re-used if they are compatible, otherwise an
     33 	// error is returned.
     34 	PinPath        string
     35 	LoadPinOptions LoadPinOptions
     36 }
     37 
     38 // MapID represents the unique ID of an eBPF map
     39 type MapID uint32
     40 
     41 // MapSpec defines a Map.
     42 type MapSpec struct {
     43 	// Name is passed to the kernel as a debug aid. Must only contain
     44 	// alpha numeric and '_' characters.
     45 	Name       string
     46 	Type       MapType
     47 	KeySize    uint32
     48 	ValueSize  uint32
     49 	MaxEntries uint32
     50 
     51 	// Flags is passed to the kernel and specifies additional map
     52 	// creation attributes.
     53 	Flags uint32
     54 
     55 	// Automatically pin and load a map from MapOptions.PinPath.
     56 	// Generates an error if an existing pinned map is incompatible with the MapSpec.
     57 	Pinning PinType
     58 
     59 	// Specify numa node during map creation
     60 	// (effective only if unix.BPF_F_NUMA_NODE flag is set,
     61 	// which can be imported from golang.org/x/sys/unix)
     62 	NumaNode uint32
     63 
     64 	// The initial contents of the map. May be nil.
     65 	Contents []MapKV
     66 
     67 	// Whether to freeze a map after setting its initial contents.
     68 	Freeze bool
     69 
     70 	// InnerMap is used as a template for ArrayOfMaps and HashOfMaps
     71 	InnerMap *MapSpec
     72 
     73 	// Extra trailing bytes found in the ELF map definition when using structs
     74 	// larger than libbpf's bpf_map_def. nil if no trailing bytes were present.
     75 	// Must be nil or empty before instantiating the MapSpec into a Map.
     76 	Extra *bytes.Reader
     77 
     78 	// The key and value type of this map. May be nil.
     79 	Key, Value btf.Type
     80 
     81 	// The BTF associated with this map.
     82 	BTF *btf.Spec
     83 }
     84 
     85 func (ms *MapSpec) String() string {
     86 	return fmt.Sprintf("%s(keySize=%d, valueSize=%d, maxEntries=%d, flags=%d)", ms.Type, ms.KeySize, ms.ValueSize, ms.MaxEntries, ms.Flags)
     87 }
     88 
     89 // Copy returns a copy of the spec.
     90 //
     91 // MapSpec.Contents is a shallow copy.
     92 func (ms *MapSpec) Copy() *MapSpec {
     93 	if ms == nil {
     94 		return nil
     95 	}
     96 
     97 	cpy := *ms
     98 
     99 	cpy.Contents = make([]MapKV, len(ms.Contents))
    100 	copy(cpy.Contents, ms.Contents)
    101 
    102 	cpy.InnerMap = ms.InnerMap.Copy()
    103 
    104 	return &cpy
    105 }
    106 
    107 // hasBTF returns true if the MapSpec has a valid BTF spec and if its
    108 // map type supports associated BTF metadata in the kernel.
    109 func (ms *MapSpec) hasBTF() bool {
    110 	return ms.BTF != nil && ms.Type.hasBTF()
    111 }
    112 
    113 func (ms *MapSpec) clampPerfEventArraySize() error {
    114 	if ms.Type != PerfEventArray {
    115 		return nil
    116 	}
    117 
    118 	n, err := internal.PossibleCPUs()
    119 	if err != nil {
    120 		return fmt.Errorf("perf event array: %w", err)
    121 	}
    122 
    123 	if n := uint32(n); ms.MaxEntries > n {
    124 		ms.MaxEntries = n
    125 	}
    126 
    127 	return nil
    128 }
    129 
    130 // dataSection returns the contents and BTF Datasec descriptor of the spec.
    131 func (ms *MapSpec) dataSection() ([]byte, *btf.Datasec, error) {
    132 
    133 	if ms.Value == nil {
    134 		return nil, nil, errMapNoBTFValue
    135 	}
    136 
    137 	ds, ok := ms.Value.(*btf.Datasec)
    138 	if !ok {
    139 		return nil, nil, fmt.Errorf("map value BTF is a %T, not a *btf.Datasec", ms.Value)
    140 	}
    141 
    142 	if n := len(ms.Contents); n != 1 {
    143 		return nil, nil, fmt.Errorf("expected one key, found %d", n)
    144 	}
    145 
    146 	kv := ms.Contents[0]
    147 	value, ok := kv.Value.([]byte)
    148 	if !ok {
    149 		return nil, nil, fmt.Errorf("value at first map key is %T, not []byte", kv.Value)
    150 	}
    151 
    152 	return value, ds, nil
    153 }
    154 
    155 // MapKV is used to initialize the contents of a Map.
    156 type MapKV struct {
    157 	Key   interface{}
    158 	Value interface{}
    159 }
    160 
    161 func (ms *MapSpec) checkCompatibility(m *Map) error {
    162 	switch {
    163 	case m.typ != ms.Type:
    164 		return fmt.Errorf("expected type %v, got %v: %w", ms.Type, m.typ, ErrMapIncompatible)
    165 
    166 	case m.keySize != ms.KeySize:
    167 		return fmt.Errorf("expected key size %v, got %v: %w", ms.KeySize, m.keySize, ErrMapIncompatible)
    168 
    169 	case m.valueSize != ms.ValueSize:
    170 		return fmt.Errorf("expected value size %v, got %v: %w", ms.ValueSize, m.valueSize, ErrMapIncompatible)
    171 
    172 	case !(ms.Type == PerfEventArray && ms.MaxEntries == 0) &&
    173 		m.maxEntries != ms.MaxEntries:
    174 		return fmt.Errorf("expected max entries %v, got %v: %w", ms.MaxEntries, m.maxEntries, ErrMapIncompatible)
    175 
    176 	case m.flags != ms.Flags:
    177 		return fmt.Errorf("expected flags %v, got %v: %w", ms.Flags, m.flags, ErrMapIncompatible)
    178 	}
    179 	return nil
    180 }
    181 
    182 // Map represents a Map file descriptor.
    183 //
    184 // It is not safe to close a map which is used by other goroutines.
    185 //
    186 // Methods which take interface{} arguments by default encode
    187 // them using binary.Read/Write in the machine's native endianness.
    188 //
    189 // Implement encoding.BinaryMarshaler or encoding.BinaryUnmarshaler
    190 // if you require custom encoding.
    191 type Map struct {
    192 	name       string
    193 	fd         *sys.FD
    194 	typ        MapType
    195 	keySize    uint32
    196 	valueSize  uint32
    197 	maxEntries uint32
    198 	flags      uint32
    199 	pinnedPath string
    200 	// Per CPU maps return values larger than the size in the spec
    201 	fullValueSize int
    202 }
    203 
    204 // NewMapFromFD creates a map from a raw fd.
    205 //
    206 // You should not use fd after calling this function.
    207 func NewMapFromFD(fd int) (*Map, error) {
    208 	f, err := sys.NewFD(fd)
    209 	if err != nil {
    210 		return nil, err
    211 	}
    212 
    213 	return newMapFromFD(f)
    214 }
    215 
    216 func newMapFromFD(fd *sys.FD) (*Map, error) {
    217 	info, err := newMapInfoFromFd(fd)
    218 	if err != nil {
    219 		fd.Close()
    220 		return nil, fmt.Errorf("get map info: %w", err)
    221 	}
    222 
    223 	return newMap(fd, info.Name, info.Type, info.KeySize, info.ValueSize, info.MaxEntries, info.Flags)
    224 }
    225 
    226 // NewMap creates a new Map.
    227 //
    228 // It's equivalent to calling NewMapWithOptions with default options.
    229 func NewMap(spec *MapSpec) (*Map, error) {
    230 	return NewMapWithOptions(spec, MapOptions{})
    231 }
    232 
    233 // NewMapWithOptions creates a new Map.
    234 //
    235 // Creating a map for the first time will perform feature detection
    236 // by creating small, temporary maps.
    237 //
    238 // The caller is responsible for ensuring the process' rlimit is set
    239 // sufficiently high for locking memory during map creation. This can be done
    240 // by calling rlimit.RemoveMemlock() prior to calling NewMapWithOptions.
    241 //
    242 // May return an error wrapping ErrMapIncompatible.
    243 func NewMapWithOptions(spec *MapSpec, opts MapOptions) (*Map, error) {
    244 	handles := newHandleCache()
    245 	defer handles.close()
    246 
    247 	m, err := newMapWithOptions(spec, opts, handles)
    248 	if err != nil {
    249 		return nil, fmt.Errorf("creating map: %w", err)
    250 	}
    251 
    252 	if err := m.finalize(spec); err != nil {
    253 		m.Close()
    254 		return nil, fmt.Errorf("populating map: %w", err)
    255 	}
    256 
    257 	return m, nil
    258 }
    259 
    260 func newMapWithOptions(spec *MapSpec, opts MapOptions, handles *handleCache) (_ *Map, err error) {
    261 	closeOnError := func(c io.Closer) {
    262 		if err != nil {
    263 			c.Close()
    264 		}
    265 	}
    266 
    267 	switch spec.Pinning {
    268 	case PinByName:
    269 		if spec.Name == "" {
    270 			return nil, fmt.Errorf("pin by name: missing Name")
    271 		}
    272 
    273 		if opts.PinPath == "" {
    274 			return nil, fmt.Errorf("pin by name: missing MapOptions.PinPath")
    275 		}
    276 
    277 		path := filepath.Join(opts.PinPath, spec.Name)
    278 		m, err := LoadPinnedMap(path, &opts.LoadPinOptions)
    279 		if errors.Is(err, unix.ENOENT) {
    280 			break
    281 		}
    282 		if err != nil {
    283 			return nil, fmt.Errorf("load pinned map: %w", err)
    284 		}
    285 		defer closeOnError(m)
    286 
    287 		if err := spec.checkCompatibility(m); err != nil {
    288 			return nil, fmt.Errorf("use pinned map %s: %w", spec.Name, err)
    289 		}
    290 
    291 		return m, nil
    292 
    293 	case PinNone:
    294 		// Nothing to do here
    295 
    296 	default:
    297 		return nil, fmt.Errorf("pin type %d: %w", int(spec.Pinning), ErrNotSupported)
    298 	}
    299 
    300 	var innerFd *sys.FD
    301 	if spec.Type == ArrayOfMaps || spec.Type == HashOfMaps {
    302 		if spec.InnerMap == nil {
    303 			return nil, fmt.Errorf("%s requires InnerMap", spec.Type)
    304 		}
    305 
    306 		if spec.InnerMap.Pinning != PinNone {
    307 			return nil, errors.New("inner maps cannot be pinned")
    308 		}
    309 
    310 		template, err := spec.InnerMap.createMap(nil, opts, handles)
    311 		if err != nil {
    312 			return nil, fmt.Errorf("inner map: %w", err)
    313 		}
    314 		defer template.Close()
    315 
    316 		// Intentionally skip populating and freezing (finalizing)
    317 		// the inner map template since it will be removed shortly.
    318 
    319 		innerFd = template.fd
    320 	}
    321 
    322 	m, err := spec.createMap(innerFd, opts, handles)
    323 	if err != nil {
    324 		return nil, err
    325 	}
    326 	defer closeOnError(m)
    327 
    328 	if spec.Pinning == PinByName {
    329 		path := filepath.Join(opts.PinPath, spec.Name)
    330 		if err := m.Pin(path); err != nil {
    331 			return nil, fmt.Errorf("pin map: %w", err)
    332 		}
    333 	}
    334 
    335 	return m, nil
    336 }
    337 
    338 // createMap validates the spec's properties and creates the map in the kernel
    339 // using the given opts. It does not populate or freeze the map.
    340 func (spec *MapSpec) createMap(inner *sys.FD, opts MapOptions, handles *handleCache) (_ *Map, err error) {
    341 	closeOnError := func(closer io.Closer) {
    342 		if err != nil {
    343 			closer.Close()
    344 		}
    345 	}
    346 
    347 	spec = spec.Copy()
    348 
    349 	// Kernels 4.13 through 5.4 used a struct bpf_map_def that contained
    350 	// additional 'inner_map_idx' and later 'numa_node' fields.
    351 	// In order to support loading these definitions, tolerate the presence of
    352 	// extra bytes, but require them to be zeroes.
    353 	if spec.Extra != nil {
    354 		if _, err := io.Copy(internal.DiscardZeroes{}, spec.Extra); err != nil {
    355 			return nil, errors.New("extra contains unhandled non-zero bytes, drain before creating map")
    356 		}
    357 	}
    358 
    359 	switch spec.Type {
    360 	case ArrayOfMaps, HashOfMaps:
    361 		if err := haveNestedMaps(); err != nil {
    362 			return nil, err
    363 		}
    364 
    365 		if spec.ValueSize != 0 && spec.ValueSize != 4 {
    366 			return nil, errors.New("ValueSize must be zero or four for map of map")
    367 		}
    368 		spec.ValueSize = 4
    369 
    370 	case PerfEventArray:
    371 		if spec.KeySize != 0 && spec.KeySize != 4 {
    372 			return nil, errors.New("KeySize must be zero or four for perf event array")
    373 		}
    374 		spec.KeySize = 4
    375 
    376 		if spec.ValueSize != 0 && spec.ValueSize != 4 {
    377 			return nil, errors.New("ValueSize must be zero or four for perf event array")
    378 		}
    379 		spec.ValueSize = 4
    380 
    381 		if spec.MaxEntries == 0 {
    382 			n, err := internal.PossibleCPUs()
    383 			if err != nil {
    384 				return nil, fmt.Errorf("perf event array: %w", err)
    385 			}
    386 			spec.MaxEntries = uint32(n)
    387 		}
    388 	}
    389 
    390 	if spec.Flags&(unix.BPF_F_RDONLY_PROG|unix.BPF_F_WRONLY_PROG) > 0 || spec.Freeze {
    391 		if err := haveMapMutabilityModifiers(); err != nil {
    392 			return nil, fmt.Errorf("map create: %w", err)
    393 		}
    394 	}
    395 	if spec.Flags&unix.BPF_F_MMAPABLE > 0 {
    396 		if err := haveMmapableMaps(); err != nil {
    397 			return nil, fmt.Errorf("map create: %w", err)
    398 		}
    399 	}
    400 	if spec.Flags&unix.BPF_F_INNER_MAP > 0 {
    401 		if err := haveInnerMaps(); err != nil {
    402 			return nil, fmt.Errorf("map create: %w", err)
    403 		}
    404 	}
    405 	if spec.Flags&unix.BPF_F_NO_PREALLOC > 0 {
    406 		if err := haveNoPreallocMaps(); err != nil {
    407 			return nil, fmt.Errorf("map create: %w", err)
    408 		}
    409 	}
    410 
    411 	attr := sys.MapCreateAttr{
    412 		MapType:    sys.MapType(spec.Type),
    413 		KeySize:    spec.KeySize,
    414 		ValueSize:  spec.ValueSize,
    415 		MaxEntries: spec.MaxEntries,
    416 		MapFlags:   spec.Flags,
    417 		NumaNode:   spec.NumaNode,
    418 	}
    419 
    420 	if inner != nil {
    421 		attr.InnerMapFd = inner.Uint()
    422 	}
    423 
    424 	if haveObjName() == nil {
    425 		attr.MapName = sys.NewObjName(spec.Name)
    426 	}
    427 
    428 	if spec.hasBTF() {
    429 		handle, err := handles.btfHandle(spec.BTF)
    430 		if err != nil && !errors.Is(err, btf.ErrNotSupported) {
    431 			return nil, fmt.Errorf("load BTF: %w", err)
    432 		}
    433 
    434 		if handle != nil {
    435 			keyTypeID, err := spec.BTF.TypeID(spec.Key)
    436 			if err != nil {
    437 				return nil, err
    438 			}
    439 
    440 			valueTypeID, err := spec.BTF.TypeID(spec.Value)
    441 			if err != nil {
    442 				return nil, err
    443 			}
    444 
    445 			attr.BtfFd = uint32(handle.FD())
    446 			attr.BtfKeyTypeId = uint32(keyTypeID)
    447 			attr.BtfValueTypeId = uint32(valueTypeID)
    448 		}
    449 	}
    450 
    451 	fd, err := sys.MapCreate(&attr)
    452 	if err != nil {
    453 		if errors.Is(err, unix.EPERM) {
    454 			return nil, fmt.Errorf("map create: %w (MEMLOCK may be too low, consider rlimit.RemoveMemlock)", err)
    455 		}
    456 		if !spec.hasBTF() {
    457 			return nil, fmt.Errorf("map create without BTF: %w", err)
    458 		}
    459 		if errors.Is(err, unix.EINVAL) && attr.MaxEntries == 0 {
    460 			return nil, fmt.Errorf("map create: %w (MaxEntries may be incorrectly set to zero)", err)
    461 		}
    462 		return nil, fmt.Errorf("map create: %w", err)
    463 	}
    464 	defer closeOnError(fd)
    465 
    466 	m, err := newMap(fd, spec.Name, spec.Type, spec.KeySize, spec.ValueSize, spec.MaxEntries, spec.Flags)
    467 	if err != nil {
    468 		return nil, fmt.Errorf("map create: %w", err)
    469 	}
    470 
    471 	return m, nil
    472 }
    473 
    474 // newMap allocates and returns a new Map structure.
    475 // Sets the fullValueSize on per-CPU maps.
    476 func newMap(fd *sys.FD, name string, typ MapType, keySize, valueSize, maxEntries, flags uint32) (*Map, error) {
    477 	m := &Map{
    478 		name,
    479 		fd,
    480 		typ,
    481 		keySize,
    482 		valueSize,
    483 		maxEntries,
    484 		flags,
    485 		"",
    486 		int(valueSize),
    487 	}
    488 
    489 	if !typ.hasPerCPUValue() {
    490 		return m, nil
    491 	}
    492 
    493 	possibleCPUs, err := internal.PossibleCPUs()
    494 	if err != nil {
    495 		return nil, err
    496 	}
    497 
    498 	m.fullValueSize = internal.Align(int(valueSize), 8) * possibleCPUs
    499 	return m, nil
    500 }
    501 
    502 func (m *Map) String() string {
    503 	if m.name != "" {
    504 		return fmt.Sprintf("%s(%s)#%v", m.typ, m.name, m.fd)
    505 	}
    506 	return fmt.Sprintf("%s#%v", m.typ, m.fd)
    507 }
    508 
    509 // Type returns the underlying type of the map.
    510 func (m *Map) Type() MapType {
    511 	return m.typ
    512 }
    513 
    514 // KeySize returns the size of the map key in bytes.
    515 func (m *Map) KeySize() uint32 {
    516 	return m.keySize
    517 }
    518 
    519 // ValueSize returns the size of the map value in bytes.
    520 func (m *Map) ValueSize() uint32 {
    521 	return m.valueSize
    522 }
    523 
    524 // MaxEntries returns the maximum number of elements the map can hold.
    525 func (m *Map) MaxEntries() uint32 {
    526 	return m.maxEntries
    527 }
    528 
    529 // Flags returns the flags of the map.
    530 func (m *Map) Flags() uint32 {
    531 	return m.flags
    532 }
    533 
    534 // Info returns metadata about the map.
    535 func (m *Map) Info() (*MapInfo, error) {
    536 	return newMapInfoFromFd(m.fd)
    537 }
    538 
    539 // MapLookupFlags controls the behaviour of the map lookup calls.
    540 type MapLookupFlags uint64
    541 
    542 // LookupLock look up the value of a spin-locked map.
    543 const LookupLock MapLookupFlags = 4
    544 
    545 // Lookup retrieves a value from a Map.
    546 //
    547 // Calls Close() on valueOut if it is of type **Map or **Program,
    548 // and *valueOut is not nil.
    549 //
    550 // Returns an error if the key doesn't exist, see ErrKeyNotExist.
    551 func (m *Map) Lookup(key, valueOut interface{}) error {
    552 	valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
    553 	if err := m.lookup(key, valuePtr, 0); err != nil {
    554 		return err
    555 	}
    556 
    557 	return m.unmarshalValue(valueOut, valueBytes)
    558 }
    559 
    560 // LookupWithFlags retrieves a value from a Map with flags.
    561 //
    562 // Passing LookupLock flag will look up the value of a spin-locked
    563 // map without returning the lock. This must be specified if the
    564 // elements contain a spinlock.
    565 //
    566 // Calls Close() on valueOut if it is of type **Map or **Program,
    567 // and *valueOut is not nil.
    568 //
    569 // Returns an error if the key doesn't exist, see ErrKeyNotExist.
    570 func (m *Map) LookupWithFlags(key, valueOut interface{}, flags MapLookupFlags) error {
    571 	valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
    572 	if err := m.lookup(key, valuePtr, flags); err != nil {
    573 		return err
    574 	}
    575 
    576 	return m.unmarshalValue(valueOut, valueBytes)
    577 }
    578 
    579 // LookupAndDelete retrieves and deletes a value from a Map.
    580 //
    581 // Returns ErrKeyNotExist if the key doesn't exist.
    582 func (m *Map) LookupAndDelete(key, valueOut interface{}) error {
    583 	return m.lookupAndDelete(key, valueOut, 0)
    584 }
    585 
    586 // LookupAndDeleteWithFlags retrieves and deletes a value from a Map.
    587 //
    588 // Passing LookupLock flag will look up and delete the value of a spin-locked
    589 // map without returning the lock. This must be specified if the elements
    590 // contain a spinlock.
    591 //
    592 // Returns ErrKeyNotExist if the key doesn't exist.
    593 func (m *Map) LookupAndDeleteWithFlags(key, valueOut interface{}, flags MapLookupFlags) error {
    594 	return m.lookupAndDelete(key, valueOut, flags)
    595 }
    596 
    597 // LookupBytes gets a value from Map.
    598 //
    599 // Returns a nil value if a key doesn't exist.
    600 func (m *Map) LookupBytes(key interface{}) ([]byte, error) {
    601 	valueBytes := make([]byte, m.fullValueSize)
    602 	valuePtr := sys.NewSlicePointer(valueBytes)
    603 
    604 	err := m.lookup(key, valuePtr, 0)
    605 	if errors.Is(err, ErrKeyNotExist) {
    606 		return nil, nil
    607 	}
    608 
    609 	return valueBytes, err
    610 }
    611 
    612 func (m *Map) lookup(key interface{}, valueOut sys.Pointer, flags MapLookupFlags) error {
    613 	keyPtr, err := m.marshalKey(key)
    614 	if err != nil {
    615 		return fmt.Errorf("can't marshal key: %w", err)
    616 	}
    617 
    618 	attr := sys.MapLookupElemAttr{
    619 		MapFd: m.fd.Uint(),
    620 		Key:   keyPtr,
    621 		Value: valueOut,
    622 		Flags: uint64(flags),
    623 	}
    624 
    625 	if err = sys.MapLookupElem(&attr); err != nil {
    626 		return fmt.Errorf("lookup: %w", wrapMapError(err))
    627 	}
    628 	return nil
    629 }
    630 
    631 func (m *Map) lookupAndDelete(key, valueOut interface{}, flags MapLookupFlags) error {
    632 	valuePtr, valueBytes := makeBuffer(valueOut, m.fullValueSize)
    633 
    634 	keyPtr, err := m.marshalKey(key)
    635 	if err != nil {
    636 		return fmt.Errorf("can't marshal key: %w", err)
    637 	}
    638 
    639 	attr := sys.MapLookupAndDeleteElemAttr{
    640 		MapFd: m.fd.Uint(),
    641 		Key:   keyPtr,
    642 		Value: valuePtr,
    643 		Flags: uint64(flags),
    644 	}
    645 
    646 	if err := sys.MapLookupAndDeleteElem(&attr); err != nil {
    647 		return fmt.Errorf("lookup and delete: %w", wrapMapError(err))
    648 	}
    649 
    650 	return m.unmarshalValue(valueOut, valueBytes)
    651 }
    652 
    653 // MapUpdateFlags controls the behaviour of the Map.Update call.
    654 //
    655 // The exact semantics depend on the specific MapType.
    656 type MapUpdateFlags uint64
    657 
    658 const (
    659 	// UpdateAny creates a new element or update an existing one.
    660 	UpdateAny MapUpdateFlags = iota
    661 	// UpdateNoExist creates a new element.
    662 	UpdateNoExist MapUpdateFlags = 1 << (iota - 1)
    663 	// UpdateExist updates an existing element.
    664 	UpdateExist
    665 	// UpdateLock updates elements under bpf_spin_lock.
    666 	UpdateLock
    667 )
    668 
    669 // Put replaces or creates a value in map.
    670 //
    671 // It is equivalent to calling Update with UpdateAny.
    672 func (m *Map) Put(key, value interface{}) error {
    673 	return m.Update(key, value, UpdateAny)
    674 }
    675 
    676 // Update changes the value of a key.
    677 func (m *Map) Update(key, value interface{}, flags MapUpdateFlags) error {
    678 	keyPtr, err := m.marshalKey(key)
    679 	if err != nil {
    680 		return fmt.Errorf("can't marshal key: %w", err)
    681 	}
    682 
    683 	valuePtr, err := m.marshalValue(value)
    684 	if err != nil {
    685 		return fmt.Errorf("can't marshal value: %w", err)
    686 	}
    687 
    688 	attr := sys.MapUpdateElemAttr{
    689 		MapFd: m.fd.Uint(),
    690 		Key:   keyPtr,
    691 		Value: valuePtr,
    692 		Flags: uint64(flags),
    693 	}
    694 
    695 	if err = sys.MapUpdateElem(&attr); err != nil {
    696 		return fmt.Errorf("update: %w", wrapMapError(err))
    697 	}
    698 
    699 	return nil
    700 }
    701 
    702 // Delete removes a value.
    703 //
    704 // Returns ErrKeyNotExist if the key does not exist.
    705 func (m *Map) Delete(key interface{}) error {
    706 	keyPtr, err := m.marshalKey(key)
    707 	if err != nil {
    708 		return fmt.Errorf("can't marshal key: %w", err)
    709 	}
    710 
    711 	attr := sys.MapDeleteElemAttr{
    712 		MapFd: m.fd.Uint(),
    713 		Key:   keyPtr,
    714 	}
    715 
    716 	if err = sys.MapDeleteElem(&attr); err != nil {
    717 		return fmt.Errorf("delete: %w", wrapMapError(err))
    718 	}
    719 	return nil
    720 }
    721 
    722 // NextKey finds the key following an initial key.
    723 //
    724 // See NextKeyBytes for details.
    725 //
    726 // Returns ErrKeyNotExist if there is no next key.
    727 func (m *Map) NextKey(key, nextKeyOut interface{}) error {
    728 	nextKeyPtr, nextKeyBytes := makeBuffer(nextKeyOut, int(m.keySize))
    729 
    730 	if err := m.nextKey(key, nextKeyPtr); err != nil {
    731 		return err
    732 	}
    733 
    734 	if err := m.unmarshalKey(nextKeyOut, nextKeyBytes); err != nil {
    735 		return fmt.Errorf("can't unmarshal next key: %w", err)
    736 	}
    737 	return nil
    738 }
    739 
    740 // NextKeyBytes returns the key following an initial key as a byte slice.
    741 //
    742 // Passing nil will return the first key.
    743 //
    744 // Use Iterate if you want to traverse all entries in the map.
    745 //
    746 // Returns nil if there are no more keys.
    747 func (m *Map) NextKeyBytes(key interface{}) ([]byte, error) {
    748 	nextKey := make([]byte, m.keySize)
    749 	nextKeyPtr := sys.NewSlicePointer(nextKey)
    750 
    751 	err := m.nextKey(key, nextKeyPtr)
    752 	if errors.Is(err, ErrKeyNotExist) {
    753 		return nil, nil
    754 	}
    755 
    756 	return nextKey, err
    757 }
    758 
    759 func (m *Map) nextKey(key interface{}, nextKeyOut sys.Pointer) error {
    760 	var (
    761 		keyPtr sys.Pointer
    762 		err    error
    763 	)
    764 
    765 	if key != nil {
    766 		keyPtr, err = m.marshalKey(key)
    767 		if err != nil {
    768 			return fmt.Errorf("can't marshal key: %w", err)
    769 		}
    770 	}
    771 
    772 	attr := sys.MapGetNextKeyAttr{
    773 		MapFd:   m.fd.Uint(),
    774 		Key:     keyPtr,
    775 		NextKey: nextKeyOut,
    776 	}
    777 
    778 	if err = sys.MapGetNextKey(&attr); err != nil {
    779 		// Kernels 4.4.131 and earlier return EFAULT instead of a pointer to the
    780 		// first map element when a nil key pointer is specified.
    781 		if key == nil && errors.Is(err, unix.EFAULT) {
    782 			var guessKey []byte
    783 			guessKey, err = m.guessNonExistentKey()
    784 			if err != nil {
    785 				return err
    786 			}
    787 
    788 			// Retry the syscall with a valid non-existing key.
    789 			attr.Key = sys.NewSlicePointer(guessKey)
    790 			if err = sys.MapGetNextKey(&attr); err == nil {
    791 				return nil
    792 			}
    793 		}
    794 
    795 		return fmt.Errorf("next key: %w", wrapMapError(err))
    796 	}
    797 
    798 	return nil
    799 }
    800 
    801 // guessNonExistentKey attempts to perform a map lookup that returns ENOENT.
    802 // This is necessary on kernels before 4.4.132, since those don't support
    803 // iterating maps from the start by providing an invalid key pointer.
    804 func (m *Map) guessNonExistentKey() ([]byte, error) {
    805 	// Provide an invalid value pointer to prevent a copy on the kernel side.
    806 	valuePtr := sys.NewPointer(unsafe.Pointer(^uintptr(0)))
    807 	randKey := make([]byte, int(m.keySize))
    808 
    809 	for i := 0; i < 4; i++ {
    810 		switch i {
    811 		// For hash maps, the 0 key is less likely to be occupied. They're often
    812 		// used for storing data related to pointers, and their access pattern is
    813 		// generally scattered across the keyspace.
    814 		case 0:
    815 		// An all-0xff key is guaranteed to be out of bounds of any array, since
    816 		// those have a fixed key size of 4 bytes. The only corner case being
    817 		// arrays with 2^32 max entries, but those are prohibitively expensive
    818 		// in many environments.
    819 		case 1:
    820 			for r := range randKey {
    821 				randKey[r] = 0xff
    822 			}
    823 		// Inspired by BCC, 0x55 is an alternating binary pattern (0101), so
    824 		// is unlikely to be taken.
    825 		case 2:
    826 			for r := range randKey {
    827 				randKey[r] = 0x55
    828 			}
    829 		// Last ditch effort, generate a random key.
    830 		case 3:
    831 			rand.New(rand.NewSource(time.Now().UnixNano())).Read(randKey)
    832 		}
    833 
    834 		err := m.lookup(randKey, valuePtr, 0)
    835 		if errors.Is(err, ErrKeyNotExist) {
    836 			return randKey, nil
    837 		}
    838 	}
    839 
    840 	return nil, errors.New("couldn't find non-existing key")
    841 }
    842 
    843 // BatchLookup looks up many elements in a map at once.
    844 //
    845 // "keysOut" and "valuesOut" must be of type slice, a pointer
    846 // to a slice or buffer will not work.
    847 // "prevKey" is the key to start the batch lookup from, it will
    848 // *not* be included in the results. Use nil to start at the first key.
    849 //
    850 // ErrKeyNotExist is returned when the batch lookup has reached
    851 // the end of all possible results, even when partial results
    852 // are returned. It should be used to evaluate when lookup is "done".
    853 func (m *Map) BatchLookup(prevKey, nextKeyOut, keysOut, valuesOut interface{}, opts *BatchOptions) (int, error) {
    854 	return m.batchLookup(sys.BPF_MAP_LOOKUP_BATCH, prevKey, nextKeyOut, keysOut, valuesOut, opts)
    855 }
    856 
    857 // BatchLookupAndDelete looks up many elements in a map at once,
    858 //
    859 // It then deletes all those elements.
    860 // "keysOut" and "valuesOut" must be of type slice, a pointer
    861 // to a slice or buffer will not work.
    862 // "prevKey" is the key to start the batch lookup from, it will
    863 // *not* be included in the results. Use nil to start at the first key.
    864 //
    865 // ErrKeyNotExist is returned when the batch lookup has reached
    866 // the end of all possible results, even when partial results
    867 // are returned. It should be used to evaluate when lookup is "done".
    868 func (m *Map) BatchLookupAndDelete(prevKey, nextKeyOut, keysOut, valuesOut interface{}, opts *BatchOptions) (int, error) {
    869 	return m.batchLookup(sys.BPF_MAP_LOOKUP_AND_DELETE_BATCH, prevKey, nextKeyOut, keysOut, valuesOut, opts)
    870 }
    871 
    872 func (m *Map) batchLookup(cmd sys.Cmd, startKey, nextKeyOut, keysOut, valuesOut interface{}, opts *BatchOptions) (int, error) {
    873 	if err := haveBatchAPI(); err != nil {
    874 		return 0, err
    875 	}
    876 	if m.typ.hasPerCPUValue() {
    877 		return 0, ErrNotSupported
    878 	}
    879 	keysValue := reflect.ValueOf(keysOut)
    880 	if keysValue.Kind() != reflect.Slice {
    881 		return 0, fmt.Errorf("keys must be a slice")
    882 	}
    883 	valuesValue := reflect.ValueOf(valuesOut)
    884 	if valuesValue.Kind() != reflect.Slice {
    885 		return 0, fmt.Errorf("valuesOut must be a slice")
    886 	}
    887 	count := keysValue.Len()
    888 	if count != valuesValue.Len() {
    889 		return 0, fmt.Errorf("keysOut and valuesOut must be the same length")
    890 	}
    891 	keyBuf := make([]byte, count*int(m.keySize))
    892 	keyPtr := sys.NewSlicePointer(keyBuf)
    893 	valueBuf := make([]byte, count*int(m.fullValueSize))
    894 	valuePtr := sys.NewSlicePointer(valueBuf)
    895 	nextPtr, nextBuf := makeBuffer(nextKeyOut, int(m.keySize))
    896 
    897 	attr := sys.MapLookupBatchAttr{
    898 		MapFd:    m.fd.Uint(),
    899 		Keys:     keyPtr,
    900 		Values:   valuePtr,
    901 		Count:    uint32(count),
    902 		OutBatch: nextPtr,
    903 	}
    904 
    905 	if opts != nil {
    906 		attr.ElemFlags = opts.ElemFlags
    907 		attr.Flags = opts.Flags
    908 	}
    909 
    910 	var err error
    911 	if startKey != nil {
    912 		attr.InBatch, err = marshalPtr(startKey, int(m.keySize))
    913 		if err != nil {
    914 			return 0, err
    915 		}
    916 	}
    917 
    918 	_, sysErr := sys.BPF(cmd, unsafe.Pointer(&attr), unsafe.Sizeof(attr))
    919 	sysErr = wrapMapError(sysErr)
    920 	if sysErr != nil && !errors.Is(sysErr, unix.ENOENT) {
    921 		return 0, sysErr
    922 	}
    923 
    924 	err = m.unmarshalKey(nextKeyOut, nextBuf)
    925 	if err != nil {
    926 		return 0, err
    927 	}
    928 	err = unmarshalBytes(keysOut, keyBuf)
    929 	if err != nil {
    930 		return 0, err
    931 	}
    932 	err = unmarshalBytes(valuesOut, valueBuf)
    933 	if err != nil {
    934 		return 0, err
    935 	}
    936 
    937 	return int(attr.Count), sysErr
    938 }
    939 
    940 // BatchUpdate updates the map with multiple keys and values
    941 // simultaneously.
    942 // "keys" and "values" must be of type slice, a pointer
    943 // to a slice or buffer will not work.
    944 func (m *Map) BatchUpdate(keys, values interface{}, opts *BatchOptions) (int, error) {
    945 	if err := haveBatchAPI(); err != nil {
    946 		return 0, err
    947 	}
    948 	if m.typ.hasPerCPUValue() {
    949 		return 0, ErrNotSupported
    950 	}
    951 	keysValue := reflect.ValueOf(keys)
    952 	if keysValue.Kind() != reflect.Slice {
    953 		return 0, fmt.Errorf("keys must be a slice")
    954 	}
    955 	valuesValue := reflect.ValueOf(values)
    956 	if valuesValue.Kind() != reflect.Slice {
    957 		return 0, fmt.Errorf("values must be a slice")
    958 	}
    959 	var (
    960 		count    = keysValue.Len()
    961 		valuePtr sys.Pointer
    962 		err      error
    963 	)
    964 	if count != valuesValue.Len() {
    965 		return 0, fmt.Errorf("keys and values must be the same length")
    966 	}
    967 	keyPtr, err := marshalPtr(keys, count*int(m.keySize))
    968 	if err != nil {
    969 		return 0, err
    970 	}
    971 	valuePtr, err = marshalPtr(values, count*int(m.valueSize))
    972 	if err != nil {
    973 		return 0, err
    974 	}
    975 
    976 	attr := sys.MapUpdateBatchAttr{
    977 		MapFd:  m.fd.Uint(),
    978 		Keys:   keyPtr,
    979 		Values: valuePtr,
    980 		Count:  uint32(count),
    981 	}
    982 	if opts != nil {
    983 		attr.ElemFlags = opts.ElemFlags
    984 		attr.Flags = opts.Flags
    985 	}
    986 
    987 	err = sys.MapUpdateBatch(&attr)
    988 	if err != nil {
    989 		return int(attr.Count), fmt.Errorf("batch update: %w", wrapMapError(err))
    990 	}
    991 
    992 	return int(attr.Count), nil
    993 }
    994 
    995 // BatchDelete batch deletes entries in the map by keys.
    996 // "keys" must be of type slice, a pointer to a slice or buffer will not work.
    997 func (m *Map) BatchDelete(keys interface{}, opts *BatchOptions) (int, error) {
    998 	if err := haveBatchAPI(); err != nil {
    999 		return 0, err
   1000 	}
   1001 	if m.typ.hasPerCPUValue() {
   1002 		return 0, ErrNotSupported
   1003 	}
   1004 	keysValue := reflect.ValueOf(keys)
   1005 	if keysValue.Kind() != reflect.Slice {
   1006 		return 0, fmt.Errorf("keys must be a slice")
   1007 	}
   1008 	count := keysValue.Len()
   1009 	keyPtr, err := marshalPtr(keys, count*int(m.keySize))
   1010 	if err != nil {
   1011 		return 0, fmt.Errorf("cannot marshal keys: %v", err)
   1012 	}
   1013 
   1014 	attr := sys.MapDeleteBatchAttr{
   1015 		MapFd: m.fd.Uint(),
   1016 		Keys:  keyPtr,
   1017 		Count: uint32(count),
   1018 	}
   1019 
   1020 	if opts != nil {
   1021 		attr.ElemFlags = opts.ElemFlags
   1022 		attr.Flags = opts.Flags
   1023 	}
   1024 
   1025 	if err = sys.MapDeleteBatch(&attr); err != nil {
   1026 		return int(attr.Count), fmt.Errorf("batch delete: %w", wrapMapError(err))
   1027 	}
   1028 
   1029 	return int(attr.Count), nil
   1030 }
   1031 
   1032 // Iterate traverses a map.
   1033 //
   1034 // It's safe to create multiple iterators at the same time.
   1035 //
   1036 // It's not possible to guarantee that all keys in a map will be
   1037 // returned if there are concurrent modifications to the map.
   1038 func (m *Map) Iterate() *MapIterator {
   1039 	return newMapIterator(m)
   1040 }
   1041 
   1042 // Close the Map's underlying file descriptor, which could unload the
   1043 // Map from the kernel if it is not pinned or in use by a loaded Program.
   1044 func (m *Map) Close() error {
   1045 	if m == nil {
   1046 		// This makes it easier to clean up when iterating maps
   1047 		// of maps / programs.
   1048 		return nil
   1049 	}
   1050 
   1051 	return m.fd.Close()
   1052 }
   1053 
   1054 // FD gets the file descriptor of the Map.
   1055 //
   1056 // Calling this function is invalid after Close has been called.
   1057 func (m *Map) FD() int {
   1058 	return m.fd.Int()
   1059 }
   1060 
   1061 // Clone creates a duplicate of the Map.
   1062 //
   1063 // Closing the duplicate does not affect the original, and vice versa.
   1064 // Changes made to the map are reflected by both instances however.
   1065 // If the original map was pinned, the cloned map will not be pinned by default.
   1066 //
   1067 // Cloning a nil Map returns nil.
   1068 func (m *Map) Clone() (*Map, error) {
   1069 	if m == nil {
   1070 		return nil, nil
   1071 	}
   1072 
   1073 	dup, err := m.fd.Dup()
   1074 	if err != nil {
   1075 		return nil, fmt.Errorf("can't clone map: %w", err)
   1076 	}
   1077 
   1078 	return &Map{
   1079 		m.name,
   1080 		dup,
   1081 		m.typ,
   1082 		m.keySize,
   1083 		m.valueSize,
   1084 		m.maxEntries,
   1085 		m.flags,
   1086 		"",
   1087 		m.fullValueSize,
   1088 	}, nil
   1089 }
   1090 
   1091 // Pin persists the map on the BPF virtual file system past the lifetime of
   1092 // the process that created it .
   1093 //
   1094 // Calling Pin on a previously pinned map will overwrite the path, except when
   1095 // the new path already exists. Re-pinning across filesystems is not supported.
   1096 // You can Clone a map to pin it to a different path.
   1097 //
   1098 // This requires bpffs to be mounted above fileName. See https://docs.cilium.io/en/k8s-doc/admin/#admin-mount-bpffs
   1099 func (m *Map) Pin(fileName string) error {
   1100 	if err := internal.Pin(m.pinnedPath, fileName, m.fd); err != nil {
   1101 		return err
   1102 	}
   1103 	m.pinnedPath = fileName
   1104 	return nil
   1105 }
   1106 
   1107 // Unpin removes the persisted state for the map from the BPF virtual filesystem.
   1108 //
   1109 // Failed calls to Unpin will not alter the state returned by IsPinned.
   1110 //
   1111 // Unpinning an unpinned Map returns nil.
   1112 func (m *Map) Unpin() error {
   1113 	if err := internal.Unpin(m.pinnedPath); err != nil {
   1114 		return err
   1115 	}
   1116 	m.pinnedPath = ""
   1117 	return nil
   1118 }
   1119 
   1120 // IsPinned returns true if the map has a non-empty pinned path.
   1121 func (m *Map) IsPinned() bool {
   1122 	return m.pinnedPath != ""
   1123 }
   1124 
   1125 // Freeze prevents a map to be modified from user space.
   1126 //
   1127 // It makes no changes to kernel-side restrictions.
   1128 func (m *Map) Freeze() error {
   1129 	if err := haveMapMutabilityModifiers(); err != nil {
   1130 		return fmt.Errorf("can't freeze map: %w", err)
   1131 	}
   1132 
   1133 	attr := sys.MapFreezeAttr{
   1134 		MapFd: m.fd.Uint(),
   1135 	}
   1136 
   1137 	if err := sys.MapFreeze(&attr); err != nil {
   1138 		return fmt.Errorf("can't freeze map: %w", err)
   1139 	}
   1140 	return nil
   1141 }
   1142 
   1143 // finalize populates the Map according to the Contents specified
   1144 // in spec and freezes the Map if requested by spec.
   1145 func (m *Map) finalize(spec *MapSpec) error {
   1146 	for _, kv := range spec.Contents {
   1147 		if err := m.Put(kv.Key, kv.Value); err != nil {
   1148 			return fmt.Errorf("putting value: key %v: %w", kv.Key, err)
   1149 		}
   1150 	}
   1151 
   1152 	if spec.Freeze {
   1153 		if err := m.Freeze(); err != nil {
   1154 			return fmt.Errorf("freezing map: %w", err)
   1155 		}
   1156 	}
   1157 
   1158 	return nil
   1159 }
   1160 
   1161 func (m *Map) marshalKey(data interface{}) (sys.Pointer, error) {
   1162 	if data == nil {
   1163 		if m.keySize == 0 {
   1164 			// Queues have a key length of zero, so passing nil here is valid.
   1165 			return sys.NewPointer(nil), nil
   1166 		}
   1167 		return sys.Pointer{}, errors.New("can't use nil as key of map")
   1168 	}
   1169 
   1170 	return marshalPtr(data, int(m.keySize))
   1171 }
   1172 
   1173 func (m *Map) unmarshalKey(data interface{}, buf []byte) error {
   1174 	if buf == nil {
   1175 		// This is from a makeBuffer call, nothing do do here.
   1176 		return nil
   1177 	}
   1178 
   1179 	return unmarshalBytes(data, buf)
   1180 }
   1181 
   1182 func (m *Map) marshalValue(data interface{}) (sys.Pointer, error) {
   1183 	if m.typ.hasPerCPUValue() {
   1184 		return marshalPerCPUValue(data, int(m.valueSize))
   1185 	}
   1186 
   1187 	var (
   1188 		buf []byte
   1189 		err error
   1190 	)
   1191 
   1192 	switch value := data.(type) {
   1193 	case *Map:
   1194 		if !m.typ.canStoreMap() {
   1195 			return sys.Pointer{}, fmt.Errorf("can't store map in %s", m.typ)
   1196 		}
   1197 		buf, err = marshalMap(value, int(m.valueSize))
   1198 
   1199 	case *Program:
   1200 		if !m.typ.canStoreProgram() {
   1201 			return sys.Pointer{}, fmt.Errorf("can't store program in %s", m.typ)
   1202 		}
   1203 		buf, err = marshalProgram(value, int(m.valueSize))
   1204 
   1205 	default:
   1206 		return marshalPtr(data, int(m.valueSize))
   1207 	}
   1208 
   1209 	if err != nil {
   1210 		return sys.Pointer{}, err
   1211 	}
   1212 
   1213 	return sys.NewSlicePointer(buf), nil
   1214 }
   1215 
   1216 func (m *Map) unmarshalValue(value interface{}, buf []byte) error {
   1217 	if buf == nil {
   1218 		// This is from a makeBuffer call, nothing do do here.
   1219 		return nil
   1220 	}
   1221 
   1222 	if m.typ.hasPerCPUValue() {
   1223 		return unmarshalPerCPUValue(value, int(m.valueSize), buf)
   1224 	}
   1225 
   1226 	switch value := value.(type) {
   1227 	case **Map:
   1228 		if !m.typ.canStoreMap() {
   1229 			return fmt.Errorf("can't read a map from %s", m.typ)
   1230 		}
   1231 
   1232 		other, err := unmarshalMap(buf)
   1233 		if err != nil {
   1234 			return err
   1235 		}
   1236 
   1237 		// The caller might close the map externally, so ignore errors.
   1238 		_ = (*value).Close()
   1239 
   1240 		*value = other
   1241 		return nil
   1242 
   1243 	case *Map:
   1244 		if !m.typ.canStoreMap() {
   1245 			return fmt.Errorf("can't read a map from %s", m.typ)
   1246 		}
   1247 		return errors.New("require pointer to *Map")
   1248 
   1249 	case **Program:
   1250 		if !m.typ.canStoreProgram() {
   1251 			return fmt.Errorf("can't read a program from %s", m.typ)
   1252 		}
   1253 
   1254 		other, err := unmarshalProgram(buf)
   1255 		if err != nil {
   1256 			return err
   1257 		}
   1258 
   1259 		// The caller might close the program externally, so ignore errors.
   1260 		_ = (*value).Close()
   1261 
   1262 		*value = other
   1263 		return nil
   1264 
   1265 	case *Program:
   1266 		if !m.typ.canStoreProgram() {
   1267 			return fmt.Errorf("can't read a program from %s", m.typ)
   1268 		}
   1269 		return errors.New("require pointer to *Program")
   1270 	}
   1271 
   1272 	return unmarshalBytes(value, buf)
   1273 }
   1274 
   1275 // LoadPinnedMap loads a Map from a BPF file.
   1276 func LoadPinnedMap(fileName string, opts *LoadPinOptions) (*Map, error) {
   1277 	fd, err := sys.ObjGet(&sys.ObjGetAttr{
   1278 		Pathname:  sys.NewStringPointer(fileName),
   1279 		FileFlags: opts.Marshal(),
   1280 	})
   1281 	if err != nil {
   1282 		return nil, err
   1283 	}
   1284 
   1285 	m, err := newMapFromFD(fd)
   1286 	if err == nil {
   1287 		m.pinnedPath = fileName
   1288 	}
   1289 
   1290 	return m, err
   1291 }
   1292 
   1293 // unmarshalMap creates a map from a map ID encoded in host endianness.
   1294 func unmarshalMap(buf []byte) (*Map, error) {
   1295 	if len(buf) != 4 {
   1296 		return nil, errors.New("map id requires 4 byte value")
   1297 	}
   1298 
   1299 	id := internal.NativeEndian.Uint32(buf)
   1300 	return NewMapFromID(MapID(id))
   1301 }
   1302 
   1303 // marshalMap marshals the fd of a map into a buffer in host endianness.
   1304 func marshalMap(m *Map, length int) ([]byte, error) {
   1305 	if length != 4 {
   1306 		return nil, fmt.Errorf("can't marshal map to %d bytes", length)
   1307 	}
   1308 
   1309 	buf := make([]byte, 4)
   1310 	internal.NativeEndian.PutUint32(buf, m.fd.Uint())
   1311 	return buf, nil
   1312 }
   1313 
   1314 // MapIterator iterates a Map.
   1315 //
   1316 // See Map.Iterate.
   1317 type MapIterator struct {
   1318 	target            *Map
   1319 	prevKey           interface{}
   1320 	prevBytes         []byte
   1321 	count, maxEntries uint32
   1322 	done              bool
   1323 	err               error
   1324 }
   1325 
   1326 func newMapIterator(target *Map) *MapIterator {
   1327 	return &MapIterator{
   1328 		target:     target,
   1329 		maxEntries: target.maxEntries,
   1330 		prevBytes:  make([]byte, target.keySize),
   1331 	}
   1332 }
   1333 
   1334 // Next decodes the next key and value.
   1335 //
   1336 // Iterating a hash map from which keys are being deleted is not
   1337 // safe. You may see the same key multiple times. Iteration may
   1338 // also abort with an error, see IsIterationAborted.
   1339 //
   1340 // Returns false if there are no more entries. You must check
   1341 // the result of Err afterwards.
   1342 //
   1343 // See Map.Get for further caveats around valueOut.
   1344 func (mi *MapIterator) Next(keyOut, valueOut interface{}) bool {
   1345 	if mi.err != nil || mi.done {
   1346 		return false
   1347 	}
   1348 
   1349 	// For array-like maps NextKeyBytes returns nil only on after maxEntries
   1350 	// iterations.
   1351 	for mi.count <= mi.maxEntries {
   1352 		var nextBytes []byte
   1353 		nextBytes, mi.err = mi.target.NextKeyBytes(mi.prevKey)
   1354 		if mi.err != nil {
   1355 			return false
   1356 		}
   1357 
   1358 		if nextBytes == nil {
   1359 			mi.done = true
   1360 			return false
   1361 		}
   1362 
   1363 		// The user can get access to nextBytes since unmarshalBytes
   1364 		// does not copy when unmarshaling into a []byte.
   1365 		// Make a copy to prevent accidental corruption of
   1366 		// iterator state.
   1367 		copy(mi.prevBytes, nextBytes)
   1368 		mi.prevKey = mi.prevBytes
   1369 
   1370 		mi.count++
   1371 		mi.err = mi.target.Lookup(nextBytes, valueOut)
   1372 		if errors.Is(mi.err, ErrKeyNotExist) {
   1373 			// Even though the key should be valid, we couldn't look up
   1374 			// its value. If we're iterating a hash map this is probably
   1375 			// because a concurrent delete removed the value before we
   1376 			// could get it. This means that the next call to NextKeyBytes
   1377 			// is very likely to restart iteration.
   1378 			// If we're iterating one of the fd maps like
   1379 			// ProgramArray it means that a given slot doesn't have
   1380 			// a valid fd associated. It's OK to continue to the next slot.
   1381 			continue
   1382 		}
   1383 		if mi.err != nil {
   1384 			return false
   1385 		}
   1386 
   1387 		mi.err = mi.target.unmarshalKey(keyOut, nextBytes)
   1388 		return mi.err == nil
   1389 	}
   1390 
   1391 	mi.err = fmt.Errorf("%w", ErrIterationAborted)
   1392 	return false
   1393 }
   1394 
   1395 // Err returns any encountered error.
   1396 //
   1397 // The method must be called after Next returns nil.
   1398 //
   1399 // Returns ErrIterationAborted if it wasn't possible to do a full iteration.
   1400 func (mi *MapIterator) Err() error {
   1401 	return mi.err
   1402 }
   1403 
   1404 // MapGetNextID returns the ID of the next eBPF map.
   1405 //
   1406 // Returns ErrNotExist, if there is no next eBPF map.
   1407 func MapGetNextID(startID MapID) (MapID, error) {
   1408 	attr := &sys.MapGetNextIdAttr{Id: uint32(startID)}
   1409 	return MapID(attr.NextId), sys.MapGetNextId(attr)
   1410 }
   1411 
   1412 // NewMapFromID returns the map for a given id.
   1413 //
   1414 // Returns ErrNotExist, if there is no eBPF map with the given id.
   1415 func NewMapFromID(id MapID) (*Map, error) {
   1416 	fd, err := sys.MapGetFdById(&sys.MapGetFdByIdAttr{
   1417 		Id: uint32(id),
   1418 	})
   1419 	if err != nil {
   1420 		return nil, err
   1421 	}
   1422 
   1423 	return newMapFromFD(fd)
   1424 }