summaryrefslogtreecommitdiff
path: root/src/pkg/exp/ogle/vars.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/pkg/exp/ogle/vars.go')
-rw-r--r--src/pkg/exp/ogle/vars.go272
1 files changed, 0 insertions, 272 deletions
diff --git a/src/pkg/exp/ogle/vars.go b/src/pkg/exp/ogle/vars.go
deleted file mode 100644
index 8a3a14791..000000000
--- a/src/pkg/exp/ogle/vars.go
+++ /dev/null
@@ -1,272 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package ogle
-
-import (
- "debug/gosym"
- "debug/proc"
- "exp/eval"
- "log"
- "os"
-)
-
-/*
- * Remote frame pointers
- */
-
-// A NotOnStack error occurs when attempting to access a variable in a
-// remote frame where that remote frame is not on the current stack.
-type NotOnStack struct {
- Fn *gosym.Func
- Goroutine *Goroutine
-}
-
-func (e NotOnStack) String() string {
- return "function " + e.Fn.Name + " not on " + e.Goroutine.String() + "'s stack"
-}
-
-// A remoteFramePtr is an implementation of eval.PtrValue that
-// represents a pointer to a function frame in a remote process. When
-// accessed, this locates the function on the current goroutine's
-// stack and returns a structure containing the local variables of
-// that function.
-type remoteFramePtr struct {
- p *Process
- fn *gosym.Func
- rt *remoteType
-}
-
-func (v remoteFramePtr) String() string {
- // TODO(austin): This could be a really awesome string method
- return "<remote frame>"
-}
-
-func (v remoteFramePtr) Assign(t *eval.Thread, o eval.Value) {
- v.Set(t, o.(eval.PtrValue).Get(t))
-}
-
-func (v remoteFramePtr) Get(t *eval.Thread) eval.Value {
- g := v.p.curGoroutine
- if g == nil || g.frame == nil {
- t.Abort(NoCurrentGoroutine{})
- }
-
- for f := g.frame; f != nil; f = f.aOuter(t) {
- if f.fn != v.fn {
- continue
- }
-
- // TODO(austin): Register for shootdown with f
- return v.rt.mk(remote{f.fp, v.p})
- }
-
- t.Abort(NotOnStack{v.fn, g})
- panic("fail")
-}
-
-func (v remoteFramePtr) Set(t *eval.Thread, x eval.Value) {
- // Theoretically this could be a static error. If remote
- // packages were packages, remote frames could just be defined
- // as constants.
- t.Abort(ReadOnlyError("remote frames cannot be assigned to"))
-}
-
-/*
- * Remote packages
- */
-
-// TODO(austin): Remote packages are implemented as structs right now,
-// which has some weird consequences. You can attempt to assign to a
-// remote package. It also produces terrible error messages.
-// Ideally, these would actually be packages, but somehow first-class
-// so they could be assigned to other names.
-
-// A remotePackage is an implementation of eval.StructValue that
-// represents a package in a remote process. It's essentially a
-// regular struct, except it cannot be assigned to.
-type remotePackage struct {
- defs []eval.Value
-}
-
-func (v remotePackage) String() string { return "<remote package>" }
-
-func (v remotePackage) Assign(t *eval.Thread, o eval.Value) {
- t.Abort(ReadOnlyError("remote packages cannot be assigned to"))
-}
-
-func (v remotePackage) Get(t *eval.Thread) eval.StructValue {
- return v
-}
-
-func (v remotePackage) Field(t *eval.Thread, i int) eval.Value {
- return v.defs[i]
-}
-
-/*
- * Remote variables
- */
-
-// populateWorld defines constants in the given world for each package
-// in this process. These packages are structs that, in turn, contain
-// fields for each global and function in that package.
-func (p *Process) populateWorld(w *eval.World) os.Error {
- type def struct {
- t eval.Type
- v eval.Value
- }
- packages := make(map[string]map[string]def)
-
- for _, s := range p.syms.Syms {
- if s.ReceiverName() != "" {
- // TODO(austin)
- continue
- }
-
- // Package
- pkgName := s.PackageName()
- switch pkgName {
- case "", "type", "extratype", "string", "go":
- // "go" is really "go.string"
- continue
- }
- pkg, ok := packages[pkgName]
- if !ok {
- pkg = make(map[string]def)
- packages[pkgName] = pkg
- }
-
- // Symbol name
- name := s.BaseName()
- if _, ok := pkg[name]; ok {
- log.Printf("Multiple definitions of symbol %s", s.Name)
- continue
- }
-
- // Symbol type
- rt, err := p.typeOfSym(&s)
- if err != nil {
- return err
- }
-
- // Definition
- switch s.Type {
- case 'D', 'd', 'B', 'b':
- // Global variable
- if rt == nil {
- continue
- }
- pkg[name] = def{rt.Type, rt.mk(remote{proc.Word(s.Value), p})}
-
- case 'T', 't', 'L', 'l':
- // Function
- s := s.Func
- // TODO(austin): Ideally, this would *also* be
- // callable. How does that interact with type
- // conversion syntax?
- rt, err := p.makeFrameType(s)
- if err != nil {
- return err
- }
- pkg[name] = def{eval.NewPtrType(rt.Type), remoteFramePtr{p, s, rt}}
- }
- }
-
- // TODO(austin): Define remote types
-
- // Define packages
- for pkgName, defs := range packages {
- fields := make([]eval.StructField, len(defs))
- vals := make([]eval.Value, len(defs))
- i := 0
- for name, def := range defs {
- fields[i].Name = name
- fields[i].Type = def.t
- vals[i] = def.v
- i++
- }
- pkgType := eval.NewStructType(fields)
- pkgVal := remotePackage{vals}
-
- err := w.DefineConst(pkgName, pkgType, pkgVal)
- if err != nil {
- log.Printf("while defining package %s: %v", pkgName, err)
- }
- }
-
- return nil
-}
-
-// typeOfSym returns the type associated with a symbol. If the symbol
-// has no type, returns nil.
-func (p *Process) typeOfSym(s *gosym.Sym) (*remoteType, os.Error) {
- if s.GoType == 0 {
- return nil, nil
- }
- addr := proc.Word(s.GoType)
- var rt *remoteType
- err := try(func(a aborter) { rt = parseRemoteType(a, p.runtime.Type.mk(remote{addr, p}).(remoteStruct)) })
- if err != nil {
- return nil, err
- }
- return rt, nil
-}
-
-// makeFrameType constructs a struct type for the frame of a function.
-// The offsets in this struct type are such that the struct can be
-// instantiated at this function's frame pointer.
-func (p *Process) makeFrameType(s *gosym.Func) (*remoteType, os.Error) {
- n := len(s.Params) + len(s.Locals)
- fields := make([]eval.StructField, n)
- layout := make([]remoteStructField, n)
- i := 0
-
- // TODO(austin): There can be multiple locals/parameters with
- // the same name. We probably need liveness information to do
- // anything about this. Once we have that, perhaps we give
- // such fields interface{} type? Or perhaps we disambiguate
- // the names with numbers. Disambiguation is annoying for
- // things like "i", where there's an obvious right answer.
-
- for _, param := range s.Params {
- rt, err := p.typeOfSym(param)
- if err != nil {
- return nil, err
- }
- if rt == nil {
- //fmt.Printf(" (no type)\n");
- continue
- }
- // TODO(austin): Why do local variables carry their
- // package name?
- fields[i].Name = param.BaseName()
- fields[i].Type = rt.Type
- // Parameters have positive offsets from FP
- layout[i].offset = int(param.Value)
- layout[i].fieldType = rt
- i++
- }
-
- for _, local := range s.Locals {
- rt, err := p.typeOfSym(local)
- if err != nil {
- return nil, err
- }
- if rt == nil {
- continue
- }
- fields[i].Name = local.BaseName()
- fields[i].Type = rt.Type
- // Locals have negative offsets from FP - PtrSize
- layout[i].offset = -int(local.Value) - p.PtrSize()
- layout[i].fieldType = rt
- i++
- }
-
- fields = fields[0:i]
- layout = layout[0:i]
- t := eval.NewStructType(fields)
- mk := func(r remote) eval.Value { return remoteStruct{r, layout} }
- return &remoteType{t, 0, 0, mk}, nil
-}