1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
13 // A RemoteMismatchError occurs when an operation that requires two
14 // identical remote processes is given different process. For
15 // example, this occurs when trying to set a pointer in one process to
16 // point to something in another process.
17 type RemoteMismatchError
string
19 func (e RemoteMismatchError
) String() string { return string(e
) }
21 // A ReadOnlyError occurs when attempting to set or assign to a
23 type ReadOnlyError
string
25 func (e ReadOnlyError
) String() string { return string(e
) }
27 // A maker is a function that converts a remote address into an
29 type maker
func(remote
) eval
.Value
31 type remoteValue
interface {
35 // remote represents an address in a remote process.
41 func (v remote
) Get(a aborter
, size
int) uint64 {
42 // TODO(austin) This variable might temporarily be in a
43 // register. We could trace the assembly back from the
44 // current PC, looking for the beginning of the function or a
45 // call (both of which guarantee that the variable is in
46 // memory), or an instruction that loads the variable into a
49 // TODO(austin) If this is a local variable, it might not be
50 // live at this PC. In fact, because the compiler reuses
51 // slots, there might even be a different local variable at
52 // this location right now. A simple solution to both
53 // problems is to include the range of PC's over which a local
54 // variable is live in the symbol table.
56 // TODO(austin) We need to prevent the remote garbage
57 // collector from collecting objects out from under us.
60 _
, err
:= v
.p
.Peek(v
.base
, buf
)
64 return uint64(v
.p
.ToWord(buf
))
67 func (v remote
) Set(a aborter
, size
int, x
uint64) {
70 v
.p
.FromWord(proc
.Word(x
), buf
)
71 _
, err
:= v
.p
.Poke(v
.base
, buf
)
77 func (v remote
) plus(x proc
.Word
) remote
{ return remote
{v
.base
+ x
, v
.p
} }
79 func tryRVString(f
func(a aborter
) string) string {
81 err
:= try(func(a aborter
) { s
= f(a
) })
83 return fmt
.Sprintf("<error: %v>", err
)
92 type remoteBool
struct {
96 func (v remoteBool
) String() string {
97 return tryRVString(func(a aborter
) string { return fmt
.Sprintf("%v", v
.aGet(a
)) })
100 func (v remoteBool
) Assign(t
*eval
.Thread
, o eval
.Value
) {
101 v
.Set(t
, o
.(eval
.BoolValue
).Get(t
))
104 func (v remoteBool
) Get(t
*eval
.Thread
) bool { return v
.aGet(t
) }
106 func (v remoteBool
) aGet(a aborter
) bool { return v
.r
.Get(a
, 1) != 0 }
108 func (v remoteBool
) Set(t
*eval
.Thread
, x
bool) {
112 func (v remoteBool
) aSet(a aborter
, x
bool) {
120 func (v remoteBool
) addr() remote
{ return v
.r
}
122 func mkBool(r remote
) eval
.Value
{ return remoteBool
{r
} }
128 type remoteUint
struct {
133 func (v remoteUint
) String() string {
134 return tryRVString(func(a aborter
) string { return fmt
.Sprintf("%v", v
.aGet(a
)) })
137 func (v remoteUint
) Assign(t
*eval
.Thread
, o eval
.Value
) {
138 v
.Set(t
, o
.(eval
.UintValue
).Get(t
))
141 func (v remoteUint
) Get(t
*eval
.Thread
) uint64 {
145 func (v remoteUint
) aGet(a aborter
) uint64 { return v
.r
.Get(a
, v
.size
) }
147 func (v remoteUint
) Set(t
*eval
.Thread
, x
uint64) {
151 func (v remoteUint
) aSet(a aborter
, x
uint64) { v
.r
.Set(a
, v
.size
, x
) }
153 func (v remoteUint
) addr() remote
{ return v
.r
}
155 func mkUint8(r remote
) eval
.Value
{ return remoteUint
{r
, 1} }
157 func mkUint16(r remote
) eval
.Value
{ return remoteUint
{r
, 2} }
159 func mkUint32(r remote
) eval
.Value
{ return remoteUint
{r
, 4} }
161 func mkUint64(r remote
) eval
.Value
{ return remoteUint
{r
, 8} }
163 func mkUint(r remote
) eval
.Value
{ return remoteUint
{r
, r
.p
.IntSize()} }
165 func mkUintptr(r remote
) eval
.Value
{ return remoteUint
{r
, r
.p
.PtrSize()} }
171 type remoteInt
struct {
176 func (v remoteInt
) String() string {
177 return tryRVString(func(a aborter
) string { return fmt
.Sprintf("%v", v
.aGet(a
)) })
180 func (v remoteInt
) Assign(t
*eval
.Thread
, o eval
.Value
) {
181 v
.Set(t
, o
.(eval
.IntValue
).Get(t
))
184 func (v remoteInt
) Get(t
*eval
.Thread
) int64 { return v
.aGet(t
) }
186 func (v remoteInt
) aGet(a aborter
) int64 { return int64(v
.r
.Get(a
, v
.size
)) }
188 func (v remoteInt
) Set(t
*eval
.Thread
, x
int64) {
192 func (v remoteInt
) aSet(a aborter
, x
int64) { v
.r
.Set(a
, v
.size
, uint64(x
)) }
194 func (v remoteInt
) addr() remote
{ return v
.r
}
196 func mkInt8(r remote
) eval
.Value
{ return remoteInt
{r
, 1} }
198 func mkInt16(r remote
) eval
.Value
{ return remoteInt
{r
, 2} }
200 func mkInt32(r remote
) eval
.Value
{ return remoteInt
{r
, 4} }
202 func mkInt64(r remote
) eval
.Value
{ return remoteInt
{r
, 8} }
204 func mkInt(r remote
) eval
.Value
{ return remoteInt
{r
, r
.p
.IntSize()} }
210 type remoteFloat
struct {
215 func (v remoteFloat
) String() string {
216 return tryRVString(func(a aborter
) string { return fmt
.Sprintf("%v", v
.aGet(a
)) })
219 func (v remoteFloat
) Assign(t
*eval
.Thread
, o eval
.Value
) {
220 v
.Set(t
, o
.(eval
.FloatValue
).Get(t
))
223 func (v remoteFloat
) Get(t
*eval
.Thread
) float64 {
227 func (v remoteFloat
) aGet(a aborter
) float64 {
228 bits
:= v
.r
.Get(a
, v
.size
)
231 return float64(v
.r
.p
.ToFloat32(uint32(bits
)))
233 return v
.r
.p
.ToFloat64(bits
)
235 panic("Unexpected float size")
238 func (v remoteFloat
) Set(t
*eval
.Thread
, x
float64) {
242 func (v remoteFloat
) aSet(a aborter
, x
float64) {
246 bits
= uint64(v
.r
.p
.FromFloat32(float32(x
)))
248 bits
= v
.r
.p
.FromFloat64(x
)
250 panic("Unexpected float size")
252 v
.r
.Set(a
, v
.size
, bits
)
255 func (v remoteFloat
) addr() remote
{ return v
.r
}
257 func mkFloat32(r remote
) eval
.Value
{ return remoteFloat
{r
, 4} }
259 func mkFloat64(r remote
) eval
.Value
{ return remoteFloat
{r
, 8} }
261 func mkFloat(r remote
) eval
.Value
{ return remoteFloat
{r
, r
.p
.FloatSize()} }
267 type remoteString
struct {
271 func (v remoteString
) String() string {
272 return tryRVString(func(a aborter
) string { return v
.aGet(a
) })
275 func (v remoteString
) Assign(t
*eval
.Thread
, o eval
.Value
) {
276 v
.Set(t
, o
.(eval
.StringValue
).Get(t
))
279 func (v remoteString
) Get(t
*eval
.Thread
) string {
283 func (v remoteString
) aGet(a aborter
) string {
284 rs
:= v
.r
.p
.runtime
.String
.mk(v
.r
).(remoteStruct
)
285 str
:= proc
.Word(rs
.field(v
.r
.p
.f
.String
.Str
).(remoteUint
).aGet(a
))
286 len := rs
.field(v
.r
.p
.f
.String
.Len
).(remoteInt
).aGet(a
)
288 bytes
:= make([]uint8, len)
289 _
, err
:= v
.r
.p
.Peek(str
, bytes
)
296 func (v remoteString
) Set(t
*eval
.Thread
, x
string) {
300 func (v remoteString
) aSet(a aborter
, x
string) {
301 // TODO(austin) This isn't generally possible without the
302 // ability to allocate remote memory.
303 a
.Abort(ReadOnlyError("remote strings cannot be assigned to"))
306 func mkString(r remote
) eval
.Value
{ return remoteString
{r
} }
312 type remoteArray
struct {
318 func (v remoteArray
) String() string {
320 for i
:= int64(0); i
< v
.len; i
++ {
324 res
+= v
.elem(i
).String()
329 func (v remoteArray
) Assign(t
*eval
.Thread
, o eval
.Value
) {
330 // TODO(austin) Could do a bigger memcpy if o is a
331 // remoteArray in the same Process.
332 oa
:= o
.(eval
.ArrayValue
)
333 for i
:= int64(0); i
< v
.len; i
++ {
334 v
.Elem(t
, i
).Assign(t
, oa
.Elem(t
, i
))
338 func (v remoteArray
) Get(t
*eval
.Thread
) eval
.ArrayValue
{
342 func (v remoteArray
) Elem(t
*eval
.Thread
, i
int64) eval
.Value
{
346 func (v remoteArray
) elem(i
int64) eval
.Value
{
347 return v
.elemType
.mk(v
.r
.plus(proc
.Word(int64(v
.elemType
.size
) * i
)))
350 func (v remoteArray
) Sub(i
int64, len int64) eval
.ArrayValue
{
351 return remoteArray
{v
.r
.plus(proc
.Word(int64(v
.elemType
.size
) * i
)), len, v
.elemType
}
358 type remoteStruct
struct {
360 layout
[]remoteStructField
363 type remoteStructField
struct {
365 fieldType
*remoteType
368 func (v remoteStruct
) String() string {
370 for i
:= range v
.layout
{
374 res
+= v
.field(i
).String()
379 func (v remoteStruct
) Assign(t
*eval
.Thread
, o eval
.Value
) {
380 // TODO(austin) Could do a bigger memcpy.
381 oa
:= o
.(eval
.StructValue
)
383 for i
:= 0; i
< l
; i
++ {
384 v
.Field(t
, i
).Assign(t
, oa
.Field(t
, i
))
388 func (v remoteStruct
) Get(t
*eval
.Thread
) eval
.StructValue
{
392 func (v remoteStruct
) Field(t
*eval
.Thread
, i
int) eval
.Value
{
396 func (v remoteStruct
) field(i
int) eval
.Value
{
398 return f
.fieldType
.mk(v
.r
.plus(proc
.Word(f
.offset
)))
401 func (v remoteStruct
) addr() remote
{ return v
.r
}
407 // TODO(austin) Comparing two remote pointers for equality in the
408 // interpreter will crash it because the Value's returned from
409 // remotePtr.Get() will be structs.
411 type remotePtr
struct {
416 func (v remotePtr
) String() string {
417 return tryRVString(func(a aborter
) string {
422 return "&" + e
.String()
426 func (v remotePtr
) Assign(t
*eval
.Thread
, o eval
.Value
) {
427 v
.Set(t
, o
.(eval
.PtrValue
).Get(t
))
430 func (v remotePtr
) Get(t
*eval
.Thread
) eval
.Value
{
434 func (v remotePtr
) aGet(a aborter
) eval
.Value
{
435 addr
:= proc
.Word(v
.r
.Get(a
, v
.r
.p
.PtrSize()))
439 return v
.elemType
.mk(remote
{addr
, v
.r
.p
})
442 func (v remotePtr
) Set(t
*eval
.Thread
, x eval
.Value
) {
446 func (v remotePtr
) aSet(a aborter
, x eval
.Value
) {
448 v
.r
.Set(a
, v
.r
.p
.PtrSize(), 0)
451 xr
, ok
:= x
.(remoteValue
)
452 if !ok || v
.r
.p
!= xr
.addr().p
{
453 a
.Abort(RemoteMismatchError("remote pointer must point within the same process"))
455 v
.r
.Set(a
, v
.r
.p
.PtrSize(), uint64(xr
.addr().base
))
458 func (v remotePtr
) addr() remote
{ return v
.r
}
464 type remoteSlice
struct {
469 func (v remoteSlice
) String() string {
470 return tryRVString(func(a aborter
) string {
479 func (v remoteSlice
) Assign(t
*eval
.Thread
, o eval
.Value
) {
480 v
.Set(t
, o
.(eval
.SliceValue
).Get(t
))
483 func (v remoteSlice
) Get(t
*eval
.Thread
) eval
.Slice
{
487 func (v remoteSlice
) aGet(a aborter
) eval
.Slice
{
488 rs
:= v
.r
.p
.runtime
.Slice
.mk(v
.r
).(remoteStruct
)
489 base
:= proc
.Word(rs
.field(v
.r
.p
.f
.Slice
.Array
).(remoteUint
).aGet(a
))
490 nel
:= rs
.field(v
.r
.p
.f
.Slice
.Len
).(remoteInt
).aGet(a
)
491 cap := rs
.field(v
.r
.p
.f
.Slice
.Cap
).(remoteInt
).aGet(a
)
493 return eval
.Slice
{nil, nel
, cap}
495 return eval
.Slice
{remoteArray
{remote
{base
, v
.r
.p
}, nel
, v
.elemType
}, nel
, cap}
498 func (v remoteSlice
) Set(t
*eval
.Thread
, x eval
.Slice
) {
502 func (v remoteSlice
) aSet(a aborter
, x eval
.Slice
) {
503 rs
:= v
.r
.p
.runtime
.Slice
.mk(v
.r
).(remoteStruct
)
505 rs
.field(v
.r
.p
.f
.Slice
.Array
).(remoteUint
).aSet(a
, 0)
507 ar
, ok
:= x
.Base
.(remoteArray
)
508 if !ok || v
.r
.p
!= ar
.r
.p
{
509 a
.Abort(RemoteMismatchError("remote slice must point within the same process"))
511 rs
.field(v
.r
.p
.f
.Slice
.Array
).(remoteUint
).aSet(a
, uint64(ar
.r
.base
))
513 rs
.field(v
.r
.p
.f
.Slice
.Len
).(remoteInt
).aSet(a
, x
.Len
)
514 rs
.field(v
.r
.p
.f
.Slice
.Cap
).(remoteInt
).aSet(a
, x
.Cap
)