Commit 6e06fa53 authored by Inphi's avatar Inphi Committed by GitHub

cannon: Enable program VM debugging for tests (#11582)

* cannon: Enable program VM debugging for tests

- Also add a symbol lookup routine to the FPVM interface for
  convenience.

* mbaxter suggestion
parent 8c17425a
......@@ -69,4 +69,8 @@ type FPVM interface {
// GetDebugInfo returns debug information about the VM
GetDebugInfo() *DebugInfo
// LookupSymbol returns the symbol located at the specified address.
// May return an empty string if there's no symbol table available.
LookupSymbol(addr uint32) string
}
......@@ -23,6 +23,7 @@ type InstrumentedState struct {
stackTracker ThreadedStackTracker
preimageOracle *exec.TrackingPreimageOracleReader
meta *program.Metadata
}
var _ mipsevm.FPVM = (*InstrumentedState)(nil)
......@@ -53,6 +54,7 @@ func (m *InstrumentedState) InitDebug(meta *program.Metadata) error {
return err
}
m.stackTracker = stackTracker
m.meta = meta
return nil
}
......@@ -116,3 +118,10 @@ func (m *InstrumentedState) GetDebugInfo() *mipsevm.DebugInfo {
func (m *InstrumentedState) Traceback() {
m.stackTracker.Traceback()
}
func (m *InstrumentedState) LookupSymbol(addr uint32) string {
if m.meta == nil {
return ""
}
return m.meta.LookupSymbol(addr)
}
......@@ -32,7 +32,7 @@ func TestInstrumentedState_Claim(t *testing.T) {
}
func TestInstrumentedState_MultithreadedProgram(t *testing.T) {
state := testutil.LoadELFProgram(t, "../../testdata/example/bin/multithreaded.elf", CreateInitialState, false)
state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/multithreaded.elf", CreateInitialState, false)
oracle := testutil.StaticOracle(t, []byte{})
var stdOutBuf, stdErrBuf bytes.Buffer
......@@ -56,7 +56,7 @@ func TestInstrumentedState_MultithreadedProgram(t *testing.T) {
func TestInstrumentedState_Alloc(t *testing.T) {
t.Skip("TODO(client-pod#906): Currently failing - need to debug.")
state := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false)
state, _ := testutil.LoadELFProgram(t, "../../testdata/example/bin/alloc.elf", CreateInitialState, false)
const numAllocs = 100 // where each alloc is a 32 MiB chunk
oracle := testutil.AllocOracle(t, numAllocs)
......
......@@ -119,3 +119,10 @@ func (m *InstrumentedState) GetDebugInfo() *mipsevm.DebugInfo {
func (m *InstrumentedState) Traceback() {
m.stackTracker.Traceback()
}
func (m *InstrumentedState) LookupSymbol(addr uint32) string {
if m.meta == nil {
return ""
}
return m.meta.LookupSymbol(addr)
}
......@@ -161,13 +161,17 @@ func multiThreadedVmFactory(po mipsevm.PreimageOracle, stdOut, stdErr io.Writer,
type ElfVMFactory func(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM
func singleThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM {
state := testutil.LoadELFProgram(t, elfFile, singlethreaded.CreateInitialState, true)
return singlethreaded.NewInstrumentedState(state, po, stdOut, stdErr, nil)
state, meta := testutil.LoadELFProgram(t, elfFile, singlethreaded.CreateInitialState, true)
fpvm := singlethreaded.NewInstrumentedState(state, po, stdOut, stdErr, meta)
require.NoError(t, fpvm.InitDebug())
return fpvm
}
func multiThreadElfVmFactory(t require.TestingT, elfFile string, po mipsevm.PreimageOracle, stdOut, stdErr io.Writer, log log.Logger) mipsevm.FPVM {
state := testutil.LoadELFProgram(t, elfFile, multithreaded.CreateInitialState, false)
return multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log)
state, meta := testutil.LoadELFProgram(t, elfFile, multithreaded.CreateInitialState, false)
fpvm := multithreaded.NewInstrumentedState(state, po, stdOut, stdErr, log)
require.NoError(t, fpvm.InitDebug(meta))
return fpvm
}
type VersionedVMTestCase struct {
......
......@@ -9,9 +9,11 @@ import (
"github.com/ethereum-optimism/optimism/cannon/mipsevm/program"
)
func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T], doPatchGo bool) T {
func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initState program.CreateInitialFPVMState[T], doPatchGo bool) (T, *program.Metadata) {
elfProgram, err := elf.Open(name)
require.NoError(t, err, "open ELF file")
meta, err := program.MakeMetadata(elfProgram)
require.NoError(t, err, "load metadata")
state, err := program.LoadELF(elfProgram, initState)
require.NoError(t, err, "load ELF into state")
......@@ -22,5 +24,5 @@ func LoadELFProgram[T mipsevm.FPVMState](t require.TestingT, name string, initSt
}
require.NoError(t, program.PatchStack(state), "add initial stack")
return state
return state, meta
}
......@@ -93,7 +93,7 @@ func RunVMTests_OpenMips[T mipsevm.FPVMState](t *testing.T, stateFactory StateFa
}
func RunVMTest_Hello[T mipsevm.FPVMState](t *testing.T, initState program.CreateInitialFPVMState[T], vmFactory VMFactory[T], doPatchGo bool) {
state := LoadELFProgram(t, "../../testdata/example/bin/hello.elf", initState, doPatchGo)
state, _ := LoadELFProgram(t, "../../testdata/example/bin/hello.elf", initState, doPatchGo)
var stdOutBuf, stdErrBuf bytes.Buffer
us := vmFactory(state, nil, io.MultiWriter(&stdOutBuf, os.Stdout), io.MultiWriter(&stdErrBuf, os.Stderr), CreateLogger())
......@@ -114,7 +114,7 @@ func RunVMTest_Hello[T mipsevm.FPVMState](t *testing.T, initState program.Create
}
func RunVMTest_Claim[T mipsevm.FPVMState](t *testing.T, initState program.CreateInitialFPVMState[T], vmFactory VMFactory[T], doPatchGo bool) {
state := LoadELFProgram(t, "../../testdata/example/bin/claim.elf", initState, doPatchGo)
state, _ := LoadELFProgram(t, "../../testdata/example/bin/claim.elf", initState, doPatchGo)
oracle, expectedStdOut, expectedStdErr := ClaimTestOracle(t)
......
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