Exemplo n.º 1
0
    def ensure_lldb_is_running(cls, w=None):
        """Returns True if lldb is running (we don't care if we started it or not).
    Returns False on error"""
        # Ensure we reflect any changes to saved settings (including project settings)
        # reload_settings()

        if not w and window_ref():
            w = window_ref()
        else:
            # We're redefining the default window.
            set_window_ref(w)

        if driver_instance() is None:
            sm = SettingsManager.getSM()
            clear_view_on_startup = sm.get_default('i/o.view.clear_on_startup',
                                                   True)
            if clear_view_on_startup:
                LLDBLayoutManager.clear_view(lldb_out_view())

            if not cls.start_debugging(w):
                return False

            set_ui_updater(LLDBUIUpdater())
            g = cls.lldb_greeting()
            if lldb_out_view().size() > 0:
                g = '\n\n' + cls.lldb_greeting()
            lldb_view_write(g)
            lldb_view_write('cwd: ' + os.getcwd() + '\n')
            w.set_view_index(lldb_out_view(), 1, 0)

            cls.debug_prologue(driver_instance())
            return True

        return True
Exemplo n.º 2
0
    def initialize_plugin(cls):
        global _initialized
        if _initialized:
            return

        thread_created('<' + threading.current_thread().name + '>')
        debug(debugAny, 'Loading LLDB Sublime Text 2 plugin')
        debug(debugAny, 'python version: %s' % (sys.version_info,))
        debug(debugAny, 'cwd: %s' % os.getcwd())

        sm = SettingsManager.getSM()
        use_bundled_debugserver = sm.get_default('debugserver.use_bundled', False)
        debugserver_path = sm.get_default('debugerver.path', None)
        global _did_not_find_debugserver
        found = False
        if debugserver_path is not None:
            # TODO: Check that it is a file
            if os.access(debugserver_path, os.X_OK):
                os.environ['LLDB_DEBUGSERVER_PATH'] = debugserver_path
                found = True
            else:
                # FIXME: Warn the user that the debugserver isn't executable
                _did_not_find_debugserver = True
        elif not use_bundled_debugserver:
            cls.find_debugserver()

        if found:
            debug(debugPlugin, 'debugserver path: %s' % os.environ['LLDB_DEBUGSERVER_PATH'])
        _initialized = True
Exemplo n.º 3
0
 def set_lldb_window_layout(cls, window=window_ref()):
     sm = SettingsManager.getSM()
     lldb_window_layout = sm.get_default('layout',
                                         _default_lldb_window_layout)
     if lldb_out_view() != None and window.num_groups() != len(
             lldb_window_layout['cells']):
         window.run_command('set_layout', lldb_window_layout)
Exemplo n.º 4
0
    def ensure_lldb_is_running(cls, w=None):
        """Returns True if lldb is running (we don't care if we started it or not).
    Returns False on error"""
        # Ensure we reflect any changes to saved settings (including project settings)
        # reload_settings()

        if not w and window_ref():
            w = window_ref()
        else:
            # We're redefining the default window.
            set_window_ref(w)

        if driver_instance() is None:
            sm = SettingsManager.getSM()
            clear_view_on_startup = sm.get_default('i/o.view.clear_on_startup', True)
            if clear_view_on_startup:
                LLDBLayoutManager.clear_view(lldb_out_view())

            if not cls.start_debugging(w):
                return False

            set_ui_updater(LLDBUIUpdater())
            g = cls.lldb_greeting()
            if lldb_out_view().size() > 0:
                g = '\n\n' + cls.lldb_greeting()
            lldb_view_write(g)
            lldb_view_write('cwd: ' + os.getcwd() + '\n')
            w.set_view_index(lldb_out_view(), 1, 0)

            cls.debug_prologue(driver_instance())
            return True

        return True
Exemplo n.º 5
0
    def run(self):
        self.setup()
        if LLDBPlugin.ensure_lldb_is_running(self.window):
            sublime.status_message('Debugging session started.')
        else:
            sublime.error_message('Couldn\'t get a debugging session.')
            return False

        LLDBLayoutManager.lldb_toggle_output_view(self.window, show=True)

        exe = LLDBPlugin.search_for_executable()
        sm = SettingsManager.getSM()
        arch = sm.get_default('arch', lldb.LLDB_ARCH_DEFAULT)

        if exe:
            args = map(str, sm.get_default('args', []))

            debug(
                debugPlugin, 'Launching program: ' + exe + ' (' + arch +
                '), with args: ' + str(args))
            t = driver_instance().debugger.CreateTargetWithFileAndArch(
                str(exe), str(arch))
            driver_instance().debugger.SetSelectedTarget(t)

            sublime.status_message('Setting default breakpoints.')
            create_default_bps_for_target(t)

            sublime.status_message('Launching program (%s): %s %s' %
                                   (arch, exe, args))
            if t.LaunchSimple(args, None, os.getcwd()):
                sublime.status_message('Program successfully launched.')
            else:
                sublime.error_message('Program failed to launch.')
Exemplo n.º 6
0
    def run(self):
        self.setup()
        if LLDBPlugin.ensure_lldb_is_running(self.window):
            sublime.status_message('Debugging session started.')
        else:
            sublime.error_message('Couldn\'t get a debugging session.')
            return False

        LLDBLayoutManager.lldb_toggle_output_view(self.window, show=True)

        exe = LLDBPlugin.search_for_executable()
        sm = SettingsManager.getSM()
        arch = sm.get_default('arch', lldb.LLDB_ARCH_DEFAULT)

        if exe:
            args = map(str, sm.get_default('args', []))

            debug(debugPlugin, 'Launching program: ' + exe + ' (' + arch + '), with args: ' + str(args))
            t = driver_instance().debugger.CreateTargetWithFileAndArch(str(exe), str(arch))
            driver_instance().debugger.SetSelectedTarget(t)

            sublime.status_message('Setting default breakpoints.')
            create_default_bps_for_target(t)

            sublime.status_message('Launching program (%s): %s %s' % (arch, exe, args))
            if t.LaunchSimple(args, None, os.getcwd()):
                sublime.status_message('Program successfully launched.')
            else:
                sublime.error_message('Program failed to launch.')
