Beispiel #1
0
func frameInit(fr *interp.Frame) {
	topFrame = fr
	curFrame = fr
	frameIndex = 0
	curBlock = fr.Block()
	// EvalEnv = interp.MakeEnv(EvalEnvironment(), program, fr)
	for stackSize = 0; fr != nil; fr = fr.Caller(0) {
		stackSize++
	}
	switch TraceEvent {
	case ssa2.CALL_RETURN, ssa2.PROGRAM_TERMINATION:
		/* These guys are not in a basic block, so curFrame.Scope
		   won't work here. . Not sure why fr.Fn() memory crashes either.
		   Otherwise, I'd use fr.Fn().Scope
		*/
		curScope = nil

		/* A "block end" sets the frame block can be nil. There should
		   be a better way to do this inside the interpreter but I get:
		       panic: unexpected type: <nil>: <nil>
		   when I tried it and don't know why. */
		switch instr := (*Instr).(type) {
		case *ssa2.Return:
			if curBlock == nil {
				curBlock = instr.Block()
			}
		}

	default:
		// FIXME: may need other cases like defer_enter, panic,
		// block_end?
		curScope = curFrame.Scope()
	}
}
Beispiel #2
0
func LocalsLookup(fr *interp.Frame, name string, scope *ssa2.Scope) uint {
	nameScope := ssa2.NameScope{
		Name:  name,
		Scope: scope,
	}
	return fr.Fn().LocalsByName[nameScope]
}
Beispiel #3
0
func skipEvent(fr *interp.Frame, event ssa2.TraceEvent) bool {
	curBpnum = NoBp
	if event == ssa2.BREAKPOINT {
		bps := BreakpointFindByPos(fr.StartP())
		for _, bpnum := range bps {
			bp := Breakpoints[bpnum]
			if !bp.Enabled {
				continue
			}
			// FIXME: check things like the condition
			curBpnum = bpnum
			bp.Hits++
			break
		}
	}
	return false
}
Beispiel #4
0
func EnvLookup(fr *interp.Frame, name string,
	scope *ssa2.Scope) (ssa2.Value, interp.Value, *ssa2.Scope) {
	fn := fr.Fn()
	reg := fr.Var2Reg[name]
	for ; scope != nil; scope = ssa2.ParentScope(fn, scope) {
		nameScope := ssa2.NameScope{
			Name:  name,
			Scope: scope,
		}
		if i := fn.LocalsByName[nameScope]; i > 0 {
			nameVal := fn.Locals[i-1]
			val := fr.Env()[nameVal]
			return nameVal, val, nameVal.Scope
		}
	}
	names := []string{name, reg}
	for _, name := range names {
		for nameVal, val := range fr.Env() {
			if name == nameVal.Name() {
				switch nameVal := nameVal.(type) {
				case *ssa2.Alloc:
					return nameVal, val, nameVal.Scope
				default:
					return nameVal, val, nil
				}
			}
		}
	}
	// FIXME: Why we would find things here and not by the
	// above scope lookup?
	if val := fn.Pkg.Var(name); val != nil {
		return val, nil, nil
	}
	return nil, nil, nil
}
Beispiel #5
0
func PrintLocal(fr *interp.Frame, i uint, isPtr bool) {
	fn := fr.Fn()
	v := fr.Local(i)
	l := fn.Locals[i]
	name := l.Name()
	scope := l.Scope
	scopeStr := ""
	if scope != nil {
		scopeStr = fmt.Sprintf(" scope %d", scope.ScopeId())
	}
	ssaVal := ssa2.Value(l)
	if name[0] == 't' && fr.Reg2Var[name] != "" {
		nameStr := fr.Reg2Var[name]
		Msg("%3d:\t%s %s (%s) = %s%s %s", i, nameStr, name,
			deref(l.Type()), interp.ToInspect(v, &ssaVal), scopeStr,
			ssa2.FmtRange(fn, l.Pos(), l.EndP()))
	} else {
		Msg("%3d:\t%s %s = %s%s %s", i, l.Name(), deref(l.Type()),
			interp.ToInspect(v, &ssaVal), scopeStr, ssa2.FmtRange(fn, l.Pos(),
				l.EndP()))
	}
}
Beispiel #6
0
func PrintStack(fr *interp.Frame, count int) {
	if fr == nil {
		return
	}
	for i := 0; fr != nil && i < count; fr = fr.Caller(0) {
		pointer := "   "
		if fr == curFrame {
			pointer = "=> "
		}
		Msg("%s#%d %s", pointer, i, fr.FnAndParamString())
		Msg("\t%s", fr.PositionRange())
		i++
	}
}
Beispiel #7
0
// GubTraceHook is the callback hook from interpreter. It contains
// top-level statement breakout.
func GubTraceHook(fr *interp.Frame, instr *ssa2.Instruction, event ssa2.TraceEvent) {
	if !fr.I().TraceEventMask[event] {
		return
	}
	gubLock.Lock()
	defer gubLock.Unlock()
	if skipEvent(fr, event) {
		return
	}
	TraceEvent = event
	frameInit(fr)
	if instr == nil && event != ssa2.PROGRAM_TERMINATION {
		instr = &curBlock.Instrs[fr.PC()]
	}
	Instr = instr

	if event == ssa2.BREAKPOINT && Breakpoints[curBpnum].Kind == "Function" {
		event = ssa2.CALL_ENTER
	}

	if FirstTime {
		IntroText()
		FirstTime = false
	}
	printLocInfo(topFrame, instr, event)

	line := ""
	var err error
	for InCmdLoop = true; err == nil && InCmdLoop; cmdCount++ {
		if inputReader != nil {
			line, err = inputReader.ReadString('\n')
		} else {
			line, err = gnureadline.Readline(computePrompt(), true)
		}
		if err != nil {
			break
		}
		line = strings.Trim(line, " \t\n")
		args := strings.Split(line, " ")
		if len(args) == 0 || len(args[0]) == 0 {
			if len(LastCommand) == 0 {
				Msg("Empty line skipped")
				gnureadline.RemoveHistory(gnureadline.HistoryLength() - 1)
				continue
			} else {
				line = LastCommand
				args = strings.Split(line, " ")
			}
		}
		if args[0][0] == '#' {
			gnureadline.RemoveHistory(gnureadline.HistoryLength() - 1)
			Msg(line) // echo line but do nothing
			continue
		}

		name := args[0]
		CmdArgstr = strings.TrimLeft(line[len(name):], " ")
		if newname := LookupCmd(name); newname != "" {
			name = newname
		}
		cmd := Cmds[name]
		LastCommand = ""

		if cmd != nil {
			runCommand(name, args)
			continue
		}

		if len(args) > 0 {
			if !WhatisName(args[0]) {
				gnureadline.RemoveHistory(gnureadline.HistoryLength() - 1)
			}
		} else {
			gnureadline.RemoveHistory(gnureadline.HistoryLength() - 1)
			Errmsg("Unknown command %s\n", cmd)
		}
	}
}
Beispiel #8
0
func printLocInfo(fr *interp.Frame, inst *ssa2.Instruction,
	event ssa2.TraceEvent) {
	defer func() {
		if x := recover(); x != nil {
			Errmsg("Internal error in getting location info")
			debug.PrintStack()
		}
	}()
	s := Event2Icon[event] + " "
	fn := fr.Fn()
	sig := fn.Signature
	name := fn.Name()

	if fn.Signature.Recv() != nil {
		if len(fn.Params) == 0 {
			panic("Receiver method " + name + " should have at least 1 param. Has 0.")
		}
		s += fmt.Sprintf("(%s).%s()", fn.Params[0].Type(), name)
	} else {
		s += fmt.Sprintf("%s.%s", fn.Pkg.Object.Path(), name)
		if len(name) > 0 {
			s += "()"
		}
	}

	if *terse && (event != ssa2.STEP_INSTRUCTION) {
		Msg(s)
	} else {
		Msg("%s block %d insn %d", s, fr.Block().Index, fr.PC())
	}

	var syntax ast.Node = nil

	switch event {
	case ssa2.CALL_RETURN:
		if sig.Results() == nil {
			Msg("return void")
		} else {
			Msg("return type: %s", sig.Results())
			Msg("return value: %s", Deref2Str(fr.Result(), nil))
		}
	case ssa2.CALL_ENTER:
		syntax = fn.Syntax()
		for _, p := range fn.Params {
			if val := fr.Env()[p]; val != nil {
				ssaVal := ssa2.Value(p)
				Msg("%s %s", p, Deref2Str(val, &ssaVal))
			} else {
				Msg("%s nil", p)
			}
		}
	case ssa2.PANIC:
		// fmt.Printf("panic arg: %s\n", fr.Get(instr.X))
	}

	Msg(fr.PositionRange())
	if Instr != nil {
		switch s := (*Instr).(type) {
		case *ssa2.Trace:
			syntax = s.Syntax()
		}
		if syntax != nil {
			PrintSyntaxFirstLine(syntax, fn.Prog.Fset)
		}
	}
}