blob: 950418b5388fee785449f8d131b50cf442213d60 [file] [log] [blame] [edit]
// 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/proc"
"exp/eval"
"reflect"
)
// This file contains remote runtime definitions. Using reflection,
// we convert all of these to interpreter types and layout their
// remote representations using the architecture rules.
//
// We could get most of these definitions from our own runtime
// package; however, some of them differ in convenient ways, some of
// them are not defined or exported by the runtime, and having our own
// definitions makes it easy to support multiple remote runtime
// versions. This may turn out to be overkill.
//
// All of these structures are prefixed with rt1 to indicate the
// runtime version and to mark them as types used only as templates
// for remote types.
/*
* Runtime data headers
*
* See $GOROOT/src/pkg/runtime/runtime.h
*/
type rt1String struct {
str uintptr
len int
}
type rt1Slice struct {
array uintptr
len int
cap int
}
type rt1Eface struct {
typ uintptr
ptr uintptr
}
/*
* Runtime type structures
*
* See $GOROOT/src/pkg/runtime/type.h and $GOROOT/src/pkg/runtime/type.go
*/
type rt1UncommonType struct {
name *string
pkgPath *string
//methods []method;
}
type rt1CommonType struct {
size uintptr
hash uint32
alg, align, fieldAlign uint8
string *string
uncommonType *rt1UncommonType
}
type rt1Type struct {
// While Type is technically an Eface, treating the
// discriminator as an opaque pointer and taking advantage of
// the commonType prologue on all Type's makes type parsing
// much simpler.
typ uintptr
ptr *rt1CommonType
}
type rt1StructField struct {
name *string
pkgPath *string
typ *rt1Type
tag *string
offset uintptr
}
type rt1StructType struct {
rt1CommonType
fields []rt1StructField
}
type rt1PtrType struct {
rt1CommonType
elem *rt1Type
}
type rt1SliceType struct {
rt1CommonType
elem *rt1Type
}
type rt1ArrayType struct {
rt1CommonType
elem *rt1Type
len uintptr
}
/*
* Runtime scheduler structures
*
* See $GOROOT/src/pkg/runtime/runtime.h
*/
// Fields beginning with _ are only for padding
type rt1Stktop struct {
stackguard uintptr
stackbase *rt1Stktop
gobuf rt1Gobuf
_args uint32
_fp uintptr
}
type rt1Gobuf struct {
sp uintptr
pc uintptr
g *rt1G
r0 uintptr
}
type rt1G struct {
_stackguard uintptr
stackbase *rt1Stktop
_defer uintptr
sched rt1Gobuf
_stack0 uintptr
_entry uintptr
alllink *rt1G
_param uintptr
status int16
// Incomplete
}
var rt1GStatus = runtimeGStatus{
Gidle: 0,
Grunnable: 1,
Grunning: 2,
Gsyscall: 3,
Gwaiting: 4,
Gmoribund: 5,
Gdead: 6,
}
// runtimeIndexes stores the indexes of fields in the runtime
// structures. It is filled in using reflection, so the name of the
// fields must match the names of the remoteType's in runtimeValues
// exactly and the names of the index fields must be the capitalized
// version of the names of the fields in the runtime structures above.
type runtimeIndexes struct {
String struct {
Str, Len int
}
Slice struct {
Array, Len, Cap int
}
Eface struct {
Typ, Ptr int
}
UncommonType struct {
Name, PkgPath int
}
CommonType struct {
Size, Hash, Alg, Align, FieldAlign, String, UncommonType int
}
Type struct {
Typ, Ptr int
}
StructField struct {
Name, PkgPath, Typ, Tag, Offset int
}
StructType struct {
Fields int
}
PtrType struct {
Elem int
}
SliceType struct {
Elem int
}
ArrayType struct {
Elem, Len int
}
Stktop struct {
Stackguard, Stackbase, Gobuf int
}
Gobuf struct {
Sp, Pc, G int
}
G struct {
Stackbase, Sched, Status, Alllink int
}
}
// Values of G status codes
type runtimeGStatus struct {
Gidle, Grunnable, Grunning, Gsyscall, Gwaiting, Gmoribund, Gdead int64
}
// runtimeValues stores the types and values that correspond to those
// in the remote runtime package.
type runtimeValues struct {
// Runtime data headers
String, Slice, Eface *remoteType
// Runtime type structures
Type, CommonType, UncommonType, StructField, StructType, PtrType,
ArrayType, SliceType *remoteType
// Runtime scheduler structures
Stktop, Gobuf, G *remoteType
// Addresses of *runtime.XType types. These are the
// discriminators on the runtime.Type interface. We use local
// reflection to fill these in from the remote symbol table,
// so the names must match the runtime names.
PBoolType,
PUint8Type, PUint16Type, PUint32Type, PUint64Type, PUintType, PUintptrType,
PInt8Type, PInt16Type, PInt32Type, PInt64Type, PIntType,
PFloat32Type, PFloat64Type, PFloatType,
PArrayType, PStringType, PStructType, PPtrType, PFuncType,
PInterfaceType, PSliceType, PMapType, PChanType,
PDotDotDotType, PUnsafePointerType proc.Word
// G status values
runtimeGStatus
}
// fillRuntimeIndexes fills a runtimeIndexes structure will the field
// indexes gathered from the remoteTypes recorded in a runtimeValues
// structure.
func fillRuntimeIndexes(runtime *runtimeValues, out *runtimeIndexes) {
outv := reflect.Indirect(reflect.ValueOf(out))
outt := outv.Type()
runtimev := reflect.Indirect(reflect.ValueOf(runtime))
// out contains fields corresponding to each runtime type
for i := 0; i < outt.NumField(); i++ {
// Find the interpreter type for this runtime type
name := outt.Field(i).Name
et := runtimev.FieldByName(name).Interface().(*remoteType).Type.(*eval.StructType)
// Get the field indexes of the interpreter struct type
indexes := make(map[string]int, len(et.Elems))
for j, f := range et.Elems {
if f.Anonymous {
continue
}
name := f.Name
if name[0] >= 'a' && name[0] <= 'z' {
name = string(name[0]+'A'-'a') + name[1:]
}
indexes[name] = j
}
// Fill this field of out
outStructv := outv.Field(i)
outStructt := outStructv.Type()
for j := 0; j < outStructt.NumField(); j++ {
f := outStructv.Field(j)
name := outStructt.Field(j).Name
f.SetInt(int64(indexes[name]))
}
}
}