Exemplo n.º 7
0
    def initialize_plugin(cls):
        global _initialized
        if _initialized:
            return

        thread_created('<' + threading.current_thread().name + '>')
        debug(debugAny, 'Loading LLDB Sublime Text 2 plugin')
        debug(debugAny, 'python version: %s' % (sys.version_info, ))
        debug(debugAny, 'cwd: %s' % os.getcwd())

        sm = SettingsManager.getSM()
        use_bundled_debugserver = sm.get_default('debugserver.use_bundled',
                                                 False)
        debugserver_path = sm.get_default('debugerver.path', None)
        global _did_not_find_debugserver
        found = False
        if debugserver_path is not None:
            # TODO: Check that it is a file
            if os.access(debugserver_path, os.X_OK):
                os.environ['LLDB_DEBUGSERVER_PATH'] = debugserver_path
                found = True
            else:
                # FIXME: Warn the user that the debugserver isn't executable
                _did_not_find_debugserver = True
        elif not use_bundled_debugserver:
            cls.find_debugserver()

        if found:
            debug(debugPlugin,
                  'debugserver path: %s' % os.environ['LLDB_DEBUGSERVER_PATH'])
        _initialized = True
Exemplo n.º 8
0
    def run(self):
        self.setup()

        sm = SettingsManager.getSM()
        basic_layout = sm.get_default('layout.basic', _default_basic_window_layout)
        if LLDBLayoutManager.good_lldb_layout(window=self.window) and basic_layout != None:
            # restore backup_layout (groups and views)
            LLDBLayoutManager.lldb_toggle_output_view(self.window, hide=True)
        else:
            LLDBLayoutManager.lldb_toggle_output_view(self.window, show=True)
Exemplo n.º 9
0
    def run(self):
        self.setup()

        sm = SettingsManager.getSM()
        basic_layout = sm.get_default('layout.basic',
                                      _default_basic_window_layout)
        if LLDBLayoutManager.good_lldb_layout(
                window=self.window) and basic_layout != None:
            # restore backup_layout (groups and views)
            LLDBLayoutManager.lldb_toggle_output_view(self.window, hide=True)
        else:
            LLDBLayoutManager.lldb_toggle_output_view(self.window, show=True)
Exemplo n.º 10
0
    def debug_prologue(cls, driver):
        """
        Prologue for the debugging session during the development of the plugin.
        Loads a simple program in the debugger and sets a breakpoint in main()
        """
        sm = SettingsManager.getSM()
        prologue = sm.get_default('prologue', [])

        debug(debugPlugin, 'LLDB prologue: %s' % str(prologue))
        for c in prologue:
            lldb_view_write(lldb_prompt() + c + '\n')
            driver.interpret_command(c)
Exemplo n.º 11
0
    def debug_prologue(cls, driver):
        """
        Prologue for the debugging session during the development of the plugin.
        Loads a simple program in the debugger and sets a breakpoint in main()
        """
        sm = SettingsManager.getSM()
        prologue = sm.get_default('prologue', [])

        debug(debugPlugin, 'LLDB prologue: %s' % str(prologue))
        for c in prologue:
            lldb_view_write(lldb_prompt() + c + '\n')
            driver.interpret_command(c)
Exemplo n.º 12
0
def get_lldb_output_view(window, name=None):
    # Search for the lldb_view view first.
    if not name:
        sm = SettingsManager.getSM()
        name = sm.get_default('i/o.view.name', default_lldb_view_name)

    f = maybe_get_lldb_output_view(window, name)
    if f is None:
        f = window.new_file()
        f.set_name(name)

    f.set_scratch(True)
    f.set_read_only(True)
    # f.set_syntax_file('…')  # lldb output syntax
    return f
Exemplo n.º 13
0
def get_lldb_output_view(window, name=None):
    # Search for the lldb_view view first.
    if not name:
        sm = SettingsManager.getSM()
        name = sm.get_default('i/o.view.name', default_lldb_view_name)

    f = maybe_get_lldb_output_view(window, name)
    if f is None:
        f = window.new_file()
        f.set_name(name)

    f.set_scratch(True)
    f.set_read_only(True)
    # f.set_syntax_file('…')  # lldb output syntax
    return f
Exemplo n.º 14
0
        def on_done(self, string):
            if self.__process:  # Check if it's still valid
                addr = int(string, 0)
                error = lldb.SBError()
                sm = SettingsManager.getSM()
                view_mem_size = sm.get_default('view.memory.size', 512)
                view_mem_width = sm.get_default('view.memory.width', 32)
                view_mem_grouping = sm.get_default('view.memory.grouping', 8)

                content = self.__process.ReadMemory(addr, view_mem_size, error)
                if error.Fail():
                    sublime.error_message(error.GetCString())
                    return None

                # Use 'ascii' encoding as each byte of 'content' is within [0..255].
                new_bytes = bytearray(content, 'latin1')

                result = generate_memory_view_for(addr, new_bytes,
                                                  view_mem_width,
                                                  view_mem_grouping)
                # Re-use a view, if we already have one.
                v = None
                name = self.__owner._view_memory_view_prefix + hex(addr)
                for _v in self.window.views():
                    if _v.name() == name:
                        v = _v
                        break

                if v is None:
                    layout_group_source_file = sm.get_default(
                        'layout.group.source_file', 0)
                    self.window.focus_group(layout_group_source_file)
                    v = self.window.new_file()
                    v.set_name(name)

                LLDBLayoutManager.clear_view(v)
                v.set_scratch(True)
                v.set_read_only(False)

                edit = v.begin_edit('lldb-view-memory-' + hex(addr))
                v.insert(edit, 0, result)
                v.end_edit(edit)
                v.set_read_only(True)
