1 """
2 All the code related to vtrace process snapshots
3 and TraceSnapshot classes.
4 """
5
6 import sys
7 import copy
8 import cPickle as pickle
9
10 import envi
11 import envi.memory as e_mem
12 import envi.resolver as e_resolv
13
14 import vtrace
15 import vtrace.platforms.base as v_base
16
21 """
22 A tracer snapshot is similar to a traditional "core file" except that
23 you may also have memory only snapshots that are never written to disk.
24
25 TraceSnapshots allow you to take a picture of a process from a given point
26 in it's execution and manipulate/test from there or save it to disk for later
27 analysis...
28 """
30
31 self.s_snapcache = {}
32 self.s_snapdict = snapdict
33
34
35 if snapdict['version'] == 1:
36 self.s_version = snapdict['version']
37 self.s_threads = snapdict['threads']
38 self.s_regs = snapdict['regs']
39 self.s_maps = snapdict['maps']
40 self.s_mem = snapdict['mem']
41 self.metadata = snapdict['meta']
42 self.s_stacktrace = snapdict['stacktrace']
43 self.s_exe = snapdict['exe']
44 self.s_fds = snapdict['fds']
45 self.localvars = snapdict.get('vars', {})
46 else:
47 raise Exception("ERROR: Unknown snapshot version!")
48
49
50 archname = self.metadata.get('Architecture')
51 envi.stealArchMethods(self, archname)
52
53 vtrace.Trace.__init__(self)
54 v_base.TracerBase.__init__(self)
55
56 self.metadata = snapdict['meta']
57
58
59 rinfo = self.s_regs.items()[0][1]
60 self.setRegisterInfo(rinfo)
61
62
63 self.s_map_lookup = {}
64 for map in self.s_maps:
65 for i in range(map[0],map[0] + map[1], 4096):
66 self.s_map_lookup[i] = map
67
68
69
70
71
72 self.running = False
73 self.attached = True
74
75 self.bplock = None
76 self.thread = None
77
79 '''
80 Save this snapshot to the given file like object
81 for later reloading...
82 '''
83 pickle.dump(self.s_snapdict, fd)
84
86 """
87 Save a snapshot to file for later reading in...
88 """
89 f = file(filename, "wb")
90 self.saveToFd(f)
91 f.close()
92
94 base = addr & 0xfffff000
95 return self.s_map_lookup.get(base, None)
96
99
102
104 tid = self.getMeta("ThreadId")
105 tr = self.s_stacktrace.get(tid, None)
106 if tr == None:
107 raise Exception("ERROR: Invalid thread id specified")
108 return tr
109
115
118
121
139
147
150
153
154
155
158
159
160
163
165 '''
166 Load a vtrace process snapshot from a file
167 '''
168 sfile = file(filename, "rb")
169 snapdict = pickle.load(sfile)
170 return TraceSnapshot(snapdict)
171
173 """
174 Take a snapshot of the process from the current state and return
175 a reference to a tracer which wraps a "snapshot" or "core file".
176 """
177 sd = dict()
178 orig_thread = trace.getMeta("ThreadId")
179
180 regs = dict()
181 stacktrace = dict()
182
183 for thrid,tdata in trace.getThreads().items():
184 ctx = trace.getRegisterContext(thrid)
185 reginfo = ctx.getRegisterInfo()
186 regs[thrid] = reginfo
187 try:
188 stacktrace[thrid] = trace.getStackTrace()
189 except Exception, msg:
190 print >> sys.stderr, "WARNING: Failed to get stack trace for thread 0x%.8x" % thrid
191
192 mem = dict()
193 maps = []
194 for base,size,perms,fname in trace.getMemoryMaps():
195 try:
196 mem[base] = trace.readMemory(base, size)
197 maps.append((base,size,perms,fname))
198 except Exception, msg:
199 print >> sys.stderr, "WARNING: Can't snapshot memmap at 0x%.8x (%s)" % (base,msg)
200
201
202 sd['version'] = 1
203 sd['threads'] = trace.getThreads()
204 sd['regs'] = regs
205 sd['maps'] = maps
206 sd['mem'] = mem
207 sd['meta'] = copy.deepcopy(trace.metadata)
208 sd['stacktrace'] = stacktrace
209 sd['exe'] = trace.getExe()
210 sd['fds'] = trace.getFds()
211 sd['vars'] = trace.localvars
212
213 return TraceSnapshot(snapdict=sd)
214