1 """
2 A unified memory analysis view
3 """
4
5 import os
6 import gtk
7 import gtk.gdk as gdk
8
9 import vwidget.views as vw_views
10 from vwidget.main import idlethread, idlethreadsync
11
12 import envi
13 import envi.memcanvas as e_canvas
14
15
16 moddir = os.path.dirname(__file__)
17
18
19
20 KEYCODE_esc = 0xff1b
21
22 -class VaTag(vw_views.VRevTextTag):
28
29 -class MemoryView(vw_views.VTextView, e_canvas.MemoryCanvas):
30 """
31 A MemoryCanvas compliant GTK TextView.
32 """
33
35 vw_views.VTextView.__init__(self)
36 self.textview.set_editable(False)
37 e_canvas.MemoryCanvas.__init__(self, memobj, syms=syms)
38 self.iter = self.vwGetAppendIter()
39 self.lastsize = 32
40
41
42 self.memwin = None
43
44 self.vatag = None
45 self.selectva = None
46
47
48 self.markmap = {}
49 self.beginva = None
50 self.endva = None
51
52 self.valist = []
53 self.histindex = None
54
55 self.colormap = None
56
57
58
59 fullpath = os.path.join(moddir,"memview.conf")
60 self.vwLoadTags(fullpath)
61
62 self.hotkeys = {}
63 self.textview.connect("key_press_event", self.keyPressed)
64 self.textview.connect("move_cursor", self.cursorMoved)
65
66 self.registerHotKey(KEYCODE_esc, self.goback)
67
68 @idlethread
70 oldmap = None
71 if self.colormap != None:
72 oldmap = self.colormap
73
74 self.colormap = map
75
76 if oldmap:
77 for va in oldmap.keys():
78 tag = self.getVaTag(va)
79 self.vwSetTagColor(tag, "va")
80
81 if self.colormap:
82 for va,color in self.colormap.items():
83 tag = self.getVaTag(va)
84 tag.set_property('background', color)
85 tag.set_property('foreground', 'black')
86
88 self.hotkeys[keycode] = (callback,args,kwargs)
89
91 hkinfo = self.hotkeys.get(event.keyval)
92 if hkinfo == None:
93 return
94 callback,args,kwargs = hkinfo
95 callback(*args, **kwargs)
96
97 - def cursorMoved(self, textview, stepsize, stepcount, eselect):
98 if stepsize == gtk.MOVEMENT_DISPLAY_LINES:
99 mark = self.textbuf.get_insert()
100 iter = self.textbuf.get_iter_at_mark(mark)
101 lineno = iter.get_line()
102 self.setVaFromLine(lineno+stepcount)
103
104
105
106
109
110 @idlethreadsync
112
113
114 tag = self.vwGetTag(typename)
115 if tag == None:
116 tag = vw_views.VTextTag(typename)
117 self.vwInitTag(tag, typename)
118 return tag
119
120 @idlethreadsync
131
132 @idlethreadsync
134 tname = "%.8x" % va
135 tag = self.vwGetTag(tname)
136 if tag == None:
137
138 tag = VaTag(va)
139 self.vwInitTag(tag, "va", self.vaTagEvent)
140
141 return tag
142
143 @idlethread
144 - def addText(self, text, tag=None):
145 if tag == None:
146 tag = self.vwGetTag("default")
147 self.vwInsertText(text, tag=tag, iter=self.iter)
148
149 @idlethread
150 - def addVaText(self, text, va):
151 tag = self.getVaTag(va)
152 self.addText(text, tag=tag)
153
154
155
156 - def appendHistory(self, va, size=None, rend=None):
157
158 if size == None:
159 size = self.lastsize
160
161 if rend == None:
162 rend = self.currend
163
164 if self.histindex == None:
165 self.histindex = -1
166 self.histindex += 1
167 self.valist = self.valist[:self.histindex]
168 self.valist.append((va,size,rend))
169
171
172
173
174 if rend == None:
175 rend = self.currend
176
177 if size == None:
178 size = self.lastsize
179
180 if ( va < self.beginva or
181 va >= self.endva or
182 rend != self.currend ):
183
184
185 self.renderMemory(va, size, rend=rend)
186
187 - def goto(self, va, size=None, rend=None):
188 if size == None:
189 size = self.lastsize
190 self.appendHistory(va, size=size, rend=rend)
191 self.checkRender(va, size, rend=rend)
192 self.__goto(va)
193
195 if self.histindex == None:
196 return
197
198 newindex = self.histindex + 1
199 if newindex < len(self.valist):
200 self.histindex = newindex
201 va,size,rend = self.valist[self.histindex]
202 self.checkRender(va,size,rend)
203 self.__goto(va)
204
206 if self.histindex == None:
207 return
208 if self.histindex > 0:
209 self.histindex -= 1
210 va,size,rend = self.valist[self.histindex]
211 self.checkRender(va,size,rend)
212 self.__goto(va)
213
215 va,size,rend = self.valist[self.histindex]
216 va = self.endva
217 self.checkRender(va, size, rend)
218 self.__goto(va)
219
221 va,size,rend = self.valist[self.histindex]
222 va = self.beginva - size
223 self.checkRender(va, size, rend)
224 self.__goto(va)
225
227
228 mark = self.markmap.get(va)
229 while mark == None:
230 va -= 1
231 mark = self.markmap.get(va)
232 self.textview.scroll_to_mark(mark, 0, True, 0, 0.3)
233
234
235 vatag = self.getVaTag(va)
236 self.vaTagSelector(vatag)
237
238 if self.memwin:
239 self.memwin.updateHistoryButtons()
240
241
242 @idlethreadsync
251
252 @idlethreadsync
254
255
256
257
258 if rend == None:
259 rend = self.currend
260
261 self.lastsize = size
262 self.currend = rend
263
264 try:
265 endva = va + size
266 while va < endva:
267 mark = self.textbuf.create_mark(None, self.iter, left_gravity=True)
268 self.markmap[va] = mark
269 va += rend.render(self, va)
270 except Exception, e:
271 self.addText("\nException At %s: %s\n" % (hex(va),e))
272
274 if va < self.beginva or va >= self.endva:
275 return
276
277 endva = va+size
278
279
280 mark = self.markmap.get(va)
281 if mark == None:
282 print "WARNING: va 0x%.8x has no mark for refresh!" % va
283 return
284
285
286 startiter = self.textbuf.get_iter_at_mark(mark)
287 startline = startiter.get_line()
288
289
290 endmark = None
291 endsearch = endva
292 enditer = None
293 while endsearch < self.endva:
294 endmark = self.markmap.get(endsearch, None)
295 if endmark != None:
296 enditer = self.textbuf.get_iter_at_mark(endmark)
297 break
298 endsearch += 1
299
300 if enditer == None:
301 enditer = self.textbuf.get_end_iter()
302
303
304 self.textbuf.delete(startiter, enditer)
305
306 for delva in range(va, endsearch):
307 mark = self.markmap.pop(delva, None)
308 if mark != None:
309
310 self.textbuf.delete_mark(mark)
311
312
313 self.iter = self.textbuf.get_iter_at_line(startline)
314
315 self.render_noclear(va, size)
316
317
318 if endmark != None:
319 self.textbuf.move_mark(endmark, self.iter)
320
321 return
322
323 - def vwClearText(self):
324 vw_views.VTextView.vwClearText(self)
325
326 self.markmap = {}
327
336
340
341 - def vwTagEvent(self, tag, textview, event, iter):
342
343
344 if event.type == gdk.BUTTON_PRESS:
345 self.setVaFromIter(iter)
346
347
348 - def vaTagEvent(self, tag, textview, event, iter):
349
350 if event.type == gdk._2BUTTON_PRESS:
351 self.goto(tag.va)
352
353 elif event.type == gdk.BUTTON_PRESS:
354 self.selectva = tag.va
355 self.vaTagSelector(tag)
356
360
362 lineiter = self.textbuf.get_iter_at_line(lineno)
363 linetags = lineiter.get_tags()
364 if len(linetags):
365 vatag = linetags[0]
366 va = getattr(vatag, "va", None)
367 if va != None:
368 self.selectva = va
369 self.vaTagSelector(vatag)
370
396
397 import vwidget.layout as vw_layout
401 self.canvas = canvas
402 vw_layout.LayoutWindow.__init__(self)
403 self.vbox = gtk.VBox()
404 elabel = gtk.Label(" Memory Expression ")
405 slabel = gtk.Label(" Memory Size ")
406
407 self.eentry = gtk.Entry()
408 self.sentry = gtk.Entry()
409 self.sentry.set_text("256")
410
411 self.nextbutton = gtk.Button()
412 i = gtk.image_new_from_stock(gtk.STOCK_GO_FORWARD, gtk.ICON_SIZE_BUTTON)
413 self.nextbutton.set_image(i)
414 self.nextbutton.connect("clicked", self.goforward)
415
416 self.backbutton = gtk.Button()
417 i = gtk.image_new_from_stock(gtk.STOCK_GO_BACK, gtk.ICON_SIZE_BUTTON)
418 self.backbutton.set_image(i)
419 self.backbutton.connect("clicked", self.goback)
420
421 self.downbutton = gtk.Button()
422 i = gtk.image_new_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_BUTTON)
423 self.downbutton.set_image(i)
424 self.downbutton.connect("clicked", self.godown)
425
426 self.upbutton = gtk.Button()
427 i = gtk.image_new_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_BUTTON)
428 self.upbutton.set_image(i)
429 self.upbutton.connect("clicked", self.goup)
430
431 hbox = gtk.HBox()
432
433 hbox.pack_start(self.backbutton, expand=False)
434 hbox.pack_start(self.nextbutton, expand=False)
435 hbox.pack_start(self.upbutton, expand=False)
436 hbox.pack_start(self.downbutton, expand=False)
437 hbox.pack_start(elabel, expand=False)
438 hbox.pack_start(self.eentry, expand=True)
439 hbox.pack_start(slabel, expand=False)
440 hbox.pack_start(self.sentry, expand=True)
441
442 self.cbox = gtk.combo_box_new_text()
443 for name in self.canvas.getRendererNames():
444 self.canvas.addRenderer(name, self.canvas.getRenderer(name))
445 self.cbox.append_text(name)
446 self.cbox.set_active(0)
447 hbox.pack_start(self.cbox, expand=False)
448
449 self.vbox.pack_start(hbox, expand=False)
450 self.vbox.pack_start(self.canvas, expand=True)
451 self.add(self.vbox)
452
453 self.eentry.connect("activate", self.entryActivated)
454 self.sentry.connect("activate", self.entryActivated)
455 self.cbox.connect("changed", self.updateMemoryView)
456
457 self.canvas.memwin = self
458 self.updateHistoryButtons()
459
461 hi = self.canvas.histindex
462 vl = self.canvas.valist
463 self.nextbutton.set_sensitive(False)
464 self.backbutton.set_sensitive(False)
465 if hi == None:
466 return
467 if hi > 0:
468 self.backbutton.set_sensitive(True)
469 if hi < (len(vl)-1):
470 self.nextbutton.set_sensitive(True)
471
472 - def goto(self, va, size=None, rend=None):
475
479
480 - def goup(self, *args):
483
487
491
493 self.eentry.set_text(expr)
494 self.sentry.set_text(size)
495 self.updateMemoryView()
496
497 - def entryActivated(self, *args):
498 self.updateMemoryView()
499 self.set_title("Memory: %s" % self.eentry.get_text())
500
502
503 expr, sizestr, rendname = self.getWindowState()
504
505
506 if not expr or not sizestr:
507 return
508
509 try:
510
511 va = self.canvas.mem.parseExpression(expr)
512 except Exception, e:
513 self.canvas.addText("Invalid Expression: %s (%s)" % (expr,str(e)))
514 return
515
516 try:
517 size = self.canvas.mem.parseExpression(sizestr)
518 except Exception, e:
519 self.canvas.addText("Invalid Expression: %s (%s)" % (expr,str(e)))
520 return
521
522 rend = self.canvas.getRenderer(rendname)
523 self.goto(va, size=size, rend=rend)
524
526 e,s,r = state
527 self.eentry.set_text(e)
528 self.sentry.set_text(s)
529 try:
530 ridx = self.canvas.getRendererNames().index(r)
531 self.cbox.set_active(ridx)
532 except ValueError, e:
533 pass
534 self.entryActivated()
535
537 e = self.eentry.get_text()
538 s = self.sentry.get_text()
539 renditer = self.cbox.get_active_iter()
540 r = self.cbox.get_model().get_value(renditer, 0)
541 return (e,s,r)
542