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_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_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 _set_debugger_location(self): location = self.debugger.file_manager.get_current_location() Logger.debug("Stop at {0}".format(location)) if location and location[0]: run_on_gui(self.set_exec_line, location[0], location[1])
def _emit_buffer(self): if not self.debugger.io_manager.stdin: return input_buffer = self._collect_buffer() try: self.debugger.io_manager.stdin.write(input_buffer) except: Logger.debug(traceback.format_exc())
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_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_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 handle_drag_end(self, target): """ @type target: Drawable """ if isinstance(target, VariableContainer): variable = target.variable if variable.type.name != self.variable.target_type.name: Logger.debug( "Assigned {} pointer to variable of type {}".format( self.variable.target_type.name, variable.type.name)) if variable.address: self.variable.value = variable.address self.invalidate()
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_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 _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
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 _read_thread(self, alloc_path): """ @type alloc_path: str """ try: with os.fdopen(os.open(alloc_path, os.O_NONBLOCK | os.O_RDONLY), "r", 1) as alloc_file: self.alloc_file = alloc_file while not self.stop_flag.is_set(): if len(select.select([alloc_file], [], [], 0.1)[0]) != 0: line = alloc_file.readline()[:-1] if line: self._handle_message(line) except: Logger.debug(traceback.format_exc())
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 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 _handle_message(self, message): """ @type message: str """ util.Logger.debug("HEAP: {}".format(message)) msg_parts = message.split(" ") action = msg_parts[0] args = msg_parts[1:] try: if action in ("malloc", "calloc"): self._handle_malloc(*args) elif action == "realloc": self._handle_realloc(*args) elif action == "free": self._handle_free(*args) else: Logger.debug("Unknown allocation action: {}".format(action)) except: Logger.debug(traceback.format_exc())
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 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 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
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 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