// LocalsCommand implements the debugger command: // locals [*name*] // which shows local variable info. // // See also "globals", "whatis", and "eval". func LocalsCommand(args []string) { argc := len(args) - 1 fr := gub.CurFrame() if argc == 0 { for i, _ := range fr.Locals() { gub.PrintLocal(fr, uint(i), false) } for reg, v := range fr.Reg2Var { gub.Msg("reg %s, var %s", reg, v) } } else { varname := args[1] if gub.PrintIfLocal(fr, varname, false) { return } // FIXME: This really shouldn't be needed. for i, v := range fr.Locals() { ssaVal := fr.Fn().Locals[i] if varname == ssaVal.Name() { gub.Msg("fixme %s %s: %s", varname, fr.Fn().Locals[i], interp.ToInspect(v, nil)) break } } } }
// GlobalsCommand implements the debugger command: // globals [*name*] // which shows global variable info. // // See also "locals", "whatis", and "eval". func GlobalsCommand(args []string) { argc := len(args) - 1 if argc == 0 { for k, v := range gub.CurFrame().I().Globals() { if v == nil { fmt.Printf("%s: nil\n") } else { // FIXME: figure out why reflect.lookupCache causes // an panic on a nil pointer or invalid address if fmt.Sprintf("%s", k) == "reflect.lookupCache" { continue } gub.Msg("%s: %s", k, interp.ToInspect(*v, &k)) } } } else { // This doesn't work and I don't know how to fix it. for i := 1; i <= argc; i++ { vv := ssa2.NewConst(exact.MakeString(args[i]), types.Typ[types.String], token.NoPos, token.NoPos) // fmt.Println(vv, "vs", interp.ToInspect(vv)) v, ok := gub.CurFrame().I().Globals()[vv] if ok { gub.Msg("%s: %s", vv, interp.ToInspect(*v, nil)) } } // This is ugly, but I don't know how to turn a string into // a ssa2.Value. globals := make(map[string]*interp.Value) for k, v := range gub.CurFrame().I().Globals() { globals[fmt.Sprintf("%s", k)] = v } for i := 1; i <= argc; i++ { vv := args[i] v, ok := globals[vv] if ok { gub.Msg("%s: %s", vv, interp.ToInspect(*v, nil)) } } } }
// InfoArgsSubcmd implements the debugger command: // info args [arg-name] // which shows argument variables of the current stack frame. func InfoArgsSubcmd(args []string) { fr := gub.CurFrame() fn := fr.Fn() if len(args) == 2 { if len(fn.Params) == 0 { gub.Msg("Function `%s()' has no parameters", fn.Name()) return } for i, p := range fn.Params { gub.Msg("%s %s", fn.Params[i], interp.ToInspect(fr.Env()[p], nil)) } } else { varname := args[2] for i, p := range fn.Params { if varname == fn.Params[i].Name() { gub.Msg("%s %s", fn.Params[i], interp.ToInspect(fr.Env()[p], nil)) break } } } }
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())) } }
func WhatisName(name string) bool { if len(name) == 0 { return false } isPtr := false if name[0] == '*' { isPtr = true name = name[1:] } ids := strings.Split(name, ".") myfn := curFrame.Fn() pkg := myfn.Pkg if len(ids) > 1 { varname := ids[0] // local lookup needs to take precedence over package lookup if i := LocalsLookup(curFrame, varname, curScope); i != 0 { Errmsg("Sorry, dotted variable lookup for local %s not supported yet", varname) return false } else { try_pkg := PkgLookup(varname) if try_pkg != nil { pkg = try_pkg } m := pkg.Members[ids[1]] if m == nil { Errmsg("%s is not a member of %s", ids[1], pkg) return false } name = ids[1] } } else { nameVal, interpVal, scopeVal := EnvLookup(curFrame, name, curScope) if nameVal != nil { if isPtr { switch v := interpVal.(type) { case *interp.Value: if v == nil { interpVal = nil } else { interpVal = *v } default: Errmsg("%s doesn't seem to be a pointer", name) return false } } PrintInEnvironment(curFrame, name, nameVal, interpVal, scopeVal) return true } if PrintIfLocal(curFrame, name, isPtr) { return true } } if fn := pkg.Func(name); fn != nil { printFuncInfo(fn) } else if v := pkg.Var(name); v != nil { Msg("%s is a variable in %s at:", name, pkg) Msg(" %s", ssa2.FmtRange(myfn, v.Pos(), v.EndP())) Msg(" %s", v.Type()) if g, ok := curFrame.I().Global(name, pkg); ok { ssaVal := ssa2.Value(v) Msg(" %s", interp.ToInspect(*g, &ssaVal)) } } else if c := pkg.Const(name); c != nil { printConstantInfo(c, name, pkg) // } else if t := pkg.Type(name); t != nil { // printTypeInfo(name, pkg) } else if pkg := program.PackagesByName[name]; pkg != nil { printPackageInfo(name, pkg) } else { Errmsg("Can't find name: %s", name) return false } return true }
func Deref2Str(v interp.Value, ssaVal *ssa2.Value) string { return interp.ToInspect(DerefValue(v), ssaVal) }