Beispiel #1
0
class StateOutput(object):
    parser = Parser()

    @staticmethod
    def parse(data):
        assert data[0] == Communicator.EXEC_ASYNC_START

        data = data[1:]
        state = OutputParser.get_name_until_param(data)

        if state == "running":
            return StateOutput(ProcessState.Running)
        elif state == "stopped":
            data = data[len(state) + 1:]
            data = StateOutput.parser.parse(data)

            state = ProcessState.Stopped
            exit_code = None

            reason = ""

            if "reason" in data:
                reason = data["reason"]

            if "exited" in reason:
                state = ProcessState.Exited

                if "exit-code" in data:
                    exit_code = int(data["exit-code"])
                elif "normally" in reason:
                    exit_code = 0

            return StateOutput(state, reason, exit_code)
        else:
            raise Exception("No state found for data: {0}".format(data))

    def __init__(self, state, reason=None, exit_code=None):
        """
        @type state: enums.ProcessState
        @type reason: enums.StopReason
        @type exit_code: int
        """
        self.state = state
        self.reason = reason
        self.exit_code = exit_code
Beispiel #2
0
 def __init__(self, debugger):
     """
     @type debugger: Debugger
     """
     super(VariableManager, self).__init__(debugger)
     self.parser = Parser()
Beispiel #3
0
class VariableManager(debugger_api.VariableManager):
    RECURSION_LIMIT = 3

    """
    Handles retrieval and updating of variables and raw memory of the
    debugged process.
    """
    def __init__(self, debugger):
        """
        @type debugger: Debugger
        """
        super(VariableManager, self).__init__(debugger)
        self.parser = Parser()

    def get_type(self, expression, level=0):
        """
        Returns type for the given expression.
        @type expression: str
        @type level: int
        @rtype: debugee.Type
        """
        if level > VariableManager.RECURSION_LIMIT:
            return None

        output = self.debugger.communicator.send("ptype {0}".
                                                 format(expression))
        short_output = self.debugger.communicator.send("whatis {0}".
                                                       format(expression))

        if output and short_output:
            try:
                type = self.parser.parse_variable_type(output.cli_data[0])
                type_name = self.parser.parse_variable_type(
                    short_output.cli_data[0])
            except:
                Logger.debug(traceback.format_exc())
                return None

            basic_type_category = BasicTypeCategory.Invalid
            type_category = TypeCategory.Class

            modificators = []

            try:
                while type.startswith("volatile") or type.startswith("const"):
                    modificator = type[:type.find(" ")]
                    type = type[len(modificator) + 1:]
                    modificators.append(modificator)

                    if type_name.startswith(modificator):
                        type_name = type_name[len(modificator) + 1:]
            except:
                Logger.debug(traceback.format_exc())
                return None

            if type in basic_type_map:
                basic_type_category = basic_type_map[type]
                type_category = TypeCategory.Builtin
            else:
                if type_name.startswith("std::vector"):
                    type_category = TypeCategory.Vector
                elif type_name.startswith("std::string"):
                    type_category = TypeCategory.String
                elif type_name.endswith("*"):
                    type_category = TypeCategory.Pointer
                elif type_name.endswith("&"):
                    type_category = TypeCategory.Reference
                elif type_name.endswith("]"):
                    type_category = TypeCategory.Array
                elif type_name.endswith(")"):
                    type_category = TypeCategory.Function
                elif type.startswith("struct"):
                    type_category = TypeCategory.Struct
                elif type.startswith("class"):
                    type_category = TypeCategory.Class
                elif type.startswith("union"):
                    type_category = TypeCategory.Union
                elif type.startswith("enum"):
                    type_category = TypeCategory.Enumeration

            size = None
            size_output = self.debugger.communicator.send("p sizeof({0})".
                                                          format(type_name))
            if size_output:
                try:
                    size = int(self.parser.parse_print_expression(
                        size_output.cli_data[0]))
                except:
                    Logger.debug(traceback.format_exc())
                    return None

            args = [type_name, type_category, basic_type_category, size,
                    tuple(modificators)]

            try:
                if type_category == TypeCategory.Array:
                    right_bracket_end = type_name.rfind("]")
                    right_bracket_start = type_name.rfind("[")
                    count = int(type_name[
                                right_bracket_start + 1:right_bracket_end])
                    child_type = self.get_type("{}[0]".format(expression),
                                               level + 1)
                    type = ArrayType(count, child_type, *args)
                elif type_category == TypeCategory.Vector:
                    child_type = self.debugger.communicator.send(
                        "python print(gdb.lookup_type(\"{}\")"
                        ".template_argument(0))".format(type_name))
                    child_type = self.get_type(" ".join(child_type.cli_data),
                                               level + 1)
                    type = ArrayType(0, child_type, *args)
                else:
                    type = Type(*args)
            except:
                Logger.debug(traceback.format_exc())
                return None

            return type
        else:
            return None

    def get_variable(self, expression, level=0):
        """
        Returns a variable for the given expression-
        @type expression: str
        @type level: int
        @rtype: debugee.Variable
        """
        if level > VariableManager.RECURSION_LIMIT:
            return None

        type = self.get_type(expression)
        output = self.debugger.communicator.send("p {0}".format(expression))

        if output and type:
            try:
                data = self.parser.parse_print_expression(output.cli_data)
            except:
                Logger.debug(traceback.format_exc())
                return None

            address = None
            address_output = self.debugger.communicator.send(
                "p &{0}".format(expression))

            try:
                if address_output:
                    address = self._parse_address(address_output.cli_data)
            except:
                Logger.debug(traceback.format_exc())

            name = self._get_name(expression)
            value = None
            variable = None
            children = []

            try:
                if type.type_category == TypeCategory.Builtin:
                    value = data
                    variable = Variable(address, name, value, type, expression)

                elif type.type_category == TypeCategory.Pointer:
                        value = data[data.rfind(" ") + 1:].lower()
                        target_type = self.get_type("*{0}".format(expression))

                        if (target_type and BasicTypeCategory.is_char(
                                target_type.basic_type_category)):
                            type.type_category = TypeCategory.CString
                            value = value[1:-1]  # strip quotes
                        variable = PointerVariable(target_type, address, name,
                                                   value, type, expression)

                elif type.type_category == TypeCategory.Reference:
                    value = data[data.find("@") + 1:data.find(":")]
                    address = self.debugger.communicator.send(
                        "p &(&{0})".format(expression))
                    if address:
                        address = self._parse_address(address.cli_data)
                    else:
                        address = "0x0"

                    target_type = self.get_type("*{0}".format(expression))
                    variable = PointerVariable(target_type, address, name,
                                               value, type, expression)

                elif type.type_category == TypeCategory.Function:
                    # skip function pointer type
                    if data.startswith("({}) ".format(type.name)):
                        data = data[(3 + len(type.name)):]

                    variable = Variable(address, name, data, type, expression)

                elif type.type_category == TypeCategory.String:
                    value = data.strip("\"")
                    variable = Variable(address, name, value, type, expression)

                elif type.type_category in (TypeCategory.Class,
                                            TypeCategory.Struct,
                                            TypeCategory.Union):
                    result = self.debugger.communicator.send(
                        "python print([field.name for field in "
                        "gdb.lookup_type(\"{0}\").fields()])".format(type.name)
                    )

                    if result:
                        members = self.parser.parse_struct_member_names(
                            result.cli_data[0])
                        for member in members:
                            child = self.get_variable("({0}).{1}".format(
                                expression, member), level + 1)
                            if child:
                                children.append(child)
                    variable = Variable(address, name, value, type, expression)

                elif type.type_category == TypeCategory.Vector:
                    length = self.get_variable(
                        "({0}._M_impl._M_finish - {0}._M_impl._M_start)"
                        .format(expression), level + 1)

                    if length:
                        length = int(length.value)

                    data_address = self.debugger.communicator.send(
                        "p {}._M_impl._M_start".format(expression))
                    data_address = " ".join(data_address.cli_data).rstrip()
                    data_address = data_address[data_address.rfind(" ") + 1:]
                    variable = VectorVariable(length, data_address, address,
                                              name, value, type, expression)
                elif type.type_category == TypeCategory.Array:
                    length = type.count
                    data_address = self.get_variable(
                        "&({}[0])".format(expression), level + 1)

                    if data_address:
                        data_address = data_address.value
                    else:
                        data_address = ""

                    variable = VectorVariable(length, data_address, address,
                                              name, value, type, expression)

                elif type.type_category == TypeCategory.Enumeration:
                    variable = Variable(address, name, data, type, expression)
                else:
                    return None

            except:
                Logger.debug(traceback.format_exc())
                return None

            if variable:
                variable.on_value_changed.subscribe(self.update_variable)

                for child in children:
                    if child:
                        variable.add_child(child)

            return variable

        else:
            return None

    def update_variable(self, variable):
        """
        Updates the variable's value in the debugged process.
        @type variable: debugee.Variable
        """
        format = "set variable *{0} = {1}"

        value = variable.value

        try:
            if variable.type.type_category == TypeCategory.String:
                format = "call static_cast<std::string*>({0})->assign(\"{1}\")"
            elif BasicTypeCategory.is_char(variable.type.basic_type_category):
                char_value = variable.value
                if len(char_value) == 1 and not char_value[0].isdigit():
                    value = "'{}'".format(char_value)
        except:
            Logger.debug(traceback.format_exc())
            return False

        result = self.debugger.communicator.send(format.format(
            variable.address, value))

        return result.is_success()

    def get_memory(self, address, count):
        """
        Returns count bytes from the given address.
        @type address: str
        @type count: int
        @rtype: list of int
        """
        command = "x/{0}xb {1}".format(count, address)
        output = self.debugger.communicator.send(command)

        bytes = []
        try:
            for line in output.cli_data:
                start = line.find(":")
                line = line[start + 1:]
                for num in line.split("\\t"):
                    if num:
                        bytes.append(int(num, 16))
        except:
            Logger.debug(traceback.format_exc())

        return bytes

    def get_registers(self):
        """
        Returns the register values as a list of tuples with name and value of
        the given register.
        @rtype: list of register.Register
        """
        try:
            register_names = self.debugger.communicator.send(
                "-data-list-register-names")
            if not register_names:
                return []

            register_names = self.parser.parse(
                register_names.data)["register-names"]

            register_values = self.debugger.communicator.send(
                "-data-list-register-values --skip-unavailable x")
            if not register_values:
                return []

            registers = []
            register_values = self.parser.parse(
                register_values.data)["register-values"]
            for reg in register_values:
                number = int(reg["number"])
                if (number < len(register_names) and
                        len(register_names[number]) > 0):
                    registers.append(Register(str(register_names[number]),
                                              str(reg["value"])))
            return registers
        except:
            Logger.debug(traceback.format_exc())

        return []

    def get_vector_items(self, vector):
        """
        @type vector: debugger.debugee.VectorVariable
        @rtype: list of debugger.debugee.Variable
        """
        items = []
        for i in xrange(vector.start, vector.start + vector.count):
            expression = vector.path
            if vector.type.type_category == TypeCategory.Array:
                expression += "[{}]".format(i)
            elif vector.type.type_category == TypeCategory.Vector:
                expression = "*({}._M_impl._M_start + {})".format(
                    expression, i)
            var = self.get_variable(expression)
            if var:
                items.append(var)

        vector.children = items

        return items

    def _get_name(self, expression):
        """
        Returns name from the given expression.
        @type expression: str
        @rtype: str
        """
        match = re.search("([a-zA-Z_$]+)$", expression)

        if match:
            return match.group(0)
        else:
            return expression

    def _parse_address(self, expression):
        """
        @type expression: str
        @rtype: str | None
        """
        try:
            address = self.parser.parse_print_expression(expression)

            if len(address) > 0 and address[0] == "(":
                return address[address.rfind(" ") + 1:]
            elif address[:2] == "0x":
                return address[:address.find(" ")]
        except:
            Logger.debug(traceback.format_exc())

        return None