Exemplo n.º 15
0
def lldb_view_write(string):
    global __out_view, __window_ref
    if not (__out_view and __window_ref and __out_view.window()):
        sm = SettingsManager.getSM()
        name = sm.get_default('i/o.view.name', default_lldb_view_name)

        __out_view = get_lldb_output_view(__window_ref, name)
        if not __window_ref:
            # Bail out and just set the first window
            __window_ref = sublime.windows()[0]

        # __window_ref.set_view_index(__out_view, 1, 0)

    __out_view.set_read_only(False)
    edit = __out_view.begin_edit('lldb-panel-write')
    __out_view.insert(edit, __out_view.size(), string)
    __out_view.end_edit(edit)
    __out_view.set_read_only(True)
    __out_view.show(__out_view.size())
Exemplo n.º 16
0
def lldb_view_write(string):
    global __out_view, __window_ref
    if not (__out_view and __window_ref and __out_view.window()):
        sm = SettingsManager.getSM()
        name = sm.get_default('i/o.view.name', default_lldb_view_name)

        __out_view = get_lldb_output_view(__window_ref, name)
        if not __window_ref:
            # Bail out and just set the first window
            __window_ref = sublime.windows()[0]

        # __window_ref.set_view_index(__out_view, 1, 0)

    __out_view.set_read_only(False)
    edit = __out_view.begin_edit('lldb-panel-write')
    __out_view.insert(edit, __out_view.size(), string)
    __out_view.end_edit(edit)
    __out_view.set_read_only(True)
    __out_view.show(__out_view.size())
Exemplo n.º 17
0
def create_default_bps_for_target(target):
    n = 0
    sm = SettingsManager.getSM()
    bps = sm.get_default('breakpoints', [])
    for bp in bps:
        if not bp:
            continue

        if type(bp) is str or type(bp) is unicode:
            bp = str(bp)
            m = bp_re_file_line.match(bp)
            if m:
                target.BreakpointCreateByLocation(m.group(1), m.group(2))
                ++n
                continue

            m = bp_re_address.match(bp)
            if m:
                target.BreakpointCreateByAddress(m.group(1))
                ++n
                continue

            m = bp_re_name.match(bp)
            if m:
                target.BreakpointCreateByName(m.group(1))
                ++n
                continue

            debug(debugPlugin,
                  "couldn't tell where the bp spec '" + bp + "' should break.")

        # bp isn't an str. It should be a dict
        elif 'file' in bp and 'line' in bp:
            target.BreakpointCreateByLocation(str(bp['file']), bp['line'])
            ++n
        elif 'address' in bp:
            target.BreakpointCreateByAddress(bp['address'])
            ++n
        else:
            debug(debugPlugin, 'unrecognized breakpoint type: ' + str(bp))
Exemplo n.º 18
0
        def on_done(self, string):
            if self.__process:  # Check if it's still valid
                addr = int(string, 0)
                error = lldb.SBError()
                sm = SettingsManager.getSM()
                view_mem_size = sm.get_default('view.memory.size', 512)
                view_mem_width = sm.get_default('view.memory.width', 32)
                view_mem_grouping = sm.get_default('view.memory.grouping', 8)

                content = self.__process.ReadMemory(addr, view_mem_size, error)
                if error.Fail():
                    sublime.error_message(error.GetCString())
                    return None

                # Use 'ascii' encoding as each byte of 'content' is within [0..255].
                new_bytes = bytearray(content, 'latin1')

                result = generate_memory_view_for(addr, new_bytes, view_mem_width, view_mem_grouping)
                # Re-use a view, if we already have one.
                v = None
                name = self.__owner._view_memory_view_prefix + hex(addr)
                for _v in self.window.views():
                    if _v.name() == name:
                        v = _v
                        break

                if v is None:
                    layout_group_source_file = sm.get_default('layout.group.source_file', 0)
                    self.window.focus_group(layout_group_source_file)
                    v = self.window.new_file()
                    v.set_name(name)

                LLDBLayoutManager.clear_view(v)
                v.set_scratch(True)
                v.set_read_only(False)

                edit = v.begin_edit('lldb-view-memory-' + hex(addr))
                v.insert(edit, 0, result)
                v.end_edit(edit)
                v.set_read_only(True)
Exemplo n.º 19
0
def create_default_bps_for_target(target):
    n = 0
    sm = SettingsManager.getSM()
    bps = sm.get_default('breakpoints', [])
    for bp in bps:
        if not bp:
            continue

        if type(bp) is str or type(bp) is unicode:
            bp = str(bp)
            m = bp_re_file_line.match(bp)
            if m:
                target.BreakpointCreateByLocation(m.group(1), m.group(2))
                ++n
                continue

            m = bp_re_address.match(bp)
            if m:
                target.BreakpointCreateByAddress(m.group(1))
                ++n
                continue

            m = bp_re_name.match(bp)
            if m:
                target.BreakpointCreateByName(m.group(1))
                ++n
                continue

            debug(debugPlugin, "couldn't tell where the bp spec '" + bp + "' should break.")

        # bp isn't an str. It should be a dict
        elif 'file' in bp and 'line' in bp:
            target.BreakpointCreateByLocation(str(bp['file']), bp['line'])
            ++n
        elif 'address' in bp:
            target.BreakpointCreateByAddress(bp['address'])
            ++n
        else:
            debug(debugPlugin, 'unrecognized breakpoint type: ' + str(bp))
