2009-08-28 19:04:18 -06:00
|
|
|
// 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 (
|
2009-09-24 10:07:47 -06:00
|
|
|
"debug/proc";
|
2009-08-28 19:04:18 -06:00
|
|
|
"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
|
|
|
|
*/
|
|
|
|
|
2009-09-03 17:59:41 -06:00
|
|
|
// Fields beginning with _ are only for padding
|
|
|
|
|
2009-08-28 19:04:18 -06:00
|
|
|
type rt1Stktop struct {
|
|
|
|
stackguard uintptr;
|
|
|
|
stackbase *rt1Stktop;
|
|
|
|
gobuf rt1Gobuf;
|
2009-09-03 17:59:41 -06:00
|
|
|
_args uint32;
|
|
|
|
_fp uintptr;
|
2009-08-28 19:04:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type rt1Gobuf struct {
|
|
|
|
sp uintptr;
|
|
|
|
pc uintptr;
|
|
|
|
g *rt1G;
|
2009-09-03 17:59:41 -06:00
|
|
|
r0 uintptr;
|
2009-08-28 19:04:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type rt1G struct {
|
2009-09-01 14:01:37 -06:00
|
|
|
_stackguard uintptr;
|
2009-08-28 19:04:18 -06:00
|
|
|
stackbase *rt1Stktop;
|
2009-09-01 14:01:37 -06:00
|
|
|
_defer uintptr;
|
|
|
|
sched rt1Gobuf;
|
|
|
|
_stack0 uintptr;
|
|
|
|
_entry uintptr;
|
|
|
|
alllink *rt1G;
|
|
|
|
_param uintptr;
|
|
|
|
status int16;
|
2009-09-03 17:59:41 -06:00
|
|
|
// Incomplete
|
2009-09-01 14:01:37 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
var rt1GStatus = runtimeGStatus{
|
|
|
|
Gidle: 0,
|
|
|
|
Grunnable: 1,
|
|
|
|
Grunning: 2,
|
|
|
|
Gsyscall: 3,
|
|
|
|
Gwaiting: 4,
|
|
|
|
Gmoribund: 5,
|
|
|
|
Gdead: 6,
|
|
|
|
};
|
2009-08-28 19:04:18 -06:00
|
|
|
|
|
|
|
// 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 {
|
2009-09-03 17:59:41 -06:00
|
|
|
Stackbase, Sched, Status, Alllink int;
|
2009-08-28 19:04:18 -06:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2009-09-01 14:01:37 -06:00
|
|
|
// Values of G status codes
|
|
|
|
type runtimeGStatus struct {
|
|
|
|
Gidle, Grunnable, Grunning, Gsyscall, Gwaiting, Gmoribund, Gdead int64;
|
|
|
|
}
|
|
|
|
|
2009-08-28 19:04:18 -06:00
|
|
|
// 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,
|
2009-09-24 10:07:47 -06:00
|
|
|
PDotDotDotType, PUnsafePointerType proc.Word;
|
2009-09-01 14:01:37 -06:00
|
|
|
// G status values
|
|
|
|
runtimeGStatus;
|
2009-08-28 19:04:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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.NewValue(out)).(*reflect.StructValue);
|
|
|
|
outt := outv.Type().(*reflect.StructType);
|
|
|
|
runtimev := reflect.Indirect(reflect.NewValue(runtime)).(*reflect.StructValue);
|
|
|
|
|
|
|
|
// 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:len(name)];
|
|
|
|
}
|
|
|
|
indexes[name] = j;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fill this field of out
|
|
|
|
outStructv := outv.Field(i).(*reflect.StructValue);
|
|
|
|
outStructt := outStructv.Type().(*reflect.StructType);
|
|
|
|
for j := 0; j < outStructt.NumField(); j++ {
|
|
|
|
f := outStructv.Field(j).(*reflect.IntValue);
|
|
|
|
name := outStructt.Field(j).Name;
|
|
|
|
f.Set(indexes[name]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|