From bd8862923ee086fe50ffd6d75fa3776baf88ea38 Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Sat, 29 Sep 2018 17:34:43 -0400 Subject: [PATCH 1/7] fixes regression that could cause IDA 6.8 --> 7.0 to hang on exit --- plugin/lighthouse/painting/ida_painter.py | 8 +++++++- plugin/lighthouse/painting/painter.py | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plugin/lighthouse/painting/ida_painter.py b/plugin/lighthouse/painting/ida_painter.py index 4e8558e8..d2168577 100644 --- a/plugin/lighthouse/painting/ida_painter.py +++ b/plugin/lighthouse/painting/ida_painter.py @@ -181,11 +181,17 @@ def _clear_nodes(self, nodes_metadata): self.clear_nodes(nodes_metadata) self._action_complete.set() - @disassembler.execute_ui + @execute_paint def _refresh_ui(self): + """ + Note that this has been decorated with @execute_paint (vs @execute_ui) + to help avoid deadlocking on exit. + """ idaapi.refresh_idaview_anyway() def _cancel_action(self, job_id): + if idaapi.IDA_SDK_VERSION < 710: + return idaapi.cancel_exec_request(job_id) #------------------------------------------------------------------------------ diff --git a/plugin/lighthouse/painting/painter.py b/plugin/lighthouse/painting/painter.py index 6748df72..71488c39 100644 --- a/plugin/lighthouse/painting/painter.py +++ b/plugin/lighthouse/painting/painter.py @@ -381,7 +381,7 @@ def _async_database_painter(self): # Asynchronous Database Painting Loop # - while True: + while not self._end_threads: # wait for the next command to come through action = self._msg_queue.get() From bf66b02df99d8cf4f3150b0d4a5eaef13b53c9cb Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Sat, 29 Sep 2018 17:39:24 -0400 Subject: [PATCH 2/7] fixes DPI regressions --- plugin/lighthouse/ui/coverage_overview.py | 2 +- plugin/lighthouse/ui/coverage_table.py | 4 ++-- plugin/lighthouse/util/qt/util.py | 17 ++++++++++++----- plugin/lighthouse/util/qt/waitbox.py | 2 +- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/plugin/lighthouse/ui/coverage_overview.py b/plugin/lighthouse/ui/coverage_overview.py index b10ff511..bc9c1dfa 100644 --- a/plugin/lighthouse/ui/coverage_overview.py +++ b/plugin/lighthouse/ui/coverage_overview.py @@ -188,7 +188,7 @@ def _ui_layout(self): # layout the major elements of our widget layout = QtWidgets.QGridLayout() - layout.setSpacing(get_dpi_scale()) + layout.setSpacing(get_dpi_scale()*5.0) layout.addWidget(self._table_view) layout.addWidget(self._toolbar) diff --git a/plugin/lighthouse/ui/coverage_table.py b/plugin/lighthouse/ui/coverage_table.py index 3a662242..6a407068 100644 --- a/plugin/lighthouse/ui/coverage_table.py +++ b/plugin/lighthouse/ui/coverage_table.py @@ -179,12 +179,12 @@ def _ui_init_table(self): # specify the fixed pixel height for the table headers spacing = title_fm.height() - title_fm.xHeight() - tweak = 24 - spacing + tweak = 26*get_dpi_scale() - spacing hh.setFixedHeight(entry_fm.height()+tweak) # specify the fixed pixel height for the table rows spacing = entry_fm.height() - entry_fm.xHeight() - tweak = 16 - spacing + tweak = 17.5*get_dpi_scale() - spacing vh.setDefaultSectionSize(entry_fm.height()+tweak) def _ui_init_table_ctx_menu_actions(self): diff --git a/plugin/lighthouse/util/qt/util.py b/plugin/lighthouse/util/qt/util.py index 0733c05a..9d984011 100644 --- a/plugin/lighthouse/util/qt/util.py +++ b/plugin/lighthouse/util/qt/util.py @@ -1,3 +1,4 @@ +import sys import time import Queue import logging @@ -69,8 +70,12 @@ def get_dpi_scale(): """ Get a DPI-afflicted value useful for consistent UI scaling. """ - font = QtGui.QFont("Times", 15) - return QtGui.QFontMetricsF(font).xHeight() + font = MonospaceFont() + font.setPointSize(normalize_to_dpi(120)) + fm = QtGui.QFontMetricsF(font) + + # xHeight is expected to be 40.0 at normal DPI + return fm.height() / 173.0 def move_mouse_event(mouse_event, position): """ @@ -89,7 +94,9 @@ def normalize_to_dpi(font_size): """ Normalize the given font size based on the system DPI. """ - return (font_size*get_dpi_scale())/5.0 + if sys.platform == "darwin": # macos is lame + return font_size + 3 + return font_size def prompt_string(label, title, default=""): """ @@ -105,8 +112,8 @@ def prompt_string(label, title, default=""): dlg.setWindowTitle(title) dlg.setTextValue(default) dlg.resize( - dpi_scale*80, - dpi_scale*10 + dpi_scale*400, + dpi_scale*50 ) ok = dlg.exec_() text = str(dlg.textValue()) diff --git a/plugin/lighthouse/util/qt/waitbox.py b/plugin/lighthouse/util/qt/waitbox.py index 9c0b290a..c2af7ff0 100644 --- a/plugin/lighthouse/util/qt/waitbox.py +++ b/plugin/lighthouse/util/qt/waitbox.py @@ -56,7 +56,7 @@ def _ui_init(self): # configure the main widget / form self.setSizeGripEnabled(False) self.setModal(True) - self._dpi_scale = get_dpi_scale() + self._dpi_scale = get_dpi_scale()*5.0 # initialize abort button self._abort_button = QtWidgets.QPushButton("Cancel") From 316e7622d757995ab8cc9d93c1ec05e33b078e57 Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Sat, 29 Sep 2018 17:40:44 -0400 Subject: [PATCH 3/7] bumps version number --- plugin/lighthouse/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/lighthouse/core.py b/plugin/lighthouse/core.py index d0812384..b361c912 100644 --- a/plugin/lighthouse/core.py +++ b/plugin/lighthouse/core.py @@ -20,7 +20,7 @@ # Plugin Metadata #------------------------------------------------------------------------------ -PLUGIN_VERSION = "0.8.0" +PLUGIN_VERSION = "0.8.1" AUTHORS = "Markus Gaasedelen" DATE = "2018" From 2bc6f109db5a2c3997d04c0b689a164d36f944bd Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Tue, 2 Oct 2018 16:00:25 -0400 Subject: [PATCH 4/7] fix for minor regression --- plugin/lighthouse/metadata.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugin/lighthouse/metadata.py b/plugin/lighthouse/metadata.py index 39ea0d4e..ea0afcf3 100644 --- a/plugin/lighthouse/metadata.py +++ b/plugin/lighthouse/metadata.py @@ -127,6 +127,15 @@ def get_node(self, address): # index = bisect.bisect_right(self._node_addresses, address) - 1 + node_metadata = self.nodes.get(self._node_addresses[index], None) + + # + # if the given address does not fall within the selected node (or the + # node simply does not exist), then we have no match/metadata to return + # + + if not (node_metadata and address in node_metadata): + return None # # if the selected node metadata contains the given target address, it @@ -134,11 +143,9 @@ def get_node(self, address): # faster consecutive lookups # - node_metadata = self.nodes.get(self._node_addresses[index], None) - if node_metadata and address in node_metadata: - self._last_node = node_metadata + self._last_node = node_metadata - # return the located node_metadata, or None + # return the located node_metadata return node_metadata def get_function(self, address): From 3f22eddc82ba84496548a503a6cb9d25183b7c77 Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Tue, 2 Oct 2018 16:44:15 -0400 Subject: [PATCH 5/7] auto-cache metadata when opening coverage overview --- plugin/lighthouse/ui/coverage_overview.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugin/lighthouse/ui/coverage_overview.py b/plugin/lighthouse/ui/coverage_overview.py index bc9c1dfa..19863c61 100644 --- a/plugin/lighthouse/ui/coverage_overview.py +++ b/plugin/lighthouse/ui/coverage_overview.py @@ -51,6 +51,15 @@ def show(self): super(CoverageOverview, self).show() self._visible = True + # + # if no metadata had been collected prior to showing the coverage + # overview (eg, through loading coverage), we should do that now + # before the user can interact with the view... + # + + if not self._core.director.metadata.cached: + self._table_controller.refresh_metadata() + def terminate(self): """ The CoverageOverview is being hidden / deleted. From 116f82e6bc11c4b501d36c7eb521b53b5155285f Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Tue, 2 Oct 2018 16:45:42 -0400 Subject: [PATCH 6/7] only disable painting (on clear) if other coverage is open --- plugin/lighthouse/painting/painter.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/plugin/lighthouse/painting/painter.py b/plugin/lighthouse/painting/painter.py index 71488c39..ebe7293a 100644 --- a/plugin/lighthouse/painting/painter.py +++ b/plugin/lighthouse/painting/painter.py @@ -128,8 +128,17 @@ def clear_paint(self): """ Clear all paint from the current database (based on metadata) """ - if self.enabled: + + # + # we should only disable the painter (as a result of clear_paint()) if + # the user has coverage open & in use. for example, there is no reason + # to *preemptively* disable painting if no other coverage is loaded. + # + + if self.enabled and len(self._director.coverage_names): self.set_enabled(False) + + # trigger the database clear self._msg_queue.put(self.MSG_CLEAR) #-------------------------------------------------------------------------- From 03cc67e629bb7a65cce5309b3d5f06d812b53b24 Mon Sep 17 00:00:00 2001 From: gaasedelen Date: Wed, 3 Oct 2018 01:44:41 -0400 Subject: [PATCH 7/7] further tweak table row height based on DPI --- plugin/lighthouse/ui/coverage_table.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/lighthouse/ui/coverage_table.py b/plugin/lighthouse/ui/coverage_table.py index 6a407068..672255bd 100644 --- a/plugin/lighthouse/ui/coverage_table.py +++ b/plugin/lighthouse/ui/coverage_table.py @@ -183,8 +183,9 @@ def _ui_init_table(self): hh.setFixedHeight(entry_fm.height()+tweak) # specify the fixed pixel height for the table rows + # NOTE: don't ask too many questions about this voodoo math :D spacing = entry_fm.height() - entry_fm.xHeight() - tweak = 17.5*get_dpi_scale() - spacing + tweak = (17*get_dpi_scale() - spacing)/get_dpi_scale() vh.setDefaultSectionSize(entry_fm.height()+tweak) def _ui_init_table_ctx_menu_actions(self):