Beispiel #4
0
def parser():
    return Parser()
 def __init__(self, debugger):
     super(BreakpointManager, self).__init__(debugger)
     self.parser = Parser()
class BreakpointManager(debugger_api.BreakpointManager):
    def __init__(self, debugger):
        super(BreakpointManager, self).__init__(debugger)
        self.parser = Parser()

    def add_breakpoint(self, location, line):
        """
        Adds a breakpoint, if there is not a breakpoint with the same location
        and line already.
        @type location: str
        @type line: int
        @rtype: boolean
        """
        self.debugger.require_state(DebuggerState.BinaryLoaded)

        if self.find_breakpoint(location, line) is not None:
            return False

        if line is not None:
            location += ":" + str(line)

        success = self.debugger.communicator.send(
            "-break-insert {0}".format(location)).is_success()

        if success:
            self.on_breakpoint_changed.notify(self.find_breakpoint(location,
                                                                   line))

        return success

    def toggle_breakpoint(self, location, line):
        """
        Toggles a breakpoint on the given location and line.
        @type location: str
        @type line: int
        @rtype: boolean
        """
        bp = self.find_breakpoint(location, line)
        if bp:
            return self.remove_breakpoint(location, line)
        else:
            return self.add_breakpoint(location, line)

    def get_breakpoints(self):
        """
        @rtype: list of debugger.Breakpoint
        """
        bps = self.debugger.communicator.send("-break-list")

        if bps:
            try:
                return self.parser.parse_breakpoints(bps.data)
            except:
                return []
        else:
            return []

    def find_breakpoint(self, location, line):
        """
        @type location: str
        @type line: int
        @rtype: debugger.Breakpoint | None
        """
        location = os.path.abspath(location)

        for bp in self.get_breakpoints():
            if bp.location == location and bp.line == line:
                return bp

        return None

    def remove_breakpoint(self, location, line):
        """
        @type location: str
        @type line: int
        @rtype: boolean
        """
        self.debugger.require_state(DebuggerState.BinaryLoaded)

        bp = self.find_breakpoint(location, line)

        if bp:
            success = self.debugger.communicator.send(
                "-break-delete {0}".format(bp.number)).is_success()

            if success:
                self.on_breakpoint_changed.notify(bp)
            return success
        else:
            return False
 def __init__(self, debugger):
     super(BreakpointManager, self).__init__(debugger)
     self.parser = Parser()
