Package vtrace :: Module snapshot
[hide private]
[frames] | no frames]

Source Code for Module vtrace.snapshot

  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  
 
17 -class TraceSnapshot( 18 vtrace.Trace, 19 v_base.TracerBase, 20 ):
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 """
29 - def __init__(self, snapdict):
30 31 self.s_snapcache = {} 32 self.s_snapdict = snapdict 33 34 # a seperate parser for each version... 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 # In the ghetto! 50 archname = self.metadata.get('Architecture') 51 envi.stealArchMethods(self, archname) 52 53 vtrace.Trace.__init__(self) 54 v_base.TracerBase.__init__(self) 55 # This will re-init meta... *sigh* set it back... 56 self.metadata = snapdict['meta'] 57 58 # Steal the reg defs of the first thread 59 rinfo = self.s_regs.items()[0][1] 60 self.setRegisterInfo(rinfo) 61 62 #FIXME hard-coded page size! 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 # Lets get some symbol resolvers created for our libraries 69 #for fname in self.getNormalizedLibNames(): 70 #subres = e_resolv.FileSymbol(fname, 71 72 self.running = False 73 self.attached = True 74 # So that we pickle 75 self.bplock = None 76 self.thread = None
77
78 - def saveToFd(self, fd):
79 ''' 80 Save this snapshot to the given file like object 81 for later reloading... 82 ''' 83 pickle.dump(self.s_snapdict, fd)
84
85 - def saveToFile(self, filename):
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
93 - def getMemoryMap(self, addr):
94 base = addr & 0xfffff000 95 return self.s_map_lookup.get(base, None)
96
97 - def platformGetFds(self):
98 return self.s_fds
99
100 - def getExe(self):
101 return self.s_exe
102
103 - def getStackTrace(self):
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
110 - def platformGetRegCtx(self, thrid):
111 rinfo = self.s_regs.get(thrid) 112 ctx = self.archGetRegCtx() 113 ctx.setRegisterInfo(rinfo) 114 return ctx
115
116 - def platformGetMaps(self):
117 return self.s_maps
118
119 - def platformGetThreads(self):
120 return self.s_threads
121
122 - def platformReadMemory(self, address, size):
123 map = self.getMemoryMap(address) 124 if map == None: 125 raise Exception("ERROR: platformReadMemory says no map for 0x%.8x" % address) 126 offset = address - map[0] # Base address 127 mapbytes = self.s_mem.get(map[0], None) 128 if mapbytes == None: 129 raise vtrace.PlatformException("ERROR: Memory map at 0x%.8x is not backed!" % map[0]) 130 if len(mapbytes) == 0: 131 raise vtrace.PlatformException("ERROR: Memory Map at 0x%.8x is backed by ''" % map[0]) 132 133 ret = mapbytes[offset:offset+size] 134 rlen = len(ret) 135 # We may have a cross-map read, just recurse for the rest 136 if rlen != size: 137 ret += self.platformReadMemory(address+rlen, size-rlen) 138 return ret
139
140 - def platformWriteMemory(self, address, bytes):
141 map = self.getMemoryMap(address) 142 if map == None: 143 raise Exception("ERROR: platformWriteMemory says no map for 0x%.8x" % address) 144 offset = address - map[0] 145 mapbytes = self.s_mem[map[0]] 146 self.s_mem[map[0]] = mapbytes[:offset] + bytes + mapbytes[offset+len(bytes):]
147
148 - def platformDetach(self):
149 pass
150
151 - def platformParseBinary(self, *args):
152 print 'FIXME FAKE PLATFORM PARSE BINARY: %s' % repr(args)
153 154 # Over-ride register *caching* subsystem to store/retrieve 155 # register information in pure dictionaries
156 - def cacheRegs(self, threadid):
157 pass
158 159 # FIXME regs in snapshots are broke... 160
161 - def syncRegs(self):
162 pass
163
164 -def loadSnapshot(filename):
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
172 -def takeSnapshot(trace):
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 # If the contents here change, change the version... 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