summaryrefslogtreecommitdiff
path: root/libgo/go/exp/ogle/rruntime.go
blob: 33f1935b89e0c6fd5ef881dcdbcb35978503c272 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
// 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.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:]
			}
			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(int64(indexes[name]))
		}
	}
}