class BreakpointManager(debugger_api.BreakpointManager):
    def __init__(self, debugger):
        super(BreakpointManager, self).__init__(debugger)
        self.parser = Parser()

    def add_breakpoint(self, location, line):
        """
        Adds a breakpoint, if there is not a breakpoint with the same location
        and line already.
        @type location: str
        @type line: int
        @rtype: boolean
        """
        self.debugger.require_state(DebuggerState.BinaryLoaded)

        if self.find_breakpoint(location, line) is not None:
            return False

        if line is not None:
            location += ":" + str(line)

        success = self.debugger.communicator.send(
            "-break-insert {0}".format(location)).is_success()

        if success:
            self.on_breakpoint_changed.notify(
                self.find_breakpoint(location, line))

        return success

    def toggle_breakpoint(self, location, line):
        """
        Toggles a breakpoint on the given location and line.
        @type location: str
        @type line: int
        @rtype: boolean
        """
        bp = self.find_breakpoint(location, line)
        if bp:
            return self.remove_breakpoint(location, line)
        else:
            return self.add_breakpoint(location, line)

    def get_breakpoints(self):
        """
        @rtype: list of debugger.Breakpoint
        """
        bps = self.debugger.communicator.send("-break-list")

        if bps:
            try:
                return self.parser.parse_breakpoints(bps.data)
            except:
                return []
        else:
            return []

    def find_breakpoint(self, location, line):
        """
        @type location: str
        @type line: int
        @rtype: debugger.Breakpoint | None
        """
        location = os.path.abspath(location)

        for bp in self.get_breakpoints():
            if bp.location == location and bp.line == line:
                return bp

        return None

    def remove_breakpoint(self, location, line):
        """
        @type location: str
        @type line: int
        @rtype: boolean
        """
        self.debugger.require_state(DebuggerState.BinaryLoaded)

        bp = self.find_breakpoint(location, line)

        if bp:
            success = self.debugger.communicator.send(
                "-break-delete {0}".format(bp.number)).is_success()

            if success:
                self.on_breakpoint_changed.notify(bp)
            return success
        else:
            return False
 def __init__(self, debugger):
     """
     @type debugger: debugger.Debugger
     """
     super(ThreadManager, self).__init__(debugger)
     self.parser = Parser()
