Commit c2cb5b6a authored by George Hotz's avatar George Hotz

test passing with custom unicorn

parent f192e77d
node_modules
artifacts
cache
unicorn
#!/bin/bash
git clone https://github.com/geohot/unicorn.git -b dev
cd unicorn
UNICORN_ARCHS=mips make -j8
UNICORN_ARCHS=mips make -j8
......@@ -3,7 +3,10 @@ package main
import (
"fmt"
uc "github.com/unicorn-engine/unicorn/bindings/go/unicorn"
"log"
"sync"
"testing"
"time"
)
func RegSerialize(ram map[uint32](uint32)) []uint32 {
......@@ -14,14 +17,19 @@ func RegSerialize(ram map[uint32](uint32)) []uint32 {
return ret
}
var done sync.Mutex
func TestCompare(t *testing.T) {
fn := "../mipigeth/test.bin"
//fn := "test/bin/sc.bin"
//fn := "../mipigeth/minigeth.bin"
steps := 10000000
//steps := 1165
//steps := 1180
cevm := make(chan []uint32)
cuni := make(chan []uint32)
cevm := make(chan []uint32, 1)
cuni := make(chan []uint32, 1)
ram := make(map[uint32](uint32))
LoadMappedFile(fn, ram, 0)
......@@ -31,11 +39,16 @@ func TestCompare(t *testing.T) {
go RunWithRam(ram, steps, 0, func(step int, ram map[uint32](uint32)) {
//fmt.Printf("%d evm %x\n", step, ram[0xc0000080])
cevm <- RegSerialize(ram)
done.Lock()
done.Unlock()
})
go RunUnicorn(fn, steps, func(step int, mu uc.Unicorn, ram map[uint32](uint32)) {
uniram := make(map[uint32](uint32))
go RunUnicorn(fn, uniram, steps, func(step int, mu uc.Unicorn, ram map[uint32](uint32)) {
SyncRegs(mu, ram)
cuni <- RegSerialize(ram)
done.Lock()
done.Unlock()
})
for i := 0; i < steps; i++ {
......@@ -49,10 +62,23 @@ func TestCompare(t *testing.T) {
}
for j := 0; j < len(x); j++ {
if x[j] != y[j] {
fmt.Println(i, "cevm", x, "cuni", y)
t.Fatal("value mismatch")
fmt.Println(i, "mismatch at", j, "cevm", x, "cuni", y)
break
}
}
}
// final ram check
done.Lock()
time.Sleep(100 * time.Millisecond)
mismatch := false
for k, v := range ram {
if uniram[k] != v {
fmt.Printf("ram mismatch at %x, evm %x != uni %x\n", k, v, uniram[k])
mismatch = true
}
}
if mismatch {
log.Fatal("RAM mismatch")
}
}
......@@ -55,7 +55,8 @@ func main() {
debug, _ := strconv.Atoi(os.Getenv("DEBUG"))
RunMinigeth(os.Args[1], steps, debug)
} else if os.Args[1] == "unicorn" {
RunUnicorn(os.Args[2], steps, nil)
uniram := make(map[uint32](uint32))
RunUnicorn(os.Args[2], uniram, steps, nil)
} else {
runTest(os.Args[1], 20, 2)
}
......
......@@ -141,7 +141,7 @@ func (s *StateDB) SetState(fakeaddr common.Address, key, value common.Hash) {
seenWrite = true
}
if debug >= 2 || true {
if debug >= 2 {
fmt.Println("HOOKED WRITE! ", fmt.Sprintf("%x = %x (at step %d)", addr, dat, pcCount))
}
......
......@@ -67,18 +67,18 @@ func FixBranchDelay(ram map[uint32](uint32)) {
opcode := insn >> 26
mfunc := insn & 0x3f
//fmt.Println(opcode)
//fmt.Printf("%d %x: %x\n", steps, pc-4, insn)
//fmt.Println(pc, opcode, mfunc)
// FIX SC
if opcode == 0x38 {
/*if opcode == 0x38 {
rt := ram[REG_OFFSET+((insn>>14)&0x7C)]
rs := ram[REG_OFFSET+((insn>>19)&0x7C)]
SignExtImm := SE(insn&0xFFFF, 16)
rs += SignExtImm
fmt.Printf("SC @ steps %d writing %x at %x\n", steps, rt, rs)
WriteRam(ram, rs, rt)
}
}*/
if opcode == 2 || opcode == 3 {
WriteRam(ram, REG_PENDPC, SE(insn&0x03FFFFFF, 26)<<2)
......@@ -116,6 +116,10 @@ func FixBranchDelay(ram map[uint32](uint32)) {
}
}
/*func rawAccess(p unsafe.Pointer, len int) []byte {
return (*(*[8440]byte)(p))[:len]
}*/
func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) {
pc, _ := mu.RegRead(uc.MIPS_REG_PC)
//fmt.Printf("%d uni %x\n", step, pc)
......@@ -129,18 +133,38 @@ func SyncRegs(mu uc.Unicorn, ram map[uint32](uint32)) {
addr += 4
}
/*ctx, _ := mu.ContextSave(nil)
ptr := rawAccess(unsafe.Pointer(*ctx), 8440)
fmt.Println(ctx)*/
// TODO: this is broken
reg_lo, _ := mu.RegRead(uc.MIPS_REG_LO)
/*for i := 0; i < 1000; i++ {
tst, _ := mu.RegRead(i)
if tst == uint64(0x3b9ac9ff) {
fmt.Println("LOW HIT", i)
}
if tst == uint64(0xc4653600) {
fmt.Println("HI HIT", i)
}
}*/
/*hflags, _ := mu.RegRead(uc.MIPS_REG_W1)
pendpc, _ := mu.RegRead(uc.MIPS_REG_W0)
fmt.Println(pendpc, hflags)
if pendpc != 0 && pc != pendpc {
WriteRam(ram, REG_PC, uint32(pc)|0x80000000)
WriteRam(ram, REG_PENDPC, uint32(pendpc))
}*/
reg_hi, _ := mu.RegRead(uc.MIPS_REG_HI)
fmt.Println(reg_lo, reg_hi)
WriteRam(ram, REG_OFFSET+0x21*4, uint32(reg_lo))
WriteRam(ram, REG_OFFSET+0x22*4, uint32(reg_hi))
reg_lo, _ := mu.RegRead(uc.MIPS_REG_LO)
WriteRam(ram, REG_OFFSET+0x21*4, uint32(reg_hi))
WriteRam(ram, REG_OFFSET+0x22*4, uint32(reg_lo))
WriteRam(ram, REG_HEAP, uint32(heap_start))
}
// reimplement simple.py in go
func RunUnicorn(fn string, totalSteps int, callback func(int, uc.Unicorn, map[uint32](uint32))) {
func RunUnicorn(fn string, ram map[uint32](uint32), totalSteps int, callback func(int, uc.Unicorn, map[uint32](uint32))) {
mu, err := uc.NewUnicorn(uc.ARCH_MIPS, uc.MODE_32|uc.MODE_BIG_ENDIAN)
check(err)
......@@ -190,13 +214,12 @@ func RunUnicorn(fn string, totalSteps int, callback func(int, uc.Unicorn, map[ui
slowMode := true
ram := make(map[uint32](uint32))
if slowMode {
mu.HookAdd(uc.HOOK_MEM_WRITE, func(mu uc.Unicorn, access int, addr64 uint64, size int, value int64) {
rt := value
rs := addr64 & 3
addr := uint32(addr64 & 0xFFFFFFFC)
fmt.Printf("%X(%d) = %x (at step %d)\n", addr, size, value, steps)
//fmt.Printf("%X(%d) = %x (at step %d)\n", addr, size, value, steps)
if size == 1 {
mem := ram[addr]
val := uint32((rt & 0xFF) << (24 - (rs&3)*8))
......@@ -224,11 +247,12 @@ func RunUnicorn(fn string, totalSteps int, callback func(int, uc.Unicorn, map[ui
if callback != nil {
callback(steps, mu, ram)
}
steps += 1
if totalSteps == steps {
//os.Exit(0)
mu.RegWrite(uc.MIPS_REG_PC, 0x5ead0000)
// immediate exit
mu.RegWrite(uc.MIPS_REG_PC, 0x5ead0004)
}
steps += 1
}, 0, 0x80000000)
}
......
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