Exemplo n.º 20
0
 def set_regular_window_layout(cls, window=window_ref()):
     sm = SettingsManager.getSM()
     basic_layout = sm.get_default('layout.basic',
                                   _default_basic_window_layout)
     window.run_command('set_layout', basic_layout)
Exemplo n.º 21
0
 def search_for_executable(cls):
     sm = SettingsManager.getSM()
     exe = sm.get_default('exe', None)
     return exe
Exemplo n.º 22
0
 def good_lldb_layout(cls, window=window_ref()):
     # if the user already has two groups, it's a good layout
     sm = SettingsManager.getSM()
     lldb_window_layout = sm.get_default('layout',
                                         _default_lldb_window_layout)
     return window.num_groups() == len(lldb_window_layout['cells'])
Exemplo n.º 23
0
 def good_lldb_layout(cls, window=window_ref()):
     # if the user already has two groups, it's a good layout
     sm = SettingsManager.getSM()
     lldb_window_layout = sm.get_default('layout', _default_lldb_window_layout)
     return window.num_groups() == len(lldb_window_layout['cells'])
Exemplo n.º 24
0
        def on_done(self, string):
            if LLDBPlugin.ensure_lldb_is_running(self.window):
                sublime.status_message('Debugging session started.')
            else:
                sublime.error_message('Couldn\'t get a debugging session.')
                return False

            driver = driver_instance()
            if driver:
                # Check if we have a previously running program
                target = driver.debugger.GetSelectedTarget()

                if not target:
                    target = driver.debugger.CreateTarget('')
                    if not target:
                        sublime.error_message('Error attaching to process')
                    driver.debugger.SetSelectedTarget(target)

                old_exec_module = target.GetExecutable()
                old_triple = target.GetTriple()

                # attach_info = lldb.SBAttachInfo()
                # If the user didn't specify anything, attach to the program from
                # the current target, if it exists
                # if string is '':
                #     if old_exec_module:
                #         attach_info.SetExecutable(old_exec_module)
                #     else:
                #         # Bail out
                #         sublime.error_message('No process name/ID specified and no current target.')
                #         return
                # else:
                error = lldb.SBError()
                sm = SettingsManager.getSM()
                wait_for_launch = sm.get_default('attach.wait_for_launch', False)

                try:
                    pid = int(string)
                    # attach_info.SetProcessID(pid)
                    debug(debugPlugin, 'Attaching to pid: %d' % pid)
                    sublime.status_message('Attaching to pid: %d' % pid)
                    process = target.AttachToProcessWithID(lldb.SBListener(), pid, error)
                except ValueError:
                    # We have a process name, not a pid.
                    # pid = lldb.LLDB_INVALID_PROCESS_ID
                    # attach_info.SetExecutable(str(string))
                    name = str(string) if string != '' else old_exec_module
                    debug(debugPlugin, 'Attaching to process: %s (wait=%s)' % (name, str(wait_for_launch)))
                    sublime.status_message('Attaching to process: %s (wait=%s)' % (name, wait_for_launch))
                    process = target.AttachToProcessWithName(lldb.SBListener(), name, wait_for_launch, error)

                # attach_info.SetWaitForLaunch(wait_for_launch)

                # error = lldb.SBError()
                # debug(debugPlugin, attach_info)
                # process = target.Attach(attach_info, error)

                debug(debugPlugin, process)
                if error.Fail():
                    sublime.error_message("Attach failed: %s" % error.GetCString())

                new_exec_module = target.GetExecutable()
                if new_exec_module != old_exec_module:
                    debug(debugPlugin, 'Executable module changed from "%s" to "%s".' % \
                        (old_exec_module, new_exec_module))

                new_triple = target.GetTriple()
                if new_triple != old_triple:
                    debug(debugPlugin, 'Target triple changed from "%s" to "%s".' % (old_triple, new_triple))

                # How can we setup the default breakpoints?
                # We *could* start a new thread with a listener, just for that...
            else:
                sublime.error_message('Couldn\'t get a debugging session.')
Exemplo n.º 25
0
        def on_done(self, string):
            if LLDBPlugin.ensure_lldb_is_running(self.window):
                sublime.status_message('Debugging session started.')
            else:
                sublime.error_message('Couldn\'t get a debugging session.')
                return False

            driver = driver_instance()
            if driver:
                # Check if we have a previously running program
                target = driver.debugger.GetSelectedTarget()

                if not target:
                    target = driver.debugger.CreateTarget('')
                    if not target:
                        sublime.error_message('Error attaching to process')
                    driver.debugger.SetSelectedTarget(target)

                old_exec_module = target.GetExecutable()
                old_triple = target.GetTriple()

                # attach_info = lldb.SBAttachInfo()
                # If the user didn't specify anything, attach to the program from
                # the current target, if it exists
                # if string is '':
                #     if old_exec_module:
                #         attach_info.SetExecutable(old_exec_module)
                #     else:
                #         # Bail out
                #         sublime.error_message('No process name/ID specified and no current target.')
                #         return
                # else:
                error = lldb.SBError()
                sm = SettingsManager.getSM()
                wait_for_launch = sm.get_default('attach.wait_for_launch',
                                                 False)

                try:
                    pid = int(string)
                    # attach_info.SetProcessID(pid)
                    debug(debugPlugin, 'Attaching to pid: %d' % pid)
                    sublime.status_message('Attaching to pid: %d' % pid)
                    process = target.AttachToProcessWithID(
                        lldb.SBListener(), pid, error)
                except ValueError:
                    # We have a process name, not a pid.
                    # pid = lldb.LLDB_INVALID_PROCESS_ID
                    # attach_info.SetExecutable(str(string))
                    name = str(string) if string != '' else old_exec_module
                    debug(
                        debugPlugin, 'Attaching to process: %s (wait=%s)' %
                        (name, str(wait_for_launch)))
                    sublime.status_message(
                        'Attaching to process: %s (wait=%s)' %
                        (name, wait_for_launch))
                    process = target.AttachToProcessWithName(
                        lldb.SBListener(), name, wait_for_launch, error)

                # attach_info.SetWaitForLaunch(wait_for_launch)

                # error = lldb.SBError()
                # debug(debugPlugin, attach_info)
                # process = target.Attach(attach_info, error)

                debug(debugPlugin, process)
                if error.Fail():
                    sublime.error_message("Attach failed: %s" %
                                          error.GetCString())

                new_exec_module = target.GetExecutable()
                if new_exec_module != old_exec_module:
                    debug(debugPlugin, 'Executable module changed from "%s" to "%s".' % \
                        (old_exec_module, new_exec_module))

                new_triple = target.GetTriple()
                if new_triple != old_triple:
                    debug(
                        debugPlugin,
                        'Target triple changed from "%s" to "%s".' %
                        (old_triple, new_triple))

                # How can we setup the default breakpoints?
                # We *could* start a new thread with a listener, just for that...
            else:
                sublime.error_message('Couldn\'t get a debugging session.')
