diff options
Diffstat (limited to 'src/pkg/exp/ogle/process.go')
| -rw-r--r-- | src/pkg/exp/ogle/process.go | 272 |
1 files changed, 136 insertions, 136 deletions
diff --git a/src/pkg/exp/ogle/process.go b/src/pkg/exp/ogle/process.go index efe3c4da4..63f42a9d4 100644 --- a/src/pkg/exp/ogle/process.go +++ b/src/pkg/exp/ogle/process.go @@ -5,14 +5,14 @@ package ogle import ( - "debug/elf"; - "debug/gosym"; - "debug/proc"; - "exp/eval"; - "fmt"; - "log"; - "os"; - "reflect"; + "debug/elf" + "debug/gosym" + "debug/proc" + "exp/eval" + "fmt" + "log" + "os" + "reflect" ) // A FormatError indicates a failure to process information in or @@ -20,7 +20,7 @@ import ( // in the object file or runtime structures. type FormatError string -func (e FormatError) String() string { return string(e) } +func (e FormatError) String() string { return string(e) } // An UnknownArchitecture occurs when trying to load an object file // that indicates an architecture not supported by the debugger. @@ -34,13 +34,13 @@ func (e UnknownArchitecture) String() string { // memory or registers of a process that is not stopped. type ProcessNotStopped struct{} -func (e ProcessNotStopped) String() string { return "process not stopped" } +func (e ProcessNotStopped) String() string { return "process not stopped" } // An UnknownGoroutine error is an internal error representing an // unrecognized G structure pointer. type UnknownGoroutine struct { - OSThread proc.Thread; - Goroutine proc.Word; + OSThread proc.Thread + Goroutine proc.Word } func (e UnknownGoroutine) String() string { @@ -52,50 +52,50 @@ func (e UnknownGoroutine) String() string { // process). type NoCurrentGoroutine struct{} -func (e NoCurrentGoroutine) String() string { return "no current goroutine" } +func (e NoCurrentGoroutine) String() string { return "no current goroutine" } // A Process represents a remote attached process. type Process struct { - Arch; - proc proc.Process; + Arch + proc proc.Process // The symbol table of this process - syms *gosym.Table; + syms *gosym.Table // A possibly-stopped OS thread, or nil - threadCache proc.Thread; + threadCache proc.Thread // Types parsed from the remote process - types map[proc.Word]*remoteType; + types map[proc.Word]*remoteType // Types and values from the remote runtime package - runtime runtimeValues; + runtime runtimeValues // Runtime field indexes - f runtimeIndexes; + f runtimeIndexes // Globals from the sys package (or from no package) - sys struct { - lessstack, goexit, newproc, deferproc, newprocreadylocked *gosym.Func; - allg remotePtr; - g0 remoteStruct; - }; + sys struct { + lessstack, goexit, newproc, deferproc, newprocreadylocked *gosym.Func + allg remotePtr + g0 remoteStruct + } // Event queue - posted []Event; - pending []Event; - event Event; + posted []Event + pending []Event + event Event // Event hooks - breakpointHooks map[proc.Word]*breakpointHook; - goroutineCreateHook *goroutineCreateHook; - goroutineExitHook *goroutineExitHook; + breakpointHooks map[proc.Word]*breakpointHook + goroutineCreateHook *goroutineCreateHook + goroutineExitHook *goroutineExitHook // Current goroutine, or nil if there are no goroutines - curGoroutine *Goroutine; + curGoroutine *Goroutine // Goroutines by the address of their G structure - goroutines map[proc.Word]*Goroutine; + goroutines map[proc.Word]*Goroutine } /* @@ -114,10 +114,10 @@ func NewProcess(tproc proc.Process, arch Arch, syms *gosym.Table) (*Process, os. goroutineCreateHook: new(goroutineCreateHook), goroutineExitHook: new(goroutineExitHook), goroutines: make(map[proc.Word]*Goroutine), - }; + } // Fill in remote runtime - p.bootstrap(); + p.bootstrap() switch { case p.sys.allg.addr().base == 0: @@ -131,127 +131,127 @@ func NewProcess(tproc proc.Process, arch Arch, syms *gosym.Table) (*Process, os. } // Get current goroutines - p.goroutines[p.sys.g0.addr().base] = &Goroutine{p.sys.g0, nil, false}; + p.goroutines[p.sys.g0.addr().base] = &Goroutine{p.sys.g0, nil, false} err := try(func(a aborter) { - g := p.sys.allg.aGet(a); + g := p.sys.allg.aGet(a) for g != nil { - gs := g.(remoteStruct); - fmt.Printf("*** Found goroutine at %#x\n", gs.addr().base); - p.goroutines[gs.addr().base] = &Goroutine{gs, nil, false}; - g = gs.field(p.f.G.Alllink).(remotePtr).aGet(a); + gs := g.(remoteStruct) + fmt.Printf("*** Found goroutine at %#x\n", gs.addr().base) + p.goroutines[gs.addr().base] = &Goroutine{gs, nil, false} + g = gs.field(p.f.G.Alllink).(remotePtr).aGet(a) } - }); + }) if err != nil { return nil, err } // Create internal breakpoints to catch new and exited goroutines - p.OnBreakpoint(proc.Word(p.sys.newprocreadylocked.Entry)).(*breakpointHook).addHandler(readylockedBP, true); - p.OnBreakpoint(proc.Word(p.sys.goexit.Entry)).(*breakpointHook).addHandler(goexitBP, true); + p.OnBreakpoint(proc.Word(p.sys.newprocreadylocked.Entry)).(*breakpointHook).addHandler(readylockedBP, true) + p.OnBreakpoint(proc.Word(p.sys.goexit.Entry)).(*breakpointHook).addHandler(goexitBP, true) // Select current frames for _, g := range p.goroutines { g.resetFrame() } - p.selectSomeGoroutine(); + p.selectSomeGoroutine() - return p, nil; + return p, nil } func elfGoSyms(f *elf.File) (*gosym.Table, os.Error) { - text := f.Section(".text"); - symtab := f.Section(".gosymtab"); - pclntab := f.Section(".gopclntab"); + text := f.Section(".text") + symtab := f.Section(".gosymtab") + pclntab := f.Section(".gopclntab") if text == nil || symtab == nil || pclntab == nil { return nil, nil } - symdat, err := symtab.Data(); + symdat, err := symtab.Data() if err != nil { return nil, err } - pclndat, err := pclntab.Data(); + pclndat, err := pclntab.Data() if err != nil { return nil, err } - pcln := gosym.NewLineTable(pclndat, text.Addr); - tab, err := gosym.NewTable(symdat, pcln); + pcln := gosym.NewLineTable(pclndat, text.Addr) + tab, err := gosym.NewTable(symdat, pcln) if err != nil { return nil, err } - return tab, nil; + return tab, nil } // NewProcessElf constructs a new remote process around a traced // process and the process' ELF object. func NewProcessElf(tproc proc.Process, f *elf.File) (*Process, os.Error) { - syms, err := elfGoSyms(f); + syms, err := elfGoSyms(f) if err != nil { return nil, err } if syms == nil { return nil, FormatError("Failed to find symbol table") } - var arch Arch; + var arch Arch switch f.Machine { case elf.EM_X86_64: arch = Amd64 default: return nil, UnknownArchitecture(f.Machine) } - return NewProcess(tproc, arch, syms); + return NewProcess(tproc, arch, syms) } // bootstrap constructs the runtime structure of a remote process. func (p *Process) bootstrap() { // Manually construct runtime types - p.runtime.String = newManualType(eval.TypeOfNative(rt1String{}), p.Arch); - p.runtime.Slice = newManualType(eval.TypeOfNative(rt1Slice{}), p.Arch); - p.runtime.Eface = newManualType(eval.TypeOfNative(rt1Eface{}), p.Arch); - - p.runtime.Type = newManualType(eval.TypeOfNative(rt1Type{}), p.Arch); - p.runtime.CommonType = newManualType(eval.TypeOfNative(rt1CommonType{}), p.Arch); - p.runtime.UncommonType = newManualType(eval.TypeOfNative(rt1UncommonType{}), p.Arch); - p.runtime.StructField = newManualType(eval.TypeOfNative(rt1StructField{}), p.Arch); - p.runtime.StructType = newManualType(eval.TypeOfNative(rt1StructType{}), p.Arch); - p.runtime.PtrType = newManualType(eval.TypeOfNative(rt1PtrType{}), p.Arch); - p.runtime.ArrayType = newManualType(eval.TypeOfNative(rt1ArrayType{}), p.Arch); - p.runtime.SliceType = newManualType(eval.TypeOfNative(rt1SliceType{}), p.Arch); - - p.runtime.Stktop = newManualType(eval.TypeOfNative(rt1Stktop{}), p.Arch); - p.runtime.Gobuf = newManualType(eval.TypeOfNative(rt1Gobuf{}), p.Arch); - p.runtime.G = newManualType(eval.TypeOfNative(rt1G{}), p.Arch); + p.runtime.String = newManualType(eval.TypeOfNative(rt1String{}), p.Arch) + p.runtime.Slice = newManualType(eval.TypeOfNative(rt1Slice{}), p.Arch) + p.runtime.Eface = newManualType(eval.TypeOfNative(rt1Eface{}), p.Arch) + + p.runtime.Type = newManualType(eval.TypeOfNative(rt1Type{}), p.Arch) + p.runtime.CommonType = newManualType(eval.TypeOfNative(rt1CommonType{}), p.Arch) + p.runtime.UncommonType = newManualType(eval.TypeOfNative(rt1UncommonType{}), p.Arch) + p.runtime.StructField = newManualType(eval.TypeOfNative(rt1StructField{}), p.Arch) + p.runtime.StructType = newManualType(eval.TypeOfNative(rt1StructType{}), p.Arch) + p.runtime.PtrType = newManualType(eval.TypeOfNative(rt1PtrType{}), p.Arch) + p.runtime.ArrayType = newManualType(eval.TypeOfNative(rt1ArrayType{}), p.Arch) + p.runtime.SliceType = newManualType(eval.TypeOfNative(rt1SliceType{}), p.Arch) + + p.runtime.Stktop = newManualType(eval.TypeOfNative(rt1Stktop{}), p.Arch) + p.runtime.Gobuf = newManualType(eval.TypeOfNative(rt1Gobuf{}), p.Arch) + p.runtime.G = newManualType(eval.TypeOfNative(rt1G{}), p.Arch) // Get addresses of type.*runtime.XType for discrimination. - rtv := reflect.Indirect(reflect.NewValue(&p.runtime)).(*reflect.StructValue); - rtvt := rtv.Type().(*reflect.StructType); + rtv := reflect.Indirect(reflect.NewValue(&p.runtime)).(*reflect.StructValue) + rtvt := rtv.Type().(*reflect.StructType) for i := 0; i < rtv.NumField(); i++ { - n := rtvt.Field(i).Name; + n := rtvt.Field(i).Name if n[0] != 'P' || n[1] < 'A' || n[1] > 'Z' { continue } - sym := p.syms.LookupSym("type.*runtime." + n[1:]); + sym := p.syms.LookupSym("type.*runtime." + n[1:]) if sym == nil { continue } - rtv.Field(i).(*reflect.Uint64Value).Set(sym.Value); + rtv.Field(i).(*reflect.Uint64Value).Set(sym.Value) } // Get runtime field indexes - fillRuntimeIndexes(&p.runtime, &p.f); + fillRuntimeIndexes(&p.runtime, &p.f) // Fill G status - p.runtime.runtimeGStatus = rt1GStatus; + p.runtime.runtimeGStatus = rt1GStatus // Get globals - p.sys.lessstack = p.syms.LookupFunc("sys.lessstack"); - p.sys.goexit = p.syms.LookupFunc("goexit"); - p.sys.newproc = p.syms.LookupFunc("sys.newproc"); - p.sys.deferproc = p.syms.LookupFunc("sys.deferproc"); - p.sys.newprocreadylocked = p.syms.LookupFunc("newprocreadylocked"); + p.sys.lessstack = p.syms.LookupFunc("sys.lessstack") + p.sys.goexit = p.syms.LookupFunc("goexit") + p.sys.newproc = p.syms.LookupFunc("sys.newproc") + p.sys.deferproc = p.syms.LookupFunc("sys.deferproc") + p.sys.newprocreadylocked = p.syms.LookupFunc("newprocreadylocked") if allg := p.syms.LookupSym("allg"); allg != nil { p.sys.allg = remotePtr{remote{proc.Word(allg.Value), p}, p.runtime.G} } @@ -263,11 +263,11 @@ func (p *Process) bootstrap() { func (p *Process) selectSomeGoroutine() { // Once we have friendly goroutine ID's, there might be a more // reasonable behavior for this. - p.curGoroutine = nil; + p.curGoroutine = nil for _, g := range p.goroutines { if !g.isG0() && g.frame != nil { - p.curGoroutine = g; - return; + p.curGoroutine = g + return } } } @@ -285,27 +285,27 @@ func (p *Process) someStoppedOSThread() proc.Thread { for _, t := range p.proc.Threads() { if _, err := t.Stopped(); err == nil { - p.threadCache = t; - return t; + p.threadCache = t + return t } } - return nil; + return nil } func (p *Process) Peek(addr proc.Word, out []byte) (int, os.Error) { - thr := p.someStoppedOSThread(); + thr := p.someStoppedOSThread() if thr == nil { return 0, ProcessNotStopped{} } - return thr.Peek(addr, out); + return thr.Peek(addr, out) } func (p *Process) Poke(addr proc.Word, b []byte) (int, os.Error) { - thr := p.someStoppedOSThread(); + thr := p.someStoppedOSThread() if thr == nil { return 0, ProcessNotStopped{} } - return thr.Poke(addr, b); + return thr.Poke(addr, b) } func (p *Process) peekUintptr(a aborter, addr proc.Word) proc.Word { @@ -323,7 +323,7 @@ func (p *Process) OnBreakpoint(pc proc.Word) EventHook { return bp } // The breakpoint will register itself when a handler is added - return &breakpointHook{commonHook{nil, 0}, p, pc}; + return &breakpointHook{commonHook{nil, 0}, p, pc} } // OnGoroutineCreate returns the hook that is run when a goroutine is created. @@ -332,27 +332,27 @@ func (p *Process) OnGoroutineCreate() EventHook { } // OnGoroutineExit returns the hook that is run when a goroutine exits. -func (p *Process) OnGoroutineExit() EventHook { return p.goroutineExitHook } +func (p *Process) OnGoroutineExit() EventHook { return p.goroutineExitHook } // osThreadToGoroutine looks up the goroutine running on an OS thread. func (p *Process) osThreadToGoroutine(t proc.Thread) (*Goroutine, os.Error) { - regs, err := t.Regs(); + regs, err := t.Regs() if err != nil { return nil, err } - g := p.G(regs); - gt, ok := p.goroutines[g]; + g := p.G(regs) + gt, ok := p.goroutines[g] if !ok { return nil, UnknownGoroutine{t, g} } - return gt, nil; + return gt, nil } // causesToEvents translates the stop causes of the underlying process // into an event queue. func (p *Process) causesToEvents() ([]Event, os.Error) { // Count causes we're interested in - nev := 0; + nev := 0 for _, t := range p.proc.Threads() { if c, err := t.Stopped(); err == nil { switch c := c.(type) { @@ -366,87 +366,87 @@ func (p *Process) causesToEvents() ([]Event, os.Error) { } // Translate causes to events - events := make([]Event, nev); - i := 0; + events := make([]Event, nev) + i := 0 for _, t := range p.proc.Threads() { if c, err := t.Stopped(); err == nil { switch c := c.(type) { case proc.Breakpoint: - gt, err := p.osThreadToGoroutine(t); + gt, err := p.osThreadToGoroutine(t) if err != nil { return nil, err } - events[i] = &Breakpoint{commonEvent{p, gt}, t, proc.Word(c)}; - i++; + events[i] = &Breakpoint{commonEvent{p, gt}, t, proc.Word(c)} + i++ case proc.Signal: // TODO(austin) } } } - return events, nil; + return events, nil } // postEvent appends an event to the posted queue. These events will // be processed before any currently pending events. func (p *Process) postEvent(ev Event) { - n := len(p.posted); - m := n * 2; + n := len(p.posted) + m := n * 2 if m == 0 { m = 4 } - posted := make([]Event, n+1, m); + posted := make([]Event, n+1, m) for i, p := range p.posted { posted[i] = p } - posted[n] = ev; - p.posted = posted; + posted[n] = ev + p.posted = posted } // processEvents processes events in the event queue until no events // remain, a handler returns EAStop, or a handler returns an error. // It returns either EAStop or EAContinue and possibly an error. func (p *Process) processEvents() (EventAction, os.Error) { - var ev Event; + var ev Event for len(p.posted) > 0 { - ev, p.posted = p.posted[0], p.posted[1:]; - action, err := p.processEvent(ev); + ev, p.posted = p.posted[0], p.posted[1:] + action, err := p.processEvent(ev) if action == EAStop { return action, err } } for len(p.pending) > 0 { - ev, p.pending = p.pending[0], p.pending[1:]; - action, err := p.processEvent(ev); + ev, p.pending = p.pending[0], p.pending[1:] + action, err := p.processEvent(ev) if action == EAStop { return action, err } } - return EAContinue, nil; + return EAContinue, nil } // processEvent processes a single event, without manipulating the // event queues. It returns either EAStop or EAContinue and possibly // an error. func (p *Process) processEvent(ev Event) (EventAction, os.Error) { - p.event = ev; + p.event = ev - var action EventAction; - var err os.Error; + var action EventAction + var err os.Error switch ev := p.event.(type) { case *Breakpoint: - hook, ok := p.breakpointHooks[ev.pc]; + hook, ok := p.breakpointHooks[ev.pc] if !ok { break } - p.curGoroutine = ev.Goroutine(); - action, err = hook.handle(ev); + p.curGoroutine = ev.Goroutine() + action, err = hook.handle(ev) case *GoroutineCreate: - p.curGoroutine = ev.Goroutine(); - action, err = p.goroutineCreateHook.handle(ev); + p.curGoroutine = ev.Goroutine() + action, err = p.goroutineCreateHook.handle(ev) case *GoroutineExit: action, err = p.goroutineExitHook.handle(ev) @@ -460,14 +460,14 @@ func (p *Process) processEvent(ev Event) (EventAction, os.Error) { } else if action == EAStop { return EAStop, nil } - return EAContinue, nil; + return EAContinue, nil } // Event returns the last event that caused the process to stop. This // may return nil if the process has never been stopped by an event. // // TODO(austin) Return nil if the user calls p.Stop()? -func (p *Process) Event() Event { return p.event } +func (p *Process) Event() Event { return p.event } /* * Process control @@ -489,29 +489,29 @@ func (p *Process) Event() Event { return p.event } // that stops the process. func (p *Process) ContWait() os.Error { for { - a, err := p.processEvents(); + a, err := p.processEvents() if err != nil { return err } else if a == EAStop { break } - err = p.proc.Continue(); + err = p.proc.Continue() if err != nil { return err } - err = p.proc.WaitStop(); + err = p.proc.WaitStop() if err != nil { return err } for _, g := range p.goroutines { g.resetFrame() } - p.pending, err = p.causesToEvents(); + p.pending, err = p.causesToEvents() if err != nil { return err } } - return nil; + return nil } // Out selects the caller frame of the current frame. @@ -519,7 +519,7 @@ func (p *Process) Out() os.Error { if p.curGoroutine == nil { return NoCurrentGoroutine{} } - return p.curGoroutine.Out(); + return p.curGoroutine.Out() } // In selects the frame called by the current frame. @@ -527,5 +527,5 @@ func (p *Process) In() os.Error { if p.curGoroutine == nil { return NoCurrentGoroutine{} } - return p.curGoroutine.In(); + return p.curGoroutine.In() } |
