-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcontext_captured.go
143 lines (116 loc) · 3.32 KB
/
context_captured.go
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
package mimic
import (
"bytes"
"encoding/base64"
"encoding/json"
"github.com/cilium/ebpf/asm"
)
func unmarshalCaptured(name string, ctx json.RawMessage) (Context, error) {
var cc CapturedContext
err := json.Unmarshal(ctx, &cc)
if err != nil {
return nil, err
}
cc.Sub, err = UnmarshalContextJSON(bytes.NewReader(cc.RawSub))
if err != nil {
return nil, err
}
return &cc, nil
}
// CapturedContext wraps another context and adds captured helper call data to it which the LinuxEmulator can use
// to replay helper calls instead of actually emulating them, or doing both in some cases.
type CapturedContext struct {
Sub Context `json:"-"`
RawSub json.RawMessage `json:"subContext"`
HelperCalls map[string][]CapturedContextHelperCall `json:"helperCalls"`
}
// MarshalJSON implements json.Marshaler
func (cc *CapturedContext) MarshalJSON() ([]byte, error) {
type Alias CapturedContext
a := Alias(*cc)
subBytes, err := json.Marshal(cc.Sub)
if err != nil {
return nil, err
}
a.RawSub = json.RawMessage(subBytes)
b, err := json.Marshal(a)
if err != nil {
return nil, err
}
proto := protoCtx{
Name: cc.Sub.GetName(),
Type: "captured",
Ctx: b,
}
return json.Marshal(proto)
}
// GetName returns the name of the context
func (cc *CapturedContext) GetName() string {
return cc.Sub.GetName()
}
// SetName sets the name of the context
func (cc *CapturedContext) SetName(name string) {
cc.Sub.SetName(name)
}
// Load loads the sub-context into memory
func (cc *CapturedContext) Load(process *Process) error {
return cc.Sub.Load(process)
}
// Cleanup cleans up the allocated memory of the sub-context
func (cc *CapturedContext) Cleanup(process *Process) error {
return cc.Sub.Cleanup(process)
}
// CapturedContextHelperCall describes a single call to a helper function
type CapturedContextHelperCall struct {
HelperFn asm.BuiltinFunc `json:"helperFn"`
Params []CapturedContextRegisterData `json:"params"`
Result []CapturedContextRegisterData `json:"results"`
}
// CapturedContextRegisterData describes the contexts of a register
type CapturedContextRegisterData struct {
Reg asm.Register `json:"reg"`
Value json.RawMessage `json:"value"`
Scalar uint64 `json:"-"`
Data []byte `json:"-"`
}
// UnmarshalJSON implements json.Unmarshaler
func (crd *CapturedContextRegisterData) UnmarshalJSON(data []byte) error {
type alias CapturedContextRegisterData
var a alias
err := json.Unmarshal(data, &a)
if err != nil {
return err
}
crd.Reg = a.Reg
if err = json.Unmarshal(a.Value, &crd.Scalar); err != nil {
var str string
if err = json.Unmarshal(a.Value, &str); err != nil {
return err
}
crd.Data, err = base64.StdEncoding.DecodeString(str)
if err != nil {
return err
}
}
return nil
}
// MarshalJSON implements json.Marshaler
func (crd *CapturedContextRegisterData) MarshalJSON() ([]byte, error) {
type alias CapturedContextRegisterData
var a alias
a.Reg = crd.Reg
if len(crd.Data) > 0 {
base64Json, err := json.Marshal(base64.StdEncoding.EncodeToString(crd.Data))
if err != nil {
return nil, err
}
a.Value = json.RawMessage(base64Json)
} else {
intJSON, err := json.Marshal(crd.Scalar)
if err != nil {
return nil, err
}
a.Value = json.RawMessage(intJSON)
}
return json.Marshal(a)
}