func (e *Executor) run() { stackState := e.runner.prog.getStack() stackOffset := len(e.runner.stack) - len(stackState) copy(e.runner.stack[stackOffset:], stackState) resumeResult := 0 // don't resume if len(stackState) > 0 { resumeResult = -1 // resume; return this value to snapshot function caller } fds, err := syscall.Socketpair(syscall.AF_UNIX, syscall.SOCK_STREAM|syscall.SOCK_CLOEXEC, 0) if err != nil { return } done := make(chan struct{}) defer func() { syscall.Close(fds[1]) <-done }() go func() { defer close(done) e.slave(fds[0], e.sigs, e.printer, e.cont) }() runtime.LockOSThread() defer runtime.UnlockOSThread() setRunArg(e.arg) globalsMemoryAddr := (*reflect.SliceHeader)(unsafe.Pointer(&e.runner.globalsMemory)).Data memoryAddr := globalsMemoryAddr + uintptr(e.runner.memoryOffset) growMemorySize := len(e.runner.globalsMemory) - e.runner.memoryOffset trap, memorySize, stackPtr := run(e.runner.prog.getText(), int(e.runner.memorySize), memoryAddr, uintptr(growMemorySize), e.runner.stack, stackOffset, resumeResult, fds[1]) e.runner.memorySize = wasm.MemorySize(memorySize) e.runner.lastTrap = traps.Id(trap) e.runner.lastStackPtr = stackPtr if trap == 0 { e.result = getRunResult() } else { e.err = e.runner.lastTrap } return }
func PrintTo(w io.Writer, text, funcMap []byte, ns *sections.NameSection) (err error) { var names []sections.FunctionName if ns != nil { names = ns.FunctionNames } engine, err := gapstone.New(gapstone.CS_ARCH_X86, gapstone.CS_MODE_64) if err != nil { return } defer engine.Close() err = engine.SetOption(gapstone.CS_OPT_SYNTAX, gapstone.CS_OPT_SYNTAX_ATT) if err != nil { return } insns, err := engine.Disasm(text, 0, 0) if err != nil { return } targets := map[uint]string{ 16: "start", } firstFuncAddr := uint(binary.LittleEndian.Uint32(funcMap)) for i := 0; len(funcMap) > 0; i++ { addr := binary.LittleEndian.Uint32(funcMap) funcMap = funcMap[4:] var name string if i < len(names) { name = names[i].FunName } else { name = fmt.Sprintf("func_%d", i) } targets[uint(addr)] = name } sequence := 0 for i := range insns { insn := insns[i] var name string switch { case insn.Mnemonic == "jmpq": continue case strings.HasPrefix(insn.Mnemonic, "j"): case insn.Mnemonic == "callq" && strings.HasPrefix(insn.OpStr, "0x"): case insn.Address < firstFuncAddr && insn.Mnemonic == "movl" && strings.HasPrefix(insn.OpStr, "$") && strings.HasSuffix(insn.OpStr, ", %eax"): var n uint fmt.Sscanf(insn.OpStr, "$%d, %%eax", &n) if id := traps.Id(n); id < traps.NumTraps { targets[insn.Address] = strings.Replace(id.String(), " ", "_", -1) } continue default: continue } addr, err := strconv.ParseUint(insn.OpStr, 0, 32) if err != nil { panic(err) } name, found := targets[uint(addr)] if !found { name = fmt.Sprintf(".L%d", sequence) sequence++ targets[uint(addr)] = name } insns[i].OpStr = name } skip := false for _, insn := range insns { name, found := targets[insn.Address] if found { if !strings.HasPrefix(name, ".") && name != "exit" { fmt.Fprintln(w) } fmt.Fprintf(w, "%s:\n", name) } switch insn.Id { case gapstone.X86_INS_INT3: if skip { continue } skip = true fallthrough default: fmt.Fprintf(w, "\t%s\t%s\n", insn.Mnemonic, insn.OpStr) } } fmt.Fprintln(w) return }