class ThreadManager(debugger_api.ThreadManager):
    def __init__(self, debugger):
        """
        @type debugger: debugger.Debugger
        """
        super(ThreadManager, self).__init__(debugger)
        self.parser = Parser()

    def get_current_thread(self):
        """
        @rtype: debugee.Thread
        """
        thread_info = self.get_thread_info()

        if thread_info:
            return thread_info.selected_thread
        else:
            return None

    def get_thread_info(self):
        """
        Returns (active_thread_id, all_threads).
        @rtype: debugee.ThreadInfo | None
        """
        output = self.debugger.communicator.send("-thread-info")

        if output:
            try:
                return self.parser.parse_thread_info(output.data)
            except:
                Logger.debug(traceback.format_exc())

        return None

    def set_thread_by_index(self, thread_id):
        """
        @type thread_id: int
        @rtype: bool
        """
        result = self.debugger.communicator.send(
            "-thread-select {0}".format(thread_id)).is_success()

        if result:
            self.debugger.on_thread_changed.notify(
                self.get_thread_info().selected_thread)
            self.debugger.on_frame_changed.notify(self.get_current_frame())

            util.Logger.debug(
                "Changed to thread with id {0}".format(thread_id))

            return True
        else:
            return False

    def get_current_frame(self, with_variables=False):
        """
        Returns the current stack frame, optionally with it's parameters.
        @type with_variables: bool
        @rtype: debugee.Frame | None
        """
        output = self.debugger.communicator.send("-stack-info-frame")

        if output:
            try:
                frame = self.parser.parse_stack_frame(output.data)

                if with_variables:
                    variables_info = self.parser.parse_frame_variables(
                        self.debugger.communicator.send(
                            "-stack-list-variables --skip-unavailable 0").data)

                    for variable in variables_info:
                        try:
                            variable = self.debugger.variable_manager.\
                                get_variable(variable["name"])
                            if variable:
                                frame.variables.append(variable)
                        except:
                            Logger.debug(
                                "Coult not load variable {}".format(variable))

                return frame
            except:
                Logger.debug(traceback.format_exc())

        return None

    def get_frames(self):
        """
        @rtype: list of debugee.Frame
        """
        output = self.debugger.communicator.send("-stack-list-frames")

        if output:
            try:
                return self.parser.parse_stack_frames(output.data)
            except:
                Logger.debug(traceback.format_exc())

        return []

    def get_frames_with_variables(self):
        """
        Returns all stack frames with all their local variables and arguments.
        @rtype: list of debugger.debugee.Frame
        """
        current_frame = self.get_current_frame(False)

        if not current_frame:
            return []

        frames = []
        try:
            for i, fr in enumerate(self.get_frames()):
                self.change_frame(i, False)
                frames.append(self.get_current_frame(True))
        except:
            Logger.debug(traceback.format_exc())
        finally:
            self.change_frame(current_frame.level, False)

        return frames

    def change_frame(self, frame_index, notify=True):
        """
        @type frame_index: int
        @type notify: bool
        @rtype: bool
        """
        if frame_index >= len(self.get_frames()):
            return False

        result = self.debugger.communicator.send(
            "-stack-select-frame {0}".format(frame_index)).is_success()

        if result:
            if notify:
                self.debugger.on_frame_changed.notify(self.get_current_frame())

                util.Logger.debug(
                    "Changed to frame with id {0}".format(frame_index))

            return True
        else:
            return False
 def __init__(self, debugger):
     """
     @type debugger: debugger.Debugger
     """
     super(ThreadManager, self).__init__(debugger)
     self.parser = Parser()
