import os
import sys
import time
import struct
import jarray
import java.lang.String
import java.lang.System as System
import com.microchip.mplab.util.observers
import com.microchip.mplab.mdbcore.debugger.Debugger
from com.microchip.mplab.comm import MPLABCommProvider
from com.microchip.mplab.mdbcore.assemblies.assemblyfactory import MCAssemblyFactory
from com.microchip.mplab.mdbcore.debugger import Debugger
from com.microchip.mplab.mdbcore.debugger import DebugException
from com.microchip.mplab.mdbcore.debugger import ToolEvent
from com.microchip.mplab.mdbcore.loader import Loader
from com.microchip.mplab.mdbcore.loader import LoadException
from com.microchip.mplab.mdbcore.translator.interfaces import ITranslator
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.objectfileparsing import Dwarf
from com.microchip.mplab.mdbcore.objectfileparsing import MDBFileMagic
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 = []
self.isHalted = True
def Update(self, obj):
if obj.GetEvent() == ToolEvent.EVENTS.HALT:
self.isHalted = True
elif obj.GetEvent() == ToolEvent.EVENTS.RUN:
self.isHalted = False
def waitForHalt(self):
while not self.isHalted:
pass
def getPC(self):
return self.mdb.GetPC()
def selectDevice(self, devstr):
self.factory = MCAssemblyFactory()
self.assembly = self.factory.Create(devstr)
self.provider = MPLABCommProvider()
def enumerateDevices(self):
try:
self.devices = self.provider.GetCurrentToolList(None, "USB","04D8", None)
if not self.devices:
print "No USB debugger found."
except DebugException:
print "Failed to enumerate USB devices."
return False
return True
def run(self):
self.mdb.Run()
def setBreakpoint(self, addr):
self.cpm = self.assembly.getLookup().lookup(ControlPointMediator)
wcps = self.cpm.getWritableControlPointStore()
if wcps.getNumberAvailableProgramControlPoints() > 0:
bp = wcps.getNewControlPoint()
bp.setBreakType(BreakType.PROGRAM)
bp.setBreakAddress(addr)
bp.setEnabled(True)
(file,line) = self.addressToSourceLine(addr)
bp.setFileNameAndLine(file, line)
self._breakpoints.append(bp)
self.cpm.commitAndReleaseWritableControlPointStore(wcps)
return True
return False
def breakpointIndexForAddress(self, addr):
result = -1
for i,bp in enumerate(self._breakpoints):
if bp.getBreakAddress() == addr:
result = i
break
return result
def allBreakpoints(self):
return [(i,bp.getBreakAddress(),bp.getFileName(),
bp.getFileLine(), bp.getEnabled())
for (i,bp) in enumerate(self._breakpoints)]
def selectDebugger(self):
alltools = PlatformToolMetaManager.getAllTools()
devname = self.devices[0].split(":=")[6] if devname.find("PICkit") == 0:
devname = devname.replace(" ", "") elif devname.lower().find("real ice") >= 0:
devname = "Real ICE"
tool = [x for x in alltools if x.getName() == devname][0]
self.factory.ChangeTool(self.assembly,
tool.getConfigurationObjectID(),
tool.getClassName(),
tool.getFlavor(),
self.devices[0])
self.factory.SetToolProperties(self.assembly,None)
def connect(self):
self.assembly.SetHeader("");
self.mdb = self.assembly.getLookup().lookup(Debugger)
print "Connecting to debugger..."
try:
self.mdb.Attach(self, None)
self.mdb.Connect(Debugger.CONNECTION_TYPE.DEBUGGER)
except DebugException:
print "Failed to connect to debugger."
return False
return True
def load(self, file):
self.loader = self.assembly.getLookup().lookup(Loader)
try:
self.loader.Load(file)
self.mdb.Program(Debugger.PROGRAM_OPERATION.AUTO_SELECT)
self.translator = self.assembly.getLookup().lookup(ITranslator)
self.disassembler = self.assembly.getLookup().lookup(DisAsm)
self.mem = self.assembly.getLookup().lookup(ProgramMemory).GetVirtualMemory()
self.file_magic = MDBFileMagic(file)
self.dwarf = Dwarf(self.file_magic)
self.comp_units = self.dwarf.getCompilationUnits()
self.filenames = [x.getSourceFileAbsolutePath() for x in self.comp_units]
except DebugException:
print "Failed to load ELF onto target."
return False
except LoadException:
print "File not found."
return False
return True
def findFile(self, filename):
abspaths = [x for x in self.filenames if x.rfind(filename) >= 0]
for path in abspaths:
if os.path.exists(path):
return path
return None
def findBreakableAddressInFile(self, filename, line):
fullpath = self.findFile(filename)
if fullpath is None:
print "File not found."
return None
addr = None
for i in range(20):
try:
info = self.translator.sourceLineToAddress(fullpath, line+i)
if info:
break
except TranslatorException:
continue
addr = info.lStartAddr
return addr
def testSourceLookup(self):
sourcefile = "/path/to/MainDemo.c"
line = 248
info = self.translator.sourceLineToAddress(sourcefile, line)
print "%s:%d ==> 0x%X" % (sourcefile.split("/")[-1], line, info.lStartAddr)
def reset(self):
self.mdb.Reset(True)
def disconnect(self):
if self.mdb:
self.mdb.Disconnect()
def getDeviceFamily(self):
bits = assembly.GetDevice().getFamilyCode()
return assembly.GetDevice().getSubFamily()
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 getFunctionAddress(self, funcname):
sv = self.assembly.getLookup().lookup(SymbolViewProvider)
info = sv.getRawSymbol(funcname)
if not info or info.Type() != 64: return None
return info.Address()
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
fmtMap = {1: "b", 2: "h", 4: "i", 8: "q"}
signMap = {VarType.ST_ULONG.value(): False,
VarType.ST_LONG.value(): True,
}
if varlength > 8:
print "Symbol type not handled!"
return None
fmt = fmtMap[varlength]
if vartype in signMap:
fmt = fmt.lower() if signMap[vartype] else fmt.upper()
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)
f = info.file
if stripdir:
f = info.file.split("/")[-1]
return (f, info.lLine)
except TranslatorException:
return ("unknown",0)
def step(self, type=StepType.OVER):
try:
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
pc = self.mdb.GetPC()
print "PC: 0x%X" % pc,
try:
info = self.translator.addressToSourceLine(pc)
print " (%s:%d)" % (info.file.split("/")[-1], info.lLine),
lines = self.translator.sourceLinesFromAddress(pc, True)
for sl in lines.result:
ins = self.disassembler.Disassemble(
self.mem.ReadWord(sl.Address()),
self.mem.ReadWord(sl.Address() + sl.AddressIncrement()),
sl.Address() | (1 if sl.AddressIncrement() == 2 else 0),
DisAsm.OPTIONS.FULL_SYMBOLS,
None)
print " (%s)" % ins.instruction,
except TranslatorException:
print " Unknown line.",
print