Skip to content

Commit

Permalink
refactor: change memory layout
Browse files Browse the repository at this point in the history
  • Loading branch information
danielvladco committed Oct 29, 2024
1 parent f4dfa9f commit 07f1e72
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 26 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test: build-bandersnatch
.PHONY: integration
## integration: Runs integration tests.
integration:
go test ./tests/... -race -v --tags=integration
go test ./... -race -v --tags=integration

## install-hooks: Install git-hooks from .githooks directory.
.PHONY: install-hooks
Expand Down
21 changes: 11 additions & 10 deletions internal/polkavm/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,21 +130,22 @@ type MemoryMap struct {

func (mm MemoryMap) NewMemory(rwData, roData, argsData []byte) Memory {
m := Memory{
data: make([]byte, 1<<32),
access: []accessRanges{
{mm.ArgsDataAddress, mm.ArgsDataAddress + mm.ArgsDataSize, ReadOnly},
{mm.StackAddressLow, mm.StackAddressLow + mm.StackSize, ReadWrite},
{mm.RWDataAddress, mm.RWDataAddress + mm.RWDataSize, ReadWrite},
{mm.RODataAddress, mm.RODataAddress + mm.RODataSize, ReadOnly},
data: []*memorySegment{
{mm.ArgsDataAddress, mm.ArgsDataAddress + mm.ArgsDataSize, ReadOnly, copySized(argsData, mm.ArgsDataSize)},
{mm.StackAddressLow, mm.StackAddressLow + mm.StackSize, ReadWrite, make([]byte, mm.StackSize)},
{mm.RWDataAddress, mm.RWDataAddress + mm.RWDataSize, ReadWrite, copySized(rwData, mm.RWDataSize)},
{mm.RODataAddress, mm.RODataAddress + mm.RODataSize, ReadOnly, copySized(roData, mm.RODataSize)},
},
}

copy(m.data[mm.RWDataAddress:mm.RWDataAddress+mm.RWDataSize], rwData)
copy(m.data[mm.RODataAddress:mm.RODataAddress+mm.RODataSize], roData)
copy(m.data[mm.ArgsDataAddress:mm.ArgsDataAddress+mm.ArgsDataSize], argsData)
return m
}

func copySized(data []byte, size uint32) []byte {
dst := make([]byte, size)
copy(dst, data)
return dst
}

func AlignToNextPage(pageSize uint, value uint) (uint, error) {
if !(pageSize != 0 && (pageSize&(pageSize-1)) == 0) {
return 0, ErrPageSizeNotPowerOfTwo
Expand Down
2 changes: 1 addition & 1 deletion internal/polkavm/exit_reason.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func (e *ErrPanic) Error() string {
// ErrOutOfGas exhaustion of gas: (∞)
var ErrOutOfGas = fmt.Errorf("out of gas")

// ErrPageFault a page fault (attempt to access some address in RAM which is not accessible). This includes the address at fault. (F)
// ErrPageFault a page fault (attempt to data some address in RAM which is not accessible). This includes the address at fault. (F)
type ErrPageFault struct {
Reason string
Address uint32
Expand Down
41 changes: 27 additions & 14 deletions internal/polkavm/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,53 +13,66 @@ const (

// Memory Equation: 34 (M)
type Memory struct {
data []byte // value V
access []accessRanges // access (A ∈ ⟦{W, R, ∅})
data []*memorySegment // data (V ∈ Y, A ∈ ⟦{W, R, ∅})
}

type accessRanges struct {
type memorySegment struct {
start, end uint32
access MemoryAccess
data []byte
}

// Read reads from the set of readable indices (Vμ)
func (m *Memory) Read(address uint32, data []byte) error {
if _, ok := m.inRange(address); !ok {
memSeg := m.inRange(address)
if data == nil {
return &ErrPageFault{Reason: "address not in a valid range", Address: address}
}
copy(data, m.data[address:address+uint32(len(data))])

offset := int(address - memSeg.start)
offsetEnd := offset + len(data)
if offsetEnd > len(memSeg.data) {
return &ErrPageFault{Reason: "memory exceeds page size, growing memory not supported", Address: address}
}
copy(data, memSeg.data[offset:offsetEnd])
return nil
}

func (m *Memory) inRange(address uint32) (MemoryAccess, bool) {
for _, r := range m.access {
func (m *Memory) inRange(address uint32) *memorySegment {
for _, r := range m.data {
if address >= r.start && address <= r.end {
return r.access, true
return r
}
}
return ReadOnly, false
return nil
}

func (m *Memory) Sbrk(pageSize, heapTop uint32) error {
if heapTop > m.access[2].end {
if heapTop > m.data[2].end {
nextPage, err := AlignToNextPage(uint(pageSize), uint(heapTop))
if err != nil {
return err
}

m.access[2].end += uint32(nextPage)
m.data[2].end += uint32(nextPage)
}
return nil
}

// Write writes to the set of writeable indices (Vμ*)
func (m *Memory) Write(address uint32, data []byte) error {
if access, ok := m.inRange(address); !ok {
memSeg := m.inRange(address)
if memSeg == nil {
return &ErrPageFault{Reason: "address not in a valid range", Address: address}
} else if access == ReadOnly {
} else if memSeg.access == ReadOnly {
return &ErrPageFault{Reason: "memory at address is read only", Address: address}
}
copy(m.data[address:address+uint32(len(data))], data)
offset := int(address - memSeg.start)
offsetEnd := offset + len(data)
if offsetEnd > len(memSeg.data) {
return &ErrPageFault{Reason: "memory exceeds page size, growing memory not supported", Address: address}
}
copy(memSeg.data[offset:offsetEnd], data)
return nil
}

Expand Down

0 comments on commit 07f1e72

Please sign in to comment.