Source code for envi.memcanvas

'''
The envi.memcanvas module is the home of the base MemoryRenderer object and
MemoryCanvas objects.
'''

import sys
import traceback

import envi
import envi.memory as e_mem
import envi.resolver as e_resolv

[docs]class MemoryRenderer: """ A top level object for all memory renderers """
[docs] def rendSymbol(self, mcanv, va): """ If there is a symbolic name for the current va, print it... """ sym = mcanv.syms.getSymByAddr(va) if sym != None: mcanv.addVaText("%s:\n" % repr(sym), va)
[docs] def rendVa(self, mcanv, va): tag = mcanv.getVaTag(va) mcanv.addText("%.8x:" % va, tag=tag)
[docs] def rendChars(self, mcanv, bytes): for b in bytes: val = ord(b) bstr = "%.2x" % val if val < 0x20 or val > 0x7e: b = "." mcanv.addNameText(b, bstr)
[docs] def render(self, mcanv, va): """ Render one "unit" and return the size you ate. mcanv will be a MemoryCanvas extender and va is the virtual address you are expected to render. """ raise Exception("Implement render!")
[docs]class MemoryCanvas: """ A memory canvas is a place where the textual representation of memory will be displayed. The methods implemented here show how a memory canvas which simply prints would be implemented. """ def __init__(self, mem, syms=None): if syms == None: syms = e_resolv.SymbolResolver() self.mem = mem self.syms = syms self.currend = None self.renderers = {} self._canv_scrolled = False self._canv_navcallback = None # A few things for tracking renders. self._canv_beginva = None self._canv_endva = None self._canv_rendvas = []
[docs] def setScrolledCanvas(self, scroll): self._canv_scrolled = scroll
[docs] def write(self, msg): # So a canvas can act like simple standard out self.addText(msg)
[docs] def setNavCallback(self, callback): ''' Set a navigation "callback" that will be called with a memory expression as it's first argument anytime the canvas recieves user input which desires nav... ''' self._canv_navcallback = callback
[docs] def addRenderer(self, name, rend): self.renderers[name] = rend self.currend = rend
[docs] def getRenderer(self, name): return self.renderers.get(name)
[docs] def getRendererNames(self): ret = self.renderers.keys() ret.sort() return ret
[docs] def setRenderer(self, name): rend = self.renderers.get(name) if rend == None: raise Exception("Unknown renderer: %s" % name) self.currend = rend
[docs] def getTag(self, typename): """ Retrieve a non-named tag (doesn't highlight or do anything particularly special, but allows color by typename). """ return None
[docs] def getNameTag(self, name, typename=None): """ Retrieve a "tag" object for a name. "Name" tags will (if possible) be highlighted in the rendered interface """ return None # No highlighting in plain text
[docs] def getVaTag(self, va): """ Retrieve a tag object suitable for showing that the text added with this tag should link through to the specified virtual address in the memory canvas. """ return None # No linking in plain text
[docs] def addText(self, text, tag=None): """ Add text to the canvas with a specified tag. NOTE: Implementors should probably check _canv_scrolled to decide if they should scroll to the end of the view... """ sys.stdout.write(text.encode(sys.stdout.encoding,'replace'))
[docs] def addNameText(self, text, name=None, typename=None): if name == None: name = text tag = self.getNameTag(name, typename=typename) self.addText(text, tag=tag)
[docs] def addVaText(self, text, va): tag = self.getVaTag(va) self.addText(text, tag=tag)
[docs] def render(self, va, size, rend=None): raise Exception('Depricated! use renderMemory!')
[docs] def clearCanvas(self): pass
def _beginRenderMemory(self, va, size, rend): pass def _endRenderMemory(self, va, size, rend): pass def _beginRenderVa(self, va): pass def _endRenderVa(self, va): pass def _beginUpdateVas(self, valist): raise Exception('Default canvas cant update!') def _endUpdateVas(self): pass def _beginRenderAppend(self): raise Exception('Default canvas cant append!') def _endRenderAppend(self): pass def _beginRenderPrepend(self): raise Exception('Default canvas cant prepend!') def _endRenderPrepend(self): pass def _isRendered(self, va, maxva): ''' Returns true if any part of the current render overlaps with the specified region. ''' if self._canv_beginva == None: return False if self._canv_endva == None: return False if va > self._canv_endva: return False if maxva < self._canv_beginva: return False return True
[docs] def renderMemoryUpdate(self, va, size): maxva = va + size if not self._isRendered(va, maxva): return # Find the index of the first and last change iend = None ibegin = None for i,(rendva,rendsize) in enumerate(self._canv_rendvas): if ibegin == None and va <= rendva: ibegin = i if iend == None and maxva <= rendva: iend = i if ibegin != None and iend != None: break saved_last = self._canv_rendvas[iend:] saved_first = self._canv_rendvas[:ibegin] updatedvas = self._canv_rendvas[ibegin:iend] #print 'IBEGIN',hex(ibegin) #print 'IEND',hex(iend) #print 'FIRST',repr([hex(va) for va in saved_first]) #print 'UPDATED',repr([hex(va) for va in updatedvas]) #print 'LAST',repr([hex(va) for va in saved_last]) # We must actually start rendering from the beginning # of the first updated VA index startva = updatedvas[0][0] endva = self._canv_endva if saved_last: endva = saved_last[0][0] newrendvas = [] self._beginUpdateVas(updatedvas) try: while startva < endva: self._beginRenderVa(startva) rsize = self.currend.render(self, startva) newrendvas.append((startva,rsize)) self._endRenderVa(startva) startva += rsize except Exception, e: s = traceback.format_exc() self.addText("\nException At %s: %s\n" % (hex(va),s)) self._canv_rendvas = saved_first + newrendvas + saved_last self._endUpdateVas()
[docs] def renderMemoryPrepend(self, size): firstva, firstsize = self._canv_rendvas[0] va = firstva - size self._beginRenderPrepend() savedrendvas = self._canv_rendvas self._canv_rendvas = [] self._canv_beginva = va rend = self.currend try: while va < firstva: self._beginRenderVa(va) rsize = rend.render(self, va) self._canv_rendvas.append((va,rsize)) self._endRenderVa(va) va += rsize self._canv_rendvas.extend(savedrendvas) except Exception, e: s = traceback.format_exc() self.addText("\nException At %s: %s\n" % (hex(va),s)) self._endRenderPrepend()
[docs] def renderMemoryAppend(self, size): lastva, lastsize = self._canv_rendvas[-1] va = lastva + lastsize self._beginRenderAppend() rend = self.currend try: maxva = va + size while va < maxva: self._beginRenderVa(va) rsize = rend.render(self, va) self._canv_rendvas.append((va,rsize)) self._endRenderVa(va) va += rsize self._canv_endva = maxva except Exception, e: s = traceback.format_exc() self.addText("\nException At %s: %s\n" % (hex(va),s)) self._endRenderAppend()
[docs] def renderMemory(self, va, size, rend=None): # if this is not a "scrolled" canvas, clear it. if not self._canv_scrolled: self.clearCanvas() if rend == None: rend = self.currend self.currend = rend # Set our canvas render tracking variables. self._canv_beginva = va self._canv_endva = va + size self._canv_rendvas = [] # A callback for "bulk" rendering (let the canvas cache...) self._beginRenderMemory(va, size, rend) try: maxva = va + size while va < maxva: self._beginRenderVa(va) rsize = rend.render(self, va) self._canv_rendvas.append((va,rsize)) self._endRenderVa(va) va += rsize except Exception, e: s = traceback.format_exc() self.addText("\nException At %s: %s\n" % (hex(va),s)) # Canvas callback for render completion (or error...) self._endRenderMemory(va, size, rend)
[docs]class StringMemoryCanvas(MemoryCanvas): def __init__(self, mem, syms=None): MemoryCanvas.__init__(self, mem, syms=None) self.strval = ""
[docs] def addText(self, text, tag=None): self.strval += text
def __str__(self): return self.strval