class ModulesPanel(QSplitter): """ ModulesPanel Signals: onAddBreakpoint([ptr, funcname]) - MenuItem AddBreakpoint onDumpBinary([ptr, size#int]) - MenuItem DumpBinary onModuleSelected([ptr, size#int]) - ModuleDoubleClicked onModuleFuncSelected(ptr) - FunctionDoubleClicked """ # pylint: disable=too-many-instance-attributes onAddBreakpoint = pyqtSignal(list, name='onAddBreakpoint') onDumpBinary = pyqtSignal(list, name='onDumpBinary') onModuleSelected = pyqtSignal(list, name='onModuleSelected') onModuleFuncSelected = pyqtSignal(str, name='onModuleFuncSelected') def __init__(self, parent=None): # pylint: disable=too-many-statements super(ModulesPanel, self).__init__(parent) self._app_window = parent if self._app_window.dwarf is None: print('ModulesPanel created before Dwarf exists') return self._app_window.dwarf.onSetModules.connect(self.set_modules) self._app_window.dwarf.onModuleLoaded.connect(self.on_module_loaded) self._uppercase_hex = True self._sized = False self.setContentsMargins(0, 0, 0, 0) # setup models self.modules_list = None self.modules_model = QStandardItemModel(0, 4, self) self.modules_model.setHeaderData(0, Qt.Horizontal, 'Name') self.modules_model.setHeaderData(1, Qt.Horizontal, 'Base') self.modules_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self.modules_model.setHeaderData(2, Qt.Horizontal, 'Size') self.modules_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self.modules_model.setHeaderData(3, Qt.Horizontal, 'Path') self.imports_list = None self.imports_model = QStandardItemModel(0, 4, self) self.imports_model.setHeaderData(0, Qt.Horizontal, 'Import') self.imports_model.setHeaderData(1, Qt.Horizontal, 'Address') self.imports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self.imports_model.setHeaderData(2, Qt.Horizontal, 'Module') self.imports_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self.imports_model.setHeaderData(3, Qt.Horizontal, 'Type') self.exports_list = None self.exports_model = QStandardItemModel(0, 3, self) self.exports_model.setHeaderData(0, Qt.Horizontal, 'Export') self.exports_model.setHeaderData(1, Qt.Horizontal, 'Address') self.exports_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self.exports_model.setHeaderData(2, Qt.Horizontal, 'Type') self.symbols_list = None self.symbols_model = QStandardItemModel(0, 3, self) self.symbols_model.setHeaderData(0, Qt.Horizontal, 'Symbol') self.symbols_model.setHeaderData(1, Qt.Horizontal, 'Address') self.symbols_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self.symbols_model.setHeaderData(2, Qt.Horizontal, 'Type') # setup ui self.modules_list = DwarfListView() self.modules_list.setContextMenuPolicy(Qt.CustomContextMenu) self.modules_list.customContextMenuRequested.connect( self._on_modules_contextmenu) self.modules_list.setEditTriggers(self.modules_list.NoEditTriggers) self.modules_list.clicked.connect(self._module_clicked) self.modules_list.doubleClicked.connect(self._module_dblclicked) self.modules_list.setModel(self.modules_model) self.modules_list.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.modules_list.header().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.modules_list.header().setSectionResizeMode( 2, QHeaderView.ResizeToContents) self.modules_list.selectionModel().selectionChanged.connect( self._module_clicked) self.addWidget(self.modules_list) v_splitter = QSplitter(Qt.Vertical) self.imports_list = DwarfListView() self.imports_list.setContextMenuPolicy(Qt.CustomContextMenu) self.imports_list.customContextMenuRequested.connect( self._on_imports_contextmenu) self.imports_list.setEditTriggers(self.modules_list.NoEditTriggers) self.imports_list.doubleClicked.connect(self._import_dblclicked) self.imports_list.setModel(self.imports_model) self.imports_list.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.imports_list.header().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.imports_list.header().setSectionResizeMode( 2, QHeaderView.ResizeToContents) self.imports_list.setVisible(False) self.exports_list = DwarfListView() self.exports_list.setContextMenuPolicy(Qt.CustomContextMenu) self.exports_list.customContextMenuRequested.connect( self._on_exports_contextmenu) self.exports_list.setEditTriggers(self.modules_list.NoEditTriggers) self.exports_list.doubleClicked.connect(self._export_dblclicked) self.exports_list.setModel(self.exports_model) self.exports_list.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.exports_list.header().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.exports_list.header().setSectionResizeMode( 2, QHeaderView.ResizeToContents) self.exports_list.setVisible(False) self.symbols_list = DwarfListView() self.symbols_list.setContextMenuPolicy(Qt.CustomContextMenu) self.symbols_list.doubleClicked.connect(self._symbol_dblclicked) self.symbols_list.setModel(self.symbols_model) self.symbols_list.header().setSectionResizeMode( 0, QHeaderView.ResizeToContents) self.symbols_list.header().setSectionResizeMode( 1, QHeaderView.ResizeToContents) self.symbols_list.header().setSectionResizeMode( 2, QHeaderView.ResizeToContents) self.symbols_list.setVisible(False) v_splitter.addWidget(self.imports_list) v_splitter.addWidget(self.exports_list) v_splitter.addWidget(self.symbols_list) v_splitter.setSizes([100, 100, 100]) self.addWidget(v_splitter) self.update_modules() # ************************************************************************ # **************************** Properties ******************************** # ************************************************************************ @property def uppercase_hex(self): """ HexDisplayStyle """ return self._uppercase_hex @uppercase_hex.setter def uppercase_hex(self, value): """ HexDisplayStyle """ if isinstance(value, bool): self._uppercase_hex = value elif isinstance(value, str): self._uppercase_hex = (value == 'upper') # ************************************************************************ # **************************** Functions ********************************* # ************************************************************************ def set_modules(self, modules): """ Fills the ModulesList with data """ if self.modules_list is None: return self.modules_list.clear() for module in modules: self.add_module(module) self.modules_list.resizeColumnToContents(0) self.modules_list.resizeColumnToContents(1) self.modules_list.resizeColumnToContents(2) self.modules_list.resizeColumnToContents(3) def on_module_loaded(self, data): module = data[0] self.add_module(module) def add_module(self, module): name = QStandardItem() name.setTextAlignment(Qt.AlignLeft) if 'name' in module: name.setText(module['name']) base = QStandardItem() base.setTextAlignment(Qt.AlignCenter) str_fmt = '0x{0:X}' if not self.uppercase_hex: str_fmt = '0x{0:x}' if 'base' in module: base.setText(str_fmt.format(int(module['base'], 16))) size = QStandardItem() size.setTextAlignment(Qt.AlignRight) if 'size' in module: size.setText("{0:,d}".format(int(module['size']))) path = QStandardItem() path.setTextAlignment(Qt.AlignLeft) if 'path' in module: path.setText(module['path']) self.modules_model.appendRow([name, base, size, path]) module_info = ModuleInfo(module) if 'exports' in module and module['exports']: module_info.apply_exports(module['exports']) if 'imports' in module and module['imports']: module_info.apply_imports(module['imports']) if 'symbols' in module and module['symbols']: module_info.apply_symbols(module['symbols']) module_info._updated_details = True def update_modules(self): """ DwarfApiCall updateModules """ return self._app_window.dwarf.dwarf_api('updateModules') def set_imports(self, imports): """ Fills the ImportsList with data """ if self.imports_list is None: return self.imports_list.clear() for import_ in imports: name = QStandardItem() name.setTextAlignment(Qt.AlignLeft) if 'name' in import_: name.setText(import_['name']) address = QStandardItem() address.setTextAlignment(Qt.AlignCenter) str_fmt = '0x{0:X}' if not self.uppercase_hex: str_fmt = '0x{0:x}' if 'address' in import_: address.setText(str_fmt.format(int(import_['address'], 16))) module = QStandardItem() if 'module' in import_: module.setTextAlignment(Qt.AlignLeft) module.setText(import_['module']) type_ = QStandardItem() if 'type' in import_: type_.setTextAlignment(Qt.AlignLeft) type_.setText(import_['type']) self.imports_model.appendRow([name, address, module, type_]) def set_exports(self, exports): """ Fills the ExportsList with data """ if self.exports_list is None: return self.exports_list.clear() for export in exports: name = QStandardItem() name.setTextAlignment(Qt.AlignLeft) if 'name' in export: name.setText(export['name']) address = QStandardItem() address.setTextAlignment(Qt.AlignCenter) str_fmt = '0x{0:X}' if not self.uppercase_hex: str_fmt = '0x{0:x}' if 'address' in export: address.setText(str_fmt.format(int(export['address'], 16))) type_ = QStandardItem() type_.setTextAlignment(Qt.AlignLeft) if 'type' in export: type_.setText(export['type']) self.exports_model.appendRow([name, address, type_]) def set_symbols(self, symbols): """ Fills the SymbolsList with data """ if self.symbols_list is None: return self.symbols_list.clear() for symbol in symbols: name = QStandardItem() name.setTextAlignment(Qt.AlignLeft) if 'name' in symbol: name.setText(symbol['name']) address = QStandardItem() address.setTextAlignment(Qt.AlignCenter) str_fmt = '0x{0:X}' if not self.uppercase_hex: str_fmt = '0x{0:x}' if 'address' in symbol: address.setText(str_fmt.format(int(symbol['address'], 16))) type_ = QStandardItem() type_.setTextAlignment(Qt.AlignLeft) if 'type' in symbol: type_.setText(symbol['type']) self.symbols_model.appendRow([name, address, type_]) # ************************************************************************ # **************************** Handlers ********************************** # ************************************************************************ def _module_clicked(self): """ Module Clicked updates imports/exports/symbols """ if not self.modules_list.hasFocus(): return module_index = self.modules_list.selectionModel().currentIndex().row() module_name = self.modules_model.item(module_index, 0) if module_name is None: return module_name = module_name.text() module_address = self.modules_model.item(module_index, 1).text() module_info = self._app_window.dwarf.database.get_module_info(module_address) if module_info is not None: if not module_info.have_details: module_info = ModuleInfo.build_module_info(self._app_window.dwarf, module_name, fill_ied=True) else: module_info = ModuleInfo.build_module_info(self._app_window.dwarf, module_name, fill_ied=True) if module_info is not None: self.update_module_ui(module_info) if not self._sized: self.setSizes([100, 100]) self._sized = True def update_module_ui(self, module_info): if module_info.imports: self.set_imports(module_info.imports) self.imports_list.setVisible(True) self.imports_list.resizeColumnToContents(0) self.imports_list.resizeColumnToContents(1) self.imports_list.resizeColumnToContents(2) else: self.imports_list.setVisible(False) if module_info.exports: self.set_exports(module_info.exports) self.exports_list.setVisible(True) self.exports_list.resizeColumnToContents(0) self.exports_list.resizeColumnToContents(1) else: self.exports_list.setVisible(False) if module_info.symbols: self.set_symbols(module_info.symbols) self.symbols_list.setVisible(True) self.symbols_list.resizeColumnToContents(0) self.symbols_list.resizeColumnToContents(1) else: self.symbols_list.setVisible(False) def _module_dblclicked(self): """ Module DoubleClicked """ module_index = self.modules_list.selectionModel().currentIndex().row() base = self.modules_model.item(module_index, 1).text() size = self.modules_model.item(module_index, 2).text().replace(',', '') self.onModuleSelected.emit([base, size]) def _import_dblclicked(self): """ ImportFunction DoubleClicked """ index = self.imports_list.selectionModel().currentIndex().row() addr = self.imports_model.item(index, 1).text() self.onModuleFuncSelected.emit(addr) def _export_dblclicked(self): """ ExportFunction DoubleClicked """ index = self.exports_list.selectionModel().currentIndex().row() addr = self.exports_model.item(index, 1).text() self.onModuleFuncSelected.emit(addr) def _symbol_dblclicked(self): """ Symbol DoubleClicked """ index = self.symbols_list.selectionModel().currentIndex().row() addr = self.symbols_model.item(index, 1).text() self.onModuleFuncSelected.emit(addr) def _on_modules_contextmenu(self, pos): """ Modules ContextMenu """ index = self.modules_list.indexAt(pos).row() glbl_pt = self.modules_list.mapToGlobal(pos) context_menu = QMenu(self) if index != -1: context_menu.addAction( 'Dump Binary', lambda: self._on_dumpmodule( self.modules_model.item(index, 1).text(), self.modules_model.item(index, 2).text())) context_menu.addSeparator() context_menu.addAction( 'Copy address', lambda: utils.copy_hex_to_clipboard( self.modules_model.item(index, 1).text())) context_menu.addAction( 'Copy Name', lambda: utils.copy_str_to_clipboard( self.modules_model.item(index, 0).text())) context_menu.addAction( 'Copy Path', lambda: utils.copy_str_to_clipboard( self.modules_model.item(index, 3).text())) context_menu.addSeparator() file_path = self.modules_model.item(index, 3).text() if self._app_window.dwarf._platform == 'linux': context_menu.addAction( 'Show ELF Info', lambda: self._on_parse_elf(file_path)) context_menu.addSeparator() # elif file_path and (file_path.endswith('.dll') or file_path.endswith('.exe')): # context_menu.addAction('Show PE Info', lambda: self._on_parse_pe(file_path)) # context_menu.addSeparator() if self.modules_list.search_enabled: context_menu.addSeparator() context_menu.addAction( 'Search', self.modules_list._on_cm_search) context_menu.addSeparator() context_menu.addAction('Refresh', self.update_modules) context_menu.exec_(glbl_pt) def _on_imports_contextmenu(self, pos): """ ImportList ContextMenu """ index = self.imports_list.indexAt(pos).row() if index != -1: context_menu = QMenu(self) func_name = self.imports_model.item(index, 0).text() addr = self.imports_model.item(index, 1).text() context_menu.addAction( 'Add Breakpoint', lambda: self._add_breakpoint(addr, func_name)) context_menu.addSeparator() context_menu.addAction( 'Copy address', lambda: utils.copy_hex_to_clipboard( self.imports_model.item(index, 1).text())) context_menu.addSeparator() context_menu.addAction( 'Copy FunctionName', lambda: utils.copy_str_to_clipboard( func_name)) context_menu.addAction( 'Copy ModuleName', lambda: utils.copy_str_to_clipboard( self.imports_model.item(index, 2).text())) if self.imports_list.search_enabled: context_menu.addSeparator() context_menu.addAction( 'Search', self.imports_list._on_cm_search) # show context menu glbl_pt = self.imports_list.mapToGlobal(pos) context_menu.exec_(glbl_pt) def _on_exports_contextmenu(self, pos): """ ExportsList ContextMenu """ index = self.exports_list.indexAt(pos).row() if index != -1: context_menu = QMenu(self) func_name = self.exports_model.item(index, 0).text() addr = self.exports_model.item(index, 1).text() context_menu.addAction( 'Add Breakpoint', lambda: self._add_breakpoint(addr, func_name)) context_menu.addSeparator() context_menu.addAction( 'Copy address', lambda: utils.copy_hex_to_clipboard( self.exports_model.item(index, 1).text())) context_menu.addSeparator() context_menu.addAction( 'Copy FunctionName', lambda: utils.copy_str_to_clipboard( func_name)) if self.exports_list.search_enabled: context_menu.addSeparator() context_menu.addAction( 'Search', self.exports_list._on_cm_search) # show contextmenu glbl_pt = self.exports_list.mapToGlobal(pos) context_menu.exec_(glbl_pt) def _on_dumpmodule(self, ptr, size): """ MenuItem DumpBinary """ if isinstance(ptr, int): str_fmt = '0x{0:X}' if not self.uppercase_hex: str_fmt = '0x{0:x}' ptr = str_fmt.format(ptr) size = size.replace(',', '') self.onDumpBinary.emit([ptr, size]) def _add_breakpoint(self, ptr, name=None): """ MenuItem AddBreakpoint """ if name is None: name = ptr if isinstance(ptr, str): if ptr.startswith('0x') or ptr.startswith('#'): self.onAddBreakpoint.emit([ptr, name]) elif isinstance(ptr, int): str_fmt = '0x{0:x}' self.onAddBreakpoint.emit(str_fmt.format([ptr, name])) def _on_parse_elf(self, elf_path): from dwarf_debugger.ui.dialogs.elf_info_dlg import ElfInfo parsed_infos = self._app_window.dwarf.dwarf_api('parseElf', elf_path) if parsed_infos: elf_dlg = ElfInfo(self._app_window, elf_path) elf_dlg.onShowMemoryRequest.connect(self.onModuleFuncSelected) elf_dlg.set_parsed_data(parsed_infos) elf_dlg.show()
class SearchPanel(QWidget): """ SearchPanel """ def __init__(self, parent=None, show_progress_dlg=False): super(SearchPanel, self).__init__(parent=parent) self._app_window = parent if self._app_window.dwarf is None: print('SearchPanel created before Dwarf exists') return self._app_window.dwarf.onMemoryScanResult.connect( self._on_search_result) self._app_window.dwarf.onSearchableRanges.connect(self._on_setranges) self._ranges_model = None self._result_model = None self._blocking_search = show_progress_dlg self.progress = None self._pattern_length = 0 self._search_results = [] self.setContentsMargins(0, 0, 0, 0) main_wrap = QVBoxLayout() main_wrap.setContentsMargins(1, 1, 1, 1) wrapping_wdgt = QWidget() wrapping_wdgt.setContentsMargins(10, 10, 10, 10) v_box = QVBoxLayout(wrapping_wdgt) v_box.setContentsMargins(0, 0, 0, 0) self.input = QLineEdit() self.input.setPlaceholderText( 'search for a sequence of bytes in hex format: deadbeef123456aabbccddeeff...' ) v_box.addWidget(self.input) self.check_all_btn = QPushButton('check all') self.check_all_btn.clicked.connect(self._on_click_check_all) self.uncheck_all_btn = QPushButton('uncheck all') self.uncheck_all_btn.clicked.connect(self._on_click_uncheck_all) self.search_btn = QPushButton('search') self.search_btn.clicked.connect(self._on_click_search) h_box = QHBoxLayout() h_box.addWidget(self.check_all_btn) h_box.addWidget(self.uncheck_all_btn) h_box.addWidget(self.search_btn) v_box.addLayout(h_box) main_wrap.addWidget(wrapping_wdgt) self.ranges = DwarfListView(self) self.ranges.clicked.connect(self._on_show_results) self.results = DwarfListView(self) self.results.setVisible(False) h_box = QHBoxLayout() h_box.setContentsMargins(0, 0, 0, 0) h_box.addWidget(self.ranges) h_box.addWidget(self.results) main_wrap.addLayout(h_box) main_wrap.setSpacing(0) self.setLayout(main_wrap) self._setup_models() self._app_window.dwarf.dwarf_api('updateSearchableRanges') # ************************************************************************ # **************************** Functions ********************************* # ************************************************************************ def _setup_models(self): self._ranges_model = QStandardItemModel(0, 7) # just replicate ranges panel model self._ranges_model.setHeaderData( 0, Qt.Horizontal, 'x' ) # TODO: replace with checkbox in header - remove checkall btns self._ranges_model.setHeaderData(0, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._ranges_model.setHeaderData(1, Qt.Horizontal, 'Address') self._ranges_model.setHeaderData(1, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._ranges_model.setHeaderData(2, Qt.Horizontal, 'Size') self._ranges_model.setHeaderData(2, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._ranges_model.setHeaderData(3, Qt.Horizontal, 'Protection') self._ranges_model.setHeaderData(3, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._ranges_model.setHeaderData(4, Qt.Horizontal, 'FileOffset') self._ranges_model.setHeaderData(4, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._ranges_model.setHeaderData(5, Qt.Horizontal, 'FileSize') self._ranges_model.setHeaderData(5, Qt.Horizontal, Qt.AlignCenter, Qt.TextAlignmentRole) self._ranges_model.setHeaderData(6, Qt.Horizontal, 'FilePath') self.ranges.setModel(self._ranges_model) self.ranges.header().setSectionResizeMode(0, QHeaderView.ResizeToContents) self.ranges.header().setSectionResizeMode(1, QHeaderView.ResizeToContents) self.ranges.header().setSectionResizeMode(2, QHeaderView.ResizeToContents) self.ranges.header().setSectionResizeMode(3, QHeaderView.ResizeToContents) self.ranges.header().setSectionResizeMode(4, QHeaderView.ResizeToContents) self.ranges.header().setSectionResizeMode(5, QHeaderView.ResizeToContents) self.ranges.doubleClicked.connect(self._on_range_dblclick) # setup results model self._result_model = QStandardItemModel(0, 1) self._result_model.setHeaderData(0, Qt.Horizontal, 'Address') self.results.setModel(self._result_model) self.results.doubleClicked.connect(self._on_double_clicked) def _on_setranges(self, ranges): """ Fills Rangelist with Data """ if self._ranges_model.rowCount(): return self.ranges.header().setSectionResizeMode(0, QHeaderView.Fixed) if isinstance(ranges, list): self._ranges_model.removeRows(0, self._ranges_model.rowCount()) for range_entry in ranges: if 'protection' in range_entry and isinstance( range_entry['protection'], str): if 'r' not in range_entry['protection']: # skip not readable range continue else: continue # create items to add str_frmt = '' if self.ranges._uppercase_hex: str_frmt = '0x{0:X}' else: str_frmt = '0x{0:x}' addr = QStandardItem() addr.setTextAlignment(Qt.AlignCenter) addr.setText(str_frmt.format(int(range_entry['base'], 16))) size = QStandardItem() size.setTextAlignment(Qt.AlignRight) size.setText("{0:,d}".format(int(range_entry['size']))) protection = QStandardItem() protection.setTextAlignment(Qt.AlignCenter) protection.setText(range_entry['protection']) file_path = None file_addr = None file_size = None if len(range_entry) > 3: if range_entry['file']['path']: file_path = QStandardItem() file_path.setText(range_entry['file']['path']) if range_entry['file']['offset']: file_addr = QStandardItem() file_addr.setTextAlignment(Qt.AlignCenter) file_addr.setText( str_frmt.format(range_entry['file']['offset'])) if range_entry['file']['size']: file_size = QStandardItem() file_size.setTextAlignment(Qt.AlignRight) file_size.setText("{0:,d}".format( int(range_entry['file']['size']))) checkbox = QStandardItem() checkbox.setCheckable(True) self._ranges_model.appendRow([ checkbox, addr, size, protection, file_addr, file_size, file_path ]) # ************************************************************************ # **************************** Handlers ********************************** # ************************************************************************ def _on_range_dblclick(self, model_index): item = self._ranges_model.itemFromIndex(model_index) if item: if self._ranges_model.item(model_index.row(), 0).checkState() != Qt.Checked: self._ranges_model.item(model_index.row(), 0).setCheckState(Qt.Checked) else: self._ranges_model.item(model_index.row(), 0).setCheckState(Qt.Unchecked) def _on_click_check_all(self): for i in range(self._ranges_model.rowCount()): self._ranges_model.item(i, 0).setCheckState(Qt.Checked) def _on_click_uncheck_all(self): for i in range(self._ranges_model.rowCount()): self._ranges_model.item(i, 0).setCheckState(Qt.Unchecked) def _on_double_clicked(self, model_index): item = self._result_model.itemFromIndex(model_index) if item: self._app_window.jump_to_address( self._result_model.item(model_index.row(), 0).text()) def _on_click_search(self): pattern = self.input.text() if pattern == '': return 1 # check if we already provide a hex string as input try: test = pattern.replace(' ', '') int(test, 16) pattern = test except ValueError: # search for string pattern = binascii.hexlify(pattern.encode('utf8')).decode('utf8') ranges = [] self._search_results = [] for i in range(self._ranges_model.rowCount()): item = self._ranges_model.item(i, 0) if item.checkState() == Qt.Checked: addr = self._ranges_model.item(i, 1) size = self._ranges_model.item(i, 2) ranges.append([addr.text(), size.text()]) if len(ranges) == 0: return 1 status_message = 'searching...' if self._blocking_search: self.progress = utils.progress_dialog(status_message) self.progress.forceShow() self._app_window.show_progress(status_message) self.input.setEnabled(False) self.search_btn.setEnabled(False) self.check_all_btn.setEnabled(False) self.uncheck_all_btn.setEnabled(False) self._pattern_length = len(pattern) * .5 search_thread = SearchThread(self._app_window.dwarf, self) search_thread.onCmdCompleted.connect(self._on_search_complete) search_thread.onError.connect(self._on_search_error) search_thread.pattern = pattern search_thread.ranges = ranges search_thread.start() def _on_search_result(self, data): self._search_results.append(data) def _on_search_complete(self): self.input.setEnabled(True) self.search_btn.setEnabled(True) self.check_all_btn.setEnabled(True) self.uncheck_all_btn.setEnabled(True) self._app_window.hide_progress() if self._blocking_search: self.progress.cancel() self._ranges_model.removeColumns(4, 3) self._ranges_model.setHeaderData(3, Qt.Horizontal, 'Search Results') self._ranges_model.setHeaderData(3, Qt.Horizontal, None, Qt.TextAlignmentRole) results_count = 0 is_selected = False for i in range(self._ranges_model.rowCount()): item = self._ranges_model.item(i, 0) if item.checkState() == Qt.Checked: item.setCheckState(Qt.Unchecked) if not is_selected: is_selected = True self.ranges.setCurrentIndex(self._ranges_model.index(i, 0)) else: self._search_results.insert(i, None) self._ranges_model.item(i, 3).setText('') self._ranges_model.item(i, 3).setTextAlignment(Qt.AlignLeft) continue if len(self._search_results[i]): results_count += len(self._search_results[i]) self._ranges_model.item(i, 3).setText('Matches: {0}'.format( len(self._search_results[i]))) self._ranges_model.item(i, 3).setTextAlignment(Qt.AlignLeft) else: self._ranges_model.item(i, 3).setText('') self._ranges_model.item(i, 3).setTextAlignment(Qt.AlignLeft) self._app_window.set_status_text( 'Search complete: {0} matches'.format(results_count)) if results_count: for i in self._search_results: if i and len(i): self.results.setVisible(True) for result in i: self._result_model.appendRow( QStandardItem(result['address'])) break def _on_search_error(self, msg): utils.show_message_box(msg) def _on_show_results(self): if self._search_results: self.results.clear() if self._app_window.debug_panel.memory_panel: self._app_window.debug_panel.memory_panel.remove_highlights('search') selected_index = self.ranges.selectionModel().currentIndex().row() if selected_index is not None: item_txt = self._ranges_model.item(selected_index, 3).text() if item_txt == '': return for result in self._search_results[selected_index]: self._result_model.appendRow( QStandardItem(result['address'])) # TODO: fix hexview highlights performance """