Exemplo n.º 26
0
 def set_regular_window_layout(cls, window=window_ref()):
     sm = SettingsManager.getSM()
     basic_layout = sm.get_default('layout.basic', _default_basic_window_layout)
     window.run_command('set_layout', basic_layout)
Exemplo n.º 27
0
class LLDBThreadDisassemblyView(LLDBReadOnlyView):
    __pc_line = 0

    settings_keys = [
        'markers.current_line.region_name', 'markers.current_line.scope',
        'markers.current_line.scope.crashed', 'markers.current_line.icon'
    ]

    __sm = SettingsManager.getSM()
    eMarkerPCName = __sm.get_default('markers.current_line.region_name',
                                     'lldb.location')
    eMarkerPCScope = __sm.get_default('markers.current_line.scope', 'bookmark')
    eMarkerPCScopeCrashed = __sm.get_default(
        'markers.current_line.scope.crashed', 'invalid')
    eMarkerPCIcon = __sm.get_default('markers.current_line.icon', 'bookmark')

    def __init__(self, view, thread):
        self.__thread = thread
        super(LLDBThreadDisassemblyView, self).__init__(view)

        self.set_name(lldb_disassembly_view_name(thread.GetThreadID()))
        self.set_scratch()

        # FIXME: Just make every LLDBCodeView observe the settings.
        #        Another way to do it would be for the class to observe and
        #        then call the appropriate method on all the instances.
        for k in self.settings_keys:
            self.__sm.add_observer(k, self.setting_updated)

    def __repr__(self):
        return '<%s: name: %s, thread %s, pc_line: %d, content size: %d>' % \
            (self.__class__.__name__, self.name(), self.thread, self.pc_line, len(self.content()))

    ##########################################
    # View properties.
    @property
    def thread(self):
        return self.__thread

    @property
    def pc_line(self):
        return self.__pc_line

    ##########################################
    # Settings observer method.
    def setting_updated(self, key, old, new):
        debug(
            debugSettings | debugViews,
            'Updating setting %s from %s to %s. instance: %s' %
            (key, old, new, self))
        if key.startswith('markers.current_line'):
            # Update all the PC settings.
            self.__mark_pc(None)
            self.__class__.eMarkerPCName = self.__sm.get_default(
                'markers.current_line.region_name', 'lldb.location')
            self.__class__.eMarkerPCScope = self.__sm.get_default(
                'markers.current_line.scope', 'bookmark')
            self.__class__.eMarkerPCScopeCrashed = self.__sm.get_default(
                'markers.current_line.scope.crashed', 'invalid')
            self.__class__.eMarkerPCIcon = self.__sm.get_default(
                'markers.current_line.icon', 'bookmark')
            self.__mark_pc(self.__pc_line - 1, False)

        else:
            raise Exception(
                'Weird key to be updated for LLDBThreadDisassemblyView %s' %
                key)

    ##########################################
    # Update mechanism implementation.
    def epilogue(self):
        if self.pc_line != 0:
            debug(debugViews,
                  'Marking PC for LLDBDisassemblyView %s' % repr(self))
            v = self.base_view()
            r = v.text_point(self.pc_line, 0)
            to_mark = [v.line(r)]

            debug(
                debugViews, '(' + self.name() + ') adding region: ' + str(
                    (self.eMarkerPCName, to_mark, self.eMarkerPCScope,
                     self.eMarkerPCIcon, sublime.HIDDEN)))
            self.base_view().add_regions(self.eMarkerPCName, to_mark,
                                         self.eMarkerPCScope,
                                         self.eMarkerPCIcon, sublime.HIDDEN)
            self.show(to_mark[0], True)
        else:
            debug(debugViews, 'erasing region: %s' % self.eMarkerPCName)
            self.base_view().erase_regions(self.eMarkerPCName)

    def updated_content(self):
        debug(debugViews, 'Updating content for: %s' % repr(self))
        # Reset the PC line number
        self.__pc_line = 0

        thread = self.__thread
        if not thread.IsValid():
            return 'Invalid thread. Has it finished its work?'

        target = thread.GetProcess().GetTarget()
        pc = thread.GetSelectedFrame().GetPCAddress()
        function = pc.GetFunction()
        symbol = pc.GetSymbol()
        if function.IsValid():
            name = function.GetName()
            start_addr = function.GetStartAddress().GetLoadAddress(target)
        elif symbol.IsValid():
            name = symbol.GetName()
            start_addr = symbol.GetStartAddress().GetLoadAddress(target)
        else:
            name = pc.GetModule().GetFileSpec().GetFilename()
            start_addr = pc.GetLoadAddress(target)

        instrs = driver_instance().disassemble_frame(thread.GetSelectedFrame())
        if not instrs:
            return 'Error getting instructions for thread 0x%x: No instructions available.' % thread.GetThreadID(
            )

        pc = driver_instance().get_PC()

        def get_max_sizes(accum, next):
            return (max(accum[0], len(next[1])), max(accum[1], len(next[2])))

        (max_mnemonic, max_operands) = reduce(get_max_sizes, instrs, (0, 0))
        format_str = '%.10s: %*s %*s%s\n'
        max_mnemonic, max_operands = (int(max_mnemonic), int(max_operands))

        result = '%s @ 0x%s:\n' % (name, start_addr)
        n_instrs = 0
        for i in instrs:
            n_instrs += 1
            if len(i) == 3:
                (addr, mnemonic, ops) = i
                comment_str = ''
            elif len(i) == 4:
                (addr, mnemonic, ops, comment) = i
                comment_str = '\t; ' + comment
            else:
                assert False

            if pc == addr:
                self.__pc_line = n_instrs

            result += format_str % (hex(addr), max_mnemonic, mnemonic,
                                    max_operands, ops, comment_str)

        return result
