| // 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])) |
| } |
| } |
| } |