summaryrefslogtreecommitdiff
path: root/usr/austin/ogle/rvalue.go
diff options
context:
space:
mode:
Diffstat (limited to 'usr/austin/ogle/rvalue.go')
-rw-r--r--usr/austin/ogle/rvalue.go246
1 files changed, 162 insertions, 84 deletions
diff --git a/usr/austin/ogle/rvalue.go b/usr/austin/ogle/rvalue.go
index 9e5a6ab55..1449ed660 100644
--- a/usr/austin/ogle/rvalue.go
+++ b/usr/austin/ogle/rvalue.go
@@ -7,6 +7,7 @@ package ogle
import (
"eval";
"fmt";
+ "os";
"ptrace";
)
@@ -34,7 +35,7 @@ type remote struct {
p *Process;
}
-func (v remote) Get(size int) uint64 {
+func (v remote) Get(a aborter, size int) uint64 {
// TODO(austin) This variable might temporarily be in a
// register. We could trace the assembly back from the
// current PC, looking for the beginning of the function or a
@@ -55,18 +56,18 @@ func (v remote) Get(size int) uint64 {
buf := arr[0:size];
_, err := v.p.Peek(v.base, buf);
if err != nil {
- eval.Abort(err);
+ a.Abort(err);
}
return uint64(v.p.ToWord(buf));
}
-func (v remote) Set(size int, x uint64) {
+func (v remote) Set(a aborter, size int, x uint64) {
var arr [8]byte;
buf := arr[0:size];
v.p.FromWord(ptrace.Word(x), buf);
_, err := v.p.Poke(v.base, buf);
if err != nil {
- eval.Abort(err);
+ a.Abort(err);
}
}
@@ -74,6 +75,15 @@ func (v remote) plus(x ptrace.Word) remote {
return remote{v.base + x, v.p};
}
+func tryRVString(f func(a aborter) string) string {
+ var s string;
+ err := try(func(a aborter) { s = f(a) });
+ if err != nil {
+ return fmt.Sprintf("<error: %v>", err);
+ }
+ return s;
+}
+
/*
* Bool
*/
@@ -83,22 +93,30 @@ type remoteBool struct {
}
func (v remoteBool) String() string {
- return fmt.Sprintf("%v", v.Get());
+ return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) });
+}
+
+func (v remoteBool) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.BoolValue).Get(t));
+}
+
+func (v remoteBool) Get(t *eval.Thread) bool {
+ return v.aGet(t);
}
-func (v remoteBool) Assign(o eval.Value) {
- v.Set(o.(eval.BoolValue).Get());
+func (v remoteBool) aGet(a aborter) bool {
+ return v.r.Get(a, 1) != 0;
}
-func (v remoteBool) Get() bool {
- return v.r.Get(1) != 0;
+func (v remoteBool) Set(t *eval.Thread, x bool) {
+ v.aSet(t, x);
}
-func (v remoteBool) Set(x bool) {
+func (v remoteBool) aSet(a aborter, x bool) {
if x {
- v.r.Set(1, 1);
+ v.r.Set(a, 1, 1);
} else {
- v.r.Set(1, 0);
+ v.r.Set(a, 1, 0);
}
}
@@ -120,19 +138,27 @@ type remoteUint struct {
}
func (v remoteUint) String() string {
- return fmt.Sprintf("%v", v.Get());
+ return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) });
+}
+
+func (v remoteUint) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.UintValue).Get(t));
}
-func (v remoteUint) Assign(o eval.Value) {
- v.Set(o.(eval.UintValue).Get());
+func (v remoteUint) Get(t *eval.Thread) uint64 {
+ return v.aGet(t);
}
-func (v remoteUint) Get() uint64 {
- return v.r.Get(v.size);
+func (v remoteUint) aGet(a aborter) uint64 {
+ return v.r.Get(a, v.size);
}
-func (v remoteUint) Set(x uint64) {
- v.r.Set(v.size, x);
+func (v remoteUint) Set(t *eval.Thread, x uint64) {
+ v.aSet(t, x);
+}
+
+func (v remoteUint) aSet(a aborter, x uint64) {
+ v.r.Set(a, v.size, x);
}
func (v remoteUint) addr() remote {
@@ -173,19 +199,27 @@ type remoteInt struct {
}
func (v remoteInt) String() string {
- return fmt.Sprintf("%v", v.Get());
+ return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) });
+}
+
+func (v remoteInt) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.IntValue).Get(t));
+}
+
+func (v remoteInt) Get(t *eval.Thread) int64 {
+ return v.aGet(t);
}
-func (v remoteInt) Assign(o eval.Value) {
- v.Set(o.(eval.IntValue).Get());
+func (v remoteInt) aGet(a aborter) int64 {
+ return int64(v.r.Get(a, v.size));
}
-func (v remoteInt) Get() int64 {
- return int64(v.r.Get(v.size));
+func (v remoteInt) Set(t *eval.Thread, x int64) {
+ v.aSet(t, x);
}
-func (v remoteInt) Set(x int64) {
- v.r.Set(v.size, uint64(x));
+func (v remoteInt) aSet(a aborter, x int64) {
+ v.r.Set(a, v.size, uint64(x));
}
func (v remoteInt) addr() remote {
@@ -222,15 +256,19 @@ type remoteFloat struct {
}
func (v remoteFloat) String() string {
- return fmt.Sprintf("%v", v.Get());
+ return tryRVString(func(a aborter) string { return fmt.Sprintf("%v", v.aGet(a)) });
+}
+
+func (v remoteFloat) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.FloatValue).Get(t));
}
-func (v remoteFloat) Assign(o eval.Value) {
- v.Set(o.(eval.FloatValue).Get());
+func (v remoteFloat) Get(t *eval.Thread) float64 {
+ return v.aGet(t);
}
-func (v remoteFloat) Get() float64 {
- bits := v.r.Get(v.size);
+func (v remoteFloat) aGet(a aborter) float64 {
+ bits := v.r.Get(a, v.size);
switch v.size {
case 4:
return float64(v.r.p.ToFloat32(uint32(bits)));
@@ -240,7 +278,11 @@ func (v remoteFloat) Get() float64 {
panic("Unexpected float size ", v.size);
}
-func (v remoteFloat) Set(x float64) {
+func (v remoteFloat) Set(t *eval.Thread, x float64) {
+ v.aSet(t, x);
+}
+
+func (v remoteFloat) aSet(a aborter, x float64) {
var bits uint64;
switch v.size{
case 4:
@@ -250,7 +292,7 @@ func (v remoteFloat) Set(x float64) {
default:
panic("Unexpected float size ", v.size);
}
- v.r.Set(v.size, bits);
+ v.r.Set(a, v.size, bits);
}
func (v remoteFloat) addr() remote {
@@ -278,30 +320,38 @@ type remoteString struct {
}
func (v remoteString) String() string {
- return v.Get();
+ return tryRVString(func(a aborter) string { return v.aGet(a) });
}
-func (v remoteString) Assign(o eval.Value) {
- v.Set(o.(eval.StringValue).Get());
+func (v remoteString) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.StringValue).Get(t));
}
-func (v remoteString) Get() string {
+func (v remoteString) Get(t *eval.Thread) string {
+ return v.aGet(t);
+}
+
+func (v remoteString) aGet(a aborter) string {
rs := v.r.p.runtime.String.mk(v.r).(remoteStruct);
- str := ptrace.Word(rs.Field(v.r.p.f.String.Str).(remoteUint).Get());
- len := rs.Field(v.r.p.f.String.Len).(remoteInt).Get();
+ str := ptrace.Word(rs.field(v.r.p.f.String.Str).(remoteUint).aGet(a));
+ len := rs.field(v.r.p.f.String.Len).(remoteInt).aGet(a);
bytes := make([]uint8, len);
_, err := v.r.p.Peek(str, bytes);
if err != nil {
- eval.Abort(err);
+ a.Abort(err);
}
return string(bytes);
}
-func (v remoteString) Set(x string) {
+func (v remoteString) Set(t *eval.Thread, x string) {
+ v.aSet(t, x);
+}
+
+func (v remoteString) aSet(a aborter, x string) {
// TODO(austin) This isn't generally possible without the
// ability to allocate remote memory.
- eval.Abort(RemoteMismatchError("remote strings cannot be assigned to"));
+ a.Abort(RemoteMismatchError("remote strings cannot be assigned to"));
}
func mkString(r remote) eval.Value {
@@ -324,30 +374,34 @@ func (v remoteArray) String() string {
if i > 0 {
res += ", ";
}
- res += v.Elem(i).String();
+ res += v.elem(i).String();
}
return res + "}";
}
-func (v remoteArray) Assign(o eval.Value) {
+func (v remoteArray) Assign(t *eval.Thread, o eval.Value) {
// TODO(austin) Could do a bigger memcpy if o is a
// remoteArray in the same Process.
oa := o.(eval.ArrayValue);
for i := int64(0); i < v.len; i++ {
- v.Elem(i).Assign(oa.Elem(i));
+ v.Elem(t, i).Assign(t, oa.Elem(t, i));
}
}
-func (v remoteArray) Get() eval.ArrayValue {
+func (v remoteArray) Get(t *eval.Thread) eval.ArrayValue {
return v;
}
-func (v remoteArray) Elem(i int64) eval.Value {
+func (v remoteArray) Elem(t *eval.Thread, i int64) eval.Value {
+ return v.elem(i);
+}
+
+func (v remoteArray) elem(i int64) eval.Value {
return v.elemType.mk(v.r.plus(ptrace.Word(int64(v.elemType.size) * i)));
}
-func (v remoteArray) From(i int64) eval.ArrayValue {
- return remoteArray{v.r.plus(ptrace.Word(int64(v.elemType.size) * i)), v.len - i, v.elemType};
+func (v remoteArray) Sub(i int64, len int64) eval.ArrayValue {
+ return remoteArray{v.r.plus(ptrace.Word(int64(v.elemType.size) * i)), len, v.elemType};
}
/*
@@ -370,25 +424,29 @@ func (v remoteStruct) String() string {
if i > 0 {
res += ", ";
}
- res += v.Field(i).String();
+ res += v.field(i).String();
}
return res + "}";
}
-func (v remoteStruct) Assign(o eval.Value) {
+func (v remoteStruct) Assign(t *eval.Thread, o eval.Value) {
// TODO(austin) Could do a bigger memcpy.
oa := o.(eval.StructValue);
l := len(v.layout);
for i := 0; i < l; i++ {
- v.Field(i).Assign(oa.Field(i));
+ v.Field(t, i).Assign(t, oa.Field(t, i));
}
}
-func (v remoteStruct) Get() eval.StructValue {
+func (v remoteStruct) Get(t *eval.Thread) eval.StructValue {
return v;
}
-func (v remoteStruct) Field(i int) eval.Value {
+func (v remoteStruct) Field(t *eval.Thread, i int) eval.Value {
+ return v.field(i);
+}
+
+func (v remoteStruct) field(i int) eval.Value {
f := &v.layout[i];
return f.fieldType.mk(v.r.plus(ptrace.Word(f.offset)));
}
@@ -411,35 +469,45 @@ type remotePtr struct {
}
func (v remotePtr) String() string {
- e := v.Get();
- if e == nil {
- return "<nil>";
- }
- return "&" + e.String();
+ return tryRVString(func(a aborter) string {
+ e := v.aGet(a);
+ if e == nil {
+ return "<nil>";
+ }
+ return "&" + e.String();
+ });
}
-func (v remotePtr) Assign(o eval.Value) {
- v.Set(o.(eval.PtrValue).Get());
+func (v remotePtr) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.PtrValue).Get(t));
}
-func (v remotePtr) Get() eval.Value {
- addr := ptrace.Word(v.r.Get(v.r.p.PtrSize()));
+func (v remotePtr) Get(t *eval.Thread) eval.Value {
+ return v.aGet(t);
+}
+
+func (v remotePtr) aGet(a aborter) eval.Value {
+ addr := ptrace.Word(v.r.Get(a, v.r.p.PtrSize()));
if addr == 0 {
return nil;
}
return v.elemType.mk(remote{addr, v.r.p});
}
-func (v remotePtr) Set(x eval.Value) {
+func (v remotePtr) Set(t *eval.Thread, x eval.Value) {
+ v.aSet(t, x);
+}
+
+func (v remotePtr) aSet(a aborter, x eval.Value) {
if x == nil {
- v.r.Set(v.r.p.PtrSize(), 0);
+ v.r.Set(a, v.r.p.PtrSize(), 0);
return;
}
xr, ok := x.(remoteValue);
if !ok || v.r.p != xr.addr().p {
- eval.Abort(RemoteMismatchError("remote pointer must point within the same process"));
+ a.Abort(RemoteMismatchError("remote pointer must point within the same process"));
}
- v.r.Set(v.r.p.PtrSize(), uint64(xr.addr().base));
+ v.r.Set(a, v.r.p.PtrSize(), uint64(xr.addr().base));
}
func (v remotePtr) addr() remote {
@@ -456,39 +524,49 @@ type remoteSlice struct {
}
func (v remoteSlice) String() string {
- b := v.Get().Base;
- if b == nil {
- return "<nil>";
- }
- return b.String();
+ return tryRVString(func(a aborter) string {
+ b := v.aGet(a).Base;
+ if b == nil {
+ return "<nil>";
+ }
+ return b.String();
+ });
+}
+
+func (v remoteSlice) Assign(t *eval.Thread, o eval.Value) {
+ v.Set(t, o.(eval.SliceValue).Get(t));
}
-func (v remoteSlice) Assign(o eval.Value) {
- v.Set(o.(eval.SliceValue).Get());
+func (v remoteSlice) Get(t *eval.Thread) eval.Slice {
+ return v.aGet(t);
}
-func (v remoteSlice) Get() eval.Slice {
+func (v remoteSlice) aGet(a aborter) eval.Slice {
rs := v.r.p.runtime.Slice.mk(v.r).(remoteStruct);
- base := ptrace.Word(rs.Field(v.r.p.f.Slice.Array).(remoteUint).Get());
- nel := rs.Field(v.r.p.f.Slice.Len).(remoteInt).Get();
- cap := rs.Field(v.r.p.f.Slice.Cap).(remoteInt).Get();
+ base := ptrace.Word(rs.field(v.r.p.f.Slice.Array).(remoteUint).aGet(a));
+ nel := rs.field(v.r.p.f.Slice.Len).(remoteInt).aGet(a);
+ cap := rs.field(v.r.p.f.Slice.Cap).(remoteInt).aGet(a);
if base == 0 {
return eval.Slice{nil, nel, cap};
}
return eval.Slice{remoteArray{remote{base, v.r.p}, nel, v.elemType}, nel, cap};
}
-func (v remoteSlice) Set(x eval.Slice) {
+func (v remoteSlice) Set(t *eval.Thread, x eval.Slice) {
+ v.aSet(t, x);
+}
+
+func (v remoteSlice) aSet(a aborter, x eval.Slice) {
rs := v.r.p.runtime.Slice.mk(v.r).(remoteStruct);
if x.Base == nil {
- rs.Field(v.r.p.f.Slice.Array).(remoteUint).Set(0);
+ rs.field(v.r.p.f.Slice.Array).(remoteUint).aSet(a, 0);
} else {
ar, ok := x.Base.(remoteArray);
if !ok || v.r.p != ar.r.p {
- eval.Abort(RemoteMismatchError("remote slice must point within the same process"));
+ a.Abort(RemoteMismatchError("remote slice must point within the same process"));
}
- rs.Field(v.r.p.f.Slice.Array).(remoteUint).Set(uint64(ar.r.base));
+ rs.field(v.r.p.f.Slice.Array).(remoteUint).aSet(a, uint64(ar.r.base));
}
- rs.Field(v.r.p.f.Slice.Len).(remoteInt).Set(x.Len);
- rs.Field(v.r.p.f.Slice.Cap).(remoteInt).Set(x.Cap);
+ rs.field(v.r.p.f.Slice.Len).(remoteInt).aSet(a, x.Len);
+ rs.field(v.r.p.f.Slice.Cap).(remoteInt).aSet(a, x.Cap);
}