1 '''
2 The stalker subsystem is a breakpoint based coverage tool
3 '''
4
5 import vtrace
6
7 import envi
8 import envi.memory as e_mem
9 import envi.codeflow as e_codeflow
10
12
17
19 self.mmap = mmap
20 self.bplist = []
21 self.sbreaks = []
22 self.scbreaks = []
23
25
26 ret = []
27
28 for br,bflags in branches:
29
30 if bflags & envi.BR_DEREF and br != None:
31 bflags &= ~envi.BR_DEREF
32 if not self.trace.probeMemory(br, 1, e_mem.MM_READ):
33 continue
34
35 br = self.trace.readMemoryFormat(br, '<P')[0]
36
37
38 if br != None and self.trace.getMemoryMap(br) != self.mmap:
39 continue
40
41 ret.append( (br, bflags) )
42
43
44
45 if bflags & envi.BR_PROC:
46 if br == None:
47 self.scbreaks.append(op.va)
48 else:
49 self.sbreaks.append(br)
50 continue
51
52 if br == None:
53
54 self.scbreaks.append(op.va)
55 continue
56
57
58 if bflags & envi.BR_COND:
59 self.bplist.append(br)
60 continue
61
62
63 if br != op.va + len(op):
64 self.bplist.append(br)
65 continue
66
67 return ret
68
70
71 '''
72 Stalker breakpoints are added to function entry points
73 to trigger code-flow analysis and subsequent block breakpoint
74 addition.
75 '''
76
77 - def __init__(self, address, expression=None):
81
85
86 - def notify(self, event, trace):
87 self.trace = trace
88
89
90 self.enabled = False
91 self.deactivate(trace)
92
93 breaks = trace.getMeta('StalkerBreaks')
94 h = trace.getMeta('StalkerHits')
95 h.append(self.address)
96
97 cf = trace.getMeta('StalkerCodeFlow')
98 if cf == None:
99 cf = StalkerCodeFlow(trace)
100 trace.setMeta('StalkerCodeFlow', cf)
101
102 cf.setupBreakLists(self.mymap)
103 cf.addCodeFlow(self.address, persist=True)
104
105 for va in cf.bplist:
106 if breaks.get(va):
107 continue
108 breaks[va] = True
109
110 b = StalkerBlockBreak(va)
111 bid = trace.addBreakpoint(b)
112
113 for va in cf.sbreaks:
114 if breaks.get(va):
115 continue
116 breaks[va] = True
117
118 b = StalkerBreak(va)
119 bid = trace.addBreakpoint(b)
120
121 for va in cf.scbreaks:
122 if breaks.get(va):
123 continue
124 breaks[va] = True
125
126 b = StalkerDynBreak(va)
127 bid = trace.addBreakpoint(b)
128
130 '''
131 A breakpoint object which is put on codeblock boundaries
132 to track hits.
133 '''
134
135 - def __init__(self, address, expression=None):
138
139 - def notify(self, event, trace):
145
147
148 '''
149 A breakpoint which is placed on dynamic branches to track
150 code flow across them.
151 '''
152
153 - def __init__(self, address, expression=None):
159
163
164 - def notify(self, event, trace):
165
166 trace.runAgain()
167
168 self.deactivate(trace)
169 op = trace.parseOpcode(self.address)
170
171 dva = op.getOperValue(0, emu=trace)
172
173 if self.lasthit == dva:
174 self.lastcnt += 1
175 else:
176 self.lasthit = dva
177 self.lastcnt = 0
178
179
180 if trace.getMemoryMap(dva) == self.mymap:
181 addStalkerEntry(trace, dva)
182
183 if self.lastcnt > 10:
184 self.lasthit = None
185 self.lastcnt = 0
186 self.enabled = False
187 else:
188 self.activate(trace)
189
191 if trace.getMeta('StalkerBreaks') == None:
192 trace.setMeta('StalkerBreaks', {})
193 trace.setMeta('StalkerHits', [])
194
196 '''
197 Clear the stalker hit list for the given trace
198 '''
199 initStalker(trace)
200 trace.setMeta('StalkerHits', [])
201
203 '''
204 Retrieve the list of blocks hit in the current stalker
205 '''
206 initStalker(trace)
207 return trace.getMeta('StalkerHits', [])
208
210 '''
211 Cleanup all stalker breaks and metadata
212 '''
213 initStalker(trace)
214 breaks = trace.getMeta('StalkerBreaks', {})
215 trace.setMeta('StalkerCodeFlow', None)
216 bpaddrs = list(breaks.keys())
217 for va in bpaddrs:
218 bp = trace.getBreakpointByAddr(va)
219 if bp != None:
220 trace.removeBreakpoint(bp.id)
221 breaks.pop(va, None)
222
224 '''
225 Re-enable all previously hit stalker breakpoints.
226 '''
227 initStalker(trace)
228 breaks = trace.getMeta('StalkerBreaks', {})
229 bpaddrs = list(breaks.keys())
230 trace.fb_bp_done = False
231 for va in bpaddrs:
232 bp = trace.getBreakpointByAddr(va)
233 if bp != None:
234 trace.setBreakpointEnabled(bp.id, enabled=True)
235
236 -def addStalkerEntry(trace, va):
237 '''
238 Add stalker coverage beginning with the specified entry point
239 '''
240 initStalker(trace)
241 b = trace.getMeta('StalkerBreaks')
242 if b.get(va):
243 return
244 bp = StalkerBreak(va)
245 trace.addBreakpoint(bp)
246 b[va] = True
247