Skip to content

Commit

Permalink
Minor improvements to main_window
Browse files Browse the repository at this point in the history
  • Loading branch information
twizmwazin committed Jul 26, 2024
1 parent 5ab305b commit 0831bb3
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 73 deletions.
104 changes: 41 additions & 63 deletions angrmanagement/ui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,12 @@
from angrmanagement.config import IMG_LOCATION, Conf, save_config
from angrmanagement.daemon import daemon_conn, daemon_exists, run_daemon_process
from angrmanagement.daemon.client import ClientService
from angrmanagement.data.jobs import DependencyAnalysisJob
from angrmanagement.data.jobs.loading import LoadAngrDBJob, LoadBinaryJob, LoadTargetJob
from angrmanagement.data.library_docs import LibraryDocs
from angrmanagement.errors import InvalidURLError, UnexpectedStatusCodeError
from angrmanagement.logic import GlobalInfo
from angrmanagement.logic.commands import BasicCommand
from angrmanagement.logic.threads import ExecuteCodeEvent
from angrmanagement.ui.views import DisassemblyView
from angrmanagement.utils.env import app_root, is_pyinstaller
from angrmanagement.utils.io import download_url, isurl

Expand Down Expand Up @@ -139,6 +137,30 @@ class MainWindow(QMainWindow):
The main window of angr management.
"""

initialized: bool
app: QApplication | None
workspace: Workspace
dock_manager: QtAds.CDockManager
toolbar_manager: ToolbarManager

# Status and Progress
_progress_stopwatch_start_time: float
_progress_message: str
_progress_percentage: float
_progress_update_timer: QTimer
_status_label: QLabel
_stopwatch_label: QIconLabel
_interrupt_job_button: QIconLabel
_progress_label: QLabel
_progress_bar: QProgressBar
_progress_dialog: QProgressDialog

_file_menu: FileMenu
_analyze_menu: AnalyzeMenu
_view_menu: ViewMenu
_help_menu: HelpMenu
_plugin_menu: PluginMenu

def __init__(
self, app: QApplication | None = None, parent=None, show: bool = True, use_daemon: bool = False
) -> None:
Expand All @@ -155,41 +177,31 @@ def __init__(
# initialization
self.setMinimumSize(QSize(400, 400))

self.app: QApplication | None = app
self.workspace: Workspace = None
self.dock_manager: QtAds.CDockManager
self.app = app
self._dock_shortcut_event_filter = DockShortcutEventFilter(self)

self._shift_shift_event_filter = ShiftShiftEventFilter(self)
if app:
if self.app is not None:
self.app.installEventFilter(self._shift_shift_event_filter)

self.toolbar_manager: ToolbarManager = ToolbarManager(self)
self.toolbar_manager = ToolbarManager(self)

self._progress_stopwatch_start_time: float = 0.0
self._progress_message: str = ""
self._progress_percentage: float = 0
self._progress_update_timer: QTimer = QTimer()
self._progress_stopwatch_start_time = 0.0
self._progress_message = ""
self._progress_percentage = 0
self._progress_update_timer = QTimer()
self._progress_update_timer.setSingleShot(False)
self._progress_update_timer.setInterval(1000)
self._progress_update_timer.timeout.connect(self._on_progress_update_timer_timeout)

self.defaultWindowFlags = None

# menus
self._file_menu = None # FileMenu
self._analyze_menu = None
self._view_menu = None
self._help_menu = None
self._plugin_menu = None

self._init_statusbar()
self._init_workspace()
self._init_statusbar()
self._init_toolbars()
self._init_menus()
self._init_plugins()
self.workspace.plugins.discover_and_initialize_plugins()
self._init_library_docs()
# self._init_url_scheme_handler()

self._register_commands()

Expand Down Expand Up @@ -263,7 +275,7 @@ def open_newstate_dialog(self) -> None:
new_state_dialog.exec_()

def open_doc_link(self) -> None:
QDesktopServices.openUrl(QUrl("https://docs.angr.io/", QUrl.TolerantMode))
QDesktopServices.openUrl(QUrl("https://docs.angr.io/", QUrl.ParsingMode.TolerantMode))

def open_about_dialog(self) -> None:
dlg = LoadAboutDialog()
Expand Down Expand Up @@ -309,7 +321,9 @@ def _init_statusbar(self) -> None:

self._progress_dialog = QProgressDialog("Waiting...", "Cancel", 0, 100, self)
self._progress_dialog.setAutoClose(False)
self._progress_dialog.setWindowFlags(self._progress_dialog.windowFlags() & ~Qt.WindowContextHelpButtonHint)
self._progress_dialog.setWindowFlags(
self._progress_dialog.windowFlags() & ~Qt.WindowType.WindowContextHelpButtonHint
)
self._progress_dialog.setModal(True)
self._progress_dialog.setMinimumDuration(2**31 - 1)

Expand Down Expand Up @@ -419,13 +433,6 @@ def init_shortcuts_on_dock(self, dock_widget) -> None:
"""
dock_widget.installEventFilter(self._dock_shortcut_event_filter)