class ThreadManager(debugger_api.ThreadManager):
    def __init__(self, debugger):
        """
        @type debugger: debugger.Debugger
        """
        super(ThreadManager, self).__init__(debugger)
        self.parser = Parser()

    def get_current_thread(self):
        """
        @rtype: debugee.Thread
        """
        thread_info = self.get_thread_info()

        if thread_info:
            return thread_info.selected_thread
        else:
            return None

    def get_thread_info(self):
        """
        Returns (active_thread_id, all_threads).
        @rtype: debugee.ThreadInfo | None
        """
        output = self.debugger.communicator.send("-thread-info")

        if output:
            try:
                return self.parser.parse_thread_info(output.data)
            except:
                Logger.debug(traceback.format_exc())

        return None

    def set_thread_by_index(self, thread_id):
        """
        @type thread_id: int
        @rtype: bool
        """
        result = self.debugger.communicator.send(
            "-thread-select {0}".format(thread_id)).is_success()

        if result:
            self.debugger.on_thread_changed.notify(
                self.get_thread_info().selected_thread)
            self.debugger.on_frame_changed.notify(self.get_current_frame())

            util.Logger.debug("Changed to thread with id {0}".format(
                thread_id))

            return True
        else:
            return False

    def get_current_frame(self, with_variables=False):
        """
        Returns the current stack frame, optionally with it's parameters.
        @type with_variables: bool
        @rtype: debugee.Frame | None
        """
        output = self.debugger.communicator.send("-stack-info-frame")

        if output:
            try:
                frame = self.parser.parse_stack_frame(output.data)

                if with_variables:
                    variables_info = self.parser.parse_frame_variables(
                        self.debugger.communicator.send(
                            "-stack-list-variables --skip-unavailable 0").data
                    )

                    for variable in variables_info:
                        try:
                            variable = self.debugger.variable_manager.\
                                get_variable(variable["name"])
                            if variable:
                                frame.variables.append(variable)
                        except:
                            Logger.debug("Coult not load variable {}"
                                         .format(variable))

                return frame
            except:
                Logger.debug(traceback.format_exc())

        return None

    def get_frames(self):
        """
        @rtype: list of debugee.Frame
        """
        output = self.debugger.communicator.send("-stack-list-frames")

        if output:
            try:
                return self.parser.parse_stack_frames(output.data)
            except:
                Logger.debug(traceback.format_exc())

        return []

    def get_frames_with_variables(self):
        """
        Returns all stack frames with all their local variables and arguments.
        @rtype: list of debugger.debugee.Frame
        """
        current_frame = self.get_current_frame(False)

        if not current_frame:
            return []

        frames = []
        try:
            for i, fr in enumerate(self.get_frames()):
                self.change_frame(i, False)
                frames.append(self.get_current_frame(True))
        except:
            Logger.debug(traceback.format_exc())
        finally:
            self.change_frame(current_frame.level, False)

        return frames

    def change_frame(self, frame_index, notify=True):
        """
        @type frame_index: int
        @type notify: bool
        @rtype: bool
        """
        if frame_index >= len(self.get_frames()):
            return False

        result = self.debugger.communicator.send(
            "-stack-select-frame {0}".format(frame_index)).is_success()

        if result:
            if notify:
                self.debugger.on_frame_changed.notify(self.get_current_frame())

                util.Logger.debug("Changed to frame with id {0}".format(
                    frame_index))

            return True
        else:
            return False
