Commit 0cb0a00d authored by protolambda's avatar protolambda

cannon: load-elf command

parent 9d8a3222
......@@ -7,3 +7,4 @@ venv
*.log
example/bin
contracts/out
state.json
package cmd
import "github.com/urfave/cli/v2"
import (
"debug/elf"
"encoding/json"
"fmt"
"io"
"os"
"github.com/urfave/cli/v2"
"cannon/mipsevm"
)
var (
LoadELFPathFlag = &cli.PathFlag{
Name: "path",
Usage: "Path to 32-bit big-endian MIPS ELF file",
TakesFile: true,
Required: true,
}
LoadELFPatchFlag = &cli.StringSliceFlag{
Name: "patch",
Usage: "Type of patching to do",
Value: cli.NewStringSlice("go", "stack"),
Required: false,
}
LoadELFOutFlag = &cli.PathFlag{
Name: "out",
Usage: "Output path to write JSON state to. State is dumped to stdout if set to empty string.",
Value: "state.json",
Required: false,
}
)
func LoadELF(ctx *cli.Context) error {
// TODO
elfPath := ctx.Path(LoadELFPathFlag.Name)
elfProgram, err := elf.Open(elfPath)
if err != nil {
return fmt.Errorf("failed to open ELF file %q: %w", elfPath, err)
}
state, err := mipsevm.LoadELF(elfProgram)
if err != nil {
return fmt.Errorf("failed to load ELF data into VM state: %w", err)
}
for _, typ := range ctx.StringSlice(LoadELFPatchFlag.Name) {
switch typ {
case "stack":
err = mipsevm.PatchStack(state)
case "go":
err = mipsevm.PatchGo(elfProgram, state)
default:
return fmt.Errorf("unrecognized form of patching: %q", typ)
}
if err != nil {
return fmt.Errorf("failed to apply patch %s: %w", typ, err)
}
}
p := ctx.Path(LoadELFOutFlag.Name)
var out io.Writer
if p != "" {
f, err := os.OpenFile(p, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
return fmt.Errorf("failed to open output file: %w", err)
}
defer f.Close()
out = f
} else {
out = os.Stdout
}
enc := json.NewEncoder(out)
if err := enc.Encode(state); err != nil {
return fmt.Errorf("failed to encode state to JSON: %w", err)
}
return nil
}
var LoadELFCommand = &cli.Command{
Name: "load-elf",
Usage: "",
Description: "",
Usage: "Load ELF file into Cannon JSON state",
Description: "Load ELF file into Cannon JSON state, optionally patch out functions",
Action: LoadELF,
Flags: nil,
Flags: []cli.Flag{
LoadELFPathFlag,
LoadELFPatchFlag,
LoadELFOutFlag,
},
}
......@@ -7,6 +7,7 @@ require (
github.com/ethereum/go-ethereum v1.11.5
github.com/stretchr/testify v1.8.2
github.com/unicorn-engine/unicorn v0.0.0-20230207094436-7b8c63dfe650
github.com/urfave/cli/v2 v2.25.3
)
require (
......@@ -20,6 +21,7 @@ require (
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 // indirect
github.com/cockroachdb/redact v1.1.3 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/deckarep/golang-set/v2 v2.1.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
......@@ -47,10 +49,12 @@ require (
github.com/prometheus/common v0.39.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 // indirect
github.com/tklauser/go-sysconf v0.3.5 // indirect
github.com/tklauser/numcpus v0.2.2 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/crypto v0.8.0 // indirect
golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
golang.org/x/sys v0.7.0 // indirect
......
......@@ -43,6 +43,8 @@ github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
......@@ -235,6 +237,8 @@ github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
......@@ -271,6 +275,10 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY=
github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBnvPM1Su9w=
......@@ -281,6 +289,8 @@ github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
......
package main
import (
"fmt"
"os"
"github.com/urfave/cli/v2"
"cannon/cmd"
......@@ -16,4 +19,9 @@ func main() {
cmd.RunStepsCommand,
cmd.GenProofCommand,
}
err := app.Run(os.Args)
if err != nil {
_, _ = fmt.Fprintf(os.Stderr, "error: %v", err)
os.Exit(1)
}
}
......@@ -15,7 +15,7 @@ Supported 55 instructions:
To run:
1. Load a program into a state, e.g. using `LoadELF`.
2. Patch the program if necessary: e.g. using `PatchVM` for Go programs.
2. Patch the program if necessary: e.g. using `PatchGo` for Go programs, `PatchStack` for empty initial stack, etc.
3. Load the state into a MIPS-32 configured unicorn instance, using `NewUnicorn`, `LoadUnicorn`
4. Implement the `PreimageOracle` interface
5. Instrument the emulator with the state, and pre-image oracle, using `NewUnicornState`
......
......@@ -128,8 +128,9 @@ func TestHelloEVM(t *testing.T) {
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchVM(elfProgram, state)
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
mu, err := NewUnicorn()
require.NoError(t, err, "load unicorn")
......@@ -199,8 +200,9 @@ func TestClaimEVM(t *testing.T) {
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchVM(elfProgram, state)
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
mu, err := NewUnicorn()
require.NoError(t, err, "load unicorn")
......
......@@ -51,7 +51,7 @@ func LoadELF(f *elf.File) (*State, error) {
return s, nil
}
func PatchVM(f *elf.File, st *State) error {
func PatchGo(f *elf.File, st *State) error {
symbols, err := f.Symbols()
if err != nil {
return fmt.Errorf("failed to read symbols data, cannot patch program: %w", err)
......@@ -82,7 +82,10 @@ func PatchVM(f *elf.File, st *State) error {
}
}
}
return nil
}
func PatchStack(st *State) error {
// setup stack pointer
sp := uint32(0x7f_ff_d0_00)
// allocate 1 page for the initial stack data, and 16KB = 4 pages for the stack to grow
......
......@@ -92,8 +92,9 @@ func TestHello(t *testing.T) {
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchVM(elfProgram, state)
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
mu, err := NewUnicorn()
require.NoError(t, err, "load unicorn")
......@@ -194,8 +195,9 @@ func TestClaim(t *testing.T) {
state, err := LoadELF(elfProgram)
require.NoError(t, err, "load ELF into state")
err = PatchVM(elfProgram, state)
err = PatchGo(elfProgram, state)
require.NoError(t, err, "apply Go runtime patches")
require.NoError(t, PatchStack(state), "add initial stack")
mu, err := NewUnicorn()
require.NoError(t, err, "load unicorn")
......
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