github.com/dylandreimerink/gobpfld@v0.6.1-0.20220205171531-e79c330ad608/emulator/maps_stack.go (about)

     1  package emulator
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/dylandreimerink/gobpfld/ebpf"
     7  )
     8  
     9  type StackMap struct {
    10  	AbstractMap
    11  
    12  	Values []*ByteMemory
    13  }
    14  
    15  func (m *StackMap) Init() error {
    16  	return nil
    17  }
    18  
    19  func (m *StackMap) Keys() []RegisterValue {
    20  	keys := make([]RegisterValue, len(m.Values))
    21  	for i := range keys {
    22  		imm := newIMM(int64(i))
    23  		keys[i] = &MemoryPtr{
    24  			Memory: &ValueMemory{
    25  				MemName: fmt.Sprintf("%s[%d]", m.Name, m.Def.ValueSize),
    26  				Mapping: []RegisterValue{
    27  					imm,
    28  					imm,
    29  					imm,
    30  					imm,
    31  				},
    32  			},
    33  		}
    34  	}
    35  	return keys
    36  }
    37  
    38  func (m *StackMap) Lookup(key RegisterValue) (RegisterValue, error) {
    39  	keyPtr, ok := key.(PointerValue)
    40  	if !ok {
    41  		return nil, errMapKeyNoPtr
    42  	}
    43  
    44  	keyVal, err := keyPtr.Deref(0, ebpf.BPF_W)
    45  	if !ok {
    46  		return nil, fmt.Errorf("key read range: %w", err)
    47  	}
    48  
    49  	keyIndex := int(keyVal.Value())
    50  	if keyIndex < 0 || keyIndex >= len(m.Values) {
    51  		return nil, errMapOutOfMemory
    52  	}
    53  
    54  	// Since the stack grows down(new items at the bottom), index 0 is the last value.
    55  	value := m.Values[len(m.Values)-1-keyIndex]
    56  
    57  	return &MemoryPtr{Memory: value, Offset: 0}, nil
    58  }
    59  
    60  func (m *StackMap) Push(value RegisterValue, size int64) error {
    61  	valuePtr, ok := value.(PointerValue)
    62  	if !ok {
    63  		return errMapValNoPtr
    64  	}
    65  
    66  	valueVal, err := valuePtr.ReadRange(0, int(size))
    67  	if !ok {
    68  		return fmt.Errorf("value read range: %w", err)
    69  	}
    70  
    71  	m.Values = append(m.Values, &ByteMemory{
    72  		MemName: fmt.Sprintf("%s[?]", m.Name),
    73  		Backing: valueVal,
    74  	})
    75  
    76  	return nil
    77  }
    78  
    79  func (m *StackMap) Pop() (RegisterValue, error) {
    80  	if len(m.Values) == 0 {
    81  		return newIMM(0), nil
    82  	}
    83  
    84  	val := m.Values[len(m.Values)-1]
    85  	m.Values = m.Values[:len(m.Values)-1]
    86  
    87  	return &MemoryPtr{
    88  		Memory: val,
    89  	}, nil
    90  }