diff options
Diffstat (limited to 'usr/austin/ogle/process.go')
-rw-r--r-- | usr/austin/ogle/process.go | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/usr/austin/ogle/process.go b/usr/austin/ogle/process.go new file mode 100644 index 000000000..0ca894072 --- /dev/null +++ b/usr/austin/ogle/process.go @@ -0,0 +1,129 @@ +// 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 ( + "eval"; + "ptrace"; + "reflect"; + "os"; + "sym"; +) + +// A FormatError indicates a failure to process information in or +// about a remote process, such as unexpected or missing information +// in the object file or runtime structures. +type FormatError string + +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. +type UnknownArchitecture sym.ElfMachine + +func (e UnknownArchitecture) String() string { + return "unknown architecture: " + sym.ElfMachine(e).String(); +} + +// A Process represents a remote attached process. +type Process struct { + Arch; + ptrace.Process; + + // The symbol table of this process + syms *sym.GoSymTable; + + // Current thread + thread ptrace.Thread; + // Current frame, or nil if the current thread is not stopped + frame *frame; + + // Types parsed from the remote process + types map[ptrace.Word] *remoteType; + + // Types and values from the remote runtime package + runtime runtimeValues; + + // Runtime field indexes + f runtimeIndexes; +} + +// NewProcess constructs a new remote process around a ptrace'd +// process, an architecture, and a symbol table. +func NewProcess(proc ptrace.Process, arch Arch, syms *sym.GoSymTable) *Process { + p := &Process{ + Arch: arch, + Process: proc, + syms: syms, + thread: proc.Threads()[0], + types: make(map[ptrace.Word] *remoteType), + }; + + // TODO(austin) Set p.frame if proc is stopped + + p.bootstrap(); + return p; +} + +// NewProcessElf constructs a new remote process around a ptrace'd +// process and the process' ELF object. +func NewProcessElf(proc ptrace.Process, elf *sym.Elf) (*Process, os.Error) { + syms, err := sym.ElfGoSyms(elf); + if err != nil { + return nil, err; + } + if syms == nil { + return nil, FormatError("Failed to find symbol table"); + } + var arch Arch; + switch elf.Machine { + case sym.ElfX86_64: + arch = Amd64; + default: + return nil, UnknownArchitecture(elf.Machine); + } + return NewProcess(proc, arch, syms), nil; +} + +// 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); + + // Get addresses of type·*runtime.XType for discrimination. + 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; + if n[0] != 'P' || n[1] < 'A' || n[1] > 'Z' { + continue; + } + sym := p.syms.SymFromName("type·*runtime." + n[1:len(n)]); + if sym == nil { + continue; + } + rtv.Field(i).(*reflect.Uint64Value).Set(sym.Common().Value); + } + + // Get field indexes + fillRuntimeIndexes(&p.runtime, &p.f); +} |