Exemplo n.º 28
0
 def setup(self):
     if lldb_out_view() is None:
         sm = SettingsManager.getSM()
         view_name = sm.get_default('i/o.view.name', default_lldb_view_name)
         set_lldb_out_view(get_lldb_output_view(
             self.window, view_name))  # for lldb output
Exemplo n.º 29
0
 def set_lldb_window_layout(cls, window=window_ref()):
     sm = SettingsManager.getSM()
     lldb_window_layout = sm.get_default('layout', _default_lldb_window_layout)
     if lldb_out_view() != None and window.num_groups() != len(lldb_window_layout['cells']):
         window.run_command('set_layout', lldb_window_layout)
Exemplo n.º 30
0
 def search_for_executable(cls):
     sm = SettingsManager.getSM()
     exe = sm.get_default('exe', None)
     return exe
Exemplo n.º 31
0
class LLDBCodeView(LLDBView):
    eRegionPC = 1 << 0
    eRegionBreakpointEnabled = 1 << 1
    eRegionBreakpointDisabled = 1 << 2

    __pc_line = None
    __bp_lock = Lock()

    # Settings for the whole class
    settings_keys = [
        'markers.current_line.region_name', 'markers.current_line.scope',
        'markers.current_line.scope.crashed', 'markers.current_line.icon',
        'markers.breakpoint.enabled.region_name',
        'markers.breakpoint.enabled.scope', 'markers.breakpoint.enabled.type',
        'markers.breakpoint.disabled.region_name',
        'markers.breakpoint.disabled.scope', 'markers.breakpoint.disabled.type'
    ]

    __sm = SettingsManager.getSM()
    eMarkerPCName = __sm.get_default('markers.current_line.region_name',
                                     'lldb.location')
    eMarkerPCScope = __sm.get_default('markers.current_line.scope', 'bookmark')
    eMarkerPCScopeCrashed = __sm.get_default(
        'markers.current_line.scope.crashed', 'invalid')
    eMarkerPCIcon = __sm.get_default('markers.current_line.icon', 'bookmark')
    eMarkerBreakpointEnabledName = __sm.get_default(
        'markers.breakpoint.enabled.region_name', 'lldb.breakpoint.enabled')
    eMarkerBreakpointEnabledScope = __sm.get_default(
        'markers.breakpoint.enabled.scope', 'string')
    eMarkerBreakpointEnabledIcon = __sm.get_default(
        'markers.breakpoint.enabled.type', 'circle')
    eMarkerBreakpointDisabledName = __sm.get_default(
        'markers.breakpoint.disabled.region_name', 'lldb.breakpoint.disabled')
    eMarkerBreakpointDisabledScope = __sm.get_default(
        'markers.breakpoint.disabled.scope', 'bookmark')
    eMarkerBreakpointDisabledIcon = __sm.get_default(
        'markers.breakpoint.disabled.type', 'circle')

    def __init__(self, view, driver):
        # FIXME: Split stuff that doesn't have to run on the UI thread.
        super(LLDBCodeView, self).__init__(view)

        self.__needs_update = False
        self.__driver = driver
        self.__enabled_bps = {}
        self.__disabled_bps = {}
        # Get info on current breakpoints for this file
        self.__populate_breakpoint_lists()
        if not view.is_loading():
            self.__update_bps()
            self.pre_update()
        else:
            debug(
                debugViews,
                'Skipped LLDBCodeView.__update_bps() because view.is_loading is True'
            )
            self.pre_update()
            self.__needs_update = 'full'  # Horrible hack to update the bp
            # markers as well as the pc marker when the on_load
            # method calls update on this object

        # FIXME: Just make every LLDBCodeView observe the settings.
        #        Another way to do it would be for the class to observe and
        #        then call the appropriate method on all the instances.
        for k in self.settings_keys:
            self.__sm.add_observer(k, self.setting_updated)

    def __del__(self):
        # FIXME: This method won't get called since our observers dict holds a
        # reference to this object.
        self.__sm.del_observer(self.settings_updated)

    def __repr__(self):
        return '<%s: file_name: %s, needs_update: %s, pc_line: %s, enabled_bps: %s, disable_bps: %s>' % \
            (self.__class__.__name__, self.file_name(), str(self._needs_update),
             str(self.__pc_line), str(self.__enabled_bps), str(self.__disabled_bps))

    ##########################################
    # Settings observer method.
    def setting_updated(self, key, old, new):
        debug(
            debugSettings | debugViews,
            'Updating setting %s from %s to %s. instance: %s' %
            (key, old, new, self))
        if key.startswith('markers.current_line'):
            # Update all the PC settings.
            self.__mark_pc(None)
            self.__class__.eMarkerPCName = self.__sm.get_default(
                'markers.current_line.region_name', 'lldb.location')
            self.__class__.eMarkerPCScope = self.__sm.get_default(
                'markers.current_line.scope', 'bookmark')
            self.__class__.eMarkerPCScopeCrashed = self.__sm.get_default(
                'markers.current_line.scope.crashed', 'invalid')
            self.__class__.eMarkerPCIcon = self.__sm.get_default(
                'markers.current_line.icon', 'bookmark')
            self.__mark_pc(self.__pc_line - 1, False)

        elif key.startswith('markers.breakpoint.enabled'):
            # Update all the enabled bp settings.
            self.__mark_regions([], self.eRegionBreakpointEnabled)
            self.__class__.eMarkerBreakpointEnabledName = self.__sm.get_default(
                'markers.breakpoint.enabled.region_name',
                'lldb.breakpoint.enabled')
            self.__class__.eMarkerBreakpointEnabledScope = self.__sm.get_default(
                'markers.breakpoint.enabled.scope', 'string')
            self.__class__.eMarkerBreakpointEnabledIcon = self.__sm.get_default(
                'markers.breakpoint.enabled.type', 'circle')
            # TODO: Check if the settings' on_change method is always called in
            # the main thread. If not, we'll have to guard the regions
            # definition
            v = self.base_view()
            regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                          self.__enabled_bps.keys())
            self.__mark_regions(regions, self.eRegionBreakpointEnabled)

        elif key.startswith('markers.breakpoint.disabled'):
            # Update all the disabled bp settings.
            self.__mark_regions([], self.eRegionBreakpointDisabled)
            self.__class__.eMarkerBreakpointDisabledName = self.__sm.get_default(
                'markers.breakpoint.disabled.region_name',
                'lldb.breakpoint.disabled')
            self.__class__.eMarkerBreakpointDisabledScope = self.__sm.get_default(
                'markers.breakpoint.disabled.scope', 'bookmark')
            self.__class__.eMarkerBreakpointDisabledIcon = self.__sm.get_default(
                'markers.breakpoint.disabled.type', 'circle')
            # TODO: Check if the settings' on_change method is always called in
            # the main thread. If not, we'll have to guard the regions
            # definition
            v = self.base_view()
            regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                          self.__disabled_bps.keys())
            self.__mark_regions(regions, self.eRegionBreakpointDisabled)

        else:
            raise Exception('Weird key to be updated for LLDBCodeView: %s' %
                            key)

    ##########################################
    # View properties.
    @property
    def __needs_update(self):
        return self._needs_update

    @__needs_update.setter
    def __needs_update(self, value):
        self._needs_update = value

    ##########################################
    # Breakpoint markers' methods.
    def mark_bp(self, line, is_enabled=True):
        # {mark,change,unmark}_bp don't update __needs_update because they
        # immediately update the breakpoint markers
        """Mark a new breakpoint as enabled/disabled and immediately mark
            its region."""
        self.__add_bps([line], is_enabled)
        v = self.base_view()

        if is_enabled:
            regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                          self.__enabled_bps.keys())
            self.__mark_regions(regions, self.eRegionBreakpointEnabled)
        else:
            regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                          self.__disabled_bps.keys())
            self.__mark_regions(regions, self.eRegionBreakpointDisabled)

    def change_bp(self, line, is_enabled):
        if is_enabled:
            remove_from = self.__disabled_bps
            add_to = self.__enabled_bps
        else:
            remove_from = self.__enabled_bps
            add_to = self.__disabled_bps

        with self.__bp_lock:
            # The breakpoint must exist in remove_from
            existing = remove_from[line]
            if existing == 1:
                del remove_from[line]
            else:
                remove_from[line] = existing - 1

            if line in add_to:
                existing = add_to[line]
            else:
                existing = 0
            add_to[line] = existing + 1

        v = self.base_view()
        regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                      self.__enabled_bps.keys())
        self.__mark_regions(regions, self.eRegionBreakpointEnabled)
        regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                      self.__disabled_bps.keys())
        self.__mark_regions(regions, self.eRegionBreakpointDisabled)

    def unmark_bp(self, line, is_enabled=True):
        """Remove merkings for a breakpoint and update the UI
            afterwards."""
        self.__remove_bps([line], is_enabled)
        v = self.base_view()

        if is_enabled:
            regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                          self.__enabled_bps.keys())
            self.__mark_regions(regions, self.eRegionBreakpointEnabled)
        else:
            regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                          self.__disabled_bps.keys())
            self.__mark_regions(regions, self.eRegionBreakpointDisabled)

    ##########################################
    # Update mechanism implementation.
    def pre_update(self):
        """pre_update will perform lldb-related work and get our PC line"""
        # FIXME: We can't use base_view().is_loading() because Sublime
        # Text 2 won't even let us query views on another thread (even
        # read-only properties!!).
        # This 'full' hack is here to make us wait for the on_load() call
        # on the LLDBUIListener.
        # This variable will make us keep __needs_update == 'full' if it was
        # like that before we ran this function.
        old_needs_update = self.__needs_update
        self.__needs_update = False

        old_pc_line = self.__pc_line
        self.__pc_line = None
        debug(debugViews, 'old pc_line: %s' % str(old_pc_line))

        thread = self.__driver.current_thread()
        if not thread:
            debug(debugViews, 'new pc_line: %s' % str(self.__pc_line))
            if self.__pc_line != old_pc_line:
                self.__needs_update = old_needs_update or True
            return False

        for frame in thread:
            line_entry = frame.GetLineEntry()
            filespec = line_entry.GetFileSpec()
            if filespec:
                filename = filespec.GetDirectory(
                ) + '/' + filespec.GetFilename()
                if filename == self.file_name():
                    self.__pc_line = line_entry.GetLine()
                    debug(debugViews, 'new pc_line: %s' % str(self.__pc_line))
                    if self.__pc_line != old_pc_line or old_needs_update == 'full':
                        self.__needs_update = old_needs_update or True
                    return True

        debug(debugViews, 'new pc_line: %s' % str(self.__pc_line))
        if self.__pc_line != old_pc_line or old_needs_update == 'full':
            self.__needs_update = old_needs_update or True
        return False

    def update(self):
        debug(
            debugViews, 'Updating LLDBCodeView. needs_update: %s' %
            str(self.__needs_update))
        if self.__needs_update and not self.base_view().is_loading():
            # Hack so we update the bps when updating the view for the first time.
            if self.__needs_update == 'full':
                self.__update_bps()

            if self.__pc_line is not None:
                self.__mark_pc(self.__pc_line - 1, True)
            else:
                self.__mark_pc(None)
            # For now, bp-marking functions will immediately update the
            # view. We don't need to update it when the view is dirty.
            # self.__update_bps()
            self.__needs_update = False
        else:
            debug(
                debugViews,
                'LLDBCodeView: didn\'t need an update (or view was loading): %s'
                % repr(self))

    def stop(self):
        self.pre_update()  # This will set pc_line to None
        self.__enabled_bps = {}
        self.__disabled_bps = {}

        def to_ui():
            debug(debugViews, 'executing UI code for LLDBCodeView.stop()')
            self.update()
            self.__update_bps()

        sublime.set_timeout(to_ui, 0)

    ##########################################
    # Private LLDBCodeView methods
    def __mark_regions(self, regions, type):
        if type == self.eRegionPC:
            self.__mark_or_delete_regions(self.eMarkerPCName, regions,
                                          self.eMarkerPCScope,
                                          self.eMarkerPCIcon, sublime.HIDDEN)
        elif type == self.eRegionBreakpointEnabled:
            self.__mark_or_delete_regions(self.eMarkerBreakpointEnabledName,
                                          regions,
                                          self.eMarkerBreakpointEnabledScope,
                                          self.eMarkerBreakpointEnabledIcon,
                                          sublime.HIDDEN)
        elif type == self.eRegionBreakpointDisabled:
            self.__mark_or_delete_regions(self.eMarkerBreakpointDisabledName,
                                          regions,
                                          self.eMarkerBreakpointDisabledScope,
                                          self.eMarkerBreakpointDisabledIcon,
                                          sublime.HIDDEN)

    def __mark_or_delete_regions(self, name, regions, scope, icon, options):
        if len(regions) > 0:
            debug(
                debugViews, '(%s) adding regions: %s' %
                (self.file_name(), (name, regions, scope, icon, options)))
            self.base_view().add_regions(name, regions, scope, icon, options)
        else:
            debug(debugViews, 'erasing regions: %s' % name)
            self.base_view().erase_regions(name)

    def __mark_pc(self, line, show=False):
        debug(debugViews, 'Marking PC for LLDBCodeView: %s' % repr(self))
        v = self.base_view()
        if line is None:
            to_mark = []
        else:
            to_mark = [v.line(v.text_point(line, 0))]
        self.__mark_regions(to_mark, self.eRegionPC)
        if show and to_mark:
            self.show(to_mark[0], True)

    def __populate_breakpoint_lists(self):
        file_bp_locs = self.__driver.get_breakpoint_locations_for_file(
            self.file_name())

        def line_from_bp_loc(bp_loc):
            line_entry = bp_loc.GetAddress().GetLineEntry()
            return line_entry.GetLine()

        enabled_bp_lines = []
        disabled_bp_lines = []
        for bp_loc in file_bp_locs:
            if bp_loc.IsEnabled():
                enabled_bp_lines.append(line_from_bp_loc(bp_loc))
            else:
                disabled_bp_lines.append(line_from_bp_loc(bp_loc))

        self.__add_bps(enabled_bp_lines, True)
        self.__add_bps(disabled_bp_lines, False)

    def __add_bps(self, lines, are_enabled=True):
        """Adds breakpoints (enabled or disabled) to the view.
            __update_bps() must be called afterwards to refresh the UI."""
        if len(lines) > 0:
            self.__needs_update = True

        if are_enabled:
            add_to = self.__enabled_bps
        else:
            add_to = self.__disabled_bps

        with self.__bp_lock:
            # We shouldn't have that many breakpoints for this to be a
            # problem. If the lock becomes a problem, we can lock for each
            # breakpoint.
            for line in lines:
                if line in add_to:
                    existing = add_to[line]
                else:
                    existing = 0

                add_to[line] = existing + 1

    def __remove_bps(self, lines, are_enabled=True):
        """Removes breakpoints (enabled or disabled) from the view.
            __update_bps() must be called afterwards to refresh the UI."""
        if len(lines) > 0:
            self.__needs_update = True

        if are_enabled:
            remove_from = self.__enabled_bps
        else:
            remove_from = self.__disabled_bps

        with self.__bp_lock:
            for line in lines:
                existing = remove_from[line]
                if existing == 1:
                    del remove_from[line]
                else:
                    remove_from[line] = existing - 1

    def __update_bps(self):
        v = self.base_view()
        regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                      self.__enabled_bps.keys())
        self.__mark_regions(regions, self.eRegionBreakpointEnabled)
        regions = map(lambda line: v.line(v.text_point(line - 1, 0)),
                      self.__disabled_bps.keys())
        self.__mark_regions(regions, self.eRegionBreakpointDisabled)
Exemplo n.º 32
0
 def setup(self):
     if lldb_out_view() is None:
         sm = SettingsManager.getSM()
         view_name = sm.get_default('i/o.view.name', default_lldb_view_name)
         set_lldb_out_view(get_lldb_output_view(self.window, view_name))  # for lldb output