Commit 8b910d7a authored by mbaxter's avatar mbaxter Committed by GitHub

cannon: Refactor instrumented_state.go to extract reusable helpers (#11174)

* cannon: Extract TrackingOracle to allow reuse

* cannon: Extract PreimageReader logic for easier reuse

* cannon: Merge preimage-related tracking and access logic

* cannon: Extract memTracker logic for easier reuse

* cannon: Extract stack tracking logic for easier reuse

* cannon: Break up StackTracker into noop and regular impls

* cannon: Clean up PreimageReader
parent 26eac671
package exec
import (
"fmt"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
)
type MemTracker interface {
TrackMemAccess(addr uint32)
}
type MemoryTrackerImpl struct {
memory *memory.Memory
lastMemAccess uint32
memProofEnabled bool
memProof [memory.MEM_PROOF_SIZE]byte
}
func NewMemoryTracker(memory *memory.Memory) *MemoryTrackerImpl {
return &MemoryTrackerImpl{memory: memory}
}
func (m *MemoryTrackerImpl) TrackMemAccess(effAddr uint32) {
if m.memProofEnabled && m.lastMemAccess != effAddr {
if m.lastMemAccess != ^uint32(0) {
panic(fmt.Errorf("unexpected different mem access at %08x, already have access at %08x buffered", effAddr, m.lastMemAccess))
}
m.lastMemAccess = effAddr
m.memProof = m.memory.MerkleProof(effAddr)
}
}
func (m *MemoryTrackerImpl) Reset(enableProof bool) {
m.memProofEnabled = enableProof
m.lastMemAccess = ^uint32(0)
}
func (m *MemoryTrackerImpl) MemProof() [memory.MEM_PROOF_SIZE]byte {
return m.memProof
}
...@@ -5,11 +5,6 @@ import ( ...@@ -5,11 +5,6 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm/memory" "github.com/ethereum-optimism/optimism/cannon/mipsevm/memory"
) )
type StackTracker interface {
PushStack(target uint32)
PopStack()
}
func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun uint32) { func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun uint32) {
insn = memory.GetMemory(pc) insn = memory.GetMemory(pc)
opcode = insn >> 26 // First 6-bits opcode = insn >> 26 // First 6-bits
...@@ -18,7 +13,7 @@ func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun ...@@ -18,7 +13,7 @@ func GetInstructionDetails(pc uint32, memory *memory.Memory) (insn, opcode, fun
return insn, opcode, fun return insn, opcode, fun
} }
func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memory *memory.Memory, insn, opcode, fun uint32, memTracker memory.MemTracker, stackTracker StackTracker) error { func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memory *memory.Memory, insn, opcode, fun uint32, memTracker MemTracker, stackTracker StackTracker) error {
// j-type j/jal // j-type j/jal
if opcode == 2 || opcode == 3 { if opcode == 2 || opcode == 3 {
linkReg := uint32(0) linkReg := uint32(0)
...@@ -73,7 +68,7 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor ...@@ -73,7 +68,7 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor
// M[R[rs]+SignExtImm] // M[R[rs]+SignExtImm]
rs += SignExtend(insn&0xFFFF, 16) rs += SignExtend(insn&0xFFFF, 16)
addr := rs & 0xFFFFFFFC addr := rs & 0xFFFFFFFC
memTracker(addr) memTracker.TrackMemAccess(addr)
mem = memory.GetMemory(addr) mem = memory.GetMemory(addr)
if opcode >= 0x28 && opcode != 0x30 { if opcode >= 0x28 && opcode != 0x30 {
// store // store
...@@ -117,7 +112,7 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor ...@@ -117,7 +112,7 @@ func ExecMipsCoreStepLogic(cpu *mipsevm.CpuScalars, registers *[32]uint32, memor
// write memory // write memory
if storeAddr != 0xFF_FF_FF_FF { if storeAddr != 0xFF_FF_FF_FF {
memTracker(storeAddr) memTracker.TrackMemAccess(storeAddr)
memory.SetMemory(storeAddr, val) memory.SetMemory(storeAddr, val)
} }
......
...@@ -36,8 +36,6 @@ const ( ...@@ -36,8 +36,6 @@ const (
MipsEINVAL = 0x16 MipsEINVAL = 0x16
) )
type PreimageReader func(key [32]byte, offset uint32) (dat [32]byte, datLen uint32)
func GetSyscallArgs(registers *[32]uint32) (syscallNum, a0, a1, a2 uint32) { func GetSyscallArgs(registers *[32]uint32) (syscallNum, a0, a1, a2 uint32) {
syscallNum = registers[2] // v0 syscallNum = registers[2] // v0
...@@ -68,7 +66,7 @@ func HandleSysMmap(a0, a1, heap uint32) (v0, v1, newHeap uint32) { ...@@ -68,7 +66,7 @@ func HandleSysMmap(a0, a1, heap uint32) (v0, v1, newHeap uint32) {
return v0, v1, newHeap return v0, v1, newHeap
} }
func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *memory.Memory, memTracker memory.MemTracker) (v0, v1, newPreimageOffset uint32) { func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint32, preimageReader PreimageReader, memory *memory.Memory, memTracker MemTracker) (v0, v1, newPreimageOffset uint32) {
// args: a0 = fd, a1 = addr, a2 = count // args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = read, v1 = err code // returns: v0 = read, v1 = err code
v0 = uint32(0) v0 = uint32(0)
...@@ -80,9 +78,9 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3 ...@@ -80,9 +78,9 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3
// leave v0 and v1 zero: read nothing, no error // leave v0 and v1 zero: read nothing, no error
case FdPreimageRead: // pre-image oracle case FdPreimageRead: // pre-image oracle
effAddr := a1 & 0xFFffFFfc effAddr := a1 & 0xFFffFFfc
memTracker(effAddr) memTracker.TrackMemAccess(effAddr)
mem := memory.GetMemory(effAddr) mem := memory.GetMemory(effAddr)
dat, datLen := preimageReader(preimageKey, preimageOffset) dat, datLen := preimageReader.ReadPreimage(preimageKey, preimageOffset)
//fmt.Printf("reading pre-image data: addr: %08x, offset: %d, datLen: %d, data: %x, key: %s count: %d\n", a1, m.state.PreimageOffset, datLen, dat[:datLen], m.state.PreimageKey, a2) //fmt.Printf("reading pre-image data: addr: %08x, offset: %d, datLen: %d, data: %x, key: %s count: %d\n", a1, m.state.PreimageOffset, datLen, dat[:datLen], m.state.PreimageKey, a2)
alignment := a1 & 3 alignment := a1 & 3
space := 4 - alignment space := 4 - alignment
...@@ -110,7 +108,7 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3 ...@@ -110,7 +108,7 @@ func HandleSysRead(a0, a1, a2 uint32, preimageKey [32]byte, preimageOffset uint3
return v0, v1, newPreimageOffset return v0, v1, newPreimageOffset
} }
func HandleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]byte, preimageOffset uint32, oracle mipsevm.PreimageOracle, memory *memory.Memory, memTracker memory.MemTracker, stdOut, stdErr io.Writer) (v0, v1 uint32, newLastHint hexutil.Bytes, newPreimageKey common.Hash, newPreimageOffset uint32) { func HandleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]byte, preimageOffset uint32, oracle mipsevm.PreimageOracle, memory *memory.Memory, memTracker MemTracker, stdOut, stdErr io.Writer) (v0, v1 uint32, newLastHint hexutil.Bytes, newPreimageKey common.Hash, newPreimageOffset uint32) {
// args: a0 = fd, a1 = addr, a2 = count // args: a0 = fd, a1 = addr, a2 = count
// returns: v0 = written, v1 = err code // returns: v0 = written, v1 = err code
v1 = uint32(0) v1 = uint32(0)
...@@ -142,7 +140,7 @@ func HandleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]b ...@@ -142,7 +140,7 @@ func HandleSysWrite(a0, a1, a2 uint32, lastHint hexutil.Bytes, preimageKey [32]b
v0 = a2 v0 = a2
case FdPreimageWrite: case FdPreimageWrite:
effAddr := a1 & 0xFFffFFfc effAddr := a1 & 0xFFffFFfc
memTracker(effAddr) memTracker.TrackMemAccess(effAddr)
mem := memory.GetMemory(effAddr) mem := memory.GetMemory(effAddr)
key := preimageKey key := preimageKey
alignment := a1 & 3 alignment := a1 & 3
......
package exec
import (
"encoding/binary"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
)
type PreimageReader interface {
ReadPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32)
}
// TrackingPreimageOracleReader wraps around a PreimageOracle, implements the PreimageOracle interface, and adds tracking functionality.
// It also implements the PreimageReader interface
type TrackingPreimageOracleReader struct {
po mipsevm.PreimageOracle
totalPreimageSize int
numPreimageRequests int
// cached pre-image data, including 8 byte length prefix
lastPreimage []byte
// key for above preimage
lastPreimageKey [32]byte
// offset we last read from, or max uint32 if nothing is read this step
lastPreimageOffset uint32
}
func NewTrackingPreimageOracleReader(po mipsevm.PreimageOracle) *TrackingPreimageOracleReader {
return &TrackingPreimageOracleReader{po: po}
}
func (p *TrackingPreimageOracleReader) Reset() {
p.lastPreimageOffset = ^uint32(0)
}
func (p *TrackingPreimageOracleReader) Hint(v []byte) {
p.po.Hint(v)
}
func (p *TrackingPreimageOracleReader) GetPreimage(k [32]byte) []byte {
p.numPreimageRequests++
preimage := p.po.GetPreimage(k)
p.totalPreimageSize += len(preimage)
return preimage
}
func (p *TrackingPreimageOracleReader) ReadPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) {
preimage := p.lastPreimage
if key != p.lastPreimageKey {
p.lastPreimageKey = key
data := p.po.GetPreimage(key)
// add the length prefix
preimage = make([]byte, 0, 8+len(data))
preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(data)))
preimage = append(preimage, data...)
p.lastPreimage = preimage
}
p.lastPreimageOffset = offset
datLen = uint32(copy(dat[:], preimage[offset:]))
return
}
func (p *TrackingPreimageOracleReader) LastPreimage() ([32]byte, []byte, uint32) {
return p.lastPreimageKey, p.lastPreimage, p.lastPreimageOffset
}
func (p *TrackingPreimageOracleReader) TotalPreimageSize() int {
return p.totalPreimageSize
}
func (p *TrackingPreimageOracleReader) NumPreimageRequests() int {
return p.numPreimageRequests
}
package exec
import (
"errors"
"fmt"
"github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
)
type StackTracker interface {
PushStack(target uint32)
PopStack()
}
type TraceableStackTracker interface {
StackTracker
Traceback()
}
type NoopStackTracker struct{}
func (n *NoopStackTracker) PushStack(target uint32) {}
func (n *NoopStackTracker) PopStack() {}
func (n *NoopStackTracker) Traceback() {}
type StackTrackerImpl struct {
state mipsevm.FPVMState
stack []uint32
caller []uint32
meta *program.Metadata
}
func NewStackTracker(state mipsevm.FPVMState, meta *program.Metadata) (*StackTrackerImpl, error) {
if meta == nil {
return nil, errors.New("metadata is nil")
}
return &StackTrackerImpl{state: state}, nil
}
func (s *StackTrackerImpl) PushStack(target uint32) {
s.stack = append(s.stack, target)
s.caller = append(s.caller, s.state.GetPC())
}
func (s *StackTrackerImpl) PopStack() {
if len(s.stack) != 0 {
fn := s.meta.LookupSymbol(s.state.GetPC())
topFn := s.meta.LookupSymbol(s.stack[len(s.stack)-1])
if fn != topFn {
// most likely the function was inlined. Snap back to the last return.
i := len(s.stack) - 1
for ; i >= 0; i-- {
if s.meta.LookupSymbol(s.stack[i]) == fn {
s.stack = s.stack[:i]
s.caller = s.caller[:i]
break
}
}
} else {
s.stack = s.stack[:len(s.stack)-1]
s.caller = s.caller[:len(s.caller)-1]
}
} else {
fmt.Printf("ERROR: stack underflow at pc=%x. step=%d\n", s.state.GetPC(), s.state.GetStep())
}
}
func (s *StackTrackerImpl) Traceback() {
fmt.Printf("traceback at pc=%x. step=%d\n", s.state.GetPC(), s.state.GetStep())
for i := len(s.stack) - 1; i >= 0; i-- {
jumpAddr := s.stack[i]
idx := len(s.stack) - i - 1
fmt.Printf("\t%d %x in %s caller=%08x\n", idx, jumpAddr, s.meta.LookupSymbol(jumpAddr), s.caller[i])
}
}
...@@ -21,6 +21,8 @@ const ( ...@@ -21,6 +21,8 @@ const (
PageKeyMask = MaxPageCount - 1 PageKeyMask = MaxPageCount - 1
) )
const MEM_PROOF_SIZE = 28 * 32
func HashPair(left, right [32]byte) [32]byte { func HashPair(left, right [32]byte) [32]byte {
out := crypto.Keccak256Hash(left[:], right[:]) out := crypto.Keccak256Hash(left[:], right[:])
//fmt.Printf("0x%x 0x%x -> 0x%x\n", left, right, out) //fmt.Printf("0x%x 0x%x -> 0x%x\n", left, right, out)
...@@ -129,7 +131,7 @@ func (m *Memory) MerkleizeSubtree(gindex uint64) [32]byte { ...@@ -129,7 +131,7 @@ func (m *Memory) MerkleizeSubtree(gindex uint64) [32]byte {
return r return r
} }
func (m *Memory) MerkleProof(addr uint32) (out [28 * 32]byte) { func (m *Memory) MerkleProof(addr uint32) (out [MEM_PROOF_SIZE]byte) {
proof := m.traverseBranch(1, addr, 0) proof := m.traverseBranch(1, addr, 0)
// encode the proof // encode the proof
for i := 0; i < 28; i++ { for i := 0; i < 28; i++ {
...@@ -335,5 +337,3 @@ func (m *Memory) Usage() string { ...@@ -335,5 +337,3 @@ func (m *Memory) Usage() string {
// KiB, MiB, GiB, TiB, ... // KiB, MiB, GiB, TiB, ...
return fmt.Sprintf("%.1f %ciB", float64(total)/float64(div), "KMGTPE"[exp]) return fmt.Sprintf("%.1f %ciB", float64(total)/float64(div), "KMGTPE"[exp])
} }
type MemTracker func(addr uint32)
package singlethreaded package singlethreaded
import ( import (
"errors"
"io" "io"
"github.com/ethereum-optimism/optimism/cannon/mipsevm" "github.com/ethereum-optimism/optimism/cannon/mipsevm"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/exec"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program" "github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
"github.com/ethereum-optimism/optimism/op-service/jsonutil" "github.com/ethereum-optimism/optimism/op-service/jsonutil"
) )
type Debug struct {
stack []uint32
caller []uint32
meta *program.Metadata
}
type InstrumentedState struct { type InstrumentedState struct {
state *State state *State
stdOut io.Writer stdOut io.Writer
stdErr io.Writer stdErr io.Writer
lastMemAccess uint32 memoryTracker *exec.MemoryTrackerImpl
memProofEnabled bool stackTracker exec.TraceableStackTracker
memProof [28 * 32]byte
preimageOracle *trackingOracle
// cached pre-image data, including 8 byte length prefix
lastPreimage []byte
// key for above preimage
lastPreimageKey [32]byte
// offset we last read from, or max uint32 if nothing is read this step
lastPreimageOffset uint32
debug Debug preimageOracle *exec.TrackingPreimageOracleReader
debugEnabled bool
} }
func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState { func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer) *InstrumentedState {
...@@ -43,7 +26,9 @@ func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdEr ...@@ -43,7 +26,9 @@ func NewInstrumentedState(state *State, po mipsevm.PreimageOracle, stdOut, stdEr
state: state, state: state,
stdOut: stdOut, stdOut: stdOut,
stdErr: stdErr, stdErr: stdErr,
preimageOracle: &trackingOracle{po: po}, memoryTracker: exec.NewMemoryTracker(state.Memory),
stackTracker: &exec.NoopStackTracker{},
preimageOracle: exec.NewTrackingPreimageOracleReader(po),
} }
} }
...@@ -52,27 +37,21 @@ func NewInstrumentedStateFromFile(stateFile string, po mipsevm.PreimageOracle, s ...@@ -52,27 +37,21 @@ func NewInstrumentedStateFromFile(stateFile string, po mipsevm.PreimageOracle, s
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &InstrumentedState{ return NewInstrumentedState(state, po, stdOut, stdErr), nil
state: state,
stdOut: stdOut,
stdErr: stdErr,
preimageOracle: &trackingOracle{po: po},
}, nil
} }
func (m *InstrumentedState) InitDebug(meta *program.Metadata) error { func (m *InstrumentedState) InitDebug(meta *program.Metadata) error {
if meta == nil { stackTracker, err := exec.NewStackTracker(m.state, meta)
return errors.New("metadata is nil") if err != nil {
return err
} }
m.debugEnabled = true m.stackTracker = stackTracker
m.debug.meta = meta
return nil return nil
} }
func (m *InstrumentedState) Step(proof bool) (wit *mipsevm.StepWitness, err error) { func (m *InstrumentedState) Step(proof bool) (wit *mipsevm.StepWitness, err error) {
m.memProofEnabled = proof m.preimageOracle.Reset()
m.lastMemAccess = ^uint32(0) m.memoryTracker.Reset(proof)
m.lastPreimageOffset = ^uint32(0)
if proof { if proof {
insnProof := m.state.Memory.MerkleProof(m.state.Cpu.PC) insnProof := m.state.Memory.MerkleProof(m.state.Cpu.PC)
...@@ -89,18 +68,20 @@ func (m *InstrumentedState) Step(proof bool) (wit *mipsevm.StepWitness, err erro ...@@ -89,18 +68,20 @@ func (m *InstrumentedState) Step(proof bool) (wit *mipsevm.StepWitness, err erro
} }
if proof { if proof {
wit.ProofData = append(wit.ProofData, m.memProof[:]...) memProof := m.memoryTracker.MemProof()
if m.lastPreimageOffset != ^uint32(0) { wit.ProofData = append(wit.ProofData, memProof[:]...)
wit.PreimageOffset = m.lastPreimageOffset lastPreimageKey, lastPreimage, lastPreimageOffset := m.preimageOracle.LastPreimage()
wit.PreimageKey = m.lastPreimageKey if lastPreimageOffset != ^uint32(0) {
wit.PreimageValue = m.lastPreimage wit.PreimageOffset = lastPreimageOffset
wit.PreimageKey = lastPreimageKey
wit.PreimageValue = lastPreimage
} }
} }
return return
} }
func (m *InstrumentedState) LastPreimage() ([32]byte, []byte, uint32) { func (m *InstrumentedState) LastPreimage() ([32]byte, []byte, uint32) {
return m.lastPreimageKey, m.lastPreimage, m.lastPreimageOffset return m.preimageOracle.LastPreimage()
} }
func (m *InstrumentedState) GetState() mipsevm.FPVMState { func (m *InstrumentedState) GetState() mipsevm.FPVMState {
...@@ -110,24 +91,11 @@ func (m *InstrumentedState) GetState() mipsevm.FPVMState { ...@@ -110,24 +91,11 @@ func (m *InstrumentedState) GetState() mipsevm.FPVMState {
func (m *InstrumentedState) GetDebugInfo() *mipsevm.DebugInfo { func (m *InstrumentedState) GetDebugInfo() *mipsevm.DebugInfo {
return &mipsevm.DebugInfo{ return &mipsevm.DebugInfo{
Pages: m.state.Memory.PageCount(), Pages: m.state.Memory.PageCount(),
NumPreimageRequests: m.preimageOracle.numPreimageRequests, NumPreimageRequests: m.preimageOracle.NumPreimageRequests(),
TotalPreimageSize: m.preimageOracle.totalPreimageSize, TotalPreimageSize: m.preimageOracle.TotalPreimageSize(),
} }
} }
type trackingOracle struct { func (m *InstrumentedState) Traceback() {
po mipsevm.PreimageOracle m.stackTracker.Traceback()
totalPreimageSize int
numPreimageRequests int
}
func (d *trackingOracle) Hint(v []byte) {
d.po.Hint(v)
}
func (d *trackingOracle) GetPreimage(k [32]byte) []byte {
d.numPreimageRequests++
preimage := d.po.GetPreimage(k)
d.totalPreimageSize += len(preimage)
return preimage
} }
package singlethreaded package singlethreaded
import ( import (
"encoding/binary"
"fmt"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum-optimism/optimism/cannon/mipsevm/exec" "github.com/ethereum-optimism/optimism/cannon/mipsevm/exec"
) )
func (m *InstrumentedState) readPreimage(key [32]byte, offset uint32) (dat [32]byte, datLen uint32) {
preimage := m.lastPreimage
if key != m.lastPreimageKey {
m.lastPreimageKey = key
data := m.preimageOracle.GetPreimage(key)
// add the length prefix
preimage = make([]byte, 0, 8+len(data))
preimage = binary.BigEndian.AppendUint64(preimage, uint64(len(data)))
preimage = append(preimage, data...)
m.lastPreimage = preimage
}
m.lastPreimageOffset = offset
datLen = uint32(copy(dat[:], preimage[offset:]))
return
}
func (m *InstrumentedState) trackMemAccess(effAddr uint32) {
if m.memProofEnabled && m.lastMemAccess != effAddr {
if m.lastMemAccess != ^uint32(0) {
panic(fmt.Errorf("unexpected different mem access at %08x, already have access at %08x buffered", effAddr, m.lastMemAccess))
}
m.lastMemAccess = effAddr
m.memProof = m.state.Memory.MerkleProof(effAddr)
}
}
func (m *InstrumentedState) handleSyscall() error { func (m *InstrumentedState) handleSyscall() error {
syscallNum, a0, a1, a2 := exec.GetSyscallArgs(&m.state.Registers) syscallNum, a0, a1, a2 := exec.GetSyscallArgs(&m.state.Registers)
...@@ -58,13 +29,13 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -58,13 +29,13 @@ func (m *InstrumentedState) handleSyscall() error {
return nil return nil
case exec.SysRead: case exec.SysRead:
var newPreimageOffset uint32 var newPreimageOffset uint32
v0, v1, newPreimageOffset = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.readPreimage, m.state.Memory, m.trackMemAccess) v0, v1, newPreimageOffset = exec.HandleSysRead(a0, a1, a2, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker)
m.state.PreimageOffset = newPreimageOffset m.state.PreimageOffset = newPreimageOffset
case exec.SysWrite: case exec.SysWrite:
var newLastHint hexutil.Bytes var newLastHint hexutil.Bytes
var newPreimageKey common.Hash var newPreimageKey common.Hash
var newPreimageOffset uint32 var newPreimageOffset uint32
v0, v1, newLastHint, newPreimageKey, newPreimageOffset = exec.HandleSysWrite(a0, a1, a2, m.state.LastHint, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.trackMemAccess, m.stdOut, m.stdErr) v0, v1, newLastHint, newPreimageKey, newPreimageOffset = exec.HandleSysWrite(a0, a1, a2, m.state.LastHint, m.state.PreimageKey, m.state.PreimageOffset, m.preimageOracle, m.state.Memory, m.memoryTracker, m.stdOut, m.stdErr)
m.state.LastHint = newLastHint m.state.LastHint = newLastHint
m.state.PreimageKey = newPreimageKey m.state.PreimageKey = newPreimageKey
m.state.PreimageOffset = newPreimageOffset m.state.PreimageOffset = newPreimageOffset
...@@ -76,49 +47,6 @@ func (m *InstrumentedState) handleSyscall() error { ...@@ -76,49 +47,6 @@ func (m *InstrumentedState) handleSyscall() error {
return nil return nil
} }
func (m *InstrumentedState) PushStack(target uint32) {
if !m.debugEnabled {
return
}
m.debug.stack = append(m.debug.stack, target)
m.debug.caller = append(m.debug.caller, m.state.Cpu.PC)
}
func (m *InstrumentedState) PopStack() {
if !m.debugEnabled {
return
}
if len(m.debug.stack) != 0 {
fn := m.debug.meta.LookupSymbol(m.state.Cpu.PC)
topFn := m.debug.meta.LookupSymbol(m.debug.stack[len(m.debug.stack)-1])
if fn != topFn {
// most likely the function was inlined. Snap back to the last return.
i := len(m.debug.stack) - 1
for ; i >= 0; i-- {
if m.debug.meta.LookupSymbol(m.debug.stack[i]) == fn {
m.debug.stack = m.debug.stack[:i]
m.debug.caller = m.debug.caller[:i]
break
}
}
} else {
m.debug.stack = m.debug.stack[:len(m.debug.stack)-1]
m.debug.caller = m.debug.caller[:len(m.debug.caller)-1]
}
} else {
fmt.Printf("ERROR: stack underflow at pc=%x. step=%d\n", m.state.Cpu.PC, m.state.Step)
}
}
func (m *InstrumentedState) Traceback() {
fmt.Printf("traceback at pc=%x. step=%d\n", m.state.Cpu.PC, m.state.Step)
for i := len(m.debug.stack) - 1; i >= 0; i-- {
s := m.debug.stack[i]
idx := len(m.debug.stack) - i - 1
fmt.Printf("\t%d %x in %s caller=%08x\n", idx, s, m.debug.meta.LookupSymbol(s), m.debug.caller[i])
}
}
func (m *InstrumentedState) mipsStep() error { func (m *InstrumentedState) mipsStep() error {
if m.state.Exited { if m.state.Exited {
return nil return nil
...@@ -134,5 +62,5 @@ func (m *InstrumentedState) mipsStep() error { ...@@ -134,5 +62,5 @@ func (m *InstrumentedState) mipsStep() error {
} }
// Exec the rest of the step logic // Exec the rest of the step logic
return exec.ExecMipsCoreStepLogic(&m.state.Cpu, &m.state.Registers, m.state.Memory, insn, opcode, fun, m.trackMemAccess, m) return exec.ExecMipsCoreStepLogic(&m.state.Cpu, &m.state.Registers, m.state.Memory, insn, opcode, fun, m.memoryTracker, m.stackTracker)
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment