IDAPython for IDA 8.3

This commit is contained in:
Arnaud Diederen
2023-06-12 10:39:14 +02:00
parent c99b9db781
commit e6841a95a3
97 changed files with 3909 additions and 1536 deletions
-2
View File
@@ -18,8 +18,6 @@ keywords: actions
see_also: add_hotkey
"""
from __future__ import print_function
import ida_kernwin
class SayHi(ida_kernwin.action_handler_t):
-2
View File
@@ -16,8 +16,6 @@ keywords: actions
see_also: actions
"""
from __future__ import print_function
import ida_kernwin
def hotkey_pressed():
-2
View File
@@ -11,8 +11,6 @@ keywords: actions
see_also: actions, add_hotkey
"""
from __future__ import print_function
import ida_expr
import ida_kernwin
-3
View File
@@ -15,9 +15,6 @@ description:
encoding, or as UTF-16.)
"""
from __future__ import print_function
import ida_kernwin
import ida_bytes
import ida_ida
-3
View File
@@ -16,9 +16,6 @@ keywords: coloring, idc
see_also: colorize_disassembly_on_the_fly
"""
from __future__ import print_function
BG_BLUE = 0xc02020
BG_GREEN = 0x208020
BG_RED = 0x2020c0
@@ -101,12 +101,13 @@ class on_the_fly_coloring_hooks_t(ida_kernwin.UI_Hooks):
del self.by_widget[title]
class carousel_color_ah_t():
class carousel_color_ah_t(ida_kernwin.action_handler_t):
"""
The action that will be invoked by IDA when the user
activates its shortcut.
"""
def __init__(self, hooks):
ida_kernwin.action_handler_t.__init__(self)
self.hooks = hooks
def activate(self, ctx):
@@ -8,7 +8,6 @@ description:
author: Gergely Erdelyi (gergely.erdelyi@d-dome.net)
"""
from __future__ import print_function
#---------------------------------------------------------------------
# Structure test
#
-1
View File
@@ -9,7 +9,6 @@ description:
It provides an example tab completion support.
"""
from __future__ import print_function
# -----------------------------------------------------------------------
# This is an example illustrating how to implement a CLI
#
@@ -11,8 +11,6 @@ description:
one format for a specific 'custom data type'.)
"""
from __future__ import print_function
import ida_bytes
import ida_idaapi
import ida_lines
-2
View File
@@ -9,8 +9,6 @@ description:
the previous and next extra comments.
"""
from __future__ import print_function
import ida_lines
import ida_kernwin
-2
View File
@@ -10,8 +10,6 @@ description:
`ida_gdl.FlowChart` type.
"""
from __future__ import print_function
import ida_gdl
import ida_funcs
import ida_kernwin
-2
View File
@@ -15,8 +15,6 @@ description:
"""
from __future__ import print_function
import ida_kernwin
import ida_lines
-2
View File
@@ -14,8 +14,6 @@ description:
`pow(3, 7)`
"""
from __future__ import print_function
import ida_expr
if ida_expr.add_idc_func(
@@ -8,8 +8,6 @@ description:
`ida_lines.user_defined_prefix_t` helper type.
"""
from __future__ import print_function
import ida_lines
import ida_idaapi
-2
View File
@@ -5,8 +5,6 @@ description:
Using the API to enumerate file imports.
"""
from __future__ import print_function
import ida_nalt
nimps = ida_nalt.get_import_module_qty()
-2
View File
@@ -6,8 +6,6 @@ description:
that were patched using IDA.
"""
from __future__ import print_function
import ida_bytes
import ida_idaapi
-1
View File
@@ -10,7 +10,6 @@ keywords: xrefs
see_also: list_segment_functions_using_idautils
"""
from __future__ import print_function
#
# Reference Lister
#
@@ -13,7 +13,6 @@ keywords: xrefs
see_also: list_segment_functions
"""
from __future__ import print_function
#
# Reference Lister
#
-1
View File
@@ -9,7 +9,6 @@ description:
see_also: show_selected_strings
"""
from __future__ import print_function
import ida_nalt
import idautils
-2
View File
@@ -5,8 +5,6 @@ description:
Register (possibly repeating) timers.
"""
from __future__ import print_function
import ida_kernwin
# -------------------------------------------------------------------------
@@ -15,8 +15,6 @@ description:
keywords: actions
"""
from __future__ import print_function
import ida_kernwin
# --------------------------------------------------------------------------
+82
View File
@@ -0,0 +1,82 @@
"""
summary: This file contains the CVT64 examples.
description:
For more infortmation see SDK/plugins/cvt64_sample example
"""
import idaapi
import ida_idaapi
import ida_netnode
SAMPLE_NETNODE_NAME = "$ cvt64 py_sample netnode"
DEVICE_INDEX = idaapi.BADADDR # -1
IDPFLAGS_INDEX = idaapi.BADADDR # -1
HASH_COMMENT = "Comment"
HASH_ADDRESS = "Address"
#--------------------------------------------------------------------------
class idp_listener_t(idaapi.IDP_Hooks):
def __init__(self):
idaapi.IDP_Hooks.__init__(self)
def ev_cvt64_hashval(self, node, tag, name, data):
helper = idaapi.netnode(SAMPLE_NETNODE_NAME)
if helper == node and tag == ida_netnode.htag:
if name == HASH_COMMENT:
comment = helper.hashstr(name)
helper.hashset_buf(name, comment)
return 1
if name == HASH_ADDRESS:
address = helper.hashval_long(name)
if address == ida_idaapi.BADADDR32:
address = ida_idaapi.BADADDR
helper.hashset_idx(name, address)
return 1
return 0
def ev_cvt64_supval(self, node, tag, idx, data):
helper = idaapi.netnode(SAMPLE_NETNODE_NAME)
if helper == node:
if tag == ida_netnode.stag and idx == ida_idaapi.BADADDR32:
helper.supset(DEVICE_INDEX, data)
return 1
if tag == ida_netnode.atag and len(data):
if idx == ida_idaapi.BADADDR32:
idx = IDPFLAGS_INDEX
val = int.from_bytes(data, 'little')
if val == ida_idaapi.BADADDR32:
val = ida_idaapi.BADADDR
helper.altset(idx, val)
return 1
return 0
#--------------------------------------------------------------------------
# This class is instantiated once per each opened database.
class cvt64_ctx_t(idaapi.plugmod_t):
def __init__(self):
self.prochook = idp_listener_t()
self.prochook.hook()
def __del__(self):
self.prochook.unhook()
def run(self, arg):
pass
#--------------------------------------------------------------------------
# This class is instantiated when IDA loads the plugin.
class cvt64_sample_t(idaapi.plugin_t):
flags = idaapi.PLUGIN_MULTI | idaapi.PLUGIN_MOD
comment = "IDAPython: An example how to implement CVT64 functionality"
wanted_name = "IDAPython: CVT64 sample"
wanted_hotkey = ""
help = ""
def init(self):
return cvt64_ctx_t()
#--------------------------------------------------------------------------
def PLUGIN_ENTRY():
return cvt64_sample_t()
@@ -20,8 +20,6 @@ description:
Note: the real body of code is in `simple_appcall_common.py`.
"""
from __future__ import print_function
import os
import sys
sys.path.append(os.path.dirname(__file__))
@@ -20,8 +20,6 @@ description:
Note: the real body of code is in `simple_appcall_common.py`.
"""
from __future__ import print_function
import os
import sys
sys.path.append(os.path.dirname(__file__))
@@ -7,8 +7,6 @@ description:
execution.
"""
from __future__ import print_function
import ida_dbg
import ida_ida
import ida_lines
-2
View File
@@ -6,8 +6,6 @@ description:
symbols that the process being debugged, provides.
"""
from __future__ import print_function
import ida_dbg
import ida_ida
import ida_name
@@ -10,8 +10,6 @@ description:
idat -Ldecompile.log -Sdecompile_entry_points.py -c file
"""
from __future__ import print_function
import ida_ida
import ida_auto
import ida_loader
-2
View File
@@ -2,8 +2,6 @@
summary: decompile & print current function.
"""
from __future__ import print_function
import ida_hexrays
import ida_lines
import ida_funcs
-2
View File
@@ -33,8 +33,6 @@ description:
author: EiNSTeiN_ (einstein@g3nius.org)
"""
from __future__ import print_function
import idautils
import ida_kernwin
-2
View File
@@ -15,8 +15,6 @@ description:
author: EiNSTeiN_ (einstein@g3nius.org)
"""
from __future__ import print_function
import ida_kernwin
import ida_hexrays
import ida_bytes
-2
View File
@@ -12,8 +12,6 @@ description:
request that ida displays that using `ida_gdl.display_gdl`.
"""
from __future__ import print_function
import ida_pro
import ida_hexrays
import ida_kernwin
-2
View File
@@ -8,8 +8,6 @@ description:
Note: this is rather crude, not quite "pythonic" code.
"""
from __future__ import print_function
import idautils
import idc
import ida_idaapi
-2
View File
@@ -8,8 +8,6 @@ description:
author: EiNSTeiN_ (einstein@g3nius.org)
"""
from __future__ import print_function
import ida_hexrays
class cblock_visitor_t(ida_hexrays.ctree_visitor_t):
+1 -1
View File
@@ -26,7 +26,7 @@ class hint_hooks_t(ida_hexrays.Hexrays_Hooks):
elif cit == ida_hexrays.VDI_EXPR:
ce = vu.item.e
if ce.op == ida_hexrays.cot_call:
return 2, "==> ", 1
return 0, "==> ", 1
if ce.op == ida_hexrays.cit_if:
return 1, "condition", 1
return 0
-2
View File
@@ -14,8 +14,6 @@ description:
see_also: curpos_details
"""
from __future__ import print_function
import inspect
import ida_idaapi
+1 -4
View File
@@ -10,7 +10,6 @@ description:
author: EiNSTeiN_ (einstein@g3nius.org)
"""
from __future__ import print_function
import ida_kernwin
import ida_hexrays
@@ -168,13 +167,11 @@ class XrefsForm(ida_kernwin.PluginForm):
addresses = []
for ea in idautils.Functions():
cfunc = ida_hexrays.decompile(ea)
cfunc = ida_hexrays.decompile(ea, flags=ida_hexrays.DECOMP_GXREFS_FORCE)
if not cfunc:
print('Decompilation of %x failed' % (ea, ))
continue
print(str(cfunc)) # KLUDGE
for citem in cfunc.treeitems:
citem = citem.to_specific_type
if not (type(citem) == ida_hexrays.cexpr_t and citem.opname in ('memptr', 'memref')):
Binary file not shown.
-2
View File
@@ -9,8 +9,6 @@ description:
See Linux/arch/arm/include/asm/bug.h for more info
"""
from __future__ import print_function
import ida_idp
import ida_bytes
import ida_segregs
-1
View File
@@ -8,7 +8,6 @@ description:
* "nothing" -> nop
"""
from __future__ import print_function
import ida_idp
import idautils
+98 -2
View File
@@ -404,6 +404,7 @@ across 4 predefined colors (and return to the "no color" state.)
<li>ida_kernwin.CK_EXTRA8</li>
<li>ida_kernwin.UI_Hooks</li>
<li>ida_kernwin.action_desc_t</li>
<li>ida_kernwin.action_handler_t</li>
<li>ida_kernwin.get_current_viewer</li>
<li>ida_kernwin.get_custom_viewer_location</li>
<li>ida_kernwin.get_custom_viewer_place_xcoord</li>
@@ -1387,6 +1388,43 @@ menu, so as to keep focus on "IDA View-A" and have the
</div>
</div>
</div>
<h2>Category: cvt64</h2>
<div class="c_list" onclick="handle_click()">
<div class="example-entry collapsed-entry" name="py_cvt64_sample">
<div>
<span class="exp-col expander">&#x25B9;</span>
<span class="exp-col collapser" style="display:none">&#x25BF;</span>
<a href="cvt64/py_cvt64_sample.py">py_cvt64_sample</a>: <i>This file contains the CVT64 examples.</i>
</div>
<div class="details" id="DIV_py_cvt64_sample">
<pre>
For more infortmation see SDK/plugins/cvt64_sample example
</pre>
<ul>
<li>Category: cvt64</li>
<li>Summary: This file contains the CVT64 examples.</li>
<li>View on <a href="https://github.com/idapython/src/blob/master/examples/cvt64/py_cvt64_sample.py">GitHub</a></li>
<li>APIs used
<ul>
<li>ida_idaapi.BADADDR</li>
<li>ida_idaapi.BADADDR32</li>
<li>ida_netnode.atag</li>
<li>ida_netnode.htag</li>
<li>ida_netnode.stag</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<h2>Category: debugging</h2>
<div class="c_list" onclick="handle_click()">
@@ -2944,6 +2982,7 @@ pressed in the Decompiler window.
<li>APIs used
<ul>
<li>ida_funcs.get_func_name</li>
<li>ida_hexrays.DECOMP_GXREFS_FORCE</li>
<li>ida_hexrays.Hexrays_Hooks</li>
<li>ida_hexrays.USE_KEYBOARD</li>
<li>ida_hexrays.VDI_EXPR</li>
@@ -3418,6 +3457,64 @@ A few notes:
</li>
</ul>
</div>
</div>
<div class="example-entry collapsed-entry" name="paint_over_graph">
<div>
<span class="exp-col expander">&#x25B9;</span>
<span class="exp-col collapser" style="display:none">&#x25BF;</span>
<a href="pyqt/paint_over_graph.py">paint_over_graph</a>: <i>Custom painting on top of graph view edges</i>
</div>
<div class="details" id="DIV_paint_over_graph">
<pre>
This sample registers an action enabling painting of a recognizable
string of text over horizontal nodes edge sections beyond a
satisfying size threshold.
In a disassembly view, open the context menu and select
"Paint on edges". This should work for both graph disassembly,
and proximity browser.
Using an "event filter", we will intercept paint events
targeted at the disassembly view, let it paint itself, and
then add our own markers along.
</pre>
<ul>
<li>Category: pyqt</li>
<li>Summary: Custom painting on top of graph view edges</li>
<li>View on <a href="https://github.com/idapython/src/blob/master/examples/pyqt/paint_over_graph.py">GitHub</a></li>
<li>Keywords:
ctxmenu
UI_Hooks
</li>
<li>APIs used
<ul>
<li>ida_graph.edge_t</li>
<li>ida_graph.get_graph_viewer</li>
<li>ida_graph.get_viewer_graph</li>
<li>ida_graph.point_t</li>
<li>ida_graph.viewer_get_gli</li>
<li>ida_kernwin.AST_DISABLE_FOR_WIDGET</li>
<li>ida_kernwin.AST_ENABLE_FOR_WIDGET</li>
<li>ida_kernwin.BWN_DISASM</li>
<li>ida_kernwin.PluginForm.FormToPyQtWidget</li>
<li>ida_kernwin.UI_Hooks</li>
<li>ida_kernwin.action_desc_t</li>
<li>ida_kernwin.action_handler_t</li>
<li>ida_kernwin.attach_action_to_popup</li>
<li>ida_kernwin.get_widget_type</li>
<li>ida_kernwin.register_action</li>
<li>ida_moves.graph_location_info_t</li>
</ul>
</li>
</ul>
</div>
</div>
@@ -3430,7 +3527,7 @@ A few notes:
<div class="details" id="DIV_paint_over_navbar">
<pre>
Using an "event filter", we'll intercept paint events
Using an "event filter", we will intercept paint events
targeted at the navigation band widget, let it paint itself,
and then add our own markers on top.
</pre>
@@ -3888,7 +3985,6 @@ The important bits to enable this are:
<li>ida_kernwin.CH_CAN_INS</li>
<li>ida_kernwin.CH_HAS_DIRTREE</li>
<li>ida_kernwin.CH_MULTI</li>
<li>ida_kernwin.CH_NOIDB</li>
<li>ida_kernwin.Choose</li>
<li>ida_kernwin.Choose.ALL_CHANGED</li>
<li>ida_kernwin.Choose.CHCOL_DRAGHINT</li>
+81 -2
View File
@@ -303,6 +303,7 @@ coloring UI_Hooks
* ida_kernwin.CK_EXTRA8
* ida_kernwin.UI_Hooks
* ida_kernwin.action_desc_t
* ida_kernwin.action_handler_t
* ida_kernwin.get_current_viewer
* ida_kernwin.get_custom_viewer_location
* ida_kernwin.get_custom_viewer_place_xcoord
@@ -1120,6 +1121,34 @@ actions
* ida_kernwin.msg
* ida_kernwin.process_ui_action
</blockquote>
</details>
## Category: cvt64
#### py_cvt64_sample
<details>
<summary>This file contains the CVT64 examples.</summary>
<blockquote>
#### Source code
<a href="https://github.com/idapython/src/blob/master/examples/cvt64/py_cvt64_sample.py">cvt64/py_cvt64_sample.py</a>
#### Category
cvt64
#### Description
For more infortmation see SDK/plugins/cvt64_sample example
#### Uses
* ida_idaapi.BADADDR
* ida_idaapi.BADADDR32
* ida_netnode.atag
* ida_netnode.htag
* ida_netnode.stag
</blockquote>
</details>
@@ -2452,6 +2481,7 @@ ctxmenu Hexrays_Hooks
#### Uses
* ida_funcs.get_func_name
* ida_hexrays.DECOMP_GXREFS_FORCE
* ida_hexrays.Hexrays_Hooks
* ida_hexrays.USE_KEYBOARD
* ida_hexrays.VDI_EXPR
@@ -2859,6 +2889,56 @@ A few notes:
* ida_kernwin.find_widget
* ida_kernwin.process_ui_action
</blockquote>
</details>
#### paint_over_graph
<details>
<summary>Custom painting on top of graph view edges</summary>
<blockquote>
#### Source code
<a href="https://github.com/idapython/src/blob/master/examples/pyqt/paint_over_graph.py">pyqt/paint_over_graph.py</a>
#### Category
pyqt
#### Description
This sample registers an action enabling painting of a recognizable
string of text over horizontal nodes edge sections beyond a
satisfying size threshold.
In a disassembly view, open the context menu and select
"Paint on edges". This should work for both graph disassembly,
and proximity browser.
Using an "event filter", we will intercept paint events
targeted at the disassembly view, let it paint itself, and
then add our own markers along.
#### Keywords
ctxmenu UI_Hooks
#### Uses
* ida_graph.edge_t
* ida_graph.get_graph_viewer
* ida_graph.get_viewer_graph
* ida_graph.point_t
* ida_graph.viewer_get_gli
* ida_kernwin.AST_DISABLE_FOR_WIDGET
* ida_kernwin.AST_ENABLE_FOR_WIDGET
* ida_kernwin.BWN_DISASM
* ida_kernwin.PluginForm.FormToPyQtWidget
* ida_kernwin.UI_Hooks
* ida_kernwin.action_desc_t
* ida_kernwin.action_handler_t
* ida_kernwin.attach_action_to_popup
* ida_kernwin.get_widget_type
* ida_kernwin.register_action
* ida_moves.graph_location_info_t
</blockquote>
</details>
@@ -2876,7 +2956,7 @@ A few notes:
pyqt
#### Description
Using an "event filter", we'll intercept paint events
Using an "event filter", we will intercept paint events
targeted at the navigation band widget, let it paint itself,
and then add our own markers on top.
@@ -3242,7 +3322,6 @@ actions chooser folders
* ida_kernwin.CH_CAN_INS
* ida_kernwin.CH_HAS_DIRTREE
* ida_kernwin.CH_MULTI
* ida_kernwin.CH_NOIDB
* ida_kernwin.Choose
* ida_kernwin.Choose.ALL_CHANGED
* ida_kernwin.Choose.CHCOL_DRAGHINT
+142
View File
@@ -0,0 +1,142 @@
"""
summary: custom painting on top of graph view edges
description:
This sample registers an action enabling painting of a recognizable
string of text over horizontal nodes edge sections beyond a
satisfying size threshold.
In a disassembly view, open the context menu and select
"Paint on edges". This should work for both graph disassembly,
and proximity browser.
Using an "event filter", we will intercept paint events
targeted at the disassembly view, let it paint itself, and
then add our own markers along.
"""
from PyQt5 import QtCore
from PyQt5 import QtGui
from PyQt5 import QtWidgets
import ida_graph
import ida_kernwin
import ida_moves
edge_segment_threshold = 50
text_color = QtGui.QColor(0, 0, 0)
text_antialiasing = True
verbose = False
class painter_t(QtCore.QObject):
def __init__(self, w, verbose=False):
QtCore.QObject.__init__(self)
self.idaview = w
self.idaview_pyqt = ida_kernwin.PluginForm.FormToPyQtWidget(w)
self.target = self.idaview_pyqt.viewport()
self.target.installEventFilter(self)
self.painting = False
def eventFilter(self, receiver, event):
if not self.painting and \
receiver == self.target and \
event.type() == QtCore.QEvent.Paint:
# Send a paint event that we won't intercept
self.painting = True
try:
pev = QtGui.QPaintEvent(self.target.rect())
QtWidgets.QApplication.instance().sendEvent(self.target, pev)
finally:
self.painting = False
# now we can paint our items
viewer = ida_graph.get_graph_viewer(self.idaview)
graph = ida_graph.get_viewer_graph(viewer)
if graph:
painter = QtGui.QPainter(receiver)
if text_antialiasing:
painter.setRenderHints(QtGui.QPainter.TextAntialiasing)
else:
# this is primarily used for testing
font = painter.font()
font.setStyleStrategy(font.NoAntialias)
painter.setFont(font)
painter.setPen(text_color)
# The edge layout info we retrieve will be in "graph
# coordinates". In order to transform those points to
# view coordinates we will need the graph location info
gli = ida_moves.graph_location_info_t()
ida_graph.viewer_get_gli(gli, viewer);
def to_view_coords(pt):
x = int((pt.x - gli.orgx) * gli.zoom)
y = int((pt.y - gli.orgy) * gli.zoom)
return ida_graph.point_t(x, y)
# Let `src_node` be each visible node in the graph...
for src_node in range(graph.size()):
if not graph.is_visible_node(src_node):
continue
# ...and `dst_node` be each visible node
# to which `src_node` is connected
for dst_node_idx in range(graph.nsucc(src_node)):
dst_node = graph.succ(src_node, dst_node_idx)
if not graph.is_visible_node(dst_node):
continue
edge_info = graph.get_edge(ida_graph.edge_t(src_node, dst_node))
if edge_info:
# For all horizontal edge segments satisfying the length requirements...
for idx in range(len(edge_info.layout)-1):
src = to_view_coords(edge_info.layout[idx])
dst = to_view_coords(edge_info.layout[idx+1])
if src.y == dst.y and abs(src.x - dst.x) > edge_segment_threshold:
off = 6
text = "%s -> %s (#%d)" % (src_node, dst_node, idx)
if verbose:
print("Painting \"%s\"" % text)
painter.drawText(min(src.x, dst.x) + off, src.y - off, text)
painter.end()
# ...and prevent the widget form painting itself again
return True
return QtCore.QObject.eventFilter(self, receiver, event)
painter = None
class paint_on_edges_t(ida_kernwin.action_handler_t):
def activate(self, ctx):
if self.get_idaview(ctx):
global painter
painter = painter_t(ctx.widget)
return 1
return 0
def update(self, ctx):
return ida_kernwin.AST_ENABLE_FOR_WIDGET \
if self.get_idaview(ctx) \
else ida_kernwin.AST_DISABLE_FOR_WIDGET
def get_idaview(self, ctx):
return ctx.widget if ctx.widget_type == ida_kernwin.BWN_DISASM else None
action_name = "paint_over_graph:enable"
ida_kernwin.register_action(
ida_kernwin.action_desc_t(
action_name,
"Paint on edges",
paint_on_edges_t()))
#
# Make sure our action is available for all disassembly views
#
class context_menu_hooks_t(ida_kernwin.UI_Hooks):
def finish_populating_widget_popup(self, widget, popup):
if ida_kernwin.get_widget_type(widget) == ida_kernwin.BWN_DISASM:
ida_kernwin.attach_action_to_popup(widget, popup, action_name, None)
hooks = context_menu_hooks_t()
hooks.hook()
+1 -1
View File
@@ -2,7 +2,7 @@
summary: custom painting on top of the navigation band
description:
Using an "event filter", we'll intercept paint events
Using an "event filter", we will intercept paint events
targeted at the navigation band widget, let it paint itself,
and then add our own markers on top.
"""
-2
View File
@@ -6,8 +6,6 @@ description:
dump their information to the "Output" window
"""
from __future__ import print_function
import inspect
import ida_kernwin
-1
View File
@@ -11,7 +11,6 @@ description:
keywords: forms
"""
from __future__ import print_function
# -----------------------------------------------------------------------
# This is an example illustrating how to use the Form class
# (c) Hex-Rays
@@ -8,7 +8,6 @@ description:
keywords: graph, actions
"""
from __future__ import print_function
# -----------------------------------------------------------------------
# This is an example illustrating how to use the user graphing functionality
# in Python
@@ -14,8 +14,6 @@ keywords: graph, idaview
see_also: wrap_idaview
"""
from __future__ import print_function
import ida_kernwin
import ida_moves
import ida_graph
-2
View File
@@ -10,8 +10,6 @@ keywords: idaview, graph
see_also: custom_graph_with_actions, sync_two_graphs
"""
from __future__ import print_function
# -----------------------------------------------------------------------
# (c) Hex-Rays
@@ -12,8 +12,6 @@ description:
keywords: listing, actions
"""
from __future__ import print_function
import ida_kernwin
import ida_lines
@@ -11,7 +11,6 @@ keywords: chooser, actions
see_also: choose_multi, chooser_with_folders
"""
from __future__ import print_function
import ida_kernwin
from ida_kernwin import Choose
@@ -9,10 +9,8 @@ keywords: chooser, actions
see_also: choose, chooser_with_folders
"""
from __future__ import print_function
from ida_kernwin import Choose
class MyChoose(Choose):
def __init__(self, title, nb = 5):
@@ -80,7 +80,6 @@ SUPVAL_COL2_DATA_TAG = '2'
class base_idapython_tree_view_t(ida_kernwin.Choose):
def __init__(self, title, nitems=100, dirspec_log=True, flags=0):
flags |= ida_kernwin.CH_NOIDB
flags |= ida_kernwin.CH_MULTI
flags |= ida_kernwin.CH_HAS_DIRTREE
ida_kernwin.Choose.__init__(self,
@@ -10,7 +10,6 @@ keywords: chooser, functions
see_also: choose, choose_multi, chooser_with_folders
"""
from __future__ import print_function
import idautils
import idc
import ida_funcs
+2 -2
View File
@@ -629,7 +629,7 @@ struct python_highlighter_t : public ida_syntax_highlighter_t
int py_major = 0, py_minor= 0;
qsscanf(Py_GetVersion(), "%d.%d", &py_major, &py_minor);
if ( py_major >= 3 && py_minor >= 5 )
add_keywords("async|await", HF_KEYWORD1);
add_keywords("async|await", HF_KEYWORD1);
if ( py_major >= 3 && py_minor >= 10 )
add_keywords("match|case", HF_KEYWORD1);
}
@@ -984,7 +984,7 @@ bool idapython_plugin_t::init()
// add new Python keywords as needed
python_highlighter.add_new_keywords();
// remove current directory
_prepare_sys_path();
+4
View File
@@ -12,6 +12,10 @@ global:
PyW_PyListToEa64Vec;
PyW_PyListToSizeVec;
PyW_PyListToStrVec;
PyW_from_jvalue_t;
PyW_to_jvalue_t;
PyW_from_jobj_t;
PyW_to_jobj_t;
PyW_ShowCbErr;
PyW_SizeVecToPyList;
PyW_UvalVecToPyList;
+4
View File
@@ -13,6 +13,10 @@ EXPORTS
PyW_PyListToEa64Vec
PyW_PyListToSizeVec
PyW_PyListToStrVec
PyW_from_jvalue_t
PyW_to_jvalue_t
PyW_from_jobj_t
PyW_to_jobj_t
PyW_register_compiled_form
PyW_ShowCbErr
PyW_TryGetAttrString
+2 -2
View File
@@ -1,11 +1,11 @@
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
targets: [ arm64-macos, x86_64-macos ]
install-name: '@executable_path/libpython3.link.dylib'
current-version: 3.9
compatibility-version: 3.9
exports:
- targets: [ arm64-macos ]
- targets: [ arm64-macos, x86_64-macos ]
symbols: [ _PyAST_CompileEx, _PyAST_CompileObject, _PyAST_FromNode, _PyAST_FromNodeObject,
_PyAST_Validate, _PyArena_AddPyObject, _PyArena_Free, _PyArena_Malloc,
_PyArena_New, _PyArg_Parse, _PyArg_ParseTuple, _PyArg_ParseTupleAndKeywords,
+46 -31
View File
@@ -102,8 +102,8 @@ else
endif
#----------------------------------------------------------------------
ifdef __APPLE_SILICON__
# set up a stub .tbd library to link against, see tbd.readme
ifdef __MAC__
# use a stub .tbd library to link against, see tbd.md
TBD_FILE = libpython$(PYTHON_VERSION_MAJOR).tbd
# note: this path must be compatible with -L$(R) -lpython3 in pyplg.mak
TBD_MODULE_DEP = $(R)$(TBD_FILE)
@@ -149,7 +149,6 @@ ifdef DO_IDAMAKE_SIMPLIFY
QGENIDAAPI = @echo $(call qcolor,genidaapi) $< && #
QGENSWIGHEADER = @echo $(call qcolor,genswigheader) $< && #
QINJECT_PYDOC = @echo $(call qcolor,inject_pydoc) $$< && #
QINJECT_BASE_HOOKS_FLAGS = @echo $(call qcolor,inject_base_hooks_flags) $< && #
QPATCH_CODEGEN = @echo $(call qcolor,patch_codegen) $$< && #
QPATCH_H_CODEGEN = @echo $(call qcolor,patch_h_codegen) $$< && #
QPATCH_PYTHON_CODEGEN = @echo $(call qcolor,patch_python_codegen) $$< && #
@@ -190,7 +189,7 @@ endif
ifeq ($(OUT_OF_TREE_BUILD),)
IDAT_CMD=TVHEADLESS=1 $(IDAT_PATH)$(SUFF64)
else
IDAT_CMD=TVHEADLESS=1 IDAPYTHON_DYNLOAD_BASE=$(SDK_BIN_PATH) $(IDAT_PATH)$(SUFF64)
IDAT_CMD=TVHEADLESS=1 IDAPYTHON_DYNLOAD_BASE=$(R) $(IDAT_PATH)$(SUFF64)
endif
# envvar HAS_HEXRAYS must have been set by build.py if needed
@@ -406,7 +405,7 @@ ifeq ($(OUT_OF_TREE_BUILD),)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP310_PYDLL) $(DEST_SIP310_PYI)
# sip for Python [3.11, ...
# sip for Python [3.11, 3.12)
DEST_SIP311_DIR:=$(DEST_PYQT_DIR)/python_3.11
$(DEST_SIP311_DIR):
-$(Q)if [ ! -d "$(DEST_SIP311_DIR)" ] ; then mkdir -p 2>/dev/null $(DEST_SIP311_DIR) ; fi
@@ -418,20 +417,36 @@ ifeq ($(OUT_OF_TREE_BUILD),)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP311_PYDLL) $(DEST_SIP311_PYI)
# sip for Python [3.12, ...
DEST_SIP312_DIR:=$(DEST_PYQT_DIR)/python_3.12
$(DEST_SIP312_DIR):
-$(Q)if [ ! -d "$(DEST_SIP312_DIR)" ] ; then mkdir -p 2>/dev/null $(DEST_SIP312_DIR) ; fi
DEST_SIP312_PYDLL:=$(DEST_SIP312_DIR)/$(SIP_PYDLL_FNAME)
DEST_SIP312_PYI:=$(DEST_SIP312_DIR)/$(SIP_PYI_FNAME)
$(DEST_SIP312_PYDLL): $(wildcard $(SIP312_TREE)/lib/python*/PyQt5/$(SIP_PYDLL_FNAME)) | $(DEST_SIP312_DIR)
$(Q)$(CP) $? $@
$(DEST_SIP312_PYI): $(wildcard $(SIP312_TREE)/lib/python*/PyQt5/$(SIP_PYI_FNAME)) | $(DEST_SIP312_DIR)
$(Q)$(CP) $? $@
DEST_SIP += $(DEST_SIP312_PYDLL) $(DEST_SIP312_PYI)
# And pick the right sip.so now (Python3 only; for Python2, we already put it in the right place)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 10; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP311_PYDLL)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 11; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP312_PYDLL)
else
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 9; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP310_PYDLL)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 10; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP311_PYDLL)
else
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 8; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP39_PYDLL)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 9; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP310_PYDLL)
else
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 7; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP38_PYDLL)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 8; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP39_PYDLL)
else
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP34_PYDLL)
ifeq ($(shell test $(PYTHON_VERSION_MINOR) -gt 7; echo $$?),0) # ugh
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP38_PYDLL)
else
DEST_INSTALL_SIP_PYDLL:=$(DEST_SIP34_PYDLL)
endif
endif
endif
endif
@@ -652,11 +667,6 @@ find-pywraps-deps = $(wildcard pywraps/py_$(subst .i,,$(notdir $(1)))*.hpp) $(wi
find-pydoc-patches-deps = $(wildcard tools/inject_pydoc/$(1).py)
find-patch-codegen-deps = $(wildcard tools/patch_codegen/*$(1)*.py)
ADDITIONAL_PYWRAP_DEP_idaapi=$(ST_PYW)/py_idaapi.hpp
$(ST_PYW)/py_idaapi.hpp: pywraps/py_idaapi.hpp.in tools/inject_base_hooks_flags.py pywraps.hpp
$(QINJECT_BASE_HOOKS_FLAGS)$(PYTHON) tools/inject_base_hooks_flags.py -i $< -o $@ -f pywraps.hpp
# Some .i files depend on some other .i files in order to be parseable by SWiG
# (e.g., segregs.i imports range.i). Declare the list of such dependencies here
# so they will be picked by the auto-generated rules.
@@ -706,7 +716,7 @@ define make-module-rules
--verbose > $(ST_WRAP)/ida_$(1).pydoc_injection
# obj/x86_linux_gcc/swig/X.i
$(ST_SWIG)/$(1).i: $(addprefix $(F),$(call find-pywraps-deps,$(1))) $(ADDITIONAL_PYWRAP_DEP_$(1)) swig/$(1).i $(ST_SWIG_HEADER) $(SWIG_IFACE_$(1):%=$(ST_SWIG)/%.i) $(ST_SWIG_HEADER) tools/deploy.py $(PARSED_HEADERS_MARKER)
$(ST_SWIG)/$(1).i: $(addprefix $(F),$(call find-pywraps-deps,$(1))) swig/$(1).i $(ST_SWIG_HEADER) $(SWIG_IFACE_$(1):%=$(ST_SWIG)/%.i) $(ST_SWIG_HEADER) tools/deploy.py $(PARSED_HEADERS_MARKER)
$(QDEPLOY)$(PYTHON) tools/deploy.py \
--pywraps $(ST_PYW) \
--template $$(subst $(F),,$$@) \
@@ -847,7 +857,11 @@ else
DUMPDOC_IS_64:=False
endif
PYDOC_INJECTIONS_IDAT_CMD=$(IDAT_CMD) $(BATCH_SWITCH) -S"$< $(ST_PYDOC_INJECTIONS) $(ST_WRAP) $(DUMPDOC_IS_64)" -t -L$(F)dumpdoc.log >/dev/null
ifndef NOTEAMS
VAULT_SERVER_OPTS=-Ovault:host=$(TEAMS_BUILD_HOST):port=$(TEAMS_BUILD_PORT):user=$(TEAMS_BUILD_USER):pass=$(TEAMS_BUILD_PASS)
endif
PYDOC_INJECTIONS_IDAT_CMD=$(IDAT_CMD) $(BATCH_SWITCH) $(VAULT_SERVER_OPTS) -S"$< $(ST_PYDOC_INJECTIONS) $(ST_WRAP) $(DUMPDOC_IS_64)" -t -L$(F)dumpdoc.log >/dev/null
pydoc_injections: $(ST_PYDOC_INJECTIONS_SUCCESS)
$(ST_PYDOC_INJECTIONS_SUCCESS): tools/dumpdoc.py $(IDAPYTHON_MODULES) $(PYTHON_BINARY_MODULES)
ifeq ($(or $(__CODE_CHECKER__),$(NO_CMP_API),$(__ASAN__),$(IDAHOME),$(DEMO_OR_FREE)),)
@@ -922,7 +936,7 @@ endif
$(R)idapyswitch$(B): $(call dumb_target, pro, $(IDAPYSWITCH_OBJS))
#----------------------------------------------------------------------
ifdef __APPLE_SILICON__
ifdef __MAC__
tbd: $(TBD_MODULE_DEP)
# copy the tbd library to idabin, and instruct idapyswitch to create the symlink to libpython
$(TBD_MODULE_DEP): $(TBD_FILE) $(IDAPYSWITCH_DEP)
@@ -993,10 +1007,10 @@ $(F)idapyswitch$(O): $(I)auto.hpp $(I)bitrange.hpp $(I)bytes.hpp \
$(I)exehdr.h $(I)fixup.hpp $(I)fpro.h $(I)funcs.hpp \
$(I)ida.hpp $(I)idp.hpp $(I)ieee.h $(I)kernwin.hpp \
$(I)lines.hpp $(I)llong.hpp $(I)loader.hpp $(I)lzfse.h \
$(I)lzvn_decode_base.h $(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)network.hpp $(I)offset.hpp $(I)pro.h \
$(I)prodir.h $(I)range.hpp $(I)segment.hpp \
$(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \
$(I)lzvn_decode_base.h $(I)md5.h $(I)nalt.hpp \
$(I)name.hpp $(I)netnode.hpp $(I)network.hpp \
$(I)offset.hpp $(I)pro.h $(I)prodir.h $(I)range.hpp \
$(I)segment.hpp $(I)segregs.hpp $(I)ua.hpp $(I)xref.hpp \
../../ldr/ar/aixar.hpp ../../ldr/ar/ar.hpp \
../../ldr/ar/arcmn.cpp ../../ldr/elf/../idaldr.h \
../../ldr/elf/elf.h ../../ldr/elf/elfbase.h \
@@ -1065,8 +1079,9 @@ $(F)idapython$(O): $(I)bitrange.hpp $(I)bytes.hpp $(I)config.hpp \
$(I)diskio.hpp $(I)err.h $(I)expr.hpp $(I)fpro.h \
$(I)funcs.hpp $(I)gdl.hpp $(I)graph.hpp $(I)ida.hpp \
$(I)ida_highlighter.hpp $(I)idd.hpp $(I)idp.hpp \
$(I)ieee.h $(I)kernwin.hpp $(I)lines.hpp $(I)llong.hpp \
$(I)loader.hpp $(I)nalt.hpp $(I)name.hpp $(I)netnode.hpp \
$(I)pro.h $(I)range.hpp $(I)segment.hpp $(I)typeinf.hpp \
$(I)ua.hpp $(I)xref.hpp extapi.cpp extapi.hpp \
idapython.cpp pywraps.cpp pywraps.hpp
$(I)ieee.h $(I)kernwin.hpp $(I)lex.hpp $(I)lines.hpp \
$(I)llong.hpp $(I)loader.hpp $(I)nalt.hpp $(I)name.hpp \
$(I)netnode.hpp $(I)parsejson.hpp $(I)pro.h \
$(I)range.hpp $(I)segment.hpp $(I)typeinf.hpp $(I)ua.hpp \
$(I)xref.hpp extapi.cpp \
extapi.hpp idapython.cpp pywraps.cpp pywraps.hpp
+3 -1
View File
@@ -1 +1,3 @@
-esym(4100, obj) // unreferenced formal parameter
-esym(4100, obj) // unreferenced formal parameter
-esym(2586, PySys_SetPath) // w2586 Function 'PySys_SetPath' is deprecated
Binary file not shown.
+800 -397
View File
File diff suppressed because it is too large Load Diff
+746 -395
View File
File diff suppressed because it is too large Load Diff
+5 -8
View File
@@ -249,7 +249,10 @@ def Modules():
mod = ida_idd.modinfo_t()
result = ida_dbg.get_first_module(mod)
while result:
yield mod
# Note: can't simply return `mod` here, since callers might
# collect all modules in a list, and they would all re-use
# the underlying C++ object.
yield ida_idaapi.object_t(name=mod.name, size=mod.size, base=mod.base, rebase_to=mod.rebase_to)
result = ida_dbg.get_next_module(mod)
@@ -432,13 +435,7 @@ def MapDataList(ea, length, func, wordsize=1):
PutDataList(ea, map(func, GetDataList(ea, length, wordsize)), wordsize)
def GetInputFileMD5():
"""
Return the MD5 hash of the input binary file
@return: MD5 string or None on error
"""
return idc.retrieve_input_file_md5()
GetInputFileMD5 = ida_nalt.retrieve_input_file_md5
class Strings(object):
+18 -13
View File
@@ -1027,13 +1027,13 @@ def split_sreg_range(ea, reg, value, tag=SR_user):
@note: IDA keeps tracks of all the points where segment register change their
values. This function allows you to specify the correct value of a segment
register if IDA is not able to find the corrent value.
register if IDA is not able to find the correct value.
"""
reg = ida_idp.str2reg(reg);
if reg >= 0:
return ida_segregs.split_sreg_range(ea, reg, value, tag)
else:
return False
rnames = [r.casefold() for r in ida_idp.ph_get_regnames()]
for regno in range(ida_idp.ph_get_reg_first_sreg(), ida_idp.ph_get_reg_last_sreg()+1):
if rnames[regno]==reg.casefold():
return ida_segregs.split_sreg_range(ea, regno, value, tag)
return False
auto_mark_range = ida_auto.auto_mark_range
@@ -2641,13 +2641,18 @@ MSF_NOFIX = 0x0002 # don't call the loader to fix relocations
MSF_LDKEEP = 0x0004 # keep the loader in the memory (optimization)
MSF_FIXONCE = 0x0008 # valid for rebase_program(): call loader only once
MOVE_SEGM_OK = 0 # all ok
MOVE_SEGM_PARAM = -1 # The specified segment does not exist
MOVE_SEGM_ROOM = -2 # Not enough free room at the target address
MOVE_SEGM_IDP = -3 # IDP module forbids moving the segment
MOVE_SEGM_CHUNK = -4 # Too many chunks are defined, can't move
MOVE_SEGM_LOADER = -5 # The segment has been moved but the loader complained
MOVE_SEGM_ODD = -6 # Can't move segments by an odd number of bytes
MOVE_SEGM_OK = 0 # all ok
MOVE_SEGM_PARAM = -1 # The specified segment does not exist
MOVE_SEGM_ROOM = -2 # Not enough free room at the target address
MOVE_SEGM_IDP = -3 # IDP module forbids moving the segment
MOVE_SEGM_CHUNK = -4 # Too many chunks are defined, can't move
MOVE_SEGM_LOADER = -5 # The segment has been moved but the loader complained
MOVE_SEGM_ODD = -6 # Can't move segments by an odd number of bytes
MOVE_SEGM_ORPHAN = -7, # Orphan bytes hinder segment movement
MOVE_SEGM_DEBUG = -8, # Debugger segments cannot be moved
MOVE_SEGM_SOURCEFILES = -9, # Source files ranges of addresses hinder segment movement
MOVE_SEGM_MAPPING = -10, # Memory mapping ranges of addresses hinder segment movement
MOVE_SEGM_INVAL = -11, # Invalid argument (delta/target does not fit the address space)
rebase_program = ida_segment.rebase_program
+93 -2
View File
@@ -1,6 +1,7 @@
#include <pro.h>
#include <ieee.h>
#include <parsejson.hpp>
#include <Python.h>
@@ -267,6 +268,83 @@ Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list)
return pyvar_walk_list(py_list, lambda_t::cvt, out);
}
//-------------------------------------------------------------------------
PyObject *ida_export PyW_from_jvalue_t(const jvalue_t &v)
{
do
{
if ( v.type() == JT_UNKNOWN )
break;
newref_t json_module(PyImport_ImportModule("json"));
if ( !json_module )
break;
borref_t json_globals(PyModule_GetDict(json_module.o));
if ( !json_globals )
break;
borref_t json_loads(PyDict_GetItemString(json_globals.o, "loads"));
if ( !json_loads )
break;
qstring clob;
if ( !serialize_json(&clob, v) )
break;
ref_t dict = newref_t(PyObject_CallFunction(json_loads.o, "s", clob.c_str()));
if ( !dict )
break;
dict.incref();
return dict.o;
} while ( false );
Py_RETURN_NONE;
}
//-------------------------------------------------------------------------
bool ida_export PyW_to_jvalue_t(jvalue_t *out, PyObject *py)
{
do
{
newref_t json_module(PyImport_ImportModule("json"));
if ( !json_module )
break;
borref_t json_globals(PyModule_GetDict(json_module.o));
if ( !json_globals )
break;
borref_t json_dumps(PyDict_GetItemString(json_globals.o, "dumps"));
if ( !json_dumps )
break;
newref_t str(PyObject_CallFunction(json_dumps.o, "O", py));
qstring buf;
if ( !PyUnicode_as_qstring(&buf, str.o) )
break;
if ( parse_json_string(out, buf.c_str()) != eOk )
break;
return true;
} while ( false );
return false;
}
//-------------------------------------------------------------------------
PyObject *ida_export PyW_from_jobj_t(const jobj_t &o)
{
jvalue_t v;
v.set_obj((jobj_t *) &o);
PyObject *rc = PyW_from_jvalue_t(v);
v.extract_obj();
return rc;
}
//-------------------------------------------------------------------------
bool ida_export PyW_to_jobj_t(jobj_t *out, PyObject *py)
{
if ( !PyDict_Check(py) )
return false;
jvalue_t v;
bool rc = PyW_to_jvalue_t(&v, py) && v.type() == JT_OBJ;
if ( rc )
out->swap(v.obj());
return rc;
}
//-------------------------------------------------------------------------
PyObject *ida_export meminfo_vec_t_to_py(meminfo_vec_t &ranges)
{
@@ -1643,19 +1721,32 @@ bool ida_export py_customidamemo_t_bind(py_customidamemo_t *_this, PyObject *sel
_this->self = borref_t(self);
_this->view = view;
newref_t result(PyObject_CallMethod(self, (char *)"_OnBind", "O", Py_True));
if ( !result && PyErr_Occurred() != nullptr )
{
msg("WARNING: Couldn't bind form object at %p:\n", self);
PyErr_Print();
}
return true;
}
//-------------------------------------------------------------------------
void ida_export py_customidamemo_t_unbind(py_customidamemo_t *_this, bool clear_view)
void ida_export py_customidamemo_t_unbind(py_customidamemo_t *_this)
{
if ( _this->self == nullptr )
return;
PYGLOG("%p: py_customidamemo_t::unbind(); self.o=%p, view=%p\n", _this, _this->self.o, _this->view);
PYW_GIL_CHECK_LOCKED_SCOPE();
newref_t result(PyObject_CallMethod(_this->self.o, (char *)"_OnBind", "O", Py_False));
if ( !result && PyErr_Occurred() != nullptr )
{
msg("WARNING: Couldn't unbind form object at %p:\n", _this->self.o);
PyErr_Print();
}
PyObject_SetAttrString(_this->self.o, S_M_THIS, Py_None);
_this->self = newref_t(nullptr);
if ( clear_view )
_this->view = nullptr;
}
+14 -10
View File
@@ -28,6 +28,9 @@ typedef PY_LONG_LONG bvsval_t;
class insn_t;
class op_t;
struct switch_info_t;
struct jobj_t;
struct jarr_t;
struct jvalue_t;
// "A pointer can be explicitly converted to any integral type large
// enough to hold it. The mapping function is implementation-defined."
@@ -507,6 +510,11 @@ idaman Py_ssize_t ida_export PyW_PyListToSizeVec(sizevec_t *out, PyObject *py_li
idaman Py_ssize_t ida_export PyW_PyListToEaVec(eavec_t *out, PyObject *py_list);
idaman Py_ssize_t ida_export PyW_PyListToStrVec(qstrvec_t *out, PyObject *py_list);
idaman PyObject *ida_export PyW_from_jvalue_t(const jvalue_t &v);
idaman bool ida_export PyW_to_jvalue_t(jvalue_t *out, PyObject *py);
idaman PyObject *ida_export PyW_from_jobj_t(const jobj_t &o);
idaman bool ida_export PyW_to_jobj_t(jobj_t *out, PyObject *py);
#ifndef LUMINA_HPP // I'd rather put the def of ea64_t and ea64vec_t into pro.h...
#ifdef __EA64__
typedef ea_t ea64_t;
@@ -682,9 +690,9 @@ struct pycim_callbacks_ids_t : public qvector<pycim_callback_id_t>
#define PY_CIM_PARAMS_bind (PyObject *in_self, TWidget *in_view)
#define PY_CIM_TRANSM_bind (this, in_self, in_view)
#define PY_CIM_HLPPRM_unbind (py_customidamemo_t *_this, bool clear_view)
#define PY_CIM_PARAMS_unbind (bool clear_view)
#define PY_CIM_TRANSM_unbind (this, clear_view)
#define PY_CIM_HLPPRM_unbind (py_customidamemo_t *_this)
#define PY_CIM_PARAMS_unbind ()
#define PY_CIM_TRANSM_unbind (this)
#define DECL_CIM_HELPER(decl, RType, MName, MParams) \
decl RType ida_export py_customidamemo_t_##MName MParams
@@ -1093,7 +1101,7 @@ py_customidamemo_t::py_customidamemo_t()
py_customidamemo_t::~py_customidamemo_t()
{
PYGLOG("%p: ~py_customidamemo_t()\n", this);
unbind(true);
unbind();
get_plugin_instance()->pycim_lookup_info.del_by_py_view(this);
}
@@ -1272,13 +1280,13 @@ protected:
}
}
#ifdef TESTABLE_BUILD
PyObject *dump_state(
const event_code_to_method_name_t *mappings,
size_t mappings_size,
bool assert_all_reimplemented) const
{
qstring buf;
#ifdef TESTABLE_BUILD
qstrvec_t missing_reimpls;
buf.sprnt("%s(this=%p) \"%s\" {type=%d, cb=%p, flags=%x}",
class_name, this, identifier.c_str(), int(type), listener.cb, flags);
@@ -1327,13 +1335,9 @@ protected:
}
if ( buf.last() != '\n' )
buf.append('\n');
#else
qnotused(mappings);
qnotused(mappings_size);
qnotused(assert_all_reimplemented);
#endif
return PyUnicode_from_qstring(buf);
}
#endif
};
//-------------------------------------------------------------------------
+32
View File
@@ -93,6 +93,38 @@ static bool py_do_get_bytes(
//<inline(py_bytes)>
#define MS_0TYPE 0x00F00000LU ///< Mask for 1st arg typing
#define FF_0VOID 0x00000000LU ///< Void (unknown)?
#define FF_0NUMH 0x00100000LU ///< Hexadecimal number?
#define FF_0NUMD 0x00200000LU ///< Decimal number?
#define FF_0CHAR 0x00300000LU ///< Char ('x')?
#define FF_0SEG 0x00400000LU ///< Segment?
#define FF_0OFF 0x00500000LU ///< Offset?
#define FF_0NUMB 0x00600000LU ///< Binary number?
#define FF_0NUMO 0x00700000LU ///< Octal number?
#define FF_0ENUM 0x00800000LU ///< Enumeration?
#define FF_0FOP 0x00900000LU ///< Forced operand?
#define FF_0STRO 0x00A00000LU ///< Struct offset?
#define FF_0STK 0x00B00000LU ///< Stack variable?
#define FF_0FLT 0x00C00000LU ///< Floating point number?
#define FF_0CUST 0x00D00000LU ///< Custom representation?
#define MS_1TYPE 0x0F000000LU ///< Mask for the type of other operands
#define FF_1VOID 0x00000000LU ///< Void (unknown)?
#define FF_1NUMH 0x01000000LU ///< Hexadecimal number?
#define FF_1NUMD 0x02000000LU ///< Decimal number?
#define FF_1CHAR 0x03000000LU ///< Char ('x')?
#define FF_1SEG 0x04000000LU ///< Segment?
#define FF_1OFF 0x05000000LU ///< Offset?
#define FF_1NUMB 0x06000000LU ///< Binary number?
#define FF_1NUMO 0x07000000LU ///< Octal number?
#define FF_1ENUM 0x08000000LU ///< Enumeration?
#define FF_1FOP 0x09000000LU ///< Forced operand?
#define FF_1STRO 0x0A000000LU ///< Struct offset?
#define FF_1STK 0x0B000000LU ///< Stack variable?
#define FF_1FLT 0x0C000000LU ///< Floating point number?
#define FF_1CUST 0x0D000000LU ///< Custom representation?
//------------------------------------------------------------------------
/*
#<pydoc>
+6 -4
View File
@@ -324,9 +324,9 @@ public:
// Form already created? try to get associated py_graph instance
// so that we reuse it
TWidget *existing = find_widget(title.c_str());
if ( existing != nullptr )
get_plugin_instance()->pycim_lookup_info.find_by_view((py_customidamemo_t**) &py_graph, existing);
TWidget *view = find_widget(title.c_str());
if ( view != nullptr )
get_plugin_instance()->pycim_lookup_info.find_by_view((py_customidamemo_t**) &py_graph, view);
if ( py_graph == nullptr )
{
@@ -335,8 +335,10 @@ public:
else
{
// unbind so we are rebound
py_graph->unbind(false);
py_graph->unbind();
py_graph->bind(self, view);
py_graph->refresh_needed = true;
refresh_viewer(view); // cfr graph.hpp how to refresh an existing mutable_graph_t
}
if ( py_graph->initialize(self, title.c_str()) < 0 )
{
+6
View File
@@ -117,6 +117,12 @@ class GraphViewer(ida_kernwin.CustomIDAMemo):
def OnCommand(self, cmd_id):
return 0
def _OnBind(self, hook):
if hook:
self.ui_hooks_trampoline.hook()
else:
self.ui_hooks_trampoline.unhook()
super()._OnBind(hook)
#<pydoc>
# def OnGetText(self, node_id):
@@ -104,8 +104,9 @@ static void ida_idaapi_closebase(void) {}
//<inline(py_idaapi)>
${BASE_HOOKS_FLAGS}
// NOTE: See also `pywraps.hpp`
#define HBF_CALL_WITH_NEW_EXEC 0x00000001
#define HBF_VOLATILE_METHOD_SET 0x00000002
//------------------------------------------------------------------------
/*
+2 -71
View File
@@ -346,25 +346,6 @@ PyObject *py_ask_str(qstring *defval, int hist, const char *prompt)
return py_ret;
}
//------------------------------------------------------------------------
/*
#<pydoc>
def str2ea(addr):
"""
Converts a string express to EA. The expression evaluator may be called as well.
@return: BADADDR or address value
"""
pass
#</pydoc>
*/
ea_t py_str2ea(const char *str, ea_t screenEA = BADADDR)
{
ea_t ea;
bool ok = str2ea(&ea, str, screenEA);
return ok ? ea : BADADDR;
}
//------------------------------------------------------------------------
/*
#<pydoc>
@@ -771,62 +752,12 @@ public:
PyObject *get_dict()
{
do
{
newref_t json_module(PyImport_ImportModule("json"));
if ( !json_module )
break;
borref_t json_globals(PyModule_GetDict(json_module.o));
if ( !json_globals )
break;
borref_t json_loads(PyDict_GetItemString(json_globals.o, "loads"));
if ( !json_loads )
break;
qstring clob;
if ( !serialize_json(&clob, o) )
break;
if ( ref_t dict = newref_t(PyObject_CallFunction(json_loads.o, "s", clob.c_str())) )
{
dict.incref();
return dict.o;
}
} while ( false );
Py_RETURN_NONE;
return PyW_from_jobj_t(*o);
}
static bool fill_jobj_from_dict(jobj_t *out, PyObject *dict)
{
do
{
if ( !PyDict_Check(dict) )
break;
newref_t json_module(PyImport_ImportModule("json"));
if ( !json_module )
break;
borref_t json_globals(PyModule_GetDict(json_module.o));
if ( !json_globals )
break;
borref_t json_dumps(PyDict_GetItemString(json_globals.o, "dumps"));
if ( !json_dumps )
break;
newref_t str(PyObject_CallFunction(json_dumps.o, "O", dict));
qstring buf;
if ( PyUnicode_as_qstring(&buf, str.o) )
{
jvalue_t tmp;
if ( parse_json_string(&tmp, buf.c_str()) == eOk )
{
out->swap(tmp.obj());
return true;
}
}
} while ( false );
return false;
return PyW_to_jobj_t(out, dict);
}
};
+2
View File
@@ -995,6 +995,8 @@ PyObject *py_get_chooser_data(const char *chooser_caption, int n)
return py_list;
}
#define CH_NOIDB 0x00000040 // bw-compat
//</inline(py_kernwin_choose)>
#endif // __PY_KERNWIN_CHOOSE__
+1 -1
View File
@@ -57,7 +57,7 @@ bool py_idaview_t::Unbind(PyObject *self)
py_idaview_t *_this = (py_idaview_t *) view_extract_this(self);
if ( _this == nullptr )
return false;
_this->unbind(true);
_this->unbind();
return true;
}
+6
View File
@@ -96,6 +96,12 @@ class CustomIDAMemo(View_Hooks):
gitpl = self._graph_item_tuple(ve)
return cb(ve.x, ve.y, ve.state, len(gitpl), gitpl, ve.renderer_pos)
def _OnBind(self, hook):
if hook:
self.hook()
else:
self.unhook()
# End of hooks->wrapper trampolines
+140
View File
@@ -0,0 +1,140 @@
#<pycode(py_lumina)>
import ida_bytes
import ida_typeinf
import ida_ida
import ida_pro
class simple_idb_diff_handler_t(func_md_diff_handler_t):
NO_DATA_MARKER = None
class indenter_t(object):
def __init__(self, handler):
self.handler = handler
self.handler.indent += 1
def __del__(self):
self.handler.indent -= 1
def __init__(self, pfn):
super(self.__class__, self).__init__()
self.pfn = pfn
self.header_generated = False
self.lines = []
self.indent = 0
def on_score_changed(self, l, r):
self.put2(str(l), str(r), "Score")
def on_name_changed(self, l, r):
self.put2(l, r, "Name")
def on_proto_changed(self, l, r):
self.put2(self.format_type(l), self.format_type(r), "Prototype")
def on_function_comment_changed(self, l, r, rep):
self.put2(l, r, "Function comment (%s)" % ("repeatable" if rep else "regular"))
def on_comment_changed(self, fchunk_nr, fchunk_off, l, r, rep):
loc = self.where(fchunk_nr, fchunk_off)
self.put2(l, r, "%s comment @ %s" % ("repeatable" if rep else "regular", loc))
def on_extra_comment_changed(self, fchunk_nr, fchunk_off, l, r, is_prev):
loc = self.where(fchunk_nr, fchunk_off)
self.put2(self.format_extra_cmt(l),
self.format_extra_cmt(r),
"%sterior extra comment @ %s" % ("An" if is_prev else "Pos", loc))
def on_user_stkpnt_changed(self, fchunk_nr, fchunk_off, l, r):
loc = self.where(fchunk_nr, fchunk_off)
self.put2(self.format_stkpnt(l),
self.format_stkpnt(r),
"User stack point @ %s" % loc)
def on_frame_member_changed(self, offset, l, r):
self.ensure_header_generated()
self.put("Member @ 0x%X" % offset)
indenter = self.indenter_t(self)
ltype, loprepr, lcmt, lrptcmt = self.format_frame_member(l)
rtype, roprepr, rcmt, rrptcmt = self.format_frame_member(r)
cmp_put = lambda l, r, topic: self.put2(l, r, topic) if l != r else None
cmp_put(ltype, rtype, ".type")
cmp_put(loprepr, roprepr, ".opinfo")
cmp_put(lcmt, rcmt, ".cmt")
cmp_put(lrptcmt, rrptcmt, ".rptcmt")
def on_insn_ops_repr_changed(self, fchunk_nr, fchunk_off, l, r):
loc = self.where(fchunk_nr, fchunk_off)
ls, rs = self.format_insn_ops(l), self.format_insn_ops(r)
self.put2(ls, rs, "Insn operands @ %s" % loc)
# --- helpers ---
def ensure_header_generated(self):
if not self.header_generated:
self.lines.append("")
self.lines.append("Function 0x%X" % self.pfn.start_ea)
self.header_generated = True
def where(self, fchunk_nr, fchunk_off):
site = insn_site_t()
site.fchunk_nr = fchunk_nr
site.fchunk_off = fchunk_off
return "0x%X" % site.toea(self.pfn)
def format_type(self, type_parts):
tif = ida_typeinf.tinfo_t()
if tif.deserialize(None, type_parts.type, type_parts.fields):
return tif._print()
def format_extra_cmt(self, cmt):
if cmt:
cmt = ida_pro.str2user(cmt)
return cmt
def format_stkpnt(self, stkpnt):
if stkpnt is not None:
return "%d" % stkpnt
def format_frame_member(self, m):
_type = self.NO_DATA_MARKER
_oprepr = self.NO_DATA_MARKER
_cmt = self.NO_DATA_MARKER
_rptcmt = self.NO_DATA_MARKER
if m:
if len(m.type.type):
_type = self.format_type(m.type)
if ida_bytes.is_off0(m.info.flags):
_oprepr = '{"target" : 0x%X, "base" : 0x%X, "tdelta" : 0x%X, "flags" : 0x%08x}' % (
m.info.opinfo.ri.target,
m.info.opinfo.ri.base,
m.info.opinfo.ri.tdelta,
m.info.opinfo.ri.flags)
_cmt = m.cmt
_rptcmt = m.rptcmt
return (_type, _oprepr, _cmt, _rptcmt)
def format_insn_ops(self, ro):
if not ro:
return "[<no ops repr>]"
parts = []
for i in range(ida_ida.UA_MAXOP):
parts.append("op%d=0x%X" % (i, (ro.flags >> ida_bytes.get_operand_type_shift(i)) & 0xF))
return "[%s]" % ", ".join(parts)
def put(self, msg):
self.lines.append(" " * self.indent + msg)
def put2(self, l, r, topic):
self.ensure_header_generated()
if l is None: l = self.NO_DATA_MARKER
if r is None: r = self.NO_DATA_MARKER
self.put(topic)
indenter = self.indenter_t(self)
self.put("- %s" % l)
self.put("+ %s" % r)
#</pycode(py_lumina)>
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+1
View File
@@ -16,6 +16,7 @@
%ignore add_stkvar;
%ignore delete_wrong_frame_info;
%ignore get_frame(ea_t);
%template(xreflist_t) qvector<xreflist_entry_t>;
-8
View File
@@ -5,14 +5,6 @@ hexdsp_t *get_idapython_hexdsp();
#include <hexrays.hpp>
%}
// Functions accepting a `func_t *` can also derive it from an `ea_t`
%typemap(in, fragment="cvt_func_t") func_t *pfn
{ // %typemap(in) func_t *pfn
if ( !cvt_func_t(&$1, $input) )
SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname" "', argument " "$argnum"" of type '" "func_t const *""' (or an address from which it can be derived)");
}
%{
SWIGINTERN void __raise_vdf(const vd_failure_t &e)
{
+20
View File
@@ -117,6 +117,25 @@
%ignore setflag(ushort &where,ushort bit,int value);
%ignore setflag(uint32 &where,uint32 bit,int value);
/* // `config.hpp` - note: ideally, this should be in its own module, */
/* // but it might be an overkill to have an `ida_config` module for */
/* // just one function (as of this writing in any case.) */
/* %ignore cfgopt_t; */
/* %ignore cfgopt_t::params_t; */
/* %ignore cfgopt_t::num_range_t; */
/* %ignore read_config; */
/* %ignore read_config2; */
/* %ignore read_config_file; */
/* %ignore read_config_file2; */
/* %ignore read_config_string; */
/* %ignore register_cfgopts; */
/* %ignore parse_config_value; */
/* %ignore cfgopt_t__apply; */
/* %ignore cfgopt_t__apply2; */
/* %ignore cfgopt_t__apply3; */
/* %ignore cfgopt_set_t; */
/* %ignore cfgopt_set_vec_t; */
// Make idainfo::get_proc_name() work
%include "cstring.i"
%cstring_bounded_output(char *buf, 8);
@@ -127,6 +146,7 @@
%predefine_uint32_macro(AF_FINAL, 0x80000000);
%include "ida.hpp"
/* %include "config.hpp" */
%clear(char *buf);
+2
View File
@@ -18,6 +18,8 @@
%rename (parse_command_line3) py_parse_command_line;
%constant ea_t BADADDR = ea_t(-1);
%constant ea32_t BADADDR32 = ea32_t(-1ULL);
%constant ea64_t BADADDR64 = ea64_t(-1ULL);
%constant sel_t BADSEL = sel_t(-1);
%constant size_t SIZE_MAX = size_t(-1);
/* %constant nodeidx_t BADNODE = nodeidx_t(-1); */
+43
View File
@@ -129,6 +129,49 @@ struct undo_records_t;
%apply size_t *OUTPUT { size_t *out_consumed };
%apply bytevec_t *vout { bytevec_t *out_relbits };
// ev_cvt64_supval, ev_cvt64_hashval, ev_privrange_changed
%const_pointer_and_size(uchar, data, datlen, bytevec_t, PyBytes_as_bytevec_t, size);
%typemap(argout) (qstring *errbuf)
{
// %typemap(argout) (qstring *errbuf)
if ( result < 0 )
{
Py_XDECREF($result);
if ( $1 != nullptr )
$result = PyUnicode_from_qstring(*$1);
else
$result = PyUnicode_FromString("Unknown error");
}
}
%define %fill_director_method_errbuf(METHOD_NAME)
%typemap(directorout) int METHOD_NAME
{
// %typemap(directorout) int METHOD_NAME
if ( PyString_Check(result) )
{
if ( errbuf != nullptr )
{
PyUnicode_as_qstring(errbuf, result);
}
$result = -1;
}
else if ( PyLong_Check(result) )
{
$result = PyLong_AsLong(result);
}
else
{
Swig::DirectorTypeMismatchException::raise(
SWIG_ErrorType(SWIG_TypeError),
"in output value of type '" "int" "'" " in method '$symname'");
}
}
%enddef
%fill_director_method_errbuf(ev_cvt64_supval);
%fill_director_method_errbuf(ev_cvt64_hashval);
%fill_director_method_errbuf(ev_privrange_changed);
// @arnaud ditch this once all modules are ported
// temporary:
%ignore out_old_data;
+2 -1
View File
@@ -120,13 +120,14 @@ struct dirspec_t;
%rename (ask_text) py_ask_text;
%rename (ask_str) py_ask_str;
%rename (str2ea) py_str2ea;
%ignore process_ui_action;
%rename (process_ui_action) py_process_ui_action;
%ignore execute_sync;
%ignore exec_request_t;
%rename (execute_sync) py_execute_sync;
%ignore ea2str(char *, size_t, ea_t);
%ignore ui_request_t;
%ignore execute_ui_requests;
%rename (execute_ui_requests) py_execute_ui_requests;
+6 -7
View File
@@ -36,13 +36,6 @@
%rename (extract_type_from_metadata) py_extract_type_from_metadata;
%rename (split_metadata) py_split_metadata;
%feature("nodirector") simple_diff_handler_t;
%ignore simple_diff_handler_t::simple_diff_handler_t;
%feature("nodirector") simple_idb_diff_handler_t;
%ignore simple_idb_diff_handler_t::simple_idb_diff_handler_t;
%ignore serialized_tinfo::empty;
%define %rpc_packet_data_t(TYPE, ENUMERATOR)
@@ -57,6 +50,7 @@
%rpc_packet_data_t(pkt_rpc_fail_t, PKT_RPC_FAIL);
%rpc_packet_data_t(pkt_rpc_notify_t, PKT_RPC_NOTIFY);
%rpc_packet_data_t(pkt_helo_t, PKT_HELO);
%rpc_packet_data_t(pkt_helo_result_t, PKT_HELO_RESULT);
%rpc_packet_data_t(pkt_pull_md_t, PKT_PULL_MD);
%rpc_packet_data_t(pkt_pull_md_result_t, PKT_PULL_MD_RESULT);
%rpc_packet_data_t(pkt_push_md_t, PKT_PUSH_MD);
@@ -192,3 +186,8 @@
//<inline(py_lumina)>
//</inline(py_lumina)>
%}
%pythoncode %{
#<pycode(py_lumina)>
#</pycode(py_lumina)>
%}
+9
View File
@@ -70,15 +70,24 @@
self.template.set_place(idap)
def __iter__(self):
"""
Iterate on bookmarks present for the widget.
"""
p = self.template.place()
if p is not None:
for idx in range(bookmarks_t.size(self.template, self.userdata)):
yield self[idx]
def __len__(self):
"""
Get the number of bookmarks for the widget.
"""
return bookmarks_t.size(self.template, self.userdata)
def __getitem__(self, idx):
"""
Get the n-th bookmark for the widget.
"""
p = self.template.place()
if p is not None:
if isinstance(idx, int) and idx >= 0 and idx < len(self):
+2
View File
@@ -75,6 +75,8 @@
%ignore refinfo_desc_t;
%ignore get_refinfo_descs;
%ignore printop_t::unused;
%ignore write_struc_path;
%ignore read_struc_path;
%ignore del_struc_path;
+1
View File
@@ -78,6 +78,7 @@
%ignore netnode_altshift;
%ignore netnode_charshift;
%ignore netnode_supshift;
%ignore netnode_blobshift;
%ignore netnode_altadjust;
%ignore netnode_altadjust2;
%ignore altadjust_visitor_t;
+1
View File
@@ -88,6 +88,7 @@
%ignore get_default_align;
%ignore align_size;
%ignore align_size;
%ignore fix_type_align;
%ignore get_arg_align;
%ignore align_stkarg_up;
%ignore get_default_enum_size;
+1
View File
@@ -39,6 +39,7 @@
%ignore outctx_base_t::regname_idx;
%ignore outctx_base_t::suspop;
%ignore outctx_base_t::F;
%ignore outctx_base_t::F_unused;
%ignore outctx_base_t::outvalues;
%ignore outctx_base_t::outvalue_getn_flags;
%ignore outctx_base_t::user_data;
+10 -10
View File
@@ -37,7 +37,7 @@ Generating TBD Files
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi
For example, this is how you can recreate libpython3.tbd on an Apple Silicon machine:
For example, this is how you can recreate libpython3.tbd:
$ alias tapi='/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/tapi'
$ cp /Library/Frameworks/Python.framework/Versions/3.9/Python /tmp/
@@ -61,14 +61,14 @@ with newer versions of the macOS linker (no surprise, the format is really unsta
So far it seems that only the following options are required:
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos ]
install-name: '@executable_path/libpython3.link.dylib'
current-version: 3.9
compatibility-version: 3.9
exports:
<list of exports>
...
--- !tapi-tbd
tbd-version: 4
targets: [ arm64-macos, x86_64-macos ]
install-name: '@executable_path/libpython3.link.dylib'
current-version: 3.9
compatibility-version: 3.9
exports:
- targets: [ arm64-macos, x86_64-macos ]
symbols: [ _PyAST_CompileEx, ...
Everything else can be removed.
+1 -2
View File
@@ -5,7 +5,6 @@ import sys
import os
import argparse
import re
import six
import pprint
mydir, _ = os.path.split(__file__)
@@ -260,7 +259,7 @@ def check_cpp(args):
if parser.text.find("""in output value of type '""int""'");""") > -1:
raise Exception("Director output value type reporting doesn't appear to be patched")
for fname, fdef in six.iteritems(functions):
for fname, fdef in functions.items():
if fdef.api_function_name:
api_functions_names.append(fdef.api_function_name)
+48 -12
View File
@@ -10,6 +10,7 @@
#define USE_DANGEROUS_FUNCTIONS 1
#endif
#include <pro.h>
#include <parsejson.hpp>
#undef DEPRECATED
#define DEPRECATED
%}
@@ -800,7 +801,7 @@ SWIGINTERN PyObject *_maybe_byte_array_or_none_result(
}
%fragment("cvt_" #CONTAINER_TYPE, "header")
{
CONTAINER_TYPE *cvt_##CONTAINER_TYPE(PyObject *obj, bool can_be_none=false)
int cvt_##CONTAINER_TYPE(CONTAINER_TYPE **pout, PyObject *obj, bool can_be_none=false)
{
CONTAINER_TYPE *out = nullptr;
if ( can_be_none && obj == Py_None )
@@ -813,38 +814,39 @@ SWIGINTERN PyObject *_maybe_byte_array_or_none_result(
out = new CONTAINER_TYPE;
IN_CONVERTER(out, obj);
}
return out;
*pout = out;
return out != nullptr ? SWIG_NEWOBJ : SWIG_ERROR;
}
}
%typemap(in, fragment="cvt_" #CONTAINER_TYPE) REFTYPE
%typemap(in, fragment="cvt_" #CONTAINER_TYPE) REFTYPE (int res=0)
{ // bytes_container REFTYPE, CONTAINER_TYPE typemap(in)
$1 = cvt_ ## CONTAINER_TYPE($input);
if ( $1 == nullptr )
res = cvt_ ## CONTAINER_TYPE(&$1, $input);
if ( !SWIG_IsOK(res) )
SWIG_exception_fail(
SWIG_ValueError,
"Expected " ELTYPE_TO_REPORT1 " " "in method '" "$symname" "', argument " "$argnum"" of type '" ELTYPE_TO_REPORT2 "'");
}
%typemap(in) const REFTYPE _type_or_none
%typemap(in) const REFTYPE _type_or_none (int res=0)
{ // bytes_container REFTYPE _type_or_none, CONTAINER_TYPE typemap(in)
$1 = cvt_ ## CONTAINER_TYPE($input, /*can_be_none=*/ true);
if ( $1 == nullptr )
res = cvt_ ## CONTAINER_TYPE(&$1, $input, /*can_be_none=*/ true);
if ( !SWIG_IsOK(res) )
SWIG_exception_fail(
SWIG_ValueError,
"Expected " ELTYPE_TO_REPORT1 " " "in method '" "$symname" "', argument " "$argnum"" of type '" ELTYPE_TO_REPORT2 "'");
}
%typemap(in) const REFTYPE _fields
%typemap(in) const REFTYPE _fields (int res=0)
{ // bytes_container REFTYPE _fields, CONTAINER_TYPE typemap(in)
$1 = cvt_ ## CONTAINER_TYPE($input, /*can_be_none=*/ true);
if ( $1 == nullptr )
res = cvt_ ## CONTAINER_TYPE(&$1, $input, /*can_be_none=*/ true);
if ( !SWIG_IsOK(res) )
SWIG_exception_fail(
SWIG_ValueError,
"Expected " ELTYPE_TO_REPORT1 " " "in method '" "$symname" "', argument " "$argnum"" of type '" ELTYPE_TO_REPORT2 "'");
}
%typemap(freearg) REFTYPE
{ // bytes_container REFTYPE typemap(freearg)
delete $1;
if ( SWIG_IsNewObj(res$argnum) ) delete $1;
}
%typemap(out) REFTYPE // e.g., %typemap(out) qstring*
{ // bytes_container typemap(out) REFTYPE
@@ -1319,6 +1321,19 @@ struct dynamic_wrapped_array_t {
{
// typemap(freearg) (const PTRTYPE *BUFNAME, size_t SIZENAME)
}
%typemap(directorin) (const uchar *data, size_t datlen)
{
// typemap(directorin) (const PTRTYPE *BUFNAME, size_t SIZENAME)
if ( $1 != nullptr )
{
$input = PyBytes_FromStringAndSize((const char *) $1, $2);
}
else
{
Py_INCREF(Py_None);
$input = Py_None;
}
}
%enddef
%define %const_void_pointer_and_size(PTRTYPE, BUFNAME, SIZENAME)
@@ -2059,5 +2074,26 @@ TRY_RAW_LONG:
}
}
// Functions accepting a `func_t *` can also derive it from an `ea_t`
%typemap(in, fragment="cvt_func_t") func_t *
{ // %typemap(in) func_t *
if ( !cvt_func_t(&$1, $input) )
SWIG_exception_fail(SWIG_ValueError, "in method '" "$symname" "', argument " "$argnum"" of type '" "func_t const *""' (or an address from which it can be derived)");
}
%typemap(in,numinputs=0) jvalue_t *out (jvalue_t temp)
{
// %typemap(in,numinputs=0) jvalue_t *out (jvalue_t temp)
$1 = &temp;
}
%typemap(argout) jvalue_t *out
{
// %typemap(argout) jvalue_t *out
Py_XDECREF($result);
$result = PyW_from_jvalue_t(*$1);
}
#endif // __HEADER_I__
// END: auto-inserted header
+24
View File
@@ -326,6 +326,30 @@ all_specific_translations = {
"'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.atoea" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.str2ea" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.str2ea_ex" : [
((
"-> 'uint32 *'",
"-> 'uint64 *'",
), "'unsigned-ea-like-numeric-type *'", True),
],
"ida_kernwin.PluginForm" : [
((
"module '__main__' from 'tools/dumpdoc.py'",
"module '__main__' (built-in)",
), "module 'main'", False),
],
}
if is_64:
+2 -3
View File
@@ -9,7 +9,6 @@ from __future__ import print_function
import os
import sys
import six
dirname, _ = os.path.split(__file__)
parent_dirname, _ = os.path.split(dirname)
@@ -69,7 +68,7 @@ def gen_methods(out):
retbody = "return %s;" % rdata["default"]
arg_strs = []
for p in (recipe_data["call_params"] if "call_params" in recipe_data else params[1:]):
if isinstance(p, six.string_types):
if isinstance(p, str):
assert(p[0] == "@")
synth_info = recipe["synthetic_params"][p]
ptype = synth_info["type"]
@@ -148,7 +147,7 @@ def gen_notifications(out):
argstr = [] # arguments to pass to the call, minus those explicitly suppressed
argstr_all = [] # all arguments
for p in (recipe_data["call_params"] if "call_params" in recipe_data else params[1:]):
if isinstance(p, six.string_types):
if isinstance(p, str):
assert(p[0] == "@")
synth_info = recipe["synthetic_params"][p]
ptype = synth_info["type"]
-30
View File
@@ -1,30 +0,0 @@
from __future__ import print_function
import re
import string
from argparse import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-i", "--input", required=True)
parser.add_argument("-o", "--output", required=True)
parser.add_argument("-f", "--file-with-flags", required=True)
args = parser.parse_args()
with open(args.input) as fin:
template = string.Template(fin.read())
with open(args.file_with_flags) as fin:
raw = fin.read()
pat = re.compile(r"^#\s*define\s+(HBF_[A-Za-z0-9_]*)\s+([0-9x]*)\s*(.*)$")
decls = []
for line in raw.split("\n"):
m = pat.match(line)
if m:
decls.append(line)
kvps = {
"BASE_HOOKS_FLAGS" : "\n".join(decls)
}
with open(args.output, "w") as fout:
fout.write(template.substitute(kvps))
+1 -2
View File
@@ -3,7 +3,6 @@ from __future__ import print_function
import os
import re
import sys
import six
import xml.etree.ElementTree as ET
from argparse import ArgumentParser
@@ -349,7 +348,7 @@ with open(args.input) as f:
current_function_proto = None
if subst is not None:
if isinstance(subst, six.string_types):
if isinstance(subst, str):
subst = [subst]
all_lines.extend(map(lambda l: "%s\n" % l, subst))
else:
+1 -2
View File
@@ -1,7 +1,6 @@
from __future__ import print_function
import os
import six
from argparse import ArgumentParser
@@ -23,7 +22,7 @@ if os.path.isfile(args.patches):
all_lines = []
for l in lines:
for patch_kind, patch_data in six.iteritems(patches):
for patch_kind, patch_data in patches.items():
if patch_kind == "repl_line":
for from_, to in patch_data:
if l == from_: