188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# 388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# This file defines the layer that talks to lldb 488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# 588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaimport os, re, sys 788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaimport lldb 888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaimport vim 988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleafrom vim_ui import UI 1088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 1188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# ================================================= 1288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# Convert some enum value to its string counterpart 1388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# ================================================= 1488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 1588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea# Shamelessly copy/pasted from lldbutil.py in the test suite 1688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleadef state_type_to_str(enum): 1788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """Returns the stateType string given an enum.""" 1888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if enum == lldb.eStateInvalid: 1988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "invalid" 2088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateUnloaded: 2188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "unloaded" 2288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateConnected: 2388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "connected" 2488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateAttaching: 2588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "attaching" 2688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateLaunching: 2788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "launching" 2888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateStopped: 2988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "stopped" 3088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateRunning: 3188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "running" 3288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateStepping: 3388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "stepping" 3488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateCrashed: 3588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "crashed" 3688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateDetached: 3788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "detached" 3888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateExited: 3988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "exited" 4088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif enum == lldb.eStateSuspended: 4188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return "suspended" 4288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 4388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea raise Exception("Unknown StateType enum") 4488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 4588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaclass StepType: 4688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea INSTRUCTION = 1 4788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea INSTRUCTION_OVER = 2 4888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea INTO = 3 4988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea OVER = 4 5088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea OUT = 5 5188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 5288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaclass LLDBController(object): 5388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Handles Vim and LLDB events such as commands and lldb events. """ 5488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 5588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # Timeouts (sec) for waiting on new events. Because vim is not multi-threaded, we are restricted to 5688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # servicing LLDB events from the main UI thread. Usually, we only process events that are already 5788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # sitting on the queue. But in some situations (when we are expecting an event as a result of some 5888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # user interaction) we want to wait for it. The constants below set these wait period in which the 5988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # Vim UI is "blocked". Lower numbers will make Vim more responsive, but LLDB will be delayed and higher 6088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # numbers will mean that LLDB events are processed faster, but the Vim UI may appear less responsive at 6188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # times. 6288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea eventDelayStep = 2 6388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea eventDelayLaunch = 1 6488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea eventDelayContinue = 1 6588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 6688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def __init__(self): 6788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Creates the LLDB SBDebugger object and initializes the UI class. """ 6888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.target = None 6988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.process = None 7088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.load_dependent_modules = True 7188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 7288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.dbg = lldb.SBDebugger.Create() 7388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.commandInterpreter = self.dbg.GetCommandInterpreter() 7488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 7588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui = UI() 7688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 7788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def completeCommand(self, a, l, p): 7888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Returns a list of viable completions for command a with length l and cursor at p """ 7988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 8088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea assert l[0] == 'L' 8188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # Remove first 'L' character that all commands start with 8288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea l = l[1:] 8388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 8488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # Adjust length as string has 1 less character 8588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea p = int(p) - 1 8688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 8788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea result = lldb.SBStringList() 8888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea num = self.commandInterpreter.HandleCompletion(l, p, 1, -1, result) 8988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 9088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if num == -1: 9188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # FIXME: insert completion character... what's a completion character? 9288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea pass 9388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif num == -2: 9488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # FIXME: replace line with result.GetStringAtIndex(0) 9588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea pass 9688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 9788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if result.GetSize() > 0: 9888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea results = filter(None, [result.GetStringAtIndex(x) for x in range(result.GetSize())]) 9988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return results 10088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 10188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return [] 10288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 10388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doStep(self, stepType): 10488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Perform a step command and block the UI for eventDelayStep seconds in order to process 10588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea events on lldb's event queue. 10688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea FIXME: if the step does not complete in eventDelayStep seconds, we relinquish control to 10788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea the main thread to avoid the appearance of a "hang". If this happens, the UI will 10888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea update whenever; usually when the user moves the cursor. This is somewhat annoying. 10988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 11088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if not self.process: 11188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea sys.stderr.write("No process to step") 11288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return 11388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 11488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea t = self.process.GetSelectedThread() 11588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if stepType == StepType.INSTRUCTION: 11688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea t.StepInstruction(False) 11788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if stepType == StepType.INSTRUCTION_OVER: 11888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea t.StepInstruction(True) 11988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif stepType == StepType.INTO: 12088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea t.StepInto() 12188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif stepType == StepType.OVER: 12288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea t.StepOver() 12388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif stepType == StepType.OUT: 12488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea t.StepOut() 12588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 12688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.processPendingEvents(self.eventDelayStep, True) 12788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 12888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doSelect(self, command, args): 12988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Like doCommand, but suppress output when "select" is the first argument.""" 13088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea a = args.split(' ') 13188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return self.doCommand(command, args, "select" != a[0], True) 13288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 13388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doProcess(self, args): 13488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Handle 'process' command. If 'launch' is requested, use doLaunch() instead 13588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea of the command interpreter to start the inferior process. 13688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 13788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea a = args.split(' ') 13888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if len(args) == 0 or (len(a) > 0 and a[0] != 'launch'): 13988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.doCommand("process", args) 14088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea #self.ui.update(self.target, "", self) 14188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 14288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.doLaunch('-s' not in args, "") 14388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 1443451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea def doAttach(self, process_name): 1453451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea """ Handle process attach. """ 1463451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea error = lldb.SBError() 1473451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea 1483451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.processListener = lldb.SBListener("process_event_listener") 1493451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.target = self.dbg.CreateTarget('') 1503451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.process = self.target.AttachToProcessWithName(self.processListener, process_name, False, error) 1513451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea if not error.Success(): 1523451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea sys.stderr.write("Error during attach: " + str(error)) 1533451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea return 1543451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea 1553451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.ui.activate() 1563451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.pid = self.process.GetProcessID() 1573451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea 1583451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea print "Attached to %s (pid=%d)" % (process_name, self.pid) 1593451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea 1603451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea def doDetach(self): 1613451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea if self.process is not None and self.process.IsValid(): 1623451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea pid = self.process.GetProcessID() 1633451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea state = state_type_to_str(self.process.GetState()) 1643451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.process.Detach() 1653451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea self.processPendingEvents(self.eventDelayLaunch) 1663451b9eed7e9d5bcca72220f4dcdc4c011ef930cDaniel Malea 16788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doLaunch(self, stop_at_entry, args): 16888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Handle process launch. """ 16988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea error = lldb.SBError() 17088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 17188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea fs = self.target.GetExecutable() 17288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea exe = os.path.join(fs.GetDirectory(), fs.GetFilename()) 17388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if self.process is not None and self.process.IsValid(): 17488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea pid = self.process.GetProcessID() 17588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea state = state_type_to_str(self.process.GetState()) 17688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.process.Destroy() 17788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 17888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea launchInfo = lldb.SBLaunchInfo(args.split(' ')) 17988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.process = self.target.Launch(launchInfo, error) 18088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if not error.Success(): 18188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea sys.stderr.write("Error during launch: " + str(error)) 18288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return 18388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 18488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # launch succeeded, store pid and add some event listeners 18588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.pid = self.process.GetProcessID() 18688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.processListener = lldb.SBListener("process_event_listener") 18788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.process.GetBroadcaster().AddListener(self.processListener, lldb.SBProcess.eBroadcastBitStateChanged) 18888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 18988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea print "Launched %s %s (pid=%d)" % (exe, args, self.pid) 19088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 19188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if not stop_at_entry: 19288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.doContinue() 19388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 19488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.processPendingEvents(self.eventDelayLaunch) 19588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 19688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doTarget(self, args): 19788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Pass target command to interpreter, except if argument is not one of the valid options, or 19888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea is create, in which case try to create a target with the argument as the executable. For example: 19988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea target list ==> handled by interpreter 20088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea target create blah ==> custom creation of target 'blah' 20188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea target blah ==> also creates target blah 20288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 20388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea target_args = [#"create", 20488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "delete", 20588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "list", 20688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "modules", 20788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "select", 20888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "stop-hook", 20988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "symbols", 21088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "variable"] 21188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 21288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea a = args.split(' ') 21388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if len(args) == 0 or (len(a) > 0 and a[0] in target_args): 21488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.doCommand("target", args) 21588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return 21688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif len(a) > 1 and a[0] == "create": 21788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea exe = a[1] 21888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea elif len(a) == 1 and a[0] not in target_args: 21988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea exe = a[0] 22088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 22188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea err = lldb.SBError() 22288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.target = self.dbg.CreateTarget(exe, None, None, self.load_dependent_modules, err) 22388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if not self.target: 22488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea sys.stderr.write("Error creating target %s. %s" % (str(exe), str(err))) 22588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return 22688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 22788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.activate() 22888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.update(self.target, "created target %s" % str(exe), self) 22988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 23088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doContinue(self): 23188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Handle 'contiue' command. 23288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea FIXME: switch to doCommand("continue", ...) to handle -i ignore-count param. 23388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 23488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if not self.process or not self.process.IsValid(): 23588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea sys.stderr.write("No process to continue") 23688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return 23788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 23888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.process.Continue() 23988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.processPendingEvents(self.eventDelayContinue) 24088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 24188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doBreakpoint(self, args): 24288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Handle breakpoint command with command interpreter, except if the user calls 24388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea "breakpoint" with no other args, in which case add a breakpoint at the line 24488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea under the cursor. 24588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 24688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea a = args.split(' ') 24788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if len(args) == 0: 24888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea show_output = False 24988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 25088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # User called us with no args, so toggle the bp under cursor 25188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea cw = vim.current.window 25288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea cb = vim.current.buffer 25388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea name = cb.name 25488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea line = cw.cursor[0] 25588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 25688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # Since the UI is responsbile for placing signs at bp locations, we have to 25788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # ask it if there already is one or more breakpoints at (file, line)... 25888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if self.ui.haveBreakpoint(name, line): 25988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea bps = self.ui.getBreakpoints(name, line) 26088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea args = "delete %s" % " ".join([str(b.GetID()) for b in bps]) 26188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.deleteBreakpoints(name, line) 26288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 26388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea args = "set -f %s -l %d" % (name, line) 26488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 26588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea show_output = True 26688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 26788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.doCommand("breakpoint", args, show_output) 26888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return 26988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 27088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doRefresh(self): 27188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ process pending events and update UI on request """ 27288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea status = self.processPendingEvents() 27388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 27488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doShow(self, name): 27588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ handle :Lshow <name> """ 2765d414624837b0fa6d9ec21fdb23326ad5879f1b1Daniel Malea if not name: 2775d414624837b0fa6d9ec21fdb23326ad5879f1b1Daniel Malea self.ui.activate() 2785d414624837b0fa6d9ec21fdb23326ad5879f1b1Daniel Malea return 2795d414624837b0fa6d9ec21fdb23326ad5879f1b1Daniel Malea 28088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if self.ui.showWindow(name): 28188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.update(self.target, "", self) 28288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 28388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doHide(self, name): 28488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ handle :Lhide <name> """ 28588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if self.ui.hideWindow(name): 28688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.update(self.target, "", self) 28788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 28888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doExit(self): 28988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.dbg.Terminate() 29088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.dbg = None 29188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 29288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def getCommandResult(self, command, command_args): 29388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Run cmd in the command interpreter and returns (success, output) """ 29488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea result = lldb.SBCommandReturnObject() 29588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea cmd = "%s %s" % (command, command_args) 29688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 29788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.commandInterpreter.HandleCommand(cmd, result) 29888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return (result.Succeeded(), result.GetOutput() if result.Succeeded() else result.GetError()) 29988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 30088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def doCommand(self, command, command_args, print_on_success = True, goto_file=False): 30188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Run cmd in interpreter and print result (success or failure) on the vim status line. """ 30288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea (success, output) = self.getCommandResult(command, command_args) 30388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if success: 30488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.update(self.target, "", self, goto_file) 30588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if len(output) > 0 and print_on_success: 30688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea print output 30788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 30888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea sys.stderr.write(output) 30988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 31088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def getCommandOutput(self, command, command_args=""): 31188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ runs cmd in the command interpreter andreturns (status, result) """ 31288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea result = lldb.SBCommandReturnObject() 31388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea cmd = "%s %s" % (command, command_args) 31488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.commandInterpreter.HandleCommand(cmd, result) 31588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea return (result.Succeeded(), result.GetOutput() if result.Succeeded() else result.GetError()) 31688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 31788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea def processPendingEvents(self, wait_seconds=0, goto_file=True): 31888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Handle any events that are queued from the inferior. 31988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea Blocks for at most wait_seconds, or if wait_seconds == 0, 32088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea process only events that are already queued. 32188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 32288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 32388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea status = None 32488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea num_events_handled = 0 32588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 32688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if self.process is not None: 32788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea event = lldb.SBEvent() 32888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea old_state = self.process.GetState() 32988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea new_state = None 33088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea done = False 33188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if old_state == lldb.eStateInvalid or old_state == lldb.eStateExited: 33288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # Early-exit if we are in 'boring' states 33388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea pass 33488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 33588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea while not done and self.processListener is not None: 33688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if not self.processListener.PeekAtNextEvent(event): 33788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if wait_seconds > 0: 33888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # No events on the queue, but we are allowed to wait for wait_seconds 33988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # for any events to show up. 34088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.processListener.WaitForEvent(wait_seconds, event) 34188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea new_state = lldb.SBProcess.GetStateFromEvent(event) 34288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 34388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea num_events_handled += 1 34488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 34588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea done = not self.processListener.PeekAtNextEvent(event) 34688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 34788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # An event is on the queue, process it here. 34888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.processListener.GetNextEvent(event) 34988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea new_state = lldb.SBProcess.GetStateFromEvent(event) 35088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 351315f54f3d3fa5a46f02d0553ab2ee385815f8140Daniel Malea # continue if stopped after attaching 352315f54f3d3fa5a46f02d0553ab2ee385815f8140Daniel Malea if old_state == lldb.eStateAttaching and new_state == lldb.eStateStopped: 353315f54f3d3fa5a46f02d0553ab2ee385815f8140Daniel Malea self.process.Continue() 354315f54f3d3fa5a46f02d0553ab2ee385815f8140Daniel Malea 35588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea # If needed, perform any event-specific behaviour here 35688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea num_events_handled += 1 35788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 35888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if num_events_handled == 0: 35988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea pass 36088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea else: 36188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea if old_state == new_state: 36288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea status = "" 36388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea self.ui.update(self.target, status, self, goto_file) 36488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 36588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 36688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleadef returnCompleteCommand(a, l, p): 36788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Returns a "\n"-separated string with possible completion results 36888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea for command a with length l and cursor at p. 36988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 37088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea separator = "\n" 37188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea results = ctrl.completeCommand(a, l, p) 37288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea vim.command('return "%s%s"' % (separator.join(results), separator)) 37388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 37488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleadef returnCompleteWindow(a, l, p): 37588cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ Returns a "\n"-separated string with possible completion results 37688cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea for commands that expect a window name parameter (like hide/show). 37788cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea FIXME: connect to ctrl.ui instead of hardcoding the list here 37888cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea """ 37988cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea separator = "\n" 38088cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea results = ['breakpoints', 'backtrace', 'disassembly', 'locals', 'threads', 'registers'] 38188cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea vim.command('return "%s%s"' % (separator.join(results), separator)) 38288cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Malea 38388cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleaglobal ctrl 38488cd3fd2f91506c5a9efd660fc0fe92f09b08117Daniel Maleactrl = LLDBController() 385