# This script allows to use LLDB in a way similar to GDB's batch mode. That is, given a text file
# containing LLDB commands (one command per line), this script will execute the commands one after
# the other.
# LLDB also has the -s and -S commandline options which also execute a list of commands from a text
# file. However, this command are execute `immediately`: the command of a `run` or `continue`
# command will be executed immediately after the `run` or `continue`, without waiting for the next
# breakpoint to be hit. This a command sequence like the following will not yield reliable results:
#
#   break 11
#   run
#   print x
#
# Most of the time the `print` command will be executed while the program is still running will thus
# fail. Using this Python script, the above will work as expected.

from __future__ import print_function
import lldb
import os
import sys
import threading
import re
import time

try:
    import thread
except ModuleNotFoundError:
    # The `thread` module was renamed to `_thread` in Python 3.
    import _thread as thread

# Set this to True for additional output
DEBUG_OUTPUT = False


def print_debug(s):
    """Print something if DEBUG_OUTPUT is True"""
    global DEBUG_OUTPUT
    if DEBUG_OUTPUT:
        print("DEBUG: " + str(s))


def normalize_whitespace(s):
    """Replace newlines, tabs, multiple spaces, etc with exactly one space"""
    return re.sub("\s+", " ", s)


def breakpoint_callback(frame, bp_loc, dict):
    """This callback is registered with every breakpoint and makes sure that the
    frame containing the breakpoint location is selected """

    # HACK(eddyb) print a newline to avoid continuing an unfinished line.
    print("")
    print("Hit breakpoint " + str(bp_loc))

    # Select the frame and the thread containing it
    frame.thread.process.SetSelectedThread(frame.thread)
    frame.thread.SetSelectedFrame(frame.idx)

    # Returning True means that we actually want to stop at this breakpoint
    return True


# This is a list of breakpoints that are not registered with the breakpoint callback. The list is
# populated by the breakpoint listener and checked/emptied whenever a command has been executed
new_breakpoints = []

# This set contains all breakpoint ids that have already been registered with a callback, and is
# used to avoid hooking callbacks into breakpoints more than once
registered_breakpoints = set()


def execute_command(command_interpreter, command):
    """Executes a single CLI command"""
    global new_breakpoints
    global registered_breakpoints

    res = lldb.SBCommandReturnObject()
    print(command)
    command_interpreter.HandleCommand(command, res)

    if res.Succeeded():
        if res.HasResult():
            print(normalize_whitespace(res.GetOutput() or ''), end='\n')

        # If the command introduced any breakpoints, make sure to register
        # them with the breakpoint
        # callback
        while len(new_breakpoints) > 0:
            res.Clear()
            breakpoint_id = new_breakpoints.pop()

            if breakpoint_id in registered_breakpoints:
                print_debug("breakpoint with id %s is already registered. Ignoring." %
                            str(breakpoint_id))
            else:
                print_debug("registering breakpoint callback, id = " + str(breakpoint_id))
                callback_command = ("breakpoint command add -F breakpoint_callback " +
                                    str(breakpoint_id))
                command_interpreter.HandleCommand(callback_command, res)
                if res.Succeeded():
                    print_debug("successfully registered breakpoint callback, id = " +
                                str(breakpoint_id))
                    registered_breakpoints.add(breakpoint_id)
                else:
                    print("Error while trying to register breakpoint callback, id = " +
                          str(breakpoint_id))
    else:
        print(res.GetError())


def start_breakpoint_listener(target):
    """Listens for breakpoints being added and adds new ones to the callback
    registration list"""
    listener = lldb.SBListener("breakpoint listener")

    def listen():
        event = lldb.SBEvent()
        try:
            while True:
                if listener.WaitForEvent(120, event):
                    if lldb.SBBreakpoint.EventIsBreakpointEvent(event) and \
                            lldb.SBBreakpoint.GetBreakpointEventTypeFromEvent(event) == \
                            lldb.eBreakpointEventTypeAdded:
                        global new_breakpoints
                        breakpoint = lldb.SBBreakpoint.GetBreakpointFromEvent(event)
                        print_debug("breakpoint added, id = " + str(breakpoint.id))
                        new_breakpoints.append(breakpoint.id)
        except:
            print_debug("breakpoint listener shutting down")

    # Start the listener and let it run as a daemon
    listener_thread = threading.Thread(target=listen)
    listener_thread.daemon = True
    listener_thread.start()

    # Register the listener with the target
    target.GetBroadcaster().AddListener(listener, lldb.SBTarget.eBroadcastBitBreakpointChanged)


def start_watchdog():
    """Starts a watchdog thread that will terminate the process after a certain
    period of time"""
    watchdog_start_time = time.clock()
    watchdog_max_time = watchdog_start_time + 30

    def watchdog():
        while time.clock() < watchdog_max_time:
            time.sleep(1)
        print("TIMEOUT: lldb_batchmode.py has been running for too long. Aborting!")
        thread.interrupt_main()

    # Start the listener and let it run as a daemon
    watchdog_thread = threading.Thread(target=watchdog)
    watchdog_thread.daemon = True
    watchdog_thread.start()

####################################################################################################
# ~main
####################################################################################################


if len(sys.argv) != 3:
    print("usage: python lldb_batchmode.py target-path script-path")
    sys.exit(1)

target_path = sys.argv[1]
script_path = sys.argv[2]

print("LLDB batch-mode script")
print("----------------------")
print("Debugger commands script is '%s'." % script_path)
print("Target executable is '%s'." % target_path)
print("Current working directory is '%s'" % os.getcwd())

# Start the timeout watchdog
start_watchdog()

# Create a new debugger instance
debugger = lldb.SBDebugger.Create()

# When we step or continue, don't return from the function until the process
# stops. We do this by setting the async mode to false.
debugger.SetAsync(False)

# Create a target from a file and arch
print("Creating a target for '%s'" % target_path)
target_error = lldb.SBError()
target = debugger.CreateTarget(target_path, None, None, True, target_error)

if not target:
    print("Could not create debugging target '" + target_path + "': " +
          str(target_error) + ". Aborting.", file=sys.stderr)
    sys.exit(1)


# Register the breakpoint callback for every breakpoint
start_breakpoint_listener(target)

command_interpreter = debugger.GetCommandInterpreter()

try:
    script_file = open(script_path, 'r')

    for line in script_file:
        command = line.strip()
        if command == "run" or command == "r" or re.match("^process\s+launch.*", command):
            # Before starting to run the program, let the thread sleep a bit, so all
            # breakpoint added events can be processed
            time.sleep(0.5)
        if command != '':
            execute_command(command_interpreter, command)

except IOError as e:
    print("Could not read debugging script '%s'." % script_path, file=sys.stderr)
    print(e, file=sys.stderr)
    print("Aborting.", file=sys.stderr)
    sys.exit(1)
finally:
    debugger.Terminate()
    script_file.close()
