import sys
import time
+import struct
+import jarray
import java.lang.String
import java.lang.System as System
import com.microchip.mplab.util.observers
from com.microchip.mplab.mdbcore.translator.exceptions import TranslatorException
from com.microchip.mplab.mdbcore.disasm import DisAsm
from com.microchip.mplab.mdbcore.memory.memorytypes import ProgramMemory
+from com.microchip.mplab.mdbcore.memory.memorytypes import FileRegisters
from com.microchip.mplab.mdbcore.objectfileparsing.exception import ProgramFileParsingException
from com.microchip.mplab.mdbcore.platformtool import PlatformToolMetaManager
+from com.microchip.mplab.mdbcore.symbolview.interfaces import SymbolViewProvider
+from com.microchip.mplab.mdbcore.common.debug.SymbolType import eFundamentalType as VarType
from com.microchip.mplab.mdbcore.ControlPointMediator.ControlPoint import BreakType
from com.microchip.mplab.mdbcore.ControlPointMediator import ControlPointMediator
System.setProperty("crownking.stream.verbosity", "quiet")
class picdebugger(com.microchip.mplab.util.observers.Observer):
+ class StepType:
+ IN = 0
+ OVER = 1
+ INSTR = 2
+
def __init__(self):
self.mdb = None
self._breakpoints = []
bits = assembly.GetDevice().getFamilyCode()
return assembly.GetDevice().getSubFamily()
- def addressToSourceLine(self, addr):
+ def getMemoryContents(self, addr, length, virtual=False):
+ fr = self.assembly.getLookup().lookup(FileRegisters)
+ data = jarray.zeros(length, "b")
+ if virtual:
+ mem = fr.GetVirtualMemory()
+ else:
+ mem = fr.GetPhysicalMemory()
+ mem.RefreshFromTarget(addr, length)
+ if mem.Read(addr, length, data) == length:
+ return data
+ return None
+
+ def getSymbolValue(self, symbol):
+ sv = self.assembly.getLookup().lookup(SymbolViewProvider)
+ info = sv.getRawSymbol(symbol)
+ if not info:
+ return None
+ vartype = info.Type()
+ varlength = info.ByteLength()
+ data = self.getMemoryContents(info.Address(), varlength, virtual=True)
+ if not data:
+ return None
+
+ # Unpack array into variable based on type
+ fmtMap = {1: "b", 2: "h", 4: "i", 8: "q"}
+ # TODO: fill out map of types and their signedness
+ signMap = {VarType.ST_ULONG.value(): False,
+ VarType.ST_LONG.value(): True,
+ }
+ if varlength > 8:
+ # TODO: Handle complex symbols. Struct or string or something.
+ print "Symbol type not handled!"
+ return None
+ fmt = fmtMap[varlength]
+ if vartype in signMap:
+ fmt = fmt.lower() if signMap[vartype] else fmt.upper()
+ # Special cases:
+ if vartype == VarType.ST_FLOAT:
+ fmt = "f"
+ elif vartype == VarType.ST_DOUBLE:
+ fmt = "d"
+ return struct.unpack(fmt, data.tostring())[0]
+
+
+
+ def addressToSourceLine(self, addr, stripdir=True):
try:
info = self.translator.addressToSourceLine(addr)
- return (info.file.split("/")[-1], info.lLine)
+ f = info.file
+ if stripdir:
+ f = info.file.split("/")[-1]
+ return (f, info.lLine)
except TranslatorException:
return ("unknown",0)
- def step(self):
+ def step(self, type=StepType.OVER):
try:
- self.mdb.StepOver()
+ if type == self.StepType.OVER:
+ self.mdb.StepOver()
+ elif type == self.StepType.IN:
+ self.mdb.StepIn()
+ else:
+ self.mdb.StepInstr()
except DebugException:
print "Lost communication with debugger or target!"
return
self._commandMap = {
"connect": {'fn': self.cmdConnect, 'help': "Conects to a PIC target."},
"load": {'fn': self.cmdLoad, 'help': "Load ELF file onto target."},
- "step": {'fn': self.cmdStep, 'help': "Step over next source line."},
+ "step": {'fn': self.cmdStep, 'help': "Step to next source line."},
+ "stepi": {'fn': self.cmdStepi, 'help': "Step to next assembly instruction."},
+ "next": {'fn': self.cmdNext, 'help': "Step to next source line, over functions."},
"quit": {'fn': self.cmdQuit, 'help': "Quits this program."},
"help": {'fn': self.cmdHelp, 'help': "Displays this help."},
"debug": {'fn': self.cmdDebug, 'help': "Drop to Python console."},
"break": {'fn': self.cmdBreak, 'help': "Set breakpoint."},
"continue": {'fn': self.cmdContinue, 'help': "Continue running target."},
- "print": {'fn': self.cmdPrint, 'help': "Print variable."},
+ "print": {'fn': self.cmdPrint, 'help': "Display variable."},
"breakpoints": {'fn': self.cmdBreakpoints, 'help': "List breakpoints."},
+ "list": {'fn': self.cmdList, 'help': "Display source code listing."},
}
-
+
def cmdConnect(self, args):
'''
Connects to a PIC target.
Supported registers:
* $pc
'''
+ if args[0] != "$":
+ data = self.dbg.getSymbolValue(args)
+ if data is not None:
+ print data
+ else:
+ print "Symbol not found."
if args.lower() == "$pc":
print "PC: 0x%X" % self.dbg.getPC()
print "%sStopped at 0x%X (%s:%d)" % ("" if bp < 0 else "Breakpoint %d: " % bp,
pc,file,line)
+ def cmdList(self, args):
+ pc = self.dbg.getPC()
+ fname,line = self.dbg.addressToSourceLine(pc, stripdir=False)
+ print "Listing from: %s" % fname
+ f = open(fname, "r")
+ for _ in range(line-1):
+ f.readline()
+ for i in range(10):
+ print "%.3d: %s" % (line+i, f.readline())
+
+
def cmdStep(self, args):
'''
-Step target over one line of source.
+Step target over one line of source. Descends into functions.
Usage: step
'''
- self.dbg.step()
-
+ self.dbg.step(self.dbg.StepType.IN)
+
+
+ def cmdStepi(self, args):
+ '''
+Step target over one single instruction.
+Usage: stepi
+'''
+ self.dbg.step(self.dbg.StepType.INSTR)
+
+
+ def cmdNext(self, args):
+ '''
+Step target over one line of source. If line is a function call, does not
+descend into it.
+Usage: step
+'''
+ self.dbg.step(self.dbg.StepType.OVER)
+
+
def cmdQuit(self, args):
'''
Quit debugger.