Beispiel #13
0
class FileManager(debugger_api.FileManager):
    def __init__(self, debugger):
        """
        @type debugger: debugger.Debugger
        """
        super(FileManager, self).__init__(debugger)
        self.parser = Parser()

    def _get_current_line(self):
        output = self.debugger.communicator.send("info line")

        if output:
            try:
                cli_data = output.cli_data[0][5:]
                match = re.match("(\d+)", cli_data)

                return int(match.group(0))
            except:
                Logger.debug(traceback.format_exc())

        return None

    def _get_current_file(self):
        output = self.debugger.communicator.send("info source")

        if output:
            try:
                cli_data = output.cli_data[2]
                return cli_data[11:]
            except:
                Logger.debug(traceback.format_exc())

        return None

    def _get_single_capture(self, pattern, input):
        match = re.search(pattern, input)
        if not match:
            return None
        else:
            return match.group(1)

    def get_main_source_file(self):
        output = self.debugger.communicator.send("info sources")

        if output:
            try:
                files = output.cli_data[1]
                return files.split(",")[0]
            except:
                Logger.debug(traceback.format_exc())

        return None

    def get_current_location(self):
        """
        Returns the current file and line of the debugged process.
        @rtype: tuple of basestring, int | None
        """
        frame = self.debugger.thread_manager.get_current_frame(False)

        if not frame:
            return None

        line = frame.line
        location = frame.file

        Logger.debug("Getting current location: ({0}, {1})".format(
            location, line))

        return (location, line)

    def get_line_address(self, filename, line):
        """
        Returns the starting address and ending address in hexadecimal format
        of code at the specified line in the given file.
        Returns None if no code is at the given location.
        @type filename: str
        @type line: int
        @rtype: tuple of int | None
        """
        command = "info line {0}:{1}".format(filename, line)
        result = self.debugger.communicator.send(command)

        if result:
            data = result.cli_data[0]
            if "address" not in data or "contains no code" in data:
                return None

            start_address = self._get_single_capture(
                "starts at address ([^ ]*)", data)
            end_address = self._get_single_capture("ends at ([^ ]*)", data)

            if start_address and end_address:
                return (start_address, end_address)

        return None

    def disassemble(self, filename, line):
        """
        Returns disassembled code for the given location.
        Returns None if no code was found,
        @type filename: str
        @type line: int
        @rtype: str | None
        """
        command = "-data-disassemble -f {0} -l {1} -n 10 -- 1".format(
            filename, line)
        result = self.debugger.communicator.send(command)
        if result:
            try:
                disassembled = self.parser.parse_disassembly(result.data)
                if disassembled:
                    return disassembled
            except:
                Logger.debug(traceback.format_exc())

        return None

    def disassemble_raw(self, filename, line):
        """
        Disassembles the given line in a raw form (returns a string with the
        line and all assembly instructions for it).
        @type filename: str
        @type line: int
        @rtype: str | None
        """
        address = self.get_line_address(filename, line)

        if not address:
            return None

        command = "disas /m {0}, {1}".format(address[0], address[1])
        result = self.debugger.communicator.send(command)
        if result:
            try:
                return "\n".join([
                    row.replace("\\t", "\t") for row in result.cli_data[1:-1]
                ])
            except:
                Logger.debug(traceback.format_exc())

        return None