This repository has been archived by the owner on Aug 7, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
unicorn: separate unicorn into test-only module
- Loading branch information
1 parent
bc29480
commit 87bad44
Showing
29 changed files
with
897 additions
and
319 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
[submodule "unicorn"] | ||
path = unicorn | ||
path = diffmips/unicorn | ||
url = https://github.com/unicorn-engine/unicorn.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,62 +1,12 @@ | ||
SHELL := /bin/bash | ||
|
||
build: submodules libunicorn contracts | ||
build: contracts | ||
.PHONY: build | ||
|
||
submodules: | ||
# CI will checkout submodules on its own (and fails on these commands) | ||
if [[ -z "$$GITHUB_ENV" ]]; then \ | ||
git submodule init; \ | ||
git submodule update; \ | ||
fi | ||
.PHONY: submodules | ||
|
||
# Approximation, use `make libunicorn_rebuild` to force. | ||
unicorn/build: unicorn/CMakeLists.txt | ||
mkdir -p unicorn/build | ||
cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release | ||
# Not sure why, but the second invocation is needed for fresh installs on MacOS. | ||
if [ "$(shell uname)" == "Darwin" ]; then \ | ||
cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release; \ | ||
fi | ||
|
||
# Rebuild whenever anything in the unicorn/ directory changes. | ||
unicorn/build/libunicorn.so: unicorn/build unicorn | ||
cd unicorn/build && make -j8 | ||
# The Go linker / runtime expects dynamic libraries in the unicorn/ dir. | ||
find ./unicorn/build -name "libunicorn.*" | xargs -L 1 -I {} cp {} ./unicorn/ | ||
# Update timestamp on libunicorn.so to make it more recent than the build/ dir. | ||
# On Mac this will create a new empty file (dyn libraries are .dylib), but works | ||
# fine for the purpose of avoiding recompilation. | ||
touch unicorn/build/libunicorn.so | ||
|
||
libunicorn: unicorn/build/libunicorn.so | ||
.PHONY: libunicorn | ||
|
||
libunicorn_rebuild: | ||
touch unicorn/CMakeLists.txt | ||
make libunicorn | ||
.PHONY: libunicorn_rebuild | ||
|
||
# Must be a definition and not a rule, otherwise it gets only called once and | ||
# not before each test as we wish. | ||
define clear_cache | ||
rm -rf /tmp/cannon | ||
mkdir -p /tmp/cannon | ||
endef | ||
|
||
clear_cache: | ||
$(call clear_cache) | ||
.PHONY: clear_cache | ||
|
||
clean: | ||
rm -f unicorn/libunicorn.* | ||
.PHONY: clean | ||
|
||
contracts: | ||
cd contracts && forge build | ||
.PHONY: contracts | ||
|
||
test: libunicorn | ||
test: | ||
cd mipsevm && go test -v ./... | ||
.PHONY: test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
SHELL := /bin/bash | ||
|
||
build: submodules libunicorn | ||
.PHONY: build | ||
|
||
submodules: | ||
# CI will checkout submodules on its own (and fails on these commands) | ||
if [[ -z "$$GITHUB_ENV" ]]; then \ | ||
git submodule init; \ | ||
git submodule update; \ | ||
fi | ||
.PHONY: submodules | ||
|
||
# Approximation, use `make libunicorn_rebuild` to force. | ||
unicorn/build: unicorn/CMakeLists.txt | ||
mkdir -p unicorn/build | ||
cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release | ||
# Not sure why, but the second invocation is needed for fresh installs on MacOS. | ||
if [ "$(shell uname)" == "Darwin" ]; then \ | ||
cd unicorn/build && cmake .. -DUNICORN_ARCH=mips -DCMAKE_BUILD_TYPE=Release; \ | ||
fi | ||
|
||
# Rebuild whenever anything in the unicorn/ directory changes. | ||
unicorn/build/libunicorn.so: unicorn/build unicorn | ||
cd unicorn/build && make -j8 | ||
# The Go linker / runtime expects dynamic libraries in the unicorn/ dir. | ||
find ./unicorn/build -name "libunicorn.*" | xargs -L 1 -I {} cp {} ./unicorn/ | ||
# Update timestamp on libunicorn.so to make it more recent than the build/ dir. | ||
# On Mac this will create a new empty file (dyn libraries are .dylib), but works | ||
# fine for the purpose of avoiding recompilation. | ||
touch unicorn/build/libunicorn.so | ||
|
||
libunicorn: unicorn/build/libunicorn.so | ||
.PHONY: libunicorn | ||
|
||
libunicorn_rebuild: | ||
touch unicorn/CMakeLists.txt | ||
make libunicorn | ||
.PHONY: libunicorn_rebuild | ||
|
||
clean: | ||
rm -f unicorn/libunicorn.* | ||
.PHONY: clean | ||
|
||
test: | ||
cd unicorntest && go test -v ./... | ||
.PHONY: test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
# diffmips | ||
|
||
This is a collection of MIPS testing tools. | ||
The Unicorn emulator first backed Cannon directly, but has been separated as a testing-only tool, | ||
and is replaced with a Go implementation of the minimal MIPS functionality. | ||
|
||
Directory layout | ||
``` | ||
unicorn -- Sub-module, used by mipsevm for offchain MIPS emulation. | ||
unicorntest -- Go module with Go tests, diffed against the Cannon state. [Work in Progress] | ||
``` | ||
|
||
### `unicorn` | ||
|
||
To build unicorn from source (git sub-module), run: | ||
``` | ||
make libunicorn | ||
``` | ||
|
||
### `unicorntest` | ||
|
||
This requires `unicorn` to be built, as well as the `contracts` for testing. | ||
|
||
To test: | ||
``` | ||
make test | ||
``` | ||
|
Submodule unicorn
updated
from 000000 to 7b8c63
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package unicorntest | ||
|
||
import ( | ||
"bytes" | ||
"os" | ||
"path" | ||
"testing" | ||
|
||
"github.com/stretchr/testify/require" | ||
|
||
"github.com/ethereum-optimism/cannon/mipsevm" | ||
) | ||
|
||
// baseAddrStart - baseAddrEnd is used in tests to write the results to | ||
const baseAddrEnd = 0xbf_ff_ff_f0 | ||
const baseAddrStart = 0xbf_c0_00_00 | ||
|
||
// endAddr is used as return-address for tests | ||
const endAddr = 0xa7ef00d0 | ||
|
||
func TestState(t *testing.T) { | ||
testFiles, err := os.ReadDir("../../mipsevm/open_mips_tests/test/bin") | ||
require.NoError(t, err) | ||
|
||
for _, f := range testFiles { | ||
t.Run(f.Name(), func(t *testing.T) { | ||
if f.Name() == "oracle.bin" { | ||
t.Skip("oracle test needs to be updated to use syscall pre-image oracle") | ||
} | ||
fn := path.Join("../../mipsevm/open_mips_tests/test/bin", f.Name()) | ||
|
||
programMem, err := os.ReadFile(fn) | ||
require.NoError(t, err) | ||
state := &mipsevm.State{PC: 0, NextPC: 4, Memory: mipsevm.NewMemory()} | ||
err = state.Memory.SetMemoryRange(0, bytes.NewReader(programMem)) | ||
require.NoError(t, err, "load program into state") | ||
|
||
// set the return address ($ra) to jump into when test completes | ||
state.Registers[31] = endAddr | ||
|
||
mu, err := NewUnicorn() | ||
require.NoError(t, err, "load unicorn") | ||
defer mu.Close() | ||
|
||
require.NoError(t, mu.MemMap(baseAddrStart, ((baseAddrEnd-baseAddrStart)&^mipsevm.PageAddrMask)+mipsevm.PageSize)) | ||
require.NoError(t, mu.MemMap(endAddr&^mipsevm.PageAddrMask, mipsevm.PageSize)) | ||
|
||
err = LoadUnicorn(state, mu) | ||
require.NoError(t, err, "load state into unicorn") | ||
|
||
us, err := NewUnicornState(mu, state, nil, os.Stdout, os.Stderr) | ||
require.NoError(t, err, "hook unicorn to state") | ||
|
||
for i := 0; i < 1000; i++ { | ||
if us.state.PC == endAddr { | ||
break | ||
} | ||
_, err := us.Step(false) | ||
require.NoError(t, err) | ||
} | ||
require.Equal(t, uint32(endAddr), us.state.PC, "must reach end") | ||
// inspect test result | ||
done, result := state.Memory.GetMemory(baseAddrEnd+4), state.Memory.GetMemory(baseAddrEnd+8) | ||
require.Equal(t, done, uint32(1), "must be done") | ||
require.Equal(t, result, uint32(1), "must have success result") | ||
}) | ||
} | ||
} |
Oops, something went wrong.