mirror of
https://github.com/idapython/src
synced 2026-06-08 14:47:00 +00:00
102 lines
3.0 KiB
Python
102 lines
3.0 KiB
Python
"""
|
|
summary: follow the movements of one graph, in another
|
|
|
|
description:
|
|
Since it is possible to be notified of movements that happen
|
|
take place in a widget, it's possible to "replay" those
|
|
movements in another.
|
|
|
|
In this case, "IDA View-B" (will be opened if necessary) will
|
|
show the same contents as "IDA View-A", slightly zoomed out.
|
|
|
|
keywords: graph, idaview
|
|
|
|
see_also: wrap_idaview
|
|
|
|
level: intermediate
|
|
"""
|
|
|
|
import ida_kernwin
|
|
import ida_moves
|
|
import ida_graph
|
|
|
|
#
|
|
# Cleanup (in case the script is run more than once)
|
|
#
|
|
try:
|
|
wrap_a.Unbind()
|
|
except:
|
|
pass
|
|
|
|
|
|
wrap_a = None
|
|
|
|
#
|
|
# The IDA View-A "monitor": changes will be reported into IDA View-B
|
|
#
|
|
class IDAViewA_monitor_t(ida_kernwin.IDAViewWrapper):
|
|
def __init__(self):
|
|
ida_kernwin.IDAViewWrapper.__init__(self, "IDA View-A")
|
|
|
|
def OnViewLocationChanged(self, now, was):
|
|
self.update_widget_b()
|
|
|
|
def update_widget_b(self):
|
|
|
|
# Make sure we are in the same function
|
|
place_a, _, _ = ida_kernwin.get_custom_viewer_place(widget_a, False)
|
|
ida_kernwin.jumpto(widget_b, place_a, -1, -1)
|
|
|
|
# and that we show the right place (slightly zoomed out)
|
|
widget_a_center_gli = ida_moves.graph_location_info_t()
|
|
if ida_graph.viewer_get_gli(widget_a_center_gli, widget_a, ida_graph.GLICTL_CENTER):
|
|
widget_b_center_gli = ida_moves.graph_location_info_t()
|
|
widget_b_center_gli.orgx = widget_a_center_gli.orgx
|
|
widget_b_center_gli.orgy = widget_a_center_gli.orgy
|
|
widget_b_center_gli.zoom = widget_a_center_gli.zoom * 0.5
|
|
ida_graph.viewer_set_gli(widget_b, widget_b_center_gli, ida_graph.GLICTL_CENTER)
|
|
|
|
#
|
|
# Make sure both views are opened...
|
|
#
|
|
for label in ["A", "B"]:
|
|
title = "IDA View-%s" % label
|
|
if not ida_kernwin.find_widget(title):
|
|
print("View %s not available. Opening." % title)
|
|
ida_kernwin.open_disasm_window(label)
|
|
|
|
#
|
|
# ...and that they are both in graph mode
|
|
#
|
|
widget_a = ida_kernwin.find_widget("IDA View-A")
|
|
ida_kernwin.set_view_renderer_type(widget_a, ida_kernwin.TCCRT_GRAPH)
|
|
|
|
widget_b = ida_kernwin.find_widget("IDA View-B")
|
|
ida_kernwin.set_view_renderer_type(widget_b, ida_kernwin.TCCRT_GRAPH)
|
|
|
|
#
|
|
# Put view B to the right of view A
|
|
#
|
|
ida_kernwin.set_dock_pos("IDA View-B", "IDA View-A", ida_kernwin.DP_RIGHT)
|
|
|
|
#
|
|
# Start monitoring IDA View-A
|
|
#
|
|
wrap_a = IDAViewA_monitor_t()
|
|
wrap_a.Bind()
|
|
|
|
#
|
|
# This is to get a properly initialized set of views to begin with.
|
|
# At this point, all UI resize/move events resulting of 'set_dock_pos()'
|
|
# haven't yet been processed, and thus the views don't know their final
|
|
# geometries. We'll give them a bit of time to process those events, and
|
|
# then we'll request that "IDA View-A" shows the whole graph (and
|
|
# "IDA View-B" will obviously follow.)
|
|
#
|
|
def fit_widget_a():
|
|
def do_fit_widget_a():
|
|
ida_graph.viewer_fit_window(widget_a)
|
|
ida_kernwin.execute_sync(do_fit_widget_a, ida_kernwin.MFF_FAST)
|
|
import threading
|
|
threading.Timer(0.25, fit_widget_a).start()
|