#
# Plugins
#

def _init_plugins(self) -> None:
self.workspace.plugins.discover_and_initialize_plugins()

#
# FLIRT Signatures
#
Expand Down Expand Up @@ -540,9 +547,9 @@ def _register_commands(self) -> None:
[
BasicCommand(action.__name__, caption, action)
for caption, action in [
("Analyze: Decompile", self.decompile_current_function),
("Analyze: Interact", self.interact),
("Analyze: Run Analysis...", self.run_analysis),
("Analyze: Decompile", self.workspace.decompile_current_function),
("Analyze: Interact", self.workspace.interact_program),
("Analyze: Run Analysis...", self.workspace.run_analysis),
("File: Exit", self.quit),
("File: Load a new binary...", self.open_file_button),
("File: Load a new docker target...", self.open_docker_button),
Expand Down Expand Up @@ -842,35 +849,6 @@ def preferences(self) -> None:
def quit(self) -> None:
self.close()

def run_variable_recovery(self) -> None:
self.workspace._get_or_create_view("disassembly", DisassemblyView).variable_recovery_flavor = "accurate"

def run_induction_variable_analysis(self) -> None:
self.workspace._get_or_create_view("disassembly", DisassemblyView).run_induction_variable_analysis()

def run_dependency_analysis(self, func_addr: int | None = None, func_arg_idx: int | None = None) -> None:
if self.workspace is None or self.workspace.main_instance is None:
return
dep_analysis_job = DependencyAnalysisJob(
self.workspace.main_instance, func_addr=func_addr, func_arg_idx=func_arg_idx
)
self.workspace.job_manager.add_job(dep_analysis_job)

def run_analysis(self) -> None:
if self.workspace:
self.workspace.run_analysis()

def decompile_current_function(self) -> None:
if self.workspace is not None:
self.workspace.decompile_current_function()

def view_proximity_for_current_function(self) -> None:
if self.workspace is not None:
self.workspace.view_proximity_for_current_function()

def interact(self) -> None:
self.workspace.interact_program(self.workspace.main_instance.img_name)

def show_command_palette(self, parent=None) -> None:
dlg = CommandPaletteDialog(self.workspace, parent=(parent or self))
dlg.setModal(True)
Expand Down Expand Up @@ -929,7 +907,7 @@ def progress_done(self) -> None:
self._progress_dialog.hide()

def bring_to_front(self) -> None:
self.setWindowState((self.windowState() & ~Qt.WindowMinimized) | Qt.WindowActive)
self.setWindowState((self.windowState() & ~Qt.WindowState.WindowMinimized) | Qt.WindowState.WindowActive)
self.activateWindow()
self.raise_()

Expand Down
8 changes: 4 additions & 4 deletions angrmanagement/ui/menus/analyze_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ def __init__(self, main_window: MainWindow) -> None:
[
MenuEntry(
"&Run Analysis...",
main_window.run_analysis,
main_window.workspace.run_analysis,
shortcut=QKeySequence(Qt.Key_F4),
icon=icon("run-analysis"),
),
MenuSeparator(),
MenuEntry(
"&Decompile",
main_window.decompile_current_function,
main_window.workspace.decompile_current_function,
shortcut=QKeySequence(Qt.Key_F5),
icon=icon("pseudocode-view"),
),
MenuEntry(
"View in Proximity &Browser",
main_window.view_proximity_for_current_function,
main_window.workspace.view_proximity_for_current_function,
shortcut=QKeySequence("Ctrl+B"),
),
MenuEntry("&Interact", main_window.interact, shortcut=QKeySequence(Qt.Key_F6)),
MenuEntry("&Interact", main_window.workspace.interact_program, shortcut=QKeySequence(Qt.Key_F6)),
],
)
2 changes: 1 addition & 1 deletion angrmanagement/ui/menus/view_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def __init__(self, main_window: MainWindow) -> None:
),
MenuSeparator(),
MenuEntry("&Hex", main_window.workspace.show_hex_view, icon=icon("hex-view")),
MenuEntry("Pro&ximity", main_window.view_proximity_for_current_function),
MenuEntry("Pro&ximity", main_window.workspace.view_proximity_for_current_function),
MenuEntry("Pseudo&code", main_window.workspace.show_pseudocode_view, icon=icon("pseudocode-view")),
MenuEntry("&Strings", main_window.workspace.show_strings_view, icon=icon("strings-view")),
MenuEntry("&Patches", main_window.workspace.show_patches_view, icon=icon("patches-view")),
Expand Down
2 changes: 1 addition & 1 deletion angrmanagement/ui/views/disassembly_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ def popup_dependson_dialog(self, addr: int | None = None, use_operand: bool = Fa

if dependson.location is not None and dependson.arg is not None:
# track function argument
self.workspace._main_window.run_dependency_analysis(
self.workspace.run_dependency_analysis(
func_addr=addr,
func_arg_idx=dependson.arg,
)
Expand Down
4 changes: 1 addition & 3 deletions angrmanagement/ui/widgets/qccode_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
from angrmanagement.ui.dialogs.xref import XRefDialog
from angrmanagement.ui.documents.qcodedocument import QCodeDocument
from angrmanagement.ui.menus.menu import Menu
from angrmanagement.ui.views.disassembly_view import DisassemblyView
from angrmanagement.ui.widgets.qccode_highlighter import FORMATS, QCCodeHighlighter

if TYPE_CHECKING:
Expand Down Expand Up @@ -309,7 +308,6 @@ def xref_node(self, *args, node=None) -> None: # pylint: disable=unused-argumen
if not isinstance(n, CVariable | CFunction | CFunctionCall):
return

disasm_view = self._code_view.workspace._get_or_create_view("disassembly", DisassemblyView)
if isinstance(n, CFunction | CFunctionCall):
addr = n.addr if isinstance(n, CFunction) else n.callee_func.addr
dialog = XRefDialog(
Expand All @@ -324,7 +322,7 @@ def xref_node(self, *args, node=None) -> None: # pylint: disable=unused-argumen
addr = self.get_closest_insaddr(n)
dialog = XRefDialog(
addr=addr,
variable_manager=disasm_view.variable_manager,
variable_manager=self.instance.project.kb.variables,
variable=n.variable,
instance=self.instance,
disassembly_view=self._code_view,
Expand Down
10 changes: 9 additions & 1 deletion angrmanagement/ui/workspace.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
PrototypeFindingJob,
VariableRecoveryJob,
)
from angrmanagement.data.jobs.dependency_analysis import DependencyAnalysisJob
from angrmanagement.data.jobs.loading import LoadBinaryJob
from angrmanagement.data.trace import BintraceTrace, Trace
from angrmanagement.logic.commands import CommandManager
Expand Down Expand Up @@ -605,6 +606,11 @@ def run_analysis(self, prompt_for_configuration: bool = True) -> None:

self.generate_cfg(cfg_options)

def run_dependency_analysis(self, func_addr: int | None = None, func_arg_idx: int | None = None) -> None:
self.job_manager.add_job(
DependencyAnalysisJob(self.main_instance, func_addr=func_addr, func_arg_idx=func_arg_idx)
)

def decompile_current_function(self) -> None:
current = self.view_manager.current_tab
if isinstance(current, CodeView):
Expand Down Expand Up @@ -739,7 +745,9 @@ def create_project_from_trace(self, trace: Trace, on_complete: Callable) -> None
job = LoadBinaryJob(self.main_instance, thing, load_options=load_options, on_finish=on_complete)
self.job_manager.add_job(job)

def interact_program(self, img_name: str, view=None) -> None:
def interact_program(self, img_name: str | None = None, view=None) -> None:
if img_name is None:
img_name = self.main_instance.img_name
if view is None or view.category != "interaction":
view = self._get_or_create_view("interaction", InteractionView)
view.initialize(img_name)
Expand Down

0 comments on commit 0831bb3

Please sign in to comment.